Description
ECE471 Embedded Systems Homework 1 Solved
For this homework short answers will suffice. There isn’t necessarily a right or wrong answer for some of
the questions, but be sure to explain your reasoning.
To submit, create a document with your answers (text, pdf, libreoffice, MS Office if you must) and e-mail
them to vincent.weaver@maine.edu by the homework deadline. Title your e-mail “ECE471 Homework 1”
and be sure your name is included in the document.
1. For each of the following three cases, classify if you would consider the device described as an embedded system or not. For each case use at least 3 of the characteristics given in class for what defines
an “embedded system” and say whether the device meets them.
(a) You buy an electric toothbrush that has an 8-bit PIC16F1516 microcontroller (16MHz, 8k flash,
512 bytes RAM), an 8 LED display, an i2c pressure sensor, and a motor driven by an H-bridge.
(b) The iPhone 11 has an Apple A13 processor in it. This processor is a six-core 64-bit CPU running
up to 2.66GHz. It includes machine learning accelerators (AMX) capable of 1 trillion 8-bit operations per second. It also has 4GB of RAM and a powerful GPU (graphics unit) with 1792×828
resolution.
(c) You open up a microwave and it has an 8-bit PIC processor in it. This processor runs at 10MHz
and the only interface is an LED display, a keypad, and some circuitry to operate the fans and
magnetron.
2. How many “bits” wide are the following systems? Why?
(a) An ARM 1176 found in the original Raspberry Pi. Its registers, integer ALU. program-counter,
and address bus are all 32-bits.
(b) A MOS 6502 processor (found in older desktop and embedded systems). Its registers, data bus,
and ALU are 8-bit while the instruction pointer and address bus are both 16-bit.
3. You are designing a small embedded system.
(a) Describe one reason why using an ASIC (application-specific integrated circuit) might be better
than using a microcontroller.
(b) Describe one reason why using a microcontroller might be better than using an ASIC.
ECE471 Homework 2 Raspberry Pi and Linux Solved
1. Get Linux Working
• Install some form of Linux onto your Raspberry Pi. I recommend Raspbian, which has recently been renamed to “Raspberry Pi OS”. You may have obtained an SD card that already
has Linux installed, or you can download images and find instructions here: http://www.
raspberrypi.org/downloads/
• Power up the Pi and ensure you can login. The most straightforward way to do this is have a
USB keyboard and a TV/monitor connected via HDMI. Be sure the SD card with Linux is in the
slot, and connect the power via USB and it should boot up. There are many tutorials on how to
do this online.
• You will probably be booted into a GUI interface. If it takes you to text, you can login at the
prompt. Otherwise, login. Raspbian the default login is pi and default password is raspberry.
• You can change the password with the passwd command.
You can also add users with the
adduser command, though you probably need to be root to do that: sudo adduser
• If the GUI doesn’t start by default, often you can use startx after logging in to get a graphics
interface.
• If you have trouble with any of these steps and need help, let me know as soon as possible!
2. Copy the Assignment to your Raspberry Pi
• Download the code from:
http://web.eece.maine.edu/~vweaver/classes/ece471/ece471_hw2_code.tar.gz
• There are various ways you can do this. Using a USB key or the network are probably the easiest.
– USB key
* Ideally you just plug the USB key in and if you are running the GUI it will pop up a
window and let you find the file that way.
* If you are in text mode the USB key will appear somewhere in the /media directory tree.
* If you’re really unlucky you might have to mount the USB key by hand, something like
sudo mount /dev/sda1 -o rw /media/usbkey
* To copy ece471_hw2_code.tar.gz to your home directory type something like
the following (it will vary based on exactly where the USB key got mounted)
cp /media/usbkey/ece471_hw2_code.tar.gz ~
* When you are done with the usbkey, before removing it you have to unmount it; you
should be able to do this from the GUI, or else you can manually
sudo umount /media/usbkey
– Network
* If you have your Pi on the local network, you can log in with ssh and you can copy files
using scp
* There are also a number of gui scp or sftp clients you can use to connect.
* If you are using a Mac, you can look into installing netatalk in order to access your Pi
over the network.
3. Unpack the homework files
Uncompress/unpack it with the command
tar -xzvf ece471_hw2_code.tar.gz
4. Build the C files
• Change into the ece471_hw2_code directory
cd ece471_hw2_code
• Run make to build the code.
• Run ./hello_world and it should run!
5. Modify the hello_world.c file (5 pts)
• Change the file so the output is 12 lines, each line looking something like this:
#1: ECE471 MY_MESSAGE
Where the number after the # increments each line, and MY_MESSAGE is any message you
want to print. Full credit requires using some sort of loop (not just cut/paste).
• You can use any text editor you want to do this coding. A simple one that is available on the Pi
is nano, you can start it by running nano hello_world.c
• Once you have updated the code, you can simply run make and it should recompile your code.
Then test by running ./hello_world
• Be sure to comment your code! Also fix all compiler warnings!
6. “Something Cool” (1 pt)
Copy your working code on top of the something_cool.c file.
cp hello_world.c something_cool.c
Then do one of the following.
• Change the number of times your printing code loops based on a command line argument. The
atoi() or strtod() functions might be useful for this.
• Modify your hello_world.c file further to print the lines in different colors.
HINT: Look up “ANSI escape codes”
• (harder) Instead of printing everything one color, print each line a different color.
• (even harder) Print each individual letter of the output a different color.
2
7. Answer the following questions (4pts total)
Short answers are fine. Put your answers in the README file using a text editor, it will be automatically
included in the submission process.
(a) If you want to know more about the ls program, what command can you run?
(b) What does the -a option to the ls program do?
(c) List one reason why C is often used on embedded systems.
(d) What method are you using to connect to your pi? (monitor/keyboard, network, serial, etc.?)
How are you copying files back and forth?
8. Submit your work
• Be sure your name and answers to questions are in the README file.
• Run make submit which will create a hw2_submit.tar.gz file containing README,
Makefile, hello_world.c and something_cool.c.
You can verify the contents with tar -tzvf hw2_submit.tar.gz
• e-mail the hw2_submit.tar.gz file to me by the homework deadline. Be sure to send the
proper file!
3
ECE471 Homework 3 Linux Assembly and Code Density Solved
1. Use your Raspberry-Pi to work on this project.
• Download the code from: http://web.eece.maine.edu/~vweaver/classes/ece471/ece471_hw3_code.tar.gz and copy it to the Raspberry-Pi. • Uncompress/unpack it with the command tar -xzvf ece471_hw3_code.tar.gz • Change into the ece471_hw3_code directory cd ece471_hw3_code • Put all answers to questions into the included text README file. This will automatically be bundled up with your submission.
2. Modify the exit_asm.s file to return the value 42. (1 point total)
(a) Modify exit_asm.s (b) Be sure any code comments are accurate! (c) Run make to generate an updated version (d) To test, run ./exit_asm followed by echo $? which will show you the last program’s exit status. (e) Some reminders about Linux GNU assembler (as) syntax: .equ IDENTIFIER,value sets a macro replacement, like #define IDENTIFIER value would in C
You can use @ to specify a comment, like // in C You prefix a constant value with # (to move the number 5 into a register you would do mov r0,#5 ) (f) Reminders about the Linux kernel ARM syscall EABI: Arguments go in r0 to r6 System Call Number goes in r7 Use swi 0x0 to trigger a system call.
3. Investigate the code density of print_integer (3 points total)
(a) Run make if you haven’t already, which should generate the print_integer and print_integer.thumb executables. (b) Look at the source code (the same file is used for both): print_integer.c. The algorithm used was described in class. (c) Find the size of the print_integer() function in the ARM32 executable and record it in the README i.
To disassemble the code, run the command objdump –disassemble-all ./integer_print | less the | less at the end says to feed the output of the call to the program less, which lets you scroll backwards and see all the output. ii. Find the print_integer() function. You could look manually, but the best way is to use the ‘/’ slash character to start a search and then search for print_integer.
The first location you find is the call from main() to the function, press ‘/’ again to find the actual function. iii. You should find something like the following: 0001041c : 1041c: e59fc064 ldr ip, [pc, #100] ; 10488 <print_integer+0x610420: e52de004 push {lr} ; (str lr, [sp, #-4]!) … The first column is the address in memory where this code lives, the next is the raw machine code for the instruction, the next is the decoded assembly language, and the last is the disassembler giving “helpful” hints about what’s going on.
iv. You can see in this first case all the instructions are 32-bit hex values. v. Calculate the length of this function and note it in the README. You can calculate length by scrolling down to where the function ends, (probably at something like __libc_csu_init) getting the memory address (the first column), then subtract from that the address of the start of the function.
(d) Now go back and do the same for the THUMB2 print_integer.thumb2 executable too. Record the size in the README. (e) Answer in README: Does the machine language look different for THUMB2 than ARM32? How?
4. C vs Assembly code density: (2 points total)
Put the answer to these in the README.
(a) Compare the size of the ARM32 integer_print executable and the THUMB2 integer_print.thumb2 executables. (list both sizes) You can get filesize with ls -l (that’s a lowercase L) You will want to run the strip command on the executables first (i.e. strip integer_print ) or your results might be unexpected.
(b) When you ran make it also compiled a pure assembly language version of the integer print code: integer_print_asm. What is the size of that file?
(c) Given these results, Which language might you use in space constrained system? Why? (d) Which code to you think is easier to write, the C or assembly one?
5. Use gdb to track down the source of a segfault. (2 points total)
(a) When you ran make it should have built a program called crash (b) Run that program. It should crash with a Segmentation fault error. (c) Use the gdb debugger to find the source of the error. (d) Run gdb ./crash (e) When it comes up to a prompt, type run and press enter to run it until it crashes. (f) It should tell you it crashed, then tell you what line of code caused the crash. Put the line that caused the crash in the README 2 (g) You can do various other things here, such as run bt to get a backtrace, which shows you which functions were called to get you to this error. You can run info regis to see the current register values. (h) Run disassem to get a disassembly of the function causing problems. There should be an arrow pointing to the problem code. Cut and paste this line into the README (i) In the end, what was the cause of the error in this program? (again, put this in the README
6. Something cool: (1 point total)
Modify integer_print.extra.c (which starts out the same as integer_print.c and do one of the following: • Easy: modify so instead of printing a hard-coded value in main(), it reads a value from the prompt. To read from the console into an integer in C you would use something like scanf(“%d”,&value); • Moderate: make the file print the integer in hexadecimal instead of decimal. (modify the existing algorithm, don’t use printf()) • Hard: modify integer_print_asm.s and make it print hexadecimal
7. Linux Command Line Exploration (1 point total)
Try out the cal program. This prints a calendar, by default the current month. You can also cal 2016 or cal 12 2016. Beware not to do cal 16 as that will give you year 16, not 2016. (a) Run cal 9 1752 Is there a bug here? Can you explain what is happening?
8. Submitting your work
• Run make submit which will create hw3_submit.tar.gz containing the various files. You can verify the contents with tar -tzvf hw3_submit.tar.gz • e-mail the hw3_submit.tar.gz file to me by the homework deadline. Be sure to send the proper file! 3
ECE471 Homework 4 Linux GPIO Interface Solved
1. Use your Raspberry-Pi to access the GPIOs.
• You will need a breadboard for this assignment.
• In addition use the resistors, LED, and wires from the parts kit.
• Download the code from:
http://web.eece.maine.edu/~vweaver/classes/ece471/ece471_hw4_code.tar.gz
and copy it to the Raspberry-Pi.
• Uncompress/unpack it: tar -xzvf ece471_hw4_code.tar.gz
• Change into the ece471_hw4_code directory: cd ece471_hw4_code
Model 1B
Camera
Pin1 Pin2
Composite
Audio
HDMI
Power
Pin25 Pin26
Ethernet
USB
Model 1B+/2B/3B/3B+
Audio/Video
Pin1 Pin2
Ethernet
USB USB
Power
HDMI
Model 4B
Audio/Video
Pin1 Pin2
Power
HDMI
HDMI
USB USB Ethernet
Figure 1: Raspberry Pi Layout
470 Ohm
GPIO18
Figure 2: LED connected to GPIO18.
Table 1: Raspberry Pi Header Pinout
3.3V 1 2 5V
GPIO2 (SDA) 3 4 5V
GPIO3 (SCL) 5 6 GND
GPIO4 (1-wire) 7 8 GPIO14 (UART_TXD)
GND 9 10 GPIO15 (UART_RXD)
GPIO17 11 12 GPIO18 (PCM_CLK)
GPIO27 13 14 GND
GPIO22 15 16 GPIO23
3.3V 17 18 GPIO24
GPIO10 (MOSI) 19 20 GND
GPIO9 (MISO) 21 22 GPIO25
GPIO11 (SCLK) 23 24 GPIO8 (CE0)
GND 25 26 GPIO7 (CE1)
ID_SD (EEPROM) 27 28 ID_SC (EEPROM)
GPIO5 29 30 GND
GPIO6 31 32 GPIO12
GPIO13 33 34 GND
GPIO19 35 36 GPIO16
GPIO26 37 38 GPIO20
GND 39 40 GPIO21
2. Hook up an LED to a GPIO pin (3 points total)
(a) Hook up an LED to GPIO18. Figure 2 shows the appropriate circuit and Figure 1 and Table 1
might be helpful.
(b) Modify blink_led.c so that it makes the LED blink. Blink at 1Hz with a 50% duty cycle: it
should blink with a pattern of 0.5 seconds on, 0.5 seconds off, repeating forever (on Linux to exit
out of a program in an infinite loop you can press control-C). Be sure you have the timing right!
(c) As a reminder:
i. Write your code in C.
ii. Make sure the code compiles *without warnings*.
iii. Comment your code!
iv. Be sure to check for errors (especially at open time)! If you detect an error, print a message
and then clean up and exit the program.
v. If you get a permissions error when trying to run things, the easiest (though not very secure)
way to get it going is to use the sudo utility which temporarily runs a program with root
permissions, i.e. sudo ./blink_led. You can permanently give permission for a user
to access the gpio device with the command sudo addgroup username gpio where
username is your username.
vi. usleep() can be used to sleep a certain number of microseconds.
(d) The Linux GPIO interface was covered in lecture. A brief overview follows:
i. Open the device
2
int fd,rv;
/* Open the gpio device */
fd=open(“/dev/gpiochip0”,O_RDWR);
ii. Set up a request struct
struct gpiohandle_request req;
memset(&req,0,sizeof(struct gpiohandle_request));
req.flags = GPIOHANDLE_REQUEST_OUTPUT;
req.lines = 1;
req.lineoffsets[0] = 23; // FIXME: replace with proper GPIO number
req.default_values[0] = 0;
strcpy(req.consumer_label, “ECE471”);
rv = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
iii. Set gpio value
struct gpiohandle_data data;
data.values[0]=0; // value to output (0 or 1)
rv=ioctl(req.fd,GPIOHANDLE_SET_LINE_VALUES_IOCTL,&data);
3.3V
1K
GPIO17
10K
Figure 3: Switch connected to GPIO.
3. Read input from a switch (3 points total)
(a) Connect GPIO17 to a switch as shown in Figure 3. If you do not have a switch, you can instead
just use a piece of wire connected to 3.3V and touch the other end to the proper pin.
(b) Modify read_switch.c so that it loops forever waiting for keypress events: it should print to
the screen when the key is pressed and when it is released.
(c) Each time you press and release the switch it should only print *two* messages, one when the
key is pressed and one when it is released.
(d) You can implement this by polling (constantly reading the input in a loop) you do not need to use
the fancier interrupts/poll() interface.
(e) You will, however, need to de-bounce the switch in software.
(f) The GPIO input code is similar to that for doing GPIO output with the following differences:
3
i. When setting up the request struct, use GPIOHANDLE_REQUEST_INPUT instead of
GPIOHANDLE_REQUEST_OUTPUT
ii. To read the value use
memset(&data, 0, sizeof(data));
rv = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
/* the read value is in data.values[0] */
4. Something cool: (1 point total)
Edit gpio_extra.c and do something cool. Put a short description of what you did in the README.
Here are some suggestions:
• Have the switch toggle the LED on and off.
• Have the LED blink a Morse code message.
• Hook up a second LED to GPIO23 and have them blink alternately.
5. Questions to Answer: (2 points total)
Put the answer to these in the README.
(a) Why is it good to use usleep() rather than a busy loop?
(b) How does having an operating system make life easier when programming GPIOs?
(c) How did you implement the debounce of the switch input?
6. Linux Command Line Exploration (1 point total)
Try out the dmesg program. This shows all of the system boot messages. Try piping the output into
less so you can easily scroll back and look at the messages:
dmesg | less
(a) You can use grep to search for text. Find out what your machine type is by running:
dmesg | grep Machine
Report your machine type in the README file.
(b) You can use uname to find out more about your system. Run:
uname -a
and report your kernel version in the README file.
(c) You can use df to find out how much disk is free. Run:
df -h
and report the free space on your rootfs filesystem.
(d) What does the -h option to the df command do?
7. Submitting your work.
• Run make submit which will create hw4_submit.tar.gz
You can verify the contents with tar -tzvf hw4_submit.tar.gz
• e-mail the hw4_submit.tar.gz file to me by the homework deadline. Be sure to send the
proper file!
4
ECE471 Homework 5 i2c interface and LED Display Solved
1. Use your Raspberry Pi for this homework.
In addition you will need one 4×7 segment LED display that was included in the parts packet.
More info on the display can be found here: http://www.adafruit.com/products/880
Camera
Pin1 Pin2
Composite
Audio
HDMI
Power
Pin25 Pin26
Ethernet
USB
Audio/Video
Pin1 Pin2
Ethernet
USB USB
Power
HDMI
Audio/Video
Pin1 Pin2
Power
HDMI
HDMI
USB USB Ethernet
Figure 1: Location of header on Raspberry Pi Model 1B, 1B+/2/3, 4B
2. First you will need to hook up the LED display. You can use Figure 1 and Table 1 for guidance.
(a) Hook the display to your pi on a breadboard:
Connect 3.3V on the Pi to + on the LED Display.
Connect GND on the Pi to – on the LED Display.
Connect SDA on the Pi to D on the LED Display.
Connect SCL on the Pi to C on the LED Display.
(b) Enable i2c support in Linux running on your pi.
• With current Raspberry Pi OS the easiest way is to run sudo raspi-config select “(5)
Interfacing Options” then “(P5) I2C” then say yes to enable support.
• You might have to reboot the pi for it to fully take effect.
• To allow accessing i2c as a normal user (without sudo) run this command:
sudo addgroup username i2c
where username is your username.
Table 1: Raspberry Pi Header Pinout
3.3V 1 2 5V
GPIO2 (SDA) 3 4 5V
GPIO3 (SCL) 5 6 GND
GPIO4 (1-wire) 7 8 GPIO14 (UART_TXD)
GND 9 10 GPIO15 (UART_RXD)
GPIO17 11 12 GPIO18 (PCM_CLK)
GPIO27 13 14 GND
GPIO22 15 16 GPIO23
3.3V 17 18 GPIO24
GPIO10 (MOSI) 19 20 GND
GPIO9 (MISO) 21 22 GPIO25
GPIO11 (SCLK) 23 24 GPIO8 (CE0)
GND 25 26 GPIO7 (CE1)
ID_SD (EEPROM) 27 28 ID_SC (EEPROM)
GPIO5 29 30 GND
GPIO6 31 32 GPIO12
GPIO13 33 34 GND
GPIO19 35 36 GPIO16
GPIO26 37 38 GPIO20
GND 39 40 GPIO21
(c) Sanity check your i2c setup.
• If you have your pi on a network you can run
apt-get install i2c-tools
to install the i2c-tools package and can scan the bus to be sure you have things hooked up
properly. If you can’t install the package, skip the next step, as it’s not really necessary (it’s
just a good way to verify you have things wired up correctly).
• Run sudo i2cdetect -y -r 1 and if things are working you should see a “70” at
address 70. This means Linux can see your device at address 0x70.
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — UU — — — —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — — — — — — — — — —
60: — — — — — — — — — — — — — — — —
70: 70 — — — — — — —
2
3. Documentation
The display is run by a ht16k33 chip. You can get the datasheet here:
http://www.adafruit.com/datasheets/ht16K33v110.pdf
4. Getting the Code
Download the template code from the ECE471 website:
http://web.eece.maine.edu/~vweaver/classes/ece471/ece471_hw5_code.tar.gz
Uncompress it with tar -xzvf ece471_hw5_code.tar.gz
5. Light up the Entire Display (3 points)
Modify the provided display_test.c file. Running make should build your code. If you get
clock skew errors, either set your clock to current time or else run make clean before running
make.
Comment your code! Fix all compiler warnings!
Make sure you to check for errors and report them back to the user and exit if appropriate.
Here are the steps needed to talk to the device:
(a) Open the device using the open() function. This returns an integer file descriptor for the device,
or -1 on error. The call will look something like
fd = open(“/dev/i2c-1”, O_RDWR);
where O_RDWR means open for reading and writing.
(b) Set the device address. An IOCTL is used for this.
result=ioctl(fd, I2C_SLAVE, 0x70);
where I2C_SLAVE is defined in the linux/i2c-dev.h header, fd is the file descriptor from
earlier, and 0x70 is the device address. A negative value is returned on error.
(c) Commands to the device are described starting on page 10 of the data sheet. Commands are an
8-bit value, with the command type in the top 4 bits and the data in the low 4 bits.
(d) Send a command to activate the oscillator on the device by modifying the “System Setup Register”. The high 4 command bits should be 0x2 and the low 4 bits should be 0x1.
To generate this
constant, shift the command left by 4-bits, then logical-or the low bits into the value. Write this
8-bit value to the device. The code will look something like this:
unsigned char buffer[17];
buffer[0]=(0x2<<4)|(0x1);
result=write(fd, buffer, 1);
This says to write to file descriptor fd 1 byte from a pointer pointing to the beginning of the
buffer array. The return value is how many bytes were successfully written.
Feel free to use C pre-processor defines to make the constants for the commands and data easier
to read.
(e) Next turn on the display, with blinking disabled. Do this via the “Display Setup Register”
(f) Next set the brightness. Set it to a value between 10 and 15 (your choice). Do this via the
“Display Dimming Data Input”. You will need to get the proper values from the data sheet.
3
(g) Finally write out the pattern you want on the display. For this simple test case we will write all
1s to make the display completely light up.
To do this, write the “Display Data Address Pointer” which for our case is 0, then followed by
16-bytes holding the two 8-bit values for each of the 8 rows. It is easiest to just write all 17 bytes
at once.
unsigned char buffer[17];
int i;
buffer[0]=0x0;
for(i=0;i<16;i++) buffer[1+i]=0xff;
write(fd,buffer,17);
(h) Now close the file descriptor with close(fd); and exit the program. The display will keep
displaying the last thing written to it.
6. Display ECE 471 (3 points)
For this part of the homework, modify display_final.c. First copy your display_test.c
file over as a starting point:
cp display_test.c display_final.c.
Then work on the display_final.c code.
The goal is to make the display show the following pattern:
• ECE
pause for 1 second
• 471
pause for 1 second
• Then loop back to the beginning to display ECE again, and repeat forever (you can stop it by
pressing Control-C).
The display mapping for each LED segment is shown in Figure 2.
As an example, to display the letter ‘E’ in the far left column, you would do:
unsigned char buffer[17];
buffer[0]=0x00; // offset pointer
buffer[1]=0x79; // Column 1, Segments ADEFG
buffer[2]=0x00; // next 8 bits of column 1, not connected
buffer[3]=0x00; // Column 2, empty
buffer[4]=0x00; // next 8 bits of column 2, not connected
…
write(fd,buffer,17);
The Linux/C function to pause (sleep) for a period of time is usleep(). The parameter is the amount
of time to sleep in micro-seconds.
4
A
B
C
D
E
F
G
P
B
1 2 3
4 5
byte 0 = 0x00 (display pointer offset)
byte 1 = (1P, 1G ,1F, 1E, 1D, 1C, 1B, 1A)
byte 2 = 0x00
byte 5 = (X, X, X, X, X, X, X, 3:, X)
byte 6 = 0x00
byte 7 = (4P, 4G, 4F, 4E, 4D, 4C, 4B, 4A)
byte 8 = 0x00
byte 9 = (5P, 5G, 5F, 5E, 5D, 5C, 5B, 5A)
byte10−byte16 = 0x00
byte 3 = (2P, 2G, 2F, 2E, 2D, 2C, 2B, 2A)
byte 4 = 0x00
Figure 2: LED Display Segment Mapping
7. Something Cool (1 point)
Copy your display_final.c code over to display_cool.c and modify it to do something
extra.
Some possible suggestions:
• Record an i2c write transaction using an analog discovery board.
See if you can interpret the SDA/SCL lines as bits are being sent. Some logic analyzers (possibly
the analog discovery?) are smart enough to interpret i2c and can decode the transaction for you.
Send an image of the plot along with your homework submission.
• Display ECE 471 on the display but have it scroll left or right.
• Make a little animation on the screen, bouncing ball, etc.
• Display your name, or as much of your name as you can with 7-segment displays.
• Display the time. (the time() and localtime() routines will be helpful here).
Put into the README a note describing the something cool that you chose.
5
8. Questions (2 points)
Answer the following in the README file: (note, we won’t cover some of these topics in class until
Monday)
(a) What part of the Raspberry Pi (hardware) is in charge of the initial boot process? Is this normal
for an ARM board?
(b) Why is the /boot partition on the Pi a FAT32 filesystem?
(c) What is the generic name for the code/program responsible for loading the operating system
kernel into memory and running it?
(d) In the i2cdetect output in part 2c you can see that addresses 0-2 and 0x78-0x7f are not
scanned. Why are these addresses skipped?
9. Linux Fun (1 point)
(a) You can use the wc word-count program to count the lines, words, and bytes in a file.
Use wc -l display_final.c (that’s a lower-case L) to count the number of lines in your
display_final.c file. Report how many lines it is.
(b) You can use the diff command to compare two files and see the differences between them. Run
diff -u display_test.c display_final.c
You can use the pipe character | to “pipe” the output of one command into the input of another.
Pipe the output of diff into wc and report how many lines are in the diff file:
diff -u display_test.c display_final.c | wc -l
10. Submitting your work
• Run make submit which will create a hw5_submit.tar.gz file containing Makefile,
README, display_test.c, display_final.c, and display_cool.c
You can verify the contents with tar -tzvf hw5_submit.tar.gz
• e-mail the hw5_submit.tar.gz file to me by the homework deadline. Be sure to send the
proper file!
6
ECE471 Homework 7 SPI, A/D and Temperature Probe Solved
1. Use your Raspberry Pi for this homework.
You will need an MCP3008 SPI A/D converter as well as a TMP36 temperature sensor (looks like a
transistor) that were in the parts packet.
You can view the datasheet for the MCP3008:
http://web.eece.maine.edu/~vweaver/classes/ece471_2014f/datasheets/MCP3008.pdf
You can view the datasheet for the TMP36:
http://web.eece.maine.edu/~vweaver/classes/ece471_2014f/datasheets/TMP35_36_37.pdf
Camera
Pin1 Pin2
Composite
Audio
HDMI
Power
Pin25 Pin26
Ethernet
USB
Audio/Video
Pin1 Pin2
Ethernet
USB USB
Power
HDMI
Audio/Video
Pin1 Pin2
Power
HDMI
HDMI
USB USB Ethernet
Figure 1: Location of header on Raspberry Pi Model B and B+/2/3, 4B
2. Get the MCP3008 providing values over SPI (3 points)
First wire up the SPI device to the Raspberry Pi. You can use Figure 1, Figure 2 and Table 1 for
guidance.
(a) Put the MCP3008 on a breadboard and connect to your Pi:
i. Connect 3.3V on the Pi to VDD (pin16) on the MCP3008.
Also connect 3.3V to VREF (pin15) on the MCP3008.
ii. Connect GND on the Pi to AGND (pin14) on the MCP3008.
Also connect GND to DGND (pin9) on the MCP3008.
iii. Connect SCLK on the Pi to CLK (pin13) on the MCP3008.
iv. Connect MOSI on the Pi to DIN (pin11) on the MCP3008.
v. Connect MISO on the Pi to DOUT (pin12) on the MCP3008.
vi. Connect CE0 on the Pi to CS (pin10) on the MCP3008.
Table 1: Raspberry Pi Header Pinout
3.3V 1 2 5V
GPIO2 (SDA) 3 4 5V
GPIO3 (SCL) 5 6 GND
GPIO4 (1-wire) 7 8 GPIO14 (UART_TXD)
GND 9 10 GPIO15 (UART_RXD)
GPIO17 11 12 GPIO18 (PCM_CLK)
GPIO27 13 14 GND
GPIO22 15 16 GPIO23
3.3V 17 18 GPIO24
GPIO10 (MOSI) 19 20 GND
GPIO9 (MISO) 21 22 GPIO25
GPIO11 (SCLK) 23 24 GPIO8 (CE0)
GND 25 26 GPIO7 (CE1)
ID_SD (EEPROM) 27 28 ID_SC (EEPROM)
GPIO5 29 30 GND
GPIO6 31 32 GPIO12
GPIO13 33 34 GND
GPIO19 35 36 GPIO16
GPIO26 37 38 GPIO20
GND 39 40 GPIO21
(b) For this first part, we will measure 0V on CH0 (pin1) and 3.3V on input CH1 (pin2). Hook up
power and ground to those pins on the MCP3008.
(c) Enable SPI support in Linux running on your Pi. This is a bit confusing as they have changed the
directions for this at least three times over the years.
• The current way to do this is to run the sudo raspi-config command, select “advanced options”, select “spi” and then say “yes” that you want this enabled and “yes” you
want to load the module.
• You can look at dmesg | grep spi after reboot to see if SPI support was found and
enabled.
• If you have created your own user account, you will want to do a sudo addgroup
YOURUSER spi
(d) Modify the test_spi.c file to read values from the MCP3008 and print them to the screen.
See the classnotes for more details.
• Open the /dev/spidev0.0 file for read/write access.
• Use ioctl to set the mode to SPI_MODE_0
• In an infinite loop, read the value of CH0 and CH1 once a second and print the voltages to
the screen.
– As described in class use ioctl to transmit 3 bytes:
* Be sure to clear out your transmit buffer with zeroes first (using memset or similar)
or you may get errors!
* Transmit three bytes:
2
i. the first byte contains just the start bit,
ii. the second byte has the single-ended mode bit, followed by 3 bits indicating the
channel to read, followed by zeros
iii. the third byte should be all zeros.
* Receive 3 bytes. The first byte can be ignored, the bottom 2 bits of the second byte
are bits 9 and 8, and the third byte is the bottom 8 bits of the result.
– Put the 10 bits you receive into an integer, then use VIN =
value×VREF
1024 to convert to a
floating-point voltage.
– CH0 should be roughly 0V and CH1 should be 3.3V.
(e) Be sure to comment your code and check for errors!
TMP36
3.3V Vout GND
1
2
3
4
5
6
7
8 9
10
11
12
13
14
15
16
MCP3008
Figure 2: TMP36 and MCP3008 Pinouts
3. Hook up the TMP36 to the SPI device (3 points)
(a) Copy your test_spi.c file to display_temp.c
(b) Connect the TMP36 temperature probe to CH2.
Connect pin1 (3.3V) of the TMP36 to 3.3V
Connect pin2 (Vout) of the TMP36 to CH2 on the MCP3008
Connect pin3 (GND) of the TMP36 to ground
WARNING! the datasheet shows the pins from the bottom not the top. If you reverse the
power/ground settings on the chip it will quickly heat up to 100+ degrees and will possibly
be ruined! Follow the diagram in Figure 2 and you will be OK.
(c) Modify the code to print the current temperature as read by the probe, once a second. You can
print degrees C or F as per your preference, but make sure the units are displayed.
(d) The temperature can be determined with the following equation:
deg_C = (100 × voltage) − 50
(e) Also the following might be useful:
deg_F = (deg_C ×
9
5
) + 32
Beware of C floating point/integer conversion rules!
(f) Be sure to comment your code!
3
4. Something Cool (1 point)
Copy your code to temp_cool.c and modify it to do something cool. Describe what you did in the
README file.
• Monitor the temperature, and after a while print the high/low temperatures recorded.
• Monitor the temperature and print a message if a temp is exceeded (for example, print a message
if someone touches the probe long enough to raise the temperature).
• Hook up the analog discovery board and plot one SPI transaction on the MOSI/MISO/CS0/CLK
lines. Send the plot in with your assignment.
• Note: Homework 9 involves displaying the temperature on the LED display so while it would be
cool to do that, you might as well wait a few weeks.
5. Questions (2 points)
Answer the following in the README file:
(a) You are designing an embedded system for a car that controls the anti-lock brakes. The specification says that to work properly the brakes needed to start pulsing within 10ms. Would this be
a hard, firm, or soft real-time task? Why?
(b) You are designing another part of the car. The specification says that if you push the “tune”
button on the stereo that it should switch stations within 1s. Would this be a hard, firm, or soft
real-time task? Why?
(c) You are working on the “info-tainment” system for the car, and it has a movie player for the
backseat. The specification calls for the video decoder to be able to maintain a framerate of
60Hz. Is this a hard, firm, or soft real-time task? Why?
(d) What is one disadvantage of SPI compared to i2c?
(e) What is one advantage SPI has over i2c?
(f) You want to connect a second temperature probe to the MCP3008 from this homework, but with
the TMP36 at the end of a 150-foot cable. Would this work? Why or why not?
(g) The MCP3008 datasheet says:
“… the time between the end of the sample period and the time that all 10 data bits have been
clocked out must not exceed 1.2 ms (effective clock frequency of 10 kHz). Failure to meet this
criterion may introduce linearity errors into the conversion outside the rated specifications.”
Your boss asks you to talk an MCP3008 by bitbanging SPI via GPIO from regular Linux. How
might this be a problem? Can you guarantee this timing if controlling the pins from userspace?
4
6. Linux Fun (1 point)
Linux shells have what’s known as job control. This isn’t a question, but you can try it out and see
how it works. To suspend something, press Control-Z. So if you are editing code in nano, try pressing
Control-Z. It should bring you back to the prompt.
To get back to nano again type fg. You can use
this to run make while editing and going back without losing your place. You can also use bg to
put programs running in the background, but be careful (you don’t want that to happen to nano for
example).
Linux has very useful devices under /dev besides the i2c and spi nodes.
(a) The first is /dev/null. What happens if you pipe a command to it?
For example ls > /dev/null?
(b) The next is /dev/full. What happens if you pipe a command to it?
For example ls > /dev/full?
(c) /dev/zero contains nothing but zeros. Why might that be useful?
(d) What do you think /dev/random contains?
7. Submitting your work
• Run make submit which will create a hw7_submit.tar.gz file containing Makefile,
README, test_temp.c, temp_cool.c and display_temp.c.
You can verify the contents with tar -tzvf hw7_submit.tar.gz
• e-mail the hw7_submit.tar.gz file to me by the homework deadline. Be sure to send the
proper file!
5
ECE471 Homework 8 1-wire bus Solved
1. You will need a DS18B20 1-wire temperature probe (looks like a transistor) and pull-up resistor (4.8K
or 10K, either works) from your parts packet.
You can view the datasheet for the DS18B20:
http://web.eece.maine.edu/~vweaver/classes/ece471_2014f/datasheets/DS18B20.pdf
Camera
Pin1 Pin2
Composite
Audio
HDMI
Power
Pin25 Pin26
Ethernet
USB
Audio/Video
Pin1 Pin2
Ethernet
USB USB
Power
HDMI
Audio/Video
Pin1 Pin2
Power
HDMI
HDMI
USB USB Ethernet
Figure 1: Location of header on Raspberry Pi Model B, Models B+/2/3, Model 4B
DS18B20
GND 3.3V Data
Figure 2: DS18B20 Pinout
Table 1: Raspberry Pi Header Pinout
3.3V 1 2 5V
GPIO2 (SDA) 3 4 5V
GPIO3 (SCL) 5 6 GND
GPIO4 (1-wire) 7 8 GPIO14 (UART_TXD)
GND 9 10 GPIO15 (UART_RXD)
GPIO17 11 12 GPIO18 (PCM_CLK)
GPIO27 13 14 GND
GPIO22 15 16 GPIO23
3.3V 17 18 GPIO24
GPIO10 (MOSI) 19 20 GND
GPIO9 (MISO) 21 22 GPIO25
GPIO11 (SCLK) 23 24 GPIO8 (CE0)
GND 25 26 GPIO7 (CE1)
ID_SD (EEPROM) 27 28 ID_SC (EEPROM)
GPIO5 29 30 GND
GPIO6 31 32 GPIO12
GPIO13 33 34 GND
GPIO19 35 36 GPIO16
GPIO26 37 38 GPIO20
GND 39 40 GPIO21
2. Get the DS18B20 temperature readings over 1-wire (6 points)
First wire up the 1-wire device to the Raspberry Pi. You can use Figure 1 and Table 1 for guidance, as
well as Figure 2.
(a) Put the DS18B20 device on a breadboard:
Connect 3.3V on the Pi to 3.3V on the DS18B20.
Connect GND on the Pi to GND on the DS18B20.
Connect GPIO4 on the Pi to Data on the DS18B20.
Connect GPIO4 to 3.3V via the pullup resistor.
(b) Enable 1-wire support in Linux running on your Pi.
It should be possible to do this by running raspi-config, Interfacing Options, 1-wire, enable,
and then rebooting.
(c) If all went well, then if you run lsmod | grep w1 it should show that both the w1-gpio
and w1-them modules (device drivers) are installed and running. (Note it’s w-one the number,
not w-lower-case-L).
2
(d) Modify the provided temp_1wire.c file to read values from the DS18B20 and print them to
the screen. See the classnotes for more details.
i. Find the unique-id for your DS18B20 device.
Look for a directory under /sys/bus/w1/devices/ that looks something like
28-000005aaf7ed.
ii. Modify the provided read_temp() routine so it returns the temperature in degrees C as a
floating point value.
A. Open the 1wire file, which looks something like this:
/sys/bus/w1/devices/28-000005aaf7ed/w1-slave
Please do not hard-code this device name directly into the call where you open the file.
Instead, modify the sensor_name.h file, which is included by temp_1wire.c.
Then when you open the file use SENSOR_NAME as the filename. This makes things a
bit easier to grade.
B. Read the file. There are two values you want to grab, the YES value at the end of the
first line and the t=24125 value from the end of the second line.
One way to do this is to use fscanf() but you can use any method that works (there
are many).
To use fscanf of a string, do something like
char string1[256],string2[256];
FILE *fff;
fff=fopen(“filename”,”r”);
fscanf(fff,”%s %s”,string1,string2);
HINT: If you want to read a string but not actually store the value (in effect, skipping a
value from the stream) you can do something like:
fscanf(fff,”%*s %s”,string1);
The asterisk there means to read the value but not store it anywhere.
C. Read the YES/NO value from the end of the first line and check if the value is YES.
If it isn’t, print an error and return an invalid temperature value.
(HINT, you can use
strcmp() if you want, but be careful, it works backward from what you might expect).
Next, read the t=XXXXX value. It is in miliCelsius, so first get the value (skipping the
t= part; there are various ways to do this, remember that in C strings are just arrays of
char, and arrays are just pointers).
Convert the integer miliCelsius value to floating point regular Celsius, and return.
iii. In an infinite loop, read the temperature value in C and print it to the screen once a second.
(e) Be sure you handle errors that may occur.
(f) Be sure to close any files that you open when you are done with them.
(g) Always comment your code!
3
3. Something Cool (1 point)
Copy your code to temp_cool.c and modify it to do something cool. Some example ideas:
• (Easy) Print the temperature in a different unit (Fahrenheit, Kelvin, etc.)
• (Medium) hook up an analog discovery board and plot a 1-wire transaction. How does it compare
to theory? Send an image along with your assignment.
• (Medium Hard) Automatically search the /sys/bus/w1/devices/ directory for a sensor
name rather than hard-coding it in.
• (Hard) Make the code also read the TMP36 sensor from last homework, and compare how closely
the temperatures match.
• (Hard) Get the sensor working in parasite mode (without Vdd). Write up what you needed to
do to get this to work. It might require wiring things differently, as well as kernel/device-tree
parameters.
4. Questions (2 points)
Answer the following in the README file:
(a) One-wire in theory only uses 1-wire for data plus ground. In this lab we hooked up Vdd too.
Why did we do that? (Hint, look up what’s needed to use parasite power mode in the DS18B20
datasheet).
(b) If you wanted to connect your pi to a temperature probe 100 yards (approximately 100 meters)
away, and your choices were i2c, spi, or 1-wire, which bus would you use and why?
5. Linux Fun (1 point)
On Linux you can create shell scripts, which are simple scripts that run shell commands.
The first line contains the path to the program that you want to interpret the path. For example
#!/bin/sh
What follows are just a list of commands as you’d type at the prompt.
The “echo” command is used to print text.
echo “Hello World”
Lines starting with a hash # are comment lines.
(a) Edit the sample.sh file (the provided file is empty) to use the /bin/sh shell, and then print a
message of your choice using echo
Make the file executable by using the command chmod +x sample.sh
Be sure to add comments to your script!
Test your shell script by running ./sample.sh
4
6. Submitting your work
• Run make submit which will create a hw8_submit.tar.gz file containing Makefile,
README, sample.sh, temp_cool.c and display_temp.c.
You can verify the contents with tar -tzvf hw8_submit.tar.gz
• e-mail the hw8_submit.tar.gz file to me by the homework deadline. Be sure to send the
proper file!
5
ECE471 Homework 9 Temperature Display Solved
1. You will need the i2c display from Homework 5 as well as either the MCP3008/TMP36 from Homework 7 or the DS18B20 sensor from Homework 8 (your choice).
Upon completing this assignment you can turn back in the parts you have signed out.
Be sure to check for errors and to comment your code!
2. Make your temperature code modular (2pts)
Take one of your temperature reading homeworks as a basis for this project. Copy your code into
read_temp.c
The interface needed, as described in read_temp.h is
double read_temp(void);
So have your code read the temperature, and return it as a double value in degrees C.
If there is an error, report a temperature of less than -1000 degrees.
The provided test_temp program uses this interface, so once your code is ready, running make
should build test_temp and it should print the temperature when you run it.
3. Make your display code modular (3pts)
Take your i2c display code and put it into the write_display.c file.
The interface it should have as described in write_display.h is:
int init_display(void);
int write_display(int fd,double value);
int shutdown_display(int fd);
The init_display() function should init the display (including turning it on, brightness, etc) and
return the file descriptor.
The write_display() function should take the file descriptor and the temperature value and put
that onto the display. (See below for more details).
The shutdown_display() function should take the file descriptor and close it, as well as any
other cleanup that needs to be done (which might be none, depending on how your code works).
The write_display() function should print the provided floating point temperature value (in F
or C, your choice).
Your code should handle four cases:
(a) Temperatures from 0 to 99.9 degrees, inclusive. 0.0 ≤ temp ≤ 99.9 These should be displayed
as two digits, a decimal point, another digit, and then a degree symbol (which is just a crude circle
made of the top 4 segments on the display). Leading zeros should be suppressed (i.e. display
“1.2” not “01.2”, 0 should be “0.0”)
(b) Temperatures between -99.9 and 0 degrees. −99.9 ≤ temp < 0 These should display a minus
sign and then two digits of temperature, then the degree symbol.
(c) Temperatures between 100 and 999 degrees. 100 ≤ temp ≤ 999 should print three digits of
temperature, then the degree symbol.
(d) Invalid temperatures that won’t fit the display (and errors reading the thermometer) should be
reported (via the display) in a method that isn’t a valid temperature. It is your choice how to
indicate this.
Once you have the code working, you can use the provided test_display program to test that it
is printing things properly. It takes one command line argument, which is the floating point value to
print.
4. Testing the display output (1pt)
Use the test_display program to test various inputs and be sure they meet the standards as described.
In the README, list 5 test values you used, and write a brief note for why you chose those values /
why you think they cover the functionality of the interface.
5. Temperature Display (1pt)
Now modify display_temp.c to be a program that uses the interface above to reads the temperature once a second and writes the value to the display.
6. Something Cool
No something cool for this homework. Put any coolness to use in your final project.
7. Questions (1pt)
Edit the README file to have your name and answer the following questions.
(a) Name one example of poorly written embedded code that had disastrous results.
(b) Why might it be good to always try to write correct, documented, well tested code even if you
think it’s not going to ever be used in anything important?
8. Linux Fun (2pts)
Do the following on a raspberry pi. If for whatever reason you do the exercise on some other sort of
machine, describe what kind you used.
When a file is created or modified on Linux various timestamps are updated. atime (last access time)
mtime (last modified time) and ctime (last attribute update).
The ls -lt (that’s a lowercase L) will show all files and their last modified time.
The Linux touch command will update the timestamps on a file to the current time (and create the
file if it doesn’t exist). You can also specify the time. You can do things like
touch –date “1983-10-16 14:40” blah
which will update the timestamp on the file blah to the specified date.
You can also do fun things like
touch –date “next Thursday” blah
2
(a) Use touch to change the file modification time of the “fakedate” file (included with the test code)
with a date from some other year (not 2020).
(b) What happens if you try to create a date in the year 2044? Why?
(c) Sometimes students turn in homework late, but suggest “check the file timestamp, it shows I
finished it before the deadline”. Why might this not be the most convincing argument?
9. Submitting your work
• Run make submit which will create a hw9_submit.tar.gz file containing Makefile,
README, display_temp.c, and fakedate. You can verify the contents with tar -tzvf
hw9_submit.tar.gz
• e-mail the hw9_submit.tar.gz file to me by the homework deadline. Be sure to send the
proper file!
3
ECE471 Homework 10 Power/Performance Solved
Power and Energy
Table 1: OpenBLAS HPL N=10000 (Matrix Multiply)
Machine Processor Cores Frequency Idle Power Load Power Time Total Energy
Raspberry Pi 2 Cortex-A7 4 900MHz 1.8W 3.4W 454s 1543J
Dragonboard Cortex-A53 4 1.2GHz 2.4W 4.7W 241s 1133J
Raspberry Pi 3 Cortex-A53 4 1.2GHz 1.8W 4.3W 178s 765J
Jetson-TX1 Cortex-A57 4 1.9GHz 2.1W 13.4W 47s 629J
Macbook Air Broadwell 2 1.6GHz 10.0W 29.1W 14s 407J
1. Table 1 shows the energy use of various machines when doing a large Matrix-Matrix multiply.
(a) Which machine has the lowest under-load power draw?
(b) Which machine consumes the least amount of energy?
(c) Which machine computes the result fastest?
2. Consider a use case with an embedded board taking a picture once every 60 seconds and then performing a matrix-multiply similar to the one in the benchmark (perhaps for image-recognition purposes).
Could all of the boards listed meet this deadline?
3. Assume a workload where a device takes a picture once a minute then does a large matrix multiply (as
seen in Table 1). The device is idle when not multiplying, but under full load when it is.
(a) Over an hour, what is the total energy usage of the Jetson TX-1?
(b) Over an hour, what is the total energy usage of the Macbook Air?
4. Given your answer in the previous question, which device would you choose if you were running this
project off of a battery?
Submitting the Assignment
Please put your answers to questions 1 – 4 in some sort of document (text, pdf, doc) and *e-mail* it to me
by the deadline.
2




