Tool/software:
Hi everyone,
My PCB board integrates an SPI ADC MAX11337 chip. My goal is to transmit 10 bytes to the SPI ADC chip via SPIB every 1ms, with each byte triggered by a seperate CS pulse. That's why DMA or FIFO mode aren't suitable as they don't handle the CS pulsing automatically.
The process begins with sending the first byte in the Timer1 ISR. Subsequent bytes are transmitted one at a time in the SPI RX interrupt until all 10 bytes are sent (in 10 SPI interrupts). After that, the SPI RX interrupt is disabled.
The issue I am currently facing is the SPIRX interrupt doesn't trigger after sending the first SPI byte from within the Timer1 ISR. However, if the SPI write is performed from a non-ISR routine, e.g main loop, the SPIRX interrupt works as expected.
Here's my code:
Initialization
CPU timer 1 interrupts every 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: non-FIFO. Interrupts on 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. On Timer 1 interrupt, write the first byte to SPI in max11337_start()
__interrupt void timer1_1ms_ISR(void)
{
if(max11337_ready()){
max11337_start();
}
}
2. This writes the first SPI byte to 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. The SPIRX interrupt handler
__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
}
Can someone point me what's wrong with my code?