现象: 将外部 Flash 挂载在 SPI,在 hardware_init() -> read_jedec_id()
里的 result = spi->wr(spi, cmd_data, sizeof(cmd_data), recv_data, sizeof(recv_data))
中, recv_data
的值经常不一致,result 的值偶尔为 SFUD_SUCCESS
, 大部分会 Error。
备注: 正常情况下,
recv_data
的值为[0x68, 0x40, 0x15]
。
原因: 由于当初我是以 GY 的移植版本为模板进行移植的,有些函数我是直接拷贝过来。问题在于,我用的 RTT 版本与 GY 的版本不一致,我的是 RTT 5.X,GY 的是 4.X。这两个版本在 rt_hw_spi_device_attach()
的参数设置上发生了变动。我当初发现参数个数不一致,就只是简单地删掉一参数。
两种版本的接口对比:
// RTT 4.X
rt_err_t rt_hw_spi_device_attach(struct rt_spi_device *device, const char *name,
const char *bus_name, void *user_data);
// RTT 5.X
rt_err_t rt_hw_spi_device_attach(const char *bus_name, const char *device_name, rt_base_t cs_pin);
解决办法: 将如下语句进行替换:
//if(rt_hw_spi_device_attach(SPI_BUD_NAME, SPI_DEVICE_NAME, GPIO_PIN_12) != RT_EOK)
if(rt_hw_spi_device_attach(SPI_BUD_NAME, SPI_DEVICE_NAME, 0x1C) != RT_EOK)
排查思路记录:
1)首先排查数据与预期不一致在哪个环节。使用示波器,发现示波器的数据显示跟 IDE 的数据显示一致。即 IDE 的数据为总线实时数据。
2)由 1)可以知道,SPI 的输入输出引脚 MOSI 与 MISO 均无问题。SPI 总共就 4 个引脚,还有 CS 引脚 跟 SCK 始终引脚。时钟引脚关系与 Read、Write 关系不大,定位是 CS 引脚不一致的问题。
3)看原理图,SPI CS 引脚 挂载在开发版的 PB12 引脚上。我们看到 rt_hw_spi_device_attach()
的第 5 个参数即是 CS 引脚的地址。
4)如何确定 PB12 的地址是个问题。Finsh 有 Pin 的相关命令。在 Finsh 里输入 pin
命令,会出现帮助文档。我们在工程文件夹下搜索文档内的几个功能语句,如 pin num
,发现 pin 命令调用的实现都在 pin.c
文件,里面有命令对应的代码及注释。阅读文件,我们知道,可以通过 Finsh 命令 pin num PB.12
获取 PB12 的地址,值为 28
,对应的十进制地址为 0x1C
。
备注:其中要看 stm32f411 的数据手册、W25Q16 的数据手册(其中重要的是 8.3.12)、原理图。要看懂 drv_spi.c,drv_gpio.c 跟 引脚交互的逻辑。
示波器调试总结
1)我们知道是在 read_jedec_id()
出了问题。在 W25Q16 的数据手册查关键字 JEDEC ID
相关信息。文字描述道第一个字节是 instruction data,在调试中,发现变量 cmd_data
确实是 9Fh;后面的 3 个字节对应 recv_data
, 在调试中,发现变量 recv_data
确实有 3 个元素。
同时,文字也说到,指令是 CS 的下降沿引起的。我们在排查问题的时候,也可以直接怀疑是 CS pin 的值不对。
- 对应 8.3.12 Read JEDEC ID(9F)。我们在用示波器调试的时候,要清楚开始采样的点是在哪里。然后才知道哪里对应 DI 的 Instruction 部分,哪里对应 DO 的 Manufacture ID。反正这里 4 根线的信号都非常重要。
标签:rt,引脚,Flash,stm32,SPI,device,spi,data From: https://www.cnblogs.com/MasterBean/p/18183148了解 SPI 的 4 种传输模式:https://www.cnblogs.com/gmpy/p/12461461.html