cpu/atmega_common: Cleanup state flags#13308
Conversation
- Use one byte of RAM to track both IRQ and UART TX state - Fix incorrect use of volatile
| unsigned long state = irq_disable(); | ||
| atmega_state |= ATMEGA_STATE_FLAG_UART_TX(uart); | ||
| irq_restore(state); |
There was a problem hiding this comment.
This is the point I expect to increase the ROM. The issue is that the AVR cannot set a flag in SRAM atomically. The original version would have looked like:
lds r24, _tx_pending
or r24, r25
sts _tx_pending, r24Or in my own words:
- Load
_tx_pendinginto a register - Set a bit in the register (according to the value in
uart) - Write the register back into
_tx_pending
Lets say in _tx_pending the bit for UART1 is set, and for UART0 is not. Now command 1. is executed and this state is loaded into the register. If the IRQ kicks in and clears the bit in _tx_pending this update is lost, as command 3 will restore this bit. Therefore this whole "load, set bit, store" sequence needs to be done atomically. The AVR cannot do this in a single instruction, so we have to resort to disabling interrupts. (Or using C11 atomic, which would internally do the same but with more overhead.)
e328feb to
1879f58
Compare
|
Btw: The reason I stumbled upon this is that putting the AVR into sleep mode (for saving power or reducing noise during ADC conversions) the UART peripheral is just turned off; even if the last character is not fully send out. Having |
|
Nice, will test asap. |
BOARD=arduino-uno make -C tests/sys_arduino flash test |
|
I don't get the exact same diff, but it is in the same general lines, I guess it depends on the exact application, less RAM, more ROM.
|
|
@fjmolinas: All green here. Note: There is also another use case for the state flags introduced here: It could also track if SPI, I2C, PWM or other stuff is in use that prevents going to low power modes. And adding some power management to AVR is overdue :-) |
|
GO! |
this could interest @roberthartung |
|
@fjmolinas thanks for the mention. My current implementation ( #8207 ) relies on pm_block() in pm_layered. I will try to work on a rebase and update on #8207 asap. |
Contribution description
Result of elf_diff on my machine: -1 Byte RAM, + 42 Bytes ROM
Testing procedure
TX should still work as expected.
Issues/PRs references
#12973