Vin*_*Ken 6 c memory enums state-machine fsm
我正在用 C 为微控制器编程,所以我不确定这个问题是属于这里还是属于电子堆栈交换。如果它不适合这里,请告诉我,我会将问题移到那里。
所以我在 C 中有有限状态机。这个 FSM 负责通过 UART 检索数据。每个状态检索一些数据并对其执行一些检查。每个状态都有三个可能的方向。如果接收到的数据有效,它将进入下一个状态。如果不是,它将重复其状态。如果该状态已重复一定次数,它将进入失败状态。为了说明这一点方向的状态返回代码:ok,err或repeat。这适用于除最后一个之外的所有状态。在这里调用时,return repeat我可以看到调试器转到该语句,然后最后检查它}函数,然后它转到内存中的随机位置,我只能在 Code Composer Studio 的反汇编视图中看到。有时这是 0x0 有时它是我看不到的 RAM 中的随机内存。
什么会导致这种奇怪的行为?我在 Code Composer Studio 中关闭了优化选项。
所有州都有这样的机构:
enum ret_codes fc_state(void) {
uint8_t buf[250];
static uint8_t fail_counter = 0;
const uint8_t max_tries = 5;
int ret = 0;
while (ret == 0) {
ret = UART_read(_uart, buf, sizeof(buf));
}
if (ret == UART_STATUS_ERROR) {
return err;
}
/*
perform tests on buf ...
*/
if (testFailed) {
fail_counter++;
if (fail_counter == max_tries) {
// Write DEN over UART ...
return err;
}
// write NACK over UART ...
return repeat; // I can see the debugger reaching this statement in the fc_state
}
// write ACK over UART ...
return ok;
} // When debugging the debugger goes here after 'return repeat' and to a random location in memory after this
// In the other states it goes back to the main loop described further below after 'return repeat'
Run Code Online (Sandbox Code Playgroud)
FSM 的代码如下所示:
enum state_codes { ipv, fup, fc, fail, succ, invalid };
enum ret_codes { ok, err, repeat };
struct transition {
enum state_codes src_state; // source state
enum ret_codes ret_code; // the code it returns
enum state_codes dst_state; // the state it should transfer to if the previous mentioned code was returned
};
enum ret_codes ipv_state(void);
enum ret_codes fup_state(void);
enum ret_codes fc_state(void);
enum ret_codes fail_state(void);
enum ret_codes succ_state(void);
enum ret_codes (* states[])(void) = {ipv_state, fup_state, fc_state, fail_state, succ_state};
struct transition transition_table[] = {
{ipv, ok, fup}, // when in the ipv state and ok is returned then go to fup state
{ipv, repeat, ipv}, // This repeat works
{ipv, err, fail},
{fup, ok, fc},
{fup, repeat, fup}, // This repeats works as well
{fup, err, fail},
{fc, ok, succ},
{fc, repeat, fc}, // This repeat fails for some reason
{fc, err, fail}
};
enum state_codes lookup_transitions(enum state_codes, enum ret_codes);
Run Code Online (Sandbox Code Playgroud)
这些状态的主循环如下所示:
while (1) {
state_fun = states[current_state];
return_code = state_fun();
if (current_state == fail) {
return 1;
}
if (current_state == succ) {
return 0;
}
current_state = lookup_transitions(current_state, return_code);
if (current_state == invalid) {
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我在下面添加了 lookup_transitions 表。顺便说一下,FSM 的这个实现取自/sf/answers/96015811/。该代码是为德州仪器 (TI) 的 CC2652R 和 Arm Cortex-M4F CPU 编写的。
enum state_codes lookup_transitions(enum state_codes cur_state, enum ret_codes rc) {
uint8_t i;
for (i = 0; i < sizeof(transition_table); i++) {
if (cur_state == transition_table[i].src_state && rc == transition_table[i].ret_code)
return transition_table[i].dst_state;
}
return invalid; // the transition table is not configured correctly
}
Run Code Online (Sandbox Code Playgroud)
这是 Code Composer Studio 反汇编查看器为 fc_state 显示的内容:
505 enum ret_codes fc_state(void) {
fc_state():
000529a0: B500 push {r14}
000529a2: F1AD0D3C sub.w r13, r13, #0x3c
512 const uint8_t max_tries = 5;
000529a6: 2005 movs r0, #5
000529a8: F88D003B strb.w r0, [r13, #0x3b]
514 int ret = 0;
000529ac: 2000 movs r0, #0
000529ae: 9000 str r0, [r13]
515 while (ret == 0) {
000529b0: 9800 ldr r0, [r13]
000529b2: B948 cbnz r0, #0x529c8
516 ret = UART_read(_uart, &rheader, sizeof(rheader));
$C$L62:
000529b4: 4829 ldr r0, [pc, #0xa4]
000529b6: 6800 ldr r0, [r0]
000529b8: A901 add r1, r13, #4
000529ba: 222B movs r2, #0x2b
000529bc: F003FFC6 bl UART_read
000529c0: 9000 str r0, [r13]
515 while (ret == 0) {
000529c2: 9800 ldr r0, [r13]
000529c4: 2800 cmp r0, #0
000529c6: D0F5 beq $C$L62
518 if (ret == UART_STATUS_ERROR) {
$C$L63:
000529c8: 9800 ldr r0, [r13]
000529ca: F1B03FFF cmp.w r0, #-1
000529ce: D101 bne $C$L64
519 return err;
000529d0: 2001 movs r0, #1
000529d2: E040 b $C$L70
522 ret = 0;
$C$L64:
000529d4: 2000 movs r0, #0
000529d6: 9000 str r0, [r13]
523 while (ret == 0) {
000529d8: 9800 ldr r0, [r13]
000529da: B958 cbnz r0, #0x529f4
524 ret = UART_read(_uart, &last_fup_info, rheader.length);
$C$L65:
000529dc: 481F ldr r0, [pc, #0x7c]
000529de: F8BD202D ldrh.w r2, [r13, #0x2d]
000529e2: 6800 ldr r0, [r0]
000529e4: F10D012F add.w r1, r13, #0x2f
000529e8: F003FFB0 bl UART_read
000529ec: 9000 str r0, [r13]
523 while (ret == 0) {
000529ee: 9800 ldr r0, [r13]
000529f0: 2800 cmp r0, #0
000529f2: D0F3 beq $C$L65
526 if (ret == UART_STATUS_ERROR) {
$C$L66:
000529f4: 9800 ldr r0, [r13]
000529f6: F1B03FFF cmp.w r0, #-1
000529fa: D101 bne $C$L67
527 return err;
000529fc: 2001 movs r0, #1
000529fe: E02A b $C$L70
530 if (
$C$L67:
00052a00: 4817 ldr r0, [pc, #0x5c]
00052a02: F8DD1037 ldr.w r1, [r13, #0x37]
00052a06: 6800 ldr r0, [r0]
00052a08: 4288 cmp r0, r1
00052a0a: D115 bne $C$L68
00052a0c: 4815 ldr r0, [pc, #0x54]
00052a0e: F8DD1037 ldr.w r1, [r13, #0x37]
00052a12: 6800 ldr r0, [r0]
00052a14: 4288 cmp r0, r1
00052a16: D10F bne $C$L68
00052a18: 4813 ldr r0, [pc, #0x4c]
00052a1a: F8DD1033 ldr.w r1, [r13, #0x33]
00052a1e: 6800 ldr r0, [r0]
00052a20: 4288 cmp r0, r1
00052a22: D109 bne $C$L68
00052a24: 4811 ldr r0, [pc, #0x44]
00052a26: F8DD1033 ldr.w r1, [r13, #0x33]
00052a2a: 6800 ldr r0, [r0]
00052a2c: 4288 cmp r0, r1
00052a2e: D103 bne $C$L68
535 UPDATEMNGR_writeAck();
00052a30: F001F834 bl UPDATEMNGR_writeAck
536 return ok;
00052a34: 2000 movs r0, #0
00052a36: E00E b $C$L70
539 fail_counter++;
$C$L68:
00052a38: 490D ldr r1, [pc, #0x34]
00052a3a: 7808 ldrb r0, [r1]
00052a3c: 1C40 adds r0, r0, #1
00052a3e: 7008 strb r0, [r1]
540 if (fail_counter != max_tries) {
00052a40: 480B ldr r0, [pc, #0x2c]
00052a42: 7800 ldrb r0, [r0]
00052a44: 2805 cmp r0, #5
00052a46: D003 beq $C$L69
541 UPDATEMNGR_writeNAck();
00052a48: F001F8BC bl UPDATEMNGR_writeNAck
542 return repeat;
00052a4c: 2002 movs r0, #2
00052a4e: E002 b $C$L70
544 UPDATEMNGR_writeDen();
$C$L69:
00052a50: F001F86E bl UPDATEMNGR_writeDen
545 return err;
00052a54: 2001 movs r0, #1
546 }
$C$L70:
00052a56: B00F add r13, #0x3c
00052a58: BD00 pop {pc}
00052a5a: 46C0 mov r8, r8
Run Code Online (Sandbox Code Playgroud)