这块板子在手上有好几年了,还是在上家公司的时候,vender送给我。
吃灰吃了这么多年,最近花了二十天的时间把freeRTOS给移植到上面去了。
总共运行了四个task,后面会把关键的代码给贴出来。
1. 这段汇编代码是主要是做入栈和出栈处理的。
#define CPU_SAVE_CONTEXT()\
[ --sp ] = rets;\
[ --sp ] = fp;\
[ --sp ] = astat;\
[--sp] = (r7:0, p5:0);\
[--sp] = lc0;\
[--sp] = lc1;\
[--sp] = lt0;\
[--sp] = lt1;\
[--sp] = lb0;\
[--sp] = lb1;\
[--sp] = a0.W;\
[--sp] = a0.X;\
[--sp] = a1.W;\
[--sp] = a1.X;\
[--sp] = i0;\
[--sp] = i1;\
[--sp] = i2;\
[--sp] = i3;\
[--sp] = b0;\
[--sp] = b1;\
[--sp] = b2;\
[--sp] = b3;\
[--sp] = l0;\
[--sp] = l1;\
[--sp] = l2;\
[--sp] = l3;\
[--sp] = m0;\
[--sp] = m1;\
[--sp] = m2;\
[--sp] = m3;
#define CPU_RESTORE_CONTEXT() \
m3 = [sp++];\
m2 = [sp++];\
m1 = [sp++];\
m0 = [sp++];\
l3 = [sp++];\
l2 = [sp++];\
l1 = [sp++];\
l0 = [sp++];\
b3 = [sp++];\
b2 = [sp++];\
b1 = [sp++];\
b0 = [sp++];\
i3 = [sp++];\
i2 = [sp++];\
i1 = [sp++];\
i0 = [sp++];\
a1.X = [sp++];\
a1.W = [sp++];\
a0.X = [sp++];\
a0.W = [sp++];\
lb1 = [sp++];\
lb0 = [sp++];\
lt1 = [sp++];\
lt0 = [sp++];\
lc1 = [sp++];\
lc0 = [sp++];\
(r7:0, p5:0) = [sp++];\
astat = [ sp++ ];\
fp = [ sp++ ];\
rets = [ sp++ ];
2. 下面这段代码是OS在create几个task后,需要启动第一个task要调用的汇编函数。
a)每个task在create的时候,都会调用prvInitialiseNewTask()函数,在该函数内部会调用pxPortInitialiseStack()函数进行stack的初始化。
b)在每个task的stack初始化完成后,该stack会在后续的以下汇编函数中进行使用。
c)函数pxPortInitialiseStack()进行stack的初始化的顺序比如和上面代码1中入栈宏的操作顺序一致。
//==========================================================================================
// Function:
// this function OSStartHighRdy() will be called only one time.
// the OS will select a highest priority task to start for the first time.
//==========================================================================================
.global _OSStartHighRdy;
_OSStartHighRdy:
// need to save RETS since _OSStartHighRdy never returns
// Get the SP for the highest ready task
p1.L = _pxCurrentTCB;
p1.H = _pxCurrentTCB;
p2 = [ p1 ];
sp = [ p2 + 0 ];
nop; nop; nop;
sp += 4;
// Restore CPU context
CPU_RESTORE_CONTEXT()
// Return to high ready task
rts;
_OSStartHighRdy.end:
3. 下面的函数是进行任务切换的核心函数,主要操作如下:
a) 先进行当前任务的context信息的保存
b) 调用vTaskSwitchContext() 函数,找到highest priority的任务
c) 将找到的任务的context信息切入。
d) 函数返回到新切入的任务,同时,rti汇编会打开中断。
e) 为了代码简便,该函数没有处理当找到的高优先级任务就是当前任务时的处理方式。
//==========================================================================================
// Function:
// This function is called to switch the context of the current running task
// This function is registered as the IVG14 handler and will be called to handle both
// interrupt and task level context switches.
//==========================================================================================
.global _OSCtxSw;
_OSCtxSw:
// Save context, interrupts disabled by IPEND[4] bit
CPU_SAVE_CONTEXT()
// The task Program Counter is in RETI,
// IPEND[4] is not cleared when it is stored
// on the stack via an intermediate register like r1
// so interrupts remain disabled
r1 = reti;
[ --sp ] = r1;
//p1 -> pxCurrentTCB
p1.L = _pxCurrentTCB;
p1.H = _pxCurrentTCB;
p2 = [p1]; //p2 -> pxCurrentTCB->pxTopOfStack
[p2] = sp; //store the switched out task's stack
// to get the higher priority task to switch in
call _vTaskSwitchContext;
// Sometime the highest priority task is current task,
// i still proceed here without skipping below code.
// Get a highest ready task priority
p3.L = _pxCurrentTCB;
p3.H = _pxCurrentTCB;
p2 = [ p3 ];
sp = [ p2 + 0 ];
nop; nop; nop;
// Recover the start address of the task
reti = [ sp++ ];
// Restoring CPU context
CPU_RESTORE_CONTEXT()
// Reenable interrupts via IPEND[4] bit and return to task
rti;
_OSCtxSw.end:
今天的代码就更新到此。