Esempio n. 1
0
/*
 * 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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
/* 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;
}
Esempio n. 4
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);
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
/*
 * 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);
    }
}
Esempio n. 7
0
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);
}
Esempio n. 8
0
/* 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
}
Esempio n. 9
0
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);
}
Esempio n. 10
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;
}
Esempio n. 11
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);
}
Esempio n. 12
0
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()
Esempio n. 13
0
//===========================================================================
//                             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, "");    
        }
    }

              
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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");
    }
}
Esempio n. 16
0
//===========================================================================
//                             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");                     
}
Esempio n. 17
0
//===========================================================================
//                             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");
       }
    }              
}
Esempio n. 18
0
//===========================================================================
// 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");
}
Esempio n. 19
0
//===========================================================================
// 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, "");   
            }
        }
    }         
}
Esempio n. 20
0
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;
}
Esempio n. 21
0
//===========================================================================
//                             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");
}
Esempio n. 22
0
// 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;
}
Esempio n. 23
0
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");
}
Esempio n. 24
0
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;
}
Esempio n. 25
0
//===========================================================================
//                             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());                 
}
Esempio n. 26
0
//===========================================================================
//                            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)  
        }
        
    }
}
Esempio n. 27
0
// 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;
}