This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

printf retarget.c - data aborts

Hello,

I work with the AT91RM9200.

I have some problems with the retarget-function for the implementation of printf. It works but sometimes I get a data abort - maybe if the buffer for printf function is too small???

that's my function to transmit printf messages to the usart

int COM1_1_sendchar(int ch)
{
        if (ch == '\n')  {                              /* Check for CR */
        while (!(COM1_1->US_CSR & AT91C_US_TXRDY));      /* Wait for Empty Tx Buffer */
    //  COM1_1->US_THR = '\r';                       /* Output CR */
                AT91F_US_PutChar (COM1_1,'\r');
        }
        while (!(COM1_1->US_CSR & AT91C_US_TXRDY));      /* Wait for Empty Tx Buffer */
        return (COM1_1->US_THR = ch);                        /* Transmit Character */
}

retarget.c

#include <stdio.h>
#include <rt_misc.h>
#include <AT91RM9200.H>
#pragma import(__use_no_semihosting_swi)

extern int COM1_1_sendchar (int ch);    /* in usart.c */

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f) {

  return (COM1_1_sendchar(ch));
}


int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}


void _ttywrch(int ch) {
  COM1_1_sendchar(ch);
}

void _sys_exit(int return_code) {
label:  goto label;  /* endless loop */
}

I hope somebody have a idea - because the problem with the data abort is not always but very often

best regards
Johannes

  • Why are you using:

    AT91F_US_PutChar (COM1_1,'\r');
    


    for the carriage return, but:

    COM1_1->US_THR = ch;
    


    for all other characters?

  • I only want to control if this function works better - but the result is the same...

    Do you know this error?

    Johannes

  • No, I don't work with Atmel ARM chips.

    I don't know how printf() does it's work. Some implementations builds the full string before emitting, and some emits the data parameter for parameter and only need buffer space for the widest parameter (such as a zero-padded integer of large/extreme width).

    Does your code contain any sprintf()? They can result in really funny things if the destination buffer is too small.

  • no I only use printf() functions in my code...

    Johannes

  • Any chance that your parameters to printf doesn't match the parameters in the formatting string?

  • I don't think so, because I have only text messages in the printf function like printf("hello world\n");

    I think the problem could be, that the first string "hello world\n" is not complete transmitted when the second string should also be transmitted via printf... so that the function printf is too slowly?

    Johannes

  • No, printf() is not too slow - your code is explicitly required to pace the output to the speed of the UART, or to the availability of output buffer/fifo space.

    The printf() can as soon as the last character is put into the transmit holding register. That means that if you do a printf() and then immediately turn off the UART, reboot or change baudrate, the last character is lost.

    However, putting two printf() after each other is always ok, since the second printf() will have to wait for an empty transmit register before printing the first character.

  • the baudrate for the usart is 115200 - so it is not slow.

    I have one printf() in a function, which is called three times. And I often have the problem, that the hyperterminal only shows "HellHello World" or something which is similar...

    so I get a data abort - and when I look which line occured this dara abort - it's very often the line
    COM1_1->US_THR = '\r';
    after the first if question...

    could there be another problem with my programm? like a storage problem?

    Johannes

  • Why didn't you specify that error before?

    Are all your printouts using printf, or do you have any other places where you print? Do you have any code that changes baudrate, timing or similar?

    This line is responsible for printf() waiting until the serial port can handle more data:

    while (!(COM1_1->US_CSR & AT91C_US_TXRDY));
    

    However, if that line is wrong, you would not just loose the last part of a printout. You would loose characters in the middle too.

    The most common reason for your error is if you put trace output in an interrupt handler.

  • I only use printf() to show some messages via the usart1 - I never change the settings of the usart...

    while (!(COM1_1->US_CSR & AT91C_US_TXRDY));
    

    I don't know why this line should be false?

    "The most common reason for your error is if you put trace output in an interrupt handler."

    ok, that's interesting. I have one printf() function in a ISR. That means, the ISR is closed before the printf() function has transmitted all values via the usart port - and that could be the problem? But is a data abort the logic effect of this?

    Johannes

  • That means, the ISR is closed before the printf() function has transmitted all values via the usart port

    No, that means that the interrupt routine does not wait for any already ongoing printouts.

    Stay away from printing in your ISR. You want an ISR to be fast - not having to wait until the UART has room for your characters. At your baudrate, your ISR will waste about 0.1ms for each character in the printout.

  • I have one printf() function in a ISR.

    That's very bad indeed. Calling printf() or one of its close relatives is just about the last thing you should ever consider doing in an ISR.

    As a rule of thumb, don't call any functions from an ISR. If the job at hand is complex enough that you feel an urge to split it into more than one function, it's probably not a job fit to be done by an ISR.

  • I have only text messages in the printf function like printf("hello world\n");

    Than why are you using printf()? puts() would do the same job with considerably less overhead.