问题描述:
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];
上一篇:【STM32】解决引脚复用成PWM开漏输出峰值达不到外部上拉的电
下一篇:【STM32】Debug下禁用看门狗
推荐阅读
史海拾趣
摘要:使用无损吸收电路,能够提高硬开关PFC的工作频率,并降低开关损耗。应用全桥移相软开关技术,实现了DC/DC变换器的大功率输出。通过应用这两种技术,研制HF220/10型高频开关电源。 关键词:无损吸收PFC变换器ZVS?FB … 查看全部问答∨ |
|
公司找的外包软件公司需要direct3d功能,对此不了解,所以有几个问题想请教一下: 1、外包公司一直提到direct3d.dll,而WINCE5.0中有d3dm.dll,两者之间的关系是类似于MDD与PDD之间的关系还是同等关系? 2、看他们软件介绍是需要Pocket PC\\Windo ...… 查看全部问答∨ |
我按照网上查到的方法 用自己的程序替换掉了explorer.exe [HKEY_LOCAL_MACHINE\\Init] "Launch50"="myapp.exe" "Depend50"=hex:14,00,1e,00 编译的系统能够运行,并且程序全屏。 我的疑问是,我想在程序的界面中输入东西怎么办? ...… 查看全部问答∨ |
各位大侠大哥你们好,小弟近日在做界面修改时,发现界面上的图片都是通过bmptobin.exe去生成相应的*.h文件的,现在我想将图片从器件中拿出来,做修改后再放回去,我找了一些方法,但是网上介绍的说可以通过bintobmp和reEdit这个软件可以将里面的数 ...… 查看全部问答∨ |
|