历史上的今天
今天是:2024年09月03日(星期二)
2021年09月03日 | 【STM32】HAL库调用HAL_SPI_Transmit出现HartFault问题
2021-09-03 来源:eefocus
问题描述:
HAL库调用硬件SPI发送函数HAL_SPI_Transmit会导致程序进入HartFault
// flash 页大小(字节)
#define FLASH_SPI_PAGE_SIZE (256)
static uint8_t write_buffer[FLASH_SPI_PAGE_SIZE + 4];
spi1_write(W25QXX_CHANNEL, (uint8_t *)write_buffer, (length + 4));
/**
* @brief SPI写入
* @param *txBuffer 发送字节集
* @param txLength 发送长度
* @return spi发送的长度
* */
uint32_t spi1_write(SPIChannel channel, uint8_t *txBuffer, uint32_t txLength)
{
if(channel == W25QXX_CHANNEL)
{
W25QXX_CHANNEL_ON;
}
HAL_SPI_Transmit(&hspi2, txBuffer, txLength, 500);
if(channel == W25QXX_CHANNEL)
{
W25QXX_CHANNEL_OFF;
}
return txLength;
}
原因分析:
Debug发现进入HartFault之前最后一句话是

是该揭开它真正面纱的时候了:我们再看出现问题的那条语句:
hspi->Instance->DR = *((uint16_t *)pData);
再看我们数组的定义:uint8_t
出现问
题这条语句把我们定义的uint8_t 数组转换成了uint16_t 同时进行半字的操作(同时操作两个byte)。这样看确实提高了执行效率,但是却也埋下了隐患。
产生这样的问题,我们就不得不扯得更远一点,arm内核对数据的非对齐数据访问。
Arm对内存的访问支持字(4byte)、半字(2byte)、字节(1byte)的直接访问,但是呢他们是有一定的要求的:
存取字时要求地址按字对齐,也就是地址要是4的整数倍,如0x0000、0x0004、0x0008(该地址只是举例,mcu的地址分配请参考具体手册的地址映射图)
存取半字是要求地址按半字对齐,也就是地址是2的倍数,这样假如通过0x0001、0x0003这样非2倍数的地址来读取一个半字就会产生错误
存取字节简单,只要地址不超范围就可以
这么看来是不是有点清晰了,我们出现错误的地方不就是在操作一个半字(uint16占用两个byte也就是半字),那么进入到了hardfault应该就是操作了非半字对齐的地址。
下面我们将write_buffer地址打印出来:
rtt_printf("0x%08xn",write_buffer);

很显然,这个地址并不是非半字对齐的地址。
解决方案:
将write_buffer定义成uint32_t即四字节对齐即可。
static uint32_t write_buffer[(FLASH_SPI_PAGE_SIZE + 4 )>>2];
史海拾趣
|
用定时器1做的简单输出,友善micro2440的板子 请帮我分析下,搞了好长时间,还是出不来 流驱动:#include \"options.h\" #include #include #include #include #include #include #include #include #include \"time.h\" ...… 查看全部问答> |
|
请问一下各位 学校里学的C语言和单片机C语言(C51)有啥子不一样的?哪个好学一点. 在学校里学了C语言后感觉没有学到啥子,挺浮浅的,现在只记得一些简单的规则和语法。 不知道现在是继续学它基础打扎实点呢,还是就开始学C51,希望大家给点建 ...… 查看全部问答> |
|
在WINCE60里面把CELLCORE组件加进了NK,怎么测试这块是不是可以正常工作?有没简单的测试AP可用?怎么测试RIL组件绑定了物理通信的串口? 在WINCE60里面把CELLCORE组件加进了NK,怎么测试这块是不是可以正常工作?有没简单的测试AP可用?怎么测试RIL组件绑定了物理通信的串口?… 查看全部问答> |
|
ppc2003可以直接访问sql2000 server中的数据吗? ppc2003通过wifi跟局域网连接后,可以通过编程直接访问服务器上sql2000 server中的数据吗?有人说必须在ppc上安装sql CE,然后通过sql CE跟服务器上的sql2000交换数据?真的是这样?… 查看全部问答> |
|
2010年度吉时利测试测量技术全国巡回研讨会将从9月初开始,在成都、重庆、合肥、南京、哈尔滨、武汉、兰州举办届时吉时利资深技术专家将与您深入交流: 绿色电子革命中的光电测试/新能源测试方案 新材料的测试方案 微弱信号测量难点与应对方 ...… 查看全部问答> |
|
使用uC2.86 ADC使用DMA中断的模式,在DMA1_CH1 初始化以及 中断 都没问题,都可以进中断, 但是改成 DMA1_CH4 就再也不进中断了,为什么?? 难道 DR_ADDRESS 地址不对?? RCC,等其他设置应该都没问题请大家看下我的初始化函 ...… 查看全部问答> |
|
最近在调STM8 的I2C(不想搞模拟的I2C),结果I2C没有调通,不知道问题所在,软件是参考I2C EEPROM固件那个程序写的。初始化如下: void IIC_Init(void) { UCHAR temp; CLK_PCKENR1 |= 0x01; I2C_CR1 = 0x00; &n ...… 查看全部问答> |
|
本帖最后由 dontium 于 2015-1-23 12:51 编辑 我这两天用面包板按照vca810芯片的datasheet中的figure2 电路搭建了一个压控放大,将8脚的50欧姆电阻去掉,并在8脚加了一个vpp=30mv,f=800hz的正弦波(函数发生器产生),并在1脚直接接地。但是在Vc= ...… 查看全部问答> |
|
《TMS320C28x系列DSP》读书笔记--通用目标文件格式,段 TMS320系列DSP的目标文件各式为通用目标文件格式 COFF (Command Object File Format,简称COFF)。 采用这种目标文件各式的优点是:将指令和数据按照段的概念进行组织和存储,这使得程序的可读性大大增强,更容易编写 ...… 查看全部问答> |




