您好!
我尝试使用 DMA TX/RX 将 SSI 设置为四路模式、但遇到了中断处理程序问题。 只要我调用 SSIIntEnable (SSI1_base、SSI_DMATX)、我的中断处理程序就会不停地关闭。
我在另一个主题中发现了看起来完全相同的问题:
https://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/361916
并已尽我所知、尝试了该主题中建议的所有内容、并参考了勘误表、其中指出:
以下是我的初始化代码:
void Board_initQSSI (uint32_t SYSCLK_Freq、uint32_t baud _rate) { //启用 QSSI 外设(使用 QSSI1上的端口 B、D、E) MAP_SysCtlPeripheralEnable (SYSCTL_Periph_SSI1); MAP_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOB); MAP_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOD); MAP_SysCtlPeripheralEnable (SYSCTL_Periph_GPIOE); //通过复用设置实现引脚功能。 这个宏被映射到 ROM_MAP.h 内的 GPIOPinConfigure // GPIOPinConfigure 在 GPIO.c 中为 def MAP_GPIOPinConfigure (GPIO_PB5_SSI1CLK); MAP_GPIOPinConfigure (GPIO_PB4_SSI1FSS); MAP_GPIOPinConfigure (GPIO_PE4_SSI1XDAT0); MAP_GPIOPinConfigure (GPIO_PE5_SSI1XDAT1); MAP_GPIOPinConfigure (GPIO_PD4_SSI1XDAT2); MAP_GPIOPinConfigure (GPIO_PD5_SSI1XDAT3); //引脚操作设置。 这个宏被映射到 ROM_MAP.h 内的 GPIOPinTypeSSI // GPIOPinTypeSSI 在 GPIO.c 中为 def MAP_GPIOPinTypeSSI (GPIO_PORTB_AHB_BASE、GPIO_PIN_4 | GPIO_PIN_5); MAP_GPIOPinTypeSSI (GPIO_PORTD_AHB_BASE、GPIO_PIN_4 | GPIO_PIN_5); MAP_GPIOPinTypeSSI (GPIO_Porte AHB_BASE、GPIO_PIN_4 | GPIO_PIN_5); //禁用 QSSI MAP_SSIDisable (SSI1_BASE); //针对 QSSI (高级)模式设置为 SPI 模式0;设置主模式 MAP_SSIConfigSetExpClk (SSI1_base、SYSCLK_Freq、SSI_FRF_MOTO_MOTO_0、SSI_MODE_MASTER、BAUD_RATE、 8); //启用高级模式 MAP_SSIAdvModeSet (SSI1_base、SSI_ADV_MODE_Quad_Read); //用虚拟数据模式填充 TX 缓冲区 G_ui8TxBuf[0]= 0xAB; //在系统级别启用 uDMA 控制器。 MAP_SysCtlPeripheralEnable (SYSCTL_Periph_UDMA); //启用 UDMA 控制器。 map_uDMAEnable(); //指向控制表以用于通道控制结构体。 map_uDMAControlBaseSet (dmaControlTable); //map_uDMAChannelAssign (UDMA_CHANGE_SSI1RX); //map_uDMAChannelAssign (UDMA_CHANGE_SSI1TX); //将 UDMA SSI1TX 通道的属性置于已知状态。 MAP_uDMAChannelAttributeDisable (UDMA_CHANGE_SSI1TX、 UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIOR| UDMA_ATTR_REQMASK); MAP_uDMAChannelAttributeEnable (UDMA_CHANGE_SSI1TX、UDMA_ATTR_USEBURST); //配置 SSI1 TX 的控制参数。 UDMA SSI TX //通道用于将数据块从缓冲区传输到 SSI。 //数据大小为8位。 源地址增量从开始为无 //数据是虚拟写入以生成时钟。 目的增量为 //由于数据将被写入 SSI 数据寄存器,因此不存在。 。 //仲裁大小设置为1024。 //1. MAP_uDMAChannelControlSet (UDMA_CHANGE_SSI1TX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1024); //设置 uDMA SSI TX 通道的传输参数。 这将会 //配置传输源和目的以及传输大小。 //使用基本模式是因为外设正在进行 UDMA 传输 //请求。 源是 TX 缓冲器、目的是 SSI //数据寄存器。 // //注释掉,因为我们还不想设置传输参数 //直到我们准备好开始发送 /*MAP_uDMAChannelTransferSet (UDMA_CHANGE_SSI1TX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、g_ui8TxBuf、 (void *) SSI1_base、 sizeof (g_ui8TxBuf));*/ //将 UDMA SSI1RX 通道的属性置于已知状态。 MAP_uDMAChannelAttributeDisable (UDMA_CHANGE_SSI1RX、 UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIOR| UDMA_ATTR_REQMASK); MAP_uDMAChannelAttributeEnable (UDMA_CHANGE_SSI1RX、UDMA_ATTR_USEBURST); //为配置主控制结构体的控制参数 // SSI1 RX 通道。 主控制结构体用于"A" //部分乒乓接收。 传输数据大小为8位 //源地址不会递增,因为它将从读取 //寄存器。 目的地址增量是字节8位字节。 。 //仲裁大小设置为1024。 //1. MAP_uDMAChannelControlSet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1024); //为的替代控制结构配置控制参数 // SSI1 RX 通道。 副控制结构体用于"B" //部分乒乓接收。 配置与相同 //主/A 控制结构。 MAP_uDMAChannelControlSet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT、 UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_1024); //设置 SSI RX 主控件的传输参数 //结构。 模式设置为乒乓模式、传输源为 // SSI1数据寄存器,目的是接收“A”缓冲区。 。 //传输大小设置为与缓冲区大小匹配。 MAP_uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_PRI_SELECT、 UDMA_MODE_PINGONG、 (void *) SSI1_base、 g_ui8RxBufA、sizeof (g_ui8RxBufA); //设置 SSI RX 交替控制的传输参数 //结构。 模式设置为乒乓模式、传输源为 // SSI 数据寄存器、目的是接收"B"缓冲区。 。 //传输大小设置为与缓冲区大小匹配。 MAP_uDMAChannelTransferSet (UDMA_CHANGE_SSI1RX | UDMA_ALT_SELECT、 UDMA_MODE_PINGONG、 (void *) SSI1_base、 g_ui8RxBufB、sizeof (g_ui8RxBufB)); //启用 UDMA SSI1RX 通道 MAP_uDMAChannelEnable (UDMA_CHANGE_SSI1RX); //启用 SSI uDMA MAP_SSIDMADisable (SSI1_BASE、SSI_DMA_RX | SSI_DMA_TX); MAP_SSIIntClear (SSI1_BASE、SSI_DMA_RX | SSI_DMA_TX); MAP_SSIDMAEnable (SSI1_BASE、SSI_DMA_RX | SSI_DMA_TX); //设置 SSI1 DMA 中断。 MAP_SSIIntEnable (SSI1_BASE、SSI_DMARX); //map_SSIIntEnable (SSI1_base、SSI_DMATX);//注释掉这一点是因为一旦我启用中断、中断就会关闭 MAP_SSIIntDisable (SSI1_BASE、SSI_DMATX); //从勘误表中:SSI 必须在 SSICR1.EOT 位清零时初始化。 HWREG (SSI1_BASE + SSI_O_CR1)&=~(SSI_CR1_EOT); //启用 QSSI MAP_SSIEnable (SSI1_BASE); //启用 SSI1外设中断。 //map_IntEnable (INT_SSI1); }
如您所见、我必须注释掉 MAP_SSIIntEnable (SSI1_BASE、SSI_DMATX)。 当我需要实际启动传输时、我已经尝试在主线程中重新启用它、如下所示:
FB_return_code GetSpiLine (uint16* destinationBuffer) { uint32_t bytesRead = 0; //开始到 SSII TX 的 DMA 传输。 MAP_uDMAChannelTransferSet (UDMA_CHANGE_SSI1TX | UDMA_PRI_SELECT、 UDMA_MODE_BASIC、g_ui8TxBuf、 (void *) SSI1_base、 sizeof (g_ui8TxBuf)); //必须启用 uDMA TX 通道。 MAP_uDMAChannelEnable (UDMA_CHANGE_SSI1TX); MAP_SSIIntEnable (SSI1_BASE、SSI_DMATX); while (bytesRead < total_bytes_per_line) { //此处处理数据 } MAP_uDMAChannelDisable (UDMA_CHANGE_SSI1TX); MAP_SSIIntDisable (SSI1_BASE、SSI_DMATX); 返回 FB_Success ;}
我的 TX/RX 缓冲区和 dmaControlTable 初始化如下所示:
#define SSI1_TXBUF_SIZE 1024 #define SSI1_RXBUF_SIZE 1024 #pragma DATA_SECTION (dmaControlTable、"extram_alloc") #pragma DATA_ALIGN (dmaControlTable、1024) uint8_t dmaControlTable[1024]; //用于 SSI1传输的发送和接收缓冲区。 //一个发送缓冲区和一对乒乓接收缓冲区 #pragma DATA_SECTION (g_ui8TxBuf、"extram_alloc") uint8_t g_ui8TxBuf[SSI1_TXBUF_SIZE]; #pragma DATA_SECTION (g_ui8RxBufA、"ui8u_uiRXBUF_SIZE];#pragma DATA_SECTION "extram_alloc") uint8_t g_ui8RxBufB[SSI1_RXBUF_SIZE];
我认为需要注意的是、我正在通过项目.cfg 文件注册中断处理程序、并在 Hwi 模块下添加一个具有50个中断号的 SSI1IntHandler 的实例。 我已经为 TX 和 RX 尝试了基本模式和突发模式。 感谢任何人的帮助/建议。