Kurze Vorgeschichte
Ich war nun doch mehrere Tage auf der Suche, nach einem Tool mit dem man
eine etwas komplexere Menüführung, als Finite State Machine einfach
erstellen kann und welches C Code generiert.
Das Tool sollte auch einfach zu handeln sein
und sollte in einer einfachen Art und Weise in meine bestehende
Toolchain integrierbar sein.
Meine Toolchain:
STMCubeMX und SW4STM32 oder Atollic trueStudio
unter LINUX
Gefunden und ausprobiert hatte ich einiges, aber entweder Java, C++, ...
oder so gut wie nicht integrierbar.
Im Bereich C Code wird es da echt mager.
Ok propriätäre Software gibt es ein paar, aber das meiste für die
Windose
Fällt also aus wegen "isnich"
So nun will ich euch aber nicht weiter auf die Folter spannen.
Dieses Tool ist Open Source.
FW Profil Framework
https://github.com/pnp-software/fwprofile
Die Hauptfeatures sind:
C language implementation suitable for safety-critical, real-time
and embedded applications
Web-based modeling tool with C code generation available
Zum Erstellen der Diagramme gibt es einen Online Editor
https://pnp-software.com/fwprofile/editor
Ein Screenshot habe ich oben angehängt.
Die Integration ist im Prinzip recht einfach.
über git clone FW Profil herunter laden und den Ordner fwprofil/Src und
fwprofil/Inc in das eigene Projekt kopieren.
in ST4STM32
unter
Project->Porperties->C/C++ General->Paths and Symbols
-> Source Location
../fwprofil/Src
-> Library Paths
../fwprofil/Inc
unter
Project->Porperties->C/C++ Build->MCU GCC Compiler
-> Includes
../fwprofil/Inc
eintragen.
Nach dem Erstellen der FSM im Online Editor läd man sich die Zip Datei
herunter. Diese entpacke man an die entsprechende Stelle und verlinke
dann die 2 Dateien auf welche es ankommt.
mainFsm.zip wurde nach ./fwFsm entpackt
z.B. wie folgt
./fwFsm/mainFsm
./fwFsm/mainFsm/MainFsm.c ->link nach ../../Src/MainFsm.c
./fwFsm/mainFsm/MainFsm.h ->link nach ../../Irc/MainFsm.h
./fwFsm/mainFsm/MainFsmMain.c
./fwFsm/mainFsm/MainFsm.png
./fwFsm/mainFsm/MainFsm.json
Aus der Datei MainFsmMain.c kopiere man die #include *.h
und den benötigten Teil aus main() in die main.c, welche von STM32CubeMX
generiert wurde
1 | /**
|
2 | * @file MainFsmMain.c
|
3 | *
|
4 | * @author FW Profile code generator version 5.22
|
5 | * @date Created on: Jan 28 2019 23:30:11
|
6 | */
|
7 |
|
8 | /** MainFsm function definitions */
|
9 | #include "MainFsm.h"
|
10 |
|
11 | /** FW Profile function definitions */
|
12 | #include "FwSmConstants.h"
|
13 | #include "FwSmSCreate.h"
|
14 | #include "FwSmConfig.h"
|
15 | #include "FwSmCore.h"
|
16 |
|
17 | #include <stdio.h>
|
18 | #include <stdlib.h>
|
19 |
|
20 | int main(void)
|
21 | {
|
22 | /***************************************************COPPY START***/
|
23 | /** Define the state machine descriptor (SMD) */
|
24 | FwSmDesc_t smDesc = MainFsmCreate(NULL);
|
25 |
|
26 | /** Check that the SM is properly configured */
|
27 | if (FwSmCheckRec(smDesc) != smSuccess) {
|
28 | printf("The state machine MainFsm is NOT properly configured ... FAILURE\n");
|
29 |
|
30 | //do not use in STM!
|
31 | //you are in main()
|
32 | // _>>>>> return EXIT_FAILURE;
|
33 | }
|
34 |
|
35 | printf("The state machine MainFsm is properly configured ... SUCCESS\n");
|
36 |
|
37 | /** Start the SM, send a few transition commands to it, and execute it */
|
38 | FwSmStart(smDesc);
|
39 | FwSmMakeTrans(smDesc, TCLK);
|
40 | FwSmMakeTrans(smDesc, TCLAK);
|
41 | /******************************************************COPPY END***/
|
42 | return EXIT_SUCCESS;
|
43 | }
|
Das war es eigentlich schon.
main.c schaut dann ungefähr so aus.
1 | ...
|
2 | /* USER CODE BEGIN Includes */
|
3 | #include "stm32f4xx_hal.h"
|
4 | /** MainFsm function definitions */
|
5 | #include "MainFsm.h"
|
6 |
|
7 | /** FW Profile function definitions */
|
8 | #include "FwSmConstants.h"
|
9 | #include "FwSmSCreate.h"
|
10 | #include "FwSmConfig.h"
|
11 | #include "FwSmCore.h"
|
12 |
|
13 | #include <stdio.h>
|
14 | #include <stdlib.h>
|
15 |
|
16 | ....
|
17 | int main(void)
|
18 | {
|
19 | ...
|
20 | /* Infinite loop */
|
21 | /* USER CODE BEGIN WHILE */
|
22 | /** Define the state machine descriptor (SMD) */
|
23 |
|
24 | FwSmDesc_t smDesc = FwFsmCreate(NULL);
|
25 | printf("The state machine Example2 is properly configured ... SUCCESS\n");
|
26 |
|
27 | /** Start the SM, send a few transition commands to it, and execute it */
|
28 | FwSmStart(smDesc);
|
29 | while (1) {
|
30 | ...
|
31 | FwSmMakeTrans(smDesc, TriggerCLK);
|
32 | FwSmMakeTrans(smDesc, TriggerCLAK);
|
33 | .....
|
34 | }
|
35 | }
|
Jetzt müsste sich das Ganze bereits compilieren lassen.
Ich hab mir zum entpacken der *.zip ein kurzes bash Script geschrieben,
so dass nach dem Herunterladen nicht viel zu tun ist. Die gesetzten
links bleiben ja bestehen.
Wenn man in dem Online Editor z.B. die Global Properties auf der rechten
Seite benutzt kann man sehr einfach über z.B. #include "stm32l0xx_hal.h"
die Funktionen der HAL einbinden.
Einen Datenaustausch zwischen FSM und main.c habe u.a. mit einem Typedef
in einer externen Datei *.h realisiert.
und mit #include "fsmDefs.h" entsprechend eingebunden.
1 | typedef struct {
|
2 | FwSmBool_t switcher_raised;
|
3 | uint32_t switcher_value;
|
4 | ....
|
5 | char tmp[32];
|
6 | } FsmIFace ;
|
7 | FsmIFace iface;
|
mit z.B. kann man wie gewohnt Funktionen einbinden
extern void Error_Handler(void);
Die meiste Funktionalität kann man direkt in der StateMachine über
das * Properties Fenster am rechten Rand
per
-> define function
GUARD1_IF_SW1
gefolgt von
-> run code
1 | /*do not enter the STATE when sw1 is on */
|
2 | if(piface->sw1_value == 0){
|
3 | return 1;
|
4 | }
|
5 | return 0;
|
ALLES IN ALLEM sehr einfach einzubinden und die Einarbeitszeit bis zur
Benutzbarkeit hält sich auch im Rahmen.