readme.md
1<h2>ATmegaxxxx</h2>
2
3__Port for generalised Microchip ATmega architecture__
4
5<h3>Description</h3>
6
7This port provides a basis for supporting all modern ATmega devices using either the Enhanced Watchdog Timer, or Timer0 (an 8-bit Timer generally available across the whole range).
8
9This initial commit contains the information required to build with System Tick being generated by either the:
10- Watchdog Timer, or
11- Timer0 - an 8-bit Timer, or
12- TimerN - a 16-bit Timer which will be configured by the user.
13
14Further commits can add support for 16-bit Timers available on many relevant devices. The availability of these 16-bit Timers is somewhat device specific, and these complex and highly configurable Timers are often used to generate phase correct PWM timing (for example) and they would be wasted as a simple System Tick.
15
16The port also provides support for the 3 byte program counter devices __ATmega2560__ and __ATmega2561__. Specific to these two devices the `EIND` register need to be preserved during a context switch. Also, due to a limitation in GCC, the scheduler needs to reside in the lower 128kB of flash for both of these devices. This is achieved by adding the `.lowtext` section attribute to the function prototype.
17
18To build generic Microchip (AVR) ATmega support the similarities across the family must be considered, and differences respected. Some comments on the strategy follow.
19
20<h3>System Tick</h3>
21
22The Microchip (AVR) ATmega family has limited Timer and Pin capabilities, and is designed to be used in physical applications, controlling hardware with PWM and recognising level and edge voltage changes. It does this mainly through the use of 16-bit Timers (for generating phase correct PWM by up/down counting), and Pins attached to Interrupts. The 8-bit Timers are also attached to Pins, and they can be used for more simple timing tasks, requiring only a single counting direction.
23
24The Timers not attached to Pins (and therefore not impacting the application of the device) are some 16-bit Timers (very device dependent, eg Timer3 on 1284p), The RTC Timer, and the Watch Dog Timer.
25
26The Watch Dog Timer is configured identically across most of the ATmega devices. It comes in two variants. 1. Old style (eg ATmega32) which does not have an Interrupt capability, and hence on these old devices cannot be used as the System Tick. and 2. New style enhanced WDT, which can generate an Interrupt, and is available on every relevant device.
27
28Using the Watch Dog Timer (WDT) to generate the System Tick does not impact its use as a watch dog. It can be configured to generate a System Tick interrupt, and then one period later to Reset the device if the interrupt is not serviced.
29
30Configuration and usage of the WDT is covered in `<avr/wdt.h>` which was revised in avr-libc 2.0.0.
31
32Two additional WDT functions are provided in `port.c`, which extend avr-libc functions to enable the WDT Interrupt without enabling Reset `wdt_interrupt_enable()`, and to enable both the Interrupt and the Reset `wdt_interrupt_reset_enable()`.
33
34<h3>3 Byte PC Devices</h3>
35
36The ATtiny, ATmega, ATxmega families can optionally support both 3 byte PC and 3 byte RAM addresses. However, focusing on just the ATmega family only two devices have a large Flash requiring them to use 3 byte PC. These are the __ATmega2560__ and __ATmega2561__. This PR provides support for these two devices in two ways.
37
38 - providing `portSAVE_CONTEXT()` and `portRESTORE_CONTEXT` saving both the __RAMPZ__ and __EIND__ registers.
39 - providing a `portTASK_FUNCTION_PROTO()` with the linker attribute `.lowtext` which is used to ensure that the scheduler and relevant functions remain in the lower 128kB of Flash.
40
41For devices which can support __XRAM__ and have the __RAMPZ__ register, this register is also preserved during the context switch.
42
43<h3>Interrupt Nesting</h3>
44
45The ATmega family does not support interrupt nesting, having only one interrupt priority. This means that when the Scheduler is running, interrupts are normally disabled.
46
47When a very time critical process is running, based on microsecond timing generated by one of the Timers, it is important to re-enable interrupts as early as possible in processing a Yield. Fortunately, this is supported through the use of the `NO_BLOCK` decorator when defining the Interrupt Service Routine.
48
49The `NO_BLOCK` decorator will enable the global interrupt early in the handling of an ISR (in this case for the Scheduler), and enable interrupts to be nested. Using this method, I've been able to successfully implement an [Audio Synthesiser](https://feilipu.me/2015/06/02/goldilocks-analogue-synthesizer/) with less than 83 microseconds for each cycle, whilst still running the Scheduler to handle display and input.
50
51Using `NO_BLOCK` is optional, and should only be done if a critical Timer should interrupt the Scheduler.
52
53<h3>Heap Management</h3>
54
55Most users of FreeRTOS will choose to manage their own heap using one of the pre-allocated heap management algorithms, but for those that choose to use `heap_3.c`, the wrappered `malloc()` method, there is an issue that needs to be addressed.
56
57The avr-libc library assumes that the stack will always be above the heap, and does a check for this when responding to a `malloc()` request. This is not the case when Tasks are running, as their stack is located in the early allocated heap address ranges which will be below free heap memory, and so the `malloc()` request will fail even though heap space is available.
58
59To avoid this issue causing `pvPort_Malloc()` to failing, the user needs to issue this tuning statement BEFORE they use the heap, or use the `xTaskCreate()` API.
60
61```c
62if( __malloc_heap_end == 0 )
63 __malloc_heap_end = (char *)(RAMEND - __malloc_margin);
64```
65Unfortunately in the repository there is nowhere sensible to include this statement as it should be included early in the `main()` function.
66
67For devices which can support __XRAM__ the user will need to tune the location of stack and heap according to their own requirements.
68
69<h3>Supported Devices</h3>
70
71ATmega devices with __ENHANCED WDT__ Interrupt capability - will use WDT.
72
73 - ATmega8U2/16U2/32U2 -> 2kB RAM
74 - ATmega16U4/32U4 - Arduino Leonardo -> 2.5kB RAM
75 - ATmega48PB/88PB/168PB/328PB - Arduino Uno -> 2kB RAM
76 - ATmega164PA/324PA/644PA/1284P - Goldilocks -> __16kB RAM__
77 - ATmega324PB -> 2kB RAM
78 - ATmega640/1280/2560/1281/2561 - Arduino Mega -> __8kB RAM + XRAM__
79
80ATmega devices without enhanced __WDT__ Interrupt capability - will use a 8-bit or 16-bit Timer.
81
82 - ATmega8A/16A/32A/64A/128A -> 4kB RAM
83 - ATmega165A/165PA/325A/325PA/3250A/3250PA/645A/645P/6450A/6450P -> 4kB RAM
84 - ATmega169A/169PA/329A/329PA/3290A/3290PA/649A/649P/6490A/6490P -> 4kB RAM
85 - ATmega808/809/1608/1609/3208/3209/4808/4809 - megaAVR 0-Series -> 6kB RAM
86
87