- c语言中调用汇编
__asm__("b 0x8a000000");
__asm__ volatile ("blx OS_CPU_SR_Save")
其中 OS_CPU_SR_Save 是一个汇编函数,用了 .global OS_CPU_SR_Save 进行标识的。这个是可以成功调用的 - makefile编译过程中要想不输出编译展开的过程信息,那么加入-s参数即可
make -s - printf函数,%X即可按照十六进制方式打印
%x即按十六进制输出,英文字母小写,右对齐。
%02X有以下变化:英文字母变大写,如果输出字符不足两位的,输出两位宽度,右对齐,空的一位补0。超过两位的,全部输出。 - cortex-a内核的MX6ULL启动汇编文件xx.s中不需要用 IMPORT 或者 EXPORT 进行声明,不然反而报错,有意思,stm32就需要的
- 有符号数和无符号数之间的强制转换(这里指同位宽的,比如unsigned int和int互相转换),内存中的二进制实体内容不会有改变的。只是这个变量是什么类型,该变量对此处的二进制内容解读不一样罢了,但是二进制实体是一样的,所以不关心数的大小解读情况下,放心转
int a
unsigned int b
int c
a=-1 //内存中以补码就是1111111...1111存放的
b=a //此时b内存中仍然是1111111...1111,只是打印该变量时会认为是一个很大的数显示出来罢了
c=a //此时c内存中仍然是1111111...1111 - 汇编要么全部用大写,要么全部用小写,不然编译会报错
- cps指令,在特权模式(非用户模式)下使用,可以直接修改cpsr寄存器低5位的值
cps #0x13 进入SVC模式,允许其他中断再次进去,因此中断处理函数中仍然处于SVC模式 - 为了成功内联,__attribute__((always_inline)) static inline 才能保证一定内联,因为仅加一个,有些时候它就是不内联,__attribute__是gcc的关键字
- cortex-a内核的汇编和cortex-m的汇编不太一样,比如
a系列不支持分号作为注释,ldr加载立即数用=xx,subs等指令采用#xx,
- 发生中断时,lr 保存的是 pc 值(正在取指的值,由于三级流水线,这个是不能直接作为返回用的,用subs pc, lr, #4返回
- 我们让程序跳转可以直接赋值pc实现,虽然采用bl指令也是这样原理,但是bl指令可以自动装载lr寄存器,如果用blx,还会自动更新cpsr中T位
- 如果子函数调用,那么lr保存的就是真正的下一条指令的地址了,所以返回直接用 bx lr
- 全局变量更新,让 OSRunning=1
非常注意:因为 OSRunning 是u8型,所以只能把r2寄存器的低8位写给OSRunning,不然覆盖掉了多余的数据,程序崩掉了(真的会)
ldr r1, =OSRunning
ldr r2, =0x01
strb r2, [r1] - 任务栈的初始化很重要,因为第二个任务被切换到第一次运行时候,根据上下文切换,cpsr的值会从栈内载入
- ucosii在cortex-a7上面的移植,需要注意:
在#include "includes.h"头文件中加入内核相关的访问函数,比如imx6ul.h - 任务切换,我不用软中断等方式触发的话,是有些问题的,比如创建的启动任务,进入临界区,任务里面再创建其它任务,然后挂起自己,然后打开临界区。如下:
//开始任务
void start_task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
pdata = pdata;
OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断)
OSTaskCreate(led0_task,(void *)0,(OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);
OSTaskCreate(led1_task,(void *)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);
OSTaskSuspend(START_TASK_PRIO); //挂起起始任务.
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}
由于进入了临界区(关中断的实现方式),而退出临界区是恢复上一次的中断状态,也就是说如果该任务中没有退出临界区,那么中断就一直是关着的。而倒数第二行把自己挂起了,是不是说明任务切换,自己也不会继续往下执行,从而无法打开最开始的中断状态了呢,不是的,因为ucosii任务切换是靠进入中断实现的,而中断一直关着的,因为一直没法任务切换的。因此第一个任务一定会运行到最后的退出临界区,一旦恢复了以前的中断状态(最开始中断是打开的),那么之前想要触发任务调度软中断的,就会立刻进入,发生了任务切换。
所以为了和ucosii编程兼容,想任务切换,必须触发软中断,然后在软中断中完成任务切换的实现方式,才能符合上面的流程规定。 - ldmfd sp!, {r0-r12, pc}^ ; 中断返回, ^表示将spsr的值复制到cpsr
- cmp指令会影响到程序状态寄存器cpsr的bit 30位Z,Z=1代表比较结果为相等,然后ldreq指令就能执行喔
- 而swi软中断不属于IRQ中断,它不可以被关闭,而且会立即执行,只是用于我们处理器运行模式的切换罢了,以此来实现权限转换,访问cpu所有的寄存器。但是要想任务切换在中断中触发,得找一个可等待中断才行,就是IRQ中的软件中断(这个可以寄存器赋值,从而产生的正常外部中断,就可以用来做任务切换,因为swi软指令中断其实只是起到运行模式切换的作用罢了,然后在此特权模式svc模式下才能进行寄存器写,使得IRQ中的软中断触发,从而进行任务切换)
- 宏定义,有多行的表示方式,得加大括号
#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \
{ \
List_t * const pxConstList = ( pxList ); \
/* Increment the index to the next item and return the item, ensuring */ \
/* we don't return the marker used at the end of the list. */ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \
{ \
( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \
} \
( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \
}
嵌入式杂记(ucosii在cortex-a7 MX6ULL处理器上的移植笔记)
原创
©著作权归作者所有:来自51CTO博客作者biao2488890051的原创作品,请联系作者获取转载授权,否则将追究法律责任
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
CentOS 7安装docker
CentOS 7安装Docker
docker centos CentOS -
CORTEX-A7芯片中断系统基本原理与控制方法
大家好,今天主要和大家聊一聊,如何使用高端芯片的中断系统的方法。 中断系统是一个处
linux 中断向量表 外部中断 sed -
Linux之ARM Cortex-A7 中断系统详解【转】
Linux之ARM Cortex-A7 中断系统详解
中断向量表 外部中断 寄存器 中断向量 服务程序