RM48L952 可以用CAN中断的方式接收数据, 我想用DMA的方式接收CAN数据. 有没有好的方法和例程..
Ken Wang:
Hi Sam,
确实我们的DMA是支持CAN总线的硬件触发的,具体的DAM channel通道你可以在datasheet(不是TRM)里面找得到。
相关的例程我们暂时还没有,不过你可以参考HALCOGEN里面的关于MIBSPI的例程来修改。
谢谢
Sam:
回复 Ken Wang:
哦。好的。最好能提供一个例程..谢谢。。
Sam:
回复 Sam:
Hi Ken,
我有查看HALCOGEN里面的关于MIBSPI的例程,当时这几个函数不是太明白,需要一一解释:
/* – assigning dma request: channel-0 with request line – 1 */
dmaReqAssign(0,1 );/* – configuring dma control packets */
dmaConfigCtrlPacket((uint32)(&TX_DATA),(uint32)(&(mibspiRAM1->tx[0].data)),D_SIZE);
/* upto 32 control packets are supported. *//* – setting dma control packets */
dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT);/* – setting the dma channel to trigger on h/w request */
dmaSetChEnable(DMA_CH0, DMA_HW);/* – configuring the mibspi dma , channel 0 , tx line -0 , rxline -1 */
/* – refer to the device data sheet dma request source for mibspi tx/rx */
mibspiDmaConfig(mibspiREG1,0,0,1);
Ken Wang:
回复 Sam:
sam,
第一个函数是DMA channel的mapping操作,这里选择的是将DMA的第一个request 1 mapping到channel 0 上面。request 1 是有我们芯片定义的硬件触发MIBSPI的请求,这个可以在我们datasheet的4.16.2 的default DMA request map表格里查到。channel 数也是自己设置的,channel 0的优先级最高。
第二个函数是设置DMA的源地址,终端地址,以及DMA传输数据的长度
第三个函数是配置DMA的package, 里面包括DMA的传输方式,终端盒源端地址的offet 和每次地址跳转的大小,element的大小,frame的大小,读写的具体位数等等。这个DMA配置的重点
第四个函数是这是我们前面定义的channel 0 通道硬件触发。
第五个函数是设置具体的MIBSPI发送和接收的channel。
谢谢
Sam:
回复 Ken Wang:
Hi Ken,
1.也就是说MIBSPI的硬件触发请求是request 1,那RM48L952 的CAN1的硬件触发请求是request X? .. 能否发份DATASHEET
2. DAM的源地址, 与终端地址配置有什么讲究?
Ken Wang:
回复 Sam:
Hi Sam,
RM48L952的datasheet下载地址如下:
http://www.ti.com/lit/ds/symlink/rm48l952.pdf
DMA 的源端地址是有点讲究的,特别是选择为硬件触发的时候,你需要将远端地址设为相应的模块的数据寄存器或者类似于发送缓存器,接收缓存器之类的寄存器,这样才能硬件触发。终端地址还好,寄存器或是memory地址都行。
谢谢
Sam:
回复 Ken Wang:
Hi Ken,
下面是例程但是有问题.不能进入DMA中断。
void main(void){ /* Enable IRQ interrupt in ARM CPSR register */ _enable_interrupt_();
/* Reset the Flag */ DMA_Comp_Flag = 0xAAAA5555;
/* initialize can 1 */ canInit();
// Enable DE3 bit in CTL register to trigger DMA when IF3 receives data// canREG1->CTL |= (1U << 20U);
/* At present HALCoGen does not support IF3 configuration, * hence doing it here */ // Read ARB, DATA A & B – 8 bytes */ //canREG1->IF3OBS = 0x1A;
// Read DATA A & B – 8 bytes */ canREG1->IF3OBS = 0x18;
// Message box 2 configured for auto update canREG1->IF3UEy[0]= 0x0000002A;
/* – DMA Configuration */ /* Enable DMA */ dmaEnable();
/* Enable Interrupt after reception of data */ dmaEnableInterrupt(DMA_CH0, FTC);
/* assigning dma request: channel-0 with request line – 16 ( DCAN1IF3) */ /* Refer Datasheet DMA request Line connection Table */ dmaReqAssign(DMA_CH0,16);
while(1){
/* – Populate dma control packets structure */ /* Source Address = IF3 Data register * Destination = Receive Buffer in Sys RAM * Length = 1 ( i.e., 64bits = 8 * 8 Bytes) */ dmaConfigCtrlRxPacket((uint32)(&(canREG1->IF3DATx[0])), (uint32)(&RX_DATA1), 1);
/* – setting dma control packets for transmit */ dmaSetCtrlPacket(DMA_CH0, g_dmaCTRLPKT);
/* – setting the dma channel to trigger on h/w request */ dmaSetChEnable(DMA_CH0, DMA_HW);
canEnableloopback(canREG1,Internal_Lbk);
dmaEnable();
/* transmit on can1 */ canTransmit(canREG1, canMESSAGE_BOX1, TX_DATA1);
/* Wait for the DMA interrupt ISR to set the Flag */// while(DMA_Comp_Flag != 0x5555AAAA);
/* Disable Loopback */ canDisableloopback(canREG1);
/* Check the RX_DATA1 for the received message */}/* USER CODE END */}
/* USER CODE BEGIN (4) */
void dmaConfigCtrlRxPacket(uint32 sadd,uint32 dadd,uint32 dsize){ g_dmaCTRLPKT.SADD = sadd; /* source address */ g_dmaCTRLPKT.DADD = dadd; /* destination address */ g_dmaCTRLPKT.CHCTRL = 0; /* channel control */ g_dmaCTRLPKT.FRCNT = 1; /* frame count */ g_dmaCTRLPKT.ELCNT = dsize; /* element count */ g_dmaCTRLPKT.ELDOFFSET = 0; /* element destination offset */ g_dmaCTRLPKT.ELSOFFSET = 0; /* element source offset */ g_dmaCTRLPKT.FRDOFFSET = 0; /* frame destination offset */ g_dmaCTRLPKT.FRSOFFSET = 0; /* frame source offset */ g_dmaCTRLPKT.PORTASGN = 4; /* port b */ g_dmaCTRLPKT.RDSIZE = ACCESS_64_BIT; /* read size */ g_dmaCTRLPKT.WRSIZE = ACCESS_64_BIT; /* write size */ g_dmaCTRLPKT.TTYPE = FRAME_TRANSFER ; /* transfer type */ g_dmaCTRLPKT.ADDMODERD = ADDR_FIXED; /* address mode read */ g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED; /* address mode write */ g_dmaCTRLPKT.AUTOINIT = AUTOINIT_ON; /* autoinit */}
void dmaGroupANotification(dmaInterrupt_t inttype, uint32 channel){ DMA_Comp_Flag = 0x5555AAAA;}
请问有什么问题??
Ken Wang:
回复 Sam:
Hi sam,
你这个程序看着很眼熟啊,应该是我们英文论坛里面一个关于软件触发DMA的实例改过来的吧。
我现在手头上没两块板子,暂时试不了。
要不你先这样吧,先试试没有中断的,简单的软件触发方式,看看DMA能不能工作,后面再去设置硬件触发的,以及想用的带DMA中断的应用。
这样比较容易排排查问题。
谢谢
Sam:
回复 Ken Wang:
Hi Ken ,
的确是从英文论坛里面修改过来的..
现在CAN1发送数据, DMA能进入中断.
如果将Read and write 配置成64BIT:
g_dmaCTRLPKT.RDSIZE = ACCESS_64_BIT; /* read size */ g_dmaCTRLPKT.WRSIZE = ACCESS_64_BIT; /* write size
调试时会出现如下错误:
CortexR4: GEL Output: Memory Map Setup for Flash @ Address 0x0CortexR4: Trouble Reading Memory Block at 0x8001584 on Page 0 of Length 0x1: (Error -1170 @ 0x0) Unable to access the DAP. Reset the device, and retry the operation. If error persists, confirm configuration, power-cycle the board, and/or try more reliable JTAG settings (e.g. lower TCLK). (Emulation package 5.0.872.0)
而且RX_DATA1 什么数据都不能收到,
如果将Read and write 配置成32BIT:
g_dmaCTRLPKT.RDSIZE = ACCESS_32_BIT; /* read size */g_dmaCTRLPKT.WRSIZE = ACCESS_32_BIT; /* write size
DAM进入中断,当时RX_DATA1只能收到前4byte 数据, 后4byte不能收到。
很疑惑啊,为什么??
Sam:
回复 Sam:
Hi Ken,
能否给出答案?