cancel
Showing results for 
Search instead for 
Did you mean: 

SSI and Circular DMA

sb_st
Associate III

Hello!

I am writing a driver for the mt6701ct rotary magnetic encoder, using cubeIDE and an stm32f405 MCU. This sensor communicates via SSI, which is to say that it's read-only (MISO-only; there is no physical connection to MOSI). 

Using a simple polling strategy, I can communicate fine with this sensor using HAL_SPI_Receive().

I'd like to learn more about using DMA for this though, and am interested in trying to get circular DMA working. 

My SPI is configured like so:

Screenshot 2025-01-14 at 8.17.05 PM.png

Screenshot 2025-01-14 at 8.21.15 PM.png

The HAL Reference Manual notes:  

Screenshot 2025-01-14 at 8.15.52 PM.png

To try to sidestep issue #1 with my SSI setup here, I do this in my code to start the circular DMA:

typedef struct
{
  SPI_HandleTypeDef *spi_handle;
  uint16_t cs_pin;
  GPIO_TypeDef *cs_pin_port;
  uint8_t sensor_receive_dma_buffer[3];
} SMT6701CT_HandleTypeDef;

// IMPORTANT! On Page 1033 of the HAL Reference Manual,
// there's a note that says we can't use circular DMA
// with SPI with only RX data (which is what we want).
// To get around this, what I'm doing is creating a
// dummy TX buffer, and then using HAL_SPI_TransmitReceive()
// to simultaneously send and receive data. There is no
// physical TX connection here, so this does nothing really,
// it's just a workaround to allow us to do this DMA trick.
uint8_t tx_dummy[3] = {0x00, 0x00, 0x00};

// Pull cs low for the sensor.
// Note that we only activate this, we don't
// deactivate it here.
MT6701CT_enable_cs(sensor);

// Now, start the DMA read
hal_status = HAL_SPI_TransmitReceive_DMA(sensor->spi_handle, tx_dummy, sensor->sensor_receive_dma_buffer, 3);

Then, I have an interrupt handler like so:

void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) {
    if (hspi == &hspi1) {
    	HAL_StatusTypeDef hal_status;
	hal_status = HAL_SPI_DMAPause(sensor->spi_handle);

	// ...
	// do a bunch of stuff to calculate the angle
	// ...

	// resume the DMA reader
	hal_status = HAL_SPI_DMAResume(sensor->spi_handle);
    }
}

I can see, via stepping through the code with the debugger in CubeIDE, that the DMA seems to be started ok, and the interrupt handler is indeed being called periodically. However, the data inside my sensor->sensor_receive_dma_buffer seems to be junk - it updates periodically as I expect, but just seems to be noise or other nonsensical data. 

I know it's hard to pinpoint the issue based on these limited code snippets, but I'm curious how I can troubleshoot what might be going wrong here? I think signs point to my hardware behaving correctly, and that I'm just dealing with a code problem. But, this is my first go-around with DMA, so I'm sure I'm overlooking something here.

 

Thank you!

0 REPLIES 0