问题描述:
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-17 11:36
推荐帖子
- Pt1000测量电路(精度为0.1°)
- 之前有了解过pt1000的测量电路,就是很不准确,求各位高人指点!file:///C:/Documents%20and%20Settings/Administrator/Application%20Data/Tencent/Users/372182098/QQ/WinTemp/GE/8C6B5CD2-B508-47B8-8B53-AEEBA13D57F7.jpgPt1000测量电路(精度为0.1°)这里有高人:https://bbs.eeworld.com.cn/thread-35473
- 林发扬 模拟电子
- EVC4.0编程环境,如何把变量文件名传入fopen?
- 两个菜鸟问题:1.找到别人的代码:intorder=0;AnsiStringfileName,path=c:\\\\temp\\\\;FILE*fp;fileName=path+IntToStr(++i)+AnsiString(.txt);fp=fopen(fileName.c_str(),w);但是在EVC下AnsiString,.c_str()都不可使用。麻烦大虾点播~~~2.同样的这类其他问题挺多,主要是要一个程序从
- qwer2006 嵌入式系统
- WINCE COM支持 CoCreateInstance API失败
- 在EVC下我写一个DeviceQuery的组件在另外一个DLL里写下面代码:HRESULThr=::CoCreateInstance(CLSID_IDeviceQuery,NULL,CLSCTX_ALL,IID_DeviceQuery,(void**)&m_IDeviceQuery);编译没有问题,但是跑起来就这个函数调用失败。说明:我PB中加入了COM支持,DeviceQuery也注册了。请教各位eeworld朋友,这是为什么?谢谢!WINCECOM支持CoCrea
- miko2007 WindowsCE
- 谁有XILINX的PCI开发板?有偿借用一周
- 帮朋友询问:XILINX的PCI开发板有偿借用一周因为是项目急用,所以如果有这个板子的朋友请帮帮忙谁有XILINX的PCI开发板?有偿借用一周没有帮顶!~有个朋友已经联系我了感谢大家关注。好像没有借用成功期待有这个板子的朋友继续帮忙回复板凳soso的帖子没有,继续帮顶继续等待...坛里面不是有SPARTAN的开发板吗?上面有PCI接口没有啊?帮顶,支持!!!有一块黄金串口卡,是XILINX的FPGA做的,但不是开发板,可以引出线
- soso FPGA/CPLD
- 请教:430软件por事件和bor事件的区别
- 软件por事件和bor事件有什么不同吗?设置了个标志位,当某个程序因为某种原因而未执行,就触发por事件,(正常情况,该程序有执行),但是,当触发了por事件后,程序有重新从头开始,而,前面的因为某种原因未执行的程序,依旧没执行,这是为什么?未执行的,por后依旧没执行么?请教:430软件por事件和bor事件的区别非常感谢啊!
- fish001 微控制器 MCU
- C2000晒晒 + 28335开发板
- 当年,想用28335的处理能力做个语音识别的板子,结果就有了这个实验板。配置是28335+CPLD,28335负责数据处理,CPLD负责显示驱动。那个时候不是STM32还没普及不是?呵呵,现在用着当开发板或者核心板还是不错的。 C2000晒晒+28335开发板惊为天人。为什么功能越强的芯片,外围器件越少呢板子很牛啊!带CPLD的显示部分LZ能不能共享原理图期待,楼主来共享
- ahuang227 微控制器 MCU
设计资源 培训 开发板 精华推荐
- LT1172CSW 的典型应用,1.25A 外部电流限制
- LTC2267-12 的典型应用 - 12 位、105Msps 低功耗双通道 ADC
- LT1767EMS8-3.3 12V 至 3.3V 降压转换器的典型应用电路
- REF196 低压差精密电流源的典型应用电路
- LT1021BCH-5 电压基准的典型应用,将 10V 单元调整为 10.24V
- NCV3063 1.5A 升压开关稳压器的典型升压应用原理图
- 使用 Analog Devices 的 LTC1479IG 的参考设计
- STM32F407VG核心板
- xmas_tree_usb_base:两节AAA电池输出5V USB的DCDC功能板
- 【涂鸦智能】温湿度传感器+897594A