你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F0非对齐访问引起的硬件错误及其排除

[复制链接]
STMCU小助手 发布时间:2021-11-23 21:00

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

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

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

/ e  w8 |- r4 ]0 Y4 }

20160928214051082.png

; i: n6 }) s& Z

如上图所示,若要访问的变量是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;


; Y. ~7 A3 s3 D

然后定时器中断中,每隔一段时间往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);  

}

) f5 x! m( o$ J! G. W

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

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

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

0 d. j. |0 ]5 y% S, N

. w5 K5 E5 y+ m) @
20160928214241812.png
7 S: d. z% Z7 u
5 r8 r. m' I* t$ g5 T2 s% Q1 ^' r

在HardFault_Handler处右击鼠标,见下图

+ c+ x. a7 [% Y  g( f4 Z( x

6 ?3 r3 ]& V! i; z; E  O
20160928214330489.png

% E9 d' W5 l" D9 V# f% J" B8 ^- C3 w- K2 [8 Y3 @3 f4 z0 I

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

! s  \6 _5 o$ \, \, r, C

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


9 l2 x, x; r* W/ f; W* O7 [

20160928214518271.png

0 f! T2 w( ?2 m7 e

$ w! K- d# z1 C1 L$ c

最后怎么搞定的呢。发现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;


& A4 n0 t0 n1 t- A1 z$ C5 y
4 [$ S# B  N9 T! U+ p7 |# F7 j
20160928214051082.png
20160928214433502.png
赞 收藏 评论0 发布时间:2021-11-23 21:00

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版