我使用DMA搬运mcbspa数据,mcbspa做SPI从设备,主设备是STM32,每5毫秒发送5个word,DMA这边设置成每接收25个word产生一次中断,并复位,现在发现主设备SPI传输时钟频率为5mhz以下就没问题,数据不丢失也不出错,主设备SPI时钟频率达到8mhz就接收到的就大量错误了,代码如下,请指导!
STM32端传输设置:16位,SPI_CPOL_High, SPI_CPHA_2Edge,FirstBit_MSB
f28335,MCBSP设置:
McbspaRegs.SPCR2.all = 0x0000; // Reset FS generator, sample rate generator & transmitter
McbspaRegs.SPCR1.all = 0x0000; // Reset Receiver, Right justify word
McbspaRegs.MFFINT.all = 0x0; // Disable all interrupts
McbspaRegs.SPCR1.bit.RJUST = 0;
McbspaRegs.SPCR1.bit.CLKSTP = 2; //
McbspaRegs.PCR.bit.CLKXP = 0; //
McbspaRegs.PCR.bit.CLKRP = 1; //
McbspaRegs.PCR.bit.CLKXM = 0;
McbspaRegs.PCR.bit.CLKRM = 0;
McbspaRegs.PCR.bit.FSRP = 0;
McbspaRegs.PCR.bit.FSRM = 0;
McbspaRegs.PCR.bit.SCLKME = 0;
McbspaRegs.PCR.bit.FSXM = 0;
McbspaRegs.PCR.bit.FSXP = 1;
McbspaRegs.RCR2.bit.RPHASE = 0;
McbspaRegs.RCR2.bit.RDATDLY = 0; // FSX setup time 1 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY = 0; // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
McbspaRegs.SRGR2.bit.CLKSM = 1;
McbspaRegs.SRGR1.bit.CLKGDV = 0x01;
McbspaRegs.SRGR2.bit.FPER = 1;
McbspaRegs.RCR1.bit.RFRLEN1 = 4;
McbspaRegs.RCR1.bit.RWDLEN1 = 2; // 16-bit word
McbspaRegs.XCR1.bit.XFRLEN1 = 4;
McbspaRegs.XCR1.bit.XWDLEN1 = 2; // 16-bit word
McbspaRegs.RCR2.bit.RFRLEN2 = 4;
McbspaRegs.RCR2.bit.RWDLEN2 = 2;
McbspaRegs.XCR2.bit.XFRLEN2 = 4;
McbspaRegs.XCR2.bit.XWDLEN2 = 2;
McbspaRegs.RCR2.bit.RCOMPAND = 0; //No companding, any size data, MSB received first
McbspaRegs.XCR2.bit.XCOMPAND = 0;
delay_loop(); // Wait at least 2 SRG clock cycles
McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
clkg_delay_loop(); // Wait at least 2 CLKG cycles
McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
F28335 DMA设置:
interrupt void local_D_INTCH1_ISR(void) // DMA Ch2
{
k++;
for(int i = 0;i<25;i++)
{
if(rdata[i] != (i%5))
{
j++;
catch2 = rdata[i];
}
}
EALLOW; // NEED TO EXECUTE EALLOW INSIDE ISR !!!
DmaRegs.CH1.CONTROL.bit.HALT = 1 ;
DmaRegs.CH1.CONTROL.bit.RUN = 1; // Re-enable DMA CH2. Should be done every transfer
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP7; // To receive more interrupts from this PIE group, acknowledge this interrupt
EDIS;
return;
}
void Config_DMA_CH1(Uint32 dst_addr)
{
EALLOW;
// Perform a hard reset on DMA
DmaRegs.DMACTRL.bit.HARDRESET = 1;
__asm(" nop"); // one NOP required after HARDRESET
// Allow DMA to run free on emulation suspend
DmaRegs.DEBUGCTRL.bit.FREE = 1;
DmaRegs.CH1.MODE.bit.CHINTE = 0;
DmaRegs.CH1.BURST_SIZE.all = 0; // 1 word/burst
DmaRegs.CH1.SRC_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.DST_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.TRANSFER_SIZE = 24; // Interrupt every 25 bursts/transfer
DmaRegs.CH1.SRC_TRANSFER_STEP = 0; // Don't move source address
DmaRegs.CH1.DST_TRANSFER_STEP = 1; // Move to next word in buffer after each word in a burst
DmaRegs.CH1.SRC_ADDR_SHADOW = &McbspaRegs.DRR1.all;; // Start address = McBSPA DRR
DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = &McbspaRegs.DRR1.all; // Not needed unless using wrap function
DmaRegs.CH1.DST_ADDR_SHADOW = dst_addr; // Start address = Receive buffer (for McBSP-A)
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = dst_addr; // Not needed unless using wrap function
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear peripheral interrupt event flag
DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1; // Clear sync flag
DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; // Clear sync error flag
DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF; // Put to maximum – don't want destination wrap
DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // Put to maximum – don't want source wrap
DmaRegs.CH1.MODE.bit.CHINTE = 1; // Enable channel interrupt
DmaRegs.CH1.MODE.bit.CHINTMODE = 1; // Interrupt at end of transfer
DmaRegs.CH1.MODE.bit.PERINTE = 1; // Enable peripheral interrupt event
DmaRegs.CH1.MODE.bit.PERINTSEL = 15; // Peripheral interrupt select = McBSP MRSYNCA
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
PieVectTable.DINTCH1= &local_D_INTCH1_ISR;
PieCtrlRegs.PIEACK.bit.ACK7 = 1;
PieCtrlRegs.PIEIER7.bit.INTx1 = 1;
IER |= PIEACK_GROUP7;
EDIS;
}
dst_addr参数是Uint16的数组。
求解!
Susan Yang:28335 DMA参数如下
• Word Size: 16-bit or 32-bit (McBSPs limited to 16-bit)
• Throughput: 4 cycles/word (5 cycles/word for McBSP reads)
您可以计算一下,是不是DMA来不及处理
我使用DMA搬运mcbspa数据,mcbspa做SPI从设备,主设备是STM32,每5毫秒发送5个word,DMA这边设置成每接收25个word产生一次中断,并复位,现在发现主设备SPI传输时钟频率为5mhz以下就没问题,数据不丢失也不出错,主设备SPI时钟频率达到8mhz就接收到的就大量错误了,代码如下,请指导!
STM32端传输设置:16位,SPI_CPOL_High, SPI_CPHA_2Edge,FirstBit_MSB
f28335,MCBSP设置:
McbspaRegs.SPCR2.all = 0x0000; // Reset FS generator, sample rate generator & transmitter
McbspaRegs.SPCR1.all = 0x0000; // Reset Receiver, Right justify word
McbspaRegs.MFFINT.all = 0x0; // Disable all interrupts
McbspaRegs.SPCR1.bit.RJUST = 0;
McbspaRegs.SPCR1.bit.CLKSTP = 2; //
McbspaRegs.PCR.bit.CLKXP = 0; //
McbspaRegs.PCR.bit.CLKRP = 1; //
McbspaRegs.PCR.bit.CLKXM = 0;
McbspaRegs.PCR.bit.CLKRM = 0;
McbspaRegs.PCR.bit.FSRP = 0;
McbspaRegs.PCR.bit.FSRM = 0;
McbspaRegs.PCR.bit.SCLKME = 0;
McbspaRegs.PCR.bit.FSXM = 0;
McbspaRegs.PCR.bit.FSXP = 1;
McbspaRegs.RCR2.bit.RPHASE = 0;
McbspaRegs.RCR2.bit.RDATDLY = 0; // FSX setup time 1 in master mode. 0 for slave mode (Receive)
McbspaRegs.XCR2.bit.XDATDLY = 0; // FSX setup time 1 in master mode. 0 for slave mode (Transmit)
McbspaRegs.SRGR2.bit.CLKSM = 1;
McbspaRegs.SRGR1.bit.CLKGDV = 0x01;
McbspaRegs.SRGR2.bit.FPER = 1;
McbspaRegs.RCR1.bit.RFRLEN1 = 4;
McbspaRegs.RCR1.bit.RWDLEN1 = 2; // 16-bit word
McbspaRegs.XCR1.bit.XFRLEN1 = 4;
McbspaRegs.XCR1.bit.XWDLEN1 = 2; // 16-bit word
McbspaRegs.RCR2.bit.RFRLEN2 = 4;
McbspaRegs.RCR2.bit.RWDLEN2 = 2;
McbspaRegs.XCR2.bit.XFRLEN2 = 4;
McbspaRegs.XCR2.bit.XWDLEN2 = 2;
McbspaRegs.RCR2.bit.RCOMPAND = 0; //No companding, any size data, MSB received first
McbspaRegs.XCR2.bit.XCOMPAND = 0;
delay_loop(); // Wait at least 2 SRG clock cycles
McbspaRegs.SPCR2.bit.GRST=1; // Enable the sample rate generator
clkg_delay_loop(); // Wait at least 2 CLKG cycles
McbspaRegs.SPCR2.bit.XRST=1; // Release TX from Reset
McbspaRegs.SPCR1.bit.RRST=1; // Release RX from Reset
McbspaRegs.SPCR2.bit.FRST=1; // Frame Sync Generator reset
F28335 DMA设置:
interrupt void local_D_INTCH1_ISR(void) // DMA Ch2
{
k++;
for(int i = 0;i<25;i++)
{
if(rdata[i] != (i%5))
{
j++;
catch2 = rdata[i];
}
}
EALLOW; // NEED TO EXECUTE EALLOW INSIDE ISR !!!
DmaRegs.CH1.CONTROL.bit.HALT = 1 ;
DmaRegs.CH1.CONTROL.bit.RUN = 1; // Re-enable DMA CH2. Should be done every transfer
PieCtrlRegs.PIEACK.all |= PIEACK_GROUP7; // To receive more interrupts from this PIE group, acknowledge this interrupt
EDIS;
return;
}
void Config_DMA_CH1(Uint32 dst_addr)
{
EALLOW;
// Perform a hard reset on DMA
DmaRegs.DMACTRL.bit.HARDRESET = 1;
__asm(" nop"); // one NOP required after HARDRESET
// Allow DMA to run free on emulation suspend
DmaRegs.DEBUGCTRL.bit.FREE = 1;
DmaRegs.CH1.MODE.bit.CHINTE = 0;
DmaRegs.CH1.BURST_SIZE.all = 0; // 1 word/burst
DmaRegs.CH1.SRC_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.DST_BURST_STEP = 0; // no effect when using 1 word/burst
DmaRegs.CH1.TRANSFER_SIZE = 24; // Interrupt every 25 bursts/transfer
DmaRegs.CH1.SRC_TRANSFER_STEP = 0; // Don't move source address
DmaRegs.CH1.DST_TRANSFER_STEP = 1; // Move to next word in buffer after each word in a burst
DmaRegs.CH1.SRC_ADDR_SHADOW = &McbspaRegs.DRR1.all;; // Start address = McBSPA DRR
DmaRegs.CH1.SRC_BEG_ADDR_SHADOW = &McbspaRegs.DRR1.all; // Not needed unless using wrap function
DmaRegs.CH1.DST_ADDR_SHADOW = dst_addr; // Start address = Receive buffer (for McBSP-A)
DmaRegs.CH1.DST_BEG_ADDR_SHADOW = dst_addr; // Not needed unless using wrap function
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear peripheral interrupt event flag
DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1; // Clear sync flag
DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; // Clear sync error flag
DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF; // Put to maximum – don't want destination wrap
DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // Put to maximum – don't want source wrap
DmaRegs.CH1.MODE.bit.CHINTE = 1; // Enable channel interrupt
DmaRegs.CH1.MODE.bit.CHINTMODE = 1; // Interrupt at end of transfer
DmaRegs.CH1.MODE.bit.PERINTE = 1; // Enable peripheral interrupt event
DmaRegs.CH1.MODE.bit.PERINTSEL = 15; // Peripheral interrupt select = McBSP MRSYNCA
DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; // Clear any spurious interrupt flags
PieVectTable.DINTCH1= &local_D_INTCH1_ISR;
PieCtrlRegs.PIEACK.bit.ACK7 = 1;
PieCtrlRegs.PIEIER7.bit.INTx1 = 1;
IER |= PIEACK_GROUP7;
EDIS;
}
dst_addr参数是Uint16的数组。
求解!
chen zeng:
回复 Susan Yang:
请问怎么计算?主设备发送是一次发送5个16-bit