2020-05-19 05:49 PM
Due to pin restrictions, I've forced to send data on two GPIO pins not wired to any uart on the 152. I've found this AP and went ahead tried porting the libraries to this board series. I changed the appropriate names for DMA regs and the like without issue and it compiles. However, nothing happens on the GPIO when the functions are called (Besides the init).
In debug I can see it setup the transmit to send a byte, however the flag never gets cleared and remains in busy state. This has me thinking its the timer setup or dma and could be a inconsistency between the two series.
This is the transmit function:
HAL_StatusTypeDef HAL_UART_Emul_Transmit_DMA(UART_Emul_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
uint32_t tmp = 0;
tmp = huart->State;
if ((tmp == HAL_UART_EMUL_STATE_READY) || (tmp == HAL_UART_EMUL_STATE_BUSY_RX))
{
if ((pData == NULL ) || (Size == 0))
{
return HAL_ERROR;
}
huart->TxXferSize = Size;
huart->pTxBuffPtr = pData;
huart->TxXferCount = 1;
huart->ErrorCode = HAL_UART_EMUL_ERROR_NONE;
/* Check if a receive process is ongoing or not */
if (huart->State == HAL_UART_EMUL_STATE_BUSY_RX)
{
huart->State = HAL_UART_EMUL_STATE_BUSY_TX_RX;
}
else
{
huart->State = HAL_UART_EMUL_STATE_BUSY_TX;
}
/* Set the UART Emulation DMA transfer complete callback */
TimHandle.hdma[TIM_DMA_ID_CC1]->XferCpltCallback = UART_Emul_DMATransmitCplt;
/* Set the DMA error callback */
TimHandle.hdma[TIM_DMA_ID_CC1]->XferErrorCallback = UART_Emul_DMAError;
/* Format first Frame to be sent */
if (huart->TxXferCount == FIRST_BYTE)
{
/* Format Frame to be sent */
UART_Emul_TransmitFormatFrame(huart, *(pData), (uint32_t*)pFirstBuffer_Tx);
/* Enable the Capture compare channel */
TIM_CCxChannelCmd(TIM3, TIM_CHANNEL_1, TIM_CCx_ENABLE);
/* Send Frames */
UART_Emul_TransmitFrame(huart);
}
if ((huart->TxXferCount == FIRST_BYTE) && (huart->TxXferCount < Size))
{
/* Format Second Frame to be sent */
UART_Emul_TransmitFormatFrame(huart, *(pData + huart->TxXferCount), (uint32_t*)pSecondBuffer_Tx);
}
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
I don't have anything in the callback functions because I only care about transmitting at this point. The ISRs I can't setup breakpoints in IAR for some reason so I have no idea if they're being called.
Basically, does anyone know if there is some limitation in the L1 series that wouldn't allow this port from the F4 series?
Thanks!
Riker
2020-05-19 10:37 PM
I've had this working on stm32f4, stm32f7 and stm32l4. Looking at the reference manual for L152, I don't see anything that would prevent it from working.
I see that the DMA Request Mapping is much simpler on L152 than F405, so you'll have to plan carefully which timer, timer-channel and DMA channel to use. I seem to remember that this was partly hidden by the HAL code. You'll have to study the DMA and timer sections of reference manuals for both your L152 and the original F4.
I suppose you could test parts of the code by e.g. telling the DMA to work in MEM2MEM mode so it doesn't wait for the timer to transfer each bit. And read the timer a few times to verify it is counting.
Good luck,
Danish
2020-05-19 11:05 PM
Read out and check/post the relevant TIM/DMA/GPIO registers content. Basically, as Danish said, observe if timer runs, and if NDTR in DMA counts.
JW
2020-05-20 03:28 PM
Thank you Danish for you response. So you have much experience doing this port.
Did you ever have to mess with the IRQ handlers? I cannot tell if the interrupts are setup or not. I find no reference to them besides where they are defined.
In regards to DMA: L1 has channels while F4 has streams. So instead of DMA2_Stream1, I did DMA2_Channel1. I read from this post: https://community.st.com/s/question/0D50X00009XkiEnSAJ/what-is-the-difference-between-channels-and-streams but didn't really grasp if they operated differently.
This is how I setup the DMA_Channel1. Essentially replacing Stream with channel and commenting out Init functionality it didn't have.
static void UART_Emul_SetConfig_DMATx(void)
{
/* Init Idle */
HAL_GPIO_WritePin((huart_emul->TxPortName), (huart_emul->Init.TxPinNumber), GPIO_PIN_SET);
/*##-1- Configure DMA For UART Emulation TX #############################*/
/* Set the parameters to be configured */
// hdma_tx.Init.Channel = DMA_CHANNEL_6; /* DMA_CHANNEL_6 */
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; /* Transfer mode */
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; /* Peripheral increment mode Disable */
hdma_tx.Init.MemInc = DMA_MINC_ENABLE; /* Memory increment mode Enable */
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD ; /* Peripheral data alignment : Word */
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ; /* memory data alignment : Word */
hdma_tx.Init.Mode = DMA_NORMAL; /* Normal DMA mode */
hdma_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH; /* priority level : very high */
//hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; /* FIFO mode disabled */
//hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; /* FIFO threshold full configuration */
//hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE; /* Memory burst */
//hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; /* Peripheral burst */
/* Set hdma_tim instance */
hdma_tx.Instance = DMA2_Channel1;
hdma_tx.Parent = TimHandle.hdma[1];
/* Link hdma_tim to hdma[ ] ( channel Tx or Rx) */
__HAL_LINKDMA(&TimHandle, hdma[1] , hdma_tx);
/* Initialize TIMx DMA handle */
HAL_DMA_Init(TimHandle.hdma[1]);
/*##-2- NVIC configuration for DMA transfer complete interrupt ###########*/
HAL_NVIC_SetPriority(DMA2_Channel1_IRQn, 3, 3);
HAL_NVIC_EnableIRQ(DMA2_Channel1_IRQn);
}
In regards to Timer: F4 example had been using TIM1, but L1 doesn't have that for whatever reason so I did TIM3.
within -> static void UART_Emul_SetConfig (UART_Emul_HandleTypeDef *huart)
TimHandle.Instance = TIM3;
TimHandle.Init.Period = bit_time;
TimHandle.Init.Prescaler = 0;
TimHandle.Init.ClockDivision = 0;
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
HAL_TIM_Base_Init(&TimHandle);
I'm going to continue putting my nose in the reference manual for clues.
2020-05-23 03:28 AM
Hi,
I am using UART_EMUL_HAL_Driver for STM32L476ZE referring stm32f4,
but in data reception some times i am getting wrong data .
do you have any solution ?
2020-05-23 03:55 AM
There are no magic solutions, it's your program, you have to solve this yourself.
Debug it as you would debug your own code. Consider false starts due to noise on line, consider timing problems due to interrupt latencies.
JW