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.

[参考译文] TMS320F28388D:CAN't 从 Timer1 ISR 内触发 SPIRX 中断

Guru**** 2539500 points


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

https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1542882/tms320f28388d-can-t-trigger-spirx-interrupt-from-within-the-timer1-isr

器件型号:TMS320F28388D


工具/软件:

大家好:

我的 PCB 板集成了 SPI ADC MAX11337 芯片。 我的目标是每 1ms 通过 SPIB 向 SPI ADC 芯片传输 10 个字节、每个字节由一个单独的 CS 脉冲触发。 这就是 DMA 或 FIFO 模式不适用的原因、因为它们不会自动处理 CS 脉冲。  

该过程从 Timer1 ISR 中的第一个字节开始。 后续字节在 SPI RX 中断期间一次发送一个、直到发送所有 10 个字节(在 10 个 SPI 中断中)。 之后、禁用 SPI RX 中断。

我目前面临的问题是从 Timer1 ISR 内发送第一个 SPI 字节后不会触发 SPIRX 中断。 但是、如果从非 ISR 例程(例如主循环)执行 SPI 写入、则 SPIRX 中断会按预期运行 。  

以下是我的代码:

初始化

CPU 计时器 1 每 1ms 中断一次

void timer1_1ms_init(){
	CPUTimer_setEmulationMode(timer1_1ms_BASE, CPUTIMER_EMULATIONMODE_STOPAFTERNEXTDECREMENT);
	CPUTimer_setPreScaler(timer1_1ms_BASE, 200U);
	CPUTimer_setPeriod(timer1_1ms_BASE, 1000U);
	CPUTimer_enableInterrupt(timer1_1ms_BASE);
	CPUTimer_stopTimer(timer1_1ms_BASE);

	CPUTimer_reloadTimerCounter(timer1_1ms_BASE);
	CPUTimer_startTimer(timer1_1ms_BASE);
}

SPIB:非 FIFO。 开启中断 SPI_INT_RX_DATA_TX_EMPTY

void spi_adc_init(){
	SPI_disableModule(spi_adc_BASE);
	SPI_setConfig(spi_adc_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL1PHA0,
				  SPI_MODE_CONTROLLER, spi_adc_BITRATE, spi_adc_DATAWIDTH);
	SPI_setPTESignalPolarity(spi_adc_BASE, SPI_PTE_ACTIVE_LOW);
	SPI_disableFIFO(spi_adc_BASE);
	SPI_disableLoopback(spi_adc_BASE);
	SPI_setEmulationMode(spi_adc_BASE, SPI_EMULATION_STOP_MIDWAY);
	SPI_enableModule(spi_adc_BASE);
}

void INTERRUPT_init(){
	
	// Interrupt Settings for INT_timer1_1ms
	// ISR need to be defined for the registered interrupts
	Interrupt_register(INT_timer1_1ms, &timer1_1ms_ISR);
	Interrupt_enable(INT_timer1_1ms);
}

在计时器 1 中断时、将第一个字节写入中的 SPI max11337_start ()

 

__interrupt void timer1_1ms_ISR(void)
{
    if(max11337_ready()){
        max11337_start();
    }
}

2.这会将第一个 SPI 字节写入 MAX11337。

void max11337_start(void)
{
     // Prime first word to start transfer
     txIndex = 1;
     rxIndex = 0;

     // Enable SPI RX interrupt
     SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_RX_DATA_TX_EMPTY);
     SPI_enableInterrupt(SPIB_BASE, SPI_INT_RX_DATA_TX_EMPTY);

     // Enable CPU interrupt group
     Interrupt_enable(INT_SPIB_RX);

     // Set CS low
     GPIO_writePin(SPI_ADC_CS, 0);
     // Write the first byte
     SPI_writeDataNonBlocking(SPIB_BASE, spiTxBuffer[0]);
}

3. SPIRX 中断处理程序

__interrupt void spi_rx()
{
    // 1. Toggle CS high
    GPIO_writePin(SPI_ADC_CS, 0);
      
    // 2. Read the received word
    spiRxBuffer[rxIndex++] = SPI_readDataNonBlocking(SPIB_BASE);

    // 3. Clear interrupt flags
    SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_RX_DATA_TX_EMPTY);

    // 4. Send next word if available
    if (txIndex < 10)
    {
        // Toggle CS low
        GPIO_writePin(SPI_ADC_CS, 0);
        SPI_writeDataNonBlocking(SPIB_BASE, spiTxBuffer[txIndex++]);
    }
    else
    {
        // All data sent and received, disable RX interrupt
        SPI_disableInterrupt(SPIB_BASE, SPI_INT_RX_DATA_TX_EMPTY);
    }

    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);  // SPIB = Group 6
}

有人能指出我的代码出了什么问题吗?

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

    我的背景主要涉及使用 Microchip PIC 产品、我在这些产品中从未遇到过任何中断问题。 这是我第一个使用 TI C2000 MCU 的原型、目前我遇到了与中断相关的问题。 如果有人能帮助确定根本原因、我将非常感激、因为我需要快速解决。

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

    您好:

    浏览您的代码、我认为这里发生的情况是、当您仍在处理计时器 ISR 时、SPI 中断正在尝试触发、并且 C28x 器件没有硬件中断嵌套。 最简单的权变措施是在计时器 ISR 中设置一个标志、阻止在主循环中写入数据。

    顺便提一下、我注意到您在提供的代码中永远不会将 CS 设置为 1。

    此致、
    Jason Osborn

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

    您好 Jason、

    感谢您的答复、我非常感谢您的答复。 请检查我的意见如下:

    1.在硬件初始化期间将 CS 设置为 1。 此处未显示该选项。  

    2.我不想在计时器 ISR 中设置标志并从主循环进行检查、因为时序不是确定性的。 我们的系统是实时的、精确的计时至关重要。

    3.我知道在 C2000 中默认未启用中断嵌套。 我不明白的是为什么在程序退出计时器 ISR 后不会触发 SPIRX 中断。 我的理解是进入计时器 ISR 时、INTM 自动设置为 1、然后在退出时清零。 在发送/接收一个字时应设置 SPIRX 中断标志(无论 INTM 状态如何)、一旦在退出计时器 ISR 后清除 INTM、CPU 应继续处理 SPIRX 中断、但这不会发生。 我花了很多时间尝试了解什么可能会阻止这种行为、我希望有人能提供一些见解。  

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

    泵。 任何人都可以帮助解决这个难题?  

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

    对不起,响应延误,我有陪审团的责任。

    再次查看您的代码、我有一些注意事项和问题:

    首先,Timer1_1ms_isr() 和 max11337_start() 没有 ack 函数。 确保此处使用的计时器外设为 CPUTIMER1 或 CPUTIMER2。 CPUTIMER0 与其他外设一样通过 PIE、并且需要 ACK。 然而、由于 TIMER0 与 SPI 不在同一组中、因此具体来说不太可能是问题的原因。

    第二,你永远不会显示 SPI Rx 的 INTERRUPT_REGISTER() 函数,但因为在某些情况下事情是有效的,我将假设这是完成的,根本不显示类似于设置 CS。

    至于您提出的实际问题、我也在研究这个问题。 这不符合我预期的情况,道歉。 您是否具有对芯片的调试访问权限? 理想情况下、失败示例中 SPI 状态寄存器的 CCS 寄存器视图在此处很有用。

    此致、
    Jason Osborn

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

    您好 Jason。

    不用担心延迟。 感谢你对这一问题的支持。  

    Timer1_1ms_isr () 和 max11337_start 没有 ACK 函数。 我可以确认 CPUTimer1 正被使用、因此不需要 ACK。

    SPIRX 的中断寄存器功能如下所示:

    void max11337_initialize()
    {
    
        // start with echo test.
        if( max11337_verifyEcho() == true){
            // initialize its registers.
            max11337_setupRegisters();
    
            // Register RX ISR
            Interrupt_register(INT_SPIB_RX, &spi_rx);
            ready = true;
        }
    }

    请注意、CPU1 最初将使用配置 MAX11337 寄存器 spi_write_read_16bit在非中断(阻塞)模式下运行 。 设置完成后、它将注册 SPIRX 中断回调函数并将 READY 标志设置为 1。 从那时起、所有 SPI 写入/读取操作都将使用中断驱动模式进行处理。

    static uint16_t spi_write_read_16bit(uint16_t txData)
    {
        uint16_t rxData = 0;
    
        GPIO_writePin(SPI_ADC_CS,0);
    
        // Wait until the TX buffer is ready (TXFFST = 0 means TX FIFO is empty)
        //while((HWREGH(SPIB_BASE + SPI_O_STS) & SPI_STS_BUFFULL_FLAG));
    
        // Write data to TX register
        SPI_writeDataBlockingNonFIFO(SPIB_BASE, txData);
    
        // Wait until RX buffer has received data (RXFFST != 0)
        //while((HWREGH(SPIB_BASE + SPI_O_FFRX) & SPI_FFRX_RXFFST_M) == 0);
    
        // Read and return received 16-bit word
        rxData = SPI_readDataBlockingNonFIFO(SPIB_BASE);
    
        GPIO_writePin(SPI_ADC_CS,1);
        return rxData;
    }

    是的、我可以对芯片进行调试访问。 请告诉我您需要查看哪些寄存器以及在何处设置断点。 我会相应地进行设置并提供屏幕截图。

    此致、

    WeeHau

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

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

    我非常抱歉再次出现响应延迟、我将绝对确定不会再次发生。

    首先,我有一个怀疑,我想测试。 您能否更改用于 TIMER2 的 CPU 计时器并添加必要的 ACK 函数? 不要启用嵌套、只需让我知道这本身是否解决了问题。

    如果这不起作用,在失败状态(即 max11337_start() 已经运行,但 SPI ISR 没有触发),请记录以下寄存器的内容:

    • SPI 寄存器 SPISTS 的完整内容(仅记录十六进制值)
    • SPI 寄存器位 SPICTL[SPIINTENA]
    • PIE 寄存器 PIEIFR6 的完整内容(仅为十六进制值)
    • 变量 txIndex、rxIndex、txData、rxData

    此致、
    Jason Osborn

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

    感谢您的跟进。 当然,我会收集信息,并很快更新你。