最近调试磁铁驱动程序时,遇到一个奇怪的情况:(问题描述在下边这个帖子中)
OSTimeDly在ucos最高优先级任务中,多次使用,有什么说法?
只是知道问题大概出现在哪块,没找到出现这种状况的理由。顺带着理清楚一些基本的常识性的东西。如下:
基本概念:
AHB:Advanced High performance Bus,先进的高性能总线,这是一种“系统总线”。AHB 是在地址/控制阶段和数据阶段之间具有固定流水线的总线协议。它只支持由
AMBA AXI 协议提供的功能性的子集。 完全的 AMBA AHB 协议规范包括许多对于主机和从机 IP 开发来说不是必需的属性,因此 ARM 公司建议通常只使用该协议的子集。这个子集定义为 AMBA AHB-Lite协议。
AMBA:Advanced Microcontroller Bus Architecture,先进的微控制器总线架构(AMBA),AMBA是描述互连策略的协议规范系列。它是 ARM 公开的片内总线标准,该片内总线规范详述了互连策略以及对组成片上系统(SoC)的功能模块的管理。它协助带有一个或多个 CPU或信号处理器和多个外设的嵌入式处理器的开发。 AMBA 通过定义一个用于 SoC 模块的通用骨干(backbone)来对可重复使用的设计方法作了补充。
SoC:System on Chip片上系统
APB:Advanced Peripheral Bus,先进的外设总线(APB) 。APB 是一个比 AXI 和 AHB 相对简单的总线协议。它是为配件,或诸如定时器、中断控制器、UART、I/O 口等通用外设而设计的。它与主要系统总线的连接是通过系统到外设总线桥来实现的,这样有助于降低系统功耗。
AHB-AP:AHB Access Ports,AHB 访问端口(AHB-AP) 。
AHB-Lite:AHB-Lite 是完全的 AMBA AHB 协议规范的子集。它提供大多数 AMBA AHB 从机和主机设计所必需的所有基本功能,尤其是与多层 AMBA 互连一起使用时。
内核:内核是处理器的一部分,包含 ALU,数据路径,通用寄存器,程序计数器以及指令译码和控制电路。
PLL:phase locked loop,锁相环。PLL的作用主要有频率合成和CDR(时钟数据恢复)。
HSI:High Speed Internal Clock Signal,高速内部时钟信号。
HSE:High Speed External Clock Signal高速外部时钟信号。
系统时钟配置:
void BSP_Init (void)
{
BSP_IntInit();
RCC_DeInit(); /*将外设RCC寄存器重设为缺省值 */
RCC_HSICmd(ENABLE); //使能内部高速晶振
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)== RESET);//等待HSI就绪
RCC_HCLKConfig(RCC_SYSCLK_Div1); /*设置AHB时钟(HCLK) RCC_SYSCLK_Div1——AHB时钟 = 系统时*/
RCC_PCLK2Config(RCC_HCLK_Div1); /* 设置高速APB时钟(PCLK2)RCC_HCLK_Div1——APB2时钟 = HCLK*/
RCC_PCLK1Config(RCC_HCLK_Div2); /*设置低速APB时钟(PCLK1)RCC_HCLK_Div2——APB1时钟 = HCLK / 2*/
FLASH_SetLatency(FLASH_Latency_2); /*设置FLASH存储器延时时钟周期数FLASH_Latency_2 2延时周期*/
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); /*选择FLASH预取指缓存的模,预取指缓存使能*/
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_16);/*设置PLL时钟源及倍频系数,频率为8/2*16=64Mhz*/
RCC_PLLCmd(ENABLE); /*使能PLL */
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) ; /*检查指定的RCC标志位(PLL准备好标志)设置与否*/
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK); /*设置系统时钟(SYSCLK) */
while(RCC_GetSYSCLKSource() != 0x08);
/*驱动初始配置*/
OC_SPI_Init();
DrawerInterfaceInit();
//ReadFlash();
CAN_Config();
initStruct();
OC_LED_Ctrl(0x0000);
}
不多解释,强调使用内部时钟作为系统时钟。内核时钟频率64MHz。
估算一段延时函数的时间:
for(u16 i=0;i<50000;i++);
反汇编:
for(u16 i=0;i<50000;i++);
<span style="background-color: rgb(51, 255, 51);">0x8001fa6: 0x2000 MOVS R0, #0</span>
for(u16 i=0;i<50000;i++);
??<span style="background-color: rgb(255, 255, 0);">drawerStateCtr_0:
0x8001fa8: 0xf24c 0x3150 MOVW R1, #50000 ; 0xc350
0x8001fac: 0xb280 UXTH R0, R0
0x8001fae: 0x4288 CMP R0, R1
0x8001fb0: 0xd201 BCS.N ??drawerStateCtr_1 ; 0x8001fb6</span>
for(u16 i=0;i<50000;i++);
<span style="background-color: rgb(255, 0, 0);"> 0x8001fb2: 0x1c40 ADDS R0, R0, #1
0x8001fb4: 0xe7f8 B.N ??drawerStateCtr_0 ; 0x8001fa8</span>
bitsClear(num);
??drawerStateCtr_1:
0x8001fb6: 0x0020 MOVS R0, R4
0x8001fb8: 0xb2c0 UXTB R0, R0
0x8001fba: 0xf7ff 0xffb8 BL bitsClear ; 0x8001f2e
涉及到的指令 及其 相应的周期数(内核周期):
MOVS 1+P1
MOVW 1
UXTH 1
CMP 1+P1
BCS.N 1+P1
ADDS 1+P1
B.N 1+P1
其中,P1=流水线重载。
可知for延时的大概内核周期数:至少 = 1+6*50000=300000个内核周期;-----这么算有问题没?待定....
(300000*1/72000000)*1000=4.17ms
关于延时可以参见:STM32在系统时钟为72M下的几个延时函数—V3.5库
其他:
Cortex-M3 处理器内核采用 ARMv7-M 架构,
关于指令的流水线:采用三级流水线
参见: ARM流水线
对于cortex-M3 处理器:
时钟周期=1/内核时钟频率;
机器周期约等于1个时钟周期;
指令周期:执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需的机器周期也不同。
这几个概念,对于cortex-M3来说,未必这样子,以上纯属个人理解。
..........................