i want to read out an 32 bit Sigma Delata ADC per DMA over the SPI Interface with an STM32F767. There is an Data Ready Signal which indicates that there is new Data available.
My current idea is to start the DMA transfer with the an Interrupt triggered by this Data Ready Pin. The Code is a mixture of Bare Metal Programming and configuration via Cube IDE:
void EXTI1_IRQHandler(void)
{
/* USER CODE BEGIN EXTI1_IRQn 0 */
/* USER CODE END EXTI1_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_1);
/* USER CODE BEGIN EXTI1_IRQn 1 */
data_ready_flag = 1;
DMA2_Stream0->CR |= DMA_SxCR_EN; // DMA-Transfer aktivieren
SPI1->CR2 |= SPI_CR2_TXDMAEN; // TXDMA-Request aktivieren
SPI1->CR1 |= SPI_CR1_SPE; // SPI aktivieren
EXTI->PR |= EXTI_PR_PR1;
/* USER CODE END EXTI1_IRQn 1 */
}
void DMA2_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
/* USER CODE END DMA2_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi1_rx);
/* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
if (DMA2->LISR & DMA_LISR_TCIF0)
{
for (int i = 0; i < SPI_BUF_LEN; i++)
{
receivedDataX[i] = destinationBuffer[i];
}
DMA2->LIFCR |= DMA_LIFCR_CTCIF0;
SPI1->CR2 &= ~SPI_CR2_TXDMAEN;
}
/* USER CODE END DMA2_Stream0_IRQn 1 */
}
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
MX_ETH_Init();
MX_USART3_UART_Init();
MX_USB_OTG_FS_PCD_Init();
MX_TIM3_Init();
MX_TIM4_Init();
MX_TIM9_Init();
/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); // Chip Select 1
TIM3->CCR1 = 10;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
/// Schritt 3: DMA für SPI1 aktivieren
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
// Schritt 4: DMA-Konfiguration
DMA2_Stream0->PAR = (uint16_t)(&(SPI1->DR)); // Quelladresse: SPI1 Datenregister
DMA2_Stream0->M0AR = (uint16_t)destinationBuffer; // Zieladresse: Speicherbereich
DMA2_Stream0->NDTR = SPI_BUF_LEN; // Anzahl der zu übertragenden Daten
DMA2_Stream0->CR = DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0; // Channel 0, Memory-Increment-Mode, Memory-to-Peripheral-Mode
// Schritt 5: DMA-Stream konfigurieren und aktivieren
DMA2_Stream0->CR |= DMA_SxCR_TCIE; // Transfer Complete Interrupt aktivieren
NVIC_EnableIRQ(DMA2_Stream0_IRQn); // NVIC-Interrupt für DMA-Stream aktivieren
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
If i try to receive the data per polling method it is working but with the DMA it is not (neither with pure configuration by Cube IDE nor by bare metal approach).
Does someone have an Idea on how to configure an DMA / SPI receive triggered by Interrupt in a proper way?
Best regards
Additionally the SPI configuration which was generated by Cube IDE:
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
Several remarks:
JW