📄 ser_test_protocol.inl
字号:
CYG_MACRO_END//----------------------------------------------------------------------------// Macros for read/write to serial with error cheking.static volatile cyg_uint32 r_stamp;static volatile int aborted;// This routine will be called if the read "times out"static voiddo_abort(void *handle){ cyg_io_handle_t io_handle = (cyg_io_handle_t)handle; cyg_int32 len = 1; // Need something here cyg_io_get_config(io_handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, 0, &len); aborted = 1;}#include "timeout.inl"// Read with timeout (__t = timeout in ticks, int* __r = result)#define Tcyg_io_read_timeout(__h, __d, __l, __t, __r) \ CYG_MACRO_START \ int __res; \ r_stamp = timeout((__t), do_abort, (__h)); \ __res = cyg_io_read((__h), (__d), (__l)); \ if (ENOERR != __res && -EINTR != __res) { \ TEST_CRASH(__h, TEST_CRASH_IO_READ, \ "cyg_io_read/timeout failed", __res); \ } \ *(__r) = __res; \ untimeout(r_stamp); \ CYG_MACRO_END#define Tcyg_io_read(__h, __d, __l) \ CYG_MACRO_START \ int __res = cyg_io_read((__h), (__d), (__l)); \ if (ENOERR != __res) { \ TEST_CRASH(__h, TEST_CRASH_IO_READ, \ "cyg_io_read failed", __res); \ } \ CYG_MACRO_END#define Tcyg_io_write(__h, __d, __l) \ CYG_MACRO_START \ int __res; \ cyg_uint32 __len = 1; \ __res = cyg_io_write((__h), (__d), (__l)); \ if (ENOERR != __res) { \ TEST_CRASH(__h, TEST_CRASH_IO_WRITE, \ "cyg_io_write failed", __res); \ } \ __res = cyg_io_get_config((__h), \ CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, \ 0, &__len); \ if (ENOERR != __res) { \ TEST_CRASH(__h, TEST_CRASH_IO_DRAIN, \ "DRAIN failed", __res); \ } \ CYG_MACRO_END//----------------------------------------------------------------------------// Some libc like functions that are handy to have around.static intstrlen(const char *c){ int l = 0; while (*c++) l++; return l;}static char*strcpy(char* dest, const char* src){ char c; while ((c = *src++)) { *dest++ = c; } *dest = c; return dest;}static char*itoa(char* dest, int v){ char b[16]; char* p = &b[16]; *--p = 0; if (v) { while (v){ *--p = (v % 10) + '0'; v = v / 10; } } else *--p = '0'; return strcpy(dest, p);}#define min(_a, _b) ((_a) < (_b)) ? (_a) : (_b)voidhang(void){ while (1);}//-----------------------------------------------------------------------------// 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>:<flow control code>!"// 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 parityintchange_config(cyg_io_handle_t handle, cyg_ser_cfg_t* cfg){ cyg_serial_info_t old_cfg, new_cfg; const char cmd[] = "@CONFIG:"; char reply[2]; int msglen; int res, len; cyg_uint8 *p1; // Prepare the command. p1 = &cmd_buffer[0]; p1 = strcpy(p1, &cmd[0]); p1 = itoa(p1, cfg->baud_rate); *p1++ = ':'; p1 = itoa(p1, cfg->data_bits); *p1++ = ':'; p1 = itoa(p1, cfg->stop_bits); *p1++ = ':'; p1 = itoa(p1, cfg->parity); *p1++ = ':'; p1 = itoa(p1, cfg->flags); *p1++ = '!'; *p1 = 0; // note: we may append to this later // Tell user what we're up to. CYG_TEST_INFO(&cmd_buffer[1]); // Change to new config and then back to determine if the driver likes it. len = sizeof(old_cfg); res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &old_cfg, &len); res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &new_cfg, &len); if (res != ENOERR) { TEST_CRASH(handle, TEST_CRASH_IO_GET_CFG, "Can't get serial config", res); } new_cfg.baud = cfg->baud_rate; new_cfg.word_length = cfg->data_bits; new_cfg.stop = cfg->stop_bits; new_cfg.parity = cfg->parity; new_cfg.flags = cfg->flags; res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_cfg, &len); cyg_thread_delay(10); // Some chips don't like changes to happen to fast... // Driver didn't like it. It will not have changed anything, so it's // safe to return now. if (ENOERR != res) { // Let user know that the config was skipped due to the target. const char txt_tskipped[] = "- skipped by target!"; p1 = strcpy(p1, txt_tskipped); *p1 = 0; CYG_TEST_INFO(&cmd_buffer[1]); return res; } // Succeeded. Change back to the original config so we can communicate // with the host. res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &old_cfg, &len); cyg_thread_delay(10); // Some chips don't like changes to happen to fast... if (res != ENOERR) { TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, "Can't set serial config", res); } // Send command to host and read host's reply. msglen = strlen(&cmd_buffer[0]); Tcyg_io_write(handle, &cmd_buffer[0], &msglen); msglen = 2; Tcyg_io_read(handle, &reply[0], &msglen); // Did host accept configuration? if ('O' != reply[0] || 'K' != reply[1]) { // Let user know that the config was skipped due to the host. const char txt_hskipped[] = "- skipped by host!"; p1 = strcpy(p1, txt_hskipped); *p1 = 0; CYG_TEST_INFO(&cmd_buffer[1]); diag_printf("Host didn't accept config (%02x, %02x).\n", reply[0], reply[1]); res = ENOSUPP; return res; } // Now change config and wait for host to send us a S(ync) // character. // Loop until protocol exchange completed. This may hang (as seen // from the host), but only when we get totally lost, in which // case there's not much else to do really. In this case the host // will consider the test a FAIL. len = sizeof(new_cfg); res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_cfg, &len); cyg_thread_delay(10); // Some chips don't like changes to happen to fast... if (res != ENOERR) { TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, "Can't set serial config/2", res); } { int change_succeeded = 0; int using_old_config = 0; char in_buf[1]; int len; int saw_host_sync; for (;;) { aborted = 0; // global abort flag // FIXME: Timeout time needs to be configurable, and needs to // be sent to the host before getting here. That would allow // changing the timeout by just rebuilding the test - without // changing the host software. saw_host_sync = 0; r_stamp = timeout(100, do_abort, handle); while(!aborted) { len = 1; in_buf[0] = 0; res = cyg_io_read(handle, in_buf, &len); if (ENOERR != res && -EINTR != res) { // We may have to reset the driver here if the fail // was due to a framing or parity error. break; } if ('R' == in_buf[0]) { // Resync - host didn't see our message. Try again. saw_host_sync = 0; } else if ('S' == in_buf[0] && !saw_host_sync) { // In sync - reply to host if we haven't already char ok_msg[2] = "OK"; int ok_len = 2; Tcyg_io_write(handle, ok_msg, &ok_len); saw_host_sync = 1; } else if ('D' == in_buf[0] && saw_host_sync) { // Done - exchange completed. change_succeeded = 1; break; } } untimeout(r_stamp); if (change_succeeded) { // If we had to revert to the old configuration, return error. if (using_old_config) return -EIO; else return ENOERR; } // We didn't synchronize with the host. Due to an IO error? if (ENOERR != res && -EINTR != res) { // We may have to reset the driver if the fail was due to // a framing or parity error. } // Revert to the old configuration and try again. len = sizeof(old_cfg); res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &old_cfg, &len); cyg_thread_delay(10); // Some chips don't like changes to happen to fast... if (res != ENOERR) { TEST_CRASH(handle, TEST_CRASH_IO_SET_CFG, "Can't set serial config/3", res); } using_old_config = 1; } }}//-----------------------------------------------------------------------------// Host sends CRC in decimal ASCII, terminated with !intread_host_crc(cyg_io_handle_t handle){ int crc, len; cyg_uint8 ch; crc = 0; while (1) { len = 1; Tcyg_io_read(handle, &ch, &len); if ('!' == ch) break; if (!((ch >= '0' && ch <= '9'))){ TEST_CRASH(handle, TEST_CRASH_CRC_CHAR, "Illegal CRC format from host", ch); } crc = crc*10 + (ch - '0'); } return crc;}//---------------------------------------------------------------------------// Test binary data transmission.// Format out:// "@BINARY:<byte size>:<mode>!"// Format in:// <checksum>!<#size bytes data>// For echo modes, also:// Format out:// <#size bytes data>// Format in:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -