📄 ggt_cpu_c.c
字号:
/****************************************************************************************************
** Gogoto OS
** (c) Copyright 2007-2008, luyigui(卢益贵)
** All Rights Reserved
** V1.00.0
**
** 狗狗兔嵌入式多任务系统(基于消息机制)
** 绿城代码、GGT-OS、Gogoto OS、狗狗兔嵌入式、狗狗兔系统
** QQ:48092788
**
**------------------文件信息------------------------------------------------------------------------
** 文件名: GGT_CPU_c.c
** 创建人: 卢益贵
** 日 期: 2007年12月8日
** 版 本: V1.00.0
** 描 述: Gogoto OS 与CPU相关的C核心代码部分,将所有移植可能与CPU和编译器相关的部分放置与此,
方便移植。
**
**------------------修改记录------------------------------------------------------------------------
** 修改人: 卢益贵
** 版 本: V1.00.1
** 日 期: 2008年1月5日
** 描 述: 增加OSIsrBegin和OSIsrEnd函数,考虑到CPU允许中断嵌套的可能,特为此增加这个两个函数,如果
CPU允许中断嵌套,将GGT_CPU.h头文件的OS_INT_COUNT 定义为1即可
**
****************************************************************************************************/
#include "GGT_OS.h"
#include "GGT_CPU.h"
#include "GGT_Func.h"
#include "GGT_SysType.h"
#include "GGT_Kernel.h"
#define T0IR (*((volatile unsigned long *) 0xE0004000))
#define T0TCR (*((volatile unsigned long *) 0xE0004004))
#define T0TC (*((volatile unsigned long *) 0xE0004008))
#define T0MCR (*((volatile unsigned long *) 0xE0004014))
#define T0MR0 (*((volatile unsigned long *) 0xE0004018))
#define VICVectAddr0 (*((volatile unsigned long *) 0xFFFFF100))
#define VICVectCntl0 (*((volatile unsigned long *) 0xFFFFF200))
#define VICIntEnable (*((volatile unsigned long *) 0xFFFFF010))
#define VICVectAddr (*((volatile unsigned long *) 0xFFFFF030))
#if(OS_INT_COUNT)
INT32 OSIrqCount = 0;
#endif
/****************************************************************************************************
** 函数名: OSClockIRQ
** 描 述: 系统时钟中断函数。系统时钟启动后,第一次节拍发生时,pOSTskNow等于pOSTskMain,
从而达到把main函数设置为main任务的目的。
** 输 入: 无
** 输 出: 无
** 创建人: 卢益贵
** 日 期: 2007年12月12日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 版 本:
** 日 期:
** 描 述:
**
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
/*
void DelayNS(int Time) __arm
{
// 以每个时钟周期为一个指令周期,主频为11059200 * 5:(1000000000 / (11059200 * 5)) = 18
// 在调用本函数时消耗两个指令:
//__asm
//{
// Mov R0,#Time
// B DelayNS
//}
Time = (Time - 18 * 5) / (18 * 3); // 消耗两个指令,因此Time< (18 * 5 + 18 * 3 = 144)的画,都是一样的;
while(Time--); // 消耗三个指令(至少一个CMP指令才能退出函数,因此Time 先减少五个指令(18*5)才能进入循环)。
}
*/
void OSClockInt(void) __arm __task
{
// 如果CPU或OS允许中断嵌套,应该在此判断是否是嵌套,是就退出
#if(OS_INT_COUNT)
__asm
{
LDR R8, =OSIrqCount
LDR R8,[R8]
CMP R8,#0
BEQ SaverTaskData
}
T0IR = 0x01;
VICVectAddr = 0;
return;
#endif
// 保存当前任务环境
__asm
{
SaverTaskData:
STMDB SP!,{R0-R1}
STMDB SP,{SP}^
LDMDB SP,{R0}
SUB LR,LR,#4
STMDB R0!,{LR}
STMDB R0!,{R2-R12,LR}^
MRS R1,SPSR
LDMIA SP!,{R2-R3}
STMDB R0!,{R1-R3}
LDR R1,=pOSTskNow
LDR R1,[R1]
STR R0,[R1,#4]
}
/*
__asm
{
//SaverTaskData:
STMDB SP,{SP}^
LDMDB SP,{R8}
MOV R9,R8
SUB LR,LR,#4
STMDB R8!,{LR}
STMDB R8!,{LR}^
STMDB R8!,{R9}
STMDB R8!,{R0-R12}^
MRS R9,SPSR
STMDB R8!,{R9}
LDR R1,=pOSTskNow
LDR R1,[R1]
STR R0,[R1,#4]
}
*/
//进行任务调度
OSTaskDispatch();
//定时器计数
OSTimerCheck();
//中断结束
T0IR = 0x01;
VICVectAddr = 0;
//就绪任务出列,并加载执行
__asm
{
LDR R4,=pOSTskNow ;当前任务变量地址
LDR R3,=pOSTskReady ;就绪任务变量地址
MOV R5, R3 ;保存就绪任务变量地址
LDR R3,[R3] ;R3=就绪任务数据区地址
STR R3,[R4] ;pOSTskNow = pOSTskReady
LDR R3,[R3] ;R3=pOSTskReady-pNext
STR R3,[R5] ;pOSTskReady = pOSTskReady-pNext
LDR R4,[R4]
LDR LR,[R4,#4]
LDMIA LR!,{R2}
MSR SPSR_cxsf,R2
ADD R0,LR,#60
STMDB SP,{R0}
LDMDB SP,{SP}^
LDMIA LR!,{R0-R12,LR}^
LDMIA LR!,{LR}
MOVS PC, LR
}
/*
__asm
{
LDR R8,=pOSTskNow ;当前任务变量地址
LDR R9,=pOSTskReady ;就绪任务变量地址
MOV R10, R9 ;保存就绪任务变量地址
LDR R9,[R9] ;R3=就绪任务数据区地址
STR R9,[R8] ;pOSTskNow = pOSTskReady
LDR R9,[R9] ;R3=pOSTskReady-pNext
STR R9,[R10] ;pOSTskReady = pOSTskReady-pNext
LDR R8,[R8]
LDR R8,[R8,#4]
LDMIA R8!,{R9}
MSR SPSR_cxsf,R9
LDMIA R8!,{R0-R12,SP,LR,PC}^
}
*/
}
/****************************************************************************************************
** 函数名: OSClockInit
** 描 述: 打开系统节拍时钟
** 输 入: 无
** 输 出: 无
** 创建人: 卢益贵
** 日 期: 2007年12月8日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 日 期:
** 说 明:
** 原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
void OSClockInit(void)
{
T0IR = 1;
T0TC = 0;
T0TCR = 0x01;
T0MCR = 0x03;
T0MR0 = OSGetFPCLK() / OSGetTick();
VICVectAddr0 = (UINT32)OSClockInt;
VICVectCntl0 = 0x20 | 4;
VICIntEnable |= (1 << 4);
}
/****************************************************************************************************
** 函数名: OSStackAlloc
** 描 述: 分配任务堆栈的函数
** 输 入: 无
** 输 出: 返回堆栈地址
** 创建人: 卢益贵
** 日 期: 2007年12月8日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 日 期:
** 说 明:
** 原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
UINT32* OSStackAlloc(void)
{
// 满降序堆栈
return((UINT32*)(((UINT32)BoxAlloc(OSGetBoxStack())) + OSGetSizeStack()));
}
/****************************************************************************************************
** 函数名: OSStackInit
** 描 述: 初始化任务堆栈
** 输 入: 无
** 输 出: 返回堆栈地址
** 创建人: 卢益贵
** 日 期: 2007年12月8日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 日 期:
** 说 明:
** 原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
UINT32* OSStackInit(void *pTaskBody, UINT32 *pStack, UINT32 Mode, UINT32 TaskParam)
{
// 满降序堆栈
*--pStack = (UINT32 *)pTaskBody; /* pc */
*--pStack = (UINT32 *)pTaskBody; /* lr */
*--pStack = 0; /* r12 */
*--pStack = 0; /* r11 */
*--pStack = 0; /* r10 */
*--pStack = 0; /* r9 */
*--pStack = 0; /* r8 */
*--pStack = 0; /* r7 */
*--pStack = 0; /* r6 */
*--pStack = 0; /* r5 */
*--pStack = 0; /* r4 */
*--pStack = 0; /* r3 */
*--pStack = 0; /* r2 */
*--pStack = 0; /* r1 */
*--pStack = TaskParam; /* r0 */
*--pStack = Mode;
return(pStack);
}
/****************************************************************************************************
** 函数名: main
** 描 述: C语言函数入口,
** 输 入: 无
** 输 出: 无
** 创建人: 卢益贵
** 日 期: 2007年12月8日
**------------------修改记录------------------------------------------------------------------------
** 修改人: 卢益贵
** 日 期: 2008年1月10日
** 说 明:
** 原代码:
void main(void) __arm __task
{
// 初始化任务系统
OSTaskInit();
// 设置main函数为当前任务,移植时应注意修改这个部分
pOSTskMain->pTskStack -= 10; // 指向空栈
__asm
{
LDR R4,=pOSTskMain // mian任务变量地址
LDR R4,[R4, #0] // main任务数据区地址
LDR R4,[R4, #4] // R4=堆栈指针
MOV SP, R4 // 把SP指向main任务堆栈区,
}
// 打开系统节拍时钟
OSClockInit();
// 调用用户主函数,初始化用户系统
umain();
// 把main任务权限设置为无穷大,将进行永久等待
pOSTskMain->PrioTick = 1000 * 90000;
while(1)
{
// 把main任务设置为永远延时任务
pOSTskMain->StateValue = 1000 * 90000;
// CPU休眠
(PCON = PCON | 0x01);
}
}
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
//用户主任务
extern void TaskUasrMain(void) __task;
#define PCON (*((volatile unsigned char *) 0xE01FC0C0))
#define IOPIN (*((volatile unsigned long *) 0xE0028000))
void main(void) __arm __task
{
// 初始化任务系统
OSInit();
// 设置main函数为当前任务,移植时应注意修改这个部分
pOSTskMain->pTskStack -= 10; // 指向空栈
__asm
{
LDR R4,=pOSTskMain // mian任务变量地址
LDR R4,[R4, #0] // main任务数据区地址
LDR R4,[R4, #4] // R4=堆栈指针
STR SP, [R4] // 把SP指向main任务堆栈区,
}
// 如果不想
// 打开系统节拍时钟
OSClockInit();
// 创建用户主任务(必须等系统初始化完了以后才能创建)
OSTaskCreate(TaskUasrMain, 0, 255);
// 把main任务权限设置为无穷大,将进行永久等待
pOSTskMain->PrioTick = 1000 * 90000;
while(1)
{
// 把main任务设置为永远延时任务
pOSTskMain->StateValue = 1000 * 90000;
// CPU休眠
(PCON = PCON | 0x01);
}
}
/****************************************************************************************************
** 函数名: OSTaskCreate
** 描 述: 创建默认模式的用户任务
** 输 入: 无
** 输 出: 无
** 创建人: 卢益贵
** 日 期: 2007年12月8日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 日 期:
** 说 明:
** 原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
UINT32 OSTaskCreate(void *pTaskBody, const UINT32 Prio, const UINT32 TaskParam)
{
return(OSTaskUserCreate(pTaskBody, Prio, USR32MODE, TaskParam));
}
/****************************************************************************************************
** 函数名: OSIsrBegin
** 描 述: 中断服务开始,对中断嵌套计数,中断函数第一条语句为调用该函数。
** 输 入: 无
** 输 出: 无
** 创建人: 卢益贵
** 日 期: 2008年1月5日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 日 期:
** 说 明:
** 原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
void OSIsrBegin(void)
{
#if(OS_INT_COUNT)
OSIrqCount++;
#endif
}
/****************************************************************************************************
** 函数名: OSIsrEnd
** 描 述: 中断服务结束,对中断嵌套计数,如果有任务要处理中断数据,中断函数的最后语句为调用本函数,
系统立即切换任务,本函数在CPU未允许中断嵌套的情况,OS_INT_COUNT定义为0时,
只执行任务切换功能。
** 输 入: IsSW:1为立即切换任务,其他未定义
** 输 出: 无
** 创建人: 卢益贵
** 日 期: 2008年1月5日
**------------------修改记录------------------------------------------------------------------------
** 修改人:
** 日 期:
** 说 明:
** 原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
void OSIsrEnd(BOOL DoSW)
{
#if(OS_INT_COUNT)
if(OSIrqCount)
OSIrqCount++;
#endif
//立即切换任务
if(DoSW)
{
OSTaskIsNULLLoadDef();
OSTaskSW();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -