EmbDev.net

Forum: ARM programming with GCC/GNU tools newlib lpc nonblocking read using interrupt driven UART


von Em H. (e_han)


Rate this post
useful
not useful
I am trying to resurrect an old olimex lpc2124 board with some code 
written using the WinARM and newlib lpc library. It is 5 year old code 
and I am running into a problem with the interrupts and UART serial 
reading. The main loop will run, but it gets stuck at read until I enter 
a character into the serial interface using putty. How can I make read 
non-blocking? I thought I set it up to do that using the newlib-lpc 
ioctl function. Does this not work?

I know that there used to be some race condition with the UART in the 
old newlib-lpc, but I have the newest version of WinARM so I thought 
that was taken car of. Could there be some other race condition I am 
getting? Or is it just read that is messing things up?

All of the code is below. If something isn't clear let me know and I'll 
update it!

Thanks


My main function has a loop the runs every so often using a regular 
timer interrupt
1
  while(1){
2
    IOSET = 1<<12;
3
    testCounter++;
4
    if(flags&PERIODIC)
5
    {
6
     
7
      IOCLR = 1<<13;
8
      ic=changeCircle();
9
      fUpdate(ic, 0, filterParams, &(Encoder[0]));
10
      Simulate(&(Circle[0]), &(simParams[0]), &(simState[0]), &(Encoder[0]), fParams->count_scale, 6);
11
      
12
      fUpdate(ic, 1, fParams, &(Encoder[1]));
13
      Simulate(&(Circle[1]), &(simParams[1]), &(simState[1]), &(Encoder[1]), fParams->count_scale, 4);
14
      
15
      
16
      flags &= ~PERIODIC;
17
      IOSET = 1<<13;
18
       
19
   }
20
   if(testCounter==900000)
21
   {
22
    nonblocking_function(&is);
23
    iprintf("PERIODIC = %1d\r\n", PERIODIC);
24
    testCounter = 0;
25
   }

nonblocking_function just calls read()
1
void nonblocking_function()
2
{
3
  int havechar;
4
  int charWaiting = 0;
5
  char inchar;
6
  char *ret;
7
  character = read(fileno(stdout), &inchar, 1);
8
}

I initialize the stdout out to be non blocking here
1
void initializeInterface(struct InterfaceState *is)
2
{
3
  int blocking,i;
4
5
   /* set non-blocking io */
6
  fcntl(fileno(stdout), F_SETFL, O_NONBLOCK);
7
  fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
8
  write(fileno(stdout),"\r\n> ",4);
9
  blocking=BLOCKING_IO_NO;
10
  ioctl( fileno(stdout), BLOCKING_SETUP, &blocking);
11
  is->flags=0;
12
  is->inputpos=0;
13
  is->expectcount=0;
14
  for(i=0;i<MAX_STRUCTS+1;i++){
15
    structs[i]=NULL;
16
  }
17
  is->structs=structs;
18
}

Here is the uart initizlization
1
const struct device_table_entry *device_table[] = {
2
  &com1_int,  /* stdin  */
3
  &com1_int,  /* stdout */
4
  &com1_int,  /* stderr */
5
  0 };  /* end of list */
6
7
void ioInit(void)
8
{
9
  struct serial_param sp;
10
  struct interrupt_param irq;
11
12
  /* Desired serial line characteristics 115200,n81      */
13
  sp.baud   = 115200uL;
14
  sp.length = UART_WORD_LEN_8;
15
  sp.parity = UART_PARITY_NONE;
16
  sp.stop   = UART_STOP_BITS_1;
17
  /*  Set up serial port to desired rate.       */
18
  ioctl( fileno(stdout), UART_SETUP, &sp);
19
20
  /* configure uart interrupt */
21
  irq.FIQ = 0;
22
  irq.pri = (INT_PRIORITY)10;
23
  ioctl( fileno(stdout), INTERRUPT_SETUP, &irq);
24
  //printf("irqmask: %f", IRQ_MASK);
25
26
  /* LEDs are output */
27
  IO0DIR |= (1<<12)|(1<<13);
28
29
  /* LEDs off */
30
  IOSET  = (1<<12)|(1<<13);
31
}

Here is the periodic timer initialization
1
void PeriodicInterrupt(void)
2
{
3
  flags |= PERIODIC;
4
  T1IR = 0x0f; //Clear all match interrupts
5
  VICVectAddrRead = 0x0ul;
6
}
7
8
void timerInit(long frequency)
9
{
10
//  long step;
11
12
  T1TCR = 0x02; //Counter reset, disabled
13
14
  T1MR3 = VPBRate()/frequency;
15
  iprintf("VPBRate: %d", VPBRate());
16
//  T1MR0 = T1MR3/2;
17
//  T1MR1 = 0;
18
//  T1MR2 = ;
19
20
//  T1MCR =  03001; //interrupt on 0 and 3, reset on #3
21
  //T1MCR =  03000; //interrupt on 3, reset on #3
22
  T1MCR = 0x600;
23
  T1IR = 0xff; //Clear all pending interrupts
24
  
25
  VICSetup(TIMER1, 4, PeriodicInterrupt, 0);
26
27
  T1TCR = 0x01; //Counter enabled
28
}


Also, just for reference, I do have some encoder interrupts as well 
which could be interfering. Here is their setup
1
void encoderInit(struct FilterParams *fp, struct FilterState *st, int fcount)
2
{
3
  unsigned long vpb;
4
  int i;
5
6
  /* Read twice, Errata VPBDIV.1 */
7
  vpb=VPBDIV;
8
  vpb=VPBDIV;
9
  fp->count_scale = ActualSpeed()*1000.f/((float)vpb*(T0PR+1));
10
11
  /* Encoder0 on pins P0.3, P0.2-CAP0.0 and P0.5, P0.4-CAP0.1\ */
12
  /* Set pins to be capture inputs */
13
  IO0DIR  &= ~(      (1<<2) |      (1<<3) |      (1<<4) |      (1<<5));
14
  PINSEL0 &= ~((0x03<<(2*2))|(0x03<<(2*3))|(0x03<<(2*4))|(0x03<<(2*5)));
15
  PINSEL0 |=   (0x02<<(2*2))|(0x00<<(2*3))|(0x02<<(2*4))|(0x00<<(2*5));
16
17
  /* Encoder1 on pins P0.27, P0.28-CAP0.2 P0.30-P0.29-CAP0.3*/
18
  IO0DIR  &= ~(       (1<<27)     |       (1<<28)     |       (1<<29)     |       (1<<30));
19
  PINSEL1 &= ~((0x03<<(2*(27-16)))|(0x03<<(2*(28-16)))|(0x03<<(2*(29-16)))|(0x03<<(2*(30-16))));
20
  PINSEL1 |=   (0x00<<(2*(27-16)))|(0x02<<(2*(28-16)))|(0x02<<(2*(29-16)))|(0x00<<(2*(30-16)));
21
22
  VICSetup(TIMER0, 3, EncoderPinInterrupt, 0);
23
  memset(st, 0, fcount*sizeof(struct FilterState));
24
  for(i=0;i<fcount;i++){
25
    st[i].lastupdate = T0TC;
26
  }
27
  /* CAP0.0, CAP0.1, CAP0.2, CAP0.3 interrupt on both edges */
28
  T0CCR |= (0x07<<(3*0))|(0x07<<(3*1))|(0x07<<(3*2))|(0x07<<(3*3));
29
30
}

von Em H. (e_han)


Rate this post
useful
not useful
I have narrowed down my problem. The problem is that
1
 ioctl( fileno(stdout), BLOCKING_SETUP, &blocking);

returns -1 with the errno 88 which is defined as "File opening Error: 
Function not implemented"

ioctl is implemented in Winarm using the newlib-lpc library right? Does 
that mean that I am having a problem with Winarm?
1
ioctl( fileno(stdout), UART_SETUP, &sp);
2
3
ioctl( fileno(stdout), INTERRUPT_SETUP, &irq);

return 0 however, which means that those ioctl functions work...

Could anyone give me some direction or suggestions with this? I have 
googled everything I can think of and cannot find anyone with the same 
issue.

von Jim M. (turboj)


Rate this post
useful
not useful
Newlib is open source. Use the source, Luke!

Note: You may have to implement non-blocking UART read and write 
yourself. Newlib is a minimal LibC implementaion which lacks many 
features in favor of size and speed.

von Em H. (e_han)


Attached files:

Rate this post
useful
not useful
Thanks,

I was finally able to find the source code. The aeoulus development 
website has a broken link for the source code (although I called the 
phone number on the website, and the owner said he was gonna fix that 
soon). But after some diffing I found a link to a forum that has the 
file Beitrag "printf bei armgcc"

But in case that goes down, I'll attach it here for any other poor soul 
who cannot find it.

Anyway, the problem was that BLOCKING_IO_NO was only implemented for spi 
and not UART. I am gonna try to implement the BLOCKING_SETUP for UART 
myself and see if I can get it to work. If I can figure it out, i'll 
post my results back here.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.