wiki:news:10oct2013
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
wiki:news:10oct2013 [2013/09/09 21:32] – pmueller | wiki:news:10oct2013 [2022/08/17 19:44] (current) – Discussion status changed pmueller | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== |
- | The sinelabore code generator allows | + | Sometimes you want to run the same state machine |
- | code from quite complex | + | |
- | Nevertheless | + | Luckily in C there is also a well known concept |
- | complex models. Especially if you used specialized state machine modeling tools | + | |
- | before and now want to switch to general purpose UML tools this is for you. | + | |
- | Examples for features not possible before are states in regions that contain regions again (region in region((Regions are well supported from the code-generator. But simulation and test-case generation is not yet possible. For more details have a look in the manual. | + | In this example we will show you how to " |
+ | And then we show you how to create an own structure where additional private data for the state handler can be defined. | ||
- | ))). | + | Let's start ... |
- | Or models with sub-machines in regions. Both is shown in the figure below. | + | |
- | Have fun! | + | ===== Create Multiple Instances ===== |
+ | Follow these simple steps to prepare the generated code for multiple instances. First set some parameters in the configuration file: | ||
+ | - Set parameter '' | ||
+ | - Set parameter '' | ||
+ | As a result the generated state machine handler signature looks like this: | ||
- | {{ : | + | <code c> |
+ | void testcase(TESTCASE_INSTANCEDATA_T* userInstanceVar, | ||
+ | </ | ||
- | {(rater> | + | You can now simply declare multiple variables of type TESTCASE_INSTANCEDATA_T which contains the data per instance. When calling the state machine just point to one of these variables. |
- | ~~DISCUSSION|Leave your comments~~ | + | |
+ | Sometimes it is necessary that a state machine knows on which object it currently works on. Therefore a predefined member called '' | ||
+ | |||
+ | <code c> | ||
+ | TESTCASE_INSTANCEDATA_T instDataA = TESTCASE_INSTANCEDATA_INIT; | ||
+ | TESTCASE_INSTANCEDATA_T instDataB = TESTCASE_INSTANCEDATA_INIT; | ||
+ | TESTCASE_INSTANCEDATA_T instDataC = TESTCASE_INSTANCEDATA_INIT; | ||
+ | |||
+ | // Set object ID if the machine needs to know which object it is | ||
+ | // E.g. which serial port to open ... | ||
+ | instDataA.inst_id=0; | ||
+ | instDataB.inst_id=1; | ||
+ | instDataC.inst_id=2; | ||
+ | |||
+ | // call " | ||
+ | testcase(& | ||
+ | | ||
+ | // call " | ||
+ | testcase(& | ||
+ | | ||
+ | // call " | ||
+ | testcase(& | ||
+ | |||
+ | </ | ||
+ | |||
+ | I think you agree that there is no magic in running multiple instances of the state handler. | ||
+ | |||
+ | ===== Provide an own Instance Structure ===== | ||
+ | Sometimes it makes sense to provide an own instance structure. In our example we want to store the baud rate, parity and other values relevant for each serial port. | ||
+ | |||
+ | So first define an own struct in a file called '' | ||
+ | |||
+ | <code c> | ||
+ | #ifndef __OWN_INST_TYPE__ | ||
+ | #define __OWN_INST_TYPE__ | ||
+ | |||
+ | typedef struct InstanceData MY_TESTCASE_INSTANCEDATA_T; | ||
+ | |||
+ | #include < | ||
+ | #include < | ||
+ | #include " | ||
+ | |||
+ | struct InstanceData{ | ||
+ | uint16_t baudrate; | ||
+ | uint8_t noBits; | ||
+ | uint8_t parity; | ||
+ | uint8_t stopBit; | ||
+ | TESTCASE_INSTANCEDATA_T instanceVar; | ||
+ | }; | ||
+ | |||
+ | #endif // __OWN_INST_TYPE__ | ||
+ | </ | ||
+ | |||
+ | Then tell the code generator to use this struct. Add the third line to the configuration file which then looks like this: | ||
+ | < | ||
+ | HsmFunctionWithInstanceParameters=YES | ||
+ | HsmFunctionWithEventParameter=YES | ||
+ | HsmFunctionUserDefinedParameter=MY_TESTCASE_INSTANCEDATA_T | ||
+ | </ | ||
+ | |||
+ | The generated state machine signature now looks as follows. The difference is that the own instance structure is now used instead of the generic one. | ||
+ | <code c> | ||
+ | void testcase(MY_TESTCASE_INSTANCEDATA_T* userInstanceVar, | ||
+ | </ | ||
+ | |||
+ | To use the newly defined instance type declare the instance variables now as follows: | ||
+ | |||
+ | <code c> | ||
+ | // init three different serial ports | ||
+ | MY_TESTCASE_INSTANCEDATA_T instDataA = {0, | ||
+ | MY_TESTCASE_INSTANCEDATA_T instDataB = {0, | ||
+ | MY_TESTCASE_INSTANCEDATA_T instDataC = {0, | ||
+ | |||
+ | // Set object ID if the machine needs to know which object it is | ||
+ | // E.g. which serial port to open ... | ||
+ | instDataA.instanceVar.inst_id=0; | ||
+ | instDataB.instanceVar.inst_id=1; | ||
+ | instDataC.instanceVar.inst_id=2; | ||
+ | |||
+ | // call " | ||
+ | testcase(& | ||
+ | |||
+ | </ | ||
+ | |||
+ | Now the state machine is ready to use the new private instance data inside the machine code. | ||
+ | |||
+ | ===== Putting all Things Together ===== | ||
+ | |||
+ | Coming back now to the example of three serial interfaces. The following figure shows a simplified state machine for handling a serial interface. The state machine is generic. Whether COM0 or COM1 or COM2 is processed is determined only from the content of the instance variable. And also other parameters are stored there and of course the local machine variables. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | I hope that the concepts how to run multiple state machines of the same type are clearer now. And also how to define an own instance structure that is necessary for more complex machines. | ||
+ | |||
+ | In case of any questions don't hesitate to contact me! | ||
+ | |||
+ | |||
+ | |||
+ | ~~DISCUSSION: |
wiki/news/10oct2013.1378755159.txt.gz · Last modified: 2013/09/09 21:32 by pmueller