GPS Device
Loading...
Searching...
No Matches
io.c
Go to the documentation of this file.
1
10
11#include "io.h"
12#include "configuration.h"
13#include "err.h"
14#include "init.h"
15#include "log.h"
16#include "modules.h"
17#include "stm32f401re_gpio.h"
18#include "cmd.h"
19#include "common.h"
20
32
34 char name[CONFIG_IO_MAX_NAME_LEN];
35
37 bool in_use;
38};
39
47struct internal_state_s {
49 IO_HANDLE_ts ios[CONFIG_IO_MAX_OBJECTS];
50
52 uint32_t io_num;
53
56
59
61 bool initialized;
62
64 bool started;
65};
66
69
70/* ---- Forward declarations for command handlers ---- */
71static ERR_te io_cmd_w_handler(uint32_t argc, char **argv);
72static ERR_te io_cmd_r_handler(uint32_t argc, char **argv);
73static ERR_te io_cmd_info_handler(uint32_t argc, char **argv);
74
82static CMD_INFO_ts io_cmds[] = {
83 {
84 .name = "w",
85 .help = "Writes to an IO pin, usage: io w <name> <1|0>",
86 .handler = io_cmd_w_handler
87 },
88 {
89 .name = "r",
90 .help = "Reads from an IO pin, usage: io r <name>",
91 .handler = io_cmd_r_handler
92 },
93 {
94 .name = "info",
95 .help = "Shows IO information, usage: io info",
96 .handler = io_cmd_info_handler
97 }
98};
99
108 .cmds_ptr = io_cmds,
109 .num_cmds = sizeof(io_cmds) / sizeof(io_cmds[0]),
110 .name = "io",
111 .log_level_ptr = &internal_state.log_level
112};
113
118
121 ERR_te err = 0;
122
123 if(internal_state.initialized) {
125 }
126
127 internal_state = (struct internal_state_s){ 0 };
128
129 internal_state.log_level = LOG_LEVEL_INFO;
130 internal_state.subsys = MODULES_IO;
131 internal_state.initialized = true;
132 internal_state.started = false;
133
134 init_log();
135
137 if(err != ERR_OK) {
138 LOG_ERROR(
139 internal_state.subsys,
140 internal_state.log_level,
141 "io_init_subsys: cmd_register error"
142 );
143
144 return err;
145 }
146 LOG_INFO(
147 internal_state.subsys,
148 internal_state.log_level,
149 "io_init_subsys: subsys initialized"
150 );
151
152 return ERR_OK;
153}
154
157 if(internal_state.initialized && !internal_state.started) {
158 internal_state = (struct internal_state_s){ 0 };
159
161 }
162 else {
163 LOG_ERROR(
164 internal_state.subsys,
165 internal_state.log_level,
166 "io_deinit_subsys: subsys is not initialized or not stopped"
167 );
168
170 }
171 LOG_INFO(
172 internal_state.subsys,
173 internal_state.log_level,
174 "io_deinit_subsys: subsys deinitialized"
175 );
176
177 return ERR_OK;
178}
179
182 if(internal_state.initialized && !internal_state.started) {
183 internal_state.started = true;
184
185 LOG_INFO(
186 internal_state.subsys,
187 internal_state.log_level,
188 "io_start_subsys: subsys started"
189 );
190 }
191 else {
192 LOG_ERROR(
193 internal_state.subsys,
194 internal_state.log_level,
195 "io_start_subsys: subsys not initialized or already started"
196 );
197
198 return ERR_UNKNOWN;
199 }
200
201 return ERR_OK;
202}
203
206 if(internal_state.initialized && internal_state.started) {
207 internal_state.started = false;
208
209 LOG_INFO(
210 internal_state.subsys,
211 internal_state.log_level,
212 "io_stop_subsys: subsys stopped"
213 );
214 }
215 else {
216 LOG_ERROR(
217 internal_state.subsys,
218 internal_state.log_level,
219 "io_stop_subsys: subsys not initialized or already already stopped"
220 );
221
222 return ERR_UNKNOWN;
223 }
224
225 return ERR_OK;
226}
227
230 if(internal_state.io_num == CONFIG_IO_MAX_OBJECTS) {
231 LOG_ERROR(
232 internal_state.subsys,
233 internal_state.log_level,
234 "io_init_handle: subsystem out of memory space"
235 );
236
238 }
239
240 gpio_init(io_cfg->gpio_handle);
241
242 for(uint32_t i = 0; i < CONFIG_IO_MAX_OBJECTS; i++) {
243 if(internal_state.ios[i].in_use == false) {
244 internal_state.ios[i].gpio_cfg = *io_cfg->gpio_handle;
245 txt_cpy(internal_state.ios[i].name,
246 io_cfg->name,
247 get_str_len(io_cfg->name) + 1);
248
249 internal_state.ios[i].in_use = true;
250
251 internal_state.io_num++;
252
253 *io_handle_o = &internal_state.ios[i];
254
255 LOG_INFO(
256 internal_state.subsys,
257 internal_state.log_level,
258 "io_init_handle: io handle %s initialized",
259 internal_state.ios[i].name
260 );
261
262 break;
263 }
264 }
265
266 return ERR_OK;
267}
268
271 if(internal_state.io_num == 0) {
272 LOG_ERROR(
273 internal_state.subsys,
274 internal_state.log_level,
275 "io_deinit_handle: no such handle to deinitialize"
276 );
277
279 }
280
281 for(uint32_t i = 0; i < CONFIG_IO_MAX_OBJECTS; i++) {
282 if(&internal_state.ios[i] == io_handle) {
283 internal_state.ios[i].gpio_cfg = (GPIO_CFG_ts){ 0 };
284
285 uint8_t name_len = get_str_len(internal_state.ios[i].name) + 1;
286 char name[name_len];
287
288 str_cpy(name, internal_state.ios[i].name, name_len);
289
290 for(uint32_t j = 0; j < name_len; j++) {
291 internal_state.ios[i].name[j] = '\0';
292 }
293
294 internal_state.ios[i].in_use = false;
295
296 internal_state.io_num--;
297
298 LOG_INFO(
299 internal_state.subsys,
300 internal_state.log_level,
301 "io_deinit_handle: io handle %s deinitialized",
302 name
303 );
304
305 break;
306 }
307
308 if(i == CONFIG_IO_MAX_OBJECTS - 1) {
309 LOG_ERROR(
310 internal_state.subsys,
311 internal_state.log_level,
312 "io_deinit_handle: no such handle to deinitialize"
313 );
314
316 }
317 }
318
319 return ERR_OK;
320}
321
323ERR_te io_write(IO_HANDLE_ts *io_handle, PIN_STATUS_te pin_status) {
324 if(internal_state.initialized && internal_state.started) {
326 io_handle->gpio_cfg.port,
327 io_handle->gpio_cfg.pin,
328 pin_status
329 );
330 }
331 else {
332 LOG_ERROR(
333 internal_state.subsys,
334 internal_state.log_level,
335 "io_write: subsystem not initialized or started"
336 );
337
338 return ERR_UNKNOWN;
339 }
340
341 return ERR_OK;
342}
343
345ERR_te io_read(IO_HANDLE_ts const *io_handle, PIN_STATUS_te *pin_status_o) {
346 if(internal_state.initialized && internal_state.started) {
347 *pin_status_o = gpio_read(
348 io_handle->gpio_cfg.port,
349 io_handle->gpio_cfg.pin
350 );
351 }
352 else {
353 LOG_ERROR(
354 internal_state.subsys,
355 internal_state.log_level,
356 "io_read: subsystem not initialized or started"
357 );
358
359 return ERR_UNKNOWN;
360 }
361
362 return ERR_OK;
363}
364
366
371
392static ERR_te io_cmd_w_handler(uint32_t argc, char **argv) {
393 ERR_te err;
394
395 if(argc != 4) {
396 LOG_ERROR(
397 internal_state.subsys,
398 internal_state.log_level,
399 "io_cmd_w_handler: invalid arguments"
400 );
402 }
403
404 for(uint32_t i = 0; i < CONFIG_IO_MAX_OBJECTS; i++) {
405 if(str_cmp(argv[2], internal_state.ios[i].name) == true) {
406 if(str_cmp(argv[3], "0") == true ||
407 str_cmp(argv[3], "off") == true) {
408 err = io_write(&internal_state.ios[i], LOW);
409 if(err != ERR_OK)
410 return err;
411
412 return ERR_OK;
413 }
414 else if(str_cmp(argv[3], "1") == true ||
415 str_cmp(argv[3], "on") == true) {
416 err = io_write(&internal_state.ios[i], HIGH);
417 if(err != ERR_OK)
418 return err;
419
420 return ERR_OK;
421 }
422 else {
423 LOG_ERROR(
424 internal_state.subsys,
425 internal_state.log_level,
426 "io_cmd_w_handler: invalid arguments"
427 );
429 }
430 }
431
432 if(i == internal_state.io_num - 1) {
433 LOG_ERROR(
434 internal_state.subsys,
435 internal_state.log_level,
436 "io_cmd_w_handler: invalid arguments"
437 );
439 }
440 }
441
442 return ERR_OK;
443}
444
463static ERR_te io_cmd_r_handler(uint32_t argc, char **argv) {
464 ERR_te err;
465
466 if(argc != 3) {
467 LOG_ERROR(
468 internal_state.subsys,
469 internal_state.log_level,
470 "io_cmd_r_handler: invalid arguments"
471 );
473 }
474
475 for(uint32_t i = 0; i < CONFIG_IO_MAX_OBJECTS; i++) {
476 if(str_cmp(argv[2], internal_state.ios[i].name) == true) {
477 PIN_STATUS_te pin_status = 0;
478
479 err = io_read(&internal_state.ios[i], &pin_status);
480 if(err != ERR_OK) {
481 return err;
482 }
483
484 LOG_INFO(
485 internal_state.subsys,
486 internal_state.log_level,
487 "io_cmd_r_handler: %s pin status: %d",
488 internal_state.ios[i].name,
489 pin_status
490 );
491
492 return ERR_OK;
493 }
494
495 if(i == internal_state.io_num - 1) {
496 LOG_ERROR(
497 internal_state.subsys,
498 internal_state.log_level,
499 "io_cmd_r_handler: invalid arguments"
500 );
502 }
503 }
504
505 return ERR_OK;
506}
507
524static ERR_te io_cmd_info_handler(uint32_t argc, char **argv) {
525 if(argc != 2) {
526 LOG_ERROR(
527 internal_state.subsys,
528 internal_state.log_level,
529 "io_cmd_info_handler: invalid arguments"
530 );
531
533 }
534
535 LOG_INFO(internal_state.subsys, internal_state.log_level, "Printing IO information:");
536
537 for(uint32_t i = 0; i < CONFIG_IO_MAX_OBJECTS; i++) {
538 if(internal_state.ios[i].in_use == true) {
539 LOG_INFO(
540 internal_state.subsys,
541 internal_state.log_level,
542 "name: %s, mode: %d",
543 internal_state.ios[i].name,
544 internal_state.ios[i].gpio_cfg.mode
545 );
546 }
547 }
548
549 return ERR_OK;
550}
551
static struct internal_state_s internal_state
Singleton instance of the SysTick driver internal state.
Command subsystem public API.
Common utility module public API.
System-wide error code definitions.
ERR_te cmd_deregister(CMD_CLIENT_INFO_ts const *cmd_client_info)
Deregisters a client from the command subsystem.
Definition cmd.c:66
ERR_te cmd_register(CMD_CLIENT_INFO_ts *cmd_client_info)
Registers a client with the command subsystem.
Definition cmd.c:51
bool str_cmp(const char *str1, const char *str2)
Compares two null-terminated strings for equality.
Definition common.c:248
int str_cpy(char *str_to, const char *str_from, uint32_t len)
Copies a null-terminated string into a destination buffer.
Definition common.c:333
uint32_t get_str_len(char const *str)
Returns the length of a string, excluding the null terminator.
Definition common.c:22
int txt_cpy(char *txt_to, const char *txt_from, uint32_t len)
Copies a fixed-length block of text into a destination buffer.
Definition common.c:350
PIN_STATUS_te
Represents the logical level of a GPIO pin.
Definition common.h:84
@ HIGH
Definition common.h:89
@ LOW
Definition common.h:86
ERR_te
Standard return type used by all public API functions.
Definition err.h:35
@ ERR_UNINITIALZIED_OBJECT
Definition err.h:42
@ ERR_DEINITIALIZATION_FAILURE
Definition err.h:44
@ ERR_UNKNOWN
Definition err.h:37
@ ERR_OK
Definition err.h:36
@ ERR_MODULE_ALREADY_INITIALIZED
Definition err.h:54
@ ERR_NOT_ENOUGH_SPACE
Definition err.h:49
@ ERR_INVALID_ARGUMENT
Definition err.h:38
ERR_te init_log(void)
Initializes the logging subsystem.
Definition init.c:25
static ERR_te io_cmd_w_handler(uint32_t argc, char **argv)
CLI handler for the "w" command. Writes a logic level to a named IO pin.
Definition io.c:392
static ERR_te io_cmd_info_handler(uint32_t argc, char **argv)
CLI handler for the "info" command. Logs the name and GPIO mode of all active IO handles.
Definition io.c:524
static ERR_te io_cmd_r_handler(uint32_t argc, char **argv)
CLI handler for the "r" command. Reads and logs the logic level of a named IO pin.
Definition io.c:463
ERR_te io_init_handle(IO_CFG_ts *io_cfg, IO_HANDLE_ts **io_handle_o)
Initializes and registers an IO handle.
Definition io.c:229
ERR_te io_write(IO_HANDLE_ts *io_handle, PIN_STATUS_te pin_status)
Writes a logic level to an IO pin.
Definition io.c:323
ERR_te io_stop_subsys(void)
Stops the IO subsystem.
Definition io.c:205
ERR_te io_deinit_subsys(void)
Deinitializes the IO subsystem.
Definition io.c:156
ERR_te io_deinit_handle(IO_HANDLE_ts const *io_handle)
Deinitializes an IO handle.
Definition io.c:270
ERR_te io_start_subsys(void)
Starts the IO subsystem.
Definition io.c:181
ERR_te io_read(IO_HANDLE_ts const *io_handle, PIN_STATUS_te *pin_status_o)
Reads the current logic level of an IO pin.
Definition io.c:345
ERR_te io_init_subsys(void)
Initializes the IO subsystem.
Definition io.c:120
struct io_handle_s IO_HANDLE_ts
Opaque handle representing an IO instance.
Definition io.h:69
#define LOG_ERROR(subsys, lvl, fmt,...)
Definition log.h:258
#define LOG_INFO(subsys, lvl, fmt,...)
Definition log.h:255
LOG_LEVEL_te
Log severity levels, in ascending order of severity.
Definition log.h:63
@ LOG_LEVEL_INFO
Definition log.h:64
MODULES_te
Identifies a subsystem for use in logging and CLI output.
Definition modules.h:42
@ MODULES_IO
Definition modules.h:46
PIN_STATUS_te gpio_read(GPIO_REGDEF_ts const *gpio_port, uint8_t gpio_pin)
Reads the current logic level of a GPIO input pin.
void gpio_write(GPIO_REGDEF_ts *gpio_port, uint8_t gpio_pin, PIN_STATUS_te pin_status)
Drives a GPIO output pin high or low.
void gpio_init(GPIO_CFG_ts *gpio_cfg)
Initializes a GPIO pin according to the given configuration.
Common initialization public API.
static CMD_CLIENT_INFO_ts io_cmd_client_info
Registration descriptor passed to the command subsystem.
Definition io.c:107
static CMD_INFO_ts io_cmds[]
Table of CLI commands registered by the IO subsystem.
Definition io.c:82
Digital IO module public API.
Log subsystem public API.
System module identifier definitions.
STM32F401RE GPIO driver public API.
Describes a subsystem client registering with the command module.
Definition cmd.h:92
Describes a single command exposed by a client.
Definition cmd.h:72
Configuration structure for initializing a GPIO pin.
GPIO_REGDEF_ts * port
GPIO_PIN_te pin
Configuration structure for initializing an IO handle.
Definition io.h:53
char name[CONFIG_IO_MAX_NAME_LEN]
Definition io.h:58
GPIO_CFG_ts * gpio_handle
Definition io.h:55
Internal state of the SysTick driver.
uint32_t io_num
Definition io.c:52
MODULES_te subsys
Definition button.c:95
IO_HANDLE_ts ios[CONFIG_IO_MAX_OBJECTS]
Definition io.c:49
LOG_LEVEL_te log_level
Definition button.c:92
Internal structure representing a single IO instance.
Definition io.c:29
bool in_use
Definition io.c:37
GPIO_CFG_ts gpio_cfg
Definition io.c:31
char name[CONFIG_IO_MAX_NAME_LEN]
Definition io.c:34