px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
printf.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2006-2014 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13============================================================================= */
14
15/**
16 * @ingroup AVR_TUTORIALS
17 * @defgroup AVR_TUT05_PRINTF 05_printf
18 *
19 * How to direct the AVR Libc stdout stream to send characters using a UART.
20 *
21 * File(s):
22 * - arch/avr/tutorials/05_printf/printf.c
23 *
24 * The UART is configured to 115200 BAUD, 8 Data Bits, No Parity and 1 Stop Bit.
25 * The following strings are sent upon start up:
26 *
27 * printf - String in data memory (SRAM)
28 * printf_P - String in program memory (FLASH)
29 * PRINTF_P - String in program memory (FLASH)
30 *
31 * @tip_s
32 * Remember that the XMODEM-CRC bootloader will send a 'C' character upon
33 * reset and this will be shown in addition to the printf strings.
34 * @tip_e
35 *
36 * A custom handler "uart_putchar(...)" is linked to the stdout stream to
37 * send a character and inject a "\r" (Carriage Return) before every
38 * "\n" (Line Feed).
39 *
40 * This example draws attention to the handling of the Harvard architecture by
41 * the GCC compiler and the AVR Libc library. The 8-bit AVRs have a small
42 * amount of SRAM (data memory) and therefore it is desirable to store constant
43 * strings in FLASH (program memory) and access it from there and not use a
44 * copy in SRAM.
45 *
46 * The recommended solution is to use the macros in
47 * [<avr/pgmspace.h>](https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html)
48 * and string handling functions with the suffix "_P", e.g. "printf_P(...)"
49 * instead of "printf(...)". This handling has been encapsulated with the
50 * following variable argument macro:
51 *
52 * @code{.c}
53 * #define PRINTF_P(format, ...) printf_P(PSTR(format), ## __VA_ARGS__)
54 * @endcode
55 *
56 * All of this functionality has been encapsulated in the following modules:
57 *
58 * - @ref AVR_UART_STDIO
59 * - @ref PX_PGM_P
60 *
61 * See:
62 * - @ref AVR_EX_PRINTF
63 *
64 * More info:
65 * - [AVR-GCC and the PROGMEM Attribute](http://www.fourwalledcubicle.com/AVRArticles.php)
66 * by Dean Camera
67 * - [avr-libc: Data in Program Space](http://www.nongnu.org/avr-libc/user-manual/pgmspace.html)
68 */
69
70#include <stdint.h>
71#include <stdbool.h>
72#include <stdio.h>
73#include <avr/io.h>
74#include <avr/pgmspace.h>
75
76#include "px_board.h"
77
78// Macro to send strings stored in program memory space
79#define PRINTF_P(format, ...) printf_P(PSTR(format), ## __VA_ARGS__)
80// Define baud rate
81#define UART0_BAUD 115200ul
82#define UART0_UBBR_VAL ((F_CPU / (UART0_BAUD * 16)) - 1)
83
84void uart_init(void)
85{
86 // Set baud rate
87 UBRR0 = UART0_UBBR_VAL;
88 // Set frame format to 8 data bits, no parity, 1 stop bit
89 UCSR0C = (0 << USBS0) | (1 << UCSZ01) | (1 << UCSZ00);
90 // Enable receiver and transmitter
91 UCSR0B = (1 << RXEN0) | (1 << TXEN0);
92}
93
94int uart_putchar(char data, FILE * stream)
95{
96 // Recursive function to prepend a carriage return before a line feed
97 if(data == '\n')
98 {
99 uart_putchar('\r', stream);
100 }
101 // Wait until data register is empty
102 while((UCSR0A & (1 << UDRE0)) == 0) {;}
103 // Load transmit register with new data
104 UDR0 = data;
105
106 return 0;
107}
108
109// Declare stream object in data memory (not heap memory)
110FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
111
112int main(void)
113{
114 // Initialise board
116 // Initialise UART
117 uart_init();
118
119 // Direct stdout stream to uart_stream
120 stdout = &uart_stream;
121
122 // String stored in program memory and copied to SRAM upon startup by
123 // C Run Time set up (CRT).
124 printf("printf - String in data memory (SRAM)\n");
125 // String stored in and accessed from program memory
126 printf_P(PSTR("printf_P - String in program memory (FLASH)\n"));
127 // Convenience macro to store and access string in program memory
128 PRINTF_P("PRINTF_P - String also in program memory (FLASH)\n");
129
130 // Loop forever
131 while(true) {;}
132}
void px_board_init(void)
Initialise the board hardware.
Definition: px_board.c:168
#define NULL
NULL pointer.
Definition: px_defs.h:49