📄 ecostestserialfilter.cpp
字号:
//------------------------// Configuration Command.// Set serial configuration.boolCeCosTestSerialFilter::SetConfig(CeCosTestSerial &pSer, const ser_cfg_t* new_cfg, ser_cfg_t* old_cfg){ if (old_cfg) { old_cfg->baud_rate = pSer.GetBaud(); old_cfg->parity = (0 != pSer.GetParity()) ? true : false; old_cfg->data_bits = pSer.GetDataBits(); old_cfg->stop_bits = pSer.GetStopBits(); } pSer.SetBaud(new_cfg->baud_rate, false); pSer.SetParity(new_cfg->parity, false); pSer.SetDataBits(new_cfg->data_bits, false); return pSer.SetStopBits(new_cfg->stop_bits, true); // apply settings}// Return false if the serial configuration is not valid for the host.boolCeCosTestSerialFilter::VerifyConfig(CeCosTestSerial &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 parityvoidCeCosTestSerialFilter::CMD_ChangeConfig(CeCosTestSerial &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"); 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"); } 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.voidCeCosTestSerialFilter::CMD_DefaultConfig(CeCosTestSerial &pSer){ static const ser_cfg_t default_ser_cfg = { 9600, 8, CeCosTestSerial::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>:....voidCeCosTestSerialFilter::ParseConfig(char* args, ser_cfg_t* new_cfg){ int ecos_parity, ecos_stop_bits, ecos_baud_rate; CeCosTestSerial::StopBitsType t2h_stop_bits[3] = { CeCosTestSerial::ONE_STOP_BIT, CeCosTestSerial::ONE_POINT_FIVE_STOP_BITS, CeCosTestSerial::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); new_cfg->parity = (ecos_parity != 0) ? true : false; new_cfg->stop_bits = t2h_stop_bits[ecos_stop_bits - 1]; // 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);}// Always make sure CRC fits in 31 bits. Bit of a hack, but we want// to send CRC as ASCII without too much hassle.intCeCosTestSerialFilter::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;}voidCeCosTestSerialFilter::SendChecksum(CeCosTestSerial &pSer, int crc){ char buffer[128]; int len; len = sprintf(buffer, "%d!", crc); TargetWrite(pSer, (const unsigned char*)buffer, len);}voidCeCosTestSerialFilter::SendStatus(CeCosTestSerial &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.voidCeCosTestSerialFilter::ReceiveDone(CeCosTestSerial &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.voidCeCosTestSerialFilter::CMD_TestBinary(CeCosTestSerial &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"; } for (i = 0; i < size; i++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -