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功能號,運行優先順序最高的任務
}