static Cyg_ErrNo termios_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len) { cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)t->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; cyg_int32 xbufsize, input_bytes_read; cyg_uint8 xbuf[WRITE_BUFSIZE]; cyg_uint8 *buf = (cyg_uint8 *)_buf; Cyg_ErrNo res; xbufsize = input_bytes_read = 0; while (input_bytes_read++ < *len) { if ( (*buf == '\n') && (priv->termios.c_oflag & (OPOST|ONLCR)) ) { xbuf[xbufsize++] = '\r'; } xbuf[xbufsize++] = *buf; if ((xbufsize >= (WRITE_BUFSIZE-1)) || (input_bytes_read == *len) || (*buf == '\n')) { cyg_int32 size = xbufsize; res = cyg_io_write(chan, xbuf, &size); if (res != ENOERR) { *len = input_bytes_read - (xbufsize - size); return res; } xbufsize = 0; } buf++; } // Everything sent, so *len is correct. return ENOERR; }
static Cyg_ErrNo termios_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len) { cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)t->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; cyg_int32 size, bytes_successful, actually_written; cyg_uint8 xbuf[WRITE_BUFSIZE]; cyg_uint8 *buf = (cyg_uint8 *)_buf; Cyg_ErrNo res; size = 0; bytes_successful = 0; actually_written = 0; while (bytes_successful++ < *len) { xbuf[size] = *buf++; if ( (xbuf[size] == '\n') && (priv->termios.c_oflag & ONLCR) ) { xbuf[size] = '\r'; } size++; if ((size == (WRITE_BUFSIZE-1)) || (bytes_successful == *len)) { res = cyg_io_write(chan, xbuf, &size); if (res != ENOERR) { *len = actually_written; return res; } actually_written += size; size = 0; } } *len = actually_written; return ENOERR; }
//=========================================================================== // Thread 1 //=========================================================================== void can_tx_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_message tx_msg; cyg_uint32 msg_cnt = 0; cyg_uint8 i; CYG_CAN_MSG_SET_PARAM(tx_msg, 0, CYGNUM_CAN_ID_STD, 0, CYGNUM_CAN_FRAME_DATA); // // Prepare CAN message with a known CAN state // for (i = 0; i < 8; ++i) { tx_msg.data.bytes[i] = i; } while (msg_cnt < 0xF0) { tx_msg.id = msg_cnt; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN_Tbl[0], &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing to channel 0"); } tx_msg.id = msg_cnt; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hLoopCAN_Tbl[0], &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing to channel 1"); } // // Increment data in each single data byte // for (i = 0; i < 8; ++i) { tx_msg.data.bytes[i] += 1; } msg_cnt++; tx_msg.dlc = (tx_msg.dlc + 1) % 9; } // while (msg_cnt < 0x100) }
/* * Sends a single character to the serial device. */ void sio_send(u8_t c, sio_fd_t fd) { cyg_uint32 len = 1; #ifdef CYGDBG_LWIP_DEBUG_SIO diag_printf("sio_send(c=0x%02x,fd=%p)\n", c, fd); #endif cyg_io_write((cyg_io_handle_t) fd, &c, &len); }
static void uart_putchar(void *base, char c) { char buf; int len; struct BSP_IO *io = (struct BSP_IO *)base; if (io->chan) { len = 1; buf = c; cyg_io_write(io->chan, &buf, &len); } }
// This function is mostly used by the 'write()' system call static void uart_write(void *base, const char *buf, int len) { struct BSP_IO *io = (struct BSP_IO *)base; if (io->chan) { if (stub_is_active) { // We are running in 'GDB' mode __output_gdb_string(buf, len); } else { cyg_io_write(io->chan, buf, &len); } } }
int hci_uart_tx_wakeup(struct hci_uart *hu) { cyg_io_handle_t serial = hu->tty; struct hci_dev *hdev = &hu->hdev; struct sk_buff *skb; if (test_and_set_bit(HCI_UART_SENDING, &hu->tx_state)) { set_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); return 0; } // BT_DBG(""); restart: clear_bit(HCI_UART_TX_WAKEUP, &hu->tx_state); while ((skb = hci_uart_dequeue(hu))) { int len = skb->len; int ret; //set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); //len = tty->driver.write(tty, 0, skb->data, skb->len);//UART write //diag_printf("write skb = %x\n",skb); //diag_printf("data[0] %x %x %x %x\n",skb->data[0],skb->data[1],skb->data[2],skb->data[3]); ret = (int)cyg_io_write(serial, skb->data, (cyg_uint32*)&len); if(ret != ENOERR) break; hdev->stat.byte_tx += len; skb_pull(skb, len); if (skb->len) { hu->tx_skb = skb; break; } hci_uart_tx_complete(hu, skb->pkt_type); kfree_skb(skb); } if (test_bit(HCI_UART_TX_WAKEUP, &hu->tx_state)) goto restart; clear_bit(HCI_UART_SENDING, &hu->tx_state); return 0; }
void tty_api_test(cyg_io_handle_t* handle) { int res; cyg_uint32 len; unsigned char buffer[16]; // Always return... if (handle) return; CYG_TEST_FAIL_FINISH("Not reached"); // read & write res = cyg_io_read(handle, &buffer[0], &len); res = cyg_io_write(handle, &buffer[0], &len); // cyg_io_get_config // TTY layer cyg_io_get_config(handle, CYG_IO_GET_CONFIG_TTY_INFO, &buffer[0], &len); // Call-throughs to serial layer. cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH, &buffer[0], &len); // cyg_io_set_config // TTY layer. cyg_io_set_config(handle, CYG_IO_SET_CONFIG_TTY_INFO, &buffer[0], &len); // Call-throughs to serial layer. cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buffer[0], &len); }
static void simple_prog(CYG_ADDRESS data) { cyg_io_handle_t handle; Cyg_ErrNo err; const char test_string[] = "serial example is working correctly!\n"; cyg_uint32 len = strlen(test_string); printf("Starting serial example\n"); err = cyg_io_lookup( "/dev/haldiag", &handle ); if (ENOERR == err) { printf("Found /dev/haldiag. Writing string....\n"); err = cyg_io_write( handle, test_string, &len ); } if (ENOERR == err) { printf("I think I wrote the string. Did you see it?\n"); } printf("Serial example finished\n"); }
/* * Writes to the serial device. */ u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len) { Cyg_ErrNo ret; cyg_uint32 count = 0; cyg_uint32 chunk; #ifdef CYGDBG_LWIP_DEBUG_SIO diag_printf("sio_write(fd=%p,data=%p,len=%lu:)\n", fd, data, len); diag_printf("sio_write: "); diag_dump_buf(data, len); #endif while (count < len) { chunk = len - count; ret = cyg_io_write((cyg_io_handle_t) fd, data, &chunk); if (ret != ENOERR) break; data += chunk; count += chunk; } return count; }
void serial_api_test(int dummy) { cyg_io_handle_t handle; int res; cyg_uint32 len; unsigned char buffer[16]; // Always return... if (dummy) return; CYG_TEST_FAIL_FINISH("Not reached"); test_open_ser(&handle); // read & write res = cyg_io_read(handle, &buffer[0], &len); res = cyg_io_write(handle, &buffer[0], &len); // cyg_io_get_config cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_ABORT, &buffer[0], &len); cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH, &buffer[0], &len); // cyg_io_set_config cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &buffer[0], &len); }
static Cyg_ErrNo termios_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len) { cyg_devtab_entry_t *dt = (cyg_devtab_entry_t *)handle; struct termios_private_info *priv = (struct termios_private_info *)dt->priv; cyg_io_handle_t chan = (cyg_io_handle_t)priv->dev_handle; struct termios *t = &priv->termios; cyg_uint32 clen; cyg_uint32 size; Cyg_ErrNo res; cyg_uint8 c; cyg_uint8 *buf = (cyg_uint8 *)_buf; cyg_bool discardc; // should c be discarded (not read, not printed) cyg_bool returnnow = false; // return back to user after this char // if receiver off if (0 == (t->c_cflag & CREAD) ) { *len = 0; return -EINVAL; } size = 0; if ( 0 == (t->c_lflag & ICANON) ) { // In non-canonical mode we return the min of *len and the // number of bytes available // So we query the driver for how many bytes are available - this // guarantees we won't block cyg_serial_buf_info_t dev_buf_conf; cyg_uint32 dbc_len = sizeof( dev_buf_conf ); res = cyg_io_get_config( chan, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &dev_buf_conf, &dbc_len ); CYG_ASSERT( res == ENOERR, "Query buffer status failed!" ); if (dev_buf_conf.rx_count > 0) { // Adjust length to be max characters currently available *len = *len < dev_buf_conf.rx_count ? *len : dev_buf_conf.rx_count; } else if (t->c_cc[VMIN] == 0) { // No chars available - don't block *len = 0; return ENOERR; } } // if while (!returnnow && size < *len) { clen = 1; discardc = false; res = cyg_io_read(chan, &c, &clen); if (res != ENOERR) { *len = size; return res; } // lock to prevent termios getting corrupted while we read from it cyg_drv_mutex_lock( &priv->lock ); if ( t->c_iflag & ISTRIP ) c &= 0x7f; // canonical mode: erase, kill, and newline processing if ( t->c_lflag & ICANON ) { if ( t->c_cc[ VERASE ] == c ) { discardc = true; // erase on display? if ( (t->c_lflag & ECHO) && (t->c_lflag & ECHOE) ) { cyg_uint8 erasebuf[3]; erasebuf[0] = erasebuf[2] = t->c_cc[ VERASE ]; erasebuf[1] = ' '; clen = sizeof(erasebuf); // FIXME: what about error or non-blocking? cyg_io_write(chan, erasebuf, &clen); } if ( size ) size--; } // if else if ( t->c_cc[ VKILL ] == c ) { // kill line on display? if ( (t->c_lflag & ECHO) && (t->c_lflag & ECHOK) ) { // we could try and be more efficient here and // output a stream of erases, and then a stream // of spaces and then more erases. But this is poor // because on a slow terminal the user will see characters // delete from the middle forward in chunks! // But at least we try and chunk up sets of writes cyg_uint8 erasebuf[30]; cyg_uint8 erasechunks; cyg_uint8 i; erasechunks = size < (sizeof(erasebuf)/3) ? size : (sizeof(erasebuf)/3); for (i=0; i<erasechunks; i++) { erasebuf[i*3] = erasebuf[i*3+2] = t->c_cc[ VERASE ]; erasebuf[i*3+1] = ' '; } while( size ) { cyg_uint8 j; j = size < (sizeof(erasebuf)/3) ? size : (sizeof(erasebuf)/3); clen = (j*3); // FIXME: what about error or non-blocking? cyg_io_write( chan, erasebuf, &clen ); size -= j; } } else size = 0; discardc = true; } // else if // CR else if ( '\r' == c ) { if ( t->c_iflag & IGNCR ) discardc = true; else if ( t->c_iflag & ICRNL ) c = '\n'; } // newlines or similar. // Note: not an else if to catch CRNL conversion if ( (t->c_cc[ VEOF ] == c) || (t->c_cc[ VEOL ] == c) || ('\n' == c) ) { if ( t->c_cc[ VEOF ] == c ) discardc = true; if ( t->c_lflag & ECHONL ) { // don't check ECHO in this case clen = 1; // FIXME: what about error or non-blocking? // FIXME: what if INLCR is set? cyg_io_write( chan, "\n", &clen ); } if ( t->c_iflag & INLCR ) c = '\r'; returnnow = true; // FIXME: true even for INLCR? } // else if } // if #ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS if ( (t->c_lflag & ISIG) && (t->c_cc[ VINTR ] == c) ) { discardc = true; if ( 0 == (t->c_lflag & NOFLSH) ) size = 0; // raise could be a non-local jump - we should unlock mutex cyg_drv_mutex_unlock( &priv->lock ); // FIXME: what if raise returns != 0? raise( SIGINT ); cyg_drv_mutex_lock( &priv->lock ); } if ( (t->c_lflag & ISIG) && (t->c_cc[ VQUIT ] == c) ) { discardc = true; if ( 0 == (t->c_lflag & NOFLSH) ) size = 0; // raise could be a non-local jump - we should unlock mutex cyg_drv_mutex_unlock( &priv->lock ); // FIXME: what if raise returns != 0? raise( SIGQUIT ); cyg_drv_mutex_lock( &priv->lock ); } #endif if (!discardc) { buf[size++] = c; if ( t->c_lflag & ECHO ) { clen = 1; // FIXME: what about error or non-blocking? termios_write( handle, &c, &clen ); } } if ( (t->c_lflag & ICANON) == 0 ) { // Check to see if read has been satisfied if ( t->c_cc[ VMIN ] && (size >= t->c_cc[ VMIN ]) ) returnnow = true; } cyg_drv_mutex_unlock( &priv->lock ); } // while *len = size; return ENOERR; }
//=========================================================================== // Thread 0 //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_message tx_msg; cyg_can_event rx_event; cyg_uint32 i; cyg_uint32 rx_msg_cnt = 0; // // Prepeare message - we use a data length of 0 bytes here. Each received message // causes an iterrupt. The shortest message is a 0 data byte message. This will generate // the highest interrupt rate // CYG_CAN_MSG_SET_PARAM(tx_msg, 0, CYGNUM_CAN_ID_STD, 0, CYGNUM_CAN_FRAME_DATA); // // Now send 1024 CAN messages as fast as possible to stress the receiver of CAN // channel 1 // for (i = 0; i< 1024; ++i) { tx_msg.id = i; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN_Tbl[1], &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing to channel 0"); } } // // Now try to receive all 1024 CAN messages. If all messages are received // and no overrun occured then the message processing is fast enought // while (1) { len = sizeof(rx_event); // // First receive CAN event from real CAN hardware // len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN_Tbl[0], &rx_event, &len)) { CYG_TEST_FAIL_FINISH("Error reading from channel 1"); } if (rx_event.flags & CYGNUM_CAN_EVENT_RX) { print_can_msg(&rx_event.msg, "RX chan 1:"); rx_msg_cnt++; if (rx_msg_cnt == 1024) { CYG_TEST_PASS_FINISH("CAN load test OK"); } } // if (rx_event.flags & CYGNUM_CAN_EVENT_RX) else { print_can_flags(rx_event.flags, ""); if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX) { CYG_TEST_FAIL_FINISH("RX overrun for channel 1"); } if (rx_event.flags & CYGNUM_CAN_EVENT_ERR_PASSIVE) { CYG_TEST_FAIL_FINISH("Channel 1 error passive event"); } if (rx_event.flags & CYGNUM_CAN_EVENT_BUS_OFF) { CYG_TEST_FAIL_FINISH("Channel 1 bus off event"); } } } // while (1) }
void console_test( CYG_ADDRWORD x ) { Cyg_ErrNo res; cyg_io_handle_t handle; char msg[] = "This is a test\n"; int msglen = sizeof(msg)-1; char in_msg[80]; int in_msglen = sizeof(in_msg)-1; cyg_serial_info_t serial_info; cyg_tty_info_t tty_info; char short_msg[] = "This is a short message\n"; char long_msg[] = "This is a longer message 0123456789abcdefghijklmnopqrstuvwxyz\n"; char filler[] = " "; char prompt[] = "\nPlease enter some data: "; int i, len; res = cyg_io_lookup(CYGDAT_IO_SERIAL_TTY_CONSOLE, &handle); if (res != ENOERR) { diag_printf("Can't lookup - DEVIO error: %d\n", res); return; } len = sizeof(serial_info); res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &serial_info, &len); if (res != ENOERR) { diag_printf("Can't get serial config - DEVIO error: %d\n", res); hang(); return; } len = sizeof(tty_info); res = cyg_io_get_config(handle, CYG_IO_GET_CONFIG_TTY_INFO, &tty_info, &len); if (res != ENOERR) { diag_printf("Can't get tty config - DEVIO error: %d\n", res); hang(); return; } diag_printf("Config - baud: %d, stop: %d, parity: %d, out flags: %x, in flags: %x\n", serial_info.baud, serial_info.stop, serial_info.parity, tty_info.tty_out_flags, tty_info.tty_in_flags); len = sizeof(serial_info); res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &serial_info, &len); if (res != ENOERR) { diag_printf("Can't set serial config - DEVIO error: %d\n", res); hang(); return; } len = sizeof(tty_info); res = cyg_io_set_config(handle, CYG_IO_SET_CONFIG_TTY_INFO, &tty_info, &len); if (res != ENOERR) { diag_printf("Can't set tty config - DEVIO error: %d\n", res); hang(); return; } msglen = strlen(msg); res = cyg_io_write(handle, msg, &msglen); if (res != ENOERR) { diag_printf("Can't write data - DEVIO error: %d\n", res); hang(); return; } for (i = 0; i < 10; i++) { len = strlen(short_msg); res = cyg_io_write(handle, short_msg, &len); if (res != ENOERR) { diag_printf("Can't write [short] data - DEVIO error: %d\n", res); hang(); return; } } for (i = 0; i < 100; i++) { len = (i % 10) + 1; cyg_io_write(handle, filler, &len); len = strlen(long_msg); res = cyg_io_write(handle, long_msg, &len); if (res != ENOERR) { diag_printf("Can't write [long] data - DEVIO error: %d\n", res); hang(); return; } } len = strlen(prompt); cyg_io_write(handle, prompt, &len); res = cyg_io_read(handle, in_msg, &in_msglen); if (res != ENOERR) { diag_printf("Can't read data - DEVIO error: %d\n", res); hang(); return; } diag_printf("Read %d bytes\n", in_msglen); dump_buf(in_msg, in_msglen); CYG_TEST_PASS_FINISH("Console I/O test OK"); }
/*-------------------------------------------------------------------------+ | function: enviar mensagem (em buffer hexadecimal) para o PIC +--------------------------------------------------------------------------*/ Cyg_ErrNo send_buffer (char msgToSend[], unsigned int length) { printf("%d\n", length); err = cyg_io_write(serH, msgToSend, &length); return err; }
//=========================================================================== // READER THREAD //=========================================================================== void can_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_message tx_msg; cyg_can_info_t can_info; cyg_can_baud_rate_t baud; cyg_uint8 i = 0; cyg_uint8 j = 0; // // Check that all cannels have the same baudrate // #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN0 len = sizeof(can_info); if (ENOERR != cyg_io_get_config(hCAN_Tbl[0], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 0"); } else { baud = can_info.baud; ++i; } #endif #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN1 len = sizeof(can_info); if (ENOERR != cyg_io_get_config(hCAN_Tbl[1], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 1"); } else { if (i && (baud != can_info.baud)) { CYG_TEST_FAIL_FINISH("Error - different baudrates for CAN channel 0 and 1"); } baud = can_info.baud; ++i; } #endif #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN2 len = sizeof(can_info); if (ENOERR != cyg_io_get_config(hCAN_Tbl[2], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 2"); } else { if (i && (baud != can_info.baud)) { CYG_TEST_FAIL_FINISH("Error - different baudrates for CAN channel 1 and 2"); } baud = can_info.baud; ++i; } #endif #ifdef CYGPKG_DEVS_CAN_LPC2XXX_CAN3 len = sizeof(can_info); if (ENOERR != cyg_io_get_config(hCAN_Tbl[3], CYG_IO_GET_CONFIG_CAN_INFO, &can_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading baudrate of CAN channel 3"); } else { if (i && (baud != can_info.baud)) { CYG_TEST_FAIL_FINISH("Error - different baudrates for CAN channel 2 and 3"); } baud = can_info.baud; ++i; } #endif diag_printf("\n\nYou should no receive 4 CAN messages from each active CAN channel\n"); // // Now each CAN channel sends 10 CAN messages // for (i = 0; i < 4; ++i) { if (hCAN_Tbl[i]) { CYG_CAN_MSG_SET_PARAM(tx_msg, i * 0x100, CYGNUM_CAN_ID_STD, 4, CYGNUM_CAN_FRAME_DATA); tx_msg.data.dwords[0] = 0; tx_msg.data.dwords[1] = 0; char err_msg[64]; diag_snprintf(err_msg, sizeof(err_msg), "Error sending TX using CAN channel %d", i); for (j = 0; j < 4; ++j) { tx_msg.id = i * 0x100 + j; tx_msg.data.bytes[0] = j; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN_Tbl[i], &tx_msg, &len)) { CYG_TEST_FAIL_FINISH(err_msg); } } } // if (hCAN_Tbl[i]) } // for (i = 0; i < 4; ++i) CYG_TEST_PASS_FINISH("LPC2xxx CAN multi channel TX test OK"); }
//=========================================================================== // READER THREAD //=========================================================================== void can_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_callback_cfg callback_cfg; cyg_can_message tx_msg; cyg_bool_t wait_res; // // open CAN0 device driver // if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) { CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } // // open CAN1 device driver // if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1)) { CYG_TEST_FAIL_FINISH("Error opening /dev/can1"); } // // configure CAN0 callback // len = sizeof(callback_cfg); callback_cfg.flag_mask = 0xFFFF; callback_cfg.data = (CYG_ADDRWORD) hCAN0; callback_cfg.callback_func = callback_func; if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_CALLBACK, &callback_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } // // transmit message from CAN1 to CAN0 // tx_msg.id = 0x001; tx_msg.ext = CYGNUM_CAN_ID_STD; tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; tx_msg.dlc = 0; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing message to /dev/can1"); } // // Wait CAN0 callback // cyg_mutex_lock(&can_lock); wait_res = cyg_cond_timed_wait(&can_wait, 100); cyg_mutex_unlock(&can_lock); // // If result of wait is a signal operation, test is successed // If timeout - test is failed, because callback_func() hasn't been // called with correct parameters // if(wait_res) { CYG_TEST_PASS_FINISH("can_callback test OK"); } else { CYG_TEST_FAIL_FINISH("can_callback test FAILED"); } }
//=========================================================================== // WRITER THREAD //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_io_handle_t hCAN0; cyg_uint32 len; cyg_can_buf_info_t buf_info; cyg_uint16 i; cyg_can_event rx_event; cyg_can_message tx_msg = { 0x000, // CAN identifier {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes CYGNUM_CAN_ID_STD, // standard frame CYGNUM_CAN_FRAME_DATA, // data frame 4, // data length code }; if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) { CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } // // first we read the buffer info // len = sizeof(buf_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } // // check if buffer is really empty // if (buf_info.rx_count != 0) { CYG_TEST_FAIL_FINISH("Receive buffer of /dev/can0 is not empty."); } // // now send messages - because TX events are supported each transmitted CAN message // will cause a TX event that is filled into receive queue // diag_printf("Sending %d CAN messages to /dev/can0 \n", buf_info.rx_bufsize); for (i = 0; i < buf_info.rx_bufsize; ++i) { tx_msg.id = i; tx_msg.data[0] = i; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); } else { print_can_msg(&tx_msg, ""); } } // // now we read the buffer info - we expect a completely filled recieve queue // len = sizeof(buf_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&buf_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } // // if receive queue is not completely filled, then we have an error here // if (buf_info.rx_bufsize != buf_info.rx_count) { diag_printf("RX bufsize: %d events in RX buffer: %d\n", buf_info.rx_bufsize, buf_info.rx_count); CYG_TEST_FAIL_FINISH("Receive queue of /dev/can0 not completely filled."); } // // now we read the receive queue // diag_printf("Receiving %d TX events from /dev/can0 \n", buf_info.rx_count); for (i = 0; i < buf_info.rx_count; ++i) { len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } // // we expect only a set TX flag because no other events may arrive for the // loopback driver // if (!(rx_event.flags & CYGNUM_CAN_EVENT_TX) || (rx_event.flags & !CYGNUM_CAN_EVENT_TX)) { CYG_TEST_FAIL_FINISH("Unexpected receive event flags."); } // // Now check if TX events contain valid data - we know that the ID and the first // data byte contain the message number // if ((rx_event.msg.id != i) || (rx_event.msg.data[0] != i)) { CYG_TEST_FAIL_FINISH("Received invalid data in TX event"); } else { print_can_msg(&rx_event.msg, ""); } } // for (i = 0; i < buf_info.rx_count; ++i) CYG_TEST_PASS_FINISH("can_txevent test OK"); }
//=========================================================================== // WRITER THREAD //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_io_handle_t hCAN0; cyg_uint8 i; cyg_uint32 len; cyg_uint32 rx_bufsize; cyg_can_buf_info_t tx_buf_info; cyg_can_event rx_event; cyg_can_message tx_msg = { 0x000, // CAN identifier {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes CYGNUM_CAN_ID_STD, // standard frame CYGNUM_CAN_FRAME_DATA, // data frame 2, // data length code }; if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) { CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); } len = sizeof(tx_buf_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&tx_buf_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } // // Before we can write the CAN messages, we need to know the buffer size of the // receiver. The receiver will tell us this buffer size with one single CAN // message // len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } // // we expect a RX event here - we treat any other flag as an error // if (!(rx_event.flags & CYGNUM_CAN_EVENT_RX) || (rx_event.flags & !CYGNUM_CAN_EVENT_RX)) { CYG_TEST_FAIL_FINISH("Unexpected RX event for /dev/can0"); } rx_bufsize = *((cyg_uint32 *)rx_event.msg.data); // // now we send exactly one CAN message more than there is space in the receive buffer // this should cause an RX ovverun in receive buffer // diag_printf("/dev/can0: Sending %d CAN messages\n", rx_bufsize); for (i = 0; i <= rx_bufsize; ++i) { // // we store the message number as CAN id and in first data byte so // a receiver can check this later // tx_msg.id = 0x000 + i; tx_msg.data[0] = i; len = sizeof(tx_msg); if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); } else { print_can_msg(&tx_msg, ""); } } // for (i = 0; i <= rx_bufsize; ++i) cyg_thread_suspend(cyg_thread_self()); }
//=========================================================================== // READER THREAD //=========================================================================== void can1_thread(cyg_addrword_t data) { cyg_io_handle_t hCAN1; cyg_uint8 i; cyg_uint32 len; cyg_can_buf_info_t rx_buf_info; cyg_can_event rx_event; cyg_can_message tx_msg; if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1)) { CYG_TEST_FAIL_FINISH("Error opening /dev/can1"); } len = sizeof(rx_buf_info); if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1"); } // // first we send the size of our receive buffer to the writer // we setup tx message now // tx_msg.id = 0x000; tx_msg.ext = CYGNUM_CAN_ID_STD; tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; tx_msg.dlc = sizeof(rx_buf_info.rx_bufsize); // // we store size of rx buffer in CAN message. We do not need to care about // endianess here because this is a loopback driver test and we will receive // our own messages // *((cyg_uint32 *)tx_msg.data) = rx_buf_info.rx_bufsize; len = sizeof(tx_msg); // // as soon as we send a CAN message, thread 0 will resume because it is waiting // for a message // diag_printf("/dev/can1: Sending size of RX buffer %d\n", rx_buf_info.rx_bufsize); if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len)) { CYG_TEST_FAIL_FINISH("Error writing to /dev/can1"); } cyg_thread_delay(10); // let thread 0 run // // now we check if we received CAN messages - if receive buffer is not full // the we have an error here because we expect a full receive buffer // len = sizeof(rx_buf_info); if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1"); } if (rx_buf_info.rx_bufsize != rx_buf_info.rx_count) { CYG_TEST_FAIL_FINISH("RX buffer of /dev/can1 does not contain number of expected messages"); } // // now we wait for messages from /dev/can0 // diag_printf("/dev/can1: Receiving %d CAN messages\n", rx_buf_info.rx_count); for (i = 0; i < rx_buf_info.rx_count; ++i) { len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN1, &rx_event, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } else { if (rx_event.flags & CYGNUM_CAN_EVENT_RX) { print_can_msg(&rx_event.msg, ""); if (rx_event.msg.data[0] != (i + 1)) { CYG_TEST_FAIL_FINISH("Received /dev/can1 RX event contains invalid data"); } } else { CYG_TEST_FAIL_FINISH("Unexpected CAN event for /dev/can1"); } // // now check if any other flag is set // if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX) { diag_printf("RX queue overrun successfully indicated for /dev/can1\n"); // // if TX events are supported then we have already a TX event in receive queue because // we sent a message and the RX queue overrun will occur one message earlier // #if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT) if (i < (rx_buf_info.rx_bufsize - 2)) #else if (i < (rx_buf_info.rx_bufsize - 1)) #endif { CYG_TEST_FAIL_FINISH("RX queue overrun occured too early for /dev/can1"); } else { CYG_TEST_PASS_FINISH("can_overrun2 test OK"); } } // if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX) } } }