1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/moluo-tech-CodeBrick

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
README.md

CodeBrick

Введение

CodeBrick — это практичная программная среда без операционной системы для микроконтроллеров (MCU), включающая в себя управление задачами опроса, менеджер команд, управление низким энергопотреблением и кольцевой буфер. В системе широко используется технология пользовательских сегментов для уменьшения взаимосвязей между различными модулями, что значительно повышает удобство сопровождения программы.

Основные функции

  • Поддержка автоматического управления модулями и предоставление интерфейсов инициализации с разными уровнями приоритета.
  • Поддержка управления опросом задач через простые макроопределения, без необходимости сложных вызовов.
  • Поддержка управления низким энергопотреблением, включая режимы сна и пробуждения.
  • Поддержка анализа и выполнения команд командной строки.
  • Управление устройствами мигания, включая унифицированное управление светодиодами, вибромоторами и зуммерами.

Использование Полную версию кода можно найти в файле проекта. Платформа разработки включает:

  • MCU: STM32F401RET6;
  • IDE: IAR 7.4 или Keil MDK 4.72A.

Инициализация задач и управление опросом (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 для компиляции и использования.

Регистрация устройств с низким энергопотреблением Например, сканирование клавиатуры. В режиме низкого энергопотребления, если клавиатура не нажата, система может перейти в спящий режим без влияния на функциональность клавиатуры. Если нажать клавишу, системе необходимо периодически просыпаться и опрашивать задачу сканирования клавиатуры.

Поэтому в системе с низким энергопотреблением необходимо решить две проблемы:

  1. Система находится в спящем режиме, но если нажать клавишу, то система должна немедленно проснуться, чтобы обработать последующее сканирование.
  2. Если нажата клавиша, система может перейти в спящий режим, но необходимо периодически просыпаться, чтобы опрашивать задачу клавиатуры.

Для решения первой проблемы можно настроить клавиатуру как граничное прерывание для пробуждения, например, для 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);

Модуль blink

Управление устройствами с мигающими характеристиками (светодиоды, двигатели, зуммеры).

Использование:

  • Требуется, чтобы система предоставляла часы с тиками, которые доступны в blink.c через интерфейс get_tick(), и зависят от модуля module.
  • Необходимо периодически опрашивать задачу.

Либо это может быть реализовано через регистрацию задач в модуле «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.c через интерфейс get_tick() и зависящие от модуля module;
  • необходимо периодически опрашивать задачу.
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

Поскольку в коде используются некоторые пользовательские функции, которые не вызываются явно, они могут быть оптимизированы при использовании 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 )

Вы можете оставить комментарий после Вход в систему

Введение

Практичная система управления программным обеспечением для микроконтроллеров без операционной системы, включающая в себя: * структуру опроса задач; * менеджер команд; * управление низким энергопотреблением; * кольцевой буфер и другие полезные модули. Развернуть Свернуть
Apache-2.0
Отмена

Обновления

Пока нет обновлений

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/moluo-tech-CodeBrick.git
git@api.gitlife.ru:oschina-mirror/moluo-tech-CodeBrick.git
oschina-mirror
moluo-tech-CodeBrick
moluo-tech-CodeBrick
master