Skip to main content
Associate
July 2, 2026
Question

STM32F051SPI CRC error cannot generate error interrupt

  • July 2, 2026
  • 2 replies
  • 56 views

I found an issue while using STM32F051, and the background is that I want to generate an interrupt when the host receives a CRC error, in order to perform my error handling in the interrupt handler. But when a CRC error occurred, the CPU did not jump into the interrupt service function. At this point, I checked that the CRCERR flag was raised and the ERRIE interrupt enable was also enabled. I have tried other conditions that can trigger error flags to generate interrupts, such as OVR, FRE, MODF, etc. These flag bits can generate interrupts and enter the interrupt service function, which proves that my interrupt enable steps are correct. I carefully reviewed the manual again, and it clearly states that when ERRIE is set, CRCERR can trigger an interrupt. So I want to know if there are some hardware defects that did not connect the CRCERR signal to the NVIC.

2 replies

mƎALLEm
ST Technical Moderator
September 4, 2026

Hello ​@ldxmz and sorry for the late reply,

1- According to the Errata sheet ES0202 - Rev 6, there is no mention of a such behavior/limitation.

2- How did you inject the SPI CRC error? How did you reproduce it?

3- Could you please share your code?

To give better visibility on the answered topics, please click "Best answer" on the reply which solved your issue or answered your question.
ldxmzAuthor
Associate
September 4, 2026

1. Yes, I have reviewed this document and did not find this situation.
2. I am connected through SPI with an external MCU (STM32H745ZI), which acts as a slave for SPI and prepares an incorrect CRC value in the sending buffer. When the host (STM32F051C8) provides a clock, both parties receive data from each other. The last frame of the host does not write data to the DR but sets the CRCNEXT bit, then waits for RXNE to read the DR and ends this transmission. At this point, I found that the CRCERR flag was raised but did not interrupt (I set a flag for observation in the interrupt and broke it to confirm that the interrupt did not enter).
3. There are many code snippets, and it is not convenient to provide them all. The main code snippets are as follows:

LL_SPI_EnableIT_ERR(SPIx);

spi_irq_nvic_enable((SpiInst_t)inst);



if (needNss) { SPI_NssLow((SpiInst_t)inst); savedNssLow = 1; }



/* 收 count 帧: 前 count-1 帧普通收, 末帧 CRCNEXT 触发 CRC 比对

所有帧的 RX 字节存到 g_spiRxData (复用已有缓冲, 避免新 bss) */

{

uint8_t *rxBuf = (uint8_t *)g_spiRxData;

for (i = 0; i < count; i++)

{

uint16_t dummy = is16bit ? 0xFFFFu : 0x00FFu;

uint16_t got;

if (i == count - 1)

{

got = SPI_Master_TxRxByte_CrcNext(SPIx, dummy); /* 末帧: 写 DR → 紧接 CRCNEXT */

}

else

{

got = SPI_Master_FullDuplex_TxRxByte(SPIx, dummy);

}

if (i < 128U) { rxBuf[i] = (uint8_t)(got & 0xFFu); }

}

rxBuf[count] = LL_SPI_ReceiveData8(SPIx);

}

SPI_WaitTransferComplete(SPIx); /* 等 BSY=0, 确保末帧发完 + CRC 比对完成 + CRCERR 已置位 */



/* 等 ISR 捕获 CRCERR (CRCERR置位 → ERRIE → ISR → g_spiIrqFired) */

fired = spi_irq_wait_fired(timeout);



if (savedNssLow) { SPI_NssHigh((SpiInst_t)inst); savedNssLow = 0; }

spi_irq_nvic_disable((SpiInst_t)inst);

LL_SPI_DisableIT_ERR(SPIx);

if (g_spiIrqFired) { fired = 1; }



/* RX 详情: 4 数据帧 + 末字节 (共 count 字节) */

{

char buf[300];

int off = snprintf(buf, sizeof(buf), "RX: ");

for (i = 0; i < count && off < (int)sizeof(buf) - 4; i++)

{

off += snprintf(buf + off, sizeof(buf) - off, "%02X ", ((uint8_t *)g_spiRxData)[i]);

}

LOGI("%s", buf);

}

/* FLAG 仅诊断: ISR 已清 CRCERR, 读数可能为 0, 但 pass 由 fired 判定 */

LOGI("FLAG: crcerr=%d (ISR may have cleared; pass by fired)", LL_SPI_IsActiveFlag_CRCERR(SPIx) ? 1 : 0);

}