2023-10-03 05:54 AM
I want to share my related code and photo here. The program runs on an STM32F746 Nucleo Board. It uses timer 2 to trigger DMA1 stream 0 causing fixed-length transmission of data via SPI 1 to an external ADC without interrupts on the transmission side. Timer 2 confüguration is settled at 25600Hz this is used as a sample rate. Therefore data must be received with SPI3 every 25600Hz. I created a test pin to understand that the sampling process is finished. The sample size is 64. The complete time is 64 x 1/25600 = 400Hz. I can see this period with diligent oscilloscope but the received data is empty. Can you show me where I'm doing wrong?
Code:
SPI_HandleTypeDef hspi3;
DMA_HandleTypeDef hdma_spi3_rx;
TIM_HandleTypeDef htim2;
DMA_HandleTypeDef hdma_tim2_up_ch4;
#define fs (25600)
#define RX_BUFFER_LENGTH (64)
memset(rxBuffer, 0, sizeof(rxBuffer));
txBuffer = 0xFFFF;
// Start SPI RX DMA
hspi3.hdmarx->XferCpltCallback = mySPI_DMAReceiveCplt;
SET_BIT(hspi3.Instance->CR2, SPI_RXFIFO_THRESHOLD);
HAL_GPIO_WritePin(ADC_CS_Pin_GPIO_Port, ADC_CS_Pin_Pin, RESET);
HAL_DMA_Start_IT(hspi3.hdmarx, (uint32_t)&hspi3.Instance->DR, (uint32_t)rxBuffer, RX_BUFFER_LENGTH);
SET_BIT(hspi3.Instance->CR2, SPI_CR2_RXDMAEN);
__HAL_SPI_ENABLE(&hspi3);
// Prepare TIM DMA to SPI_DR
HAL_DMA_Start(htim2.hdma[TIM_DMA_ID_UPDATE], (uint32_t)&txBuffer, (uint32_t)&hspi3.Instance->DR, 1);
__HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_UPDATE);
// Start the timer
__HAL_TIM_ENABLE(&htim2);
while (1)
{
}
2023-10-03 07:06 AM - edited 2023-10-03 07:13 AM
Since mySPI_DMAReceiveCplt is being called, something is working right.
How do you know 0 isn't the correct data in this case? Initialize it to something unique (perhaps a ramp, 0, 1, 2, 3, etc.) and see if it gets changed. (Even if 0 isn't the expected data, it could still be due to a pin misconfigured or disconnected or otherwise.)
Could also define rxBuffer as volatile, but I doubt that's it.
2023-10-03 07:28 AM
I defined buffer as volatile but there is no change. I can see debugging mode.
first I configurated external adc register wrote and read the same register then set it to auto mode and started the sample with spi3.In addition ı don't use nss pin. I use software nss . Cs pin is already low(active).
2023-10-03 08:35 AM
I don't see how any of that addresses the case where MISO=0, which would explain your results exactly.
2023-10-03 09:37 AM
Start with polled implementation, that would clarify both MISO=0 as @TDK said above, and also incorrectly initialized GPIO cases.
As this is Cortex-M7, also watch out for the caching issues.
JW
2023-10-03 11:51 PM
I controlled initialization SPI3,DMA.
// SPI configuration, I check the spi with external adc doing write and read register.
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hspi->Instance==SPI3)
{
/* USER CODE BEGIN SPI3_MspInit 0 */
/* USER CODE END SPI3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**SPI3 GPIO Configuration
PB2 ------> SPI3_MOSI
PC10 ------> SPI3_SCK
PC11 ------> SPI3_MISO
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_SPI3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
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(GPIOC, &GPIO_InitStruct);
/* SPI3 DMA Init */
/* SPI3_RX Init */
hdma_spi3_rx.Instance = DMA1_Stream0;
hdma_spi3_rx.Init.Channel = DMA_CHANNEL_0;
hdma_spi3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi3_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_spi3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_spi3_rx.Init.Mode = DMA_CIRCULAR;
hdma_spi3_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_spi3_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi3_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi3_rx);
/* USER CODE BEGIN SPI3_MspInit 1 */
/* USER CODE END SPI3_MspInit 1 */
}
}
// This case is triggered the dma , it is correct because we can see the image that 405Hz toggle pin.
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 DMA Init */
/* TIM2_UP_CH4 Init */
hdma_tim2_up_ch4.Instance = DMA1_Stream7;
hdma_tim2_up_ch4.Init.Channel = DMA_CHANNEL_3;
hdma_tim2_up_ch4.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_tim2_up_ch4.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim2_up_ch4.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim2_up_ch4.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_tim2_up_ch4.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_tim2_up_ch4.Init.Mode = DMA_CIRCULAR;
hdma_tim2_up_ch4.Init.Priority = DMA_PRIORITY_LOW;
hdma_tim2_up_ch4.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_tim2_up_ch4) != HAL_OK)
{
Error_Handler();
}
/* Several peripheral DMA handle pointers point to the same DMA handle.
Be aware that there is only one stream to perform all the requested DMAs. */
__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_UPDATE],hdma_tim2_up_ch4);
__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_CC4],hdma_tim2_up_ch4);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
}
// Startin process
memset(rxBuffer, 0, sizeof(rxBuffer));
txBuffer = 0xFFFF;
// Start SPI RX DMA
// hspi3.hdmarx->XferHalfCpltCallback = mySPI_DMAHalfReceiveCplt;
hspi3.hdmarx->XferCpltCallback = mySPI_DMAReceiveCplt;
SET_BIT(hspi3.Instance->CR2, SPI_RXFIFO_THRESHOLD);
HAL_GPIO_WritePin(ADC_CS_Pin_GPIO_Port, ADC_CS_Pin_Pin, RESET);
HAL_DMA_Start_IT(hspi3.hdmarx, (uint32_t)&hspi3.Instance->DR, (uint32_t)rxBuffer, RX_BUFFER_LENGTH);
SET_BIT(hspi3.Instance->CR2, SPI_CR2_RXDMAEN);
__HAL_SPI_ENABLE(&hspi3);
// Prepare TIM DMA to SPI_DR
HAL_DMA_Start(htim2.hdma[TIM_DMA_ID_UPDATE], (uint32_t)&txBuffer, (uint32_t)&hspi3.Instance->DR, 1);
__HAL_TIM_ENABLE_DMA(&htim2, TIM_DMA_UPDATE);
// Start the timer
__HAL_TIM_ENABLE(&htim2);
2023-10-04 04:53 AM
The error comes from triggering the SPI NSS pin.
First, I performed Hardware output Nss and saw that it did not write or read the register return value was 0. After Hardware I canceled NSS and turned it on and off with software. I wrote to the registers and read the correct data, but I could not read adc value. The problem right now is that I need to turn the CS pin on and off while receiving data via dma.
2023-10-04 05:13 AM
> The problem right now is that I need to turn the CS pin on and off while receiving data via dma.
How? Show some timing diagram.
JW
2023-10-04 07:22 AM
2023-10-04 08:04 AM
Check out NSS pulse mode:
Note that CPHA must be 0. Check with the slave's datasheet if this is viable.
I don't use Cube/CubeMX so don't know how to click this in CubeMX or what Cube/HAL incantations lead to this being properly used.
JW