This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| en:multiasm:exercisesbook:arduinouno [2026/05/04 10:05] – pczekalski | en:multiasm:exercisesbook:arduinouno [2026/05/04 14:55] (current) – [Function Call Standards] ktokarz | ||
|---|---|---|---|
| Line 33: | Line 33: | ||
| Source code needs to use explicit declarations to tell the GCC-AVR toolkit how to handle the contents: whether it is code or data, whether the variable is read-only, whether it should be stored across updates, and so on. There are two possible approaches to is: one is to use declarations (' | Source code needs to use explicit declarations to tell the GCC-AVR toolkit how to handle the contents: whether it is code or data, whether the variable is read-only, whether it should be stored across updates, and so on. There are two possible approaches to is: one is to use declarations (' | ||
| There are five '' | There are five '' | ||
| - | Each of them does the job of '' | ||
| <table arduinomemorysections> | <table arduinomemorysections> | ||
| Line 44: | Line 43: | ||
| | **.eeprom** | Long-term storage | EEPROM | No | | | **.eeprom** | Long-term storage | EEPROM | No | | ||
| </ | </ | ||
| - | + | The AVR GCC compiler uses virtual addresses to distinguish the nature of objects; thus, each section (corresponding to a kind of memory) has a separate virtual address | |
| - | We mentioned before | + | |
| - | It is, because Flash, EEPROM, and SRAM all start at 0x0000 (see figure {{ref> | + | |
| For this reason, the way the AVR-GCC toolchain (assembler and linker) handles Harvard Architecture in Arduino Uno (ATMega328P) is the use of virtual memory offsets: '' | For this reason, the way the AVR-GCC toolchain (assembler and linker) handles Harvard Architecture in Arduino Uno (ATMega328P) is the use of virtual memory offsets: '' | ||
| <table arduinomemoryblocks> | <table arduinomemoryblocks> | ||
| < | < | ||
| - | ^ Memory Type ^ GCC Internal Offset ^ Hardware Address ^ | + | ^ Memory Type |
| - | | Flash | %%0x000000%% | %%0x0000%% | | + | | Flash |
| - | | SRAM | %%0x800000%% | %%0x0000%% | | + | | SRAM (Registers and I/ |
| - | | SRAM (Internal) | %%0x800100%% | %%0x0100%% | | + | | SRAM (Internal) |
| - | | EEPROM | %%0x810000%% | %%0x0000%% | | + | | EEPROM |
| </ | </ | ||
| - | <note tip>In some of the following chapters, we sometimes present a " | + | <note tip>In some of the following chapters, we sometimes present a " |
| - | To summarise briefly, the most common scenario is that the code is intended to land in Flash memory, while variables are in SRAM. Appropriate '.org' | + | To summarise briefly, the most common scenario is that the code is intended to land in Flash memory, while variables are in SRAM. Appropriate |
| - | It is possible to write code without using sections, but that makes the code unnecessarily complicated. Whenever you use variable declarations, | + | It is possible to write code without using sections, but that makes the code unnecessarily complicated. Whenever you use variable declarations, |
| The sample code below declares a 16-bit value named ' | The sample code below declares a 16-bit value named ' | ||
| Line 71: | Line 68: | ||
| .org 0x100 ; Set SRAM start address manually | .org 0x100 ; Set SRAM start address manually | ||
| analogue_value: | analogue_value: | ||
| - | .skip 2 ; 16-bit variable | + | .skip 2 ; 16-bit variable |
| .section .text | .section .text | ||
| Line 90: | Line 87: | ||
| </ | </ | ||
| - | <note warning> | + | <note warning> |
| ===== GPIO and Ports ===== | ===== GPIO and Ports ===== | ||
| Line 107: | Line 104: | ||
| </ | </ | ||
| - | <note tip>Some GPIOs have extra features (as presented | + | <note tip>Some GPIOs have extra features (as presented |
| - | **IO Registers **\\ | + | **I/O Registers **\\ |
| Each Port has assigned three 8-bit registers (there are 9 in total then): | Each Port has assigned three 8-bit registers (there are 9 in total then): | ||
| * DDRx (Data Direction Register): there are 3 of those registers, one per Port (B, C, D): DDRB, DDRC and DDRD. This registers configures GPIO as Input (0) or Output (1). Configuration is done "per bit", so it is equivalent to controlling each GPIO individually. | * DDRx (Data Direction Register): there are 3 of those registers, one per Port (B, C, D): DDRB, DDRC and DDRD. This registers configures GPIO as Input (0) or Output (1). Configuration is done "per bit", so it is equivalent to controlling each GPIO individually. | ||
| Line 178: | Line 175: | ||
| A common scenario for manual control of the GPIO pin is to first set either the GPIO is input or output (using the correct DDRx register), then either set ('' | A common scenario for manual control of the GPIO pin is to first set either the GPIO is input or output (using the correct DDRx register), then either set ('' | ||
| - | <note tip>'' | + | <note tip>'' |
| Line 412: | Line 409: | ||
| </ | </ | ||
| - | The function is called when interrupt INT0 (on the falling edge of GPIO 2) occurs, and it simply toggles PB5 (GPIO 13, built-in LED). This is a trick in AVR that simplifies code: the classical read-> | + | The function is called when interrupt INT0 (on the falling edge of GPIO 2) occurs, and it simply toggles PB5 (GPIO 13, built-in LED). This is a trick in AVR that simplifies code: the classical read-> |
| <code asm> | <code asm> | ||
| ; --- Interrupt Service Routine --- | ; --- Interrupt Service Routine --- | ||
| Line 474: | Line 471: | ||
| Where **Fcpu** is 16MHz for regular Arduino Uno (AtMega 328P). Note that this calculation yields ~9615 bps, not exactly 9600 bps. A tolerance of up to 2% is acceptable (here, it is 0.16%). | Where **Fcpu** is 16MHz for regular Arduino Uno (AtMega 328P). Note that this calculation yields ~9615 bps, not exactly 9600 bps. A tolerance of up to 2% is acceptable (here, it is 0.16%). | ||
| - | Next step is to enable UART: | + | Next step is to configure frame format (8 bits, no parity, 1 stop bit, shortly 8N1 - the most common case): |
| <code asm> | <code asm> | ||
| - | ldi r16, (1 << | + | ldi r18, (1<<UCSZ01) | (1<< |
| - | sts UCSR0B, r16 | + | sts UCSR0C, r18 |
| </ | </ | ||
| - | and configure frame format (8 bits, no parity, 1 stop bit, shortly 8N1 - the most common case): | + | |
| + | and enable | ||
| <code asm> | <code asm> | ||
| ldi r16, (1 << TXEN0) | ldi r16, (1 << TXEN0) | ||
| sts UCSR0B, r16 | sts UCSR0B, r16 | ||
| </ | </ | ||
| - | Now it is time to send the string to the transmitter, | + | |
| + | Now it is time to send the string to the transmitter, | ||
| <code asm> | <code asm> | ||
| main: | main: | ||
| Line 531: | Line 530: | ||
| <table arduinotimerprescalers> | <table arduinotimerprescalers> | ||
| - | < | + | < |
| ^ Prescaler ^ Frequency ^ Period (Tick Speed) ^ | ^ Prescaler ^ Frequency ^ Period (Tick Speed) ^ | ||
| | 1 | 16 MHz | 0.0625 µs | | | 1 | 16 MHz | 0.0625 µs | | ||
| Line 579: | Line 578: | ||
| ** The Notification **\\ | ** The Notification **\\ | ||
| - | These registers are to control the timer-based interrupt notification system. We do not use interrupts for PWM; therefore, this description is omitted. | + | These registers are to control the timer-based interrupt notification system. We do not use interrupts for PWM, but they are necessary for handling timer-based tasks. |
| <table arduinothemanagertimer> | <table arduinothemanagertimer> | ||
| Line 965: | Line 964: | ||
| Start conversion by setting the ADSC bit (6) of ADSCRA to 1. | Start conversion by setting the ADSC bit (6) of ADSCRA to 1. | ||
| - | ADC requires some time to read the value and complete the conversion | + | ADC requires some time to complete the conversion; thus, when the result |
| Here, we do not use any interrupts, just dummy pulling. | Here, we do not use any interrupts, just dummy pulling. | ||
| <code asm> | <code asm> | ||
| Line 1001: | Line 1000: | ||
| ** Speed vs Quality ** | ** Speed vs Quality ** | ||
| - | ADC converts an analogue value to its digital representation using a capacitor. Charging and discharging of the capacitor require time and depend on the impedance of the analogue signal' | + | ADC converts an analogue value to its digital representation using a method called successive approximation, |
| <table arduinoadcprescaler> | <table arduinoadcprescaler> | ||
| Line 1044: | Line 1043: | ||
| <figure avrarduinocallingconventions> | <figure avrarduinocallingconventions> | ||
| - | {{: | + | {{: |
| < | < | ||
| </ | </ | ||
| Line 1198: | Line 1197: | ||
| To use a string (e.g. constant) that is stored in Flash, convert this line: | To use a string (e.g. constant) that is stored in Flash, convert this line: | ||
| '' | '' | ||
| - | <note important> | + | <note important> |
| ** Delay (in ms) **\\ | ** Delay (in ms) **\\ | ||