FreeRTOS on TI 28335

I’m trying to run FreeRTOS on TI DSP28335. There is a tranplant version developed by CodeSkin and is working well for most of the time. But I’ve found that there is something wrong with the pxPortInitialiseStack() function, and parameter (void *pvParameters) is disabled as a result .
the code of  pxPortInitialiseStack() is like this:
portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters ){
    /* FIRST we need to emulate automatic context save assumed by the IRET function */
    /* ============================================================================ */
    /* see "TMS320C28x CPU and Instruction Set Reference Guide", page 3-14
     * on how stack is populated by automatic context save */

    // we even-align stack (details of automatic context save depend on alignment
    if(((unsigned long)pxTopOfStack & 1) != 0){
        pxTopOfStack++;
    } 

    // ST0: for C runtime environment, it is presumed that OVM=0, PM=0
    *pxTopOfStack = 0x0000;     
    pxTopOfStack++;
    // T - upper 16-bit of Multiplicand Register, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // AL - Accumulator, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // AH - Accumulator, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // PL - Product Register, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // PH - Product Register, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // AR0 - Aux Register 0, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // AR1 - Aux Register 0, nothing presumed
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;     

    // ST1: ARP(15-13) XF(12) M0M1MAP(11) Reserved(10) OBJMODE(9) AMODE(8) IDLESTAT(7)
    //      EALLOW(6) LOOP(5) SPA(4) VMAP(3) PAGE0(2) DBGM(1) INTM(0)
    //      presumed is PAGE0=0 
    // 1: M0 and M1 mapping mode bit. The M0M1MAP bit should always remain set to 1 in the C28x object mode.
    // 0: Reserved
    // 1: C28x object mode (OBJMODE == 1)
    // 0: AMODE This bit is set to 0 on reset.
    // 0: IDLESTAT is not restored from the stack.
    // 0: When the CPU services an interrupt, the current value of EALLOW is saved on the
    //   stack (when ST1 is saved on the stack), and then EALLOW is cleared. Therefore, at the
    //   start of an interrupt service routine (ISR), access to protected registers is disabled. If the
    //   ISR must access protected registers, it must include an EALLOW instruction. At the end
    //   of the ISR, EALLOW can be restored by the IRET instruction.
    // 0: Upon return from the interrupt, LOOP is not restored from the stack.
    // 0: SPA = 0 The stack pointer has not been aligned to an even address.
    // 1: VMAP = For normal operation leave this bit set.
    // 0: PAGE0 = presumed at 0 by C compiler
    // 0: DBGM: 0 = Debug events are enabled.
    // 0: INTM: 0 Maskable interrupts are globally enabled. 
    // ST1 B: 0000 1010 0000 1000
    *pxTopOfStack = ( portSTACK_TYPE ) 0x8A08; 
    pxTopOfStack++;
    // DP - no assumptions made
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
    // IER - interrupt enable register - probably needs to be passed as a parameter!
    *pxTopOfStack = ( portSTACK_TYPE ) configTICK_IER_MASK; 
    pxTopOfStack++;
    // DBGSTAT, emulation info - NOT SURE
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;
    // PCL
    *pxTopOfStack = ( portSTACK_TYPE ) ((unsigned long)pxCode & 0xFFFF); 
    pxTopOfStack++;
    // PCH
    *pxTopOfStack = ( portSTACK_TYPE ) (((unsigned long)pxCode >> 16) & 0xFFFF); 
    pxTopOfStack++;
    // unused location (per automatic context save)
    *pxTopOfStack = ( portSTACK_TYPE )0xbea1;
    pxTopOfStack++;     

    /* SECOND, we need to emulate portSAVE_CONTEXT in portext.asm */
    /* ========================================================== */    
    /* A variable is used to keep track of the critical section nesting.
    This variable has to be stored as part of the task context and is
    initially set to zero. */
    *pxTopOfStack = ( portSTACK_TYPE ) portNO_CRITICAL_SECTION_NESTING; 
    pxTopOfStack++; 
    /* alignment of stack (required by C environment) */
    if(((unsigned long)pxTopOfStack & 1) == 0){
        // stack already aligned, save SPA = 0
        *pxTopOfStack = ( portSTACK_TYPE ) 0x8A08; // ST1 B: 0000 1010 0000 1000
        pxTopOfStack++;
    } else {
        // align stack, save SPA = 1
        pxTopOfStack++;     
        *pxTopOfStack = ( portSTACK_TYPE ) 0x8A18; // ST1 B: 0000 1010 0001 1000
        pxTopOfStack++;     
    }
    // now DP again, for emulating complete PUSH DP:ST1
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; // DP - no assumptions made
    pxTopOfStack++; 

    // RPC needs to be saved when stack switching (value does not matter initially)
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000;  // RPC L
    pxTopOfStack++;     
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000;  // RPC H
    pxTopOfStack++; 
    // PUSH AR1H:AR0H
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000;  
    pxTopOfStack++;     
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
    // PUSH *SP++,XAR4
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000;  
    pxTopOfStack++;             
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
    // PUSH *SP++,XAR5 
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000;  
    pxTopOfStack++;     
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
     // PUSH *SP++,XAR6 
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++;     
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
     //PUSH *SP++,XAR7 
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 
    // PUSH XT  
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000;  
    pxTopOfStack++; 
    *pxTopOfStack = ( portSTACK_TYPE ) 0x0000; 
    pxTopOfStack++; 

    /* Return a pointer to the top of the stack we have generated so this can
    be stored in the task control block for the task. */
    return pxTopOfStack;
}
We can see that parameter void *pvParameters  is simply skipped in the function, thus one cannot utilise this parameter afterwards. How can I properly correct this? Thanks! Xiatao

FreeRTOS on TI 28335

There is no official port to that device, and I am not familiar with the architecture at all, but I can’t help noticing that pvParameters does not appear in your code snippet at all. pvParameters is passed into pxPortInitialiseStack(), and should be assigned to a register on the stack frame being created such that, when the task is started, the parameter value is popped into the register your compiler expects to find it in.  As pvParameters is not loaded into any register, it is no wonder it is not being passed into the task.  If you know which register (or otherwise which stack position, if parameters are passed on the stack) it should be in you could edit the code to ensure it works as the compiler expects. Regards.

FreeRTOS on TI 28335

By the way – please let me know where this port is on the internet, or who is maintaining it, so it or a link to it can be added to the FreeRTOS Interactive site for the benefit of the whole community.  I didn’t even know it existed. Regards.

FreeRTOS on TI 28335

Thank you for the prompt reply. The link to this port has been posted on the FreeRTOS Interactive site http://www.freertos.org/Interactive_Frames/Open_Frames.html?http://interactive.freertos.org/forums/135229-texas-instruments, but the source code seems to have been removed…

FreeRTOS on TI 28335

I’ve just solved this problem with your help. I’ve checked the assembly code and found that the parameter *pvParameters  is passed through register XAR4. So I stacked that in function pxPortInitialiseStack() and it seems to work~Thanks once again!

FreeRTOS on TI 28335

I tried to do this for the ‘C551X family but had some difficulty with an internal system stack that is on the processor – maybe I can revisit this soon. Glad to see someone has seemingly got this working on a TI DSP.

FreeRTOS on TI 28335

do you have this port by chance? Best

FreeRTOS on TI 28335

do you have port by chance?