Categories: C/C++

linux-timers-and-gpio/

По традиции, при изучении нового языка программирования первой пишется программа, показывающая сообщение «Hello world». В мире электроники есть аналогичная традиция, только вместо вывода сообщения нужно помигать светодиодом. При изучении модулей ядра Linux ( часть 1 , часть 2 ) мы как-то обошли стороной этот важнейший этап. Пришло время исправиться, и написать модуль, мигающий светодиодом.

Сразу перейдем к исходному коду модуля:

#include <linux/module.h>
#include <linux/gpio.h>

#define LED 14

static struct timer_list blink_timer ;
static int led_status = 0 ;

static void blink_timer_func ( struct timer_list * unused )
{
gpio_set_value ( LED , led_status ) ;

led_status = ! led_status ;

blink_timer. expires = jiffies + ( 1 * HZ ) ;
add_timer ( & blink_timer ) ;
}

int init_module ( void )
{
int ret = 0 ;

// register, turn off
ret = gpio_request_one ( LED , GPIOF_OUT_INIT_LOW , «led1» ) ;

if ( ret ) {
printk ( KERN_ERR «Unable to request GPIOs: %d n » , ret ) ;
return ret ;
}

timer_setup ( & blink_timer , blink_timer_func , 0 ) ;

led_status = 0 ;
blink_timer. expires = jiffies + ( 1 * HZ ) ;
add_timer ( & blink_timer ) ;

return ret ;
}

void cleanup_module ( void )
{
del_timer_sync ( & blink_timer ) ;

// turn LED off
gpio_set_value ( LED , 0 ) ;

// unregister GPIO
gpio_free ( LED ) ;
}

MODULE_LICENSE ( «GPL» ) ;

С GPIO мы уже работали в рамках заметки GPIO-пины Raspberry Pi и их использование из Python . Вспомним, какой пин где находится:

Это иллюстрация для Raspberry Pi 2, но у 3-ей и 4-ой малины пины расположены так же. По коду не сложно понять, что он мигает светодиодом на 14-ом пине.

Fun fact! В Raspbian есть команда pinout . Она очень наглядно выводит в консоль информацию о доступных пинах, и не только он них.

Для работы с GPIO модуль использует процедуры gpio_request_one , gpio_free и gpio_set_value . Думаю, что в пояснениях они не нуждаются. Если вам хочется больше узнать про GPIO, рекомендую почитать Documentation/driver-api/gpio/ в исходном коде ядра Linux.

Для изменения состояния пина модуль использует таймеры . Это новый для нас примитив, так что остановимся на нем поподробнее.

Таймеру соответствует структура timer_list . Инициализация происходит при помощи процедуры timer_setup , а уничтожение — при помощи del_timer_sync . Процедура add_timer позволяет запланировать выполнение колбэка, переданного вторым аргументом в timer_setup . Время срабатывания колбэка определяется значением поля expires структуры timer_list .

Время в ядре Linux измеряется в так называемых jiffies. Это время с момента запуска системы. Единица измерения jiffies зависит от платформы. Макрос HZ хранит количество jiffies в одной секунде. Текущее время можно получить через глобальную переменную jiffies .

Таким образом, код:

blink_timer. expires = jiffies + ( 1 * HZ ) ;
add_timer ( & blink_timer ) ;

… говорит таймеру сработать через одну секунду.

Указанный колбэк, в нашем случае — blink_timer_func , выполняется в контексте прерывания (interrupt context). Это означает, что колбэк должен вернуть управление как можно быстрее. В нем не допускается делать блокирующие вызовы, такие как msleep или mutex_lock , ровно как и долго крутиться в цикле.

Функции printk , add_timer , del_timer и kfree всегда безопасно вызывать из любого контекста . Работа с GPIO на большинстве платформ реализована, как обращение к памяти, и потому также не является блокирующей. Для пина, работа с которым на текущей платформе приводит к блокировкам, процедура gpio_cansleep возвращает ненулевое значение.

В качестве домашнего задания убедитесь, что на Raspberry Pi безопасно работать с GPIO в контексте прерывания. Полная версия исходников доступна на GitHub . А на сегодня это все. Казалось бы, рассмотренный модуль был совсем простым. Но смотрите, как много нового мы узнали!

Дополнение: Модули ядра Linux: обработка прерываний

admin

Share
Published by
admin
Tags: C/C++

Recent Posts

Консоль удаленного рабочего стола(rdp console)

Клиент удаленного рабочего стола (rdp) предоставляет нам возможность войти на сервер терминалов через консоль. Что…

1 месяц ago

Настройка сети в VMware Workstation

В VMware Workstation есть несколько способов настройки сети гостевой машины: 1) Bridged networking 2) Network…

1 месяц ago

Логи брандмауэра Windows

Встроенный брандмауэр Windows может не только остановить нежелательный трафик на вашем пороге, но и может…

1 месяц ago

Правильный способ отключения IPv6

Вопреки распространенному мнению, отключить IPv6 в Windows Vista и Server 2008 это не просто снять…

1 месяц ago

Ключи реестра Windows, отвечающие за параметры экранной заставки

Параметры экранной заставки для текущего пользователя можно править из системного реестра, для чего: Запустите редактор…

1 месяц ago

Как управлять журналами событий из командной строки

В этой статье расскажу про возможность просмотра журналов событий из командной строки. Эти возможности можно…

1 месяц ago