This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

FreeRTOS on nRF52810

Hello,

Does anyone know if the FreeRTOS port that's distributed with the nRF5_SDK_14.2.0 is intended to support nRF52810 chips (which have no hardware FPU)? I started working on an application that would be easier to implement using FreeRTOS but can't get it to work. I was unable to find any mention of it in the existing documentation. SDK 14.2 contains FreeRTOS examples for the other dev boards, but "pca10040e" FreeRTOS examples are missing...

I am getting the following compiler error after including the FreeRTOS files in my project:

Compile output:


Compiling ‘port_cmsis_systick.c’
Compiling ‘queue.c’
Compiling ‘port.c’
     Assembler messages:
        selected processor does not support `vstmdbeq r0!,{s16-s31}' in Thumb mode
        instruction not allowed in IT block -- `stmdb r0!,{r4-r11,r14}'
        selected processor does not support `vldmiaeq r0!,{s16-s31}' in Thumb mode
        instruction not allowed in IT block -- `msr psp,r0'
Compiling ‘tasks.c’
Build failed

Parents
  • Nordic FreeRTOS port does not use FPU for anything. All it does is push the FPU context of the task that is using it to the stack when it is starting the scheduler using PendSV interrupt handler. The best would have been to fence under a macro.

    Comment out below in port_cmsis.c

    #if !(__FPU_USED) && !(__LINT__)
        #error This port can only be used when the project options are configured to enable hardware floating point support.
    #endif

    replace xPortPendSVHandler in port.c with this

    __asm void xPortPendSVHandler( void )
    {
        extern uxCriticalNesting;
        extern pxCurrentTCB;
        extern vTaskSwitchContext;
    
        PRESERVE8
    
        mrs r0, psp
        isb
        /* Get the location of the current TCB. */
        ldr r3, =pxCurrentTCB
        ldr r2, [r3]
    
        /* Is the task using the FPU context?  If so, push high vfp registers. */
    #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
        tst r14, #0x10
        it eq
        vstmdbeq r0!, {s16-s31}
    #endif
        
        /* Save the core registers. */
        stmdb r0!, {r4-r11, r14}
    
        /* Save the new top of stack into the first member of the TCB. */
        str r0, [r2]
    
        stmdb sp!, {r3}
        mov r0, #(configMAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
        msr basepri, r0
        dsb
        isb
        bl vTaskSwitchContext
        mov r0, #0
        msr basepri, r0
        ldmia sp!, {r3}
    
        /* The first item in pxCurrentTCB is the task top of stack. */
        ldr r1, [r3]
        ldr r0, [r1]
    
        /* Pop the core registers. */
        ldmia r0!, {r4-r11, r14}
    
        /* Is the task using the FPU context?  If so, pop the high vfp registers
        too. */
    #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
        tst r14, #0x10
        it eq
        vldmiaeq r0!, {s16-s31}
    #endif
        msr psp, r0
        isb
    
        bx r14
    
        ALIGN
    }

    The rest of the port is independent of FPU. This should work, given that you have enough space in that chip to run freertos and your appliction

Reply
  • Nordic FreeRTOS port does not use FPU for anything. All it does is push the FPU context of the task that is using it to the stack when it is starting the scheduler using PendSV interrupt handler. The best would have been to fence under a macro.

    Comment out below in port_cmsis.c

    #if !(__FPU_USED) && !(__LINT__)
        #error This port can only be used when the project options are configured to enable hardware floating point support.
    #endif

    replace xPortPendSVHandler in port.c with this

    __asm void xPortPendSVHandler( void )
    {
        extern uxCriticalNesting;
        extern pxCurrentTCB;
        extern vTaskSwitchContext;
    
        PRESERVE8
    
        mrs r0, psp
        isb
        /* Get the location of the current TCB. */
        ldr r3, =pxCurrentTCB
        ldr r2, [r3]
    
        /* Is the task using the FPU context?  If so, push high vfp registers. */
    #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
        tst r14, #0x10
        it eq
        vstmdbeq r0!, {s16-s31}
    #endif
        
        /* Save the core registers. */
        stmdb r0!, {r4-r11, r14}
    
        /* Save the new top of stack into the first member of the TCB. */
        str r0, [r2]
    
        stmdb sp!, {r3}
        mov r0, #(configMAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
        msr basepri, r0
        dsb
        isb
        bl vTaskSwitchContext
        mov r0, #0
        msr basepri, r0
        ldmia sp!, {r3}
    
        /* The first item in pxCurrentTCB is the task top of stack. */
        ldr r1, [r3]
        ldr r0, [r1]
    
        /* Pop the core registers. */
        ldmia r0!, {r4-r11, r14}
    
        /* Is the task using the FPU context?  If so, pop the high vfp registers
        too. */
    #if (__FPU_PRESENT == 1U) && (__FPU_USED == 1U)
        tst r14, #0x10
        it eq
        vldmiaeq r0!, {s16-s31}
    #endif
        msr psp, r0
        isb
    
        bx r14
    
        ALIGN
    }

    The rest of the port is independent of FPU. This should work, given that you have enough space in that chip to run freertos and your appliction

Children
Related