9. Embedded programming¶
This week I programmed the board which was designed during week 7
ATTiny 44¶
I skimmed through the Datasheet for the ATTiny44 to get an overall idea of the architecture and the key features. Below are some main pictures from the datasheet.
|
|
|
|
|
Programming¶
I modified Niel’s code to blink a LED. In my hardware board, I had connected a white LED on the PB2 pin of the AVR, where AVR is sinking the current, which means that the LED will glow when 0
is written on the PB2. The code changes required were quite simple, all I had to do was set the PB2 pin as output and then write an appropriate word on the data register of the port.
DDRB |= (1<<PB2); % this is how you set the direction of PB2 to output PORTB |= (1<<PB2); % this is how you write 1 on PB2 without modifying any other bits. This will turn off the LED PORTB &= ~(1<<PB2); %this is how you write 0 on PB2 without modifying any other bits. This will turn ON the LED
An extremely short C tutorial¶
Let’s deconstruct each of the lines shown above, word(token) by word(token).
DDRB |= (1<<PB2);
DDRB
–> this is a macro (written by keyword #define
) specifying the data direction register. it is defined in iotnx4.h
it expands to _SFR_IO8(0x17)
. _SFR_IO8
is another macro defined in sfr_defs.h and it expands to
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr) + __SFR_OFFSET) #define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
which ultimately comes to a following statement
(*(volatile uint8_t *)0Xxx) --> here 0Xxx is the address in hexadecimal.
it is a cast to pointer to a volatile byte.
This means that the compiler will assume that it is possible for the variable that the memory
location being pointed to have changed even if there is nothing in the source code to suggest that this might occur
|=
is a bitwise OR operator where the token on left side (Lval) is one input to the bitwise OR operation.
the second input for the OR operation is the value on the right (rval). Furthermore, the result is stored
back in the token on the left.
PB2
is another macro which decomposes to a number, say 2.
<<
is a left shift operation
(1<<PB2)
is shifting binary 1 to left to make a new number, for exacple if PB2 is 2
then (1<<2) = '00000100'
or 0x04 or 4 in decimal
PORTB |= (1<<PB2);
This is almost similar to the above line with the only difference being in the memory address to which a value is being written to.
PORTB &= ~(1<<PB2);
Here, we are again writing something to a memory location but instead of using btwise OR operation we are using bitwise AND operation to build the value. The ~
is a bitwise NOT operator which flips the bits. for example as shown above, (1<<2)
will give us 0x04
. Now doing a bitwise NOT on it will give us 0xFB
or in binary 11111011
.
Complete Code for blinking the LED
/* * GccApplication3.c * * Created: 20.3.2019 0.43.21 * Author : asethi */ #include <avr/io.h> #include <util/delay.h> int main(void) { unsigned int delay = 100; DDRB |= (1<<PB2); /* Replace with your application code */ while (1) { _delay_ms(delay); PORTB &= ~(1<<PB2); _delay_ms(delay); PORTB |= (1<<PB2); } }
WSL¶
Since earlier I had installed the windows subsystem for linux, it was fairly easy to download the tools required. I used apt
command to install the compiler, C library for the AVR and other tools.
sudo apt install avrdude gcc-avr avr-libc make
Even though I had installed avrdude, I soon found out that USB device tree is not supported by the WSL which means I cannot use the avrdude in WSL to program the board. I had to use avrdude under windows environment only. Given the fact that there is no IDE available for the WSL and the makefiles involved are so simple that I can just call gcc directly, I will be anyway going to use the Atmel Studio.
Atmel Studio¶
It is always nice to use an IDE if you are planning to write anything larger than couple of lines of code and as I am planning to use the Atmels Advanced Software Framework in the future, I will be using Atmel Studio for further development.
Start with a new project
|
|
To build the Niel’s code a pre-processor macro named F_CPU
has to be defined. It can be defined in the code or can be defined in the tool-chain setting. I defined it in the tool-chain settings. The screenshot below shows the location.
|
|
|
Build the solution
|
Add the programmer. Keep in mind that I am using USBasp programmer instead of the the FabISP. Change the avrdude command accordingly.
|
Add the avrdude to the path of the user, if not done already. Should be done for the windows user who is using the Atmel Studio, not for the administrator.
|
|
STM32¶
We used a Nucleo-F429ZI board. The board support package came from STM itself and we used FreeRTOS as a scheduler to blink a couple of LEDs. Eclipse was used as an IDE and openocd was used for debugging.
ToolChain and IDE¶
Follow this page for help on getting the toolchain and eclipse helper plugin. Furthermore, install STM32CubeMx application for generating the board support package, middleware and correct startup configuration.
Firmware¶
Start with the STM32CubeMx application
|
|
|
|
|
|
Compiling and Running¶
In the previous step all the required boilerplate plate was generated. Now it will be compiled, edited and then will be run on the board.
|
|
|
|
|
|
|
|
|
After successfully building and running just the boilerplate code, we can modify the code and add some user specific code to make two leds toggle. Add the following code in main.c, compile and run.
void StartDefaultTask(void const * argument) { /* USER CODE BEGIN 5 */ /* Infinite loop */ for(;;) { HAL_GPIO_WritePin(GPIOB, LD3_Pin|LD2_Pin, GPIO_PIN_RESET); osDelay(300); HAL_GPIO_WritePin(GPIOB, LD3_Pin|LD2_Pin, GPIO_PIN_SET); osDelay(300); } /* USER CODE END 5 */ }
Make sure to plug an Ethernet cable in an active port otherwise the board will get stuck in Ethernet initialization. To temporarily get around it, you can remove the infinite loop in the following error handler. In an actual application, this error should be handled properly instead of an infinite loop.
void _Error_Handler(char *file, int line) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ while(0) { } /* USER CODE END Error_Handler_Debug */ }
Comparison¶
The STM32 family of 32-bit microcontrollers are based on the Arm® Cortex®-M processor. The STM32 F4-series, compared to earlier versions, has higher clock speed (upto 180 MHz), 384 KB of static RAM, upto 2 MB of flash memory, and faster ADCs. All devices offer one 12-bit ADC, a low-power RTC, six general-purpose 16-bit timers including one PWM timer for motor control, two general-purpose 32-bit timers. They also feature standard and advanced communication interfaces.
AVR microcontroller was developed in the year of 1996 by Atmel Corporation. These are modified Harvard architecture 8-bit RISC single-chip microcontrollers. AVR Microcontrollers are available in three Categories
- TinyAVR:- The have small size with 0.5–32 KB program memory. They are appropriate for simpler applications.
- MegaAVR:- These are the mainly popular ones having a good quantity of memory (up to 256 KB), higher number of inbuilt peripherals and appropriate for modest to complex applications.
- XmegaAVR:- They have big ICs with upto 100 pins and upto 384 KB program memory. They also support advanced features like cryptography and event management.
An ARM processor is one of a family of CPUs based on the RISC (reduced instruction set computer) architecture developed by Advanced RISC Machines (ARM). They are available in both 32-bit and 64-bit RISC multi-core processors. RISC processors are designed to perform a smaller number of types of computer instructions so that they can operate at a higher speed, performing extra millions of instructions per second (MIPS). By stripping out unnecessary instructions and optimizing pathways, RISC processors give outstanding performance at a part of the power demand of CISC (complex instruction set computing) procedure. They are widely used in customer electronic devices such as smart phones, tablets, multimedia players and other mobile devices, such as wearables.
Reflection¶
What questions do you have? Regarding embedded programming, none.
What would you like to learn more about? JTAG and other debugging tools. How to debug AVR microcontrollers.
Problems¶
- FTDI cable is not working correctly on my laptop. All I receive is raw 0x00 irrespective of whatever the board is sending. I have checked via oscilloscope that what board is sending is correct and other PCs do show correct result with the same FTDI cable.