I am reading data continuously from RS 485 port by C program from a device by the following code. For some reason, obtained data is not the latest data in the device. The changes of data is not reflected when I read data, it gives me old value. After couple of minutes, I get the changed value (since I am continuously reading). If I read the same device by Pytty I get the updated value immediately. So there must be some problem in my code though I couldn't figure it out. Any help would be great!
static int load_serial_port(char *port) //port is 485, port="/dev/ttyS2"/
{
int fd = 0;
fd = open (port, O_RDWR);
if (fd < 0) {
log_error("SerialPort opening failed.");
return -1;
}
struct serial_rs485 rs485conf;
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;
/* Set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND;
/* or, set logical level for RTS pin equal to 0 when sending: */
rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
/* Set logical level for RTS pin equal to 1 after sending: */
rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
/* or, set logical level for RTS pin equal to 0 after sending: */
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
/* Set rts delay before send, if needed: */
rs485conf.delay_rts_before_send = 0;
/* Set rts delay after send, if needed: */
rs485conf.delay_rts_after_send = 0;
/* Set this flag if you want to receive data even whilst sending data */
//rs485conf.flags |= SER_RS485_RX_DURING_TX;
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
log_error("SerialPort config failed.");
return -1;
}
struct termios option;
tcgetattr(fd, &option);
cfsetospeed(&option, B9600); /* baud rate */
option.c_cflag &= ~PARENB; /* no parity */
option.c_cflag &= ~CSTOPB; /* 1 stop bit */
option.c_cflag &= ~CSIZE;
option.c_cflag |= CS8 | CLOCAL; /* 8 bits */
option.c_lflag = ICANON; /* canonical mode */
option.c_oflag &= ~OPOST; /* raw output */
tcsetattr(fd, TCSANOW, &option); /* apply the settings */
tcflush(fd, TCOFLUSH);
log_debug("SerialPort loaded fd %d", fd);
return fd;
}
Following is the read function
static void port_read(port_t *s)
{
uint8_t rxBuffer[20];
char portString[20] = "";
double value = 0.0;
if(s->serialPortFd > 0) {
int amount = read(s->serialPortFd, rxBuffer, 100);
int i = 0;
int charindex = 0;
if(amount > 1 ) {
for (i = 0; i< amount; i++) {
if ( isdigit( rxBuffer[i]) || ( (char)rxBuffer[i] == '-' || (char)rxBuffer[i] == '.') ) {
portString[charindex] = (char)rxBuffer[i];
charindex++;
}
}
portString[charindex] = '\0';
sscanf(portString, "%lf", &value); //value is same ???
}
}
memset(rxBuffer, 0, sizeof rxBuffer);
}
Sometimes I feel experts post, comment in this forum without reading questions carefully. I found the correct solution after reading and doing more experiment and that I was expecting to save time.
My reading goes fine with the following changes in my code:
int amount = read(s->serialPortFd, rxBuffer, 20);
tcflush(s->serialPortFd, TCIOFLUSH);
I was missing flashing the file.
I am using USB to Uart converter for transmission and reception for my data.
Here is my code for transmission
void main()
{
int USB = open( "/dev/ttyUSB0", O_RDWR | O_NONBLOCK | O_NDELAY);
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
/* WRITE */
unsigned char cmd[] = "YES this program is writing \r";
int n_written = 0,spot = 0;
do {
n_written = write( USB, &cmd[spot], 1 );
spot += n_written;
} while (cmd[spot-1] != '\r' && n_written > 0);
The output of my code is same as expacted
YES this program is writing
Now this is my code for reading from UART
/* READ */
int n = 0,spot1 =0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
do {
n = read( USB, &buf, 1 );
sprintf( &response[spot1], "%c", buf );
spot1 += n;
} while( buf != '\r' && n > 0);
if (n < 0) {
printf("Error reading %d %s",errno, strerror(errno));
}
else if (n==0) {
printf("read nothing");
}
else {
printf("Response %s",response);
}
}
This reading from Uart gives error from errno and it is error number 11 which says that Resource is temporary unavailable
I am getting this output
Error reading 11 Resource temporarily unavailable
I am using USB to UART converter. Hope someone could help. Thanks :)
You are getting the error code EAGAIN from your read call and this is causing you to exit your loop and print out the error. Of course EAGAIN means that this was a temporary problem (e.g. there wasn't anything to read at the time you tried to read it, perhaps you'd like to try later?).
You could restructure the read to be similar to:
n = read(USB, &buf, 1)
if (n == 0) {
break;
} else if (n > 0) {
response[spot1++] = buf;
} else if (n == EAGAIN || n == EWOULDBLOCK)
continue;
} else { /*unrecoverable error */
perror("Error reading");
break;
}
You could improve your code by making buf be an array and reading more than one character at a time. Also notice that sprintf was unnecessary, you can just copy the character(s) in to the array.
I have written code for a uPP device driver to be used with an OMAPL138 based custom board for data acquisition through a camera lens. The code for my device driver is:
/*
* A device driver for the Texas Instruments
* Universal Paralllel Port (UPP)
*
* Modified by: Ali Shehryar <github.com/sshehryar>
*
*/
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/fs.h>
#include <linux/delay.h> //for "mdelay(...)"
#include <linux/interrupt.h>
#include <linux/cdev.h>
#include <linux/moduleparam.h>
#include <mach/da8xx.h>
#include <asm/sizes.h>
#include <asm/io.h>
#include <mach/mux.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <asm/gpio.h>
//SPRUH77A.PDF, Table 12-1. The Interrupt number assigned to the UPP module.
#define UPP_INTERRUPT 91
//SPRS586D.PDF, Table 2-4
#define DA850_UPP_BASE 0x01E16000
//SPRS586D.PDF, Table 5-117. Offsets from DA850_UPP_BASE
#define UPPCR 0x00000004
#define UPDLB 0x00000008
#define UPCTL 0x00000010
#define UPICR 0x00000014
#define UPIVR 0x00000018
#define UPTCR 0x0000001C
#define UPIER 0x00000024
#define UPIES 0x00000028
#define UPIEC 0x0000002C
#define UPEOI 0x00000030
#define UPID0 0x00000040
#define UPID1 0x00000044
#define UPID2 0x00000048
#define UPIS0 0x00000050
#define UPIS1 0x00000054
#define UPIS2 0x00000058
//SPRS586D.PDF, Table 2-4
#define DA850_PSC1_BASE 0x01E27000
//SPRUH77A.PDF, Table 9-7.
//"Power and Sleep Controller 1" (PSC1) Revision ID Register.
#define PSC_REVID 0x00000000
//SPRUH77A.PDF, Table 9-7.
//"Power Domain Transition Status" Register.
#define PSC_PTSTAT 0x00000128
//SPRUH77A.PDF, Table 9-2, Table 9-7.
//NOTE that in Table 9-2, UPP module has an LPSC number of 19...
#define PSC1_MDCTL_19 0x00000A4C //0xA00 + (19*4).
//SPRUH77A.PDF, Table 9-7.
//"Power Domain Transition Command Register" Register.
#define PSC_PTCMD 0x00000120
//DMA Status Register bitmasks used in the ISR handler....
#define EOLI 16
#define EOWI 8
#define ERRI 4
#define UORI 2
#define DPEI 1
#define UPIES_MASK 0x0000001F
///#define UPIES_MASK 0x1717 ---> Reverted back to 1717 because Window interrupt is not used, for now its useless
//To Enable all interrupts ---> #define UPIES_MASK 0x1F1F
/// Shehryar: These Parameters are to be modified and tweaked according to reqirements in realtime.
//The DMA PARAMETERS
#define UPP_BUF_SIZE 8192 //Need to lookup for an exact val (changed from 8192 on 2 DEc 14)
#define UPP_RX_LINE_COUNT 8 //Changed from 8
#define UPP_RX_LINE_SIZE 1024
#define UPP_RX_LINE_OFFSET 1024 //value changed from 1024 to 0 on 2 DEC 2014
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//MODIFIED BY: SHEHRYAR ---> Pg 888 General-Purpose Input/Output (GPIO) SPRUH82A–December 2011. Added 25-Nov-2014
#define DA850_GPIO_BASE 0x01E26000
//------------------------------------- 9/12/2014-----------------
//#define MY_BUFFER_SIZE 1048756
//----------------------------------------------------------------
//MODIFIED BY: SHEHRYAR. Offsets from GPIO_Base (SPRS653C.PDF TABLE 5-134)
#define DIR67 0x00000088
#define OUT_DATA67 0x0000008C
#define SET_DATA67 0x00000090
#define CLR_DATA67 0x00000094
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void *rxBuf;
static void __iomem *pinmux_base = 0;
static void __iomem *upp_base = 0;
static void __iomem *psc1_base = 0;
static void __iomem *gpio_base = 0;
static DECLARE_WAIT_QUEUE_HEAD(read_queue);
static int32_t read_pending = 0; // changed from static int
//set to '1' when loading this module to use the Digital Loopback (DLB)
//features,e.g:"insmod UPP_driver.ko loopbackMode=1"
static int loopbackMode = 0;
module_param( loopbackMode, int, S_IRUGO);
int EOWI_Count = 0; int UORI_count =0;
///////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////INTERRUPT SERVICE ROUTINE//////////////////////////////////////
//////////////////////////////////////SPRUH82A–December 2014 PAGE 1515////////////////////////////////
//SPRUGJ5B.PDF, Section 2.6.4
static irqreturn_t upp_ISR_handler(int irq, void *dev_id)
{
uint32_t regVal, status;
if (pinmux_base == 0)
{
return IRQ_HANDLED;
}
status = ioread32( upp_base + UPIER );
while (status & 0x0000001F ) //0x1F1F is an interrupt bit-mask
{
//
//DMA Channel I (Channel A), Receiving data (We Need A (DMA Ch I ) to Rx Data instead of Tx ; 27th Nov 2014 - 10:38am)
//
if (status & EOLI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(EOLI, upp_base + UPIER );
//printk(KERN_INFO "DMA: EOLI\n");
//printk(KERN_INFO "DMA:EOLI. UPP_RX_LINE_SIZE[%d] UPP_RX_LINE_OFFSET[%d] UPP_RX_LINE_COUNT[%d] \n", UPP_RX_LINE_SIZE,UPP_RX_LINE_OFFSET,UPP_RX_LINE_COUNT );
//dump_Channel_regs();
}
if (status & EOWI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
//printk(KERN_INFO "DMA: EOWI\n");
iowrite32(EOWI, upp_base + UPIER );
read_pending = 8192;
wake_up_interruptible(&read_queue);
//add 1 to EOWI counter
EOWI_Count += 1;
// dump_Channel_regs();
}
if (status & ERRI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(ERRI, upp_base + UPIER );
//dump_Channel_regs();
}
if (status & UORI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(UORI, upp_base + UPIER );
UORI_count +=1;
//dump_Channel_regs();
}
if (status & DPEI)
{
//Clear the interrupt. WRITING ZERO to any other bit has NO effect,
//per SPRUH77A.PDF, section 33.3.9.
iowrite32(DPEI, upp_base + UPIER );
//dump_Channel_regs();
}
//read again, and process if necessary.
status = ioread32( upp_base + UPIER );
}
//Clear UPEOI to allow future calls to this function.
regVal = ioread32( upp_base + UPEOI);
regVal &= 0xFFFFFF00;
regVal = 0;// End of Interrupt
iowrite32(regVal, upp_base + UPEOI);
return IRQ_HANDLED;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void pin_mux_set( int index, unsigned int bits )
{
static DEFINE_SPINLOCK(mux_spin_lock);
unsigned long flags;
unsigned int offset;
if ((index < 0) || (index > 19))
{
printk(KERN_INFO "pin_mux_set:index is out of range.\n");
return;
}
if (!pinmux_base)
{
//SRPUH77A.PDF,Table 11-3
if ((pinmux_base = ioremap(DA8XX_SYSCFG0_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "pin_mux_set:Cannot fetch pinmux_base.\n");
return;
}
}
offset = 0x120 + (index * 4);
spin_lock_irqsave(&mux_spin_lock, flags);
iowrite32(bits, pinmux_base + offset);
spin_unlock_irqrestore(&mux_spin_lock, flags);
//NOTE: do NOT "iounmap" the pinmux_base pointer, as it is used
// in the ISR_handler.....
}
static void upp_pin_mux_init(void)
{
pin_mux_set( 13, 0x44440000 );
pin_mux_set( 14, 0x44444480 );
pin_mux_set( 15, 0x44444444 );
pin_mux_set( 16, 0x44444444 );
pin_mux_set( 17, 0x44444444 );
pin_mux_set( 18, 0x00444444 );
pin_mux_set( 19, 0x08888800 );
//pin_mux_print() ;
}
//SPRUGJ5B.PDF, Section 2.6.1.2.
static void upp_power_and_clocks( void )
{
/*
* Refer to:
* * Power and Sleep Controller (PSC), Chapter 9 in the TRM(SPRUH77A.PDF)
* * Device Clocking, Chapter 7 (esp Section 7.3.5) in the TRM.
*
*
*/
int regVal;
if (!psc1_base)
{
if ((psc1_base = ioremap(DA850_PSC1_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "upp_power_and_clocks:Cannot fetch psc1_base.\n");
return;
}
}
regVal = ioread32(psc1_base + PSC_REVID);
//PSC Revision ID should be "44825A00" per SPRUH77A.PDF, section 9.6.1
if (regVal == 0x44825A00)
{
printk( KERN_INFO "PSC_REVID = 0x%08X....OK\n", regVal);
}
else
{
printk( KERN_INFO "********ERROR: PSC_REVID = 0x%08X********\n", regVal);
}
// SPRUH77A.PDF, 9.3.2.1, Table 9-6, 9.6.10
// wait for GOSTAT[0] in PSTAT to clear to 0 ("No transition in progress")
while ( ioread32(psc1_base + PSC_PTSTAT) & 0x00000001 )
;
//
//SPRUH77A.PDF, 9.3.2.2, 9.6.19.
//Set NEXT bit in MDCTL19 to Enable(3h).
regVal = ioread32( psc1_base + PSC1_MDCTL_19 );
regVal |= 0x00000003;
iowrite32(regVal, psc1_base + PSC1_MDCTL_19);
//
//SPRUH77A.PDF, 9.3.2.3, 9.6.9.
//Set the GO[0] bit in PTCMD to 1 to initiate power-domain transition
regVal = ioread32(psc1_base + PSC_PTCMD);
regVal |= 0x00000001;
iowrite32(regVal, psc1_base + PSC_PTCMD);
//
// SPRUH77A.PDF, 9.3.2.4
// Wait for GOSTAT[0] in PTSTAT to clear to 0
while ( ioread32(psc1_base + PSC_PTSTAT) & 0x00000001 )
;
iounmap( psc1_base );
psc1_base = 0;
}
//SPRUGJ5B.PDF, Section 2.6.1.3, 2.6.1.4
static void upp_swrst( void )
{
int32_t reg_val;
if (!upp_base)
{
if ((upp_base = ioremap(DA850_UPP_BASE, SZ_4K)) == 0)
{
printk(KERN_INFO "upp_swrst:Cannot fetch upp_base.\n");
return;
}
}
//Fetch the UPP ID for the sake of sanity....Should be "44231100"
reg_val = ioread32( upp_base + 0 );
if (reg_val == 0x44231100 )
{
printk(KERN_INFO "UPP_UPPID = 0x%08X....OK\n", reg_val);
}
else
{
printk( KERN_INFO "********ERROR: UPP_UPPID = 0x%08X********\n", reg_val);
}
// SPRUH77A.PDF, Section 33.2.7.1.1, Table 33-12.
// clear EN bit of UPPCR to (temporarily) disable the UPP.
reg_val = ioread32( upp_base + UPPCR );
reg_val &= ~(1 << 3); //0xfffffff7;
iowrite32( reg_val, upp_base + UPPCR );
// SPRUH77A.PDF, Section 33.2.7.1.2, Table 33-12.
//poll "DMA Burst" (DB) bit of UPPCR to ensure DMA controller is idle
while ( ioread32( upp_base + UPPCR ) & (1 << 7) )
;
// SPRUH77A.PDF, Section 33.2.7.1.3, Table 33-12.
// assert SWRST bit (bit 4) of UPPCR
reg_val = ioread32( upp_base + UPPCR );
reg_val |= 0x00000010;
iowrite32( reg_val, upp_base + UPPCR );
//
// wait at least 200 clock cycles
// (SPRUGJ5B.PDF, 2.6.1.4)
mdelay( 200 ); // abitrary choice of 200ms
// SPRUH77A.PDF, Section 33.2.7.1.4 --AND--
// SPRUGJ5B.PDF, 2.6.1.4
// clear SWRST bit (bit 4) of UPPCR
reg_val = ioread32( upp_base + UPPCR );
reg_val &= 0xffffffef;
iowrite32( reg_val, upp_base + UPPCR );
}
//SPRUGJ5B.PDF, Section 2.6.1.5
static void upp_config( void )
{
int32_t regVal;
//-------------------------------------------------------------------------
// UPPCTL - UPP Interface Channel Settings....SPRUH77A.PDF, Section 33.3.4.
//
// - DATA and XDATA Pin assignments to Channels A & B:
// Refer to SPRUGJ5B.PDF, Table 3:
//
// ____PHYSICAL_PINS___|____CHANNEL_ASSIGNMENT___
// * DATA[7:0] | A[7:0]
// * DATA[15:8] | B[7:0]
//-------------------------------------------------------------------------
regVal = 0;
regVal |= 1 << 17; // IWA - CHANNEL A 8/16bit MODE: Set Channel A to 16 bit mode
iowrite32( regVal, upp_base + UPCTL );
//-------------------------------------------------------------------------
// UPPICR - signal enable, signal inversion, clk div (tx only), etc.
// SPRUH77A.PDF, Section 33.3.5
//-------------------------------------------------------------------------
regVal = 0; //Channel A: START is active-high
regVal |= 1<<3; //Channel A:STARTA is honored in Rev Mode
regVal |= 1<<4; //Channel A:ENABLEA is honored in Rev Mode
regVal |= 1<<12; //Channel A:(CLKINVA) Signal on rising edge of clock
regVal |= 1<<13; //Channel A:(TRISA) pins are High-impedence while idle
iowrite32( regVal, upp_base + UPICR );
//-------------------------------------------------------------------------
// UPPIVR - Idle Value Register
// SPRUH77A.PDF, Section 33.3.5
//-------------------------------------------------------------------------
regVal = 0;
regVal |= 0xab00; //Channel B Idle Value
regVal |= 0x00cd; //Channel A Idle Value
iowrite32( regVal, upp_base + UPIVR );
//-------------------------------------------------------------------------
// UPTCR - i/o tx thresh (tx only), dma read burst size
//-------------------------------------------------------------------------
regVal = 0x00000003; //DMA Channel I READ-threshold. 256 bytes (max)
iowrite32(regVal, upp_base + UPTCR );
}
//SPRUGJ5B.PDF, Section 2.6.1.6
static void upp_interrupt_enable( void )
{
int32_t regVal, status;
// Register the ISR before enabling the interrupts....
status = request_irq( UPP_INTERRUPT, upp_ISR_handler, 0, "upp_ISR", 0 );
if( status < 0 )
{
return;
}
// clear all interrupts
iowrite32( UPIES_MASK, upp_base + UPIEC );
//------------------------------------------------------------------------
//Dumping Registers again for debugging purpose
//dump_Channel_regs();
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// UPIES - Interrupt Enable. Interrupt events will generate a CPU interrupt
//-------------------------------------------------------------------------
// regVal = 0x17; //Enable ALL interrupts (but EOWI) for DMA Channel I
//regVal |= 0x17 << 8; //Enable ALL interrupts (but EOWQ) for DMA Channel Q
regVal = UPIES_MASK;
iowrite32( regVal, upp_base + UPIES );
}
//SPRUGJ5B.PDF, Section 2.6.1.7
static void upp_enable( void )
{
int32_t reg_val;
// set EN bit in UPPCR.
// The EN bit (effectively disabling the UPP peripheral)...
// was cleared in "upp_swrst()" function
reg_val = ioread32( upp_base + UPPCR );
reg_val |= 1 << 3;
iowrite32( reg_val, upp_base + UPPCR );
}
static void upp_disable( void )
{
int32_t reg_val;
reg_val = ioread32( upp_base + UPPCR );
reg_val &= ~(1 << 3); //0xfffffff7;
iowrite32( reg_val, upp_base + UPPCR );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////MODIFIED BY: SHEHRYAR ; 25-NOV-2014 4:40pm PST (+5.00 GMT)///////////////////
static void setpin_GPIO (void)
{
int32_t reg_val=0;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//reg_val = ioread32(gpio_base + SET_DATA67);
reg_val |= (1<<6); ///Set Pin 6 of Bank 6 GP6P6 to 1 to drive GPIO high
iowrite32(reg_val,gpio_base + SET_DATA67);
}
static void clrpin_GPIO(void)
{
int32_t reg_val=0;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//reg_val = ioread32(gpio_base + CLR_DATA67);
/*reg_val |= ~(1<<0);
reg_val |= ~(1<<1);
reg_val |= ~(1<<2);
reg_val |= ~(1<<3);
reg_val |= ~(1<<4);*/
reg_val |= (1<<6); //Set Pin 6 of bank 6 GP6P6 of CLR_DATA67 Register to High to drive GPIO signals low
iowrite32(reg_val,gpio_base + CLR_DATA67);
}
///////Function to set DIR to 1 for GP6P5//////////////////////////////////////////////////////////////
static void Config_GPIO(void)
{
int32_t reg_val;
if ((gpio_base = ioremap(DA850_GPIO_BASE, SZ_4K)) == 0)
{
return;
}
//set dir
reg_val = ioread32(gpio_base + DIR67);
reg_val &= ~(1<<0);
reg_val &= ~(1<<1);
reg_val &= ~(1<<2);
reg_val &= ~(1<<3);
reg_val &= ~(1<<4);
reg_val &= ~(1<<6);
iowrite32(reg_val,gpio_base + DIR67);
printk(KERN_INFO "DIR67 => [0x%08X]\n", reg_val);
//set to high
reg_val = ioread32(gpio_base + SET_DATA67);
reg_val |= (1<<0);
reg_val |= (1<<1);
reg_val |= (1<<2);
reg_val |= (1<<3);
reg_val |= (1<<4);
iowrite32(reg_val,gpio_base + SET_DATA67);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
//SPRUGJ5B.PDF, Section 2.6.1.8
// Return false on error
static bool upp_mem_alloc( void )
{
//rxBuf2 = kcalloc( 1 , UPP_BUF_SIZE, GFP_KERNEL | GFP_DMA );
rxBuf = kcalloc( 1 , UPP_BUF_SIZE, GFP_KERNEL | GFP_DMA );
if (!rxBuf) //|| (!rxBuf2)
{
return false;
}
return true;
}
static void upp_program_DMA_channelA( void )
{
while ( ioread32( upp_base + UPIS2 ) & 0x00000002 );
//------------------------------------------------------------------------
// Channel A (Rx), (DMA Channel I) //27th Nov 2014 - 11:08 am
//------------------------------------------------------------------------
iowrite32( rxBuf, upp_base + UPID0);
iowrite32( ( (UPP_RX_LINE_COUNT << 16) | UPP_RX_LINE_SIZE ), upp_base + UPID1);
iowrite32( UPP_RX_LINE_OFFSET, upp_base + UPID2);
}
//------------------------------------------------------------------------
// User-mode functions read/write/open/close, etc.
//------------------------------------------------------------------------
int upp_open( struct inode *iPtr, struct file *fPtr )
{
int minor,major;
read_pending = 0;
minor=iminor(iPtr);
major=imajor(iPtr);
printk( KERN_INFO "upp_open: MAJOR(%d), MINOR(%d)\n", major, minor);
upp_disable();
upp_enable();
return 0;
}
////////////////////////////////////////////////////////////READ FUNCTION STARTS HERE!!!!!!////
/*-------------------------------------------------------------------------------------------*/
//int count_missing_data=0;
//static int read_flag =0;
ssize_t upp_read( struct file *fPtr, char __user *buffer, size_t size, loff_t *offset )
{
int readBytes = 0;
int retVal=0;
void *bPtr = (void *)buffer;
if (!bPtr) {return -1; printk(KERN_INFO "ERROR: bPtr not initilized\n");}
printk(KERN_INFO "Reading %d Bytes ...\n",size );
while (readBytes<size)
{
//read_flag+=1;
read_pending = 0;
//mdelay(10);
memset(rxBuf,255,8192);
//memset(rxBuf2,128,8192);
upp_program_DMA_channelA();
clrpin_GPIO();
wait_event_interruptible( read_queue, read_pending > 0 );
while ( ioread32( upp_base + UPIS2 ) & 0x00000001 )
{
printk (KERN_INFO "DMA IS STILL ACTIVE! \n");
}
setpin_GPIO(); // Set High
retVal = copy_to_user(bPtr,rxBuf,read_pending);
if(retVal)
{
printk(KERN_INFO "ERROR: Copy to user failed!\n");
return readBytes;
}
readBytes += read_pending;
bPtr += 8192;
} //end of while loop
printk(KERN_INFO"\nRead [%d] Bytes.\n",readBytes);
printk(KERN_INFO"END OF WINDOW (EOWI) INTERRUPT Count = [%d]\n", EOWI_Count);
printk(KERN_INFO"DMA UNDERRUN OR OVERFLOW (UORI) Interrupt Count = %d\n", UORI_count);
return readBytes;
//read_flag += 1;
//mdelay(9);
}
//////////////////////////////////////////////READ() FUNCTION ENDS HERE!!!!!!///////////////////////////
/*---------------------------------------------------------------------------------------------------*/
int upp_release( struct inode *iPtr, struct file *fPtr )
{
return 0;
printk(KERN_INFO "upp_release completed.\n");
}
static struct cdev *UPP_cdev;
static dev_t UPP_MajorMinorNumbers;
struct file_operations upp_fops = {
.owner = THIS_MODULE,
//.llseek = no_llseek,
//.poll = upp_poll,
.read = upp_read,
//.write = upp_write,
//.ioctl = upp_ioctl,
.open = upp_open,
//.release = upp_release,
};
/*
* Return ZERO on success.
*
*/
static int __init upp_init(void)
{
int retVal;
//printk(KERN_INFO "Entering upp_init().\n");
//SPRUGJ5B.PDF, Section 2.6.1.8
// I'm doing this out-of-order...If the mem-allocation fails,
// there is no sense in doing anything else, except to bail early...
if (upp_mem_alloc() == false)
{
printk(KERN_INFO "******ERROR: Could not allocate buffers. Bailing!******\n");
return -1;
}
//--------------------------------------------------------
//--------------------------------------------------------
//SPRUGJ5B.PDF, Section 2.6.1.1
upp_pin_mux_init();
printk(KERN_INFO "upp_pin_mux_init()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.2.
upp_power_and_clocks();
printk(KERN_INFO "upp_power_and_clocks()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.3, 2.6.1.4
upp_swrst();
printk(KERN_INFO "upp_swrst()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.5
upp_config();
printk(KERN_INFO "upp_config()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.6
upp_interrupt_enable();
printk(KERN_INFO "upp_interrupt_enable()...OK.\n");
//SPRUGJ5B.PDF, Section 2.6.1.7
upp_enable();
printk(KERN_INFO "upp_enable()...OK.\n");
//---------------------------SETTING GPIOS----------------
Config_GPIO();
//--------------------------------------------------------
setpin_GPIO(); // Set High
UPP_MajorMinorNumbers = MKDEV( 0, 0);
if ( (retVal = alloc_chrdev_region( &UPP_MajorMinorNumbers, 0, 1, "UPP" )) < 0)
{
printk(KERN_INFO "ERROR: Major/Minor number allocation failed.\n");
return retVal;
}
UPP_cdev = cdev_alloc();
UPP_cdev->ops = &upp_fops;
UPP_cdev->owner = THIS_MODULE;
if (cdev_add( UPP_cdev, UPP_MajorMinorNumbers, 1) != 0)
{
printk(KERN_INFO "ERROR: UPP driver NOT loaded. CDEV registration failed.\n");
}
else
{
printk(KERN_INFO "\nUPP Major: %d , Minor: %d \n", MAJOR(UPP_MajorMinorNumbers), MINOR(UPP_MajorMinorNumbers));
}
printk("UPP driver (1.8.0 - 5/January/2015) succesfully installed.\n");
return 0;
}
/*
*
*
*
*/
static void __exit upp_exit(void)
{
uint32_t regVal;
printk(KERN_INFO "Exiting..Initializing upp_exit call......\n");
// SPRUH77A.PDF, Section 33.2.7.1.1, Table 33-12.
// clear EN bit of UPPCR to disable the UPP.
regVal = ioread32( upp_base + UPPCR );
regVal &= 0xfffffff7;
iowrite32( regVal, upp_base + UPPCR );
free_irq( UPP_INTERRUPT, 0);
if (rxBuf)
{
kfree( rxBuf );
rxBuf = 0;
}
/*if (rxBuf2)
{
kfree(rxBuf2);
rxBuf2=0;
}*/
cdev_del( UPP_cdev );
unregister_chrdev_region( UPP_MajorMinorNumbers, 1);
clrpin_GPIO(); //added 2-Dec-2014
printk(KERN_INFO "UPP driver unloaded (Successful Exit). \n");
}
MODULE_AUTHOR("Ali Shehryar & Umair Ali");
MODULE_DESCRIPTION("OMAP-L138/AM-1808 UPP bus driver");
MODULE_LICENSE("GPL");
module_init(upp_init)
module_exit(upp_exit)
With the code, I have made a tester application that writes a .264 based output file consisting of data acquired from my custom board which I call upp_tester.cpp :
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <string.h>
int main(int argc, char **argv )
{
int count = 0;
const int BytesToRead = 8192*4; //32kB
int bytesRead = -1;
int bytesWritten = -1 ;
int upp_fd,out_fd;
char readBuff[BytesToRead] = {0,};
int k = 0;
readBuff[BytesToRead]={'\0'};
upp_fd = open( "/dev/upp", O_RDWR);
out_fd = open( "output_upp.264", O_RDWR|O_CREAT);
for(count = 0; count<100; count++)
{
if (upp_fd == -1)
{
fprintf( stderr , "OPEN failed [%d] - UPP\n" , errno );
if (errno == 2)
{
fprintf( stderr , "NOTE! Check that /dev/upp actually exists, and has the right permissions \n");
}
return errno;
}
if (out_fd == -1)
{
fprintf( stderr , "OPEN /output_upp failed [%d] - Out.dat\n" , errno );
}
//fprintf( stderr , "UPP TESTER Version 1.0.17\n\n" );
for (k=0;k<32;k++)
{
bytesRead = read( upp_fd, readBuff, sizeof (readBuff));
fprintf( stderr , "READ [%d] bytes out of [%d] bytes\n" , bytesRead , sizeof(readBuff) );
bytesWritten = write( out_fd, readBuff, bytesRead );
fprintf( stderr , "WROTE [%d] bytes out of [%d] bytes\n" , bytesWritten , sizeof(readBuff) );
}
}
close(upp_fd);
close(out_fd);
return 0;
}
Now when I explore the output file, I see that a lot of bytes are missing which I usually set to 255 using memset. This is because the core I have programmed for my dsp processor for the tester file is set to throw fixed data from 0-99. What could be causing this problem. I am a total newbie to device drivers and kernel level programming so any help would be deeply appreciated.
In case you would like to submit the driver to upstream (which actually a right way to go), you probably may contact with TI guys who are working with DaVinci boards. I assume you already googled the link DaVinci Wiki.
Regarding to your driver it's hard to check due to its code style. Moreover you may check modern kernel APIs for stuff you are trying to program manually (voltage regulators, clocks, pin control, and so on). For many basic devices there are already drivers and setup. Also you have to describe you board configuration in device tree. Usually it means to create an additional (to the common) piece of configuration and put it under arch/arm/boot/dts/. There you may find da850 predefined data bases.
I'm trying to send/receive data over an USB Port using FTDI, so I need to handle serial communication using C/C++. I'm working on Linux (Ubuntu).
Basically, I am connected to a device which is listening for incoming commands. I need to send those commands and read device's response. Both commands and response are ASCII characters.
Everything works fine using GtkTerm but, when I switch to C programming, I encounter problems.
Here's my code:
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
/* Open File Descriptor */
int USB = open( "/dev/ttyUSB0", O_RDWR| O_NONBLOCK | O_NDELAY );
/* Error Handling */
if ( USB < 0 )
{
cout << "Error " << errno << " opening " << "/dev/ttyUSB0" << ": " << strerror (errno) << endl;
}
/* *** Configure Port *** */
struct termios tty;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( USB, &tty ) != 0 )
{
cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << endl;
}
/* Set Baud Rate */
cfsetospeed (&tty, B9600);
cfsetispeed (&tty, B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_lflag = 0; // no signaling chars, no echo, no canonical processing
tty.c_oflag = 0; // no remapping, no delays
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
tty.c_iflag &= ~(IXON | IXOFF | IXANY);// turn off s/w flow ctrl
tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
tty.c_oflag &= ~OPOST; // make raw
/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0)
{
cout << "Error " << errno << " from tcsetattr" << endl;
}
/* *** WRITE *** */
unsigned char cmd[] = {'I', 'N', 'I', 'T', ' ', '\r', '\0'};
int n_written = write( USB, cmd, sizeof(cmd) -1 );
/* Allocate memory for read buffer */
char buf [256];
memset (&buf, '\0', sizeof buf);
/* *** READ *** */
int n = read( USB, &buf , sizeof buf );
/* Error Handling */
if (n < 0)
{
cout << "Error reading: " << strerror(errno) << endl;
}
/* Print what I read... */
cout << "Read: " << buf << endl;
close(USB);
What happens is that read() returns 0 (no bytes read at all) or block until timeout (VTIME). I'm assuming this happens because write() does not send anything. In that case, device wouldn't receive command and I cannot receive response. In fact, turning off the device while my program is blocked on reading actually succeded in getting a response (device sends something while shutting down).
Strange thing is that adding this
cout << "I've written: " << n_written << "bytes" << endl;
right after write() call, I receive:
I've written 6 bytes
which is exactly what I expect. Only my program doesn't work as it should, like my device cannot receive what I'm actually writing on port.
I've tried different things and solution, also regarding data types (I've tried using std::string, such as cmd = "INIT \r" or const char) but nothing really worked.
Can someone tell me where I'm wrong?
Thank you in advance.
EDIT:
Previously version of this code used
unsigned char cmd[] = "INIT \n"
and also cmd[] = "INIT \r\n". I changed it because command sintax for my device is reported as
<command><SPACE><CR>.
I've also tried avoiding the O_NONBLOCK flag on reading, but then I only block until forever. I've tried using select() but nothing happens. Just for a try, I've created a waiting loop until data is avaliable, but my code never exit the loop. Btw, waiting or usleep() is something I need to avoid. Reported one is only an excerpt of my code. Complete code needs to work in a real-time environment (specifically OROCOS) so I don't really want sleep-like function.
I've solved my problems, so I post here the correct code in case someone needs similar stuff.
Open Port
int USB = open( "/dev/ttyUSB0", O_RDWR| O_NOCTTY );
Set parameters
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( USB, &tty ) != 0 ) {
std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
}
/* Save old tty parameters */
tty_old = tty;
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0) {
std::cout << "Error " << errno << " from tcsetattr" << std::endl;
}
Write
unsigned char cmd[] = "INIT \r";
int n_written = 0,
spot = 0;
do {
n_written = write( USB, &cmd[spot], 1 );
spot += n_written;
} while (cmd[spot-1] != '\r' && n_written > 0);
It was definitely not necessary to write byte per byte, also int n_written = write( USB, cmd, sizeof(cmd) -1) worked fine.
At last, read:
int n = 0,
spot = 0;
char buf = '\0';
/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);
do {
n = read( USB, &buf, 1 );
sprintf( &response[spot], "%c", buf );
spot += n;
} while( buf != '\r' && n > 0);
if (n < 0) {
std::cout << "Error reading: " << strerror(errno) << std::endl;
}
else if (n == 0) {
std::cout << "Read nothing!" << std::endl;
}
else {
std::cout << "Response: " << response << std::endl;
}
This one worked for me. Thank you all!
Some receivers expect EOL sequence, which is typically two characters \r\n, so try in your code replace the line
unsigned char cmd[] = {'I', 'N', 'I', 'T', ' ', '\r', '\0'};
with
unsigned char cmd[] = "INIT\r\n";
BTW, the above way is probably more efficient. There is no need to quote every character.
1) I'd add a /n after init. i.e. write( USB, "init\n", 5);
2) Double check the serial port configuration. Odds are something is incorrect in there. Just because you don't use ^Q/^S or hardware flow control doesn't mean the other side isn't expecting it.
3) Most likely: Add a "usleep(100000); after the write(). The file-descriptor is set not to block or wait, right? How long does it take to get a response back before you can call read? (It has to be received and buffered by the kernel, through system hardware interrupts, before you can read() it.) Have you considered using select() to wait for something to read()? Perhaps with a timeout?
Edited to Add:
Do you need the DTR/RTS lines? Hardware flow control that tells the other side to send the computer data? e.g.
int tmp, serialLines;
cout << "Dropping Reading DTR and RTS\n";
ioctl ( readFd, TIOCMGET, & serialLines );
serialLines &= ~TIOCM_DTR;
serialLines &= ~TIOCM_RTS;
ioctl ( readFd, TIOCMSET, & serialLines );
usleep(100000);
ioctl ( readFd, TIOCMGET, & tmp );
cout << "Reading DTR status: " << (tmp & TIOCM_DTR) << endl;
sleep (2);
cout << "Setting Reading DTR and RTS\n";
serialLines |= TIOCM_DTR;
serialLines |= TIOCM_RTS;
ioctl ( readFd, TIOCMSET, & serialLines );
ioctl ( readFd, TIOCMGET, & tmp );
cout << "Reading DTR status: " << (tmp & TIOCM_DTR) << endl;
I have a one line serial communication interface, and the problem is that I send in 01010101 and the echo that I receive is 8 out of 10 times 01010101 but 2 out of 10 I receive 01110101.
Code example:
void checkVersion(int fd) {
tcflush(fd, TCIFLUSH);
unsigned char checkVersion[] = {0x55, 0x02, 0x00, 0x02};
int n = write(fd, &checkVersion, 4); //Send data
if (n < 0) cout << "BM: WRITE FAILED" << endl;
char read_bytes[10] = {0};
char c;
int aantalBytes = 0;
bool foundU = false;
int res;
while (aantalBytes < 7) {
res = read(fd, &c, 200);
if (res != 0) {
cout << "Byte received: " << bitset < 8 > (c) << endl;
if (c == 'U')foundU = true;
if (foundU)
read_bytes[aantalBytes++] = c;
}
if (aantalBytes > 2 && !foundU) break;
}
if (!foundU) checkVersionSucceeded = false;
if (read_bytes[aantalBytes - 3] == 0x02 && read_bytes[aantalBytes - 2] == 0x04 && read_bytes[aantalBytes - 1] == 0x06)
cout << "BM Version 4" << endl;
}
How I configure my port:
int configure_port(int fd) // configure the port
{
struct termios port_settings; // structure to store the port settings in
cfsetispeed(&port_settings, B9600); // set baud rates
cfsetospeed(&port_settings, B9600);
port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
return (fd);
}
What is the problem? How is it possible that the echo is mixed up 2 out 10 times?
Perhaps you should try the function bzero() when you configure the connection.
bzero(&port_settings, sizeof (port_settings));
This clears the struct for new port settings, which might help to stop the irregular answers you receive over the serial port.