问题描述:
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下禁用看门狗
推荐阅读最新更新时间:2024-11-10 17:17
推荐帖子
- Hi-Fi/AV放大器维修图集 486页
- Hi-Fi/AV放大器维修图集486页
- wzt 电源技术
- 有偿服务:使用ucgui设计一个界面,有经验者进
- 因最近手上任务比较多,再加上对ucgui不是很熟悉,所以想把一个项目的GUI界面外包出去,可以使用ucgui模拟器实现,我自行移植即可。有意者请加QQ:570101566了解详细需求。有偿服务:使用ucgui设计一个界面,有经验者进ucguibuider 还需要对应的响应函数哈。不仅仅是界面
- fengxu0217 实时操作系统RTOS
- 低价出 AM3359的开发板,和一块 三星4412开发板
- 照片如图,一块AM359的 带屏幕,九成新,资料不怎么齐全,目前只有linux部分的,但是够用。不适合入门学习。300元一块三星4412的,cortexA9四核,基本全新,资料齐全,有入门资料,适合入门者学习。500元可以淘宝交易需要的联系QQ429512065本站强荐:185娱乐R城.足球R真_人.彩票齐全R手机可投R注任何游戏.首次开户送10元.首存送58元.信誉绝对保证185.cc低价出AM3359的开发板,和一块三星4412开发板大概有什么资料也得截
- 2638823746 淘e淘
- 内存泄漏,请帮忙看看问题出在哪里?
- voidCRS2USBDlg::OnTimer(UINTnIDEvent){//TODO:Addyourmessagehandlercodehereand/orcalldefaultHKEYhKey=HKEY_LOCAL_MACHINE;DWORDnumSubKey=0;DWORDi;DWORDsizeSubKey;
- BlueSummer 嵌入式系统
- 问个傻傻的问题
- 一直没太明白keil编译时全局变量是存放在哪个区的,今天在程序里面试了下,定义几个全局变量后,code区的大小一直未变,倒是Xdata区的变大了。我的理解是这样的,在编译的时候,不也应该在代码区给全局变量分配地址吗,这样程序运行过程中才可以找得到这个变量。如果定义在xdata区,又因为xdata不是属于ram区吗,掉电后不是会丢失?现在全迷糊了,以前没考虑过这么多,乱了!!!问个傻傻的问题变量不管是什么类型都是处于RAM中,Code区是程序代码存放的地方,只能定义程序区的常量。XD
- ena 51单片机
- 430F149键盘中断问题,急!!
- 键盘采用中断方式,可是我按键盘后,程序没反映,跟踪时有键盘的值,在P1键盘中断中,先判断键盘的值,再做标志位,然后在主程序根据标志位来完成任务!现在不知道是什么问题,多按几下却能够得到响应的希望结果,现在请问专家和高手们,你们的键盘是做如何处理的,能否发个简短的程序啊!430F149键盘中断问题,急!!程序贴来看看~查询!! 引用: 键盘采用中断方式,可是我按键盘后,程序没反映,跟踪时有键盘的值,在P1键盘中断中,先判断键盘
- transhuman 微控制器 MCU
设计资源 培训 开发板 精华推荐
- LTC3456,采用 4mm-4mm QFN 封装的完整 2 节 AA/USB 电源管理器
- LT3976IMSE 2.5V 降压转换器的典型应用电路
- NCV33074ADR2G 交流耦合反相放大器典型应用
- 用于电机控制的 24W、24V 交流转直流单输出电源
- 使用 Analog Devices 的 LT4276BIUFD 的参考设计
- 使用 ROHM Semiconductor 的 BD49L36G-TL 的参考设计
- B数显示器
- LT3089IR 负载均分不带镇流电阻器的典型应用电路
- 带有四路信号开关的 ADP1190 集成 500mA 负载开关的典型应用
- NeuroStimDuino:面向对神经科学感兴趣的学生、研究人员和爱好者的开源神经刺激器