spi master запускает неуправляемый dma tc прерывает, ничего не получая - PullRequest
0 голосов
/ 13 мая 2019

Я уже задавал этот вопрос на форуме mbed, но ответа не получил.

Введение

У меня две платы Nucleo L432kc, яхотите, чтобы они общались с протоколом SPI, используя DMA.

В следующей схеме вы можете увидеть фактическую настройку оборудования: enter image description here

Что работает

Если я отправляю данные от ведущего к подчиненному, я получаю их правильно, а когда ведущее устройство не передает, ведомое устройство ничего не получает.

Код мастера

#include <mbed.h>
uint8_t dma_buffer_tx[4];
uint8_t dma_buffer_rx[4];
uint8_t buff[4];
uint32_t receive_buff_length = 4;

unsigned int c = 0;

Serial pc(USBTX,USBRX,921600);
DigitalOut led(LED3); 

SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;

void Error_Handler(){
  led.write(1);
  while(1){}
}

static void HAL_GPIO_Init(void){

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi1.Instance==SPI1)
  {    
      __HAL_RCC_GPIOA_CLK_ENABLE();
      /**SPI1 GPIO Configuration    
      PA1     ------> SPI1_SCK
      PA11     ------> SPI1_MISO
      PA12     ------> SPI1_MOSI 
      */
      GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }

  else
    Error_Handler();
}

static void SPI1_Init(void)
{
  __HAL_RCC_SPI1_CLK_ENABLE();

  /* 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.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  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();
  }

  /* SPI1 interrupt Init */
  HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(SPI1_IRQn);
}

static void DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* SPI1 DMA Init */
  /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Request = DMA_REQUEST_1;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

  __HAL_LINKDMA(&hspi1,hdmarx,hdma_spi1_rx);

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);

    /* SPI1 DMA Init */
  /* SPI1_TX Init */
  hdma_spi1_tx.Instance = DMA1_Channel3;
  hdma_spi1_tx.Init.Request = DMA_REQUEST_1;
  hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_spi1_tx.Init.Mode = DMA_NORMAL;
  hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_LINKDMA(&hspi1,hdmatx,hdma_spi1_tx);

  /* DMA interrupt init */
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);

}

extern "C"{

  void DMA1_Channel3_IRQHandler(void)
  {
    HAL_NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
    HAL_DMA_IRQHandler(&hdma_spi1_tx);
  }

  void DMA1_Channel2_IRQHandler(void)
  {
    HAL_NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
    HAL_DMA_IRQHandler(&hdma_spi1_rx);
  }

  void SPI1_IRQHandler(void)
  {
    HAL_SPI_IRQHandler(&hspi1);
  }
}

void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi1){

  for(int i = 0; i < receive_buff_length/2; i++){
    buff[i] = dma_buffer_rx[i];
  }

}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi1){

  for(int i = receive_buff_length/2; i < receive_buff_length; i++){
    buff[i] = dma_buffer_rx[i];
  }

  printf("%u\n",*(unsigned int *)buff); // to understan when I am actually receiving data
  memset(dma_buffer_rx,0,sizeof(dma_buffer_rx));
}

void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi1){

  c += 5;
  dma_buffer_tx[0] = c & 0xFF; 
  dma_buffer_tx[1] = (c >> 8) & 0xFF;

}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi1){

  dma_buffer_tx[2] = (c >> 16) & 0xFF;
  dma_buffer_tx[3] = (c >> 24) & 0xFF;
}

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* SPI INIT */
  SPI1_Init();

  /* GPIO USART2 INIT */
  HAL_GPIO_Init();

  /* DMA INIT */
  DMA_Init();

  c = 1000;
  dma_buffer_rx[0] = c & 0xFF; 
  dma_buffer_rx[1] = (c >> 8) & 0xFF;
  dma_buffer_rx[2] = (c >> 16) & 0xFF;
  dma_buffer_rx[3] = (c >> 24) & 0xFF;


  while(true){
    HAL_SPI_Transmit_DMA(&hspi1,dma_buffer_rx,receive_buff_length); 
    wait(0.001);
  }
}

Код ведомого

#include <mbed.h>
uint8_t dma_buffer_tx[4];
uint8_t dma_buffer_rx[4];
uint8_t buff[4];
uint32_t receive_buff_length = 4;

unsigned int c = 0;

Serial pc(USBTX,USBRX,921600);
DigitalOut led(LED3); 

SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;

void Error_Handler(){
  led.write(1);
  while(1){}
}

static void HAL_GPIO_Init(void){

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(hspi1.Instance==SPI1)
  {    
      __HAL_RCC_GPIOA_CLK_ENABLE();
      /**SPI1 GPIO Configuration    
      PA1     ------> SPI1_SCK
      PA11     ------> SPI1_MISO
      PA12     ------> SPI1_MOSI 
      */
      GPIO_InitStruct.Pin = GPIO_PIN_1|GPIO_PIN_11|GPIO_PIN_12;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
      HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  }

  else
    Error_Handler();
}

static void SPI1_Init(void)
{
  __HAL_RCC_SPI1_CLK_ENABLE();

  /* SPI1 parameter configuration*/
  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_SLAVE;
  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.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  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();
  }

  /* SPI1 interrupt Init */
  HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(SPI1_IRQn);
}

static void DMA_Init(void) 
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();

  /* SPI1 DMA Init */
  /* SPI1_RX Init */
    hdma_spi1_rx.Instance = DMA1_Channel2;
    hdma_spi1_rx.Init.Request = DMA_REQUEST_1;
    hdma_spi1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_spi1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_spi1_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_spi1_rx.Init.Mode = DMA_NORMAL;
    hdma_spi1_rx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_spi1_rx) != HAL_OK)
    {
      Error_Handler();
    }

  __HAL_LINKDMA(&hspi1,hdmarx,hdma_spi1_rx);

  /* DMA interrupt init */
  /* DMA1_Channel2_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);

    /* SPI1 DMA Init */
  /* SPI1_TX Init */
  hdma_spi1_tx.Instance = DMA1_Channel3;
  hdma_spi1_tx.Init.Request = DMA_REQUEST_1;
  hdma_spi1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_spi1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_spi1_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_spi1_tx.Init.Mode = DMA_NORMAL;
  hdma_spi1_tx.Init.Priority = DMA_PRIORITY_LOW;
  if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
  {
    Error_Handler();
  }

  __HAL_LINKDMA(&hspi1,hdmatx,hdma_spi1_tx);

  /* DMA interrupt init */
  /* DMA1_Channel3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);

}

extern "C"{

  void DMA1_Channel3_IRQHandler(void)
  {
    HAL_NVIC_ClearPendingIRQ(DMA1_Channel3_IRQn);
    HAL_DMA_IRQHandler(&hdma_spi1_tx);
  }

  void DMA1_Channel2_IRQHandler(void)
  {
    HAL_NVIC_ClearPendingIRQ(DMA1_Channel2_IRQn);
    HAL_DMA_IRQHandler(&hdma_spi1_rx);
  }

  void SPI1_IRQHandler(void)
  {
    HAL_SPI_IRQHandler(&hspi1);
  }
}

void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi1){

  for(int i = 0; i < receive_buff_length/2; i++){
    buff[i] = dma_buffer_rx[i];
  }

}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi1){

  for(int i = receive_buff_length/2; i < receive_buff_length; i++){
    buff[i] = dma_buffer_rx[i];
  }

  printf("%u\n",*(unsigned int *)buff); // to understan when I am actually receiving data
  memset(dma_buffer_rx,0,sizeof(dma_buffer_rx));
}

void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi1){

  c += 5;
  dma_buffer_tx[0] = c & 0xFF; 
  dma_buffer_tx[1] = (c >> 8) & 0xFF;

}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi1){

  dma_buffer_tx[2] = (c >> 16) & 0xFF;
  dma_buffer_tx[3] = (c >> 24) & 0xFF;
}

int main(void)
{
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* SPI INIT */
  SPI1_Init();

  /* GPIO USART2 INIT */
  HAL_GPIO_Init();

  /* DMA INIT */
  DMA_Init();

  c = 1000;
  dma_buffer_rx[0] = c & 0xFF; 
  dma_buffer_rx[1] = (c >> 8) & 0xFF;
  dma_buffer_rx[2] = (c >> 16) & 0xFF;
  dma_buffer_rx[3] = (c >> 24) & 0xFF;


  while(true){
    HAL_SPI_Receive_DMA(&hspi1,dma_buffer_rx,receive_buff_length); 
  }
}

Что не работает

Если я изменяю роль в сообщении, поэтому я отправляю данные из salve введущий меняет следующие строки

[...]
HAL_SPI_Transmit_DMA(&hspi1,dma_buffer_rx,receive_buff_length); 
wait(0.001);
[...]

на:

[...]
HAL_SPI_Receive_DMA(&hspi1,dma_buffer_rx,receive_buff_length); 
[...]

Даже если ведомый не включен, ведущий непрерывно получает прерывания и вызывает HAL_SPI_RxCpltCallback.Если мы включаем подчиненное устройство, мастер печатает случайные числа.

То, что я уже попробовал без успеха

  1. Я проверил мастер-код на плате Nucleo F446.
  2. Я установил понижающие и подтягивающие резисторы на выводе MISO.
  3. Я пробовал другой кабель для подключения hw.
  4. Я пытался использовать напрямуюфункция HAL_SPI_TransmitReceive_DMA, но поведение такое же.на самом деле называется.Я думаю, что один и тот же буфер используется для передачи и приема, но я не знаю, как это доказать.Я также напечатал hdma_spi1_rx.Instance->CNDTR и заметил, что значение увеличивается до 4, что на самом деле является количеством байтов, которые мы собираемся получить.

1 Ответ

0 голосов
/ 13 мая 2019

Мастер SPI всегда получает данные при передаче. Вот как работает SPI. Даже если SPI не передает данные, мастер все время читает данные.

...