2 #include <twr_scheduler.h> 4 #include <twr_system.h> 18 bool async_write_in_progress;
19 bool async_read_in_progress;
39 static uint32_t _twr_uart_brr_t[] =
49 static void _twr_uart_async_write_task(
void *param);
50 static void _twr_uart_async_read_task(
void *param);
51 static void _twr_uart_2_dma_read_task(
void *param);
56 memset(&_twr_uart[channel], 0,
sizeof(_twr_uart[channel]));
73 RCC->APB1ENR |= RCC_APB1ENR_USART4EN;
79 USART4->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
82 USART4->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
85 USART4->BRR = _twr_uart_brr_t[baudrate];
87 NVIC_EnableIRQ(USART4_5_IRQn);
89 _twr_uart[channel].usart = USART4;
109 RCC->CCIPR |= RCC_CCIPR_LPUART1SEL_1 | RCC_CCIPR_LPUART1SEL_0;
112 RCC->APB1ENR |= RCC_APB1ENR_LPUART1EN;
118 LPUART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
121 LPUART1->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
124 LPUART1->BRR = 0x369;
126 NVIC_EnableIRQ(LPUART1_IRQn);
128 _twr_uart[channel].usart = LPUART1;
137 RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
143 USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
146 USART2->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
149 USART2->BRR = _twr_uart_brr_t[baudrate];
151 NVIC_EnableIRQ(USART2_IRQn);
153 _twr_uart[channel].usart = USART2;
171 RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
177 USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UESM;
180 USART1->CR3 = USART_CR3_UCESM | USART_CR3_OVRDIS | USART_CR3_ONEBIT;
183 USART1->BRR = _twr_uart_brr_t[baudrate];
185 NVIC_EnableIRQ(USART1_IRQn);
187 _twr_uart[channel].usart = USART1;
198 _twr_uart[channel].usart->ICR |= USART_ICR_CMCF | USART_ICR_IDLECF | USART_ICR_FECF;
201 _twr_uart[channel].usart->CR2 &= ~USART_CR2_STOP_Msk;
202 _twr_uart[channel].usart->CR2 |= ((uint32_t) setting & 0x03) << USART_CR2_STOP_Pos;
205 _twr_uart[channel].usart->CR1 &= ~(USART_CR1_PCE_Msk | USART_CR1_PS_Msk);
206 _twr_uart[channel].usart->CR1 |= (((uint32_t) setting >> 2) & 0x03) << USART_CR1_PS_Pos;
209 _twr_uart[channel].usart->CR1 &= ~(USART_CR1_M1_Msk | USART_CR1_M0_Msk);
211 uint32_t word_length = setting >> 4;
213 if ((setting & 0x0c) != 0)
218 if (word_length == 0x07)
222 _twr_uart[channel].usart->CR1 |= 1 << USART_CR1_M1_Pos;
224 else if (word_length == 0x09)
226 _twr_uart[channel].usart->CR1 |= 1 << USART_CR1_M0_Pos;
230 _twr_uart[channel].usart->CR1 |= USART_CR1_UE;
232 _twr_uart[channel].initialized =
true;
241 _twr_uart[channel].usart->CR1 &= ~USART_CR1_UE_Msk;
243 if (_twr_uart[channel].async_write_task_id != 0) {
251 NVIC_DisableIRQ(USART4_5_IRQn);
254 RCC->APB1ENR &= ~RCC_APB1ENR_USART4EN;
266 if (_twr_uart[channel].usart == LPUART1)
268 NVIC_DisableIRQ(LPUART1_IRQn);
271 RCC->APB1ENR &= ~RCC_APB1ENR_LPUART1EN;
275 NVIC_DisableIRQ(USART2_IRQn);
278 RCC->APB1ENR &= ~RCC_APB1ENR_USART2EN;
291 NVIC_DisableIRQ(USART1_IRQn);
294 RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN_Msk;
310 _twr_uart[channel].initialized =
false;
315 if (!_twr_uart[channel].initialized || _twr_uart[channel].async_write_in_progress)
320 USART_TypeDef *usart = _twr_uart[channel].usart;
322 size_t bytes_written = 0;
324 if (_twr_uart[channel].usart != LPUART1)
326 twr_system_pll_enable();
329 while (bytes_written != length)
332 while ((usart->ISR & USART_ISR_TXE) == 0)
338 usart->TDR = *((uint8_t *) buffer + bytes_written++);
342 while ((usart->ISR & USART_ISR_TC) == 0)
347 if (_twr_uart[channel].usart != LPUART1)
349 twr_system_pll_disable();
352 return bytes_written;
357 if (!_twr_uart[channel].initialized)
362 USART_TypeDef *usart = _twr_uart[channel].usart;
364 size_t bytes_read = 0;
366 if (_twr_uart[channel].usart != LPUART1)
368 twr_system_pll_enable();
373 while (bytes_read != length)
382 if ((usart->ISR & USART_ISR_RXNE) == 0)
388 *((uint8_t *) buffer + bytes_read++) = usart->RDR;
391 if (_twr_uart[channel].usart != LPUART1)
393 twr_system_pll_disable();
401 _twr_uart[channel].event_handler = event_handler;
402 _twr_uart[channel].event_param = event_param;
407 _twr_uart[channel].write_fifo = write_fifo;
408 _twr_uart[channel].read_fifo = read_fifo;
413 if (!_twr_uart[channel].initialized || _twr_uart[channel].write_fifo == NULL)
418 size_t bytes_written = 0;
420 for (
size_t i = 0; i < length; i += 16)
422 bytes_written +=
twr_fifo_write(_twr_uart[channel].write_fifo, (uint8_t *)buffer + i, length - i > 16 ? 16 : length - i);
425 if (bytes_written != 0)
427 if (!_twr_uart[channel].async_write_in_progress)
431 if (_twr_uart[channel].usart == LPUART1)
433 twr_system_deep_sleep_disable();
437 twr_system_pll_enable();
448 _twr_uart[channel].usart->CR1 |= USART_CR1_TXEIE;
452 _twr_uart[channel].async_write_in_progress =
true;
455 return bytes_written;
460 if (!_twr_uart[channel].initialized || _twr_uart[channel].read_fifo == NULL || _twr_uart[channel].async_read_in_progress)
465 _twr_uart[channel].async_timeout = timeout;
467 _twr_uart[channel].async_read_task_id =
twr_scheduler_register(_twr_uart_async_read_task, (
void *) channel, _twr_uart[channel].async_timeout);
476 .length = _twr_uart[channel].read_fifo->
size,
478 .address_memory = _twr_uart[channel].read_fifo->
buffer,
479 .address_peripheral = (
void *) &_twr_uart[channel].usart->RDR,
491 _twr_uart[channel].usart->CR3 |= USART_CR3_DMAR;
500 _twr_uart[channel].usart->CR1 |= USART_CR1_RXNEIE;
504 if (_twr_uart[channel].usart != LPUART1)
506 twr_system_pll_enable();
509 _twr_uart[channel].async_read_in_progress =
true;
516 if (!_twr_uart[channel].initialized || !_twr_uart[channel].async_read_in_progress)
521 _twr_uart[channel].async_read_in_progress =
false;
531 _twr_uart[channel].usart->CR3 &= ~USART_CR3_DMAR_Msk;
539 _twr_uart[channel].usart->CR1 &= ~USART_CR1_RXNEIE_Msk;
544 if (_twr_uart[channel].usart != LPUART1)
546 twr_system_pll_disable();
556 if (!_twr_uart[channel].initialized || !_twr_uart[channel].async_read_in_progress)
561 size_t bytes_read =
twr_fifo_read(_twr_uart[channel].read_fifo, buffer, length);
566 static void _twr_uart_async_write_task(
void *param)
571 uart->async_write_in_progress =
false;
575 if (uart->usart == LPUART1)
577 twr_system_deep_sleep_enable();
581 twr_system_pll_disable();
584 if (uart->event_handler != NULL)
590 static void _twr_uart_async_read_task(
void *param)
597 if (uart->event_handler != NULL)
610 static void _twr_uart_2_dma_read_task(
void *param)
618 if (_twr_uart_2_dma.length != length)
620 uart->read_fifo->
head = uart->read_fifo->
size - length;
622 _twr_uart_2_dma.length = length;
632 USART_TypeDef *usart = _twr_uart[channel].usart;
634 if ((usart->CR1 & USART_CR1_RXNEIE) != 0 && (usart->ISR & USART_ISR_RXNE) != 0)
639 character = usart->RDR;
647 if ((usart->CR1 & USART_CR1_TXEIE) != 0 && (usart->ISR & USART_ISR_TXE) != 0)
655 usart->TDR = character;
660 usart->CR1 &= ~USART_CR1_TXEIE;
663 usart->CR1 |= USART_CR1_TCIE;
668 if ((usart->CR1 & USART_CR1_TCIE) != 0 && (usart->ISR & USART_ISR_TC) != 0)
671 usart->CR1 &= ~USART_CR1_TCIE;
677 void AES_RNG_LPUART1_IRQHandler(
void)
682 void USART1_IRQHandler(
void)
687 void USART2_IRQHandler(
void)
692 void USART4_5_IRQHandler(
void)
twr_dma_request_t request
DMA channel request.
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
GPIO channel operates in alternate mode AF6.
size_t twr_fifo_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO.
GPIO channel P0, A0, TXD0.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
DMA channel data size 1B.
size_t twr_fifo_irq_write(twr_fifo_t *fifo, const void *buffer, size_t length)
Write data to FIFO from interrupt.
void twr_irq_enable(void)
Enable interrupt requests globally (call can be nested)
bool twr_uart_async_read_start(twr_uart_channel_t channel, twr_tick_t timeout)
Start async reading.
GPIO channel P3, A3, RXD1.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
bool twr_uart_async_read_cancel(twr_uart_channel_t channel)
Cancel async reading.
void twr_gpio_set_pull(twr_gpio_channel_t channel, twr_gpio_pull_t pull)
Set pull-up/pull-down configuration for GPIO channel.
GPIO channel operates in analog mode.
void twr_dma_channel_config(twr_dma_channel_t channel, twr_dma_channel_config_t *config)
Configure DMA channel.
void twr_uart_init(twr_uart_channel_t channel, twr_uart_baudrate_t baudrate, twr_uart_setting_t setting)
Initialize UART channel.
GPIO channel has no pull-up/pull-down.
size_t size
Size of buffer where FIFO holds data.
void * buffer
Pointer to buffer where FIFO holds data.
bool twr_fifo_is_empty(twr_fifo_t *fifo)
Is empty.
void twr_dma_channel_run(twr_dma_channel_t channel)
Start DMA channel.
GPIO channel has pull-up.
DMA channel configuration.
size_t twr_uart_async_read(twr_uart_channel_t channel, void *buffer, size_t length)
Get data that has been received in async mode.
size_t head
Position of FIFO's head.
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
DMA channel direction from peripheral to RAM.
GPIO channel operates in alternate mode AF4.
void twr_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
size_t twr_scheduler_task_id_t
Task ID assigned by scheduler.
uint64_t twr_tick_t
Timestamp data type.
GPIO channel P2, A2, TXD1.
twr_uart_setting_t
UART setting.
size_t twr_uart_read(twr_uart_channel_t channel, void *buffer, size_t length, twr_tick_t timeout)
Read data from UART channel (blocking call)
twr_uart_baudrate_t
UART baudrate.
void twr_uart_set_event_handler(twr_uart_channel_t channel, void(*event_handler)(twr_uart_channel_t, twr_uart_event_t, void *), void *event_param)
Set callback function.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
size_t twr_fifo_irq_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO from interrupt.
GPIO channel P1, A1, RXD0.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
DMA channel priority is high.
twr_uart_event_t
Callback events.
void twr_dma_channel_stop(twr_dma_channel_t channel)
Stop DMA channel.
size_t twr_fifo_read(twr_fifo_t *fifo, void *buffer, size_t length)
Read data from FIFO.
DMA channel mode circular.
void twr_irq_disable(void)
Disable interrupt requests globally (call can be nested)
Structure of FIFO instance.
void twr_uart_deinit(twr_uart_channel_t channel)
Deinitialize UART channel.
twr_uart_channel_t
UART channels.
size_t twr_uart_write(twr_uart_channel_t channel, const void *buffer, size_t length)
Write data to UART channel (blocking call)
void twr_dma_init(void)
Initialize DMA.
#define TWR_TICK_INFINITY
Maximum timestamp value.
void twr_uart_set_async_fifo(twr_uart_channel_t channel, twr_fifo_t *write_fifo, twr_fifo_t *read_fifo)
Set buffers for async transfers.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
size_t twr_uart_async_write(twr_uart_channel_t channel, const void *buffer, size_t length)
Add data to be transmited in async mode.