Lazuli
Loading...
Searching...
No Matches
usart.c
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: GPL-3.0-only
3 * This file is part of Lazuli.
4 */
5
14#include <stdint.h>
15#include <stdio.h>
16
17#include <Lazuli/common.h>
18#include <Lazuli/config.h>
19#include <Lazuli/serial.h>
22#include <Lazuli/sys/compiler.h>
23#include <Lazuli/sys/kernel.h>
24
28static Usart * const usart = (Usart*)&UCSR0A;
29
38
39int
40putchar(int c)
41{
42 const unsigned char value = (unsigned char)c;
43
44 while (!(usart->ucsr0a & UCSR0A_UDRE0));
45
46 usart->udr0 = value;
47
48 return value;
49}
50
51int
52puts(const char * s)
53{
54 const char newLine[] = LZ_CONFIG_SERIAL_NEWLINE;
55 uint8_t i;
56
57 if (NULL == s) {
58 return EOF;
59 }
60
61 while ('\0' != *s) {
62 putchar(*s);
63 ++s;
64 }
65
66 for (i = 0; i < sizeof(newLine) - 1; ++i) {
67 putchar(newLine[i]);
68 }
69
70 return 1;
71}
72
78static enum Lz_SerialEnableFlags
80{
82
83 if (usart->ucsr0b & UCSR0B_TXEN0) {
85 }
86
87 if (usart->ucsr0b & UCSR0B_RXEN0) {
89 }
90
91 return flags;
92}
93
99static enum Lz_SerialStopBits
101{
102 if (usart->ucsr0c & UCSR0C_USBS0) {
104 }
105
107}
108
114static enum Lz_SerialParityBit
116{
117 if (usart->ucsr0c & UCSR0C_UPM01) {
118 if (usart->ucsr0c & UCSR0C_UPM00) {
120 }
121
123 }
124
125 if (usart->ucsr0c & UCSR0C_UPM00) {
126 Kernel_Panic();
127 }
128
130}
131
137static enum Lz_SerialSize
139{
140 if (usart->ucsr0b & UCSR0B_UCSZ02) {
141 Kernel_Panic();
142 }
143
144 if (usart->ucsr0c & UCSR0C_UCSZ01) {
145 if (usart->ucsr0c & UCSR0C_UCSZ00) {
146 return LZ_SERIAL_SIZE_8;
147 }
148
149 return LZ_SERIAL_SIZE_7;
150 }
151
152 if (usart->ucsr0c & UCSR0C_UCSZ00) {
153 return LZ_SERIAL_SIZE_6;
154 }
155
156 return LZ_SERIAL_SIZE_5;
157}
158
164static void
166{
167 if (flags & LZ_SERIAL_ENABLE_TRANSMIT) {
169 } else {
170 usart->ucsr0b &= ~UCSR0B_TXEN0;
171 }
172
173 if (flags & LZ_SERIAL_ENABLE_RECEIVE) {
175 } else {
176 usart->ucsr0b &= ~UCSR0B_RXEN0;
177 }
178}
179
183static void
185{
186 usart->ucsr0c &= ~UCSR0C_USBS0;
187}
188
192static void
194{
196}
197
204PROGMEM static
205void (* const setStopBits[])(void) = {
208};
209
212(
213 ELEMENTS_COUNT(setStopBits) == __LZ_SERIAL_STOP_BITS_ENUM_END,
214 all_entries_of_enum_Lz_SerialStopBits_must_be_set_in_setStopBits
215);
223static void
224SetStopBits(const enum Lz_SerialStopBits stopBits)
225{
226 void (*jump)(void);
227
229 if (stopBits <= __LZ_SERIAL_STOP_BITS_ENUM_BEGIN ||
230 stopBits >= __LZ_SERIAL_STOP_BITS_ENUM_END) {
231 Kernel_Panic();
232 }
233 }
234
236 jump();
237}
238
242static void
247
251static void
253{
255 usart->ucsr0c &= ~UCSR0C_UPM00;
256}
257
261static void
266
273PROGMEM static
274void (* const setParityBit[])(void) = {
278};
279
282(
283 ELEMENTS_COUNT(setParityBit) == __LZ_SERIAL_PARITY_BIT_ENUM_END,
284 all_entries_of_enum_Lz_SerialParityBit_must_be_set_in_setParityBit
285);
293static void
294SetParityBit(const enum Lz_SerialParityBit parityBit)
295{
296 void (*jump)(void);
297
299 if (parityBit <= __LZ_SERIAL_PARITY_BIT_ENUM_BEGIN ||
300 parityBit >= __LZ_SERIAL_PARITY_BIT_ENUM_END) {
301 Kernel_Panic();
302 }
303 }
304
306 jump();
307}
308
312static void
314{
315 usart->ucsr0b &= ~UCSR0B_UCSZ02;
317}
318
322static void
324{
325 usart->ucsr0b &= ~UCSR0B_UCSZ02;
326 usart->ucsr0c &= ~UCSR0C_UCSZ01;
328}
329
333static void
335{
336 usart->ucsr0b &= ~UCSR0B_UCSZ02;
338 usart->ucsr0c &= ~UCSR0C_UCSZ00;
339}
340
344static void
346{
347 usart->ucsr0b &= ~UCSR0B_UCSZ02;
349}
350
356PROGMEM static
357void (* const setSize[])(void) = {
358 SetSize5,
359 SetSize6,
360 SetSize7,
361 SetSize8
362};
363
366(
367 ELEMENTS_COUNT(setSize) == __LZ_SERIAL_SIZE_ENUM_END,
368 all_entries_of_enum_Lz_SerialSize_must_be_set_in_setSize
369);
377static void
378SetSize(const enum Lz_SerialSize size)
379{
380 void (* jump)(void);
381
383 if (size <= __LZ_SERIAL_SIZE_ENUM_BEGIN ||
384 size >= __LZ_SERIAL_SIZE_ENUM_END) {
385 Kernel_Panic();
386 }
387 }
388
390 jump();
391}
392
399PROGMEM static const
401 (uint16_t)416,
402 (uint16_t)207,
403 (uint16_t)103,
404 (uint16_t)51
405};
406
409(
410 ELEMENTS_COUNT(serialSpeedRegisterValue) == __LZ_SERIAL_SPEED_ENUM_END,
411 all_entries_of_enum_Lz_SerialSpeed_must_be_set_in_serialSpeedRegisterValue
412);
420static void
421SetSpeed(const enum Lz_SerialSpeed speed)
422{
423 uint16_t registerValue;
424
426 if (speed <= __LZ_SERIAL_SPEED_ENUM_BEGIN ||
427 speed >= __LZ_SERIAL_SPEED_ENUM_END) {
428 Kernel_Panic();
429 }
430 }
431
432 registerValue = Arch_LoadU16FromProgmem(&serialSpeedRegisterValue[speed]);
433
434 usart->ubrr0l = LO8(registerValue);
435 usart->ubrr0h = HI8(registerValue);
436
437 currentSerialSpeed = speed;
438}
439
440void
442{
443 configuration->enableFlags = GetEnablingStatus();
444 configuration->stopBits = GetStopBits();
445 configuration->parityBit = GetParityBit();
446 configuration->size = GetSize();
447 configuration->speed = currentSerialSpeed;
448}
449
450void
452{
453 InterruptsStatus interruptsStatus;
454
455 /* Wait all receive and transmit operations has completed */
456 /* TODO: This one doesn't work as expected */
457 /* while (!(usart->ucsr0a & UCSR0A_TXC0) || (usart->ucsr0a & UCSR0A_RXC0)); */
458
459 /*
460 * From the ATmega328p datasheet:
461 * "For interrupt driven USART operation, the Global Interrupt Flag should be
462 * cleared (and interrupts globally disabled) when doing the initialization."
463 */
465 interruptsStatus = Arch_DisableInterruptsGetStatus();
466 }
467
468 SetEnablingStatus(configuration->enableFlags);
469 SetStopBits(configuration->stopBits);
470 SetParityBit(configuration->parityBit);
471 SetSize(configuration->size);
472 SetSpeed(configuration->speed);
473
475 Arch_RestoreInterruptsStatus(interruptsStatus);
476 }
477}
478
479void
481{
482 const Lz_SerialConfiguration serialConfiguration = {
488 };
489
490 Arch_SetSerialConfiguration(&serialConfiguration);
491
492 /* Set USART to asynchronous */
494}
unsigned int uint16_t
Represents a unsigned integer type with width of exactly 16 bits.
Definition stdint.h:94
unsigned char uint8_t
Represents a unsigned integer type with width of exactly 8 bits.
Definition stdint.h:89
Architecture Abstraction API.
void(*)(void) Arch_LoadFunctionPointerFromProgmem(const void *source)
Return a function pointer stored in program memory.
Definition arch.h:133
InterruptsStatus Arch_DisableInterruptsGetStatus(void)
Disable all interrupts and return the previous interrupts status.
void Arch_RestoreInterruptsStatus(const InterruptsStatus interruptsStatus)
Restore a previously saved interrupts status.
uint8_t InterruptsStatus
Define the type used to store interrupts status.
Definition arch.h:154
uint16_t Arch_LoadU16FromProgmem(const void *source)
Return a double-byte word stored in program memory.
Basic type definitions and useful macros.
#define NULL
NULL pointer.
Definition common.h:70
#define STATIC_ASSERT(C, M)
Perform an assertion at compile time.
Definition common.h:65
#define HI8(X)
Take the high byte of a 16-bit value.
Definition common.h:208
#define CLEAR_BITS(V, T, X)
Clear the corresponding bits of X in the value V of type T.
Definition common.h:158
#define ELEMENTS_COUNT(X)
Get the number of elements in a statically initialized array.
Definition common.h:266
#define LO8(X)
Take the low byte of a 16-bit value.
Definition common.h:201
Macro aliases on compiler facilities.
Include appropriate config file.
const bool LZ_CONFIG_SERIAL_USE_INTERRUPTS
When 1, serial input and output will use interrupt blocking.
#define LZ_CONFIG_SERIAL_NEWLINE
The sequence to use for new lines on the serial line.
const bool LZ_CONFIG_CHECK_WRONG_ENUM_ENTRIES_IN_SERIAL
When 1, check for enum parameters that are over the admissible values defined by the enum.
void Kernel_Panic(void)
Kernel panic.
Definition kernel.c:84
Kernel symbols definition.
Serial port configuration interface.
Lz_SerialSpeed
Define the baud rate of the serial line.
Definition serial.h:175
@ LZ_SERIAL_SPEED_4800
Use a 4800 baud rate on the serial line.
Definition serial.h:194
Lz_SerialParityBit
Define the kind of parity bit to use on serial line.
Definition serial.h:90
@ LZ_SERIAL_PARITY_EVEN
Use even parity bit.
Definition serial.h:109
@ LZ_SERIAL_PARITY_ODD
Use odd parity bit.
Definition serial.h:114
@ LZ_SERIAL_PARITY_NONE
Use no parity bit.
Definition serial.h:104
Lz_SerialSize
Define the size of the character used on serial line.
Definition serial.h:130
@ LZ_SERIAL_SIZE_6
Use 6-bit character size on serial line.
Definition serial.h:149
@ LZ_SERIAL_SIZE_7
Use 7-bit character size on serial line.
Definition serial.h:154
@ LZ_SERIAL_SIZE_5
Use 5-bit character size on serial line.
Definition serial.h:144
@ LZ_SERIAL_SIZE_8
Use 8-bit character size on serial line.
Definition serial.h:159
Lz_SerialEnableFlags
Define flags for enabling/disabling serial transmission/reception.
Definition serial.h:30
@ LZ_SERIAL_ENABLE_RECEIVE
Enable serial reception.
Definition serial.h:44
@ LZ_SERIAL_DISABLE_ALL
Disable both serial transmission and reception.
Definition serial.h:34
@ LZ_SERIAL_ENABLE_TRANSMIT
Enable serial transmission.
Definition serial.h:39
Lz_SerialStopBits
Define the number of stop bits to use on serial line.
Definition serial.h:55
@ LZ_SERIAL_STOP_BITS_1
Use 1 stop bit.
Definition serial.h:69
@ LZ_SERIAL_STOP_BITS_2
Use 2 stop bits.
Definition serial.h:74
stdio standard header file.
#define EOF
Defines the End-Of-File constant.
Definition stdio.h:24
Represents the configuration of a serial interface.
Definition serial.h:222
enum Lz_SerialParityBit parityBit
The kind of parity bit.
Definition serial.h:236
enum Lz_SerialStopBits stopBits
The number of stop bits.
Definition serial.h:231
enum Lz_SerialEnableFlags enableFlags
The enable/disable Tx/Rx options.
Definition serial.h:226
enum Lz_SerialSize size
The size of the character.
Definition serial.h:241
enum Lz_SerialSpeed speed
The baud rate.
Definition serial.h:246
Describes the memory mapping for the USART.
Definition usart.h:49
volatile uint8_t ucsr0b
USART Control and Status Register B.
Definition usart.h:51
volatile uint8_t ucsr0c
USART Control and Status Register C.
Definition usart.h:52
volatile uint8_t ucsr0a
USART Control and Status Register A.
Definition usart.h:50
volatile uint8_t ubrr0l
USART Baud Rate Register low
Definition usart.h:54
volatile uint8_t udr0
USART I/O Data Register
Definition usart.h:56
volatile uint8_t ubrr0h
USART Baud Rate Register high
Definition usart.h:55
static const uint16_t serialSpeedRegisterValue[]
Jump table containing the setting values of UBRR0L and UBRR0H registers for baud rates defined in Lz_...
Definition usart.c:400
static void SetSpeed(const enum Lz_SerialSpeed speed)
Set the baud rate of the serial line.
Definition usart.c:421
static void SetStopBits(const enum Lz_SerialStopBits stopBits)
Set the number of stop bits of the serial line.
Definition usart.c:224
static void SetSize7(void)
Set character size to 7 bits.
Definition usart.c:334
static enum Lz_SerialSpeed currentSerialSpeed
The current serial baud rate.
Definition usart.c:37
static void SetStopBits1(void)
Set USART to use 1 stop bit.
Definition usart.c:184
static enum Lz_SerialStopBits GetStopBits(void)
Retrieve the number of stop bits currently used by the serial line.
Definition usart.c:100
static enum Lz_SerialSize GetSize(void)
Retrieve the character size currently used by the serial line.
Definition usart.c:138
static Usart *const usart
A constant pointer to the memory mapped Usart structure.
Definition usart.c:28
static enum Lz_SerialEnableFlags GetEnablingStatus(void)
Retrieve the enabling status of the serial line.
Definition usart.c:79
static enum Lz_SerialParityBit GetParityBit(void)
Retrieve the kind of parity currently used by the serial line.
Definition usart.c:115
static void SetSize8(void)
Set character size to 8 bits.
Definition usart.c:345
void Arch_GetSerialConfiguration(Lz_SerialConfiguration *const configuration)
Retrieve the current configuration of the serial line.
Definition usart.c:441
void Arch_SetSerialConfiguration(const Lz_SerialConfiguration *const configuration)
Configure the serial line according to the parameter.
Definition usart.c:451
static void SetSize6(void)
Set character size to 6 bits.
Definition usart.c:323
static void SetParityBitEven(void)
Set even parity bit.
Definition usart.c:252
static void SetParityBitNone(void)
Set no parity bit.
Definition usart.c:243
static void(*const setSize[])(void)
Jump table to functions setting character sizes of the serial line.
Definition usart.c:357
static void SetParityBit(const enum Lz_SerialParityBit parityBit)
Set the kind of parity bit of the serial line.
Definition usart.c:294
static void(*const setStopBits[])(void)
Jump table to functions setting the number of stop bits of the serial line.
Definition usart.c:205
void Arch_InitSerial(void)
Initialize serial line with default configuration at system startup.
Definition usart.c:480
static void SetStopBits2(void)
Set USART to use 2 stop bits.
Definition usart.c:193
int puts(const char *s)
Transmit the NUL-terminated string s followed by a trailing newline on the serial line,...
Definition usart.c:52
static void(*const setParityBit[])(void)
Jump table to functions setting the kind of parity of the serial line.
Definition usart.c:274
static void SetSize5(void)
Set character size to 5 bits.
Definition usart.c:313
static void SetParityBitOdd(void)
Set odd parity bit.
Definition usart.c:262
static void SetSize(const enum Lz_SerialSize size)
Set the character size of the serial line.
Definition usart.c:378
int putchar(int c)
Transmit a single character on the serial line.
Definition usart.c:40
static void SetEnablingStatus(const enum Lz_SerialEnableFlags flags)
Set the enabling/disabling of Tx/Rx of the serial line.
Definition usart.c:165
USART API for the ATmega328P.
@ UCSR0A_UDRE0
USART Data Register Empty
Definition usart.h:65
@ UCSR0B_UCSZ02
Character Size 2
Definition usart.h:82
@ UCSR0B_RXEN0
Receiver Enable
Definition usart.h:80
@ UCSR0B_TXEN0
Transmitter Enable
Definition usart.h:81
@ UCSR0C_UMSEL01
USART Mode Select 1.
Definition usart.h:91
@ UCSR0C_UPM01
Parity Mode 1
Definition usart.h:93
@ UCSR0C_UCSZ00
Character Size 0
Definition usart.h:97
@ UCSR0C_UMSEL00
USART Mode Select 0.
Definition usart.h:92
@ UCSR0C_UPM00
Parity Mode 0
Definition usart.h:94
@ UCSR0C_USBS0
Stop Bit Select
Definition usart.h:95
@ UCSR0C_UCSZ01
Character size 1
Definition usart.h:96
#define UCSR0A
USART Control and Status Register A.
Definition usart.h:29