Hierodule 1.6.2
Utility module set for STM32 MCUs
Loading...
Searching...
No Matches
USART Module

The module basically lets you

  • Transmit a single byte or a string.
  • Easily assign an ISR to handle the incoming bytes.
  • Maintain a ring buffer with arbitrary length for the received data.

Also provided are routines to

  • Unidirectionally parse the ring buffer
  • Toggle the RXNEIE & RE control bits
  • Check the RXNE & TXE flags.
  • Initialize or destroy USART wrapper instances dynamically.

HIERODULE_USART_Wrapper is the main item in the module, with which you can access the variables related to the ring buffer and use the module routines to implement your RXNE ISR.

The module does not address peripheral configuration and initialization, it is assumed those are performed beforehand. Make sure to have configured the baudrate and GPIO modes of the pins for your peripheral.

Also notice that the USART IRQs are defined in the module's source file. The compiler will throw a multiple definition error if an IRQ is defined somewhere else.

To start using the module, first thing you need is a double pointer to HIERODULE_USART_Wrapper to create an instance for the USART peripheral.

HIERODULE_USART_Wrapper **My_USART1_Wrapper = NULL;
Struct that keeps variables for the ring buffer, a pointer to the USART peripheral and a pointer to t...

It has to be a double pointer, since the wrapper initializer passes you the wrapper pointer defined in the module by reference. The wrapper instance is handled in the module with a pointer and not with a variable of type HIERODULE_USART_Wrapper, since you use pointers for dynamic memory allocation.

Secondly, you need a void function with a uint8_t parameter for the RXNE ISR. You might as well just pass NULL if you intend to use the received data somewhere else. Or you can even maintain an array for the function pointers (i.e. void (*)(uint8_t)) to switch between ISRs on the fly.
Here's a simple example that assigns a task to the ISR that sums up the bytes received at USART1 and initializes the wrapper for USART1 with a ring buffer that's 12 bytes long.

uint32_t Acc = 0;
void Add(uint8_t NewValue)
{
Acc += NewValue;
}
/*
...
*/
My_USART1_Wrapper = HIERODULE_USART_InitWrapper(USART1, 12, Add);
HIERODULE_USART_Wrapper ** HIERODULE_USART_InitWrapper(USART_TypeDef *USART, uint16_t RX_BufferSize, void(*RX_Handler)(uint8_t))
Initializes a wrapper for the specified USART peripheral.


Once initialized, the wrapper may be used to transmit data.

uint8_t SingleByte = '!';
HIERODULE_USART_TransmitByte(*My_USART1_Wrapper, SingleByte);
HIERODULE_USART_TransmitString(*My_USART1_Wrapper, "Hello World!\n");
void HIERODULE_USART_TransmitByte(HIERODULE_USART_Wrapper *Wrapper, uint8_t Byte)
Transmits a single byte.
void HIERODULE_USART_TransmitString(HIERODULE_USART_Wrapper *Wrapper, char *String)
Transmits a string.


You need to enable the RE and RXNEIE bits at the control register to enable the USART IRQ and start receiving data. Simply call:

HIERODULE_USART_Enable_IT_RXNE(*My_USART1_Wrapper);
void HIERODULE_USART_Enable_IT_RXNE(HIERODULE_USART_Wrapper *Wrapper)
Enables the RX not empty interrupt of the USART peripheral , also enables the RE bit of the control r...


You can also disable the receive control bits via:

HIERODULE_USART_Disable_IT_RXNE(*My_USART1_Wrapper);
void HIERODULE_USART_Disable_IT_RXNE(HIERODULE_USART_Wrapper *Wrapper)
Disables the RX not empty interrupt of the USART peripheral , also disables the RE bit of the control...


You can "release" the instance of your wrapper to free memory:

HIERODULE_USART_ReleaseWrapper(*My_USART1_Wrapper);
void HIERODULE_USART_ReleaseWrapper(HIERODULE_USART_Wrapper *Wrapper)
Frees the memory allocated to a USART wrapper and clears USART status flags and control bits.

Keep in mind this only frees the wrapper pointer in the module and not your double pointer that points to it. It's best to free and nullify that, as well:

free(My_USART1_Wrapper);
My_USART1_Wrapper = NULL;

Notice that trying to access a freed memory address might turn out ugly for your run-time. However, you can reuse your double pointer to re-initialize the USART peripheral after releasing it.