Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on September 24, 2013

I am portin the FreeRTOS onto ARM926 platform. My processor gets resetting when i am creating the Task. actually this is happening in the below code.

define portENTER_CRITICAL() vPortEnterCritical()
define portEXIT_CRITICAL() vPortExitCritical()
define portDISABLEINTERRUPTS() __disableirq()
define portENABLEINTERRUPTS() __enableirq()

void disableirq (void) { unsigned long old,temp; serialputc('I'); __asm volatile("mrs %0, cpsrn" "orr %1, %0, #0xc0n" "msr cpsr_c, %1" : "=r" (old), "=r" (temp) : : "memory");

    serial_putc('J');

// return (old & 0x80) == 0; }

Please suggest me the correct procedure.

Thanks & Regards, Nagaraju


FreeRTOS porting to ARM926ejs

Posted by davedoors on September 24, 2013

It should be the same code as the ARM7 port.

#ifdef THUMB_INTERWORK

  extern void vPortDisableInterruptsFromThumb( void ) __attribute__ ((naked));
  extern void vPortEnableInterruptsFromThumb( void ) __attribute__ ((naked));

  #define portDISABLE_INTERRUPTS()  vPortDisableInterruptsFromThumb()
  #define portENABLE_INTERRUPTS()    vPortEnableInterruptsFromThumb()
  
#else

  #define portDISABLE_INTERRUPTS()                      \
    __asm volatile (                            \
      "STMDB  SP!, {R0}    \n\t"  /* Push R0.            */  \
      "MRS  R0, CPSR    \n\t"  /* Get CPSR.          */  \
      "ORR  R0, R0, #0xC0  \n\t"  /* Disable IRQ, FIQ.      */  \
      "MSR  CPSR, R0    \n\t"  /* Write back modified value.  */  \
      "LDMIA  SP!, {R0}      " )  /* Pop R0.            */
      
  #define portENABLE_INTERRUPTS()                        \
    __asm volatile (                            \
      "STMDB  SP!, {R0}    \n\t"  /* Push R0.            */  \
      "MRS  R0, CPSR    \n\t"  /* Get CPSR.          */  \
      "BIC  R0, R0, #0xC0  \n\t"  /* Enable IRQ, FIQ.        */  \
      "MSR  CPSR, R0    \n\t"  /* Write back modified value.  */  \
      "LDMIA  SP!, {R0}      " )  /* Pop R0.            */

#endif /* THUMB_INTERWORK */

FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 1, 2013

Hi,

I ported the basic startup code, timer and interrupt is generating at given period of time and serial port is working.

I have created the two tasks and started the scheduler, at this time i observed that only one task is running, both the tasks have the same priority.

If i assign one task priority is high at this time only high priority task is running i am unable to see any console messages from the task2..

I initialized one hardware timer and which is generating interrupt at 5 ms.In my timer interrupt handler i am calling the vTaskIncrementTick().

Please suggest me how do i make my scheduler has to the schedule the created tasks to make sure multitasking is happening.

Thanks,


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 1, 2013

Assuming the interrupt handler is formed correctly, as a naked function or as an assembly file, then it should contain the code:

if( xTaskIncrementTick() != pdFALSE ) { vTaskSwitchContext(); }

xTaskIncrementTick() being the function that might unblock a task, and vTaskSwitchContext() being the function that selects the highest priority task to run.

This is correct for FreeRTOS V7.5.0 onwards, anyway.

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 2, 2013

Thank you, Ricahrd.

Currently my timer handler code consists of the below.

void OSTimeTick( void ) {
/* Increment the tick counter. */ vTaskIncrementTick();

#if configUSE_PREEMPTION == 1
{
    /* The new tick value might unblock a task.  Ensure the highest task that
    is ready to execute is the task that will execute when the tick ISR
    exits. */
    vTaskSwitchContext();
}
#endif

}

configUSE_PREEMPTION flag is enable.I am using the FreeRTOS version 7.5.2

Thanks,


FreeRTOS porting to ARM926ejs

Posted by edwards3 on October 2, 2013

vTaskSwitchContext() does not exist in FreeRTOS V7.5.2? It is called xTaskSwitchContext().

Is your OSTimeTick() function called after the task context is stored? It should be something like this:

void OSTimeTick( void ) __attribute__((naked));
void OSTimeTick( void )
{
    /* Save the context of the current task. */
    portSAVE_CONTEXT();			

    if( xTaskIncrementTick() != pdFALSE )
    {
        vTaskSwitchContext();
    }
		
    portRESTORE_CONTEXT();
}

The yield function should also be naked.

I'm using FreeRTOS\Source\portable\GCC\ARM7_AT91SAM7S\portISR.c as a reference.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 3, 2013

Hi,

My Code looks to be same as you suggested. Only i observed that the prints are coming from my ISR at peroidically.

But my taks have to through some chars on to the console when they run.

Please find my attached console log. in this chars are 'M' 'N' 'O' 'P'are i am printing through the ISR routine of the timer.

Please suggest me which part of code making wrong me.

Thanks

Attachments

teraterm.log (1023264 bytes)

FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 3, 2013

Please find the attached file that explains my portSAVECONTEXT() and portRESTORECONTEXT().

Attachments

port.txt (1966 bytes)

FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 3, 2013

Are you 100% sure the interrupt is actually being entered and executed, and that the tick count is being incremented (the tick count is held in the xTickCount variable that is accessible from inside tasks.c).

Only i observed that the prints are coming from my ISR at peroidically.

Are you printing to a console from an interrupt? If so, then that is highly likely to cause you problems.

Trying to rapidly print from tasks can also cause problems, depending on how characters are actually being output. Anything that uses semihosting on an ARM9 will cause all sorts of issues as it will probably try and use the same interrupts as FreeRTOS.

I would recommend just starting with two tasks, of the form:

volatile unsigned long ul1 = 0, ul2 = 0;

void vTask1( void *pvParameters )
{
    for( ;; )
    {
        ul1++;
    }
}

void vTask2( void *pvParameters )
{
    for( ;; )
    {
        ul2++;
    }
}

Let that run for a while then check both ul1 and ul2 are being incremented at roughly the same rate.

Regards.


FreeRTOS porting to ARM926ejs

Posted by berni8k on October 3, 2013

Another thing to make sure is that you have your config file contains sets configUSE_PREEMPTION to 1 and make sure it does indeed get included in all the code correctly.

I created my port for a ARM9 by sticking the ARM7 context save routines in to a ARM Cortex R4 port of it. Only had a slight snag with interrupt enables.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 3, 2013

I am 100% sure that interrupt is firing and ISR routine is executing. The xTickCount variable is getting incrementing this i have tested like in tasks.c file i am cheking this variable for a value of 1000 at that time i am entering into infinite loop and serial_put('D') which coming here and contineously printing D like below.

xTaskIncrementTick()

++xTickCount

if(xTickCount == 1000) while(1){ serial_putc('D'); }

in case of ARM 9 the interrupt code like below.

void do_irq (void) {

ifdef CONFIG_MCS8140
    if ((__read_irq_status) & (1<<IRQ_TIMER))
    {
            __clear_irq(IRQ_TIMER);

      if(rd_b(TIMERS_INTERRUPT_STATUS_REG)&2)
     {
            bit16_timer_interrupt_occured = 1;

/* serialputc('M'); serialputc('N'); serialputc('O'); serialputc('P'); serial_putc('@');*/ OSTimeTick();

     }

}

/-----------------------------------------------------------/ void OSTimeTick( void ) attribute((naked)); void OSTimeTick( void ) {

//portSAVE_CONTEXT(); /* Increment the tick counter. */ if( xTaskIncrementTick() != pdFALSE );

// #if configUSE_PREEMPTION == 1 { /* The new tick value might unblock a task. Ensure the highest task that is ready to execute is the task that will execute when the tick ISR exits. */

    serial_putc('W');
    serial_putc('W');
    serial_putc('W');
    serial_putc('W');
    serial_putc('W');
    vTaskSwitchContext();
}

// #endif

//portRESTORE_CONTEXT(); }

I don't have flexibility to run the suggested program to watch the values. Instead that when my count value equal to some 100 then i am going to infinite loop but i have not observed that.

Apart from that is there any program to check the my FreeRTOS up and running.

Here i observed that only one task is continuously running.When i change the priority of another task at that time only high priority task is runing.

Please guide me how do i make sure that my both the tasks are running simultaneously.

Thanks,


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 3, 2013

In vTaskSwitchContext() function i am entering in to the else part in this i have not seen the defination for the below

traceTASKSWITCHEDOUT();

and the configGENERATERUNTIME_STATS is not defined not entering in to this condition.

traceTASKSWITCHEDIN(); is also not defined and configUSENEWLIBREENTRANT is defined as 0.

Please suggest me how to overcome the problem.

Regards,


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 4, 2013

Hi, I have run the below code by placing the break points in task 1 and task2.Every time task2 break point and only the varible inside the ul2 is getting updated.

volatile unsigned long ul1 = 0, ul2 = 0;

void vTask1( void *pvParameters ) { for( ;; ) { ul1++; } }

void vTask2( void *pvParameters ) { for( ;; ) { ul2++; } }

Please could you point out me why the scheduler is not scheduling my task1. Which part of the code needs to be modified.

Regards,


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 4, 2013

Every time the break point inside the task2 is hitting and the value inside task2 getting incremented but ihave not observed that the task 1 break point is not hitting and the variable inside the task2 is not getting updated.

Please could you update me on the same, i am using FreeRTOS version 7.5.2.

Regards,


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 4, 2013

serialputc('W'); serialputc('W'); serialputc('W'); serialputc('W'); serial_putc('W'); vTaskSwitchContext();

I think I already mentioned that sending serial characters from the interrupt is really not a good idea - sending 5 from the tick interrupt is positively a bad idea!

Have you removed that code?

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 4, 2013

Hi,

I observed that my code gets hanging in portSAVE_CONTEXT() function.

Regards


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 9, 2013

Hi,

I have configured my interrupt handler like below.

irq: getirqstack bl portSAVECONTEXT bl doirq bl portRESTORE_CONTEXT

my do_irq function is like below.

void do_irq (void) {

    if ((__read_irq_status) & (1<<IRQ_TIMER))
    {
            __clear_irq(IRQ_TIMER);



     if(rd_b(TIMERS_INTERRUPT_STATUS_REG)&2)
     {
            OSTimeTick();

     }

}

void OSTimeTick( void ) attribute((naked)); void OSTimeTick( void ) { /* Increment the tick counter. */ if( xTaskIncrementTick() != pdFALSE );

{
    /* The new tick value might unblock a task.  Ensure the highest task                                                                                                                                                                                                                                                                        that is ready to execute is the task that will execute when the tick ISR
    exits. */

    vTaskSwitchContext();
}

}

I have configured the timer interrupt to generate at every 5ms and i called this in my vTaskStartScheduler() function just before calling the

if( xPortStartScheduler() != pdFALSE ) with the function name

prvSetupTimerInterrupt();

Initially my processor is in SVC mode and interrupts are enabled and IRQ interrupt is firing and entering into the IRQ mode and IRQ interrupts are disabled.We dont get any further interrupts that means no further do_irq gets called.

Then entering into portSAVE_CONTEXT and hanging at the below stmfd instruction.

@ Push all the system mode registers onto the task stack.
    stmfd   LR, {R0-LR}^
    NOP
    SUB     LR, LR, #60

In my main routine i have created the two tasks of both having the same priority and both the tasks are created successfully and i have started the scheduler.

my code looks like below

portBASE_TYPE xPortStartScheduler( void ) {

    /* Start the first task. */
    serial_putc('K');
    vPortStartFirstTask();

    serial_putc('N');
    /* Should not get here! */
    return 0;

}

my vPortStartFirstTask(); calls the bl portRESTORE_CONTEXT.

First time my task2 gets scheduling and only that task running contineously but the task1 never get a chance to schedule and it is not running.

But some times at the end of instruction portRESTORECONTEXT bl which is jumping to the OSTimeTick function but my tasks are not gets scheduled and which is hanging at the portSAVECONTEXT as i mentioned above.

Please could you provide me the tips to overcome my hang issue and to scheduler to schedule my two tasks symultaneously.

Thanks


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 9, 2013

Ok - I'm loosing the thread here. Lets go back to the beginning and go through this step by step.

irq: getirqstack bl portSAVECONTEXT bl doirq bl portRESTORE_CONTEXT

Broadly speaking, there are two ways the interrupt controller can work on ARM9 devices.

1) Single vector interrupt.

In this scheme there is only one entry point into any interrupt. That single entry point performs some stack management, then looks to see what caused the interrupt, then calls the appropriate handler. The handler is just a standard C function that returns back to the single interrupt handler, which then cleans up the stack and returns back to non interrupt code.

From the code quoted above, it looks like that is the scheme you are using. Although I'm not sure what the line "getirqstack" is doing, as the processor should automatically switch to the IRQ stack for you.

2) Auto vectoring

In auto vectoring the interrupt controller is clever enough to know the cause of the interrupt and jumps directly to a handler for that interrupt. In this scheme there are multiple interrupt entry points - one for each interrupt source.

The discussion in this thread so far has assumed scheme 2 was being used - auto vectoring, but the code you have just posted (and quoted in this thread) makes me think you are actually using scheme 1 - single vector interrupt.

Can you confirm which you are using. Then we can move onto the next step.

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 9, 2013

Thank you for your posting.

Yes i am using the scheme1 single vector interrupt, and getirqstack does the STACK pointer point to particular location address.

Regards,


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 9, 2013

Ok - I'm going to ignore the getirqstack call as I'm not sure what it is doing. It is however very important that, whatever it is doing, it does not change the value of any registers before they have been saved as part of the task context (the IRQ stack pointer can be changed, as that is not used by tasks).

The other thing about your interrupt code I note is that you are branching to the save and restore context macros - these should be inline macros, not functions.

One of the STR9 demos in the FreeRTOS download uses the single vector method. Take a look at the file:

FreeRTOSDemoARM9STR91XIAR91x_vect.s

in that file find the IRQHandler assembly function. You will see the first thing it does is call portSAVECONTEXT, but portSAVECONTEXT is a macro - it is inlined - the CPU does not branch to it. The implementation of the macro is part of the FreeRTOS port layer (for IAR in this case) and is defined in:

FreeRTOSSourceportableIARSTR91xISR_Support.h.

IRQHandler likewise ends in the inline portRESTORE_CONTEXT macro.

The code between portSAVECONTEXT and portRESTORECONTEXT is specific to the chip - so ignore that.

Once your vector is set up like this then the individual functions that service peripherals become standard C functions - you don't need the naked attribute or to do any further saving or restoring of context.

While you are in the 91x_vect.s file also take a look at the vector table. vPortYieldProcessor is installed as the SWI handler:

        LDR     PC, Reset_Addr
        LDR     PC, Undefined_Addr
        LDR     PC, SWI_Addr
        LDR     PC, Prefetch_Addr
        LDR     PC, Abort_Addr
        NOP                             ; Reserved vector
        LDR     PC, IRQ_Addr



Reset_Addr      DCD     __iar_program_start
Undefined_Addr  DCD     UndefinedHandler
SWI_Addr        DCD     vPortYieldProcessor ; <<<<<<<<<<<<<<<<
Prefetch_Addr   DCD     PrefetchAbortHandler
Abort_Addr      DCD     DataAbortHandler
                DCD     0               ; Reserved vector
IRQ_Addr        DCD     IRQHandler

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 9, 2013

Thank you for your reply.

By doing the below changes i am able to run the multiple tasks.

I have created the three tasks in my main programme and started the scheduler.

In my each task entry i am enabling my IRQ interrupts and before exiting task disbaling the irq interrupts.

Why i enabled the interrupts:

I observed that once entering into the task interrupts are disabling and i am not getting the IRQ interrupts and contineously only that task is running.

Once i enabled the interrupts i am getting the interrupt and next task getting the cpu time slice and it is running. But these tasks are running in ARM IRQ mode.

my code looks like below.

void OSTimeTick( void )
{

    if( xTaskIncrementTick() != pdFALSE );
        {

            vTaskSwitchContext();
        }
        portRESTORE_CONTEXT();
  }

I have removed my portSAVE_CONTEXT code as i mentioned in my previous message. Please correct me if i am wrong.

I will try now with suggested inputs.

Regards,


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 9, 2013

Are your clearing the timer interrupt anywhere? When a timer generates an interrupt it is normal for the interrupt handler to clear the interrupt in the peripheral. It is often additionally necessary to clear the interrupt in the interrupt controller too. How that is done is chip specific, and not FreeRTOS related, but it sounds like you might be missing that step somewhere.

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 9, 2013

Thank you for your reply,

Yes i am clearing the my timer interrupt in my interrupt handler. Once interrupt comes i am checking that this is timer interrupt, if it is timer interrupt then i am clearing the timer interrupt in my simple interrupt controller.

code looks like below.

void do_irq (void)
{

        if ((__read_irq_status) & (1<<IRQ_TIMER))
        {
            __clear_irq(IRQ_TIMER);

             if(rd_b(TIMERS_INTERRUPT_STATUS_REG)&2)
             {
                   OSTimeTick();
             }
        }
  }

As you have stated that it is chip specific.

Please could you guide me how to do the missing step (as present in FreeRTOS).

Regards,


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 9, 2013

I'm afraid without having the project and hardware in front of me I don't know what the missing step is. OSTimeTick() should now just be a standard C function (not naked).

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 10, 2013

Please could you elaborate me on what is naked ? If OSTimeTick function is not naked how do i make it as naked?

Regards,


FreeRTOS porting to ARM926ejs

Posted by xz8987f on October 10, 2013

for ARM gcc: attribute ((naked)) void vPortTickHandler(void) ... ...

Erich


FreeRTOS porting to ARM926ejs

Posted by xz8987f on October 10, 2013

needs to have double underscore around attribute:

__attribute__ ((naked)) void vPortTickHandler(void) ...

FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 10, 2013

is it true for arm-none-eabi-gcc ?

In case od ARM will jump into the generic handler called do_irq() inside this handlwe will check for which peripheral has raised the interrupt then will call the OSTimeTick().

Please could you suggest me now i have to made OSTimeTick() as naked or do_irq() naked?

Regards ,


FreeRTOS porting to ARM926ejs

Posted by richardbarry on October 10, 2013

As already said - if you are using a single interrupt entry point that is saving the task context, then determining the interrupt source, then calling the appropriate C function to handle the interrupt source....the C function that is called should be a standard C function - not a naked function.

All the stack manipulation and context saving and restoring is performed in just on place - the IRQ entry point. After that everything is just C code managed by the compiler.

Regards.


FreeRTOS porting to ARM926ejs

Posted by nagarajukarre on October 10, 2013

Thank you for your reply.

I observed the code for Cortex-M3 and i found the below observations.

void xPortSysTickHandler( void ) and

void xPortPendSVHandler( void ) inside this handler we are getting the current TCB and saving all the processor registers and calling bl vTaskSwitchContext and restoring the context.

Whenever the timer gets expired xPortSysTickHandler() function will be called and timer tick count gets incremented.

Please could you clarify me the below.When the below handlers are going to be called and where we are registering thse handlers.

vPortSVCHandler() and void xPortPendSVHandler( void )

Regards,


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS