├─APP
│ hello.c
│
├─lpc17xx
│ core_cm3.c
│ core_cm3.h
│ LPC17xx.h
│ startup_LPC17xx.s
│ system_LPC17xx.c
│ system_LPC17xx.h
│ type.h
│
├─Output
│ ├─list
│ └─obj
├─uC-CPU
│ os_cpu.h
│ os_cpu_a.asm
│ os_cpu_c.c
│ os_dbg.c
│
└─uCOS-II
app_cfg.h
os_cfg.h
os_core.c
os_flag.c
os_mbox.c
os_mem.c
os_mutex.c
os_q.c
os_sem.c
os_task.c
os_time.c
os_tmr.c
ucos_ii.h
- #include <LPC17xx.h>
- #include <ucos_ii.h>
- #define TASK_STK_SIZE 512
- OS_STK TaskStartStk[TASK_STK_SIZE];
- void TaskStart(void *data);
- int main(void)
- {
- OSInit();
- OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);
- OSStart();
- return 0;
- }
- void TaskStart(void *data)
- {
- data=data;
- OS_CPU_SysTickInit(SystemFrequency/100);
- for(;;)
- {
- OSCtxSwCtr = 0;
- OSTimeDlyHMSM(0,0,0,10);
- }
- }
![](https://i-blog.csdnimg.cn/blog_migrate/c08cfb63b70942242b309132e6e0283e.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/4ca37e0a8d7bb01d9db53eddb458b38f.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/bfcdfce69351d412a6ee2a9a710ba8f3.jpeg)
![](https://i-blog.csdnimg.cn/blog_migrate/3b73c53e62a2d87385e94437be6308b1.jpeg)
中断类型
|
表项地址偏移量
|
中断向量
|
0
|
0x00
|
MSP的初始值
|
1
|
0x04
|
复位
|
2
|
0x08
|
NMI
|
…
|
…
|
…
|
①NVIC复位,控制内核;
②NVIC从复位中释放内核;
③内核配置堆栈;
④从地址0x00000000处取出MSP的初始值,从地址0x00000004处取出PC的初始值——这个值是复位向量;
⑤运行复位中断服务子程序;
- Reset_Handler PROC
- EXPORT Reset_Handler [WEAK]
- IMPORT SystemInit
- IMPORT __main
- LDR R0, =SystemInit
- BLX R0
- LDR R0, =__main
- BX R0
- ENDP
位段
|
名称
|
类型
|
复位值
|
描述
|
16
|
COUNTFLAG
|
R
|
0
|
如果在上次读取本寄存器后,SysTick已经计到了0,则该位为1;如果读取该位,该位自动清0
|
2
|
CLKSOURCE
|
R/W
|
0
|
0=外部时钟源(STCLK)
1=内核时钟源(FCLK)
|
1
|
TICKINT
|
R/W
|
0
|
1=SysTick倒数计数到0时产生SysTick异常请求
0=倒数到0时无动作
|
0
|
ENABLE
|
R/W
|
0
|
SysTick定时器的使能位
|
位段
|
名称
|
类型
|
复位值
|
描述
|
23:0
|
RELOAD
|
R/W
|
0
|
当倒数计数到0时,将被重装载的值
|
位段
|
名称
|
类型
|
复位值
|
描述
|
23:0
|
CURRENT
|
R/Wc
|
0
|
读取时返回当前倒数计数的值,写它则使之清零,同时还会清除在SysTick控制及状态寄存器中的COUNTFLAG标志
|
- void OS_CPU_SysTickInit (INT32U cnts)
- {
- OS_CPU_CM3_NVIC_ST_RELOAD = cnts - 1u;
- /* 设置SysTickHandler中断优先级为最低优先级 */
- OS_CPU_CM3_NVIC_PRIO_ST = OS_CPU_CM3_NVIC_PRIO_MIN;
- /* 使能定时器 */
- OS_CPU_CM3_NVIC_ST_CTRL |= OS_CPU_CM3_NVIC_ST_CTRL_CLK_SRC | OS_CPU_CM3_NVIC_ST_CTRL_ENABLE;
- /* 使能SysTickHandler中断 */
- OS_CPU_CM3_NVIC_ST_CTRL |= OS_CPU_CM3_NVIC_ST_CTRL_INTEN;
- }
- void OS_CPU_SysTickHandler (void)
- {
- OS_CPU_SR cpu_sr;
- OS_ENTER_CRITICAL(); /* Tell uC/OS-II that we are starting an ISR */
- OSIntNesting++;
- OS_EXIT_CRITICAL();
- OSTimeTick(); /* Call uC/OS-II's OSTimeTick() */
- OSIntExit(); /* Tell uC/OS-II that we are leaving the ISR */
- }
- OS_CPU_PendSVHandler
- CPSID I ; Prevent interruption during context switch
- MRS R0, PSP ; PSP is process stack pointer
- CBZ R0, OS_CPU_PendSVHandler_nosave ; Skip register save the first time
- SUBS R0, R0, #0x20 ; Save remaining regs r4-11 on process stack
- STM R0, {R4-R11}
- LDR R1, =OSTCBCur ; OSTCBCur->OSTCBStkPtr = SP;
- LDR R1, [R1]
- STR R0, [R1] ; R0 is SP of process being switched out
- ; At this point, entire context of process has been saved
- OS_CPU_PendSVHandler_nosave
- PUSH {R14} ; Save LR exc_return value
- LDR R0, =OSTaskSwHook ; OSTaskSwHook();
- BLX R0
- POP {R14}
- LDR R0, =OSPrioCur ; OSPrioCur = OSPrioHighRdy;
- LDR R1, =OSPrioHighRdy
- LDRB R2, [R1]
- STRB R2, [R0]
- LDR R0, =OSTCBCur ; OSTCBCur = OSTCBHighRdy;
- LDR R1, =OSTCBHighRdy
- LDR R2, [R1]
- STR R2, [R0]
- LDR R0, [R2] ; R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
- LDM R0, {R4-R11} ; Restore r4-11 from new process stack
- ADDS R0, R0, #0x20
- MSR PSP, R0 ; Load PSP with new process SP
- ORR LR, LR, #0x04 ; Ensure exception return uses process stack
- CPSIE I
- BX LR ; Exception return will restore remaining context
- END
- OSCtxSw
- LDR R0, =NVIC_INT_CTRL ; Trigger the PendSV exception (causes context switch)
- LDR R1, =NVIC_PENDSVSET
- STR R1, [R0]
- BX LR
![](https://i-blog.csdnimg.cn/blog_migrate/a2ef34714cf8f8e1524c391b8066d3a1.gif)
附件:
1、IMPORT的运用
IMPORT伪操作告诉编译器当前的符号不是在本源文件中定义的,而是在其他源文件中定义的,在本源文件中可能引用该符号,而且不论本源文件是否实际引用该符号,该符号都将被加入到本源文件的符号表中。
语法格式:
IMPORT symbol{[WEAK]}
其中,symbol为声明的符号的名称。它是区分大小写的。
[WEAK]指定这个选项后,如果symbol在所有的源文件中都没有被定义,编译器也不会产生任何错误信息,同时编译器也不会到当前没有被INCLUDE进来的库中去查找该符号。
使用说明:
使用IMPORT伪操作声明一个符号是在其他源文件中的定义。如果连接器在连接处理时不能解析该符号,而IMPORT伪操作中没有指定[WEAK]选项,则连接器将会报告错误。如果连接器在连接处理时不能解析该符号,而IMPORT伪操作中指定了[WEAK]选项,则连接器将不会报告错误,而是及进行下面的操作: 如果该符号被B或者BL指令引用,则该符号被设置成下一条指令的地址,该B或者BL指令相当于一条NOP指令
其他情况下该符号被设置为0
2、修改os_cpu_a.asm文件
根据我们移植的源码情况来修改os_cpu_a.asm文件,如果我们用的是MDK 软件,并且.S源码还是PUBLIC的话就进行相应的改写。
因为我们使用的是keil,所以需要建里面的public改为EXPORT如下图所示。
另外还有段代码需要修改,否则编译不过。
IAR汇编:
RSEG CODE:CODE:NOROOT(2)
THUMB
Keil汇编:(这段不知)
AREA |.text|, CODE, READONLY, ALIGN=2
THUMB
REQUIRE8
PRESERVE8
修改完以上内容编译并下载进目标板,发现操作系统的函数都执行了,但是始终不能进入我们自己创建的任务。
3、始终不能进入我们的任务
我就出现这种情况,经调试现象是OSInit()、OSStart()、 OSTaskCreateExt()都已经执行。唯独就是第一个任务Task_Start()进不去。错误原因:
startup_LPC11xx.s的两个中断函数和uCOS-II的内核的中断函数定义的不相同。也就是uCOS-II自己定义的有相关中断,我们要用到uCOS-II的内核的中断函数。
修改如下: