Początki z STM8

To miejsce dla mało znanych mikrokontrolerów jak ST7, ST8, MSP itd , z wyłączeniem AVR !!
Regulamin forum
W tym miejscu dopuszczalne są wszelkie formy mikrokontrolerów 8/16/24 bitowych , ale nie wolno zamieszczać postów dotyczących mikrokontrolerów AVR , ARDUINO itd ... jest wiele for im poświęconych i wszystkie ATMEGOWE będą definitywnie poddawane dekapitacji.

PISZEMY tylko o mikrokontrolerach:

ST7 , STM8, MSP430 , dsPIC , i innych mało znanych i popularnych
a nawet zapomnianych jak : Z80, 6510 , m68K ...

NIE PISZEMY O POPULARNYCH AVR !!
ODPOWIEDZ
Awatar użytkownika
squeez
Użytkownik
Posty: 102
Rejestracja: 16 paź 2017, 23:52

Początki z STM8

Post autor: squeez » 18 sty 2019, 2:57

Zaciekawiony tą rodziną musiałem coś w nich pogrzebać.

I tak wczoraj przyszłą płytka (w sumie to kilka) z STM8S003F3. O samym układzie nie będę pisał bo każdy to znajdzie w sieci ale opiszę swoje początki.

Na starcie mała przykrość nie ma gcc ale nie ma też tragedii jest darmowy (opensource) kompilator sdcc (http://sdcc.sourceforge.net) poza STM8 obsługuje jeszcze (kilka innych mikrokontrolerów).

No to trzeba przygotować środowisko. Ponoć są jakieś gotowe na windowsy ale że ja jestem odmieńcem (używam linuxa) to opis będzie dotyczyć tego systemu.

Co potrzebujemy:
1) kompilator
2) program do wgrania wsadu
3) jakiś edytor do pisania

i na tym można by poprzestać ale przyda się jeszcze plik z makrami i definicjami rejestrów, można to zrobić samemu na podstawie DS/RM ale można też skorzystać z gotowych. Na githubie jest tego całą masa, różni autorzy przyjmują różne standardy. Ja postanowiłem skorzystać z tego udostępnianego przez producenta. Jednak z pewnym wyjątkiem.
Na stronie ST (https://www.st.com/en/embedded-software ... m8069.html) jest całą biblioteka taki SPL dla STM8S/A jednak że SPL za specjalnie mi nie przypada to wykorzystuję tylko plik stm8s.h w którym są makra do rejestrów i struktury danych.

Dla potrzeb sdcc należy też go trochę zmodyfikować gdyż przystosowany jest on dla komercyjnych kompilatorów (raisonance i cosmic).

No to zaczynamy:
Poniższe kroki dotyczą Dystrybucji Debian (Buster) z której obecnie korzystam w innych dystrybucjach pochodnych od Debiana będzie podobnie jak nie tak samo.

1) instalacja kompilatora.

Kod: Zaznacz cały

#apt-get install sdcc sdcc-libraries
2) program do flashowania
Z pomocą przychodzi github i polecany program stm8flash (https://github.com/vdudouyt/stm8flash)

Kod: Zaznacz cały

$git clone https://github.com/vdudouyt/stm8flash
Przed kompilacja powinniśmy się zaopatrzyć w libusb-1.0-0-dev jeśli jeśli jej nie macie to zainstalować

Kod: Zaznacz cały

#apt-get install libusb-1.0-0-dev
być może będzie jeszcze potrzebny pkg-config ja go miałem już wcześniej.
Jak wszystko skompletowane to kompilacja programu:

Kod: Zaznacz cały

$cd stm8flash
$make
po tym powinniśmy mieć w katalogu plik binarny stm8flash ja dla wygody kopiuję go do /usr/local/bin żeby było łatwo wywołać (bez podawania pełnej ścieżki).

3) edytor to już każdy jakiś ma :) mi już od jakiegoś czasu przypadł do gustu sublime (https://www.sublimetext.com/3) jest na Win Linux Mac.

Teoretycznie można już pisać kod kompilować i wgrywać ale ułatwieniem będzie Makefile w IDE jak Eclipse czy Atolic (też eclipse) Makefile się nie przejmujemy bo samo środowisko tworzy go dynamicznie przed kompilacja, dla użytkownika jest to niejako niewidzialny proces.

Ja swój Makefile poskładałem z kliku istniejących + dopisałem kilka swoich rzeczy.

Cłego nie będę prezentował wszystko z przykładowym projektem będzie w paczce na końcu posta. Zamysł jest taki że projekt składa się z 3 katalogów: bin - do którego trafia efekt końcowy pracy (między innymi plik ihex), inc - miejsce na pliki nagłówkowe, src - katalog dla plików źródłowych c.

Tak wygląda to u mnie:
Obrazek
W edytorze po lewej widać strukturę projektu i w zakładkach otwarte pliki. Jedynym wyjątkiem jest plik od ST (stm8s.h) który trzymam poza projektem (żeby nie musieć go za każdym razem dodawać do każdego projektu) a to jakie makra będą wykorzystane (czasami adresy rejestrów są różne dla różnych mikrokontrolerów) w Makefile jest przekazana zmienna dla prekompilatora z jakiego uC korzystamy w projekcie i jakich makr ma użyć.

No dobra to prosty kod do miagania LED-em na płytce podpiętym do pinu PB5, a miganie na przerwaniach TIM4.

główny kod plik main.c

Kod: Zaznacz cały

#include "stm8s.h"
#include "stm8s_it.h"
#include "common.h"

int main(void) {
   setup();
   rim();
   while(1) {
    }
}
plik common.c

Kod: Zaznacz cały

#include "stm8s.h"
#include "common.h"

void setup(void) {
	// GPIO
	GPIOB->DDR |= LED;
	GPIOB->CR1 |= LED;

	//Tim4
	TIM4->PSCR = TIM4_PSCR_PSC; // pre. 128
	TIM4->ARR = 99;
	TIM4->IER |= TIM4_IER_UIE;
	TIM4->CR1 |= TIM4_CR1_CEN;
}
plik z funkcjami (funkcją) obsługi przerwań stm8s_it.c:

Kod: Zaznacz cały

#include "stm8s.h"
#include "stm8s_it.h"
#include "common.h"

void TIM4_update(void) __interrupt (IE_TIM4_OVR_UIF) {
	static uint8_t sec = 100;
	TIM4->SR1 &= ~TIM4_SR1_UIF;
	
	if( !sec-- ) {
		ChgBit(GPIOB->ODR, 5);
		sec = 100;
	}
}
Potrzebny jest jeszcze plik z numerami wektorów przerwań (tan akurat pisałem sam i jest pod STM8S003F3 dla podobnych z rodziny będzie tak samo ale przy innych trzeba sprawdzić i ewentualnie poprawić (dopisać).

Kod: Zaznacz cały

#ifndef STM8S_IT__H
#define STM8S_IT__H

/* Interrupt numbers */
#define IE_TLI				0
#define IE_AWU				1
#define IE_CLK				2
#define IE_EXTI0			3
#define IE_EXTI1			4
#define IE_EXTI2			5
#define IE_EXTI3			6
#define IE_EXTI4			7
#define IE_SPI				10
#define IE_TIM1_OVR_UIF 	11
#define IE_TIM1_CAP_COM 	12
#define IE_TIM2_OVR_UIF 	13
#define IE_TIM2_CAP_COM 	14
#define IE_UART1_TX			17
#define IE_UART1_RX			18
#define IE_I2C				19
#define IE_ADC1_EOC 		22
#define IE_TIM4_OVR_UIF 	23
#define IE_FLASH			24

void TIM4_update(void) __interrupt (IE_TIM4_OVR_UIF);
#endif
Ten plik nagłówkowy musimy też inkludować w mian.c bez tego będzie kupa o czym się sam przekonałem tracąc kilka czas dlaczego nie działają przerwania. Fragment z dokumentacji If you have multiple source files in your project, interrupt service routines can be present in any of them, but a prototype of the isr MUST be present or included in the file that contains the function main.

No dobra reszt nie zamieszczam będzie do pobrania na końcu.

Teraz co do samej kompilacji. Jak wspomniałem jest Makefile więc będąc w katalogu projektu możemy skorzystać z 4 poleceń:
1) make - kompilacja projektu
2) make clena - sprzątanie po kompilacji
3) make size - wyświetli ile zajmuje wsad (niestety sdcc nie ma jeszcze statystyk wykorzystania pamięci)
4) make flash (wgranie wsadu do układu)

No i oczywista oczywistość żeby wgrać potrzebujemy jeszcze programator najlepiej ST-LINK2 (więc jak nie samodzielnego to można wykorzystać ten z płytek Nucleo czy Doscovery od STM).
A pinologia do podłączenia:
1) GND
2) NRST
3) SWIM

Obrazek

Plik z projektem poniżej jedyne co trzeba zmienić to w Makefile wiersz:

Kod: Zaznacz cały

BASE_HEADERS = /home/misiek/workspaces/stm8/include
Który wskazuje katalog include w którym znajduje się plik stm8s.h

Jak wspomniałem to początek drogi z STM8 i sdcc.
Będę musiał jeszcze sprawdzić openocd bo ponoć ma możliwość debugowania po SWIM więc być może pojawi się jeszcze jakiś wpis.

A tymczasem zachęcam do zabawy z 8bit ale jakże urokliwym w porównaniu z AVR.
stm8_tim4.zip
Nie masz wymaganych uprawnień, aby zobaczyć pliki załączone do tego posta.

Awatar użytkownika
Nefarious19
Moderator
Posty: 21
Rejestracja: 17 paź 2017, 10:03
Lokalizacja: Łódź

Re: Początki z STM8

Post autor: Nefarious19 » 18 sty 2019, 11:08

Super artykuł! Ja dorzucam od siebie paczkę pod Windowsa z:
  • SDCC - kompilator
  • STM8S_StdPeriph_Lib_V2.3.1 - biblioteki do peryferiów od ST spaczowane pod SDCC
  • stm8flasher - skompilowany pod windowsa. Wymaga zainstalowanej biblioteki libusb0.dll
https://1drv.ms/u/s!Ak14cjNgL-UDaIpDirsrijqDMfE

Awatar użytkownika
l3n1n
Moderator
Posty: 216
Rejestracja: 28 paź 2017, 8:46
Lokalizacja: 3M

Re: Początki z STM8

Post autor: l3n1n » 18 sty 2019, 12:08

Dzięki, mam nadzieję skorzystać 🙂

gufim
Użytkownik
Posty: 45
Rejestracja: 16 paź 2017, 16:58

Re: Początki z STM8

Post autor: gufim » 18 sty 2019, 13:25

Wielkie dzięki :)

Awatar użytkownika
squeez
Użytkownik
Posty: 102
Rejestracja: 16 paź 2017, 23:52

Re: Początki z STM8

Post autor: squeez » 19 sty 2019, 20:55

No dobra to leci my dalej z tematem :)

Pomimo że w STM8 podobnie jak w STM32 mamy jedną przestrzeń adresową czy to FLASH, RAM czy EEPROM możemy bezpośrednio się do nich odwoływać ... ale. Domyślnie po resecie i starcie programu zapis do FLASH i EEPROM jest zablokowany (takie zabezpieczenie przed przypadkowym nadpisaniem).

Pilnuje tego MASS (nie mylić z niejakim Masą) - Memory Access Security System.
Żeby zdjąć ochronę trzeba wykonać dość prostą sekwencję zapisu do rejestru FLASH_DUKR. Dla odblokowania zapisu w eeprom musimy do tego rejestru zapisać najpierw wartość 0xAE i zaraz potem 0x56, jeśli tego nie zrobimy to dostęp do zapisu będzie zablokowany a ponowną próbę odblokowania będzie można zrobić po resecie. Ponowne wprowadzenie hardware key (tak się nazywają te wartości) nic nie da.

No dobra jak już odblokujemy dostęp to możemy się jeszcze upewnić bit DUL w rejestrze FLASH_IAPSR powinien mieć wartość 1 w przypadku blokady zapisu ma on wartość 0.

Po odblokowaniu zapisu możemy już zapisywać pamięć, dobra praktyka to po zapisie ponownie zablokować by przypadkiem nie nabałaganić, jak wyżej napisałem wyzerowanie bitu DUL powoduje załączenie blokady.

Napisałem dwie proste funkcje do zapisu i odczytu EEPROM-a:

Kod: Zaznacz cały

uint8_t eeprom_read(uint8_t addr) {
	uint8_t *eemem = (char *) 0x4000;
	return *(eemem + addr);
}

void eeprom_save(uint8_t addr, uint8_t *data, uint8_t len) {
	uint8_t *eemem = (char *) 0x4000;

	if( !(FLASH->IAPSR & FLASH_IAPSR_DUL) ) {
	// Write lock
		FLASH->DUKR = 0xAE;
		FLASH->DUKR = 0x56;
		while ( !(FLASH->IAPSR & FLASH_IAPSR_DUL) );
	}

	for( uint8_t i = 0; i<len; i++) {
		*(eemem + addr + i) = data[i];
		while ( !(FLASH->IAPSR & FLASH_IAPSR_EOP) );
	}

	FLASH->IAPSR &= ~FLASH_IAPSR_DUL; 
}
W podobny sposób możemy z poziomu programu odczytywać i zapisywać FLASH-a. Z tym że są nieco inne BITY i rejestr. Oraz klucz (hardware key).

Dla FLASH-a rejestr dla kluczy to FLASH_PUKR klucze najpierw 0x56 a potem 0xAE do sprawdzenia blokady bit PUL w rejestrze FLASH_IAPSR.
No i oczywiście flash zaczyna się pod innym adresem 0x8000 gdzie w przypadku eeprom jest to 0x4000.

Awatar użytkownika
squeez
Użytkownik
Posty: 102
Rejestracja: 16 paź 2017, 23:52

Re: Początki z STM8

Post autor: squeez » 20 sty 2019, 10:55

Jeszcze kilka zmian w projekcie a gównie w makefile.
Obrazek

1) bin - katalog do którego trafia końcowy wynik kompilacji (binarki)
2) inc - katalog na pliki nagłówkowe (.h)
3) src - katalog na pliki źródłowe (.c) main.c również
4) tmp - katalog do którego trafiają kompilowane pliki źródłowe, które linker łączy i tworzy z nich binarke

W poprzedniej wersji nie było tmp i pliki będące wynikiem kompilacji trafiały tam gdzie pliki źródłowe przez co mogło to wyglądać chaotycznie. Oczywiście make clean czyściło wszytko i zostawały same pliki .c ale w takim układzie jak teraz jest lepszy ład :)

Zmieniłem też ścieżkę bezwzględną na względną dla includowania pliku nagłówkowego dla rejestrów (stm8s.h).
Teraz bez żadnych modyfikacji każdy powinien u siebie odpalić kompilacje.

Makefile

Kod: Zaznacz cały

DEVICE = stm8s003f3
#DEVICE = stm8s103f3

BASE_HEADERS = ../include
SRC_DIR = src
INC_DIR = inc
TMP_DIR = tmp
OUT_DIR = bin

PROGRAM = $(lastword $(subst /, ,$(CURDIR)))

SOURCES = $(wildcard *.c $(SRC_DIR)/*.c)
OBJECTS = $(SOURCES:.c=.rel)
HEADERS = $(wildcard *.h $(INC_DIR)/*.h)

CC = sdcc
OBJCOPY = sdobjcopy
PROGRAMMER = stlinkv2

DEFINES = -D__SDCC__
## Set MCU-type DEFINE
ifeq ($(DEVICE),stm8s003f3)
    DEFINES += -DSTM8S003
endif
ifeq ($(DEVICE),stm8s103f3)
    DEFINES += -DSTM8S103
endif

CPPFLAGS = -I$(SRC_DIR) -I$(INC_DIR) -I$(BASE_HEADERS)
CFLAGS = --Werror --std-sdcc99 -mstm8 $(DEFINES) -c
LDFLAGS = -lstm8 -mstm8 --out-fmt-ihx
CFLAGS_O = --opt-code-size

.PHONY: all clean flash

%.rel : %.c $(HEADERS)
	$(CC) --verbose $(CFLAGS) $(CPPFLAGS) -o $(subst src,tmp, $@)  $<

$(PROGRAM).ihx: $(OBJECTS)
	$(CC) --verbose $(LDFLAGS) $(subst src,tmp, $^) -o $(OUT_DIR)/$@

clean:
	@echo "--- Czyszczenie katalogow: bin, tmp ---"
	rm -f $(OUT_DIR)/*
	rm -f $(TMP_DIR)/*

size:
	@$(OBJCOPY) -I ihex --output-target=binary $(OUT_DIR)/$(PROGRAM).ihx $(OUT_DIR)/$(PROGRAM).bin
	@echo "--- Rozmiar binarki ---"
	@stat -L -c %s $(OUT_DIR)/$(PROGRAM).bin

flash: $(PROGRAM).ihx
	stm8flash -c $(PROGRAMMER) -p $(DEVICE) -w $(OUT_DIR)/$(PROGRAM).ihx
Na chwilę obecną kompilowane jest dla STM8S003F3 żeby to zmienić należy podać odpowiedni typ układu dla zmiennej DEVICE w pliku Makefile
W pliku jestejeszcze możliwość wyboru STM8S103F3

to co podamy w DEVICE trafia jako parametr do programu stm8flash

Kod: Zaznacz cały

-p $(DEVICE)
oraz dodawana jest zmienna dla preprocesora na podstawie której wybierane są rejestry z plku stm8s.h na zasadie prostyc instrukcji warunkowych.

Zgodnie z tym co jest w pliku stm8s.h możemy programować ukłądy:

Kod: Zaznacz cały

 /* #define STM8S208 */      /*!< STM8S High density devices with CAN */
 /* #define STM8S207 */      /*!< STM8S High density devices without CAN */
 /* #define STM8S007 */      /*!< STM8S Value Line High density devices */
 /* #define STM8AF52Ax */    /*!< STM8A High density devices with CAN */
 /* #define STM8AF62Ax */    /*!< STM8A High density devices without CAN */
 /* #define STM8S105 */      /*!< STM8S Medium density devices */
 /* #define STM8S005 */      /*!< STM8S Value Line Medium density devices */
 /* #define STM8AF626x */    /*!< STM8A Medium density devices */
 /* #define STM8AF622x */    /*!< STM8A Low density devices */
 /* #define STM8S103 */      /*!< STM8S Low density devices */
 /* #define STM8S003 */      /*!< STM8S Value Line Low density devices */
 /* #define STM8S903 */      /*!< STM8S Low density devices */
 /* #define STM8S001 */      /*!< STM8S Value Line Low denisty devices */
Więc jak byśmy chcieli zrobić projekt dla STM8S207 dla zmiennej DEVICE podajemy stm8s207c8 (lista wspieranych układów przez stm8flash dostaniemy jak wywołamy stm8flash -l) i do Makefile należało by dodać warunek:

Kod: Zaznacz cały

ifeq ($(DEVICE),stm8s207c8)
    DEFINES += -DSTM8S207
endif
Małe wyjaśnienie:

DEFINES - to nazwa zmiennej
DEFINES = costam - to przypisanie zmiennej wartości (costam)
DEFINES += cos innego - powoduje dopisanie do zmiennej (dodanie/połączenie) "cos" czyli po tym DEFINES ma warość "costam cos"

-DJAKISCIAG=jeszczecos powoduje -D (dodanie "zmiennej" dla preprocesora) z przypisaniem jej wartości (znak =) czyli tak ja by w pliku .h wstawić

Kod: Zaznacz cały

#define JAKISCIAG  jeszczecos
bez przypisania wartość zostanie tylko zdefiniowana zmienna, a na tym nam zależy bo przed kompilacją preprocesor dokona odpowiednich wyborów w pliku.

W sumie to nie chciałem opisywać za bardzo Makefile bo sam mało wiem ale chociaż ta podstawowa wiedza będzie potrzebna żeby dostosować plik do własnego projektu.

ODPOWIEDZ