Replies: 1 comment 6 replies
-
Transmit_receive function must always complete transfers before you return back to LwOW space. That means that use of DMA really makes very high sense if you use operating system and put task to blocked state and run context-switch. That's the demo code I use in one of the private projects. /* Static function declarations */
static uint8_t prv_init(void* arg);
static uint8_t prv_deinit(void* arg);
static uint8_t prv_set_baudrate(uint32_t baud, void* arg);
static uint8_t prv_tx_rx(const uint8_t* tx, uint8_t* rx, size_t len, void* arg);
/* Define structure to functions */
static lwow_ll_drv_t
ow_temp_drv = {
.init = prv_init,
.deinit = prv_deinit,
.set_baudrate = prv_set_baudrate,
.tx_rx = prv_tx_rx
};
/* Define LwOW instance */
static lwow_t ow_temp;
static LL_LPUART_InitTypeDef usart_init;
static lwc_sys_sem_t sync_sem;
/* Static function declarations */
static uint8_t
prv_init(void* arg) {
LL_GPIO_InitTypeDef gpio_init;
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_LPUART2);
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);
/* Select HSI kernel mux clock */
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART2_CLKSOURCE_HSI);
/*************************************/
/** GPIO **/
/*************************************/
/* Configure GPIO pins */
LL_GPIO_StructInit(&gpio_init);
gpio_init.Pin = LL_GPIO_PIN_6 | LL_GPIO_PIN_7;
gpio_init.Mode = LL_GPIO_MODE_ALTERNATE;
gpio_init.Speed = LL_GPIO_SPEED_FREQ_HIGH;
gpio_init.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
gpio_init.Pull = LL_GPIO_PULL_UP;
gpio_init.Alternate = LL_GPIO_AF_10;
LL_GPIO_Init(GPIOB, &gpio_init);
/*************************************/
/** RX DMA **/
/*************************************/
/* DMA1_Channel4_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 6, 0));
NVIC_EnableIRQ(DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn);
/* USARTx RX DMA Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_4, LL_DMAMUX_REQ_LPUART2_RX);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_4, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_4, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_4, LL_LPUART_DMA_GetRegAddr(LPUART2, LL_LPUART_DMA_REG_DATA_RECEIVE));
/* Enable DMA interrupts */
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_4);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_4);
/*************************************/
/** TX DMA **/
/*************************************/
/* DMA1_Channel5_IRQn interrupt configuration */
NVIC_SetPriority(DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 6, 0));
NVIC_EnableIRQ(DMA1_Ch4_7_DMA2_Ch1_5_DMAMUX1_OVR_IRQn);
/* USARTx TX DMA Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_5, LL_DMAMUX_REQ_LPUART2_TX);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_5, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PRIORITY_LOW);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MODE_NORMAL);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_PDATAALIGN_BYTE);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_5, LL_DMA_MDATAALIGN_BYTE);
LL_DMA_SetPeriphAddress(DMA1, LL_DMA_CHANNEL_5, LL_LPUART_DMA_GetRegAddr(LPUART2, LL_LPUART_DMA_REG_DATA_TRANSMIT));
/* Enable DMA interrupts */
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_5);
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_5);
/*************************************/
/** UART **/
/*************************************/
/* Configure UART peripherals */
LL_LPUART_DeInit(LPUART2);
LL_LPUART_StructInit(&usart_init);
usart_init.BaudRate = 9600;
usart_init.DataWidth = LL_LPUART_DATAWIDTH_8B;
usart_init.StopBits = LL_LPUART_STOPBITS_1;
usart_init.Parity = LL_LPUART_PARITY_NONE;
usart_init.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
usart_init.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
LL_LPUART_Init(LPUART2, &usart_init);
LL_LPUART_SetTXFIFOThreshold(LPUART2, LL_LPUART_FIFOTHRESHOLD_1_8);
LL_LPUART_SetRXFIFOThreshold(LPUART2, LL_LPUART_FIFOTHRESHOLD_1_8);
LL_LPUART_DisableFIFO(LPUART2);
return 1;
}
static uint8_t
prv_deinit(void* arg) {
LL_LPUART_DeInit(LPUART2);
return 1;
}
static uint8_t
prv_set_baudrate(uint32_t baud, void* arg) {
usart_init.BaudRate = baud;
LL_LPUART_Init(LPUART2, &usart_init);
return 1;
}
static uint8_t
prv_tx_rx(const uint8_t* tx, uint8_t* rx, size_t len, void* arg) {
uint8_t ret = 1, *r = rx;
const uint8_t* t = tx, use_dma = 1;
if (use_dma && len > 1) {
/* Setup RX DMA */
LL_DMA_ClearFlag_TC4(DMA1);
LL_DMA_ClearFlag_HT4(DMA1);
LL_DMA_ClearFlag_GI4(DMA1);
LL_DMA_ClearFlag_TE4(DMA1);
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_4, (uint32_t)r);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_4, len);
/* Setup TX DMA */
LL_DMA_ClearFlag_TC5(DMA1);
LL_DMA_ClearFlag_HT5(DMA1);
LL_DMA_ClearFlag_GI5(DMA1);
LL_DMA_ClearFlag_TE5(DMA1);
LL_DMA_SetMemoryAddress(DMA1, LL_DMA_CHANNEL_5, (uint32_t)t);
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_5, len);
/* Enable DMA request for UART */
LL_LPUART_EnableDMAReq_TX(LPUART2);
LL_LPUART_EnableDMAReq_RX(LPUART2);
/* Enable UART */
LL_LPUART_Enable(LPUART2);
while (!LL_LPUART_IsActiveFlag_TEACK(LPUART2) || !LL_LPUART_IsActiveFlag_REACK(LPUART2)) {}
/* Acquire semaphore before sync first */
if (lwc_sys_sem_wait(&sync_sem, 100) != LWC_SYS_TIMEOUT) {
/* Start DMA transfers, RX first */
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_4);
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_5);
/* Wait to complete ... semaphore is released in interrupt */
if (lwc_sys_sem_wait(&sync_sem, 100) == LWC_SYS_TIMEOUT) {
ret = 0;
}
lwc_sys_sem_release(&sync_sem);
} else {
ret = 0;
}
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_4);
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_5);
LL_LPUART_Disable(LPUART2);
} else {
/* Start and wait complete with polling mode */
LL_LPUART_Enable(LPUART2);
while (!LL_LPUART_IsActiveFlag_TEACK(LPUART2) || !LL_LPUART_IsActiveFlag_REACK(LPUART2)) {}
for (; len > 0; --len, ++t, ++r) {
LL_LPUART_TransmitData8(LPUART2, *t);
while (!LL_LPUART_IsActiveFlag_TXE(LPUART2)) {}
while (!LL_LPUART_IsActiveFlag_RXNE(LPUART2)) {}
*r = LL_LPUART_ReceiveData8(LPUART2);
}
while (!LL_LPUART_IsActiveFlag_TC(LPUART2)) {}
LL_LPUART_Disable(LPUART2);
}
return ret;
}
/* Interrupt handlers for DMA */
/**
* \brief This function handles DMA1 channel5 global interrupt
*/
void
DMA1_Channel5_IRQHandler(void) {
/* Handle DMA TX interrupt */
if (LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_CHANNEL_5) && LL_DMA_IsActiveFlag_TC5(DMA1)) {
LL_DMA_ClearFlag_TC5(DMA1);
}
if (LL_DMA_IsEnabledIT_TE(DMA1, LL_DMA_CHANNEL_5) && LL_DMA_IsActiveFlag_TE5(DMA1)) {
LL_DMA_ClearFlag_TE5(DMA1);
}
}
/**
* \brief This function handles DMA1 channel4 global interrupt
*/
void
DMA1_Channel4_IRQHandler(void) {
/* Handle DMA TX interrupt */
if (LL_DMA_IsEnabledIT_TC(DMA1, LL_DMA_CHANNEL_4) && LL_DMA_IsActiveFlag_TC4(DMA1)) {
LL_DMA_ClearFlag_TC4(DMA1);
lwc_sys_sem_release(&sync_sem);
}
if (LL_DMA_IsEnabledIT_TE(DMA1, LL_DMA_CHANNEL_4) && LL_DMA_IsActiveFlag_TE4(DMA1)) {
LL_DMA_ClearFlag_TE4(DMA1);
lwc_sys_sem_release(&sync_sem);
}
} |
Beta Was this translation helpful? Give feedback.
6 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi Tilen,
I am using you lwow library together with an STM32F429BG STM32 uC and a configured USART.
I noticed, that your "porting" code uses the USART in Polling mode.
Is there a possibility to use the USART in DMA mode for tx and/or rx direction together with your lwow code ?
Thank you very much for your replay
Best Regards
Jochen
Beta Was this translation helpful? Give feedback.
All reactions