IoT Supervisor 0.0
Loading...
Searching...
No Matches
IoT Supervisor_main.c
Go to the documentation of this file.
1
14//-----------------------------------------------------------------------------
15// Includes
16//-----------------------------------------------------------------------------
17#include <hardware.h>
18#include <SI_EFM8BB1_Register_Enums.h> // SFR declarations
19#include "InitDevice.h"
20#include "IoT_Supervisor.h"
21#include "ModbusMiddleWare.h"
22#include "PetitModbus.h"
24// $[Generated Includes]
25// [Generated Includes]$
30
39{
40 // $[SiLabs Startup]
41 // [SiLabs Startup]$
42}
43
44//-----------------------------------------------------------------------------
45// Global Variables
46//-----------------------------------------------------------------------------
47volatile sv_dev_sta_t sv_dev_sta = {0};
48
49// controls the main loop
50volatile t1Count_t t1Count = 0;
51
52// used in the timer 0 loop
53volatile uint8_t t0Count = 0;
55uint8_t T0C_TOP = 0;
56
57
100#define HB_DIV (9u) // approximately once a second, actually less
101 // must be at least two, but it probably won't look good
102 // at two...
103#define HB_DUTYCYCLE (32u) // select zero here to bypass the dutycycle gen
104#define HB_SKIP (3u) // number of heartbeat cycles to skip between blinks
105#define FAST_BLINK (9u) // one second
106#define SLOW_BLINK (FAST_BLINK + 2u)
107
108bool sys_ok = true;
109bool configuring = false;
110uint8_t hbdCount = 0; // heartbeat dutycycle counter
111uint8_t hbsCount = 0; // heartbeat skip counter
112
113void blinker(void)
114{
115 // sys ok is heart beat
116 if (sys_ok == true && configuring == false)
117 {
118 // one: determine heart beat
119 // t1Count & (1 << HB_DIV)
120 bool hb_slow = (t1Count & (1 << HB_DIV)) != 0;
121 bool hb_fast = (t1Count & (1 << HB_DIV - 2)) != 0;
122 // heart beat slow _ rising edge
123 bool hbs_re = (t1Count & ((1 << HB_DIV + 1) - 1)) == (1 << HB_DIV);
124 // heart beat fast _ rising edge
125 bool hbf_re = (t1Count & ((1 << HB_DIV - 1) - 1)) == (1 << HB_DIV - 2);
126 bool hb_internal = hb_fast && hb_slow;
127 if (hbs_re == true && hbsCount < HB_SKIP)
128 {
129 hbsCount++;
130 }
131 else if (hbs_re == true)
132 {
133 hbsCount = 0;
134 }
135 // compute heartbeat skip
136 hb_internal = hb_internal && (hbsCount == 0);
137
138 // two: LED duty cycle limiter
139 if (hb_internal == true && hbf_re == true)
140 {
141 hbdCount = 1;
142 nPWR_LED = 0;
143 }
144
145 // if the selected dutycycle is 0, base this part
146 // off of the heatbeat generated before
148 {
149 hbdCount++;
150 }
151 else if (HB_DUTYCYCLE > 0u || hb_internal == false)
152 {
153 nPWR_LED = 1;
154 }
155 }
156 // sys not ok is short blink
157 else if (configuring == false) // sys_ok == false
158 {
159 nPWR_LED = !(t1Count & (1 << FAST_BLINK));
160 }
161 // configuring is long blink
162 else // configuring == true
163 {
164 nPWR_LED = !((t1Count & (1 << SLOW_BLINK)));
165 }
166}
169
185// == outputs ==
186bool nReset = false; // inverse logic
187bool modbusWdtSmEn = false;
188// == inputs ==
189// comparator input flag
190bool cprif = false; // set outside, cleared here
191// modbus watchdog expired
192bool modbusWdtExp = false; // set outside, cleared in this SM
193
194// == constants ==
195#define SCOUNTER_ONE_SECOND (125)
196// 125 for one second
204void VinSm(void)
205{
206 // static variables
207 static uint8_t sCounter = 0;
208
209 // determine input state
210 bool VinCmp = VIN_CMP_CPOUT();
211
212 // default output states
213 nReset = false;
214 modbusWdtSmEn = false;
215
216 // transitions
217 switch (sv_dev_sta.v.vinSmS)
218 {
219 case eVIN_Init:
220 if (cprif == true || VinCmp == true)
221 {
223 }
224 else if (sCounter >= SCOUNTER_ONE_SECOND * 2 - 1)
225 {
227 }
228 break;
229 case eVIN_VLow:
230 if (VinCmp == false)
231 {
233 }
234 break;
235 case eVIN_OK:
236 if (cprif == true || VinCmp == true)
237 {
240 }
241 else if (modbusWdtExp == true)
242 {
245 }
246 break;
247 default:
249 break;
250 }
251
252 // outputs
253 switch (sv_dev_sta.v.vinSmS)
254 {
255 case eVIN_Init:
256 sCounter++;
257 modbusWdtExp = false;
258 break;
259 case eVIN_VLow:
260 sCounter = 0;
261 sys_ok = false;
262 break;
263 case eVIN_OK:
264 nReset = true;
265 modbusWdtSmEn = true;
266 sCounter = 0;
267 break;
268 }
269
270 // output signals
271 RESET_P = nReset;
273
274 // reset flags
275 cprif = false;
276}
// section Voltage State Machine
278
294#define C_DEFAULT_MB_WD_TIMEOUT (15)
296#define C_MB_WD_COUNT2MIN (7500)
297
299bool mbWDTen = false;
300bool mbWDTpet = false;
301
308void mbWDTsm(void)
309{
310 // statics
311 static uint16_t mbWDTc = 0; // modbus watchdog timer counter
312 static uint16_t mbWDTcM = 0; // modbus watchdog timer counter (minute)
313
314 // transitions
315 switch (sv_dev_sta.v.wdtSmS)
316 {
317 case eMW_Ini:
318 if (mbWDTen && modbusWdtSmEn)
320 break;
321 case eMW_En:
322 if (!mbWDTen || mbWDTpet)
324 if (mbWDTcM >= MB_WD_TIMEOUT)
326 break;
327 case eMW_Timeout:
329 break;
330 default:
332 break;
333 }
334
335 // output
336 switch (sv_dev_sta.v.wdtSmS)
337 {
338 case eMW_Ini:
339 mbWDTc = 0;
340 mbWDTcM = 0;
341 break;
342 case eMW_En:
343 mbWDTc++;
344 if (mbWDTc >= C_MB_WD_COUNT2MIN)
345 {
346 mbWDTcM++;
347 mbWDTc = 0;
348 }
349 break;
350 case eMW_Timeout:
351 mbWDTen = false;
352 modbusWdtExp = true;
353 break;
354 }
355
356 // inverse logic
358
359 mbWDTpet = false;
360}
// section Modbus WDT State Machine
362
382#define C_FLASH_CONF (0x1E00)
384#define pFLASH_CONF ((uint8_t code*)C_FLASH_CONF)
389#define C_PW_DEFAULT (0xDEFA)
390// manually determined program memory end.
391#if defined(DEBUG) && DEBUG
396#define C_FOUND_PROG_END (0x101F) // end of program memory to check (exclusive)
397#else
398#define C_FOUND_PROG_END (0x12A9) // determine me
399#endif
400
401// configuration variables
408code const uint8_t ex_cfg_header[] =
409{
410 'M','A','G', // Makers, Artists, and Gadgeteers Laboratory
411 'S','V', // IoT Supervisor
412 '0', // sw major
413 '0', // sw minor
414 '0' // header version
415};
417#define C_CFG_HEADER_LEN (sizeof(ex_cfg_header))
424code const cfg_t default_cfg =
425{
426 255, // sid, the default is 255
427 eMMW_B_38400, // baud
428 C_DEFAULT_MB_WD_TIMEOUT, // fifteen minutes
430};
436#define C_CFG_DATA_LEN (sizeof(cfg_t))
438#define C_CFG_C_CRC_LEN (2)
440#define C_CFG_P_CRC_LEN (2)
444#define C_CFG_DATA_END (C_CFG_HEADER_LEN + C_CFG_DATA_LEN)
448#define C_CFG_C_CRC_END (C_CFG_DATA_END + C_CFG_C_CRC_LEN)
453#define C_CFG_P_CRC_END (C_CFG_C_CRC_END + C_CFG_P_CRC_LEN)
454
456bool pw_flag = false;
457bool dir_tx = false;
458bool run_petitmodbus = false;
459uint16_t pw;
461uint8_t cfg_write_idx = 0;
462uint16_t calc_cfg_crc = 0xFFFF;
463uint16_t calc_prog_crc = 0xFFFF;
464
472bool ccfg_check(void)
473{
474 uint8_t i = 0;
475 calc_cfg_crc = 0xFFFF;
476 // check header
477 for (i = 0; i < C_CFG_HEADER_LEN; i++)
478 {
479 if (*(pFLASH_CONF + i) != ex_cfg_header[i])
480 {
482 return false;
483 }
485 }
486
487 // check contents
488 // modbus SID
490 if(i < C_SID_MIN || i > C_SID_MAX)
491 {
493 return false;
494 }
495 else
496 {
497 cfg.sid = i;
499 }
500 // modbus baud config
501 i = *(pFLASH_CONF + C_CFG_HEADER_LEN + 1);
502 if (i == 0 || i >= eMMW_B_NUM)
503 {
505 return false;
506 }
507 else
508 {
509 cfg.baud = i;
511 }
512 // modbus WD timeout
513 i = *(pFLASH_CONF + C_CFG_HEADER_LEN + 2);
514 if (i == 0)
515 {
517 return false;
518 }
519 else
520 {
521 cfg.wdto = i;
523 }
524 // password
525 i = *(pFLASH_CONF + C_CFG_HEADER_LEN + 3);
526 cfg.pw = i;
528 i = *(pFLASH_CONF + C_CFG_HEADER_LEN + 4);
529 cfg.pw |= (uint16_t)i << 8;
531 if (cfg.pw == C_CMD_COMMIT || cfg.pw == C_CMD_CANCEL)
532 {
534 return false;
535 }
536 // check CFG CRC
538 if ((calc_cfg_crc & 0xFF) != i)
539 {
541 return false;
542 }
543 else
544 {
545 i = *(pFLASH_CONF + C_CFG_DATA_END + 1);
546 if (calc_cfg_crc >> 8 != i)
547 {
549 return false;
550 }
551 }
552 return true;
553}
554
562{
563 // check SID
564 if (cfg.sid < C_SID_MIN || cfg.sid > C_SID_MAX)
565 {
566 return false;
567 }
568 // check baud enum (no parity)
569 if (cfg.baud < 1 || cfg.baud >= eMMW_B_NUM)
570 {
571 return false;
572 }
573 // check wdt timeout
574 if (cfg.wdto < 1)
575 {
576 return false;
577 }
578 // check password
579 if (cfg.pw == C_CMD_COMMIT || cfg.pw == C_CMD_CANCEL)
580 {
581 return false;
582 }
583 return true;
584}
585
586
603{
604 uint8_t code* addr;
605 uint8_t i = 0;
606 bool cfg_ok = true;
607
608 cfg_ok = ccfg_check();
609
610 // calculate PROG CRC
611 // this is set to run even if the CRC is not checked in order to ensure
612 // a valid startup time for debugging is achieved
613 calc_prog_crc = 0xFFFF;
614 for (addr = 0; addr < C_FOUND_PROG_END; addr++)
615 {
617 }
618
619 // check PROG CRC
621 {
623 // check low byte
624 if ((calc_prog_crc & 0xFF) != i)
625 {
627 sys_ok = false;
628 }
629 else
630 {
631 // check high byte
632 i = *(pFLASH_CONF + C_CFG_C_CRC_END + 1);
633 if (calc_prog_crc >> 8 != i)
634 {
636 sys_ok = false;
637 }
638 }
639 }
640
641 if (cfg_ok == false)
642 {
643 // load the default configuration structure
648 sys_ok = false;
649 }
650
651 // apply configuration structure
654
656}
657
663void cfg_write(void)
664{
665 calc_cfg_crc = 0xFFFF;
667 {
671 }
672 // sid
675 // baud
678 // wdt top
681 // pw
686 // cfg crc
689 // prog crc
692
693 // reset to complete
694 RSTSRC |= RSTSRC_SWRSF__SET;
695 // uh, set the state machine to idle in case we have not reset
697}
698
711void CFGsm()
712{
713 // transitions
714 switch (cfgSmS)
715 {
716 case eCFG_Load:
717 // transitions handled in-function
718 break;
719 case eCFG_Idle:
720 if (pw_flag)
721 {
722 if (pw == cfg.pw)
723 {
725 configuring = true;
726 }
727 pw_flag = false;
728 }
729 break;
730 case eCFG_Cache:
731 if (pw_flag && Petit_RxTx_State == PETIT_RXTX_RX && dir_tx == false)
732 {
733 if (pw == C_CMD_COMMIT)
734 {
735 if (dcfg_check())
736 {
740 }
741 }
742 if (pw == C_CMD_CANCEL)
743 {
746 configuring = false;
747 }
748 pw_flag = false;
749 }
750 break;
751 case eCFG_Commit:
752 if (pw_flag && Petit_RxTx_State == PETIT_RXTX_RX && dir_tx == false)
753 {
754 if (pw == cfg.pw)
755 {
757 }
758 if (pw == C_CMD_CANCEL)
759 {
761 configuring = false;
762 }
763 pw_flag = false;
764 }
765 break;
766 case eCFG_Erase:
768 break;
769 case eCFG_Write:
770 // transitions handled in function
771 break;
772 default:
774 break;
775 }
776
777 // outputs
778 switch (cfgSmS)
779 {
780 case eCFG_Load:
781 cfg_load();
782 run_petitmodbus = false;
783 break;
784 case eCFG_Idle:
785 run_petitmodbus = true;
786 break;
787 case eCFG_Cache:
788 run_petitmodbus = true;
789 mbWDTen = false;
790 // the magic in processing actually happens in the modbus rx function
791 break;
792 case eCFG_Commit:
793 run_petitmodbus = true;
794 // functionality implemented in the transitions, believe it or not
795 break;
796 case eCFG_Erase:
797 run_petitmodbus = false;
799 break;
800 case eCFG_Write:
801 run_petitmodbus = false;
802 cfg_write();
803 break;
804 }
805}
// section Configuration State Machine
807
808
831int main(void)
832{
833 static t1Count_t t1CountLast = 0;
834 // reset handling code
835 // skip startup reset if a software reset was called
836 if ((RSTSRC & RSTSRC_SWRSF__BMASK) == RSTSRC_SWRSF__SET)
837 {
839 }
840 // Call hardware initialization routine
842#if defined(DEBUG) && DEBUG
843 // enter debugmode to get the pins working
844 enter_DebugMode_from_DefaultMode();
845#endif
846 while (1)
847 {
848 // apparently, casting this to unsigned is necessary
849 if (t1Count - t1CountLast >= 1u)
850 {
852 CFGsm();
853 blinker();
854 if (run_petitmodbus)
855 {
856 t1CountLast++;
857 ProcessPetitModbus();
858 }
859 else
860 {
861 t1CountLast = t1Count;
862 }
864 }
865
866 // idle mode taken out because of some race condition that keeps
867 // being reached.
868
869 // $[Generated Run-time code]
870 // [Generated Run-time code]$
871 }
872 // this return should never be reached
873}
// group Main_Application
void FLASH_ByteWrite(FLADDR addr, uint8_t byte)
void FLASH_PageErase(FLADDR addr)
void enter_DefaultMode_from_RESET(void)
Definition InitDevice.c:25
#define t1Count_t
void KirisakiCRC16Calc(uint8_t Data, uint16_t *CRC)
#define HB_DUTYCYCLE
#define HB_SKIP
bool configuring
bool sys_ok
#define HB_DIV
void blinker(void)
#define SLOW_BLINK
#define FAST_BLINK
uint8_t hbdCount
uint8_t hbsCount
#define C_SID_MAX
bool pw_flag
#define C_PW_DEFAULT
cfg_t cfg
#define C_CFG_C_CRC_END
uint16_t pw
uint16_t calc_prog_crc
#define C_FOUND_PROG_END
CfgSM_t
uint16_t calc_cfg_crc
#define C_CMD_COMMIT
code const cfg_t default_cfg
#define C_SID_MIN
#define C_CFG_HEADER_LEN
#define C_CMD_CANCEL
bool dir_tx
code const uint8_t ex_cfg_header[]
CfgSM_t cfgSmS
bool run_petitmodbus
bool dcfg_check()
#define C_FLASH_CONF
void cfg_load()
uint8_t cfg_write_idx
void CFGsm()
#define pFLASH_CONF
#define C_CFG_DATA_END
bool ccfg_check(void)
void cfg_write(void)
@ eCFG_Cache
New Configuration is Caching from Modbus.
@ eCFG_Load
Configuration Loading from memory.
@ eCFG_Commit
New Configuration is Committed (Active)
@ eCFG_Idle
Idle State. No configuration state machine activity.
@ eCFG_Write
Write the new Configuration (into Flash)
@ eCFG_Erase
Erase the old Configuration (from Flash)
@ eVS_Cfg
Configuration Error or CRC Mismatch Detected.
@ eVS_Prog
Program Memory Mismatch Detected.
@ eVS_Setup
Initial Setup.
uint8_t T0C_TOP
void SiLabs_Startup(void)
SiLabs_Startup() Routine.
volatile t1Count_t t1Count
volatile sv_dev_sta_t sv_dev_sta
int main(void)
volatile uint8_t t0Count
@ eLR_WDT
The modbus watchdog timer caused the last reset.
@ eLR_VSM
A low voltage condition caused the last reset.
void mmw_init(uint8_t sid, uint8_t baud)
@ eMMW_B_38400
@ eMMW_B_NUM
void mbWDTsm(void)
bool mbWDTpet
#define C_DEFAULT_MB_WD_TIMEOUT
uint8_t MB_WD_TIMEOUT
bool mbWDTen
#define C_MB_WD_COUNT2MIN
@ eMW_Ini
Initial State.
@ eMW_Timeout
Timeout State. This watchdog bites!
@ eMW_En
Enable State.
bool modbusWdtSmEn
bool nReset
bool cprif
bool modbusWdtExp
void VinSm(void)
#define SCOUNTER_ONE_SECOND
@ eVIN_Init
@ eVIN_VLow
Voltage Low State.
@ eVIN_OK
Voltage in and Reset State Machine OK.
#define PETIT_PROCESS_OFF()
Definition hardware.h:97
#define RESET_LED_SET(nSTATE)
Definition hardware.h:98
#define VIN_CMP_CPOUT()
Definition hardware.h:52
#define PETIT_PROCESS_ON()
Definition hardware.h:96
#define WDT_LED_SET(nSTATE)
Definition hardware.h:99
#define RESET_P
Definition hardware.h:48
This struct is a storage type for flash memory.
uint16_t pw
uint8_t sid
uint8_t wdto
uint8_t baud
VerifSt_t verifSt
mbWDTsmS_t wdtSmS
LastRst_t lastRstS
struct sv_dev_sta_t::@0 v