From: richardbarry Date: Mon, 20 Sep 2010 11:08:39 +0000 (+0000) Subject: Temporarily revert the AVR32 port back to the V6.0.5 files. Work will continue on... X-Git-Tag: V6.1.0~28 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=ea33d501186e86e38c5236a435bd50e60cf35124;p=freertos Temporarily revert the AVR32 port back to the V6.0.5 files. Work will continue on the reverted files following the next release. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@1107 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- diff --git a/Source/portable/GCC/AVR32_UC3/exception.S b/Source/portable/GCC/AVR32_UC3/exception.S new file mode 100644 index 000000000..9a2833f2e --- /dev/null +++ b/Source/portable/GCC/AVR32_UC3/exception.S @@ -0,0 +1,297 @@ +/*This file is prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief Exception and interrupt vectors. + * + * This file maps all events supported by an AVR32UC. + * + * - Compiler: GNU GCC for AVR32 + * - Supported devices: All AVR32UC devices with an INTC module can be used. + * - AppNote: + * + * \author Atmel Corporation: http://www.atmel.com \n + * Support and FAQ: http://support.atmel.no/ + * + ******************************************************************************/ + +/* Copyright (c) 2007, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include +#include "intc.h" + + +//! @{ +//! \verbatim + + + .section .exception, "ax", @progbits + + +// Start of Exception Vector Table. + + // EVBA must be aligned with a power of two strictly greater than the EVBA- + // relative offset of the last vector. + .balign 0x200 + + // Export symbol. + .global _evba + .type _evba, @function +_evba: + + .org 0x000 + // Unrecoverable Exception. +_handle_Unrecoverable_Exception: + rjmp $ + + .org 0x004 + // TLB Multiple Hit: UNUSED IN AVR32UC. +_handle_TLB_Multiple_Hit: + rjmp $ + + .org 0x008 + // Bus Error Data Fetch. +_handle_Bus_Error_Data_Fetch: + rjmp $ + + .org 0x00C + // Bus Error Instruction Fetch. +_handle_Bus_Error_Instruction_Fetch: + rjmp $ + + .org 0x010 + // NMI. +_handle_NMI: + rjmp $ + + .org 0x014 + // Instruction Address. +_handle_Instruction_Address: + rjmp $ + + .org 0x018 + // ITLB Protection. +_handle_ITLB_Protection: + rjmp $ + + .org 0x01C + // Breakpoint. +_handle_Breakpoint: + rjmp $ + + .org 0x020 + // Illegal Opcode. +_handle_Illegal_Opcode: + rjmp $ + + .org 0x024 + // Unimplemented Instruction. +_handle_Unimplemented_Instruction: + rjmp $ + + .org 0x028 + // Privilege Violation. +_handle_Privilege_Violation: + rjmp $ + + .org 0x02C + // Floating-Point: UNUSED IN AVR32UC. +_handle_Floating_Point: + rjmp $ + + .org 0x030 + // Coprocessor Absent: UNUSED IN AVR32UC. +_handle_Coprocessor_Absent: + rjmp $ + + .org 0x034 + // Data Address (Read). +_handle_Data_Address_Read: + rjmp $ + + .org 0x038 + // Data Address (Write). +_handle_Data_Address_Write: + rjmp $ + + .org 0x03C + // DTLB Protection (Read). +_handle_DTLB_Protection_Read: + rjmp $ + + .org 0x040 + // DTLB Protection (Write). +_handle_DTLB_Protection_Write: + rjmp $ + + .org 0x044 + // DTLB Modified: UNUSED IN AVR32UC. +_handle_DTLB_Modified: + rjmp $ + + .org 0x050 + // ITLB Miss: UNUSED IN AVR32UC. +_handle_ITLB_Miss: + rjmp $ + + .org 0x060 + // DTLB Miss (Read): UNUSED IN AVR32UC. +_handle_DTLB_Miss_Read: + rjmp $ + + .org 0x070 + // DTLB Miss (Write): UNUSED IN AVR32UC. +_handle_DTLB_Miss_Write: + rjmp $ + + .org 0x100 + // Supervisor Call. +_handle_Supervisor_Call: + lda.w pc, SCALLYield + + +// Interrupt support. +// The interrupt controller must provide the offset address relative to EVBA. +// Important note: +// All interrupts call a C function named _get_interrupt_handler. +// This function will read group and interrupt line number to then return in +// R12 a pointer to a user-provided interrupt handler. + + .balign 4 + +_int0: + // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the + // CPU upon interrupt entry. +#if 1 // B1832: interrupt stack changed to exception stack if exception is detected. + mfsr r12, AVR32_SR + bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE + cp.w r12, 0b110 + brlo _int0_normal + lddsp r12, sp[0 * 4] + stdsp sp[6 * 4], r12 + lddsp r12, sp[1 * 4] + stdsp sp[7 * 4], r12 + lddsp r12, sp[3 * 4] + sub sp, -6 * 4 + rete +_int0_normal: +#endif + mov r12, 0 // Pass the int_lev parameter to the _get_interrupt_handler function. + call _get_interrupt_handler + cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function. + movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler. + rete // If this was a spurious interrupt (R12 == NULL), return from event handler. + +_int1: + // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the + // CPU upon interrupt entry. +#if 1 // B1832: interrupt stack changed to exception stack if exception is detected. + mfsr r12, AVR32_SR + bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE + cp.w r12, 0b110 + brlo _int1_normal + lddsp r12, sp[0 * 4] + stdsp sp[6 * 4], r12 + lddsp r12, sp[1 * 4] + stdsp sp[7 * 4], r12 + lddsp r12, sp[3 * 4] + sub sp, -6 * 4 + rete +_int1_normal: +#endif + mov r12, 1 // Pass the int_lev parameter to the _get_interrupt_handler function. + call _get_interrupt_handler + cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function. + movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler. + rete // If this was a spurious interrupt (R12 == NULL), return from event handler. + +_int2: + // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the + // CPU upon interrupt entry. +#if 1 // B1832: interrupt stack changed to exception stack if exception is detected. + mfsr r12, AVR32_SR + bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE + cp.w r12, 0b110 + brlo _int2_normal + lddsp r12, sp[0 * 4] + stdsp sp[6 * 4], r12 + lddsp r12, sp[1 * 4] + stdsp sp[7 * 4], r12 + lddsp r12, sp[3 * 4] + sub sp, -6 * 4 + rete +_int2_normal: +#endif + mov r12, 2 // Pass the int_lev parameter to the _get_interrupt_handler function. + call _get_interrupt_handler + cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function. + movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler. + rete // If this was a spurious interrupt (R12 == NULL), return from event handler. + +_int3: + // R8-R12, LR, PC and SR are automatically pushed onto the system stack by the + // CPU upon interrupt entry. +#if 1 // B1832: interrupt stack changed to exception stack if exception is detected. + mfsr r12, AVR32_SR + bfextu r12, r12, AVR32_SR_M0_OFFSET, AVR32_SR_M0_SIZE + AVR32_SR_M1_SIZE + AVR32_SR_M2_SIZE + cp.w r12, 0b110 + brlo _int3_normal + lddsp r12, sp[0 * 4] + stdsp sp[6 * 4], r12 + lddsp r12, sp[1 * 4] + stdsp sp[7 * 4], r12 + lddsp r12, sp[3 * 4] + sub sp, -6 * 4 + rete +_int3_normal: +#endif + mov r12, 3 // Pass the int_lev parameter to the _get_interrupt_handler function. + call _get_interrupt_handler + cp.w r12, 0 // Get the pointer to the interrupt handler returned by the function. + movne pc, r12 // If this was not a spurious interrupt (R12 != NULL), jump to the handler. + rete // If this was a spurious interrupt (R12 == NULL), return from event handler. + + +// Constant data area. + + .balign 4 + + // Values to store in the interrupt priority registers for the various interrupt priority levels. + // The interrupt priority registers contain the interrupt priority level and + // the EVBA-relative interrupt vector offset. + .global ipr_val + .type ipr_val, @object +ipr_val: + .word (INT0 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int0 - _evba),\ + (INT1 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int1 - _evba),\ + (INT2 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int2 - _evba),\ + (INT3 << AVR32_INTC_IPR0_INTLEV_OFFSET) | (_int3 - _evba) + + +//! \endverbatim +//! @} diff --git a/Source/portable/GCC/AVR32_UC3/port.c b/Source/portable/GCC/AVR32_UC3/port.c index ecb39aea6..9f49e4b15 100644 --- a/Source/portable/GCC/AVR32_UC3/port.c +++ b/Source/portable/GCC/AVR32_UC3/port.c @@ -1,3 +1,17 @@ +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief FreeRTOS port source for AVR32 UC3. + * + * - Compiler: GNU GCC for AVR32 + * - Supported devices: All AVR32 devices can be used. + * - AppNote: + * + * \author Atmel Corporation: http://www.atmel.com \n + * Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + /* FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd. @@ -51,8 +65,10 @@ licensing and training services. */ -/* Standard includes. */ +/* Standard includes. */ +#include +#include #include /* Scheduler includes. */ @@ -62,8 +78,10 @@ /* AVR32 UC3 includes. */ #include #include "gpio.h" -#include -#include +#if( configTICK_USE_TC==1 ) + #include "tc.h" +#endif + /* Constants required to setup the task context. */ #define portINITIAL_SR ( ( portSTACK_TYPE ) 0x00400000 ) /* AVR32 : [M2:M0]=001 I1M=0 I0M=0, GM=0 */ @@ -73,8 +91,11 @@ #define portNO_CRITICAL_NESTING ( ( unsigned long ) 0 ) volatile unsigned long ulCriticalNesting = 9999UL; -/* Clear the COUNT&COMPARE match Interrupt Flag. */ -static void prvClearCcInt( void ); +#if( configTICK_USE_TC==0 ) + static void prvScheduleNextTick( void ); +#else + static void prvClearTcInt( void ); +#endif /* Setup the timer to generate the tick interrupts. */ static void prvSetupTimerInterrupt( void ); @@ -119,8 +140,8 @@ void _init_startup(void) #endif - /* Give the used PBA clock frequency to Newlib, so it can work properly. */ - set_cpu_hz( configPBA_CLOCK_HZ ); + /* Give the used CPU clock frequency to Newlib, so it can work properly. */ + set_cpu_hz( configCPU_CLOCK_HZ ); /* Code section present if and only if the debug trace is activated. */ #if configDBG @@ -192,16 +213,22 @@ void *pvReturn; /*-----------------------------------------------------------*/ /* The cooperative scheduler requires a normal IRQ service routine to -simply increment the system tick. -The preemptive scheduler is defined as "naked" as the full context is saved +simply increment the system tick. */ +/* The preemptive scheduler is defined as "naked" as the full context is saved on entry as part of the context switch. */ __attribute__((__naked__)) static void vTick( void ) { /* Save the context of the interrupted task. */ portSAVE_CONTEXT_OS_INT(); - /* Clear the interrupt flag. */ - prvClearCcInt(); + #if( configTICK_USE_TC==1 ) + /* Clear the interrupt flag. */ + prvClearTcInt(); + #else + /* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ) + clock cycles from now. */ + prvScheduleNextTick(); + #endif /* Because FreeRTOS is not supposed to run with nested interrupts, put all OS calls in a critical section . */ @@ -214,13 +241,6 @@ __attribute__((__naked__)) static void vTick( void ) } /*-----------------------------------------------------------*/ -/* Note that the scall handler in the framework 'exception.x' must - * jump to this handler. - * In file: 'AVR32_UC3/Drivers/INTC/exception.x' replace the line after - * '_handle_Supervisor_Call:' which might be 'rjmp $' - * with the instruction: - * 'lda.w pc, SCALLYield' - */ __attribute__((__naked__)) void SCALLYield( void ) { /* Save the context of the interrupted task. */ @@ -288,7 +308,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE *pxTopOfStack-- = ( portSTACK_TYPE ) 0x04040404; /* R4 */ *pxTopOfStack-- = ( portSTACK_TYPE ) 0x05050505; /* R5 */ *pxTopOfStack-- = ( portSTACK_TYPE ) 0x06060606; /* R6 */ - *pxTopOfStack-- = ( portSTACK_TYPE ) 0x00000000; /* R7 aka Frame Pointer */ + *pxTopOfStack-- = ( portSTACK_TYPE ) 0x07070707; /* R7 */ *pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_NESTING; /* ulCriticalNesting */ return pxTopOfStack; @@ -318,28 +338,124 @@ void vPortEndScheduler( void ) /* Schedule the COUNT&COMPARE match interrupt in (configCPU_CLOCK_HZ/configTICK_RATE_HZ) clock cycles from now. */ -static void prvScheduleFirstTick(void) -{ - Set_system_register(AVR32_COMPARE, configCPU_CLOCK_HZ/configTICK_RATE_HZ); - Set_system_register(AVR32_COUNT, 0); -} -/*-----------------------------------------------------------*/ +#if( configTICK_USE_TC==0 ) + static void prvScheduleFirstTick(void) + { + unsigned long lCycles; -__attribute__((__noinline__)) static void prvClearCcInt(void) -{ - Set_system_register(AVR32_COMPARE, Get_system_register(AVR32_COMPARE)); -} + lCycles = Get_system_register(AVR32_COUNT); + lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ); + // If lCycles ends up to be 0, make it 1 so that the COMPARE and exception + // generation feature does not get disabled. + if(0 == lCycles) + { + lCycles++; + } + Set_system_register(AVR32_COMPARE, lCycles); + } + + __attribute__((__noinline__)) static void prvScheduleNextTick(void) + { + unsigned long lCycles, lCount; + + lCycles = Get_system_register(AVR32_COMPARE); + lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ); + // If lCycles ends up to be 0, make it 1 so that the COMPARE and exception + // generation feature does not get disabled. + if(0 == lCycles) + { + lCycles++; + } + lCount = Get_system_register(AVR32_COUNT); + if( lCycles < lCount ) + { // We missed a tick, recover for the next. + lCycles += (configCPU_CLOCK_HZ/configTICK_RATE_HZ); + } + Set_system_register(AVR32_COMPARE, lCycles); + } +#else + __attribute__((__noinline__)) static void prvClearTcInt(void) + { + AVR32_TC.channel[configTICK_TC_CHANNEL].sr; + } +#endif /*-----------------------------------------------------------*/ /* Setup the timer to generate the tick interrupts. */ static void prvSetupTimerInterrupt(void) { +#if( configTICK_USE_TC==1 ) + + volatile avr32_tc_t *tc = &AVR32_TC; + + // Options for waveform genration. + tc_waveform_opt_t waveform_opt = + { + .channel = configTICK_TC_CHANNEL, /* Channel selection. */ + + .bswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOB. */ + .beevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOB. */ + .bcpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOB. */ + .bcpb = TC_EVT_EFFECT_NOOP, /* RB compare effect on TIOB. */ + + .aswtrg = TC_EVT_EFFECT_NOOP, /* Software trigger effect on TIOA. */ + .aeevt = TC_EVT_EFFECT_NOOP, /* External event effect on TIOA. */ + .acpc = TC_EVT_EFFECT_NOOP, /* RC compare effect on TIOA: toggle. */ + .acpa = TC_EVT_EFFECT_NOOP, /* RA compare effect on TIOA: toggle (other possibilities are none, set and clear). */ + + .wavsel = TC_WAVEFORM_SEL_UP_MODE_RC_TRIGGER,/* Waveform selection: Up mode without automatic trigger on RC compare. */ + .enetrg = FALSE, /* External event trigger enable. */ + .eevt = 0, /* External event selection. */ + .eevtedg = TC_SEL_NO_EDGE, /* External event edge selection. */ + .cpcdis = FALSE, /* Counter disable when RC compare. */ + .cpcstop = FALSE, /* Counter clock stopped with RC compare. */ + + .burst = FALSE, /* Burst signal selection. */ + .clki = FALSE, /* Clock inversion. */ + .tcclks = TC_CLOCK_SOURCE_TC2 /* Internal source clock 2. */ + }; + + tc_interrupt_t tc_interrupt = + { + .etrgs=0, + .ldrbs=0, + .ldras=0, + .cpcs =1, + .cpbs =0, + .cpas =0, + .lovrs=0, + .covfs=0, + }; + +#endif + /* Disable all interrupt/exception. */ portDISABLE_INTERRUPTS(); /* Register the compare interrupt handler to the interrupt controller and enable the compare interrupt. */ - INTC_register_interrupt(&vTick, AVR32_CORE_COMPARE_IRQ, AVR32_INTC_INT0); - prvScheduleFirstTick(); + + #if( configTICK_USE_TC==1 ) + { + INTC_register_interrupt(&vTick, configTICK_TC_IRQ, INT0); + + /* Initialize the timer/counter. */ + tc_init_waveform(tc, &waveform_opt); + + /* Set the compare triggers. + Remember TC counter is 16-bits, so counting second is not possible! + That's why we configure it to count ms. */ + tc_write_rc( tc, configTICK_TC_CHANNEL, ( configPBA_CLOCK_HZ / 4) / configTICK_RATE_HZ ); + + tc_configure_interrupts( tc, configTICK_TC_CHANNEL, &tc_interrupt ); + + /* Start the timer/counter. */ + tc_start(tc, configTICK_TC_CHANNEL); + } + #else + { + INTC_register_interrupt(&vTick, AVR32_CORE_COMPARE_IRQ, INT0); + prvScheduleFirstTick(); + } + #endif } -/*-----------------------------------------------------------*/ diff --git a/Source/portable/GCC/AVR32_UC3/portmacro.h b/Source/portable/GCC/AVR32_UC3/portmacro.h index 87e640770..e7ecb2daa 100644 --- a/Source/portable/GCC/AVR32_UC3/portmacro.h +++ b/Source/portable/GCC/AVR32_UC3/portmacro.h @@ -1,3 +1,17 @@ +/*This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief FreeRTOS port source for AVR32 UC3. + * + * - Compiler: GNU GCC for AVR32 + * - Supported devices: All AVR32 devices can be used. + * - AppNote: + * + * \author Atmel Corporation: http://www.atmel.com \n + * Support and FAQ: http://support.atmel.no/ + * + *****************************************************************************/ + /* FreeRTOS V6.0.5 - Copyright (C) 2010 Real Time Engineers Ltd. @@ -86,6 +100,8 @@ extern "C" { #define TASK_DELAY_S(x) ( (x)*1000 /portTICK_RATE_MS ) #define TASK_DELAY_MIN(x) ( (x)*60*1000/portTICK_RATE_MS ) +#define configTICK_TC_IRQ ATPASTE2(AVR32_TC_IRQ, configTICK_TC_CHANNEL) + #if( configUSE_16_BIT_TICKS == 1 ) typedef unsigned portSHORT portTickType; #define portMAX_DELAY ( portTickType ) 0xffff @@ -182,7 +198,7 @@ extern void *pvPortRealloc( void *pv, size_t xSize ); "st.w r8[0], r0 \n\t"\ \ /* Restore R0..R7 */ \ - "ldm sp++, r0-r7 \n\t"\ + "ldm sp++, r0-r7 \n\t"\ /* R0-R7 should not be used below this line */ \ /* Skip PC and SR (will do it at the end) */ \ "sub sp, -2*4 \n\t"\