×
单片机 > 单片机程序设计 > 详情

STM32F0非对齐访问引起的硬件错误及其排除

发布时间:2020-08-21 发布时间:
|

前段时间在用STM32L0芯片时遇到一个硬件错误,主要是内存的非对齐访问导致的。


注:CM3内核支持非对齐访问,而CM0不支持非对齐访问。


先科普一下,什么是非对齐访问

如上图所示,若要访问的变量是int、float、u32类型的(占4字节),则这些变量在内存中,只能以图中0、4、8为起始地址;


若要访问的变量是u16类型的(占2字节),则这些变量在内存中,只能以0、2、4、6、8、10为起始地址;


如上图所示,像*(u16 * )0x20000001这样读取数据的话,在CM0内核的芯片上就会直接进hardfault。


故事是这样的,我用了两片595来驱动数码管,用SPI方式。我想,反正一片595就是一个8位的移位寄存器,每次发送一个u8类型的数据要发送两次,我干嘛不把两个595当成一个16位的移位寄存器,发一个u16类型的数据就好了。所以我就把SPI初始化成这样:


 hspi1.Instance = SPI1;


 hspi1.Init.Mode = SPI_MODE_MASTER;


 hspi1.Init.Direction = SPI_DIRECTION_1LINE;


 hspi1.Init.DataSize = SPI_DATASIZE_16BIT;


和数码管有关的,我还定义了两个结构体


typedef   struct


{


         u8  buf[4];


         u8  no;


} Display_TypeDef;


 


typedef   struct


{


         u8   buf[2];


         u8   no;


} SPI_LED_TX_TypeDef;


Display_TypeDef               Display_structure;


SPI_LED_TX_TypeDef       SPILED_TxStructure;


然后定时器中断中,每隔一段时间往595发送数据,代码如下


void TIM1_CC_IRQHandler(void)


{


         u16capture = 0;


         HAL_TIM_IRQHandler(&htim1);


         capture= TIM_GetCapture1(TIM1);


         TIM_SetCompare1(TIM1,capture + 10);


         HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);


         if(Display_structure.no< 4)


         {


                   SPILED_TxStructure.buf[1]=   0x0a;


         }


         SPILED_TxStructure.buf[0]=   0x0b;                 


         HAL_SPI_Transmit_IT(&hspi1,SPILED_TxStructure.buf,1);  


}


除了初始化的代码,就上面这一小段代码,然而一运行,就直接跳到hardfault里面。


这个现象当时让我大为不解。在纠结了两个下午之后,终于知道了问题所在(原谅我第一次遇到hardfault)。


当出现hardfault这类异常时,在调试状态下,点开view中call stack window,如下图:

在HardFault_Handler处右击鼠标,见下图


选择Show Caller,会出现下图,即hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr)这句引起了Hardfault。

知道是哪里引起的就好办了,经过分析,发现*((uint16_t *)hspi->pTxBuffPtr)这里面的hspi->pTxBuffPtr就是指向0x20000005,引发了hardfault。让我们来看一下内存分布:


最后怎么搞定的呢。发现Display_TypeDef这个结构体占了5个字节,SPI_LED_TX_TypeDef这个结构体占了3个字节,把他们定义成如下就OK了:


typedef   struct


{


         u8  buf[4];


         u16  no;


} Display_TypeDef;


 


typedef struct


{


         u8  buf[2];


         u16  no;


} SPI_LED_TX_TypeDef;


恩,就写到这里把。坚持把工作遇到的一些问题记录下来。



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
STM32中断向量表的位置.重定向