UCOS-II在LPC2210上的移植--OS_CPU_c.c
CPU: Philips ARM7 LPC2210
OS: uC/OS-II 2.52
IDE: ADS 1.2
移植一個操作系統到一個CPU體系的結構上,移植者必須的要求:
1、對目標體系結構要有很深的瞭解 -- ARM Architecture Reference Manual
2、對OS原理要有較深入的瞭解 -- 嵌入式實時操作系統uC/OS-II
3、對所使用的編譯器要有較深入的瞭解 -- ADS自帶的編譯器和連接器的手冊
4、對需要移植的操作系統要有相當的瞭解 -- 嵌入式實時操作系統uC/OS-II
5、對具體使用的芯片也要有一定的瞭解 -- 芯片的數據手冊
編寫 OS_CPU_c.c
#define OS_CPU_GLOBALS
#include "config.h"
/*********************************************************************************************************
** 函數名稱: OSTaskStkInit
** 功能描述: 任務堆棧初始化代碼,本函數調用失敗會使系統崩潰
** 輸 入: task : 任務開始執行的地址
** pdata :傳遞給任務的參數
** ptos :任務的堆棧開始位置
** opt :附加參數,當前版本對於本函數無用,具體意義參見OSTaskCreateExt()的opt參數
** 輸 出: 棧頂指針位置
** 全局變量:
** 調用模塊:
********************************************************************************************************/
OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
OS_STK *stk;
opt = opt; /* 'opt' 沒有使用。作用是避免編譯器警告 */
stk = ptos; /* 獲取堆棧指針 */
/* 建立任務環境,ADS1.2使用滿遞減堆棧 */
*stk = (OS_STK) task; /* PC( R15 ) */
*--stk = (OS_STK) task; /* LR( R14 ) */
*--stk = 0; /* r12 */
*--stk = 0; /* r11 */
*--stk = 0; /* r10 */
*--stk = 0; /* r9 */
*--stk = 0; /* r8 */
*--stk = 0; /* r7 */
*--stk = 0; /* r6 */
*--stk = 0; /* r5 */
*--stk = 0; /* r4 */
*--stk = 0; /* r3 */
*--stk = 0; /* r2 */
*--stk = 0; /* r1 */
*--stk = (unsigned int) pdata; /* r0,第一個參數使用R0傳遞 */
*--stk = (USER_USING_MODE|0x00); /* spsr,允許 IRQ, FIQ 中斷 */
*--stk = 0; /* 關中斷計數器OsEnterSum; */
return (stk);
}
/*********************************************************************************************************
** 函數名稱: SWI_Exception
** 功能描述: 軟中斷異常處理程序,提供一些系統服務
**
** 輸 入: SWI_Num:功能號
** Regs[0] 爲第一個參數,也是返回值
** Regs[1] 爲第二個參數
** Regs[2] 爲第三個參數
** Regs[3] 爲第四個參數
** 輸 出: 根據功能而定
**
** 全局變量: 無
** 調用模塊: 無
**
********************************************************************************************************/
#if OS_SELF_EN > 0
extern int const _OSFunctionAddr[];
extern int const _UsrFunctionAddr[];
#endif
void SWI_Exception(int SWI_Num, int *Regs)
{
OS_TCB *ptcb;
switch(SWI_Num)
{
//case 0x00: /* 任務切換函數OS_TASK_SW,參考os_cpu_s.s文件 */
// break;
//case 0x01: /* 啓動任務函數OSStartHighRdy,參考os_cpu_s.s文件 */
// break;
/* 在ARM處理器核中斷和開中斷時,通過改變CPSR中的相應位實現。由於使用了軟件中斷,程序狀態寄存器CPSR
保存到SPSR中,軟件中斷退出時會將SPSR恢復到CPSR中,所以程序只需要改變SPSR中的相應控制位就可以了 */
case 0x02: /* 關中斷函數OS_ENTER_CRITICAL(),參考os_cpu.h文件 */
__asm
{
MRS R0, SPSR
ORR R0, R0, #NoInt /* 禁止IRQ中斷 */
MSR SPSR_c, R0
}
OsEnterSum++; /* 中斷嵌套計數器增加一 */
break;
case 0x03: /* 開中斷函數OS_EXIT_CRITICAL(),參考os_cpu.h文件 */
if (--OsEnterSum == 0) /* 判斷是否中斷嵌套已經完了 */
{
__asm
{
MRS R0, SPSR
BIC R0, R0, #NoInt /* 清楚IRQ標誌,允許中斷 */
MSR SPSR_c, R0
}
}
break;
#if OS_SELF_EN > 0
case 0x40:
/* 返回指定系統服務函數的地址 */
/* 函數地址存於數組_OSFunctionAddr中*/
/* 數組_OSFunctionAddr需要另外定義 */
/* Regs[0] 爲第一個參數,也是返回值 */
/* Regs[1] 爲第二個參數 */
/* Regs[2] 爲第三個參數 */
/* Regs[3] 爲第四個參數 */
/* 僅有一個參數爲系統服務函數的索引 */
Regs[0] = _OSFunctionAddr[Regs[0]];
break;
case 0x41:
/* 返回指定用戶的服務函數的地址 */
/* 函數地址存於數組_UsrFunctionAddr中*/
/* 數組_UsrFunctionAddr需要另外定義 */
/* Regs[0] 爲第一個參數,也是返回值 */
/* Regs[1] 爲第二個參數 */
/* Regs[2] 爲第三個參數 */
/* Regs[3] 爲第四個參數 */
/* 僅有一個參數爲用戶服務函數的索引 */
Regs[0] = _UsrFunctionAddr[Regs[0]];
break;
case 0x42: /* 中斷開始處理 */
OSIntNesting++;
break;
case 0x43: /* 判斷中斷是否需要切換 */
if (OSTCBHighRdy == OSTCBCur)
{
Regs[0] = 0;
}
else
{
Regs[0] = 1;
}
break;
#endif
case 0x80: /* 任務切換到系統模式 */
__asm
{
MRS R0, SPSR
BIC R0, R0, #0x1f /* 先清再賦值 */
ORR R0, R0, #SYS32Mode /* 設置爲系統模式 */
MSR SPSR_c, R0
}
break;
case 0x81: /* 任務切換到用戶模式 */
__asm
{
MRS R0, SPSR
BIC R0, R0, #0x1f
ORR R0, R0, #USR32Mode
MSR SPSR_c, R0
}
break;
// 0x82和0x83功能用於指定任務以ARM的那種指令集運行
case 0x82: /* 任務是ARM代碼 */
if (Regs[0] <= OS_LOWEST_PRIO) // 先確定任務有效
{
ptcb = OSTCBPrioTbl[Regs[0]]; // 獲取任務控制塊
if (ptcb != NULL)
{
ptcb -> OSTCBStkPtr[1] &= ~(1 << 5); // 指向堆棧棧頂的指針
}
}
break;
case 0x83: /* 任務是THUMB代碼 */
if (Regs[0] <= OS_LOWEST_PRIO)
{
ptcb = OSTCBPrioTbl[Regs[0]];
if (ptcb != NULL)
{
ptcb -> OSTCBStkPtr[1] |= (1 << 5);
}
}
break;
default:
break;
}
}
/*********************************************************************************************************
** 函數名稱: OSStartHighRdy
** 功能描述: uC/OS-II啓動時使用OSStartHighRdy運行第一個任務,
** 實質是產生swi 1指令
** 輸 入: 無
** 輸 出 : 無
** 全局變量: 無
** 調用模塊: 無
********************************************************************************************************/
void OSStartHighRdy(void)
{
_OSStartHighRdy(); // swi的0x01功能號,運行優先級最高的任務
}