CodeBrick
Введение
CodeBrick — это практичная программная среда без операционной системы для микроконтроллеров (MCU), включающая в себя управление задачами опроса, менеджер команд, управление низким энергопотреблением и кольцевой буфер. В системе широко используется технология пользовательских сегментов для уменьшения взаимосвязей между различными модулями, что значительно повышает удобство сопровождения программы.
Основные функции
Использование Полную версию кода можно найти в файле проекта. Платформа разработки включает:
Инициализация задач и управление опросом (module) Перед использованием этого модуля система должна предоставить функцию обратного отсчёта для управления задачами опроса. (См. platform.c)
// Обработчик прерывания таймера (обеспечивает системный отсчёт)
void SysTick_Handler(void) {
systick_increase(SYS_TICK_INTERVAL); // Увеличение системного отсчёта
}
Регистрация инициализирующего входа и задачи (см. key_task.c).
static void key_init(void) { /*do something*/ }
static void key_scan(void) { /*do something*/ }
module_init("key", key_init); // Регистрация инициализатора клавиатуры
driver_register("key", key_scan, 20); // Регистрация задачи клавиатуры (опрос каждые 20 мс)
Менеджер команд (cli) Подходит для отладки в реальном времени, настройки параметров и других функций. Пользователи могут управлять поведением устройства, запрашивать состояние устройства и выполнять другие функции через последовательный порт.
Формат команды Команды cli имеют следующий формат: <имя команды> <параметр1> <параметр2> <парамn> < \r\n > <имя команды>, <параметр1>, <параметр2>, <параметры>, < \r\n > Каждая строка команды содержит имя команды и параметры, которые могут быть разделены пробелами или запятыми.
Системные команды по умолчанию Система cli имеет две встроенные команды: «?» и «help». При вводе этих команд будет отображаться список доступных команд системы.
? - псевдоним для 'help'
help - список всех команд.
pm - управление низким энергопотреблением
reset - сброс системы
sysinfo - показать информацию о системе.
Адаптация менеджера команд Полный пример можно посмотреть в cli_task.c.
static cli_obj_t cli; /* Объект менеджера команд */
/*
* @brief Инициализатор задачи командной строки
* @return none
*/
static void cli_task_init(void) {
cli_port_t p = {tty.write, tty.read}; /* Интерфейс чтения и записи */
cli_init(&cli, &p); /* Инициализировать объект командной строки */
cli_enable(&cli);
cli_exec_cmd(&cli,"sysinfo"); /* Показать информацию о системе*/
}
/*
* @brief Задача обработки командной строки
* @return none
*/
static void cli_task_process(void) {
cli_process(&cli);
}
module_init("cli", cli_task_init);
task_register("cli", cli_task_process, 10); /* Зарегистрировать задачу командной строки*/
Регистрация команд В качестве примера возьмём команду сброса (см. cmd_devinfo.c):
#include "cli.h"
//...
/*
* @brief Команда сброса
*/
int do_cmd_reset(struct cli_obj *o, int argc, char *argv[]) {
NVIC_SystemReset();
return 0;
}cmd_register("reset",do_cmd_reset, "reset system");
Управление низким энергопотреблением (pm) Управляет периодическим режимом работы, снижая энергопотребление системы. Основной принцип работы заключается в том, чтобы периодически проверять, может ли каждый модуль разрешить системе перейти в режим низкого энергопотребления. Фактически это механизм принятия решений, в котором каждый модуль имеет право вето, и если хотя бы один модуль не разрешает переход в спящий режим, система не перейдёт в спящий режим. Перед переходом в спящий режим модуль pm подсчитывает минимальное время ожидания для каждого модуля и переходит в спящий режим на основе минимального времени ожидания.
Как адаптировать Перед использованием необходимо выполнить инициализацию адаптации через pm_init и предоставить максимальное время ожидания системы. Основные определения интерфейса функции перехода в спящий режим следующие:
/* Адаптер управления низким энергопотреблением ---------------------------------------------------------*/
typedef struct {
/**
* @brief Максимальное время ожидания системы (мс)
*/
unsigned int max_sleep_time;
/**
* @brief Функция перехода в спящий режим
* @param[in] time - ожидаемое время ожидания (мс)
* @retval фактическое время ожидания
* @note После перехода в спящий режим необходимо учитывать две вещи: во-первых, необходимо установить таймер для периодического наблюдения за сторожевым псом, иначе сторожевой пёс отправит сигнал перезагрузки во время спящего режима. Во-вторых, необходимо компенсировать время ожидания спящего режима для системных часов отсчёта, иначе время будет неточным.
*/
unsigned int (*goto_sleep)(unsigned int time);
}pm_adapter_t;
void pm_init(const pm_adapter_t *adt);
void pm_enable(void);
void pm_disable(void);
void pm_process(void);
Пример использования можно найти в platform-lowpower.c. По умолчанию функция низкого энергопотребления отключена. Читатели могут удалить версию platform.c без функции низкого энергопотребления и добавить файл platform-lowpower.c для компиляции и использования.
Регистрация устройств с низким энергопотреблением Например, сканирование клавиатуры. В режиме низкого энергопотребления, если клавиатура не нажата, система может перейти в спящий режим без влияния на функциональность клавиатуры. Если нажать клавишу, системе необходимо периодически просыпаться и опрашивать задачу сканирования клавиатуры.
Поэтому в системе с низким энергопотреблением необходимо решить две проблемы:
Для решения первой проблемы можно настроить клавиатуру как граничное прерывание для пробуждения, например, для STM32F4 (см. key_task.c), который поддерживает внешнее прерывание пробуждения. Для второго случая можно использовать pm_dev_register, чтобы обработать ситуацию. Если в момент запроса системы на переход в спящий режим нажать клавишу, то будет возвращено время следующего пробуждения, как показано в следующем примере:
//Ссылка на key_task.c
#include "pm.h"
/*
* @brief Уведомление о переходе в спящий режим
*/
static unsigned int key_sleep_notify(void)
{
return key_busy(&key) || readkey() ? 20 : 0; /* 20 мс нужно для пробуждения при непустом значении*/
} pm_dev_register("key", NULL, key_sleep_notify, NULL);
Управление устройствами с мигающими характеристиками (светодиоды, двигатели, зуммеры).
Использование:
Либо это может быть реализовано через регистрацию задач в модуле «module».
task_register("blink", blink_dev_process, 50); //опрос каждые 50 мс
blink_dev_t led; //определение устройства led
/*
*@brief Управление красным светодиодом (GPIOA.8)
*@param[in] on - управление включением/выключением
*/
static void led_ctrl(int on)
{
if (on)
GPIOA->ODR |= (1 << 8);
else
GPIOA->ODR &= ~(1 << 8);
}
/*
*@brief Программа инициализации led
*/
void led_init(void)
{
led_io_init(void); //инициализация ввода-вывода led
blink_dev_create(&led, led_ctrl); //создание устройства led
blink_dev_ctrl(&led, 50, 100, 0); //быстрое мигание (50мс включено, 100мс выключено)
}
Аналогичен модулю blink, но есть два момента, на которые следует обратить внимание:
key_t key; //определение менеджера клавиш
/*
*@brief Событие клавиши
*@param[in] type - тип клавиши (KEY_PRESS, KEY_LONG_DOWN, KEY_LONG_UP)
*@param[in] duration - длительность удержания клавиши
*/
void key_event(int type, unsigned int duration)
{
if (type == KEY_PRESS) { //короткое нажатие
} else if (type == KEY_LONG_DOWN) { //долгое нажатие
}
}
//Чтение значения клавиши (предполагается, что выходной порт клавиши — STM32 MCU PA8)
int read_key(void)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == Bit_RESET;
}
/*
*@brief Инициализация клавиш
*/
void key_init(void)
{
//Включить часы GPIO
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
//Настроить в качестве входного режима
gpio_conf(GPIOA, GPIO_Mode_IN, GPIO_PuPd_NOPULL, GPIO_Pin_8);
//Создать одну клавишу
key_create(&key, read_key, key_event);
}
Поскольку в коде используются некоторые пользовательские функции, которые не вызываются явно, они могут быть оптимизированы при использовании GCC. Поэтому при компоновке необходимо добавить объявления для сохранения этих функций в файле связей (.lds):
.custom_sesion:
{
KEEP (*(SORT(init.item.*)))
KEEP (*(SORT(task.item.*)))
KEEP (*(SORT(pm.item.*)))
KEEP (*(SORT(cli.cmd.*)))
}
Здесь .custom_session обозначает имя пользовательского сегмента, KEEP указывает на сохранение этого кода, SORT сортирует код для удобства поиска программой.
Что делать, если в проекте MCU обычно используется файл связей, а в универсальных приложениях, подобных LINUX, используется стандартный файл связей?
Например, в случае GCC можно открыть программу ld, скопировать и сохранить её в файл .lds, а затем сослаться на него в makefile (обычно LDFLAGS += -Txxx.lds).
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )