Standard Peripherals Library (она же SPL) - это модуль аппаратной абстракции (HAL) для микроконтроллеров STM8/STM32 за авторством STMicroelectronics. Эта библиотека представляет собой описание регистров, констант и функций для взаимодействия с периферией. Необходимость HAL объясняется просто: бизнес-логика не должна напрямую зависеть от платформы на которой она работает. В этом случаи возможна безболезненная замена платформы. А еще становится доступно модульное тестирование за счет подмены функций HAL на mock-функции.
В оригинальной версии эта библиотека не совместима с компилятором SDCC. Но сторонними разработчиками разработан публичный патч
Компилятору необходимо передать дефайн DEVICE=STM8SXXX. STM8SXXX - модель микроконтроллера, полный список можно посмотреть в заголовочном файле stm8s.h
Часть файлов нужно включать в сборку условно в зависимости от модели микроконтроллера. Пример из скрипта сборки:
set(UART2_PRESENT
"STM8S105"
"STM8S005"
"STM8AF626x"
)if(${DEVICE} IN_LIST UART2_PRESENT)
set(SPL_SOURCES ${SPL_SOURCES} ${SPL_SOURCE_DIR}/stm8s_uart2.c)
endif()
mark_as_advanced(UART2_PRESENT)
Также потребуется несколько дополнительных файлов. Шаблоны есть в документации к библиотеке.
stm8s_conf.h
В этом файле в зависимости от модели микроконтроллера
(дефайн DEVICE) подключаются заголовочные файлы доступной
перферии и определяется макрос assert_param, при помощи
которого библиотека проверяет входные параметры функций. Проверка
параметров мне сейчас не требуется, поэтому я удалил
строчку #define USE_FULL_ASSERT (1))
для развертывания
макроса assert_param в пустое выражение. Этот файл включается
в stm8s.h (основной загловочный файл SPL).
stm8s_it.h
Тут находятся объявления обработчиков прерываний. Включается в stm8s.h
stm8s_it.c
Определения обработчиков прерываний. Непосредственно для сборки SPL он не нужен, но потребуется при компоновке с ней.
Тестовый пример будет таким:
#include <stm8s.h>
#define LED_GPIO_PORT (GPIOB)
#define LED_GPIO_PINS (GPIO_PIN_ALL)
void delay(uint32_t t) {
while (t--)
;
}
void main(void) {
(LED_GPIO_PORT,
GPIO_Init(GPIO_Pin_TypeDef)LED_GPIO_PINS,
);
GPIO_MODE_OUT_PP_LOW_FAST
for (;;) {
(LED_GPIO_PORT,
GPIO_WriteReverse(GPIO_Pin_TypeDef)LED_GPIO_PINS);
(10000UL);
delay}
}
Функция GPIO_Init выполняет настройку порта (выход, push-pull). Функция GPIO_WriteReverse изменяет состояние порта для мигания светодиодом. Назначения функций и констант понятны из их имен.
К сборке бинарника (в главном CMakeLists.txt) добавляем добавляем опеределения обработчиков прерывания (stm8s_it.c) и линкуем его с SPL:
set(DEVICE "STM8S103")
include_directories(${CMAKE_SOURCE_DIR})
add_subdirectory(vendor/STM8S_StdPeriph_Lib)
add_executable(blink
main.c
stm8s_it.c
)target_link_libraries(blink spl)
Пример для таймера TIM4. Обработчик прерывания таймера в stm8s_it.c:
/*
* Current frenq master clock: 16MHz HSI / 8 (default prescaler) = 2MHz
* Irq overflow frenq: 2MHz / (256 * 128 (max prescaler)) = ~60Hz
*/
(TIM4_UPD_OVF_IRQHandler, 23)
INTERRUPT_HANDLER{
static uint8_t c = 0;
++;
cif (c == 15) {
(LED_GPIO_PORT,
GPIO_WriteReverse(GPIO_Pin_TypeDef)LED_GPIO_PINS);
= 0;
c }
(TIM4_IT_UPDATE);
TIM4_ClearITPendingBit}
Для повторных срабатываний прерывания необходимо очищать флаг
вызовом TIM4_ClearITPendingsBit.
Так же внутри реализован импровизированый делитель, чтобы мигание можно
было наблюдать без осцилографа.
В функции main настраивается порт, таймер, разрешаются прерывания, включается счет таймера и запускается бесконечный цикл.
int main(void) {
(LED_GPIO_PORT,
GPIO_Init(GPIO_Pin_TypeDef)LED_GPIO_PINS,
);
GPIO_MODE_OUT_PP_LOW_FAST
(TIM4_PRESCALER_128, TIM4_ARR_RESET_VALUE);
TIM4_TimeBaseInit(TIM4_FLAG_UPDATE);
TIM4_ClearFlag(TIM4_IT_UPDATE, ENABLE);
TIM4_ITConfig
();
enableInterrupts
(ENABLE);
TIM4_Cmd
for (;;)
;
}
January 2021