Хочу описать собственную идею (возможно она не нова), по которой я собираюсь создавать драйверы для различных аппаратных модулей, микросхем и тп.. Базируется она на основе использования статических библиотек, которые будут подключаться к основному проекту и представлять собой драйвер для какого-нибудь отдельно взятого модуля. Статическую библиотеку предлагаю писать на ассемблере, с целью сокращения объёма кода а также получения наивысшей производительности=) Такая библиотека, подключённая к основному проекту будет занимать минимум, при этом останется больше свободного места в памяти МК для написания основной логики.
В качестве примера можно рассмотреть тривиальный пример - драйвер для лампочки (индикатора). Данный пример подходит только для демонстрации самой идеи, а не её практического применения. Лампочка уж слишком простая вещь чтобы для неё писать целый драйвер. А вообще хотелось бы написать таковые для ЖК-дисплея, микросхемы ds1307, да много чего можно ещё придумать:) Главное желание, и свободное время. С последним у меня пока проблемы... Итак, приступим!
Подготовительная часть
1) Необходимо установить в систему пакеты gcc-avr, binutils-avr, и avr-libc. (если ещё не были установлены)
2) Вкратце изучить документацию по avr-libc. Там содержится очень много интересного(:3) Создать папку для основного проекта, у меня это ~/hard_project.
4) Создать папку для проекта библиотеки, у меня это ~/hard_project/libdrv.
Написание библиотеки
Основной файл будет иметь следующее содержание:
;; файл ~/hard_project/libdrv/leddrv.S: #include <avr/io.h> #include "conf.h" .global led_init ; void led_init() ; предварительная настройка порта led_init: sbi _SFR_IO_ADDR(LED_DDR),LED_NPIN ; установить ножку на вывод данных ret .global led_on ; void led_on() ; включение лампочки led_on: sbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логическую 1 в порт ret .global led_off ; void led_off() ; выключение лампочки led_off: cbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логический 0 в порт ret .global led_blink ; void led_blink(uint16_t f) ; мигание лампочки с заданной частотой led_blink: sbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логическую 1 в порт push r24 push r25 rcall delay ; задержать выполнение cbi _SFR_IO_ADDR(LED_PORT),LED_NPIN ; записать логический 0 в порт pop r25 pop r24 rcall delay ; задержать выполнение ret ; задержка на заданное значение delay: ; до 770*65535/F_CPU, сек clr r0 0: com r0 1: dec r0 brne 1b sbiw r24,1 brne 0b ; 770 тактов за цикл ret
Здесь первый параметр для функции led_blink будет передаваться через регистр r24:r25, согласно соглашениям компилятора avr-gcc. Далее, заголовочный файл будет иметь следующее содержание:
// файл ~/hard_project/libdrv/leddrv.h: #include <stdint.h> #ifdef F_CPU #define led_blink_ms(x) led_blink(((x)*(uint64_t)F_CPU)/(770*1000ul)) #endif void led_init(); void led_on(); void led_off(); void led_blink(uint16_t f);
Здесь определён макрос led_blink_ms для удобства. При его вызове нужно указывать значение в миллисекундах, в отличии от led_blink, в которой указывается значение в условных единицах =) Последний файл проекта будет иметь следующее содержание:
// файл ~/hard_project/libdrv/conf.h: #define LED_PORT PORTC #define LED_DDR DDRC #define LED_NPIN PC1
Ну здесь наверное понятно, указываются параметры порта и ножки на которой будет сидеть лампочка =)
Это всё. Теперь необходимо собрать нашу бибиотеку. Упрощённую версию Makefile для сборки проекта можно скачать тут. Скомандовав в консоли, я и получил целевой файл libleddrv.a:
$Make avr-gcc -Wall -x assembler-with-cpp -mmcu=atmega168 -o .leddrv.o -c leddrv.S avr-ar rcs libleddrv.a .leddrv.o
В следующий раз я покажу как использовал эту библиотеку в своём проекте=)
---
Скачать исходники libdrv.tar.gz
1 комментарий:
Ссылки на загрузку недействительны...перезалей пожалуйста ещё раз.
Отправить комментарий