Part Number:TMS570LS0714
各位前辈:
近期我在摸索TMS570LS0714的DMA模块,想通过配置DMA完成SCI接收以节约CPU资源。但是我现在碰到了点问题,SCI我使用的是SCI/LIN,当我将DMA的source地址配置为scilinREG-》RD时,我的DMA接收数据全部为零。如果我使用SCI中的scireceivebyte功能将sci的rx存放于data1,并同时产生DMA的request请求,将data1存放进data中,这时DMA可以正常工作。恳请各位前辈指导一下,为何直接使用sciRd作为源地址不可行,或者给我一些建议,感谢各位!
Cherry Zhou:
您好我们已收到您的问题并升级到英文论坛寻求帮助,如有答复将尽快回复您。谢谢!
,
Cherry Zhou:
?? ? 说:如果我使用SCI中的scireceivebyte功能将sci的rx存放于data1,并同时产生DMA的request请求,将data1存放进data中,这时DMA可以正常工作
您好,能麻烦您重新描述下这句话吗?
此外为了更好地解决您的问题,您能否提供以下信息:
DMA 使用的触发源是什么?
请问您是否使用使能了 DMA 的多缓冲 SCI 模式? 如果是的话,在 SCIFORMAT 寄存器中配置的长度值是多少?
您的代码是否方便提供下?
,
?? ?:
1.DMA的触发源是 SCI的RX; 2.并未使能DMA的多缓冲模式;3.部分代码如下:
/** @file sys_main.c*@brief Application main file *@date 11-Dec-2018 *@version 04.07.01 * *This file contains an empty main function, *which can be used for the application. *//** Copyright (C) 2009-2018 Texas Instruments Incorporated - www.ti.com***Redistribution and use in source and binary forms, with or without*modification, are permitted provided that the following conditions*are met: * *Redistributions of source code must retain the above copyright*notice, this list of conditions and the following disclaimer. * *Redistributions in binary form must reproduce the above copyright *notice, this list of conditions and the following disclaimer in the*documentation and/or other materials provided with the*distribution. * *Neither the name of Texas Instruments Incorporated nor the names of *its contributors may be used to endorse or promote products derived *from this software without specific prior written permission. * *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS*"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT*LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR *A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT*OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,*SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT*LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY *THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE*OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *//* USER CODE BEGIN (0) */ /* USER CODE END *//* Include Files */#include "sys_common.h"/* USER CODE BEGIN (1) */ #include "system.h" #include "rti.h" #include "het.h" #include "gio.h" #include "can.h" #include "esm.h" #include "sys_core.h" #include "structdef.h" #include "sci.h" #include "spi.h" #include "sys_dma.h"#define DMA_SCI_RX28 #define SCI_SET_RX_DMA(1<<17) #define SCI_SET_RX_DMA_ALL(1<<18) #define SCI_RX_ADDR ((uint32_t)(&(scilinREG->RD))) g_dmaCTRL g_dmaCTRLPKT; /* USER CODE END *//** @fn void main(void) *@brief Application main function *@note This function is empty by default. * *This function is called after startup. *The user can use this function to implement the application. *//* USER CODE BEGIN (2) */ union unOBCTXDATA1{struct stBYTETEMPObcTxByte1;struct unOBCTXWORD1ObcTxWord1; }; union unOBCTXDATA2{struct sciBYTETEMPObcTxByte2;struct unOBCTXWORDSCIObcTxWord2; }; spiDAT1_t dataconfig1_t; uint8 tx_data1[8]; uint8 tx_data2[8]; uint8 tx_data3[8]; uint8 tx_data4[8]; uint8 tx_data5[8]; uint8 tx_data6[8]; uint8 tx_data7[8]; uint8 tx_data8[8]; uint8 sci_tx_data[3]; uint8 rx_data[100] = {0}; uint8 rx_data1[100] = {0}; uint16 spi_txdata[8]; uint16 spi_rxdata[8]; uint16 length; uint32 sciRxData; //int delay_flag; void Can_ObcData1_Send(void); void spi_HVLV_SendandRecieve(void); void dma_init(void); void dmaConfigCtrlPacket(uint32 sadd,uint32 dadd,uint32 dsize); /* USER CODE END */int main(void) { /* USER CODE BEGIN (3) */sciRxData = SCI_RX_ADDR;uint16_t i;spiInit();gioInit();rtiInit();hetInit();canInit();sciInit();dma_init();rtiEnableNotification(rtiNOTIFICATION_COMPARE0);_enable_IRQ();dmaEnable();scilinREG->SETINT |= SCI_SET_RX_DMA | SCI_SET_RX_DMA_ALL;gioSetBit(hetPORT1, 14, 0); //将CAN设置为normalrtiStartCounter(rtiCOUNTER_BLOCK0);length = 0;for(i=0;i<8;i++){spi_txdata[i] = 0;spi_rxdata[i] = 0;}dataconfig1_t.CSNR = 0;dataconfig1_t.CS_HOLD = 0;dataconfig1_t.DFSEL = SPI_FMT_0;dataconfig1_t.WDEL = 1;while(1){if(sciReceiveByte(scilinREG) == 0xFF){for(length=0;length<16;length++){rx_data[length]= sciReceiveByte(scilinREG); //rx_data1[length]= sciReceiveByte(scilinREG);}}} /* USER CODE END */return 0; }/* USER CODE BEGIN (4) */ void dma_init(void) {dmaReqAssign(DMA_CH0, DMA_SCI_RX);dmaConfigCtrlPacket((uint32)(sciRxData),(uint32)(rx_data),16); //dmaConfigCtrlPacket((uint32)(rx_data1),(uint32)(rx_data),16);dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT);dmaSetChEnable(DMA_CH0, DMA_HW);} void rtiNotification(uint32 notification) { /*enter user code between the USER CODE BEGIN and USER CODE END. *//* Toggle HET pin 0 */gioSetBit(hetPORT1, 22, gioGetBit(hetPORT1, 22) ^ 1);spi_HVLV_SendandRecieve();Can_ObcData1_Send();Sci_ObcData1_Send();} //void Can_ObcData1_Send(void) //{ //union unOBCTXDATA1ObcTxData1 = {0}; //int j; ////Get_Obc_Message(); // //ObcTxData1.ObcTxWord1.OBC_Status = 0x001; //ObcTxData1.ObcTxWord1.PFC_Error_State = 0x001; //ObcTxData1.ObcTxWord1.OBC_Output_Vol_H = 3000/256; //ObcTxData1.ObcTxWord1.OBC_Output_Vol_L = 3000%256; //ObcTxData1.ObcTxWord1.OBC_Input_Cur_H = 3000/256; //ObcTxData1.ObcTxWord1.OBC_Input_Cur_L = 3000%256; //ObcTxData1.ObcTxWord1.OBC_Input_Vol_H = 3000/256; //ObcTxData1.ObcTxWord1.OBC_Input_Vol_L = 3000%256; // //for(j = 0; j < 8; j++) //{ //tx_data[j] = ObcTxData1.ObcTxByte1.ByteTemp[j]; //} // //canTransmit(canREG2, canMESSAGE_BOX1, tx_data); ////while(!canIsRxMessageArrived(canREG1, canMESSAGE_BOX2)); ////canGetData(canREG1, canMESSAGE_BOX2, rx_data);/* receive on can2*/ // //} void spi_HVLV_SendandRecieve(void) {spiTransmitAndReceiveData(spiREG2,&dataconfig1_t,4,spi_txdata,spi_rxdata);spi_txdata[0] ++; } void Can_ObcData1_Send(void) {int j;for(j = 0; j < 8;j++){tx_data1[j] = rx_data[j];}for(j = 0; j < 8;j++){tx_data2[j] = rx_data[j+8];}for(j = 0; j < 8;j++){tx_data3[j] = rx_data[j+16];}for(j = 0; j < 8;j++){tx_data4[j] = rx_data[j+24];}for(j = 0; j < 8;j++){tx_data5[j] = rx_data[j+32];}for(j = 0; j < 8;j++){tx_data6[j] = rx_data[j+40];}for(j = 0; j < 8;j++){tx_data7[j] = rx_data[j+48];}canTransmit(canREG2, canMESSAGE_BOX1, tx_data1);canTransmit(canREG2, canMESSAGE_BOX2, tx_data2);canTransmit(canREG2, canMESSAGE_BOX3, tx_data3);canTransmit(canREG2, canMESSAGE_BOX4, tx_data4);canTransmit(canREG2, canMESSAGE_BOX5, tx_data5);canTransmit(canREG2, canMESSAGE_BOX6, tx_data6);canTransmit(canREG2, canMESSAGE_BOX7, tx_data7); //canTransmit(canREG2, canMESSAGE_BOX2, tx_data8); } Sci_ObcData1_Send() {union unOBCTXDATA2ObcTxData2 = {0};int j1;ObcTxData2.ObcTxWord2.OBC_CONTROL = 0x001;ObcTxData2.ObcTxWord2.OBC_REF_V_H = 3000/256;ObcTxData2.ObcTxWord2.OBC_REF_V_L = 3000%256;for(j1 = 0; j1 < 3; j1++){sci_tx_data[j1] = ObcTxData2.ObcTxByte2.SCIByteTemp[j1];}sciSend(scilinREG,3,sci_tx_data); }void dmaConfigCtrlPacket(uint32 sadd,uint32 dadd,uint32 dsize) {g_dmaCTRLPKT.SADD= sadd;/* source address*/g_dmaCTRLPKT.DADD= dadd;/* destinationaddress*/g_dmaCTRLPKT.CHCTRL= 0;/* channel control*/g_dmaCTRLPKT.FRCNT= dsize;/* frame count*/g_dmaCTRLPKT.ELCNT= 1;/* element count*/g_dmaCTRLPKT.ELDOFFSET = 0;/* element destination offset */g_dmaCTRLPKT.ELSOFFSET = 0;/* element destination offset */g_dmaCTRLPKT.FRDOFFSET = 0;/* frame destination offset*/g_dmaCTRLPKT.FRSOFFSET = 0;/* frame destination offset*/g_dmaCTRLPKT.PORTASGN= 4;/* port b*/g_dmaCTRLPKT.RDSIZE= ACCESS_8_BIT;/* read size*/g_dmaCTRLPKT.WRSIZE= ACCESS_8_BIT;/* write size*/g_dmaCTRLPKT.TTYPE= FRAME_TRANSFER ;/* transfer type*/ //g_dmaCTRLPKT.ADDMODERD = ADDR_INC1;/* address mode read*/g_dmaCTRLPKT.ADDMODERD = ADDR_FIXED;/* address mode read*/g_dmaCTRLPKT.ADDMODEWR = ADDR_INC1;/* address mode write*/g_dmaCTRLPKT.AUTOINIT= AUTOINIT_ON;/* autoinit*/ }/* USER CODE END */
,
Cherry Zhou:
好的感谢您提供的信息。
此外您所提到的以下信息,能否重新阐述一下工作机制?我们没太理解。
?? ? 说:如果我使用SCI中的scireceivebyte功能将sci的rx存放于data1,并同时产生DMA的request请求,将data1存放进data中,这时DMA可以正常工作。
,
?? ?:
DMA在我看来就是把地址A的东西搬到地址B去,之前我以为是我的硬件请求没有发送出来,所以我使用了SCI的接收函数获取通讯结果值并将其存放在数组data1中,在完成读取之后 我使用软件触发方式触发CH0通道转换(此时转换是从数组data1传递到data中),发现data数组能正常得到data1中的数,说明我有关DMA的配置是正确的的。之后我将软件触发方式修改为SCI硬件触发,依旧得到了正确的结果。但是如果将source address更换为scilinReg的RD寄存器,收到的数据就有问题,大部分DMA结果都为零。
,
Cherry Zhou:
好的收到哈,我们反馈给工程师看下。
,
Cherry Zhou:
您好,
您给出的代码中有一个错误,
您将"SCI_RX_ADDR"定义为"((uint32_t)(&(scilinREG->RD))",但这将仅在系统配置为小端字节序时有效。 如果系统在大端字节序中配置,那么不应是 RX 地址,而应将其添加3,因此最好按如下方式进行配置:
#if ((__little_endian__ == 1) || (__LITTLE_ENDIAN__ == 1))
#define SCI_RX_ADDR ((uint32_t)(&(sciREG->RD)))
#else
#define SCI_RX_ADDR ((uint32_t)(&(sciREG->RD)) + 3)
#endif
系统现在应该是在以大端字节序运行,这应该就是读取出来都为零的原因。 您也可以在我们的其他器件 SCI DMA 示例中找到相同的东西。
,
?? ?:
感谢各位工程师的帮助,刚刚尝试了一下,确实是大小端的问题!