Hello alltogether!
I knew that this is not a FreeRTOS forum, but i think there are many people here which are very familiar with freeRTOS on ARM microcontrollers.
What is the problem?
I used the provided port files for the SAM7 and copied it to my project at eclipse (using yagarto). Further I took the startup code which is provided at Jim Lynch’s great tutorial.
But I have to tell the Controller with the startup code where to jump if there occurs a software Interrupt? Is this correct?
I modified the Startup code as follows:
/* ****************************************************************************************************** */
/* crt.s */
/* */
/* Assembly Language Startup Code for Atmel AT91SAM7S256 */
/* */
/* */
/* */
/* */
/* Author: James P Lynch */
/* ****************************************************************************************************** */
/* Stack Sizes */
.set UND_STACK_SIZE, 0x00000010 /* stack for "undefined instruction" interrupts is 16 bytes */
.set ABT_STACK_SIZE, 0x00000010 /* stack for "abort" interrupts is 16 bytes */
.set FIQ_STACK_SIZE, 0x00000080 /* stack for "FIQ" interrupts is 128 bytes */
.set IRQ_STACK_SIZE, 0X00000080 /* stack for "IRQ" normal interrupts is 128 bytes */
.set SVC_STACK_SIZE, 0x00000010 /* stack for "SVC" supervisor mode is 16 bytes */
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */
.set MODE_USR, 0x10 /* Normal User Mode */
.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */
.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */
.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */
.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */
.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */
.set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */
.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */
.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */
/* Interrupt controller offsets */
.set AT91C_BASE_AIC, 0xFFFFF000 /* (AIC) Base Address */
.set AIC_IVR, 256 /* IRQ Vector Register */
.set AIC_EOICR, 304 /* End of Interrupt Command Register */
/* identify all GLOBAL symbols */
.global _vec_reset
.global _vec_undef
.global _vec_swi
.global _vec_pabt
.global _vec_dabt
.global _vec_rsv
.global _vec_irq
.global _vec_fiq
.global AT91F_Irq_Handler
.global AT91F_Default_FIQ_handler
.global AT91F_Default_IRQ_handler
.global AT91F_Spurious_handler
/* GNU assembler controls */
.text /* all assembler code that follows will go into .text section */
.arm /* compile for 32-bit ARM instruction set */
.align /* align section on 32-bit boundary */
/* ============================================================ */
/* VECTOR TABLE */
/* */
/* Must be located in FLASH at address 0x00000000 */
/* */
/* Easy to do if this file crt.s is first in the list */
/* for the linker step in the makefile, e.g. */
/* */
/* $(LD) $(LFLAGS) -o main.out crt.o main.o */
/* */
/* ============================================================ */
/* FreeRTOS SWI Interrupt - needed by PORTYIELD */
_vec_reset: b _init_reset /* RESET vector - must be at 0x00000000 */
_vec_undef: b _vec_undef /* Undefined Instruction vector */
_vec_swi: b _yield_handler /* Software Interrupt vector */
_vec_pabt: b _vec_pabt /* Prefetch abort vector */
_vec_dabt: b _vec_dabt /* Data abort vector */
_vec_rsv: b _vec_rsv /* Reserved vector */
_vec_irq: b _vec_irq /* Interrupt Request (IRQ) vector */
_vec_fiq: b _vec_fiq /* Fast interrupt request (FIQ) vector */
_yield_handler: b vPortYieldProcessor
/* Reset Handler */
_init_reset:
/* Setup a stack for each mode with interrupts initially disabled. */
ldr r0, =_stack_end /* r0 = top-of-stack */
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* switch to Undefined Instruction Mode */
mov sp, r0 /* set stack pointer for UND mode */
sub r0, r0, #UND_STACK_SIZE /* adjust r0 past UND stack */
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* switch to Abort Mode */
mov sp, r0 /* set stack pointer for ABT mode */
sub r0, r0, #ABT_STACK_SIZE /* adjust r0 past ABT stack */
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* switch to FIQ Mode */
mov sp, r0 /* set stack pointer for FIQ mode */
sub r0, r0, #FIQ_STACK_SIZE /* adjust r0 past FIQ stack */
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* switch to IRQ Mode */
mov sp, r0 /* set stack pointer for IRQ mode */
sub r0, r0, #IRQ_STACK_SIZE /* adjust r0 past IRQ stack */
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* switch to Supervisor Mode */
mov sp, r0 /* set stack pointer for SVC mode */
sub r0, r0, #SVC_STACK_SIZE /* adjust r0 past SVC stack */
msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* switch to System Mode */
mov sp, r0 /* set stack pointer for SYS mode */
/* we now start execution in SYSTEM mode */
/* This is exactly like USER mode (same stack) */
/* but SYSTEM mode has more privileges */
/* copy initialized variables .data section (Copy from ROM to RAM) */
ldr R1, =_etext
ldr R2, =_data
ldr R3, =_edata
1: cmp R2, R3
ldrlo R0, [R1], #4
strlo R0, [R2], #4
blo 1b
/* Clear uninitialized variables .bss section (Zero init) */
mov R0, #0
ldr R1, =_bss_start
ldr R2, =_bss_end
2: cmp R1, R2
strlo R0, [R1], #4
blo 2b
/* Enter the C code */
b main
/* ========================================================== */
/* - Function : AT91F_Irq_Handler */
/* - Treatments : IRQ Controller Interrupt Handler. */
/* - Called Functions : AIC_IVR[interrupt] */
/* ---------------------------------------------------------- */
AT91F_Irq_Handler:
/* Adjust and save LR_irq in IRQ stack */
sub lr, lr, #4
stmfd sp!, {lr}
/* Save and r0 in IRQ stack */
stmfd sp!, {r0}
/* Write in the IVR to support Protect Mode */
/* No effect in Normal Mode */
/* De-assert the NIRQ and clear the source in Protect Mode */
ldr r14, =AT91C_BASE_AIC
ldr r0 , [r14, #AIC_IVR]
str r14, [r14, #AIC_IVR]
/* Enable Interrupt and Switch in Supervisor Mode */
msr CPSR_c, #MODE_SVC
/* Save scratch/used registers and LR in User Stack */
stmfd sp!, { r1-r3, r12, r14}
/* =============================================== */
/* Branch to the routine pointed by the AIC_IVR */
/* =============================================== */
/* Branch to the routine pointed by the AIC_IVR */
mov r14, pc
bx r0
/* =============================================== */
/* Manage Exception Exit */
/* =============================================== */
/* Restore scratch/used registers and LR from User Stack */
ldmia sp!, { r1-r3, r12, r14}
/* Disable Interrupt and switch back in IRQ mode */
msr CPSR_c, #MODE_IRQ|I_BIT
/* Mark the End of Interrupt on the AIC */
ldr r14, =AT91C_BASE_AIC
str r14, [r14, #AIC_EOICR]
/* Restore SPSR_irq and r0 from IRQ stack */
ldmia sp!, {r0}
/* Restore adjusted LR_irq from IRQ stack directly in the PC */
ldmia sp!, {pc}^
AT91F_Default_FIQ_handler: b AT91F_Default_FIQ_handler
AT91F_Default_IRQ_handler: b AT91F_Default_IRQ_handler
AT91F_Spurious_handler: b AT91F_Spurious_handler
.end
In fact, i only inserted the vPortYieldProcessor function to the SWI Interrupt source.
And this is my application code which creates one task:
//***************************************************************************
// FREERTOS - APPLICATION
//***************************************************************************
#include "./include/AT91SAM7X256.h"
#include "./include/board_ex256.h"
#include "./include/registers.h"
#include "./include/lcd.h"
#include "./include/debug.h"
/* FreeRTOS includes */
#include "./freeRTOS/include/FreeRTOS.h"
#include "./freeRTOS/include/task.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern void LowLevelInit(void);
void init(void);
//void IRQ_Routine (void) __attribute__ ((interrupt("IRQ")));
void FIQ_Routine (void) __attribute__ ((interrupt("FIQ")));
//void SWI_Routine (void) __attribute__ ((interrupt("SWI")));
void UNDEF_Routine (void) __attribute__ ((interrupt("UNDEF")));
/* Task functions */
void OS_Setup(void);
void TaskBlink(void *taskData);
/* Set the TaskStack Size to the default minimal value */
#define TaskStackSize configMINIMAL_STACK_SIZE
void OS_Setup(void)
{
unsigned int taskData = 0x0;
xTaskHandle taskHandle;
/* Lets create the Application TASKS */
xTaskCreate(TaskBlink, "TaskBlink", TaskStackSize, (void *) &taskData, tskIDLE_PRIORITY+1, &taskHandle);
printf("Task Created \n\r");
vTaskStartScheduler();
}
void TaskBlink(void *taskData)
{
char debugMessage[100];
taskData = taskData;
printf("We are in Task Blink now \n\r");
while(1==1){
Backlight(BKLGHT_LCD_ON);
printf("FREE_RTOS: Backlight ON \n\r");
vTaskDelay(1000);
Backlight(BKLGHT_LCD_OFF);
printf("FREE_RTOS: Backlight OFF \n\r");
vTaskDelay(1000);
}
}
int main(int argc, char **argv) {
init();
initDbgUnit();
printf("Trying to start FREE_RTOS \n\r");
OS_Setup();
while(1==1){
/* Hopefully the OS never returns here */
;
}
}
void init(void) {
//*************** lowlevel init (watchdog, PLL clock, default interrupts, etc.)
LowLevelInit();
//*************** inint defined state
//set all Ports to PIO controlled, not on-chip peripheral
pPIOA->PIO_PER = 0xffffffff;
pPIOB->PIO_PER = 0xffffffff;
//we coould also have used
//pSYS->PIOA_PER = 0xffffffff;
//pSYS->PIOB_PER = 0xffffffff;
//enable all pull ups
pSYS->PIOA_PPUER = 0xffffffff;
pSYS->PIOB_PPUER = 0xffffffff;
//select multiplex function A (should be default). only needed if
//on-chip peripheral was selected
pSYS->PIOA_ASR = 0xffffffff;
pSYS->PIOB_ASR = 0xffffffff;
//we use PIO controlled i/o lines (see above) and set them to input
pSYS->PIOA_ODR = 0xffffffff;
pSYS->PIOB_ODR = 0xffffffff;
//****************** init lcd
InitLCD();
LCDSettings();
//for buttons interrupt do not forget to enable PIO Clock
}//init
/* Stubs for various interrupts (may be replaced later) */
/* ---------------------------------------------------- */
//void IRQ_Routine (void) {
// while (1) ;
//}
void FIQ_Routine (void) {
while (1) ;
}
//void SWI_Routine (void) {
// while (1) ;
//}
void UNDEF_Routine (void) {
while (1) ;
}
My problem is that after i call vTaskStartScheduler(); the program stopps and the task code is not executed.
My first idea was that there is something wrong with the OS tick timer. How could i figure out if the tick timer is not running?
Do i have to add further modifications at my startup code to get freeRTOS running?
Any help is welcome. Thanks a lot in advance.
rain