您好!
我已经有一个正常工作的中断驱动 SSI 来与 Winbond 闪存通信、最近我已经进入了 DMA 的领域。 我认为最好将其与 Winbond 代码相结合、以加快数据传输速度并降低 CPU 负载。 有人以前做过吗? 我在论坛上似乎找不到任何有关这方面的信息。
目前、我已经创建了一个 SPI_TRANSFCTION 函数、调用该函数时、将首先设置和传输命令/地址字节。 然后、在 DMA 传输完成后、SSI ISR 将被触发。 触发后、ISR 将设置另一个 DMA 传输、以便写入/读取我们感兴趣的数据字节。
例如、如果我要读取 Winbond 闪存的器件 ID 和制造商 ID。 闪存要求主器件发送 Wb_read_ID、后跟3个0x00字节、然后闪存将输出器件 ID +制造商 ID。 下面是一个用于说明传输的图:
XX =无关
//传输4个数据字节,需要两个字节的设备 id +制造商 id
TX RX
WB_READ_ID XX --
0x00 XX |___ 在第一个 DMA 传输期间传输
0x00 XX |
0x00 XX --
//主设备需要驱动时钟以允许将 man_id 和 dev_id 移出
0x00 man_id --______ 在第二个 DMA 传输期间传输
0x00 DEV_ID __|
我的代码如下:
//通过首先传输 cmd / addr 字节来启动传输
// // //通过传输命令/地址字节来启动与闪存的通信 // ************* void SSI_transfer (uint8_t * cmd_buf、uint32_t cmd_count、uint8_t * tx_buf、 uint32_t TX_COUNT、uint8_t * rx_Buf、uint32_t rx_count){ G_ui8SSITxBuf = TX_Buf; G_ui8SSIRxBuf = Rx_Buf; G_ui32SSITxCount = TX_COUNT; G_ui32SSIRxCount = Rx_COUNT; // //为 TX 和 RX 通道启用 uDMA 接口。 // SSIDMAEnable (SSI0_BASE、SSI_DMA_RX | SSI_DMA_TX); // //uDMA SSI0 RX // // //将 UDMA SSI0RX 通道的属性置于已知状态。 这些 默认情况下、//应已禁用。 // uDMAChannelAttributeDisable (UDMA_CHANGE_SSI0RX、 UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT | (uDMA_attr_high_priority | uDMA_attr_REQMASK); // //为配置主控制结构体的控制参数 // SSIORX 通道。 // uDMAChannelControlSet (UDMA_CHANGE_SSI0RX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_4); // //设置 SSI0RX 通道的传输参数 // uDMAChannelTransferSet (UDMA_CHANGE_SSI0RX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、 (void *)(SSI0_BASE + SSI_O_DR)、 CMD_BUF、 CMD_COUNT); // //uDMA SSI0 TX // // //将 UDMA SSI0TX 通道的属性置于已知状态。 这些 默认情况下、//应已禁用。 // uDMAChannelAttributeDisable (UDMA_CHANGE_SSI0TX、 UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIOR| UDMA_ATTR_REQMASK); // //配置 SSI0 TX 的控制参数。 // uDMAChannelControlSet (UDMA_CHANGE_SSI0TX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_4); // //设置 uDMA SSI0 TX 通道的传输参数。 这将会 //配置传输源和目的以及传输大小。 //使用基本模式是因为外设正在进行 UDMA 传输 //请求。 源是 TX 缓冲区、目的是 SSI0 //数据寄存器。 // uDMAChannelTransferSet (UDMA_CHANGE_SSI0TX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、 CMD_BUF、 (void *)(SSI0_BASE + SSI_O_DR)、 CMD_COUNT); //开始发送命令/地址字节并弹出返回字节 CHIP_SELECT (~GPIO_PIN_3); // //现在,UDMA SSI0 TX 和 RX 通道都要以启动 A 为底 //传输。 一旦启用通道、外设将会启动 //发出传输请求,数据传输将开始。 // uDMAChannelEnable (UDMA_CHANGE_SSI0RX); uDMAChannelEnable (UDMA_CHANGE_SSI0TX); // //启用 SSI0 DMA TX/RX 中断。
//我是否还需要包括 SSI_DMATX? // SSIIntEnable (SSI0_BASE、SSI_DMARX); //等待 SSI 芯片选择无效、表示结束 //传输。 while (!(GPIOPinRead (GPIO_Porta_base、GPIO_PIN_3)& GPIO_PIN_3)); }
// ISR
void SSI0IntHandler (void){ GPIOPinWrite (GPIO_PORTB_BASE、GPIO_PIN_2、GPIO_PIN_2);//指示 ISR 条目
uint32_t ui32Status; uint32_t ui32模式; ui32Status = SSIIntStatus (SSI0_BASE、1); SSIIntClear (SSI0_BASE、ui32Status); if (g_cmd_sent){ CHIP_SELECT (GPIO_PIN_3); } 否则{ //在此处输入意味着命令/地址字节已发送 //为我们感兴趣的数据设置另一个传输 G_CMD_SENT = 1;//发送命令和 addr 的信号,以便在接下来发送 // ISR 入口将拉高 SS 线路 ui32Mode = uDMAChannelModeGet (UDMA_CHANGE_SSI0RX | UDMA_PRI_SELECT); // RX DMA 完成 //如果是写入、g_rx_dst_inc 将为 UDMA_dst_inc_none //如果读取、g_rx_dst_inc = uDMA_dst_inc_8 if (ui32Mode = udma_mode_stop){ uDMAChannelControlSet (UDMA_CHANGE_SSI0RX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | G_Rx_DST_inc | UDMA_ARB_4); uDMAChannelTransferSet (UDMA_CHANGE_SSI0RX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、 (void *)(SSI0_BASE + SSI_O_DR)、 G_ui8SSIRxBuf、 g_ui32SSIRxCount); uDMAChannelEnable (UDMA_CHANGE_SSI0RX); } // TX DMA 完成 //如果是写入、g_TX_DST_inc 将为 UDMA_SRC_INC_8 //如果读取、g_TX_src_inc = UDMA_SRC_INC_NONE if (!uDMAChannelIsEnabled (UDMA_CHANGE_SSI0TX)){ uDMAChannelControlSet (UDMA_CHANGE_SSI0TX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | G_TX_src_inc | UDMA_DST_INC_NONE | UDMA_ARB_4); uDMAChannelTransferSet (UDMA_CHANGE_SSI0TX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、 G_ui8SSITxBuf、 (void *)(SSI0_BASE + SSI_O_DR)、 g_ui32SSITxCount); uDMAChannelEnable (UDMA_CHANGE_SSI0TX); } } GPIOPinWrite (GPIO_PORTB_BASE、GPIO_PIN_2、~GPIO_PIN_2);//指示 ISR 退出 }
因此、我的问题是、当我单步调试程序时、我将获得正确的 man_id 和 dev_id (0xef 和0x17)、但当我执行完整运行时、ID 是错误的(0x90、0xff)。 以下是逻辑分析仪上完整运行的屏幕截图:
如屏幕截图中所示、SS 线路被拉至高电平的时间太短、我不确定原因。
为了确保 DMA 工作正常、我还尝试在一个 DMA 传输中传输所有数据、而不是在两个 DMA 传输中传输(如前所述)、这为我提供了正确的结果、如下面的屏幕截图所示:
我是否缺少或不正确理解 UDMA?
此致、提前感谢您
Jacky