<<< | >>>

ColdFire RTOS Implementation

Phase 2: Running a Simple Task

In order to run a simple task, the FreeRTOS™ performs the following functions which are relevant to our port:
  1. Memory is allocated for the task control block (TCB) and stack.
  2. An initial context is pushed onto the stack to simulate a suspended task.
  3. The initial context for the process is loaded use the restore context function.
Developing the second increment of our RTOS port required addressing these three steps.

Other FreeRTOS™ ports use various manual block allocation schemes to provide memory allocation.
We chose instead to use the Newlib implementation of malloc() and free() as having decided already to use this library this did not seem to be an unreasonable dependency.

The remaining two steps were somewhat more complicated and highly interdependent. In Table 1 we compare the initial stack we generated with the assembly code we used to restore the stack.

 

Restore context assembly code

Comment

 

move.l pxCurrentTCB, %a0

Loads the address of the task's stack (stored in the task control block) onto the stack pointer.

Initial stack

move.l (%a0),%sp

0x6

move.l %sp@+,%a6

Pops the value on the top of the stack onto register A6 (also known as FP for frame pointer) and increments the stack pointer.

0x5

move.l %sp@+,%a5

Likewise for register A5…

0x4

move.l %sp@+,%a4

 

0x3

move.l %sp@+,%a3

 

0x2

move.l %sp@+,%a2

 

0x1

move.l %sp@+,%a1

 

0x0

move.l %sp@+,%a0

 

0x7

move.l %sp@+,%d7

Pops the value on the top of the stack onto register D7.

0x6

move.l %sp@+,%d6

Likewise for register D6…

0x5

move.l %sp@+,%d5

 

0x4

move.l %sp@+,%d4

 

0x3

move.l %sp@+,%d3

 

0x2

move.l %sp@+,%d2

 

0x1

move.l %sp@+,%d1

 

0x2000

move.l %sp@+,%d0

move.w %d0,%sr

Pops the value on the top of stack onto register D0 and then onto the status register.

0x0

move.l %sp@+,%d0

Pops the value on the top of the stack onto register D0.

(address of first instruction of task)

 

 

0x0

 

 

(function parameter—address passed in)

 

 

0x33

 

 

0x22

 

 

0x11

 

 

Table 1 - Comparison of initial stack with original restore context code

The first thing we note is that each time something is popped off the stack the stack pointer is also incremented (that is the function of the %An@+ addressing mode). This is because the stack grows from high memory to low memory.

The values used to populate the initial stack reflect the names of the registers they are transferred to. This is purely to aid debugging. Similarly the three values placed at the bottom of the stack (0x33, 0x22, 0x11) are for debugging purposes only. These two conventions were adopted from the MegaAVR port.

An initial value for the status register of 0x2000 is also stored. This value corresponds to a status where the processor interrupts are enabled and supervisor mode is on as this is the status with which we wish the task to begin. This value is first loaded into D0 because the status register can only be loaded from a data register.

After all registers are restored the top of the stack will contain the address of the first instruction of the task. An RTS (return from subroutine) instruction will then be executed which will pop this address from the stack and load it into the program counter.

After the task has begun the top of the stack is expected to contain the return address of the current function (which we set to 0x0 as tasks in FreeRTOS™ should be implemented as non-terminating loops) and values deeper in the stack are the parameters passed to the function. When we initialise the stack we push the task parameter pvParameters (which is a pointer to parameters for the task) onto the stack so that it can be accessed by the task like a regular function parameter.

To test this increment of our development we produced a simple test program, the body of which is shown in Program 1.

portSHORT main( void )
{
    xTaskCreate( vTestTask, "Hello",   portMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL );

    vTaskStartScheduler( pdFALSE );

    return 0;
}
/*-----------------------------------------------*/

static void vTestTask( void *pvParameters )
{
    printf("Hello FreeRTOS™\n");
    printf("pvParameters: %d\n", pvParameters);

    /* Tasks must be implemented as continuous loops */
    while(1);
}
Program 1 - Creating a task

The result of this test program is shown in Figure 1.


Figure 1 - Output from test program demonstrating task creation and successful passing of parameters.

NEXT >>> ColdFire RTOS Port - Phase 3 - Cooperative Multitasking

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