This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS320F280049C:F280049C SPI TX 在 FIFO 模式下的问题:新字符在旧字符开始't 完成时开始

Guru**** 2538930 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1565489/tms320f280049c-issue-with-f280049c-spi-tx-in-fifo-mode-new-char-starts-while-the-old-one-hasn-t-finished

器件型号:TMS320F280049C


工具/软件:

大家好、感谢观看。

我尝试在主模式下使用 F280049C 的 SPI 并使用 FIFO 连接 EEPROM。 在我的应用程序中、有时 CPU 会写入 TXBUF(短命令)、其他情况下则是 DMA(长数据数组)。

我从 SPI_EX7_EEPROM_DMA 修改了一个简单的代码。 它从空 FIFO(字长为 8 位)开始、并使用 SPI_writeDataNonBlocking 向 TX_BUF 数组 (0x1100、0x2200 ... 0x9900) 写入、但我在逻辑分析仪上看到以下内容:

如您所见、对于大多数字 、只有两个时钟周期、只有在代码停止写入时、我们才会得到一个完整字。

如果我 暂停 MCU(我正在 LaunchPad 上进行测试)、设置 SPIPRI = 0x0000、然后使用调试器手动逐个写入 TXBUFF(观察 TXFFST 增加情况)、然后设置 SPIPRI.FREE=1、得到预期的序列:

以下是我在示例配置中更改的内容:

void iniSPI(void){
	spiFinished = true;
	SPI_Pin_Init();
	SPI_Peripheral_Init();
	SPI_DMA_Init();
	spiRXisr_cnt = 0;
}

void SPI_DMA_Init(void) {
	//setupSPI_DMA_Handler(SPI_BASE, 8U, DMA_CH_SPI_TX, DMA_CH_SPI_RX);
}

void SPI_Pin_Init(void)
{
	GPIO_setPinConfig(GPIO_8_SPIA_SIMO);
	GPIO_setPinConfig(GPIO_9_SPIA_CLK);
	GPIO_setPinConfig(GPIO_10_SPIA_SOMI);
	GPIO_setPinConfig(GPIO_57_SPIA_STE);
}

void SPI_Peripheral_Init(void)
{

	//SPI_EEPROM initialization
	SPI_disableModule(SPI_BASE);
	SPI_setConfig(SPI_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA0,
				  SPI_MODE_MASTER, SPI_FREQ, 8);
	SPI_enableFIFO(SPI_BASE);
	SPI_resetTxFIFO(SPI_BASE);
	SPI_resetRxFIFO(SPI_BASE);
	SPI_setFIFOInterruptLevel(SPI_BASE, SPI_FIFO_TXEMPTY, SPI_FIFO_RXFULL);
	SPI_clearInterruptStatus(SPI_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
	SPI_enableInterrupt(SPI_BASE,SPI_INT_TXFF);
	SPI_disableLoopback(SPI_BASE);
	SPI_setEmulationMode(SPI_BASE, SPI_EMULATION_FREE_RUN);//SPI_EMULATION_STOP_AFTER_TRANSMIT);//MIDWAY
	SPI_enableModule(SPI_BASE);
	Interrupt_register(SPI_INT_TX, &spiTXisr);
	SPI_clearInterruptStatus(SPI_BASE, SPI_INT_TXFF);
	Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
	Interrupt_enable(SPI_INT_TX);
}


ISR 只会增加一个用于调试目的的计数器并确认中断。

这是我的 main.c:

void main(void)
{
    uint16_t i;

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pullups.
    //
    Device_initGPIO();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    iniSPI();
    EINT;
    ERTM;


    char example[20] = {0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0};

    i = 0;

    while(example[i]){
        sendSPIByte(example[i]);
        i++;
        //while(!spiHasFinished());
    }




        while(1);

下面是我如何“发送字节“:

void sendSPIByte(uint16_t data) {
	spiFinished = false;
	SPI_setcharLength(SPI_BASE,8);
	SPI_writeDataNonBlocking(SPI_BASE, data<<8);//Writes to register must be left justified
	Interrupt_enable(SPI_INT_TX);
}



编辑:语法

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    若要对此问题进行展开、如果我使用 SPI_writeDataBlockingFIFO 函数而不是上面的函数、我会得到类似的行为、但通过 DMA、它可以正常工作。

    例如、在本例中、我以这种方式写入 0x11、0x22 和 0x33、然后使用 DMA 写入孔阵列(从 0x68 开始):

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ivan:

    几个说明:  

    1) 这里的一点是不建议在发送函数内使用 setCharLength API。 您能否删除它、看看您是否注意到任何差异?

    2) SPI PTE 由 HW 控制、而不是像在 SPI_EX7 中那样手动控制? 此外、Transmit 函数中 Interrupt_enable 的用途是什么?

    此致、

    Arnav  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好 Arnav、谢谢你

    1.评论该行确实得到了正确的行为:



    为什么不推荐? 我需要切换 charlength 中流、是否有任何建议的方法来实现这一点? (可能是等待所有位被清除,然后禁用,重新配置和启用 SPI?
    2. A. STE 确实是由硬件在捕获中控制的,虽然我以后将不得不手动控制它。 它用于调试和了解正在发生的事情。
    2. B.目前我只是在测试东西。 将来、我需要在 SPI 8 位和 SPI 16 位之间切换、以便能够向外部 EEPROM(具有 8 位指令)发送具有 16 位变量(或更大)的数据结构。 我可以将缓冲区转换为字节并全部以 SPI 8 位格式发送、但我试图避免 CPU 开销。 因此、我的方法是发送第一个字节(指令)或前三个字节(包括地址)、然后配置 DMA 发送所有其他字节。  此时、中断仅用于调试目的、我可以使用先配置 DMA、然后对其进行预配置并使用硬件触发器。  我稍后决定。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Ivan:

    是的、我们观察到了在 SPI 有效工作时更改字符长度时出现的杂散脉冲。 在模块处于复位状态时进行更改、如您所说应该可以正常工作。

    如果您有任何其他问题、请告诉我。

    此致、

    Arnav