Troubles while setting up FreeRTOS @ SAM7X/Yagarto Toolchain

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

Hello again,

I found out that my Stack sizes are way to small. I changed them but still no success.

Any hint is welcome.

rain

You would be very lucky to compille any program more than a few bytes and expect it to work out of the box. You have to “sneak up” on things - that is, have a strategy for verifying that each step of the process is working as intended.

Are yiou able to compile, load and execute code without using an OS? That is the first step in determining that your tools are in order.

yes my toolchain works fine - i have compiled several programms before starting with freertos.

rain