ATmegaxxxx - refine RAMPZ configuration

This commit is contained in:
Phillip Stevens 2020-04-11 14:20:45 +10:00
parent 5052273cd7
commit fa8cde691f
2 changed files with 20 additions and 16 deletions

View file

@ -216,14 +216,14 @@ void wdt_interrupt_reset_enable (const uint8_t value)
* *
* r0 is set to __tmp_reg__ as the compiler expects it to be thus. * r0 is set to __tmp_reg__ as the compiler expects it to be thus.
* *
* #if defined(__AVR_3_BYTE_PC__)
* #define __EIND__ 0x3C
* #endif
*
* #if defined(__AVR_HAVE_RAMPZ__) * #if defined(__AVR_HAVE_RAMPZ__)
* #define __RAMPZ__ 0x3B * #define __RAMPZ__ 0x3B
* #endif * #endif
* *
* #if defined(__AVR_3_BYTE_PC__)
* #define __EIND__ 0x3C
* #endif
*
* The interrupts will have been disabled during the call to portSAVE_CONTEXT() * The interrupts will have been disabled during the call to portSAVE_CONTEXT()
* so we need not worry about reading/writing to the stack pointer. * so we need not worry about reading/writing to the stack pointer.
*/ */
@ -277,14 +277,14 @@ void wdt_interrupt_reset_enable (const uint8_t value)
"in __tmp_reg__, __SP_H__ \n\t" \ "in __tmp_reg__, __SP_H__ \n\t" \
"st x+, __tmp_reg__ \n\t" \ "st x+, __tmp_reg__ \n\t" \
); );
#elif defined(__AVR_3_BYTE_PC__) #elif defined(__AVR_HAVE_RAMPZ__)
/* 3-Byte PC Save */ /* 2-Byte PC Save with RAMPZ */
#define portSAVE_CONTEXT() \ #define portSAVE_CONTEXT() \
__asm__ __volatile__ ( "push __tmp_reg__ \n\t" \ __asm__ __volatile__ ( "push __tmp_reg__ \n\t" \
"in __tmp_reg__, __SREG__ \n\t" \ "in __tmp_reg__, __SREG__ \n\t" \
"cli \n\t" \ "cli \n\t" \
"push __tmp_reg__ \n\t" \ "push __tmp_reg__ \n\t" \
"in __tmp_reg__, 0x3C \n\t" \ "in __tmp_reg__, 0x3B \n\t" \
"push __tmp_reg__ \n\t" \ "push __tmp_reg__ \n\t" \
"push __zero_reg__ \n\t" \ "push __zero_reg__ \n\t" \
"clr __zero_reg__ \n\t" \ "clr __zero_reg__ \n\t" \
@ -425,8 +425,8 @@ void wdt_interrupt_reset_enable (const uint8_t value)
"out __SREG__, __tmp_reg__ \n\t" \ "out __SREG__, __tmp_reg__ \n\t" \
"pop __tmp_reg__ \n\t" \ "pop __tmp_reg__ \n\t" \
); );
#elif defined(__AVR_3_BYTE_PC__) #elif defined(__AVR_HAVE_RAMPZ__)
/* 3-Byte PC Restore with RAMPZ */ /* 2-Byte PC Restore with RAMPZ */
#define portRESTORE_CONTEXT() \ #define portRESTORE_CONTEXT() \
__asm__ __volatile__ ( "lds r26, pxCurrentTCB \n\t" \ __asm__ __volatile__ ( "lds r26, pxCurrentTCB \n\t" \
"lds r27, pxCurrentTCB + 1 \n\t" \ "lds r27, pxCurrentTCB + 1 \n\t" \
@ -466,7 +466,7 @@ void wdt_interrupt_reset_enable (const uint8_t value)
"pop r2 \n\t" \ "pop r2 \n\t" \
"pop __zero_reg__ \n\t" \ "pop __zero_reg__ \n\t" \
"pop __tmp_reg__ \n\t" \ "pop __tmp_reg__ \n\t" \
"out 0x3C, __tmp_reg__ \n\t" \ "out 0x3B, __tmp_reg__ \n\t" \
"pop __tmp_reg__ \n\t" \ "pop __tmp_reg__ \n\t" \
"out __SREG__, __tmp_reg__ \n\t" \ "out __SREG__, __tmp_reg__ \n\t" \
"pop __tmp_reg__ \n\t" \ "pop __tmp_reg__ \n\t" \
@ -591,7 +591,7 @@ uint16_t usAddress;
#endif #endif
#if defined(__AVR_HAVE_RAMPZ__) #if defined(__AVR_HAVE_RAMPZ__)
/* If we have an ATmega2560, we are also saving the RAMPZ register. /* We are saving the RAMPZ register.
* We should default to 0. * We should default to 0.
*/ */
*pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */ *pxTopOfStack = ( StackType_t ) 0x00; /* RAMPZ */
@ -814,8 +814,8 @@ uint8_t ucLowByte;
* *
*/ */
ISR(portSCHEDULER_ISR, ISR_NAKED) __attribute__ ((hot, flatten)); ISR(portSCHEDULER_ISR, ISR_NAKED) __attribute__ ((hot, flatten));
/* ISR(portSCHEDULER_ISR, ISR_NAKED ISR_NOBLOCK) __attribute__ ((hot, flatten)); */ /* ISR(portSCHEDULER_ISR, ISR_NAKED ISR_NOBLOCK) __attribute__ ((hot, flatten));
*/
ISR(portSCHEDULER_ISR) ISR(portSCHEDULER_ISR)
{ {
vPortYieldFromTick(); vPortYieldFromTick();
@ -831,8 +831,8 @@ uint8_t ucLowByte;
* use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler. * use ISR_NOBLOCK where there is an important timer running, that should preempt the scheduler.
*/ */
ISR(portSCHEDULER_ISR) __attribute__ ((hot, flatten)); ISR(portSCHEDULER_ISR) __attribute__ ((hot, flatten));
/* ISR(portSCHEDULER_ISR, ISR_NOBLOCK) __attribute__ ((hot, flatten)); */ /* ISR(portSCHEDULER_ISR, ISR_NOBLOCK) __attribute__ ((hot, flatten));
*/
ISR(portSCHEDULER_ISR) ISR(portSCHEDULER_ISR)
{ {
xTaskIncrementTick(); xTaskIncrementTick();

View file

@ -12,7 +12,7 @@ This initial commit contains the information required to build with System Tick
Further 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. Further 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.
The port also provides support for the 3 byte program counter devices __ATmega2560__ and __ATmega2561__. Specific to these two devices the `RAMPZ` and `EIND` registers 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. The 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.
To build generic Microchip (AVR) ATmega support the similarities across the family must be considered, and differences respected. Some comments on the strategy follow. To build generic Microchip (AVR) ATmega support the similarities across the family must be considered, and differences respected. Some comments on the strategy follow.
@ -37,6 +37,8 @@ The ATtiny, ATmega, ATxmega families can optionally support both 3 byte PC and 3
- providing `portSAVE_CONTEXT()` and `portRESTORE_CONTEXT` saving both the __RAMPZ__ and __EIND__ registers. - providing `portSAVE_CONTEXT()` and `portRESTORE_CONTEXT` saving both the __RAMPZ__ and __EIND__ registers.
- 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. - 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.
For devices which can support __XRAM__ and have the __RAMPZ__ register, this register is also preserved during the context switch.
<h3>Interrupt Nesting</h3> <h3>Interrupt Nesting</h3>
The ATmega family does not support interrupt nesting, having only one interrupt priority. This means that when the Scheduler is running, interrupts are normally disabled. The ATmega family does not support interrupt nesting, having only one interrupt priority. This means that when the Scheduler is running, interrupts are normally disabled.
@ -61,6 +63,8 @@ if( __malloc_heap_end == 0 )
``` ```
Unfortunately in the repository there is nowhere sensible to include this statement as it should be included early in the `main()` function. Unfortunately in the repository there is nowhere sensible to include this statement as it should be included early in the `main()` function.
For devices which can support __XRAM__ the user will need to tune the location of stack and heap according to their own requirements.
<h3>Supported Devices</h3> <h3>Supported Devices</h3>
ATmega devices with __ENHANCED WDT__ Interrupt capability - will use WDT. ATmega devices with __ENHANCED WDT__ Interrupt capability - will use WDT.