[MsgOS]MsgOS相关帖子汇总
https://bbs.21ic.com/forum.php?mod=viewthread&tid=1607442&fromuid=1131700
(出处: 21ic电子技术论坛)
本帖介绍MsgOS中异常向量处理的相关部分。
对于大部分cortex-m3内核单片机软件工程,尤其是STM32F系列的,与异常相关的代码部分如下:
1.在由汇编编写的源文件中,弱定义一个中断向量表,且把大部分中断函数弱定义为死循环函数。
2.向量表首项为主堆栈初始值,是在汇编源文件中分配一段静态RAM区,将该内存段的尾地址作为向量表首相。
3.向量表第二项为复位向量,一般会先调用时钟初始化再调用_main。
4.有一对专门为重定义中断函数的.c和.h源文件,实际的中断响应函数都在此文件中进行重定义,函数名要和汇编中对应一致。
MsgOS中对异常向量是这样处理的,
1.os_vector.c源文件中定义了中断向量表,但只包括前16个系统异常。系统异常响应函数是在汇编中实现的,后面的外设中断只是由宏VECTOR_REG(handler,IRQn)来定义的。
2.为了最大化利用芯片RAM空间和最大化主堆栈空间,主堆栈初始化值是由芯片RAM区尾地址确定的。
3.复位向量只调用了_main函数,避免了不同芯片时钟初始化的差异性,及系统复位后只使用硬件默认时钟,修该系统时钟的驱动应该到应用层再去调用。
4.具备对系统异常hardfault、memmanage, busfault和usagefault的分析处理功能,便于异常原因分析和判断。
5.滴答定时器(systick)用于内核心跳中断,可悬起系统调用(pendsv)
os_vector.c源文件现有的内容为以下部分
1.系统异常向链表定义
2.向量表初始化
3.系统异常处理
os_asm.asm源文件主要内容如下
1.系统异常响应处理
2.时间轴打点函数
3.微库适配处理
向量表初始化中会获取实际系统中断优先级位数和实际外部中断个数,会将中断响应优先级全设置为抢占优先级。凡是与系统向量表及前16个系统异常相关的操作都应由MsgOS来处理,其余的外设中断则应该做为驱动部分来编写,通过CPU_NVIC_SetPriority设置优先级,CPU_NVIC_EnableIRQ来允许中断,VECTOR_REG来注册中断。
这样做一是减少了存储消耗,只有用到的外部中断才会占用空间;二是和具体的单片机型号无关了,模块化和可移植性得以提高,因为每一种具体型号单片机其外设中断都是不同的,预定义的那个中断向量表必定需要和芯片型号关联。
以串口中断处理为例,源码如下:
void UART1_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE);
/* 配置 USART1_TX PA.9 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 配置 USART1_RX PA.10 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* USARTx configuration ------------------------------------------------------*/
/* USARTx configured as follow:
- BaudRate = 115200 baud
- Word Length = 8 Bits
- One Stop Bit
- No parity
- Hardware flow control disabled (RTS and CTS signals)
- Receive and transmit enabled
*/
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No ;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
USART_ClearFlag(USART1,USART_FLAG_TC);//防止无法输出复位后的首字符
USART_Cmd(USART1, ENABLE);
/* Enable the USART2 Interrupt */
CPU_NVIC_SetPriority(USART1_IRQn,0);//设置串口1中断优先级为0
CPU_NVIC_EnableIRQ(USART1_IRQn);//允许串口1中断
}
void USART1_IRQHandler(void)
{
char c;
//接收中断
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //判断是否为串口1接收到数据中断
{
c=USART_ReceiveData(USART1); //读取USART接收到的数据
if(uart_recv_uart1.length<256)
{
uart_recv_uart1.buf[uart_recv_uart1.position_irq++]=c;
uart_recv_uart1.length++;
}
USART_ClearITPendingBit(USART1, USART_IT_RXNE); //清除中断标志
}
}
VECTOR_REG(USART1_IRQHandler,USART1_IRQn);//注册串口1中断响应函数
|