cancel
Showing results for 
Search instead for 
Did you mean: 

bypass HAL fro spi dma transfer

ulao
Associate III

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.

5 REPLIES 5
gbm
Lead III

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.

ulao
Associate III

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?

gbm
Lead III

Yeah, 80%. 😉

ulao
Associate III

80% of my code is redundant? Or I'm 80% of the way there?

ulao
Associate III

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
}