2023-01-05 05:16 AM
Hi I'm looking to possibly skip the HAL overheads to sent an SPI DMA transfer.
basically I want to do this
HAL_SPI_TransmitReceive_DMA(&hspi5, (uint16_t*) &data_to_send, (uint16_t*) &FromTheADC, sizeof(data_to_send));
without the HAL overhead that seems to actually be quite a bit. I'd hope it would just be a matter of set the pointer, set the register bits, while complete.
Currently I'm trying to go thru the HAL code and remove what I do not need but this seems to be an overkill. Most examples I find out there are for HAL but it would help if I knew what to look for.
Working with the stm32h7 chip.
2023-01-05 07:40 AM
Read the RefMan sections on SPI, DMA, and DMAMUX, write approx. 30 lines of C code. That's it. After you enable everything in RCC and configure the port pins, DMA programming is like 5 lines, DMAMUX - 1 line, SPI - 4 lines of C source.
2023-01-05 08:57 AM
best I got it to was this
__HAL_LOCK(hspi); //Lock the process
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
/* Set the transaction information */
hspi->pTxBuffPtr = (uint8_t *)pTxData;
hspi->pRxBuffPtr = (uint8_t *)pRxData;
hspi->TxXferSize =
hspi->TxXferCount =
hspi->RxXferSize =
hspi->RxXferCount = Size;
/* Reset the Tx/Rx DMA bits */
CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);
//////////////
// RX code //
//////////////
__HAL_LOCK(hspi->hdmarx); // Process locked
/* Change DMA peripheral state */
hspi->hdmarx->State = HAL_DMA_STATE_BUSY;
/* Disable the peripheral */
__HAL_DMA_DISABLE(hspi->hdmarx);
// DMA_SetConfig(hspi->hdmarx, (uint32_t)&hspi->Instance->RXDR,(uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount);
/* calculate DMA base and stream number */
DMA_Base_Registers *regs_dma = (DMA_Base_Registers *)hspi->hdmarx->StreamBaseAddress;
regs_dma->IFCR = 0x3FUL << (hspi->hdmarx->StreamIndex & 0x1FU);
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->NDTR = hspi->RxXferCount;
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->PAR = &hspi->Instance->RXDR;
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->M0AR = &hspi->pRxBuffPtr;
/* Enable Common interrupts*/
MODIFY_REG(((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
/* Enable the Peripheral */
__HAL_DMA_ENABLE(hspi->hdmarx);
//////////////
// TX code //
//////////////
/* Enable Rx DMA Request */
SET_BIT(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN);
__HAL_LOCK(hspi->hdmatx); // Process locked
/* Change DMA peripheral state */
hspi->hdmatx->State = HAL_DMA_STATE_BUSY;
/* Disable the peripheral */
__HAL_DMA_DISABLE(hspi->hdmatx);
DMA_Base_Registers *regs_dma2 = (DMA_Base_Registers *)hspi->hdmatx->StreamBaseAddress;
regs_dma2->IFCR = 0x3FUL << (hspi->hdmatx->StreamIndex & 0x1FU);
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->NDTR = Size;
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->PAR = &hspi->Instance->TXDR;
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->M0AR =&hspi->pTxBuffPtr;
/* Enable Common interrupts*/
MODIFY_REG(((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
/* Enable the Peripheral */
__HAL_DMA_ENABLE(hspi->hdmatx);
//////////////
// clean up //
//////////////
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
/* Enable Tx DMA Request */
SET_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN);
/* Enable the SPI Error Interrupt Bit */
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_OVR | SPI_IT_UDR | SPI_IT_FRE | SPI_IT_MODF));
/* Enable SPI peripheral */
__HAL_SPI_ENABLE(hspi);
/* Master transfer start */
SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
/* Unlock the process */
__HAL_UNLOCK(hspi);
/* re enable int */
__HAL_SPI_ENABLE_IT(hspi, SPI_IT_EOT);
anything here redundant?
2023-01-06 04:54 AM
Yeah, 80%. ;)
2023-01-06 05:45 AM
80% of my code is redundant? Or I'm 80% of the way there?
2023-01-11 07:42 AM
i think I'm a bit more bare-bones now.
this is how I setup and start ( not using interrupts) .
__HAL_LOCK(hspi); //Lock the process
CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);// Reset the Tx/Rx DMA bits
__HAL_LOCK(hspi->hdmarx);
__HAL_LOCK(hspi->hdmatx);
__HAL_DMA_DISABLE(hspi->hdmarx);
__HAL_DMA_DISABLE(hspi->hdmatx);
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->NDTR = Size;
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->PAR = &hspi->Instance->RXDR;
((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->M0AR = (uint8_t *)pRxData;
MODIFY_REG(((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->CR, (DMA_IT_TC ), (DMA_IT_TC ));
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->CR &= (uint32_t)(~DMA_SxCR_DBM);
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->NDTR = Size;
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->PAR = &hspi->Instance->TXDR;
((DMA_Stream_TypeDef *)hspi->hdmatx->Instance)->M0AR = (uint8_t *)pTxData;
MODIFY_REG(((DMA_Stream_TypeDef *)hspi->hdmarx->Instance)->CR, (DMA_IT_TC ), (DMA_IT_TC ));
SET_BIT(hspi->Instance->CFG1, SPI_CFG1_RXDMAEN);// Enable Rx DMA Request
__HAL_DMA_ENABLE(hspi->hdmarx);
__HAL_DMA_ENABLE(hspi->hdmatx);
MODIFY_REG(hspi->Instance->CR2, SPI_CR2_TSIZE, Size);
SET_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN);
__HAL_SPI_ENABLE(hspi);
SET_BIT(hspi->Instance->CR1, SPI_CR1_CSTART);
then I while and clear
while (!( hspi->Instance->SR & 0x08UL)) {}
__HAL_SPI_CLEAR_TXTFFLAG(hspi);
__HAL_SPI_DISABLE(hspi);
CLEAR_BIT(hspi->Instance->CFG1, SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN);//Disable Tx DMA Request
}