Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_log.c
1 #include <bc_log.h>
2 #include <bc_error.h>
3 
4 typedef struct
5 {
6  bool initialized;
7  bc_log_level_t level;
8  bc_log_timestamp_t timestamp;
9  bc_tick_t tick_last;
10 
11  char buffer[256];
12 
13 } bc_log_t;
14 
15 #ifndef RELEASE
16 
17 static bc_log_t _bc_log = { .initialized = false };
18 
19 void application_error(bc_error_t code);
20 
21 static void _bc_log_message(bc_log_level_t level, char id, const char *format, va_list ap);
22 
24 {
25  if (_bc_log.initialized)
26  {
27  return;
28  }
29 
30  memset(&_bc_log, 0, sizeof(_bc_log));
31 
32  _bc_log.level = level;
33  _bc_log.timestamp = timestamp;
34 
36  bc_uart_write(BC_LOG_UART, "\r\n", 2);
37 
38  _bc_log.initialized = true;
39 }
40 
41 void bc_log_dump(const void *buffer, size_t length, const char *format, ...)
42 {
43  va_list ap;
44 
45  if (_bc_log.level > BC_LOG_LEVEL_DUMP)
46  {
47  return;
48  }
49 
50  va_start(ap, format);
51  _bc_log_message(BC_LOG_LEVEL_DUMP, 'X', format, ap);
52  va_end(ap);
53 
54  size_t offset_base = 0;
55 
56  for (; offset_base < sizeof(_bc_log.buffer); offset_base++)
57  {
58  if (_bc_log.buffer[offset_base] == '>')
59  {
60  break;
61  }
62  }
63 
64  offset_base += 2;
65 
66  size_t position;
67 
68  size_t offset;
69 
70  if (buffer != NULL && length != 0)
71  {
72  for (position = 0; position < length; position += BC_LOG_DUMP_WIDTH)
73  {
74  offset = offset_base + snprintf(_bc_log.buffer + offset_base, sizeof(_bc_log.buffer) - offset_base, "%3d: ", position);
75 
76  char *ptr_hex = _bc_log.buffer + offset;
77 
78  offset += (BC_LOG_DUMP_WIDTH * 3 + 2 + 1);
79 
80  char *ptr_text = _bc_log.buffer + offset;
81 
82  offset += BC_LOG_DUMP_WIDTH;
83 
84  uint32_t line_size;
85 
86  uint32_t i;
87 
88  if ((position + BC_LOG_DUMP_WIDTH) <= length)
89  {
90  line_size = BC_LOG_DUMP_WIDTH;
91  }
92  else
93  {
94  line_size = length - position;
95  }
96 
97  for (i = 0; i < line_size; i++)
98  {
99  uint8_t value = ((uint8_t *) buffer)[position + i];
100 
101  if (i == (BC_LOG_DUMP_WIDTH / 2))
102  {
103  *ptr_hex++ = '|';
104  *ptr_hex++ = ' ';
105  }
106 
107  snprintf(ptr_hex, 4, "%02X ", value);
108 
109  ptr_hex += 3;
110 
111  if (value < 32 || value > 126)
112  {
113  *ptr_text++ = '.';
114  }
115  else
116  {
117  *ptr_text++ = value;
118  }
119  }
120 
121  for (; i < BC_LOG_DUMP_WIDTH; i++)
122  {
123  if (i == (BC_LOG_DUMP_WIDTH / 2))
124  {
125  *ptr_hex++ = '|';
126  *ptr_hex++ = ' ';
127  }
128 
129  strcpy(ptr_hex, " ");
130 
131  ptr_hex += 3;
132 
133  *ptr_text++ = ' ';
134  }
135 
136  _bc_log.buffer[offset++] = '\r';
137  _bc_log.buffer[offset++] = '\n';
138 
139  bc_uart_write(BC_LOG_UART, _bc_log.buffer, offset);
140  }
141  }
142 }
143 
144 void bc_log_debug(const char *format, ...)
145 {
146  va_list ap;
147 
148  va_start(ap, format);
149  _bc_log_message(BC_LOG_LEVEL_DEBUG, 'D', format, ap);
150  va_end(ap);
151 }
152 
153 void bc_log_info(const char *format, ...)
154 {
155  va_list ap;
156 
157  va_start(ap, format);
158  _bc_log_message(BC_LOG_LEVEL_INFO, 'I', format, ap);
159  va_end(ap);
160 }
161 
162 void bc_log_warning(const char *format, ...)
163 {
164  va_list ap;
165 
166  va_start(ap, format);
167  _bc_log_message(BC_LOG_LEVEL_WARNING, 'W', format, ap);
168  va_end(ap);
169 }
170 
171 void bc_log_error(const char *format, ...)
172 {
173  va_list ap;
174 
175  va_start(ap, format);
176  _bc_log_message(BC_LOG_LEVEL_ERROR, 'E', format, ap);
177  va_end(ap);
178 }
179 
180 static void _bc_log_message(bc_log_level_t level, char id, const char *format, va_list ap)
181 {
182  if (!_bc_log.initialized)
183  {
184  application_error(BC_ERROR_LOG_NOT_INITIALIZED);
185  }
186 
187  if (_bc_log.level > level)
188  {
189  return;
190  }
191 
192  size_t offset;
193 
194  if (_bc_log.timestamp == BC_LOG_TIMESTAMP_ABS)
195  {
196  bc_tick_t tick_now = bc_tick_get();
197 
198  uint32_t timestamp_abs = tick_now / 10;
199 
200  offset = sprintf(_bc_log.buffer, "# %lu.%02lu <%c> ", timestamp_abs / 100, timestamp_abs % 100, id);
201  }
202  else if (_bc_log.timestamp == BC_LOG_TIMESTAMP_REL)
203  {
204  bc_tick_t tick_now = bc_tick_get();
205 
206  uint32_t timestamp_rel = (tick_now - _bc_log.tick_last) / 10;
207 
208  offset = sprintf(_bc_log.buffer, "# +%lu.%02lu <%c> ", timestamp_rel / 100, timestamp_rel % 100, id);
209 
210  _bc_log.tick_last = tick_now;
211  }
212  else
213  {
214  strcpy(_bc_log.buffer, "# <!> ");
215 
216  _bc_log.buffer[3] = id;
217 
218  offset = 6;
219  }
220 
221  offset += vsnprintf(&_bc_log.buffer[offset], sizeof(_bc_log.buffer) - offset - 3, format, ap);
222 
223  _bc_log.buffer[offset++] = '\r';
224  _bc_log.buffer[offset++] = '\n';
225 
226  bc_uart_write(BC_LOG_UART, _bc_log.buffer, offset);
227 }
228 
229 #endif
Log level INFO.
Definition: bc_log.h:28
void bc_log_warning(const char *format,...)
Log WARNING message (annotated in log as <W>)
Definition: bc_log.c:162
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
Log level ERROR.
Definition: bc_log.h:34
Log level DEBUG.
Definition: bc_log.h:25
Logging DUMP.
Definition: bc_log.h:22
void bc_log_info(const char *format,...)
Log INFO message (annotated in log as )
Definition: bc_log.c:153
8N1: 8 data bits, none parity bit, 1 stop bit
Definition: bc_uart.h:70
Log level WARNING.
Definition: bc_log.h:31
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
void bc_uart_init(bc_uart_channel_t channel, bc_uart_baudrate_t baudrate, bc_uart_setting_t setting)
Initialize UART channel.
Definition: bc_uart.c:53
void bc_log_init(bc_log_level_t level, bc_log_timestamp_t timestamp)
Initialize logging facility.
Definition: bc_log.c:23
Definition: bc_log.c:4
bc_log_level_t
Log level.
Definition: bc_log.h:19
bc_log_timestamp_t
Log timestamp.
Definition: bc_log.h:43
void bc_log_dump(const void *buffer, size_t length, const char *format,...)
Log DUMP message (annotated in log as <X>)
Definition: bc_log.c:41
size_t bc_uart_write(bc_uart_channel_t channel, const void *buffer, size_t length)
Write data to UART channel (blocking call)
Definition: bc_uart.c:330
void bc_log_error(const char *format,...)
Log ERROR message (annotated in log as <E>)
Definition: bc_log.c:171
Timestamp logging enabled (absolute time format)
Definition: bc_log.h:49
UART baudrat 115200 bps.
Definition: bc_uart.h:43
Timestamp logging enabled (relative time format)
Definition: bc_log.h:52
void bc_log_debug(const char *format,...)
Log DEBUG message (annotated in log as <D>)
Definition: bc_log.c:144