Skip to content

Commit a54b65c

Browse files
authored
Support additional USART baud rates. (#21)
* Support additional USART baud rates. * Remove BAUD macro that is no longer needed.
1 parent 8ac9cd6 commit a54b65c

8 files changed

Lines changed: 162 additions & 81 deletions

File tree

.vscode/c_cpp_properties.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
],
99
"defines": [
1010
"MCU=\"atmega1284p\"",
11-
"BAUD=19200",
12-
"F_CPU=8000000",
11+
"F_CPU=16000000",
1312
"_DEBUG=1",
1413
"_BUILD_TYPE=\"Debug\"",
1514
"_FEATURE_ON=1",
1615
"_FEATURE_OFF=0",
1716
"_FEATURE_ENABLE_DEBUG_PORT=_FEATURE_ON",
17+
"_FEATURE_OPT_DEBUG_PORT_BAUD=USART_BAUD_38400",
1818
"_CONFIG_DFLT_WPM=200",
1919
"_CONFIG_DFLT_WPM_ELEMENT_SCALE=1.0f",
2020
"_CONFIG_DFLT_BUZZER_ENABLED=true",

CMakeLists.txt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ set(DEVICE_MCU atmega1284p
3737
CACHE STRING "The MCU model to compile for.")
3838
set(DEVICE_F_CPU 16000000
3939
CACHE STRING "The device's CPU frequency, in Hz.")
40-
set(DEVICE_BAUD 19200
41-
CACHE STRING "The default USART baud rate, in bits per second.")
4240

4341
# -- Project Setup --
4442

@@ -75,7 +73,6 @@ add_compile_definitions(
7573
# Device information
7674
MCU="${DEVICE_MCU}"
7775
F_CPU=${DEVICE_F_CPU}
78-
BAUD=${DEVICE_BAUD}
7976
# Build type
8077
_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
8178
$<$<CONFIG:Debug>:_DEBUG=1>

configuration.cmake

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ add_compile_definitions(
1818
_FEATURE_ENABLE_DEBUG_PORT=${FEATURE_ENABLE_DEBUG_PORT}
1919
)
2020

21+
# -- Feature Options --
22+
23+
# Define values
24+
set(FEATURE_OPT_DEBUG_PORT_BAUD USART_BAUD_38400
25+
CACHE STRING "Baud rate for debug port. (usart_baud_t)")
26+
27+
# Set compile definitions
28+
add_compile_definitions(
29+
_FEATURE_OPT_DEBUG_PORT_BAUD=${FEATURE_OPT_DEBUG_PORT_BAUD}
30+
)
31+
2132
# -- Configuration Defaults --
2233

2334
# Define values

src/main/application/debug_port.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ void debug_port_init( void )
266266
usart_init( DEBUG_PORT_USART,
267267
true,
268268
true,
269+
_FEATURE_OPT_DEBUG_PORT_BAUD,
269270
USART_DATA_BITS_8,
270271
USART_STOP_BITS_1,
271272
USART_PARITY_DISABLED );

src/main/drivers/gpio.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,19 @@
2424

2525
// Helper macro for the register table below
2626
#define gpio_reg( _port, _pin, _pcmsk_reg ) \
27-
{ register_addr( DDR ## _port ), \
28-
register_addr( PIN ## _port ), \
29-
register_addr( PORT ## _port ), \
30-
register_addr( PCMSK ## _pcmsk_reg ), \
27+
{ register8_addr( DDR ## _port ), \
28+
register8_addr( PIN ## _port ), \
29+
register8_addr( PORT ## _port ), \
30+
register8_addr( PCMSK ## _pcmsk_reg ), \
3131
_pin }
3232

3333
// This array must be in the same order as the gpio_pin_t enumeration
3434
static struct
3535
{
36-
register_t ddr_reg; /**< DDR register. */
37-
register_t in_reg; /**< PIN register. */
38-
register_t out_reg; /**< PORT register. */
39-
register_t pcmsk_reg; /**< PCMSK register. */
36+
register8_t ddr_reg; /**< DDR register. */
37+
register8_t in_reg; /**< PIN register. */
38+
register8_t out_reg; /**< PORT register. */
39+
register8_t pcmsk_reg; /**< PCMSK register. */
4040
uint8_t index; /**< Pin index in port. */
4141
}
4242
const s_reg_tbl[] =

src/main/drivers/usart.c

Lines changed: 93 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include <avr/interrupt.h>
1919
#include <avr/io.h>
2020
#include <util/delay.h>
21-
#include <util/setbaud.h>
2221

2322
#include "core/sys.h"
2423
#include "drivers/usart.h"
@@ -29,21 +28,23 @@
2928
/* --------------------------------------------------- CONSTANTS ---------------------------------------------------- */
3029

3130
#define usart_reg( _idx ) \
32-
{ register_addr( UDR ## _idx ), \
33-
register_addr( UCSR ## _idx ## A ), \
34-
register_addr( UCSR ## _idx ## B ), \
35-
register_addr( UCSR ## _idx ## C ), \
36-
register_addr( UBRR ## _idx ## H ), \
37-
register_addr( UBRR ## _idx ## L ) }
31+
{ register8_addr( UDR ## _idx ), \
32+
register8_addr( UCSR ## _idx ## A ), \
33+
register8_addr( UCSR ## _idx ## B ), \
34+
register8_addr( UCSR ## _idx ## C ), \
35+
register16_addr( UBRR ## _idx ), \
36+
register8_addr( UBRR ## _idx ## H ), \
37+
register8_addr( UBRR ## _idx ## L ) }
3838

3939
static struct
4040
{
41-
register_t udr; /**< The UDRn register for this USART. */
42-
register_t ucsra; /**< The UCSRnA register for this USART. */
43-
register_t ucsrb; /**< The UCSRnB register for this USART. */
44-
register_t ucsrc; /**< The UCSRnC register for this USART. */
45-
register_t ubrrh; /**< The UBRRnH register for this USART. */
46-
register_t ubrrl; /**< The UBRRnL register for this USART. */
41+
register8_t udr; /**< The UDRn register for this USART. */
42+
register8_t ucsra; /**< The UCSRnA register for this USART. */
43+
register8_t ucsrb; /**< The UCSRnB register for this USART. */
44+
register8_t ucsrc; /**< The UCSRnC register for this USART. */
45+
register16_t ubrr; /**< The UBRRn register for this USART. */
46+
register8_t ubrrh; /**< The UBRRnH register for this USART. */
47+
register8_t ubrrl; /**< The UBRRnL register for this USART. */
4748
}
4849
const s_reg_tbl[] =
4950
{
@@ -69,14 +70,17 @@ _Static_assert( array_count( s_reg_tbl ) == USART_COUNT, "Invalid register table
6970
/**
7071
* @def TX_DELAY_US
7172
* @brief The time to wait before trying again if the TX buffer is full, in microseconds.
73+
* @note This macro uses `19200` as a conservative estimated baud rate.
7274
*/
73-
#define TX_DELAY_US ( ( ( USEC_PER_MSEC * MSEC_PER_SEC ) / ( unsigned int )BAUD ) * 2 )
75+
#define TX_DELAY_US ( ( ( USEC_PER_MSEC * MSEC_PER_SEC ) / ( unsigned int )19200 ) * BITS_PER_BYTE )
7476

7577
/* ----------------------------------------------------- MACROS ----------------------------------------------------- */
7678

7779
// Validation macros
7880
#define validate_usart( _usart ) \
7981
assert_always( ( _usart ) < USART_COUNT )
82+
#define validate_baud( _baud ) \
83+
assert_always( ( _baud ) < USART_BAUD_COUNT )
8084
#define validate_data_bits( _data_bits ) \
8185
assert_always( ( _data_bits ) < USART_DATA_BITS_COUNT )
8286
#define validate_parity( _parity ) \
@@ -95,6 +99,8 @@ _Static_assert( array_count( s_reg_tbl ) == USART_COUNT, "Invalid register table
9599
( * ( s_reg_tbl[ ( _usart ) ].ucsrb ) )
96100
#define UCSRC( _usart ) \
97101
( * ( s_reg_tbl[ ( _usart ) ].ucsrc ) )
102+
#define UBRR( _usart ) \
103+
( * ( s_reg_tbl[ ( _usart ) ].ubrr ) )
98104
#define UBRRH( _usart ) \
99105
( * ( s_reg_tbl[ ( _usart ) ].ubrrh ) )
100106
#define UBRRL( _usart ) \
@@ -149,12 +155,6 @@ static volatile size_t s_tx_tail[ USART_COUNT ];
149155

150156
/* ---------------------------------------------- PROCEDURE PROTOTYPES ---------------------------------------------- */
151157

152-
/**
153-
* @fn autoconfigure_baud( usart_t )
154-
* @brief Automatically configures the baud rate for the specified USART based on the `BAUD` macro.
155-
*/
156-
static void autoconfigure_baud( usart_t usart );
157-
158158
/**
159159
* @fn isr_rx_complete( usart_t )
160160
* @brief Runs the USART RX complete interrupt service routine for the specified USART.
@@ -185,6 +185,12 @@ static size_t rx_buf_avail( usart_t usart );
185185
*/
186186
static size_t rx_buf_count( usart_t usart );
187187

188+
/**
189+
* @fn set_baud( usart_t, usart_baud_t )
190+
* @brief Sets the baud rate for the specified USART.
191+
*/
192+
static void set_baud( usart_t usart, usart_baud_t baud );
193+
188194
/**
189195
* @fn set_data_bits( usart_t, usart_data_bits_t )
190196
* @brief Sets the data bits setting for the specified USART.
@@ -314,11 +320,13 @@ usart_error_t usart_get_errors( usart_t usart )
314320
void usart_init( usart_t usart,
315321
bool rx_enabled,
316322
bool tx_enabled,
323+
usart_baud_t baud,
317324
usart_data_bits_t data_bits,
318325
usart_stop_bits_t stop_bits,
319326
usart_parity_t parity )
320327
{
321328
validate_usart( usart );
329+
validate_baud( baud );
322330
validate_data_bits( data_bits );
323331
validate_stop_bits( stop_bits );
324332
validate_parity( parity );
@@ -332,7 +340,7 @@ void usart_init( usart_t usart,
332340
TX_TAIL( usart ) = 0;
333341

334342
// Configure USART
335-
autoconfigure_baud( usart );
343+
set_baud( usart, baud );
336344
set_data_bits( usart, data_bits );
337345
set_stop_bits( usart, stop_bits );
338346
set_parity( usart, parity );
@@ -347,20 +355,6 @@ void usart_init( usart_t usart,
347355
} /* usart_init() */
348356

349357

350-
size_t usart_max_rx_size( void )
351-
{
352-
return( RX_BUF_SIZE );
353-
354-
} /* usart_max_rx_size() */
355-
356-
357-
size_t usart_max_tx_size( void )
358-
{
359-
return( TX_BUF_SIZE );
360-
361-
} /* usart_max_tx_size() */
362-
363-
364358
size_t usart_rx( usart_t usart, byte_t * data, size_t max_size )
365359
{
366360
validate_usart( usart );
@@ -449,19 +443,6 @@ size_t usart_tx_str( usart_t usart, char const * str, usart_wait_mode_t wait_mod
449443
} /* usart_tx_str() */
450444

451445

452-
static void autoconfigure_baud( usart_t usart )
453-
{
454-
UBRRH( usart ) = UBRRH_VALUE;
455-
UBRRL( usart ) = UBRRL_VALUE;
456-
#if( USE_2X )
457-
set_bit( UCSRA( usart ), U2X0 );
458-
#else
459-
clear_bit( UCSRA( usart ), U2X0 );
460-
#endif
461-
462-
} /* autoconfigure_baud() */
463-
464-
465446
static void isr_rx_complete( usart_t usart, event_t event )
466447
{
467448
// If the buffer is full, drop the oldest received byte
@@ -523,6 +504,70 @@ static size_t rx_buf_count( usart_t usart )
523504
} /* rx_buf_count() */
524505

525506

507+
static void set_baud( usart_t usart, usart_baud_t baud )
508+
{
509+
_Static_assert( F_CPU == 16000000UL, "Baud settings depend on F_CPU of 16 MHz!" );
510+
511+
// Always enable 2X setting
512+
set_bit( UCSRA( usart ), U2X0 );
513+
514+
// Set UBRR register based on selected baud rate
515+
// These are taken from table 19-12 in the ATmega1283P data sheet:
516+
// https://ww1.microchip.com/downloads/en/DeviceDoc/ATmega164A_PA-324A_PA-644A_PA-1284_P_Data-Sheet-40002070B.pdf
517+
switch( baud )
518+
{
519+
case USART_BAUD_2400:
520+
UBRR( usart ) = 832;
521+
break;
522+
523+
case USART_BAUD_4800:
524+
UBRR( usart ) = 416;
525+
break;
526+
527+
case USART_BAUD_9600:
528+
UBRR( usart ) = 207;
529+
break;
530+
531+
case USART_BAUD_14400:
532+
UBRR( usart ) = 138;
533+
break;
534+
535+
case USART_BAUD_19200:
536+
UBRR( usart ) = 103;
537+
break;
538+
539+
case USART_BAUD_28800_NOT_RECOMMENDED:
540+
UBRR( usart ) = 68;
541+
break;
542+
543+
case USART_BAUD_38400:
544+
UBRR( usart ) = 51;
545+
break;
546+
547+
case USART_BAUD_57600_NOT_RECOMMENDED:
548+
UBRR( usart ) = 34;
549+
break;
550+
551+
case USART_BAUD_76800:
552+
UBRR( usart ) = 25;
553+
break;
554+
555+
case USART_BAUD_115200_NOT_RECOMMENDED:
556+
UBRR( usart ) = 16;
557+
break;
558+
559+
case USART_BAUD_230400_NOT_RECOMMENDED:
560+
UBRR( usart ) = 8;
561+
break;
562+
563+
case USART_BAUD_250000:
564+
UBRR( usart ) = 7;
565+
break;
566+
}
567+
568+
} /* set_baud() */
569+
570+
526571
static void set_data_bits( usart_t usart, usart_data_bits_t data_bits )
527572
{
528573
// Note that UCSZn2 is in UCSRnB, not UCSRnC

src/main/drivers/usart.h

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,31 @@ enum
3434
USART_COUNT, /**< Number of valid USARTs. */
3535
};
3636

37+
/**
38+
* @typedef usart_baud_t
39+
* @brief Enumeration of the supported USART baud settings.
40+
* @note The approximate error percentage for each setting is indicated in the comment. Baud settings with an error
41+
* of more than 0.5% are not recommended.
42+
*/
43+
typedef uint8_t usart_baud_t;
44+
enum
45+
{
46+
USART_BAUD_2400, /**< 2400 baud (0.0% error). */
47+
USART_BAUD_4800, /**< 4800 baud (-0.1% error). */
48+
USART_BAUD_9600, /**< 9600 baud (0.2% error). */
49+
USART_BAUD_14400, /**< 14400 baud (-0.1% error). */
50+
USART_BAUD_19200, /**< 19200 baud (0.2% error). */
51+
USART_BAUD_28800_NOT_RECOMMENDED, /**< 28800 baud (0.6% error - N/R). */
52+
USART_BAUD_38400, /**< 38400 baud (0.2% error). */
53+
USART_BAUD_57600_NOT_RECOMMENDED, /**< 57600 baud (-0.8% error - N/R). */
54+
USART_BAUD_76800, /**< 76800 baud (0.2% error). */
55+
USART_BAUD_115200_NOT_RECOMMENDED, /**< 115200 baud (2.1% error - N/R). */
56+
USART_BAUD_230400_NOT_RECOMMENDED, /**< 230400 baud (-3.5% error - N/R). */
57+
USART_BAUD_250000, /**< 250000 baud (0.0% error). */
58+
59+
USART_BAUD_COUNT, /**< Number of valid USART baud settings. */
60+
};
61+
3762
/**
3863
* @typedef usart_data_bits_t
3964
* @brief Enumeration of the supported data bits settings for the USARTs.
@@ -126,29 +151,18 @@ void usart_deinit( usart_t usart );
126151
usart_error_t usart_get_errors( usart_t usart );
127152

128153
/**
129-
* @fn usart_init( usart_t, bool, bool, usart_data_bits_t, usart_stop_bits_t, usart_parity_t )
154+
* @fn usart_init( usart_t, bool, bool, usart_baud_t, usart_data_bits_t, usart_stop_bits_t, usart_parity_t )
130155
* @brief Initializes the specified USART with the specified configuration.
131156
* @note Must be called prior to attempting any use of the USART.
132157
*/
133158
void usart_init( usart_t usart,
134159
bool rx_enabled,
135160
bool tx_enabled,
161+
usart_baud_t baud,
136162
usart_data_bits_t data_bits,
137163
usart_stop_bits_t stop_bits,
138164
usart_parity_t parity );
139165

140-
/**
141-
* @fn usart_max_rx_size( void )
142-
* @brief Returns the maximum supported RX buffer size for all USARTs.
143-
*/
144-
size_t usart_max_rx_size( void );
145-
146-
/**
147-
* @fn usart_max_tx_size( void )
148-
* @brief Returns the maximum supported TX buffer size for all USARTs.
149-
*/
150-
size_t usart_max_tx_size( void );
151-
152166
/**
153167
* @fn usart_rx( usart_t, byte_t *, size_t )
154168
* @brief Receives up to `max_size` bytes from the RX buffer for the specified USART.

0 commit comments

Comments
 (0)