📄 ecostestserialfilter.cpp
字号:
pSer.SetBaud(new_cfg->baud_rate, false);
pSer.SetParity(new_cfg->parity, false);
pSer.SetDataBits(new_cfg->data_bits, false);
pSer.SetXONXOFFFlowControl((new_cfg->flags&FLOW_XONXOFF_RX) != 0, false);
pSer.SetRTSCTSFlowControl((new_cfg->flags&FLOW_RTSCTS_RX) != 0, false);
pSer.SetDSRDTRFlowControl((new_cfg->flags&FLOW_DSRDTR_RX) != 0, false);
return pSer.SetStopBits(new_cfg->stop_bits, true); // apply settings
}
// Return false if the serial configuration is not valid for the host.
bool
CeCosTestSerialFilter::VerifyConfig(CeCosSerial &pSer, ser_cfg_t* new_cfg)
{
ser_cfg_t old_cfg;
bool rc;
// Try changing to the new config, recording the result. Then restore
// the original config.
rc = SetConfig(pSer, new_cfg, &old_cfg);
SetConfig(pSer, &old_cfg, NULL);
return rc;
}
//-----------------------------------------------------------------------------
// Configuration changing function.
//
// First change to the new config and back again to determine if the driver
// can handle the config.
// If not, return error.
//
// Then query the host for its capability to use the config:
// Format out:
// "@CONFIG:<baud rate code>:<#data bits>:<#stop bits>:<parity on/off>!"
// Format in:
// OK/ER
//
// On ER, return error.
//
// On OK, change to the new configuration. Resynchronize with the host:
// Target waits for host to send S(ync)
// [host will delay at least .1 secs after changing baud rate so the
// line has time to settle.]
//
// When receiving S(ync), target replies OK to the host which then
// acknowledges with D(one).
//
// Host can also send R(esync) which means it didn't receieve the OK. If
// so the target resends its S(ync) message.
//
// If the synchronization has not succeeded within 1 second
// (configurable in the protocol), both host and target will revert to
// the previous configuration and attempt to synchronize again. If
// this fails, this call will hang and the host will consider the test
// a failure.
//
// To Do:
// Host&protocol currently only supports:
// - no/even parity
void
CeCosTestSerialFilter::CMD_ChangeConfig(CeCosSerial &pSer, char* cfg_str)
{
ser_cfg_t new_cfg, old_cfg;
ParseConfig(cfg_str, &new_cfg);
// Return without changing the config if it's not valid.
if (!VerifyConfig(pSer, &new_cfg)) {
TargetASCIIWrite(pSer, "ER");
return;
}
// Tell target we're ready to go, wait 1/10 sec, and then change
// the config.
TargetASCIIWrite(pSer, "OK");
CeCosThreadUtils::Sleep(100);
SetConfig(pSer, &new_cfg, &old_cfg);
int loops;
for (loops = 0; loops < 3; loops++) {
unsigned int len, read;
unsigned char buffer[2];
int delay_mticks = 0; // millisecond-ticks. 10 of these per target tick
// Start by sending a Sync.
TargetASCIIWrite(pSer, "S");
for(;;) {
// Did target reply?
len = 2;
read = 0;
buffer[0] = 0;
buffer[1] = 0;
if (!pSer.Read((void*) buffer, len, read)) {
throw "CMD_ChangeConfig: serial read failure";
}
if (read) {
// If only one char read, try to get the next one.
if (1 == read) {
unsigned int read2 = 0;
len = 1;
if (!pSer.Read((void*) &buffer[1], len, read2)) {
throw "CMD_ChangeConfig: serial read failure";
}
read += read2;
}
if (m_bOptSerDebug)
PrintHex(buffer, read);
if ('O' == buffer[0] && 'K' == buffer[1]) {
// success!
TargetASCIIWrite(pSer, "D");
Trace("Config change succeeded.\n");
return;
} else {
// Garbage, ask target to resend its OK message.
TargetASCIIWrite(pSer, "R");
}
} else {
// Resend Sync message.
TargetASCIIWrite(pSer, "S");
}
CeCosThreadUtils::Sleep(1);
delay_mticks++;
// Timeout.
if (100 == delay_mticks/10)
break;
}
SetConfig(pSer, &old_cfg, NULL);
}
// Abort the test.
Log("FAIL:<target timed out>\n");
Trace("**** Timed out while changing config\n");
static const char kill_msg[] = "$X00#b8";
filter_abort_t* msg = new filter_abort_t();
msg->data_len = strlen(kill_msg);
msg->data_ptr = (const unsigned char *)kill_msg;
throw msg;
}
// Set default configuration.
void
CeCosTestSerialFilter::CMD_DefaultConfig(CeCosSerial &pSer)
{
static const ser_cfg_t default_ser_cfg = { 9600,
8,
CeCosSerial::ONE_STOP_BIT,
false };
TargetASCIIWrite(pSer, "OK");
SetConfig(pSer, &default_ser_cfg, NULL);
}
// Parse config string from target and set new_cfg accordingly.
// String from target is:
// <baud rate>:<data bits>:<stop bits>:<parity>:....
void
CeCosTestSerialFilter::ParseConfig(char* args, ser_cfg_t* new_cfg)
{
int ecos_parity, ecos_stop_bits, ecos_baud_rate, ecos_flags;
CeCosSerial::StopBitsType t2h_stop_bits[3] = {
CeCosSerial::ONE_STOP_BIT,
CeCosSerial::ONE_POINT_FIVE_STOP_BITS,
CeCosSerial::TWO_STOP_BITS};
INIT_VALUE(args);
SET_VALUE(int, ecos_baud_rate);
SET_VALUE(int, new_cfg->data_bits);
SET_VALUE(int, ecos_stop_bits);
SET_VALUE(int, ecos_parity);
SET_VALUE(int, ecos_flags);
new_cfg->parity = (ecos_parity != 0) ? true : false;
new_cfg->stop_bits = t2h_stop_bits[ecos_stop_bits - 1];
// flags is an optional field
if ( -1 == ecos_flags )
new_cfg->flags = FLOW_NONE;
else
new_cfg->flags = ecos_flags;
// eCos->human translation of serial baud rate. This table must
// match the one in io/serial/current/include/serialio.h
static const int tt_baud_rate[] = {
-1, // 0 invalid
50, // 1 50
75, // 2 75
110, // 3
135, // 4 134_5
150, // 5
200, // 6 200
300, // 7
600, // 8
1200, // 9
1800, // 10 1800
2400, // 11
3600, // 12 3600
4800, // 13
7200, // 14 7200
9600, // 15
14400, // 16 14400
19200, // 17
38400, // 18
57600, // 19
115200, // 20
234000 // 21 234000
};
if (ecos_baud_rate > 0 && ecos_baud_rate < (int) sizeof(tt_baud_rate))
ecos_baud_rate = tt_baud_rate[ecos_baud_rate];
else
ecos_baud_rate = -2;
new_cfg->baud_rate = ecos_baud_rate;
Trace("Parsed Config baud=%d, bParity=%d, stopbits=%d, databits=%d\n",
new_cfg->baud_rate, (int) new_cfg->parity, new_cfg->stop_bits,
new_cfg->data_bits);
Trace("Parsed Config xonxoff_rx=%d,tx=%d, rtscts_rx=%d,tx=%d, "
"dsrdtr_rx=%d,tx=%d\n",
(new_cfg->flags & FLOW_XONXOFF_RX) != 0,
(new_cfg->flags & FLOW_XONXOFF_TX) != 0,
(new_cfg->flags & FLOW_RTSCTS_RX) != 0,
(new_cfg->flags & FLOW_RTSCTS_TX) != 0,
(new_cfg->flags & FLOW_DSRDTR_RX) != 0,
(new_cfg->flags & FLOW_DSRDTR_TX) != 0);
}
// Always make sure CRC fits in 31 bits. Bit of a hack, but we want
// to send CRC as ASCII without too much hassle.
int
CeCosTestSerialFilter::DoCRC(unsigned char* data, int size)
{
int i;
unsigned long crc;
for (i = 0, crc = 0; i < size; i++) {
crc = (crc << 1) ^ data[i]; // FIXME: standard definition?
}
i = (int) crc;
if (i < 0)
i = -i;
return i;
}
void
CeCosTestSerialFilter::SendChecksum(CeCosSerial &pSer, int crc)
{
char buffer[128];
int len;
len = sprintf(buffer, "%d!", crc);
TargetWrite(pSer, (const unsigned char*)buffer, len);
}
void
CeCosTestSerialFilter::SendStatus(CeCosSerial &pSer, int state)
{
if (state)
TargetWrite(pSer, (unsigned char*) &msg_ok, 2);
else
TargetWrite(pSer, (unsigned char*) &msg_er, 2);
}
// Receive test DONE message from target.
void
CeCosTestSerialFilter::ReceiveDone(CeCosSerial &pSer,
unsigned char* data_in, int size)
{
static const char msg_done[] = "DONE";
unsigned char data_reply[4];
int first = 1;
TargetRead(pSer, data_reply, 4);
while (0 != strncmp((char*) data_reply, msg_done, 4)) {
if (first) {
if (data_in && size) {
Trace("Data received from target:\n");
PrintHex(data_in, size);
Trace("<end>\n");
}
Trace("Receiving junk instead of DONE:\n");
first = 0;
}
PrintHex(data_reply, 4);
data_reply[0] = data_reply[1];
data_reply[1] = data_reply[2];
data_reply[2] = data_reply[3];
// The TargetRead call will handle recovery in case of timeout...
TargetRead(pSer, &data_reply[3], 1);
}
}
//-----------------------------------------------------------------------------
// Test binary data transmission.
// Format in:
// <byte size>:<mode>
// Format out:
// <4 bytes binary checksum><#size bytes data>
// If echo mode, also:
// Format in:
// <#size bytes data>
// Format out:
// OK/ER - according to CRC match on incomin data
// Format in:
// DONE
//
// To Do:
// o Add mode/flag specifying 5-8 bit transfer.
// Test that 0xff gets masked off accordingly when transfered.
// (This should be an INFO result if failing)
// o Clean up the DUPLEX_ECHO implementation. Currently it's an ugly hack
// that doesn't match the arguments / behavior of the two other modes.
void
CeCosTestSerialFilter::CMD_TestBinary(CeCosSerial &pSer, char* args)
{
int size;
cyg_mode_t mode;
unsigned char *data_out, *data_in;
int i;
int crc;
int loop_count = 0;
INIT_VALUE(args);
SET_VALUE(int, size);
SET_VALUE(cyg_mode_t, mode);
// Change behavior for DUPLEX mode.
if (MODE_DUPLEX_ECHO == mode) {
loop_count = size;
size = 1024; // must be at least 4*block_size
}
// Generate data.
data_out = (unsigned char*) malloc(size);
if (!data_out) {
fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);
throw "data_out malloc failed";
}
data_in = (unsigned char*) malloc(size);
if (!data_in) {
fprintf(stderr, "Could not allocate %d byte buffer for data!\n", size);
throw "data_in malloc failed";
}
int count = 0;
for (i = 0; i < size; i++) {
// Output 255 chars, not 256 so that we aren't a multiple/factor of the
// likely buffer sizes in the system, this can mask problems as I've
// found to my cost!
unsigned char c = (unsigned char) (count++ % 255);
// don't allow $s and @s in the data, nor 0x03 (GDB C-c), nor flow
// control chars
if ('$' == c || '@' == c || 0x03 == c || 0x11 == c || 0x13 == c)
c = (unsigned char) '*';
data_out[i] = c;
}
// Do checksum.
crc = DoCRC(data_out, size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -