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

von Em H. (e_han)

Rate this post
0 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!


My main function has a loop the runs every so often using a regular 
timer interrupt

    IOSET = 1<<12;
      IOCLR = 1<<13;
      fUpdate(ic, 0, filterParams, &(Encoder[0]));
      Simulate(&(Circle[0]), &(simParams[0]), &(simState[0]), &(Encoder[0]), fParams->count_scale, 6);
      fUpdate(ic, 1, fParams, &(Encoder[1]));
      Simulate(&(Circle[1]), &(simParams[1]), &(simState[1]), &(Encoder[1]), fParams->count_scale, 4);
      flags &= ~PERIODIC;
      IOSET = 1<<13;
    iprintf("PERIODIC = %1d\r\n", PERIODIC);
    testCounter = 0;

nonblocking_function just calls read()
void nonblocking_function()
  int havechar;
  int charWaiting = 0;
  char inchar;
  char *ret;
  character = read(fileno(stdout), &inchar, 1);

I initialize the stdout out to be non blocking here
void initializeInterface(struct InterfaceState *is)
  int blocking,i;

   /* set non-blocking io */
  fcntl(fileno(stdout), F_SETFL, O_NONBLOCK);
  fcntl(fileno(stdin), F_SETFL, O_NONBLOCK);
  write(fileno(stdout),"\r\n> ",4);
  ioctl( fileno(stdout), BLOCKING_SETUP, &blocking);

Here is the uart initizlization
const struct device_table_entry *device_table[] = {
  &com1_int,  /* stdin  */
  &com1_int,  /* stdout */
  &com1_int,  /* stderr */
  0 };  /* end of list */

void ioInit(void)
  struct serial_param sp;
  struct interrupt_param irq;

  /* Desired serial line characteristics 115200,n81      */
  sp.baud   = 115200uL;
  sp.length = UART_WORD_LEN_8;
  sp.parity = UART_PARITY_NONE;
  sp.stop   = UART_STOP_BITS_1;
  /*  Set up serial port to desired rate.       */
  ioctl( fileno(stdout), UART_SETUP, &sp);

  /* configure uart interrupt */
  irq.FIQ = 0;
  irq.pri = (INT_PRIORITY)10;
  ioctl( fileno(stdout), INTERRUPT_SETUP, &irq);
  //printf("irqmask: %f", IRQ_MASK);

  /* LEDs are output */
  IO0DIR |= (1<<12)|(1<<13);

  /* LEDs off */
  IOSET  = (1<<12)|(1<<13);

Here is the periodic timer initialization
void PeriodicInterrupt(void)
  flags |= PERIODIC;
  T1IR = 0x0f; //Clear all match interrupts
  VICVectAddrRead = 0x0ul;

void timerInit(long frequency)
//  long step;

  T1TCR = 0x02; //Counter reset, disabled

  T1MR3 = VPBRate()/frequency;
  iprintf("VPBRate: %d", VPBRate());
//  T1MR0 = T1MR3/2;
//  T1MR1 = 0;
//  T1MR2 = ;

//  T1MCR =  03001; //interrupt on 0 and 3, reset on #3
  //T1MCR =  03000; //interrupt on 3, reset on #3
  T1MCR = 0x600;
  T1IR = 0xff; //Clear all pending interrupts
  VICSetup(TIMER1, 4, PeriodicInterrupt, 0);

  T1TCR = 0x01; //Counter enabled

Also, just for reference, I do have some encoder interrupts as well 
which could be interfering. Here is their setup
void encoderInit(struct FilterParams *fp, struct FilterState *st, int fcount)
  unsigned long vpb;
  int i;

  /* Read twice, Errata VPBDIV.1 */
  fp->count_scale = ActualSpeed()*1000.f/((float)vpb*(T0PR+1));

  /* Encoder0 on pins P0.3, P0.2-CAP0.0 and P0.5, P0.4-CAP0.1\ */
  /* Set pins to be capture inputs */
  IO0DIR  &= ~(      (1<<2) |      (1<<3) |      (1<<4) |      (1<<5));
  PINSEL0 &= ~((0x03<<(2*2))|(0x03<<(2*3))|(0x03<<(2*4))|(0x03<<(2*5)));
  PINSEL0 |=   (0x02<<(2*2))|(0x00<<(2*3))|(0x02<<(2*4))|(0x00<<(2*5));

  /* Encoder1 on pins P0.27, P0.28-CAP0.2 P0.30-P0.29-CAP0.3*/
  IO0DIR  &= ~(       (1<<27)     |       (1<<28)     |       (1<<29)     |       (1<<30));
  PINSEL1 &= ~((0x03<<(2*(27-16)))|(0x03<<(2*(28-16)))|(0x03<<(2*(29-16)))|(0x03<<(2*(30-16))));
  PINSEL1 |=   (0x00<<(2*(27-16)))|(0x02<<(2*(28-16)))|(0x02<<(2*(29-16)))|(0x00<<(2*(30-16)));

  VICSetup(TIMER0, 3, EncoderPinInterrupt, 0);
  memset(st, 0, fcount*sizeof(struct FilterState));
    st[i].lastupdate = T0TC;
  /* CAP0.0, CAP0.1, CAP0.2, CAP0.3 interrupt on both edges */
  T0CCR |= (0x07<<(3*0))|(0x07<<(3*1))|(0x07<<(3*2))|(0x07<<(3*3));


von Em H. (e_han)

Rate this post
0 useful
not useful
I have narrowed down my problem. The problem is that
 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?
ioctl( fileno(stdout), UART_SETUP, &sp);

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 

von Jim M. (turboj)

Rate this post
1 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
0 useful
not useful

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.


Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]

Bild automatisch verkleinern, falls nötig
Note: the original post is older than 6 months. Please don't ask any new questions in this thread, but start a new one.