/* * Tries to read from the serial device. Same as sio_read but returns * immediately if no data is available and never blocks. */ u32_t sio_tryread(sio_fd_t fd, u8_t *data, u32_t len) { Cyg_ErrNo ret; cyg_serial_buf_info_t info; cyg_uint32 l; #ifdef CYGDBG_LWIP_DEBUG_SIO diag_printf("sio_tryread(fd=%p,data=%p,len=%lu:)\n", fd, data, len); #endif // Check how many bytes there are to read l = sizeof(info); ret = cyg_io_get_config((cyg_io_handle_t) fd, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &info, &l); if (ret != ENOERR) return 0; l = info.rx_count; if (l < 1) return 0; if (l > len) l = len; ret = cyg_io_read((cyg_io_handle_t) fd, data, &l); if (ret != ENOERR) return 0; #ifdef CYGDBG_LWIP_DEBUG_SIO diag_printf("sio_tryread: "); diag_dump_buf(data, len); #endif return l; }
static Cyg_ErrNo termios_get_config(cyg_io_handle_t handle, cyg_uint32 key, 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_ErrNo res = ENOERR; switch (key) { case CYG_IO_GET_CONFIG_TERMIOS: { if ( *len < sizeof(struct termios) ) { return -EINVAL; } cyg_drv_mutex_lock( &priv->lock ); *(struct termios *)buf = priv->termios; cyg_drv_mutex_unlock( &priv->lock ); *len = sizeof(struct termios); } break; default: // Assume this is a 'serial' driver control res = cyg_io_get_config(chan, key, buf, len); } // switch return res; }
/* Reset device */ static int hci_uart_flush(struct hci_dev *hdev) { struct hci_uart *hu = (struct hci_uart *) hdev->driver_data; cyg_io_handle_t serial = hu->tty; BT_DBG("hdev %p tty %p", hdev, tty); if (hu->tx_skb) { kfree_skb(hu->tx_skb); hu->tx_skb = NULL; } #if 0 /* Flush any pending characters in the driver and discipline. */ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); #else //cyg_tty_info_t tty_info; //cyg_uint32 len = sizeof(cyg_tty_info_t); //cyg_io_write(tty, const void *buf, cyg_uint32 *len) cyg_io_get_config(serial, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH, NULL, NULL); #endif if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) hu->proto->flush(hu); return 0; }
// This routine will be called if the read "times out" static void do_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); }
static Cyg_ErrNo termios_set_config(cyg_io_handle_t handle, cyg_uint32 key, 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_ErrNo res = ENOERR; switch (key) { case CYG_IO_SET_CONFIG_TERMIOS: { setattr_struct *attr = (setattr_struct *)buf; int optact = attr->optact; if ( *len != sizeof( *attr ) ) { return -EINVAL; } CYG_ASSERT( (optact == TCSAFLUSH) || (optact == TCSADRAIN) || (optact == TCSANOW), "Invalid optact" ); cyg_drv_mutex_lock( &priv->lock ); if ( ( TCSAFLUSH == optact ) || ( TCSADRAIN == optact ) ) { res = cyg_io_get_config( chan, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN, NULL, NULL ); CYG_ASSERT( ENOERR == res, "Drain request failed" ); } if ( TCSAFLUSH == optact ) { res = cyg_io_get_config( chan, CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH, NULL, NULL ); CYG_ASSERT( ENOERR == res, "Flush request failed" ); } res = set_attr( attr->termios_p, priv ); cyg_drv_mutex_unlock( &priv->lock ); return res; } default: // Pass on to serial driver res = cyg_io_set_config(chan, key, buf, len); } return res; }
/* * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, * at the requested speed, etc. If `local' is true, set CLOCAL * regardless of whether the modem option was specified. * * For *BSD, we assume that speed_t values numerically equal bits/second. */ void set_up_tty(cyg_io_handle_t handle, int local) { cyg_serial_info_t cfg; int err; int len = sizeof(cfg); err = cyg_io_get_config( handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &cfg, &len); if( err != 0 ) { syslog(LOG_ERR, "cyg_io_get_config: %d",err); die(1); } switch ( flowctl ) { case CYG_PPP_FLOWCTL_DEFAULT: break; case CYG_PPP_FLOWCTL_NONE: cfg.flags &= ~(CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX| CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX); break; case CYG_PPP_FLOWCTL_HARDWARE: cfg.flags &= ~(CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX); cfg.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX; break; case CYG_PPP_FLOWCTL_SOFTWARE: cfg.flags &= ~(CYGNUM_SERIAL_FLOW_RTSCTS_RX|CYGNUM_SERIAL_FLOW_RTSCTS_TX); cfg.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_XONXOFF_TX; break; } if( inspeed != 0 ) cfg.baud = inspeed; err = cyg_io_set_config( handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &cfg, &len); if( err != 0 ) { syslog(LOG_ERR, "cyg_io_set_config: %d",err); die(1); } }
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); }
/* get framebuffer palette*/ void ioctl_getpalette(int start, int len, short *red, short *green, short *blue) { diag_printf("%s - NOT IMPLEMENTED\n", __FUNCTION__); while (1) ; #if 0 struct fb_cmap cmap; cyg_uint32 sz = sizeof(cmap); cmap.start = start; cmap.len = len; cmap.red = red; cmap.green = green; cmap.blue = blue; cmap.transp = NULL; cyg_io_get_config( fb_handle, CYG_IO_GET_CONFIG_FB_PALETTE, &cmap, &sz ); // ioctl(fb, FBIOGETCMAP, &cmap); #endif }
cyg_bool jffs2_flash_erase(struct jffs2_sb_info * c, struct jffs2_eraseblock * jeb) { cyg_io_flash_getconfig_erase_t e; cyg_flashaddr_t err_addr; Cyg_ErrNo err; cyg_uint32 len = sizeof (e); struct super_block *sb = OFNI_BS_2SFFJ(c); e.offset = jeb->offset; e.len = c->sector_size; e.err_address = &err_addr; // D2(printf("FLASH ERASE ENABLED!!!\n")); // D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset)); // D2(printf("size = %x\n", c->sector_size)); err = cyg_io_get_config(sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len); return (err != ENOERR || e.flasherr != 0); }
/* hci_uart_tty_open * * Called when line discipline changed to HCI_UART. * * Arguments: * tty pointer to tty info structure * Return Value: * 0 if success, otherwise error code */ static int hci_uart_tty_open(cyg_io_handle_t tty) { struct hci_uart *hu = (struct hci_uart *)serial_getdisc(tty);//(void *) tty->disc_data; //BT_DBG //printf("open tty %p, hu= %x,return=%x\n", tty, hu, __builtin_return_address(0)); if (hu) return -EEXIST; if (!(hu = malloc(sizeof(struct hci_uart)))) { //BT_ERR printf("Can't allocate controll structure\n"); return -ENFILE; } memset(hu, 0, sizeof(struct hci_uart)); serial_setdisc(tty, (void*)hu); hu->tty = tty; // spin_lock_init(&hu->rx_lock); cyg_spinlock_init(&hu->rx_lock, 0); #if 0 /* Flush any pending characters in the driver and line discipline */ if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); MOD_INC_USE_COUNT; #else cyg_io_get_config(tty, CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH, NULL, NULL); #endif 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 Cyg_ErrNo real_termios_init( struct termios_private_info *priv ) { Cyg_ErrNo res; struct termios *t; cyg_serial_info_t dev_conf; cyg_serial_buf_info_t dev_buf_conf; cyg_uint32 len = sizeof( dev_conf ); CYG_REPORT_FUNCTYPE("returning %d"); CYG_REPORT_FUNCARG1XV( priv ); CYG_CHECK_DATA_PTRC( priv ); t = &priv->termios; // Get info from driver res = cyg_io_get_config( priv->dev_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &dev_conf, &len ); if ( ENOERR == res ) { len = sizeof( dev_buf_conf ); res = cyg_io_get_config( priv->dev_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO, &dev_buf_conf, &len ); } priv->errbuf = (cyg_uint8 *)malloc( dev_buf_conf.rx_bufsize ); if ( NULL == priv->errbuf ) res = ENOMEM; // FIXME: Are we allowed to do this? priv->errbufpos = priv->errbuf; priv->errbufsize = dev_buf_conf.rx_bufsize; if ( ENOERR != res ) { CYG_REPORT_RETVAL( res ); return res; } // we only support symmetric baud rates t->c_ispeed = t->c_ospeed = map_ecosbaud_to_posixbaud( dev_conf.baud ); t->c_iflag = C_IFLAG_INIT; t->c_oflag = C_OFLAG_INIT; t->c_cflag = C_CFLAG_INIT; t->c_lflag = C_LFLAG_INIT; memcpy( t->c_cc, c_cc_init, sizeof( t->c_cc ) ); switch ( dev_conf.parity ) { case CYGNUM_SERIAL_PARITY_NONE: t->c_iflag |= IGNPAR; break; case CYGNUM_SERIAL_PARITY_ODD: t->c_cflag |= PARODD; // DROPTHROUGH case CYGNUM_SERIAL_PARITY_EVEN: t->c_iflag |= PARENB; break; default: CYG_FAIL( "Unsupported default parity" ); break; } switch( dev_conf.word_length ) { case CYGNUM_SERIAL_WORD_LENGTH_5: t->c_cflag |= CS5; break; case CYGNUM_SERIAL_WORD_LENGTH_6: t->c_cflag |= CS6; break; case CYGNUM_SERIAL_WORD_LENGTH_7: t->c_cflag |= CS7; break; case CYGNUM_SERIAL_WORD_LENGTH_8: t->c_cflag |= CS8; break; default: CYG_FAIL( "Unsupported word length" ); break; } switch ( dev_conf.stop ) { case CYGNUM_SERIAL_STOP_1: // Don't need to do anything break; case CYGNUM_SERIAL_STOP_2: t->c_cflag |= CSTOPB; break; default: CYG_FAIL( "Unsupported number of stop bits" ); break; } switch ( dev_conf.flags ) { case CYGNUM_SERIAL_FLOW_RTSCTS_RX: t->c_cflag |= CRTSCTS; // drop through case CYGNUM_SERIAL_FLOW_XONXOFF_RX: t->c_iflag |= IXOFF; break; case CYGNUM_SERIAL_FLOW_RTSCTS_TX: t->c_cflag |= CRTSCTS; // drop through case CYGNUM_SERIAL_FLOW_XONXOFF_TX: t->c_iflag |= IXON; break; default: // Ignore flags we don't grok break; } return ENOERR; } // real_termios_init()
//=========================================================================== // READER THREAD //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_event rx_event; cyg_can_remote_buf rtr_buf; cyg_can_remote_buf rtr_buf2; cyg_can_msgbuf_info msgbox_info; cyg_can_mode mode; cyg_can_state state; // // before we start configuring the CAN hardware we stop the chip // mode = CYGNUM_CAN_MODE_STOP; len = sizeof(mode); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } // // now check if FlexCAN modul is really stopped // len = sizeof(state); if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_STATE ,&state, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } if (state != CYGNUM_CAN_STATE_STOPPED) { CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); } // // We would like to setup 2 remote buffers - check if we have enough // free message buffers // len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } else { diag_printf("Message boxes available: %d free: %d\n", msgbox_info.count, msgbox_info.free); } if (msgbox_info.free < 2) { CYG_TEST_FAIL_FINISH("Not enough free message buffers/dev/can0"); } // // Setup the first remote response buffer for resception of standard // remote frames // rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; rtr_buf.msg.id = 0x7FF; rtr_buf.msg.ext = CYGNUM_CAN_ID_STD; rtr_buf.msg.rtr = CYGNUM_CAN_FRAME_DATA; rtr_buf.msg.dlc = 1; rtr_buf.msg.data[0] = 0xAB; len = sizeof(rtr_buf); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } // // setup the second remote response buffer for reception of extended // remote frames // rtr_buf2.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; rtr_buf2.msg.id = 0x800; rtr_buf2.msg.ext = CYGNUM_CAN_ID_EXT; rtr_buf2.msg.rtr = CYGNUM_CAN_FRAME_DATA; rtr_buf2.msg.dlc = 4; rtr_buf2.msg.data[0] = 0xAB; len = sizeof(rtr_buf2); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf2, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } if (rtr_buf.handle == CYGNUM_CAN_MSGBUF_NA) { CYG_TEST_FAIL_FINISH("No free message buffer available for /dev/can0"); } // // now configuration is finished and we can start chip again // mode = CYGNUM_CAN_MODE_START; len = sizeof(mode); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } diag_printf("Test of FlexCAN remote response buffer configuration\n" "If a CAN node sends a remote request with ID 0x7FF\n" "or 0x800 then the FlexCAN modul should respond with\n" "data frames.\n"); diag_printf("!!! This test can be stopped by sending a data frame with ID 0x100 !!!\n\n"); len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } else { diag_printf("Message boxes available: %d free: %d\n", msgbox_info.count, msgbox_info.free); } while (1) { len = sizeof(rx_event); if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } if (0x100 == rx_event.msg.id) { CYG_TEST_PASS_FINISH("flexcan_remote test OK"); } else { print_can_flags(rx_event.flags, ""); print_can_msg(&rx_event.msg, ""); } } }
int read_gps(struct gps *gpsData_ptr) { // serial port buffer handle cyg_io_handle_t port_handle; cyg_serial_buf_info_t buff_info; unsigned int len = sizeof (buff_info); // get serial port handle cyg_io_lookup( gpsData_ptr->portName, &port_handle ); cyg_io_get_config (port_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO,\ &buff_info, &len); unsigned int bytesInBuffer = buff_info.rx_count; unsigned int bytesReadThisCall =0;; unsigned short msgPayloadSize = 0, bytesToRead = 0, bytesRead = 0; int status = 0; // Initialization of persistent local buffer if (gpsData_ptr->localBuffer == NULL) { gpsData_ptr->localBuffer = (unsigned char*) malloc (1024 * sizeof (unsigned char)); } // First check if there are any bytes in the serial buffer, return if none if( bytesInBuffer == 0 ) return -1; // Get localBuffer stored in gps packet. This is to keep the following code readable localBuffer = gpsData_ptr->localBuffer; bytesInLocalBuffer= gpsData_ptr->bytesInLocalBuffer; readState = gpsData_ptr->readState; // Keep reading until we've processed all of the bytes in the buffer while (bytesReadThisCall < bytesInBuffer){ switch (readState){ case 0: //Look for packet header bytes // Read in up to 2 bytes to the first open location in the local buffer bytesRead = read(gpsData_ptr->port,&localBuffer[bytesInLocalBuffer],2-bytesInLocalBuffer); bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (localBuffer[0] == 0xA0){ // Check for first header byte bytesInLocalBuffer = 1; if (localBuffer[1] == 0xA2){ // Check for second header byte bytesInLocalBuffer = 2; readState++; // header complete, move to next stage } } else { gpsData_ptr->err_type = noPacketHeader; } break; // end case 0 case 1: //Look for message size bytes // Find how many bytes need to be read for data length (2) - bytes already read (includes 2 byte header) bytesToRead = 4 - bytesInLocalBuffer; // Read in up to 2 bytes to the first open location in the local buffer bytesRead = read(gpsData_ptr->port,&localBuffer[bytesInLocalBuffer],bytesToRead); bytesReadThisCall += bytesRead; // keep track of bytes read during this call bytesInLocalBuffer += bytesRead; // keep track of bytes in local buffer if (bytesRead == bytesToRead){ readState++; // size bytes complete, move to next stage } else{ //printf ("\n<GPS>: Failed to get size bytes"); gpsData_ptr->err_type = incompletePacket; } break; // end case 1 case 2: //Read payload, checksum, and stop bytes // Find message payload size msgPayloadSize = getbeuw(localBuffer,2)&0x7FFF; // packet size is 15 bits. bitwise AND ensures only 15 bits are used. //printf("<GPS>: msgPayloadSize: %d\n",msgPayloadSize); // Error checking on payload size. If size is bigger than expected, dump packet if(msgPayloadSize > GPS_MAX_MSG_SIZE){ gpsData_ptr->err_type = incompletePacket; reset_localBuffer(); } // Find how many bytes need to be read for the total message (Header (2) + Size (2) + Payload + checksum (2) + stop (2) - bytes already read ) bytesToRead = msgPayloadSize + 8 - bytesInLocalBuffer; // Read in the remainder of the message to the local buffer, starting at the first empty location bytesRead = read (gpsData_ptr->port, &localBuffer[bytesInLocalBuffer], bytesToRead); bytesInLocalBuffer += bytesRead; // keep track of bytes in local buffer bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (bytesRead == bytesToRead){ //printf ("\n<GPS>: Got complete message! Tried for %d, got %d",bytesToRead,bytesRead); //printf("<GPS>: Packet ID %d \n", localBuffer[4]); //printf("<GPS>: msgPayloadSize: %d\n",msgPayloadSize); //printf("<GPS>: My checksum: %d Recv: %d\n",do_chksum(localBuffer, 4, msgPayloadSize+4),getbeuw(localBuffer,4+msgPayloadSize)); // Checksum verification (15-bit, big endian) if ( (do_chksum(localBuffer, 4, msgPayloadSize+4)&0x7FFF) == (getbeuw(localBuffer,4+msgPayloadSize)&0x7FFF) ){ // If it's OK, extract data parse_gps( gpsData_ptr ); gpsData_ptr->err_type = data_valid; //printf ("\n<GPS>: Success!"); status = 1; } else{ //printf ("\n<GPS>: Checksum mismatch!"); gpsData_ptr->err_type = checksum_err; } reset_localBuffer(); // Clear the local buffer regardless } else{ //printf ("<GPS>: Didn't get complete message. Tried for %d, got %d. %d\n",bytesToRead,bytesRead,msgPayloadSize); gpsData_ptr->err_type= incompletePacket; status = 0; } break; // end case 2 default: reset_localBuffer(); printf ("\n<GPS>: Why are you here?"); status = 0; break; // end default } // end switch (readState) } // end while (bytesReadThisCall < bytesInBuffer) // Store local buffer in gps packet gpsData_ptr->localBuffer = localBuffer; gpsData_ptr->bytesInLocalBuffer = bytesInLocalBuffer; gpsData_ptr->readState = readState; return status; }
externC void cyg_start( void ) { Cyg_ErrNo stat; cyg_io_handle_t flash_handle; cyg_io_flash_getconfig_erase_t e; cyg_io_flash_getconfig_devsize_t d; cyg_io_flash_getconfig_blocksize_t b; cyg_io_flash_getconfig_lock_t l; cyg_io_flash_getconfig_unlock_t u; CYG_ADDRWORD flash_start, flash_end; CYG_ADDRWORD flash_test_start, flash_addr; cyg_uint32 flash_block_size, flash_num_blocks; CYG_ADDRWORD test_buf1, test_buf2; cyg_uint32 *lp1, *lp2; int i, len; cyg_bool passed, ok; CYG_TEST_INIT(); passed = true; if ((stat = cyg_io_lookup(FLASH_TEST_DEVICE, &flash_handle)) == -ENOENT) { stat = cyg_io_lookup(FLASH_TEST_DEVICE2, &flash_handle); } if (stat != 0) { diag_printf("FLASH: driver init failed: %s\n", strerror(-stat)); CYG_TEST_FAIL_FINISH("FLASH driver init failed"); } len = sizeof(d); stat = cyg_io_get_config( flash_handle, CYG_IO_GET_CONFIG_FLASH_DEVSIZE, &d, &len ); flash_start = 0; // Keep 'end' address as last valid location, to avoid wrap around problems flash_end = d.dev_size - 1; len = sizeof(b); b.offset = 0; stat = cyg_io_get_config( flash_handle, CYG_IO_GET_CONFIG_FLASH_BLOCKSIZE, &b, &len ); flash_block_size = b.block_size; flash_num_blocks = d.dev_size/flash_block_size; diag_printf("FLASH: %p - %p, %d blocks of 0x%x bytes each.\n", (void*)flash_start, (void*)(flash_end + 1), flash_num_blocks, flash_block_size); // Verify that the testing limits are within the bounds of the // physical device. Also verify that the size matches with // the erase block size on the device if ((FLASH_TEST_OFFSET > (flash_end - flash_start)) || ((FLASH_TEST_OFFSET + FLASH_TEST_LENGTH) > (flash_end - flash_start))) { CYG_TEST_FAIL_FINISH("FLASH test region outside physical limits"); } if ((FLASH_TEST_LENGTH % flash_block_size) != 0) { CYG_TEST_FAIL_FINISH("FLASH test region must be integral multiple of erase block size"); } // Allocate two buffers large enough for the test test_buf1 = (CYG_ADDRWORD)CYGMEM_SECTION_heap1; test_buf2 = test_buf1 + FLASH_TEST_LENGTH; if (CYGMEM_SECTION_heap1_SIZE < (FLASH_TEST_LENGTH * 2)) { CYG_TEST_FAIL_FINISH("FLASH not enough heap space - reduce size of test region"); } diag_printf("... Using test buffers at %p and %p\n", (void *)test_buf1, (void *)test_buf2); flash_test_start = flash_start + FLASH_TEST_OFFSET; #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING // Unlock test diag_printf("... Unlock test\n"); ok = true; u.offset = flash_test_start; u.len = FLASH_TEST_LENGTH; len = sizeof(u); if ((stat = cyg_io_get_config(flash_handle, CYG_IO_GET_CONFIG_FLASH_UNLOCK, &u, &len ) ) != 0 || u.flasherr != 0) { diag_printf("FLASH: unlock failed: %s %s\n", strerror(stat), cyg_flash_errmsg(u.flasherr)); ok = false; } #endif // Erase test diag_printf("... Erase test\n"); ok = true; e.offset = flash_test_start; e.len = FLASH_TEST_LENGTH; len = sizeof(e); if ((stat = cyg_io_get_config(flash_handle, CYG_IO_GET_CONFIG_FLASH_ERASE, &e, &len ) ) != 0 || e.flasherr != 0) { diag_printf("FLASH: erase failed: %s %s\n", cyg_epcs_errmsg(stat), cyg_epcs_errmsg(e.flasherr)); ok = false; } len = FLASH_TEST_LENGTH; if (ok && (stat = cyg_io_bread(flash_handle, (void *)test_buf1, &len, flash_test_start)) != 0) { diag_printf("FLASH: read/verify after erase failed: %s\n", cyg_epcs_errmsg(stat)); ok = false; } lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { if (*lp1++ != 0xFFFFFFFF) { diag_printf("FLASH: non-erased data found at offset %p\n", (void*)((CYG_ADDRWORD)(lp1-1) - test_buf1)); diag_dump_buf((void *)(lp1-1), 32); ok = false; break; } } // Try reading in little pieces len = FLASH_TEST_LENGTH; flash_addr = flash_test_start; while (len > 0) { cyg_uint32 l = 0x200; if ((stat = cyg_io_bread(flash_handle, (void *)test_buf1, &l, flash_addr)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read[short]/verify after erase failed: %s\n", strerror(stat)); ok = false; break; } flash_addr = flash_addr + l; len -= l; lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < 0x200; i += sizeof(cyg_uint32)) { if (*lp1++ != 0xFFFFFFFF) { diag_printf("FLASH: non-erased data found at offset %p\n", (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp1-1) - test_buf1)); diag_dump_buf((void *)(lp1-1), 32); ok = false; len = 0; break; } } } if (!ok) { CYG_TEST_INFO("FLASH erase failed"); passed = false; } // Simple write/verify test diag_printf("... Write/verify test\n"); lp1 = (cyg_uint32 *)test_buf1; for (i = 0; i < FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { *lp1 = (cyg_uint32)lp1; lp1++; } ok = true; len = FLASH_TEST_LENGTH; if (ok && (stat = cyg_io_bwrite(flash_handle, (void *)test_buf1, &len, flash_test_start)) != 0) { diag_printf("FLASH: write failed: %s\n", strerror(stat)); ok = false; } len = FLASH_TEST_LENGTH; if (ok && (stat = cyg_io_bread(flash_handle, (void *)test_buf2, &len, flash_test_start)) != CYG_FLASH_ERR_OK) { diag_printf("FLASH: read/verify after write failed: %s\n", strerror(stat)); ok = false; } lp1 = (cyg_uint32 *)test_buf1; lp2 = (cyg_uint32 *)test_buf2; for (i = 0; i < FLASH_TEST_LENGTH; i += sizeof(cyg_uint32)) { if (*lp2++ != *lp1++) { diag_printf("FLASH: incorrect data found at offset %p\n", (void *)((CYG_ADDRWORD)(lp2-1) - test_buf2)); diag_dump_buf((void *)(lp2-1), 32); ok = false; break; } } // Try reading in little pieces len = FLASH_TEST_LENGTH; flash_addr = flash_test_start; lp1 = (cyg_uint32 *)test_buf1; lp2 = (cyg_uint32 *)test_buf2; while (len > 0) { cyg_uint32 l = 0x200; if ((stat = cyg_io_bread(flash_handle, (void *)lp2, &l, flash_addr)) != 0) { diag_printf("FLASH: read[short]/verify after erase failed: %s\n", strerror(stat)); ok = false; break; } flash_addr = flash_addr + l; len -= l; for (i = 0; i < l; i += sizeof(cyg_uint32)) { if (*lp2++ != *lp1++) { diag_printf("FLASH: incorrect data found at offset %p\n", (cyg_uint8 *)flash_addr + (CYG_ADDRWORD)((lp2-1) - test_buf2)); diag_dump_buf((void *)(lp2-1), 32); ok = false; len = 0; break; } } } #ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING // Lock test diag_printf("... Lock test\n"); ok = true; l.offset = flash_test_start; l.len = FLASH_TEST_LENGTH; len = sizeof(l); if ((stat = cyg_io_get_config(flash_handle, CYG_IO_GET_CONFIG_FLASH_LOCK, &l, &len ) ) != 0 || l.flasherr != 0 ) { diag_printf("FLASH: unlock failed: %s %s\n", strerror(stat), cyg_flash_errmsg(l.flasherr)); ok = false; } #endif if (!ok) { CYG_TEST_INFO("FLASH write/verify failed"); } if (passed) { CYG_TEST_PASS_FINISH("FLASH test1"); } else { CYG_TEST_FAIL_FINISH("FLASH test1"); } }
//=========================================================================== // 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"); }
//=========================================================================== // READER THREAD //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_event rx_event1; cyg_can_event rx_event2; cyg_can_msgbuf_info msgbox_info; cyg_can_mode mode; cyg_can_state state; diag_printf("Test of FlexCAN standby mode with selfwakeup\n" "As soon as a message arrives the FlexCAN modul\n" "will leave standby and generates a leave standby event.\n" "Each time you send a message you should see LSTY first\n" "for \"leaving standby\" and then \"RX\" for the\n" "RX event that caused the leave standby event. You can send\n" "a CAN data frame with any ID\n"); diag_printf("!!! This test can be stopped by sending a data frame with ID 0x100 !!!\n\n"); len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } else { diag_printf("Message boxes available: %d free: %d\n", msgbox_info.count, msgbox_info.free); } while (1) { // // now we set FlexCAN into standby mode // mode = CYGNUM_CAN_MODE_STANDBY; len = sizeof(mode); if (ENOERR != cyg_io_set_config(hDrvFlexCAN, CYG_IO_SET_CONFIG_CAN_MODE ,&mode, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } // // now check if FlexCAN modul is really in standby mode // len = sizeof(state); if (ENOERR != cyg_io_get_config(hDrvFlexCAN, CYG_IO_GET_CONFIG_CAN_STATE ,&state, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } if (state != CYGNUM_CAN_STATE_STANDBY) { CYG_TEST_FAIL_FINISH("Error stopping FlexCAN /dev/can0"); } // // as soon as a message arrives the FlexCAN modul leaves standby mode // and we should receive a CYGNUM_CAN_EVENT_LEAVING_STANDBY event but // we will also receive a RX event because a message arrived // len = sizeof(rx_event1); if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event1, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } len = sizeof(rx_event2); if (ENOERR != cyg_io_read(hDrvFlexCAN, &rx_event2, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } print_can_flags(rx_event1.flags, ""); print_can_flags(rx_event2.flags, ""); // // The first event we receive should be a leaving standby event because // first flexcan leaves standby and then a message will be received // if (!(rx_event1.flags & CYGNUM_CAN_EVENT_LEAVING_STANDBY)) { CYG_TEST_FAIL_FINISH("CYGNUM_CAN_EVENT_LEAVING_STANDBY event expexted /dev/can0"); } if (rx_event2.msg.id == 0x100) { CYG_TEST_PASS_FINISH("flexcan_wake test OK"); } } }
//=========================================================================== // Main thread //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_event rx_event; cyg_uint16 i; cyg_can_hdi hdi; cyg_can_msgbuf_info msgbox_info; cyg_can_msgbuf_cfg msgbox_cfg; len = sizeof(hdi); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_HDI ,&hdi, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } // // Normally the CAN modul should support message filters. So the // FULLCAN flag should be set - if it is not, we treat this as an error // if (!(hdi.support_flags & CYGNUM_CAN_HDI_FULLCAN)) { CYG_TEST_FAIL_FINISH("/dev/can0 does not support message buffers"); } // // Now reset message buffer configuration - this is mandatory bevore starting // message buffer runtime configuration // msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; len = sizeof(msgbox_cfg); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&msgbox_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error resetting message buffer configuration of /dev/can0"); } // // Now query number of available and free message boxes // len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } // // if there are no free message boxes available then this is a failure // if (!msgbox_info.free) { CYG_TEST_FAIL_FINISH("No free message boxes available for /dev/can0"); } // // We setup as many standard CAN message filters as there are free // message buffers available. // for (i = 0; i < msgbox_info.free; ++i) { cyg_can_filter rx_filter; rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD; rx_filter.msg.id = i; rx_filter.msg.ext = CYGNUM_CAN_ID_STD; len = sizeof(rx_filter); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rx_filter, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } else if (CYGNUM_CAN_MSGBUF_NA == rx_filter.handle) { CYG_TEST_FAIL_FINISH("Error setting up message filter for /dev/can0"); } } diag_printf("\n\nNow try to send CAN messages. The device should only\n" "receive messages identifiers in the range of 0x00 to 0x%X.\n" "As soon as a standard message with ID 0x000 arrives, all\n" "message filters will be cleared\n\n", (msgbox_info.free - 1)); // // Now receive messages until a message arrives with largest ID of all // available message filters // rx_event.msg.id = 1; while(rx_event.msg.id != 0) { len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN0, &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 (ENOERR != cyg_io_read(hCAN0, &rx_event, &len)) else { print_can_flags(rx_event.flags, ""); rx_event.msg.id = 1; } } // while(1) // // Now enable reception of all available CAN messages // cyg_can_filter rx_filter; rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ALL; len = sizeof(rx_filter); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF , &rx_filter, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } diag_printf("\n\nAll message filters have been cleared an now the device\n" "will receive any available CAN message identifiers.\n" "Send a CAN message with ID 0x100 to stop this test.\n\n"); // // Now receive messages until a message arrives with largest ID of all // available message filters // rx_event.msg.id = 1; while(rx_event.msg.id != 0x100) { len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN0, &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 (ENOERR != cyg_io_read(hCAN0, &rx_event, &len)) } // while(1) CYG_TEST_PASS_FINISH("can_filter test OK"); }
//=========================================================================== // Main thread //=========================================================================== void can0_thread(cyg_addrword_t data) { cyg_uint32 len; cyg_can_event rx_event; cyg_can_remote_buf rtr_buf; cyg_can_filter rx_filter; cyg_can_msgbuf_info msgbox_info; cyg_can_msgbuf_cfg msgbox_cfg; // // We would like to setup 2 remote buffers - check if we have enough // free message buffers // len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } else { diag_printf("\n\n\nMessage boxes available: %d free: %d\n", msgbox_info.count, msgbox_info.free); } // // We have not enougth free message buffers, so we clear all message buffers now // and try again // if (msgbox_info.free < 2) { msgbox_cfg.cfg_id = CYGNUM_CAN_MSGBUF_RESET_ALL; len = sizeof(msgbox_cfg); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF, &msgbox_cfg, &len)) { CYG_TEST_FAIL_FINISH("Error clearing message buffers of /dev/can0"); } // // Now query number of free message boxes again. We need 3 free message boxes. // 2 message boxes for setup of remote response buffers and 1 message box for // setup of receive message box for CAN identifier 0x100 // len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); } else { diag_printf("Message boxes available: %d free: %d\n", msgbox_info.count, msgbox_info.free); } if (msgbox_info.free < 3) { CYG_TEST_FAIL_FINISH("Not enough free message buffers available for /dev/can0"); } else { rx_filter.cfg_id = CYGNUM_CAN_MSGBUF_RX_FILTER_ADD; CYG_CAN_MSG_SET_STD_ID(rx_filter.msg, 0x100); len = sizeof(rx_filter); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rx_filter, &len)) { CYG_TEST_FAIL_FINISH("Error adding rx filter for CAN ID 0x100 for /dev/can0"); } } // if (msgbox_info.free < 3) } // if (msgbox_info.free < 2) #ifdef CYGOPT_IO_CAN_STD_CAN_ID // // Setup the first remote response buffer for resception of standard // remote frames // rtr_buf.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; CYG_CAN_MSG_SET_PARAM(rtr_buf.msg, 0x7FF, CYGNUM_CAN_ID_STD, 1, CYGNUM_CAN_FRAME_DATA); CYG_CAN_MSG_SET_DATA(rtr_buf.msg, 0, 0xAB); len = sizeof(rtr_buf); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } #endif #ifdef CYGOPT_IO_CAN_EXT_CAN_ID cyg_can_remote_buf rtr_buf2; // // setup the second remote response buffer for reception of extended // remote frames // rtr_buf2.cfg_id = CYGNUM_CAN_MSGBUF_REMOTE_BUF_ADD; CYG_CAN_MSG_SET_PARAM(rtr_buf2.msg, 0x800, CYGNUM_CAN_ID_EXT, 4, CYGNUM_CAN_FRAME_DATA); CYG_CAN_MSG_SET_DATA(rtr_buf2.msg, 0, 0xCD); len = sizeof(rtr_buf2); if (ENOERR != cyg_io_set_config(hCAN0, CYG_IO_SET_CONFIG_CAN_MSGBUF ,&rtr_buf2, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } if (rtr_buf.handle == CYGNUM_CAN_MSGBUF_NA) { CYG_TEST_FAIL_FINISH("No free message buffer available for /dev/can0"); } #endif diag_printf("\nTest of CAN remote response buffer configuration\n" "If a CAN node sends a remote request with ID 0x7FF (std. ID)\n" "or 0x800 (ext. ID) then the CAN driver should respond with\n" "data frames.\n\n"); diag_printf("!!! This test can be stopped by sending a data frame\n" "with ID 0x100 !!!\n\n"); len = sizeof(msgbox_info); if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_MSGBUF_INFO ,&msgbox_info, &len)) { CYG_TEST_FAIL_FINISH("Error writing config of /dev/can0"); } else { diag_printf("Message boxes available: %d free: %d\n", msgbox_info.count, msgbox_info.free); } while (1) { len = sizeof(rx_event); if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len)) { CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); } if (0x100 == rx_event.msg.id) { CYG_TEST_PASS_FINISH("can_remote test OK"); } else { print_can_flags(rx_event.flags, ""); if (rx_event.flags & CYGNUM_CAN_EVENT_RX) { print_can_msg(&rx_event.msg, ""); } } } }
static Cyg_ErrNo set_attr( struct termios *t, struct termios_private_info *priv ) { Cyg_ErrNo res = ENOERR; cyg_serial_info_t dev_conf, new_dev_conf; cyg_uint32 len = sizeof( dev_conf ); cc_t *tempcc = &priv->termios.c_cc[0]; struct termios *ptermios = &priv->termios; // Get info from driver res = cyg_io_get_config( priv->dev_handle, CYG_IO_GET_CONFIG_SERIAL_INFO, &dev_conf, &len ); if ( ENOERR != res ) return res; // We need to set up each facet of config to change one by one because // POSIX says we should try and change as much of the config as possible // This is tedious and has to be done by steam :-( if ( t->c_ospeed != ptermios->c_ospeed ) { new_dev_conf = dev_conf; new_dev_conf.baud = map_posixbaud_to_ecosbaud( t->c_ospeed ); if ( 0 != new_dev_conf.baud ) { len = sizeof( new_dev_conf ); res = cyg_io_set_config( priv->dev_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_dev_conf, &len ); if ( ENOERR == res ) { // It worked, so update dev_conf to reflect the new state dev_conf.baud = new_dev_conf.baud; // and termios ptermios->c_ispeed = t->c_ospeed; ptermios->c_ospeed = t->c_ospeed; } } } if ( (t->c_cflag & CSTOPB) != (ptermios->c_cflag & CSTOPB) ) { new_dev_conf = dev_conf; if ( t->c_cflag & CSTOPB ) new_dev_conf.stop = CYGNUM_SERIAL_STOP_2; else new_dev_conf.stop = CYGNUM_SERIAL_STOP_1; len = sizeof( new_dev_conf ); res = cyg_io_set_config( priv->dev_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_dev_conf, &len ); if ( ENOERR == res ) { // It worked, so update dev_conf to reflect the new state dev_conf.stop = new_dev_conf.stop; // and termios ptermios->c_cflag &= ~CSTOPB; ptermios->c_cflag |= t->c_cflag & CSTOPB; } } if ( ((t->c_cflag & PARENB) != (ptermios->c_cflag & PARENB)) || ((t->c_cflag & PARODD) != (ptermios->c_cflag & PARODD)) ) { new_dev_conf = dev_conf; if ( t->c_cflag & PARENB ) if ( t->c_cflag & PARODD ) new_dev_conf.parity = CYGNUM_SERIAL_PARITY_ODD; else new_dev_conf.parity = CYGNUM_SERIAL_PARITY_EVEN; else new_dev_conf.parity = CYGNUM_SERIAL_PARITY_NONE; len = sizeof( new_dev_conf ); res = cyg_io_set_config( priv->dev_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_dev_conf, &len ); if ( ENOERR == res ) { // It worked, so update dev_conf to reflect the new state dev_conf.parity = new_dev_conf.parity; // and termios ptermios->c_cflag &= ~(PARENB|PARODD); ptermios->c_cflag |= t->c_cflag & (PARENB|PARODD); } } if ( (t->c_cflag & CSIZE) != (ptermios->c_cflag & CSIZE) ) { new_dev_conf = dev_conf; switch ( t->c_cflag & CSIZE ) { case CS5: new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_5; break; case CS6: new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_6; break; case CS7: new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_7; break; case CS8: new_dev_conf.word_length = CYGNUM_SERIAL_WORD_LENGTH_8; break; } len = sizeof( new_dev_conf ); res = cyg_io_set_config( priv->dev_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_dev_conf, &len ); if ( ENOERR == res ) { // It worked, so update dev_conf to reflect the new state dev_conf.word_length = new_dev_conf.word_length; // and termios ptermios->c_cflag &= ~CSIZE; ptermios->c_cflag |= t->c_cflag & CSIZE; } } if ( (t->c_cflag & IXOFF) != (ptermios->c_cflag & IXOFF) ) { new_dev_conf = dev_conf; new_dev_conf.flags &= ~(CYGNUM_SERIAL_FLOW_XONXOFF_RX|CYGNUM_SERIAL_FLOW_RTSCTS_RX); if ( t->c_cflag & IXOFF ) if ( t->c_cflag & CRTSCTS) new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_RX; else new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_RX; else new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_NONE; len = sizeof( new_dev_conf ); res = cyg_io_set_config( priv->dev_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_dev_conf, &len ); if ( ENOERR == res ) { // It worked, so update dev_conf to reflect the new state dev_conf.flags = new_dev_conf.flags; // and termios ptermios->c_cflag &= ~(IXOFF|CRTSCTS); ptermios->c_cflag |= t->c_cflag & (IXOFF|CRTSCTS); } } if ( (t->c_cflag & IXON) != (ptermios->c_cflag & IXON) ) { new_dev_conf = dev_conf; new_dev_conf.flags &= ~(CYGNUM_SERIAL_FLOW_XONXOFF_TX|CYGNUM_SERIAL_FLOW_RTSCTS_TX); if ( t->c_cflag & IXON ) if ( t->c_cflag & CRTSCTS) new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_RTSCTS_TX; else new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_XONXOFF_TX; else new_dev_conf.flags |= CYGNUM_SERIAL_FLOW_NONE; len = sizeof( new_dev_conf ); res = cyg_io_set_config( priv->dev_handle, CYG_IO_SET_CONFIG_SERIAL_INFO, &new_dev_conf, &len ); if ( ENOERR == res ) { // It worked, so update dev_conf to reflect the new state dev_conf.flags = new_dev_conf.flags; // and termios ptermios->c_cflag &= ~(IXON|CRTSCTS); ptermios->c_cflag |= t->c_cflag & (IXON|CRTSCTS); } } // Input/Output processing flags can just be set as we grok them all // with few exceptions (see lflags below) ptermios->c_iflag &= ~(BRKINT|ICRNL|IGNBRK|IGNCR|IGNPAR|INLCR|INPCK| ISTRIP|PARMRK); ptermios->c_iflag |= t->c_iflag & ( #ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS BRKINT| #endif ICRNL|IGNBRK|IGNCR|IGNPAR| INLCR|INPCK|ISTRIP|PARMRK ); ptermios->c_oflag &= ~(OPOST|ONLCR); ptermios->c_oflag |= t->c_oflag & (OPOST|ONLCR); ptermios->c_cflag &= ~(CLOCAL|CREAD|HUPCL); ptermios->c_cflag |= t->c_cflag & (CLOCAL|CREAD|HUPCL); ptermios->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON| IEXTEN|ISIG|NOFLSH|TOSTOP); // Note we don't support IEXTEN nor TOSTOP so we don't set them ptermios->c_lflag |= t->c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ICANON| #ifdef CYGSEM_IO_SERIAL_TERMIOS_USE_SIGNALS ISIG| #endif NOFLSH); // control characters. We don't support changing of VSTART, VSTOP, // VTIME or VSUSP though tempcc[VEOF] = t->c_cc[VEOF]; tempcc[VEOL] = t->c_cc[VEOL]; tempcc[VERASE] = t->c_cc[VERASE]; tempcc[VINTR] = t->c_cc[VINTR]; tempcc[VKILL] = t->c_cc[VKILL]; tempcc[VMIN] = t->c_cc[VMIN]; tempcc[VQUIT] = t->c_cc[VQUIT]; return res; }
//=========================================================================== // 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"); }
// How to handle static variables with multiple sensors? objects? add to gpspacket? int read_gps(struct gps *gpsData_ptr) { cyg_io_handle_t port_handle; cyg_serial_buf_info_t buff_info; unsigned int len = sizeof (buff_info); // get serial port handle cyg_io_lookup( gpsData_ptr->portName, &port_handle ); cyg_io_get_config (port_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO,\ &buff_info, &len); unsigned int bytesInBuffer = buff_info.rx_count; unsigned int bytesReadThisCall =0;; unsigned short msgPayloadSize = 0, bytesToRead = 0, bytesRead = 0; int status =0; // Initialization of persistent local buffer if (gpsData_ptr->localBuffer == NULL) { gpsData_ptr->localBuffer = (unsigned char*) malloc (1024 * sizeof (unsigned char)); } // First check if there are any bytes in the serial buffer, return if none if( bytesInBuffer == 0 ) return -1; // Get localBuffer stored in gps packet. This is to keep the following code readable localBuffer = gpsData_ptr->localBuffer; bytesInLocalBuffer= gpsData_ptr->bytesInLocalBuffer; readState = gpsData_ptr->readState; //fprintf(stderr, "read state is %d (before while)\n", readState); // Keep reading until we've processed all of the bytes in the buffer while (bytesReadThisCall < bytesInBuffer){ //fprintf(stderr, "read state is %d (after while)\n", readState); switch (readState){ case 0: //Look for packet header bytes // Read in up to 4 bytes to the first open location in the local buffer bytesRead = read(gpsData_ptr->port,&localBuffer[bytesInLocalBuffer],4-bytesInLocalBuffer); bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (localBuffer[0] == '$'){ // Check for first header byte bytesInLocalBuffer = 1; //fprintf(stderr, "case 0, $ header type \n"); if (localBuffer[1] == 'B'){ // Check for second header byte bytesInLocalBuffer = 2; if (localBuffer[2] == 'I'){ // Check for third header byte bytesInLocalBuffer = 3; if (localBuffer[3] == 'N'){ // Check for fourth header byte bytesInLocalBuffer = 4; readState++; // header complete, move to next stage } } } } else { gpsData_ptr->err_type = noPacketHeader; } break; // end case 0 case 1: // Look for block ID and data length // Find how many bytes need to be read for block ID (2) + data length (2) - bytes already read (includes 4 byte header) bytesToRead = 8 - bytesInLocalBuffer; // Read in bytes to the last location in the local buffer bytesRead = read(gpsData_ptr->port,&localBuffer[bytesInLocalBuffer],bytesToRead); bytesInLocalBuffer += bytesRead; // keep track of bytes in local buffer bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (bytesRead == bytesToRead){ readState++; //printf ("\n<GPS>: Got msgID: %d and Data Length: %d", localBuffer[5]*256 + localBuffer[4], localBuffer[7]*256 + localBuffer[6]); } else{ gpsData_ptr->err_type = incompletePacket; } break; // end case 1 case 2: //Read payload, checksum, and stop bytes // Find message payload size msgPayloadSize = localBuffer[7]*256 + localBuffer[6]; // data is in little endian format // Error checking on payload size. If size is bigger than expected, dump packet if(msgPayloadSize > GPS_MAX_MSG_SIZE){ gpsData_ptr->err_type = incompletePacket; reset_localBuffer(); } // Find how many bytes need to be read for the total message (Header (4) + ID (2) + Size (2) + Payload + checksum (2) + stop (2) - bytes already read ) bytesToRead = msgPayloadSize + 12 - bytesInLocalBuffer; // Read in the remainder of the message to the local buffer, starting at the first empty location bytesRead = read (gpsData_ptr->port, &localBuffer[bytesInLocalBuffer], bytesToRead); bytesInLocalBuffer += bytesRead; // keep track of bytes in local buffer bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (bytesRead == bytesToRead){ //printf ("\n<GPS>: Got complete message! Tried for %d, got %d",bytesToRead,bytesRead); //printf ("\n<GPS>: My checksum: %d Recv: %d",do_chksum(localBuffer, 8, msgPayloadSize+8),(localBuffer[8+msgPayloadSize+1]*256 + localBuffer[8+msgPayloadSize])); // Checksum verification if ( do_chksum(localBuffer, 8, msgPayloadSize+8) == (localBuffer[8+msgPayloadSize+1]*256 + localBuffer[8+msgPayloadSize]) ){ // If it's OK, extract data parse_gps( gpsData_ptr ); gpsData_ptr->err_type = data_valid; //printf ("\n<GPS>: Success!"); status = 1; } else{ //printf ("\n<GPS>: Checksum mismatch!"); gpsData_ptr->err_type = checksum_err; } reset_localBuffer(); } else{ //printf ("\n<GPS>: Didn't get complete message. Tried for %d, got %d",bytesToRead,bytesRead); gpsData_ptr->err_type= incompletePacket; status = 0; } break; // end case 2 default: reset_localBuffer(); printf ("\n<GPS>: Why are you here?"); status = 0; break; // end default } // end switch (readState) } // end while (bytesReadThisCall < bytesInBuffer) // Store local buffer in gps packet gpsData_ptr->localBuffer = localBuffer; gpsData_ptr->bytesInLocalBuffer = bytesInLocalBuffer; gpsData_ptr->readState = readState; return status; }
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"); }
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; }
//=========================================================================== // 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) } } }
// How to handle static variables with multiple sensors? objects? add to gpspacket? int read_gps(struct gps *gpsData_ptr) { cyg_io_handle_t port_handle; cyg_serial_buf_info_t buff_info; unsigned int len = sizeof (buff_info); // get serial port handle cyg_io_lookup( gpsData_ptr->portName, &port_handle ); cyg_io_get_config (port_handle, CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO,\ &buff_info, &len); unsigned int bytesInBuffer = buff_info.rx_count; unsigned int bytesReadThisCall = 0; unsigned short msgPayloadSize = 0, bytesToRead = 0, bytesRead = 0; unsigned long CRC_computed, CRC_read; int j, status =0; // Initialization of persistent local buffer if (gpsData_ptr->localBuffer == NULL) { gpsData_ptr->localBuffer = (unsigned char*) malloc (1024 * sizeof (unsigned char)); } // First check if there are any bytes in the serial buffer, return if none if( bytesInBuffer == 0 ) return -1; // Get localBuffer stored in gps packet. This is to keep the following code readable localBuffer = gpsData_ptr->localBuffer; bytesInLocalBuffer= gpsData_ptr->bytesInLocalBuffer; readState = gpsData_ptr->readState; while (bytesReadThisCall < bytesInBuffer){ switch (readState){ case 0: //Look for packet header bytes // Read in up to 3 bytes to the first open location in the local buffer //fprintf(stderr,"bytesInLocalBuffer is %d\n",bytesInLocalBuffer); bytesRead = read(gpsData_ptr->port,&localBuffer[bytesInLocalBuffer],3-bytesInLocalBuffer); //fprintf(stderr,"The first three bytes are %0X %0X %0X\n",localBuffer[0],localBuffer[1],localBuffer[2]); //fprintf(stderr,"bytesRead is %d\n",bytesRead); //fprintf(stderr,"Read %d bytes, The first three bytes are %0X %0X %0X\n", bytesRead,localBuffer[0],localBuffer[1],localBuffer[2]); bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (localBuffer[0] == 0xAA){ // Check for first header byte bytesInLocalBuffer = 1; //fprintf(stderr, "case 0, 0xAA header type \n"); if (localBuffer[1] == 0x44){ // Check for second header byte bytesInLocalBuffer = 2; if (localBuffer[2] == 0x12){ // Check for third header byte bytesInLocalBuffer = 3; readState++; } } } else { gpsData_ptr->err_type = noPacketHeader; } break; // end case 0 case 1: // Look for block ID and data length // Read 28 Header Bytes bytesToRead = 28 - bytesInLocalBuffer; // Read in bytes to the last location in the local buffer bytesRead = read(gpsData_ptr->port,&localBuffer[bytesInLocalBuffer],bytesToRead); bytesInLocalBuffer += bytesRead; // keep track of bytes in local buffer bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (bytesRead == bytesToRead){ readState++; //fprintf (stderr,"<GPS>: Got msgID: %d and Data Length: %d\n", localBuffer[5]*256 + localBuffer[4], localBuffer[9]*256 + localBuffer[8]); //printf ("<GPS>: localBuffer[0] = %02X localBuffer[1] = %02X localBuffer[2] = %02X localBuffer[3] = %02X localBuffer[4] = %02X localBuffer[5] = %02X \n", localBuffer[0], localBuffer[1], localBuffer[2], localBuffer[3], localBuffer[4], localBuffer[5]); } else{ gpsData_ptr->err_type = incompletePacket; } break; // end case 1 case 2: //Read payload // Find message payload size msgPayloadSize = localBuffer[9]*256 + localBuffer[8]; // data is in little endian format // Error checking on payload size. If size is bigger than expected, dump packet if(msgPayloadSize > GPS_MAX_MSG_SIZE){ gpsData_ptr->err_type = incompletePacket; reset_localBuffer(); } // Find how many bytes need to be read for the total message (Sync (3) + Remaining Header (25) + Payload - bytes already read ) bytesToRead = msgPayloadSize + 28 - bytesInLocalBuffer; //printf("bytesInLocalBuffer is %d bytesToRead is %d \n",bytesInLocalBuffer,bytesToRead); // Read in the remainder of the message to the local buffer, starting at the first empty location bytesRead = read (gpsData_ptr->port, &localBuffer[bytesInLocalBuffer], bytesToRead); bytesInLocalBuffer += bytesRead; // keep track of bytes in local buffer bytesReadThisCall += bytesRead; // keep track of bytes read during this call if (bytesRead == bytesToRead){ //printf ("<GPS>: Got complete message! Tried for %d, got %d\n",bytesToRead,bytesRead); readState++; } else { gpsData_ptr->err_type = incompletePacket; } break; // end case 2 case 3: // read CRC bytes (4 bytes) bytesToRead = 4; bytesRead = read (gpsData_ptr->port, &localBuffer[bytesInLocalBuffer], bytesToRead); bytesInLocalBuffer += bytesRead; bytesReadThisCall += bytesRead; if(bytesRead == bytesToRead) { // CRC verification CRC_computed = CalculateBlockCRC32(bytesInLocalBuffer-4,localBuffer); endian_swap(localBuffer,140,4); CRC_read = *(uint32_t *) (localBuffer+140); if (CRC_computed == CRC_read) { gpsData_ptr->err_type = data_valid; parse_gps(gpsData_ptr); //fprintf (stderr,"<GPS t = %9.3lf>: Success!\n",gpsData_ptr->GPS_TOW); } else{ send_status("GPS CRC ERR"); //fprintf (stderr,"<GPS>: Checksum mismatch!\n"); /* ============= DEBUG CHECKSUM ERROR ================ fprintf (stderr,"<GPS %d>: Checksum mismatch! Buffer: %02X%02X%02X%02X Read: %08lX Computed: %08lX\n",localBuffer[5]*256 + localBuffer[4],localBuffer[140],localBuffer[141],localBuffer[142],localBuffer[143],CRC_read,CRC_computed); fprintf (stderr,"Hex: \n"); for (j = 0; j < bytesInLocalBuffer; j++) { fprintf(stderr,"%02X ",localBuffer[j]); if(j%8==7) fprintf(stderr,"\n"); } */ gpsData_ptr->err_type = checksum_err; } reset_localBuffer(); } else{ //printf ("\n<GPS>: Didn't get complete message. Tried for %d, got %d",bytesToRead,bytesRead); gpsData_ptr->err_type= incompletePacket; status = 0; } break; // end case 3 default: reset_localBuffer(); printf ("\n<GPS>: Why are you here?"); status = 0; break; // end default } // end switch (readState) } // end while (bytesReadThisCall < bytesInBuffer) // Store local buffer in gps packet gpsData_ptr->localBuffer = localBuffer; gpsData_ptr->bytesInLocalBuffer = bytesInLocalBuffer; gpsData_ptr->readState = readState; return status; }