[解决方案] 2011/2018:问题不存在如所描述的那样。DMA传输未暂停。由于逻辑分析仪的错误触发器,我看了一个错误的数据传输。]用逻辑分析仪查看我的PIC的两个不同SPI外设的信号,我惊讶地看到,我的DMA SPI传输(写入512个字节到闪存)被CN(IOC)中断/暂停。中断服务例程,它访问另一个SPI外围设备。只需注意:传输和中断工作得很好,这只是我想优化的时机。在我看来,DMA传输的想法是在没有MPU的情况下工作(使用SPI重复的连续模式),所以我没有想到MPU中断对DMA传输有影响。它。我的意图是,DMA传输应该继续而不是等待另一个(无关的)中断。虽然我有一个模糊的理解,DMA SPI传输确实依赖于内部的中断逻辑,但我还没有找到文档中的细节的解释,尤其是我如何才能解释。观察到的行为。我必须注意中断优先级还是应该继续搜索哪个方向…这里是一些背景信息。前4个频道显示了512字节DMA SPI传输(SPI 2)的摘录,它被CN中断(底部4通道)打断。CN中断例程读取来自另一SPI外围设备(SPI 1)的数据的七个16位字,即在最后4个通道中看到的数据传输也反映中断的长度。在中断退出时,DMA继续工作。在ButtoMod中看到的图像是中断功能。这是对DMA SPI传输的SPI 2的一次初始化,这是一个函数,它实际上对512字节的附加信息进行DMA传输:嵌套中断被启用(而不是DI)。中断优先级是所有4(这是复位后的默认值,例如,πSPI2TXIP,πSPI2IP)(设置为3,对于SPI2不改变行为)在这个PIC的中断向量表中。CN中断位于γ-SPI2中断和γ-SPI2TX中断之前,即“自然优先级”F。或CN高于SPI2(第8.1章FRM)
以上来自于百度翻译
以下为原文
["solu
tion" 11.Jan.2018: the problem does not exist as described. The DMA transfer is NOT paused. Due to wrong trigger for the Logic Analyzer, I looked at a wrong data transfer.]
Looking at the signals of two different SPI peripherals of my PIC with a logic analyzer, I was a bit astonished to see that my DMA SPI transfer (writing 512 bytes into a flash memory) is interrupted/paused by a CN (IOC) interrupt service routine, which accesses another SPI peripheral. Just to note: the transfers and interrupts work perfectly,- it's just the timing which I would like to optimize.
In my mind the idea of a DMA transfer is to work
without the MPU (using SPI repeated continous mode), so I did not expect an MPU interrupt to have influence on the DMA transfer, by delaying it. My intention is that the DMA transfer should continue and not wait for another (unrelated) interrupt.
While I have a vague understanding that the DMA SPI transfer DOES depend on interrupt logic internally, I did not yet find an explanation of the details in the documentation, especially how can I change the observed behaviour. Do I have to pay attention to interrupt priorities or
in which direction should I continue to search ...
Here is some background information
The top 4 channels shows an excerpt of the 512 byte DMA SPI transfer (SPI 2), which is interrupted by a CN interrupt (bottom 4 channels). The CN interrupt routine reads seven 16-bit words of data from another SPI peripheral (SPI 1), i.e. the data transfer seen in the last 4 channels also reflects the length of the interrupt. On exit of interrupt, the DMA continues to work.
See image at bottom
This is the interrupt function
void __attribute__((interrupt, auto_psv)) _CNInterrupt(void)
{
if (_IOCFB10)
{
spiReadData16(ICM_ACCEL_XOUT_H, (WORD *) dataICM.iData, ICM_DATA_COUNT);
bIcmDataReady = 1;
_IOCFB10 = 0;
}
_CNIF = 0; // clear interrupt flag
}
This is some one-time initialization of SPI #2 for the DMA SPI transfer
SPI2CON1bits.MODE16 = 0; // byte mode
SPI2CON1bits.MSTEN = 1; //SPI Master
SPI2CON1bits.CKP = 0; // Idle state for clock is a low level
SPI2CON1bits.CKE = 1;
SPI2CON1bits.ENHBUF = 0;
SPI2STATLbits.SPIROV = 0; // clear the Receive overflow flag
SPI2BRGLbits.BRG = 0;
SPI2CON1bits.MCLKEN = 0;
// SPIEN enabled; DISSDO disabled; MCLKEN FOSC/2; CKP Idle:Low, Active:High;
// SSEN disabled;MSTEN Master; MODE16 disabled; SMP Middle; DISSCK disabled;
// SPIFE Frame Sync pulse precedes;CKE Idle to Active; MODE32 disabled;
// SPISIDL disabled; ENHBUF enabled; DISSDI disabled;
SPI2CON1Hbits.IGNROV = 1;
SPI2CON1Lbits.SPIEN = 1; // enable SPI2 peripheral
and this is the function which actually does DMA transfers of 512 bytes
static void dmaWrite(BYTE *pBuf, WORD wCount, WORD wMode)
{
DMACON = 0x0001; // DMACONbits.DMAEN = 0;
DMAH= DMA_UPPER_LIMIT;
DMAL= 0x0000;
// CHEN enabled; DAMODE Unchanged; TRMODE One-Shot; CHREQ disabled;
// RELOAD disabled; SIZE 8 bit; NULLW disabled; SAMODE Incremented;
// HALFIF disabled; LOWIF disabled; HALFEN disabled; DONEIF disabled;
// OVRUNIF disabled; CHSEL SPI2 Event; HIGHIF disabled;
DMACH0 = 0;
// SPI "repeated continous mode"
DMACH0bits.TRMODE=0; // Transfer mode
DMACH0bits.SAMODE=1; // Source address increment mode
DMACH0bits.DAMODE=0; // dest
DMACH0bits.SIZE=1; // byte
DMACH0bits.NULLW=0; // null write disable
DMAINT0= 0x00;
IFS0bits.DMA0IF = false;
_DMA0IE = 1; // enable interrupt
// for CHSEL see FRM Table 5-1
DMAINT0bits.CHSEL = DMA_TRIG_SRC_SPI2_TRANSMIT; //Trig on SPI2 TX
DMASRC0= (WORD) pBuf;
DMADST0= (unsigned int)&SPI2BUFL;
DMACNT0= wCount;
_SPI2TXIF = 0;
SPI2IMSKLbits.SPITBEN = 1; // interrupt if tx empty
// Clearing Channel 0 Interrupt Flag;
IFS0bits.DMA0IF = 0;
//Enable DMA
DMACONbits.DMAEN = 1;
//Enable DMA Channel 0
DMACH0bits.CHEN = 1;
DMACH0bits.CHREQ = 1;
// note, actually the end of the DMA transfer is signalled end handled
// by a DMA interrupt, not shown here
}
Additional information:
Nested interrupts are enabled (not disabled)
Interrupt priorities are all 4 (which is the default after reset, e.g. _SPI2TXIP, _SPI2IP)
(setting them to 3 for SPI2 does not change the behaviour)
In the interrupt vectors table for this PIC the CNInterrupt comes BEFORE the __SPI2Interrupt and __SPI2TXInterrupt,
i.e. the 'natural priority' for CN is higher than for SPI2 (chapter 8.1 FRM)
Attached Image(s)