Split atmega_common code into avr8_common folder. This moves common
avr8 code to be used for all avr8 variants: tiny, mega and xmega.
Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
Split cpu.c file into cpu.c and atmega_cpu.c files. This extract mega
specific code from common code.
Signed-off-by: Gerson Fernando Budke <nandojve@gmail.com>
The module cpu_atmega_common_cxx seems to be non-existing and not used. It is
unclear whether this slipped in by accident or if this was actually useful at
some point in time. In any case, the module is not present (anymore) and cannot
be used, so let's clean up the Makefile.
Split out Gunar Schorcht's clever approach to provide thread safe malloc for
AVR into a system module and make AVR depend on this. This allows other
platforms to also use this.
If a timer triggers while the idle thread is running, previously a stack
overflow was triggered. This commit increases the idle threads stack size if
xtimer is used.
Added a low level implementation of timer_set() that allows setting relative
timeouts as short as 0. This results in tests/periph_timer_short_relative_set
no passing.
The inline assembly implementation was badly in need of improvement.
- irq_disable() took 2 CPU cycles more than needed
- The current interrupt state was stored in a temporary register and
afterwards copied to the target register, rather than storing it in the
target register right away
- The lower bits of the state were cleared (as they have no meaning for the
interrupt status), but the API purposely never required such things from
implementations.
- irq_restore() took 5 CPU cycles. This was reduced to 3 CPU cycles (or 2 CPU
cycles in the best case)
- On pwm_poweron, the PWM resolution was not restored. (A custom resolution was
only usable if, PWM channel 0 is not used. That configuration is not common,
so this bug was likely never triggered)
- Disabled a work around to prevent flickering:
- Previously, PWM was disconnected on level 0% and 100%
- This increases the run time of `pwm_set()`
- It prevents using the PWM for wave form generation via DDS, as the wave
noticeably jumps when reaching 0% or 100%
- Slightly reduces memory requirements: 2 Bytes of RAM, 112 Bytes of ROM
- Tested with avr-gcc 9.2.0 and LTO enabled
Drop `#include "irq.h"` in `cpu.h`, which was there for a legacy work around.
A bunch of missing includes of `irq.h` materialized due to this and were
fixed.
This implements a basic Real Time Clock based on TIM2.
As the timer is too fast and wraps around after just 8 bits, it is
not used directly. Instead TIM2 is responsible for providing a 1 Hz
tick by generating an alarm every second.
The current time data is kept in the `.noinit` section, so it will survive
a reboot, but the clock will not be updated while the bootloader runs, so
expect inaccuracies.
The reboot process for ATmegas is to enable the watchdog timer and loop until
the wdt reboots this MCU. However, this reboot will keep the wdt configuration,
so that the wdt needs to be disabled during boot. This is done in get_mcusr,
but without the attribute "used" it will be optimized out in LTO builds. This
commits adds the attribute "used" to get_mcusr.
Also simplified the backward compatibility with older ATmegas (currently not
supported by RIOT) on outdated versions of avrlibc.
For atmega boards a TX has not actually completed until UDRn is empty
as well as the Transmit Shift Register.
To avoid resetting an UART before a TX has completed we use the TXCn
flash and ISR to set a variables that indicates TX is ongoing. This
allows not reseting the UART while there are ongoing TX pending.
This fixes an issue where part of the last byte is not shifted out
of the TX shift register causing rubish on the first TX following an
uart_init.
- Using a enum instead of _COUNTER is easier to read
- _COUNTER is also a reserved name; so better not use it to avoid issues
- Split out the pcint code into a static inline function for increased
readability
The bank index and the pin number are not necessarily identical. For all
PCINT banks except for bank 3 bank_idx was used therefore. It was likely
just forgotten to update that for bank 3 as well.
At the end of an ISR, the ATmega code was doing an `thread_yield()` instead of
a `thread_yield_higher()`. This resulted in tests/isr_yield_higher failing.
Fixing this saves a few lines of code, some ROM, and solves the issue.
Names with two leading underscores are reserved in any context of the c
standard, and thus must not be used. This ATmega platform used it however for
defining internal stuff. This commit fixes this.
Moved macros and static inline helper functions needed to access ATmega GPIOs
to cpu/atmega_common/include/atmega_gpio.h in order to reuse them for the
platform specific low level part of the Neopixel driver.
ATmega128RFA1/ATmega256RFR2 do not have a unique CPU ID.
Use the RC oscillator callibration byte as an impromptu CPU ID and rely
on bootlader constants present on all ATmega families for the remaining
bytes.
This way we can provide a faux CPU ID on all ATmega MCUs and typical hobbyists
with no access to JTAG adapters or high voltage programmer capable of writing
the user signature have a good chance that the CPU IDs of their device do not collide.
Memory management function like `malloc`, `calloc`, `realloc` and `free` must not be preempted when they operate on allocator structures. To avoid such a preemption, wrappers around these functions are used which simply disable all interrupts for the time of their execution.
Functions marked with __atribute__((naked)) may only use basic inline assembly
and must not use any c code. The functions __enter_thread_mode() and
cpu_switch_context_exit() are using C code, so they must not be marked as
naked.
To prevent reordering of accesses to the interrupt control register when link
time optimization (LTO) is enabled, memory barriers are needed. Without LTO
calls to the external functions irq_disable(), irq_restore(), irq_enable() and
irq_is_in() have the same affect as compiler barriers, as the compiler is unable
to prove that reordering of memory accesses is safe (from a single-threaded
point of view). With LTO the compiler can easily prove that reordering is safe
from a single-threaded point of view: Thus, the compiler may move memory
accesses wrapped in irq_disable(), irq_restore() across those calls.
The memory barriers will have no effect on non-LTO builds.
Citing the doc of irq_enable():
@return Previous value of status register. [...]
On atmega however the new value of the status register is returned, not the one
prior to enabling interrupts.
Moving atmega_stdio_init() to cpu_init() just before periph_init() guarantees
that stdio is available to allow DEBUG() in periph_init(). This also helps to
unify the boot up process of ATmega boards and de-duplicates the stdio init from
board_init().