With an STM32F764 I want to receive 33 bytes from 11 daisy-chained 24 bit ADCs via SPI in read-only mode. The received data looks okay but there are 37 to 39 bytes in the buffer. Also with other byte numbers I receive 4 to 6 bytes more than expected.
Does anyone have an idea why that happens?
HAL_SPI_Receive_DMA is called by a GPIO interrupt from an external ADC when the 33 bytes are ready. After finishing the DMA the buffer content is processed in Sampling().
Is the external GPIO interrupt handler the correct place for calling HAL_SPI_Receive_DMA?
/*SPI init for external ADCs (only Rx)*/
uint8_t SPI3_Init_ADC(void)
{
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; /*SPI3_CLK = 12.5 MHz*/
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
return ERR;
return OK;
}
/*SPI MSP and DMA Initialization*/
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/*SPI3: ADCs*/
if(hspi->Instance==SPI3)
{
__HAL_RCC_SPI3_CLK_ENABLE(); /* Peripheral clock enable */
__HAL_RCC_GPIOB_CLK_ENABLE();
/*PB3 --> SPI3_SCK*/
/*PB4 --> SPI3_MISO*/
GPIO_InitStruct.Pin = GPIO_PIN_3|GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF6_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/*DMA 1 / channel 0 / stream 0 transfers data from external ADC to sample registers*/
__HAL_RCC_DMA1_CLK_ENABLE(); /*DMA clock*/
hdma_spi3_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; /*from SPI to memory*/
hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE; /*no increment on SPI side*/
hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE; /*increment sample memory address*/
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi3_rx.Init.Mode = DMA_NORMAL;
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_spi3_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
hdma_spi3_rx.Init.MemBurst = DMA_PBURST_SINGLE;
hdma_spi3_rx.Init.PeriphBurst = DMA_PBURST_SINGLE;
hdma_spi3_rx.Instance = DMA1_Stream0;
HAL_DMA_Init(&hdma_spi3_rx);
HAL_NVIC_SetPriority(DMA1_Stream0_IRQn, 0, 0); /*highest priority for DMA interrupt*/
HAL_NVIC_EnableIRQ(DMA1_Stream0_IRQn); /*enable DMA interrupt*/
__HAL_LINKDMA(hspi, hdmarx, hdma_spi3_rx); /*link DMA1 to SPI3*/
}
/*INTERRUPT HANDLERS*/
/*Data ready interrupt (/ADC_/DRDY) of external ADCs*/
void EXTI9_5_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7); /*clear interrupt*/
HAL_SPI_Receive_DMA(&hspi3, SplRxBuff, 33); /*get 33 bytes ADC data*/
}
/*DMA1 stream0 global interrupt (Rx of external ADCs complete)*/
void SPI_DMA_Rx_IRQHandler(void)
{
HAL_DMA_IRQHandler(&hdma_spi3_rx);
Sampling();
}
Screenshot:
The red part is excess data. The ADC delivers actual data here from its unused 12th channel.
SplRxBuff
size initialized? – VaibhavHAL_SPI_Receive_DMA()
or point us to the HAL library version? - It is important to check its properties (behaviour on port registers, reentrancy etc.). (3) Is it possible that there is some electronic problem on the interrupt pin so that the interrupt gets re-triggered shortly after the initial IRQ happens? – HelpingHand