?? flag0.c
字號:
break;
case 'R': // read
{
// only copy the data if it's valid, otherwise
// send a NAK to force a retransmit
if (!REG_VALID) {
xmit_nak (); // char timeout off, msg timeout restarts
break;
}
if (char_cnt != 0) {
char_cnt = min(char_cnt, MAX_CHAR_CNT);
data_cnt = (char_cnt + 1)/2;
if (address <= 0x7fff) {
// registers in xdata memory (CE, etc.)
// misbehaves with a zero length
memcpy_xce (
(int32x_t *)&data_buffer[0],
(int32x_t *)address,
((data_cnt + 3)/4));
} else if (address >= 0x8080 && address <= 0x80ff) {
uint8_t csfr;
address &= 0xff;
for(csfr = 0; csfr < data_cnt; ++csfr) {
SFR_Read (address + csfr, &t);
data_buffer[csfr] = t;
}
} else { // SFRs (ugh)
// registers in idata memory
address &= 0xff;
for(t = 0; t < data_cnt; ++t) {
data_buffer[t] = *(t + ((uint8i_t*)address));
}
}
}
state = STATE_XMIT_DATA;
msg_ptr = msg_data;
xmit(); // xmit msg, char timeout off, msg timeout starts
}
break;
case 'W': // write
{
// only copy the data if it's valid, otherwise
// send a NAK to force a retransmit
if (!REG_VALID) {
xmit_nak (); // char timeout off, msg timeout starts
break;
}
if (char_cnt != 0) {
char_cnt = min(char_cnt, MAX_CHAR_CNT);
data_cnt = (char_cnt + 1)/2;
// write the buffered data
if (address <= 0x7fff) {
uint8_t xdata *pDst;
uint8_t xdata *pSrc;
uint8_t cnt = data_cnt;
// variables to save interrupt state for a CE transfer
CE_XFER_DEFINES;
// save a snapshot of the state
CE_XFER_SAVE;
pDst = (uint8x_t*)address;
pSrc = (uint8x_t*)&data_buffer[0];
while (cnt != 0) {
BEGIN_CE_CRITICAL_SECTION; // Disable CE interrupts.
*((int8x_t *) pDst) = *((int8x_t *) pSrc);
++pDst;
++pSrc;
--cnt;
if (cnt != 0) {
*((int8x_t *) pDst) = *((int8x_t *) pSrc);
++pDst;
++pSrc;
--cnt;
}
if (cnt != 0)
{
*((int8x_t *) pDst) = *((int8x_t *) pSrc);
++pDst;
++pSrc;
--cnt;
}
if (cnt != 0)
{
CLK_STRETCH; // Change stretch to '6' equivalent.
*((int8x_t *) pDst) = *((int8x_t *) pSrc);
CLK_RELAX; // Back to default value.
++pDst;
++pSrc;
--cnt;
}
END_CE_CRITICAL_SECTION; // Reenable CE interrupts.
}
// transfer registers to hardware when convenient
REG_WRITE = TRUE; // not needed for SFRs
} else if (address >= 0x8080 && address <= 0x80ff) {
// SFRs (ugh)
uint8_t csfr;
address &= 0xff;
for(csfr = 0; csfr < data_cnt; ++csfr) {
SFR_Write (
address + csfr,
data_buffer[csfr],
ASSIGN);
}
} else {
// registers in idata memory
address &= 0xff;
for(t = 0; t < data_cnt; ++t) {
*(t + ((uint8d_t*)address)) = data_buffer[t];
}
} // end figure which addressing to use
} // data exists?
xmit_ack (); // char timeout off, msg timeout starts
}
break;
} // end switch on command in no-error case
break;
} // end switch on error, in command recv state
} // end respond to command
#pragma restore
static code const void (*flag_state_table[STATE_COUNT])(void) small reentrant =
{
sign_on, // STATE_XMIT_EMPTY_READOUT, After Y0 is sent
sign_on, // STATE_XMIT_BREAK, After setting the password (command P1) fails
get_cmd, // STATE_XMIT_ERR, After an err_msg is sent
send_id, // STATE_RCV_SIGN_ON, After a sign-on message sent
rcv_id_ack, // STATE_XMIT_ID, After id is sent, receive the ack
send_password, // STATE_RCV_ID_ACK, after receiving the ack of the ID
get_cmd, // STATE_XMIT_PASSWORD_OPERAND, after password data sent
get_cmd, // STATE_XMIT_DATA, after data is transmitted
get_cmd, // STATE_XMIT_NAK, after NAK is transmitted
do_cmd, // STATE_RCV_COMMAND, after a command is received, act on it
do_cmd_after_ack // STATE_XMIT_ACK; commands to do after sending ACK
}; // end flag state table
#pragma save
#pragma NOAREGS
// lookup and run the state machine's behavior in the state table
static void flag_state (void) small reentrant
{
msg_fld_index = 0;
log(1);
log(state);
if (state < STATE_LOWER_LIMIT || state > STATE_UPPER_LIMIT)
{
sign_on (); // default state, enables receive, turns off timeouts
}
else
{
(*flag_state_table[state])();
}
log(2);
}
#pragma restore
#pragma save
#pragma NOAREGS
// last field
static void end_in (void) small reentrant
{
--msg_fld_index; // stay in this field forever
}
#pragma restore
#pragma save
#pragma NOAREGS
// field Y- no baud rate negotiation in this version
static void y_in (void) small reentrant
{
if (cur_char != '1')
{
error = max ( error, PasswordBad );
log(0x85);
log(error);
}
}
#pragma restore
#pragma save
#pragma NOAREGS
// do nothing
static void do_nothing (void) small reentrant
{
}
#pragma restore
#pragma save
#pragma NOAREGS
// field C, a command
static void c_in (void) small reentrant
{
cmd = cur_char;
// only Break and Password commands work without authorization
if ((!authorized) && cur_char != 'B' && cur_char != 'P')
{
error = max ( error, AuthorizationBad );
log(0x86);
log(error);
}
}
#pragma restore
#pragma save
#pragma NOAREGS
// field D, a command
static void d_in (void) small reentrant
{
cmd_subtype = cur_char;
// search for a matching message template
for(t = MAX_MSG_INDEX; t > 0; --t) {
msg_ptr = msg_ptr_array[t];
if ( msg_ptr[CMD_FLD_INDEX] == cmd
&& msg_ptr[CMD_SUBTYPE_FLD_INDEX] == cmd_subtype ) {
break;
}
}
// if no message template is found, the search ends on the zeroth
// element of the array, which is an invalid default
if ( 1 > t || t > MAX_MSG_INDEX )
{
error = max ( error, CommandBad );
log(0x87);
log(error);
}
}
#pragma restore
#pragma save
#pragma NOAREGS
// field device address, ignore hexadecimal device address
static void device_address_in (void) small reentrant
{
if (msg_fld_next == cur_char) // look for the end of the field
++msg_fld_index; // skip field and ending character
else
--msg_fld_index; // stay in this field until the digits are done
}
#pragma restore
#pragma save
#pragma NOAREGS
// field data address,
static void data_address_in (void) small reentrant
{
--msg_fld_index; // stay in this field until the digits are done
if (cur_char >= '0' && cur_char <= '9') {
t = cur_char - '0';
} else if (cur_char >= 'A' && cur_char <= 'F') {
t = cur_char - ('A' - 10);
} else if (cur_char >= 'a' && cur_char <= 'f') {
t = cur_char - ('a' - 10);
} else {
// the next character was not hex
if (msg_fld_next != cur_char) { // look for the end of the field
error = max ( error, DataBad );
log(0x88);
log(error);
data_bit_index = 0;
}
// cope with the end of the field
msg_fld_index += 2; // digits done, next char checked
return;
}
// cope with a normal hex value
address = t + (address << 4);
}
#pragma restore
#pragma save
#pragma NOAREGS
// field data count,
static void data_count_in (void) small reentrant
{
--msg_fld_index; // stay in this field until the digits are done
if (cur_char >= '0' && cur_char <= '9') {
t = cur_char - '0';
} else if (cur_char >= 'A' && cur_char <= 'F') {
t = cur_char - ('A' - 10);
} else if (cur_char >= 'a' && cur_char <= 'f') {
t = cur_char - ('a' - 10);
} else {
// the next character was not hex
if (msg_fld_next != cur_char) { // look for the end of the field
error = max ( error, DataBad );
log(0x89);
log(error);
data_bit_index = 0;
}
if (char_cnt > MAX_CHAR_CNT) { // look for the end of the field
error = max ( error, DataBad );
log(0x8a);
log(error);
char_cnt = MAX_CHAR_CNT;
}
msg_fld_index += 2; // digits done, next char checked
return;
}
// cope with a normal hex value
char_cnt = t + (char_cnt << 4);
}
#pragma restore
#pragma save
#pragma NOAREGS
// field ,
static void hex_data_in (void) small reentrant
{
--msg_fld_index; // stay in this field until the digits are done
t = 0xff;
if (cur_char >= '0' && cur_char <= '9') {
t = cur_char - '0';
} else if (cur_char >= 'A' && cur_char <= 'F') {
t = cur_char - ('A' - 10);
} else if (cur_char >= 'a' && cur_char <= 'f') {
t = cur_char - ('a' - 10);
} else {
// the next character was not hex
if (msg_fld_next != cur_char) { // look for the end of the field
error = max ( error, DataBad );
log(0x8b);
log(error);
data_bit_index = 0;
}
// cope with the end of the field
if (data_bit_index != 0) {
error = max(error,DataBad);
log(0x8c);
log(error);
data_bit_index = 0;
}
msg_fld_index += 2; // digits done, next char checked
return;
}
// cope with a normal hex value
char_cnt += 1;
if (data_bit_index == 4) {
hex_byte = t | hex_byte;
data_bit_index = 0;
data_buffer[data_index++] = hex_byte;
if (data_index > MAX_DATA_INDEX)
data_index = MAX_DATA_INDEX;
} else {
hex_byte = t << 4;
data_bit_index = 4;
}
}
#pragma restore
#pragma save
#pragma NOAREGS
// field BEGIN_BCC, indicate the start of the data
// tested by the bcc (block check character)
static void begin_bcc_in (void) small reentrant
{
bcc = cur_char;
}
#pragma restore
#pragma save
#pragma NOAREGS
// field BCC, check the bcc (block check character)
static void bcc_in (void) small reentrant
{
if (bcc != 0)
{
error = max(error,ChecksumBad);
log(0x8d);
log(error);
}
}
#pragma restore
// start of logic that reads characters from an input port, and
// interprets them as a flag message
static code const void (* flag_in_state_table[MSG_FLD_COUNT])(void) small reentrant =
{
end_in, // END: last field- do not increment field pointer
do_nothing, // field z- baud rate negotiation
y_in, // field Y- baud rate negotiation
c_in, // field c- command
d_in, // field d- command subtype
device_address_in, // DEVICE_ADDRESS: ignore a hexadecimal device address
data_address_in, // DATA_ADDRESS: hexadecimal data address
data_count_in, // DATA_COUNT: hexadecimal data count
hex_data_in, // HEX_DATA: a string of bytes in hex.
begin_bcc_in, // BEGIN_BCC: start of data protected by a BCC.
bcc_in, // BCC: check the bcc (block check character).
do_nothing // ERROR: do nothing.
};
/* run a flag state machine for serial port input */
// This works by stepping through the current message template.
#pragma save
#pragma NOAREGS
#if PORT==0
void flag0_in (void) small reentrant
#endif
#if PORT==1
void flag1_in (void) small reentrant
#endif
{
log(3);
log(msg_fld_index);
cur_char = ser_rcv(); // receive a byte
bcc ^= cur_char; // calculate the bcc
// the hardware level state machine
if ( ser_rcv_err() ) {
error = ParityBad;
log(0x8e);
log(error);
ser_clr_err();
}
#if TIMERS
reset_char_timer ();
#endif
// the character level state machine
// It reads fields in message templates and interprets them.
// The message templates are selected by the
// protocol-level flag state machine.
do {
msg_fld = *(msg_ptr + msg_fld_index);
++msg_fld_index; // automatically step to the next field
msg_fld_next = *(msg_ptr + msg_fld_index );
// if it's not an executable field value
if (msg_fld < MSG_FLD_LOWER_LIMIT
|| msg_fld > MSG_FLD_UPPER_LIMIT)
{
// the input should be the same as the template
if (msg_fld != cur_char) {
if (msg_ptr == msg_P1) {
error = max(error,PasswordBad);
log(0x8f);
log(error);
} else {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -