STM8L–Первый старт
Сегодня по плану первый старт с демо платой STM8L-Discovery. В рамках которого хочется рассказать о том как самостоятельно создать простенький проект и прошить его. Что из этого получится посмотрим…
Введение
Ранее я писал что предлагаемые IDE меня не устраивают, уж больно сильно я подсел на Eclipse. Отказ ведет к потере автоматизма, в связи с чем придется собирать все ручками, но данный процесс меня устраивает. Однако это не мешает Вам использовать решения “по умолчанию”.
Cosmic
В состав пакета входят компилятор и компоновщик (линкер), задача компилятора прочитать наш программный код и сформировать из них набор инструкций, которые компоновщик соберет в конечный выходной файл годный для заливки в МК.
Исходя из того нам нужно каким-то образом объяснить компоновщику как устроен наш МК, т.е. написать некий сценарий (указать сколько у нас флеш и ОЗУ, по каким адресам расположены, а так же указать куда что «положить»).
Кроме того нужно выполнить начальную инициализацию МК.
Сценарий
Необходимый минимум информации который должен содержать сценарий:
- расположение и размер флеш, ОЗУ и EEPROM
- расположение кода, данных
- размер и расположение стека
Шаблон сценария идёт в комплекте с компилятором, файл располагается в корневой директории Stm8lkf.lkf. Я немного скорректировал его, и добавил комментарии:
#==========================================================
# File: Linker Script File for STM8L152C6
# Date: 2011-01-22
#==========================================================
# флеш: константы
+seg .const -b 0x8080 -m 0x7f80 -n .const -it
# флеш: программный код
+seg .text -a .const -n .text
# EEPROM
+seg .eeprom -b 0x1000 -m 0x400 -n .eeprom
# ОЗУ: нулевая страница
+seg .bsct -b 0x0 -m 0x100 -n .bsct
+seg .ubsct -a .bsct -n .ubsct
+seg .bit -a .ubsct -n .bit -id
+seg .share -a .bit -n .share -is
# ОЗУ:
+seg .data -b 0x100 -m 0x4ff -n .data
+seg .bss -a .data -n .bss
#----------------------------------------------------------
# начальная инициализация
crtsi0.sm8
# исходники
target/main.o
target/lcd_nokia_1100.o
# библиотеки
libis0.sm8
libm0.sm8
# таблица прерываний
+seg .const -b 0x8000 -k
target/stm8_interrupt_vector.o
# определения используются при начальной инициализации
+def __endzp=@.ubsct
+def __memory=@.bss
+def __startmem=@.bss
+def __endmem=0x5fe
+def __stack=0x7ff
Формат файла довольно прост, необходимо указать распределение памяти: флеш, EEPROM, ОЗУ. Далее перечислить исходники: код начальной инициализации, ваши исходники, файлы библиотек и таблицу прерываний. В заключении описаны определения необходимые для начальной инициализации микроконтроллера.
Начальная инициализация
В отличии от STM32, здесь я решил воспользоваться файлами идущими в комплекте с компилятором. На выбор имеются несколько вариантов начальной инициализации:
Название файла | Краткое описание |
crts.sm8 crts0.sm8 | Инициализация стека, передача управления основной программе |
crtsif.sm8 crtsx.sm8 crtsx0.sm8 crtsxf.sm8 | Инициализация стека, инициализация переменных, передача управления основной программе |
Наличие нескольких файлов с инициализацией переменных обусловлено структурой памяти, например файлы с именами заканчивающимися нулем предназначены для приложений с размером кода менее 64 кБ (при этом файлы библиотек так же должны заканчиваться “нулем”). Более подробно можно почитать в документации: C Cross Compiler User’s Guide for ST Microelectronics STM8, раздел Programming Environments.
Makefile
Все необходимое для сборки проекта у нас есть, можно приступить к майк-файлу. Долго не мудрил взял готовый от проекта на STM32 и поправил только под текущий компилятор. Вот что получилось:
>#==========================================================
# File: Makefile for STM8
# Date: 2011-01-22
#==========================================================
SRC_C = main.c
SRC_C += stm8_interrupt_vector.c
SRC_C += lcd_nokia_1100.c
#----------------------------------------------------------
CROSS_PATH = C:/Tools/Cosmic/4.3.4
CROSS = $(CROSS_PATH)/
INCLUDES += -imcu
INCLUDES += -imcu/peripherals
INCLUDES += -iutility
VPATH += mcu
VPATH += mcu/peripherals
VPATH += utility
#----------------------------------------------------------
FLAGS_C = +warn +mods0 -pxp -pp -l
#----------------------------------------------------------
all: clean target.elf
%.elf: $(SRC_C:%.c=target/%.o)
@echo Linking: $@
@echo '-----------------------------------------------------------'
@$(CROSS)clnk -l'$(CROSS_PATH)/Lib' -o'target/target.sm8' -m'target/target.map' -sa 'mcu/stm8l152c6.lsf'
@$(CROSS)cvdwarf target/target.sm8
@$(CROSS)chex -o target/target.s19 target/target.sm8
@$(CROSS)cobj -n target/target.sm8
@rm -f target/*.o
$(SRC_C:%.c=target/%.o): target/%.o: %.c
@$(CROSS)cxstm8 $(FLAGS_C) $(INCLUDES) -i. -i$(CROSS_PATH)/Hstm8 -cl'target' -co'target' $>
clean:
@echo '-----------------------------------------------------------'
@rm -f target/*.*
mcu_program:
@C:/Tools/STMicroelectronics/ToolKit/apisample.exe -BoardName=ST-LINK -Device=STM8L152x6 -Port=USB -ProgMode=SWIM -no_loop -no_log -FileProg=target/target.s19
mcu_restart:
@C:/Tools/STMicroelectronics/ToolKit/gdb7.exe --quiet --command=mcu/stm8l152c6.ini
.PHONY : all clean program
Ни чего сложного в файле нет. Вначале из исходников получаем объектные файлы, далее их собирает компоновщик, ну и для информативности вывожу информацию о секциях.
Последние две цели mcu_program и mcu_restart позволяют прошить и сбросить микроконтроллер, что очень удобно не нужно переключаться между окнами. (К сожалению данная утилита не хочет прошивать микроконтроллер установленный в STM32-Discovery, хотя теоритически должна. И почему то в ней не предусмотрен сброс, поэтому приходится использовать костыль в виде mcu_restart). Файл управляющих команд (stm8l152c6.ini):
#
# define emulator reset port and MCU
#
define emulator-reset-port-mcu
target gdi -dll swimstm_swim.dll -stlink3 -port $arg0 -mcuname $arg1
mcuname -set $arg1
end
#
# reset command and quit
#
emulator-reset-port-mcu usb://usb stm8l152c6
quit
В результате получаем вот такую информацию (сборка, прошивка, сброс):
make all
-----------------------------------------------------------
main.c:
mcu/stm8_interrupt_vector.c:
mcu/peripherals/lcd_nokia_1100.c:
Linking: target.elf
-----------------------------------------------------------
sections:
.const: hilo code, at address 0x8080
526 data bytes (0x020e)
.text: hilo code, at address 0x8291
1030 data bytes (0x0406)
.eeprom: no attribute, at address 0x1000
0 data bytes (0x0000)
.bsct: no attribute, at address 0x0
0 data bytes (0x0000)
.ubsct: bss hilo zpage, at address 0x0
11 reserved bytes (0x000b)
.bit: no attribute, at address 0xb
0 data bytes (0x0000)
.share: no attribute, at address 0xb
0 data bytes (0x0000)
.data: no attribute, at address 0x100
0 data bytes (0x0000)
.bss: bss hilo, at address 0x100
0 reserved bytes (0x0000)
.info.: no attribute, at address 0x0
770 data bytes (0x0302)
.const: hilo code, at address 0x8000
128 data bytes (0x0080)
.init: hilo code, at address 0x828e
3 data bytes (0x0003)
make mcu_program
Configuration:
BoardName=ST-LINK Device=STM8L152x6 Port=USB ProgMode=SWIM
Loading file target/target.s19 in PROGRAM MEMORY
Programming PROGRAM MEMORY
Cut Version and Revision of device: 2.0
Programming PROGRAM MEMORY succeeds
Verifying PROGRAM MEMORY
Cut Version and Revision of device: 2.0
Verifying PROGRAM MEMORY succeeds
make mcu_restart
Connected to the GDI Debug Instrument.
Disconnected from the GDI Debug Instrument.
Последний штрих
Для полного счастья нахватает только описать таблицу прерываний и структуру регистров микроконтроллера. Данные файлы я взял из стандартной либы. (stm8_interrupt_vector.c, stm8l15x.h). Приведу только файл с таблицей:
/* BASIC INTERRUPT VECTOR TABLE FOR STM8S devices
* Copyright (c) 2007 STMicroelectronics
*/
typedef void @far (*interrupt_handler_t)(void);
struct interrupt_vector
{
unsigned char interrupt_instruction;
interrupt_handler_t interrupt_handler;
};
@far @interrupt void NonHandledInterrupt (void)
{
/* in order to detect unexpected events during development,
it is recommended to set a breakpoint on the following instruction
*/
return;
}
extern void _stext(); /* startup routine */
struct interrupt_vector const _vectab[] =
{
{
0x82, (interrupt_handler_t)_stext
}
, /* reset */
{0x82, NonHandledInterrupt}, /* trap */
{0x82, NonHandledInterrupt}, /* irq0 - tli */
{0x82, NonHandledInterrupt}, /* irq1 - awu */
{0x82, NonHandledInterrupt}, /* irq2 - clk */
{0x82, NonHandledInterrupt}, /* irq3 - exti0 */
{0x82, NonHandledInterrupt}, /* irq4 - exti1 */
{0x82, NonHandledInterrupt}, /* irq5 - exti2 */
{0x82, NonHandledInterrupt}, /* irq6 - exti3 */
{0x82, NonHandledInterrupt}, /* irq7 - exti4 */
{0x82, NonHandledInterrupt}, /* irq8 - can rx */
{0x82, NonHandledInterrupt}, /* irq9 - can tx */
{0x82, NonHandledInterrupt}, /* irq10 - spi*/
{0x82, NonHandledInterrupt}, /* irq11 - tim1 */
{0x82, NonHandledInterrupt}, /* irq12 - tim1 */
{0x82, NonHandledInterrupt}, /* irq13 - tim2 */
{0x82, NonHandledInterrupt}, /* irq14 - tim2 */
{0x82, NonHandledInterrupt}, /* irq15 - tim3 */
{0x82, NonHandledInterrupt}, /* irq16 - tim3 */
{0x82, NonHandledInterrupt}, /* irq17 - uart1 */
{0x82, NonHandledInterrupt}, /* irq18 - uart1 */
{0x82, NonHandledInterrupt}, /* irq19 - i2c */
{0x82, NonHandledInterrupt}, /* irq20 - uart2/3 */
{0x82, NonHandledInterrupt}, /* irq21 - uart2/3 */
{0x82, NonHandledInterrupt}, /* irq22 - adc */
{0x82, NonHandledInterrupt}, /* irq23 - tim4 */
{0x82, NonHandledInterrupt}, /* irq24 - flash */
{0x82, NonHandledInterrupt}, /* irq25 - reserved */
{0x82, NonHandledInterrupt}, /* irq26 - reserved */
{0x82, NonHandledInterrupt}, /* irq27 - reserved */
{0x82, NonHandledInterrupt}, /* irq28 - reserved */
{0x82, NonHandledInterrupt} /* irq29 - reserved */
};
Хух, на этом пока все, далее по плану линии ввода-вывода и пример работы с ЖКИ индикатором от мобильного телефона Нокиа 1100.
Стандартная библиотека (STM8L15x standard peripheral library)
STM8L-Ultra Low Power-8 bits Microcontrollers
comments powered by Disqus