This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/LAUNCHXL-CC2640R2: Exception when tying to use UART.C ?

Part Number: LAUNCHXL-CC2640R2

Tool/software: TI-RTOS

I am trying to use the files at:

/home/marc/ti/simplelink_cc2640r2_sdk_1_50_00_58/source/ti/devices/cc26x0r2/driverlib

Uart.C and Uart.h and get an Exception on the first H# register write?

UART_init(  );
UARTEnable(UART0_BASE );
UARTConfigSetExpClk( UART0_BASE, 24000000, 115200,    UART_CONFIG_WLEN_8|UART_CONFIG_STOP_ONE |UART_CONFIG_PAR_NONE );

ROV on HWI module reports:

Decoded exception    
Decoded    Hard Fault: FORCED: BUSFAULT: PRECISERR.Data Access Error. Address = 0x4000102c

The routine that faults in driverlib UART.C:

__STATIC_INLINE void
UARTEnable(uint32_t ui32Base)
{
    // Check the arguments.
    ASSERT(UARTBaseValid(ui32Base));

    // Enable the FIFO.
    HWREG(ui32Base + UART_O_LCRH) |= UART_LCRH_FEN;  <+++++++++++++++ when stepped, exception occurs ==================

    // Enable RX, TX, and the UART.
    HWREG(ui32Base + UART_O_CTL) |= (UART_CTL_UARTEN | UART_CTL_TXE |
                                     UART_CTL_RXE);
}

I'm sure I am simply missing some other routine to call first to enable writing to the UART0_BASE addresses....

Anybody in the know let me know!

Cheers,

Marc Y.

  • Hi Marc,

    Why aren't you using the UART driver? Found under <ti/drivers/UART.h>.
  • I do not want to carry a boat load of overhead for a simply reading UART char. data and outputting.

    I have to do RS485/MODBUS and have my own drivers to port from the older product line.  When I see how one

    has to output 1 character (by making it into a string, getting the length and calling UART_Write()) I simply don't

    want to go that route.

    Additionally I will only use TI-RTOS and BLE stack for the first 30 seconds of operation of the product then

    have to shut that all down and become the simple application code that we are going to port.  We will only

    use BLE for OTA update and configuration settings for service modes just after reset boot up.  So there will

    not be any of the queues, sem's, mailboxes or even tasks for 99% of the product run time.  The product is

    to be used around explosives and there can be no RF emissions after power up (about 1 minute).

    So, what I need is how or what to do to enable writing to various H/W peripherals in the M3 with out getting

    an exception and having to debug that.   I am missing something the larger drivers are doing or the pin and

    port setup stuff somewhere to enable writing to all the UART registers (and I'll have the same issue for most

    of the other peripherals in the M3 when I get to porting our stuff).  So this is a leaning step for me right now

    to learn the M3 per TI and the lowest level drivers that are already written in the SDK.

    TI did a good job providing several levels of drivers and such, but I haven't see an overview which talks

    about I/O address and general addressing ennoblement (like the IO manager in Linux that has to be set

    up to write to ports directly from user level).

    Back to the original question?

    Thanks,

    Marc Y.

  • An add on note, I have found and read some on NORTOS.H. This is a great way for me to use and have some
    basic timing and such, even blocking queues and mailboxes, etc. However there isn't any real documentation
    on setting this up and what is needed in a basic "includes" list to do a project with this method.
    Any help on the NORTOS.H application build would be helpful!
    Thanks again,
    Marc Y.
  • Hi Marc,

    It is a reason why we supply a UART driver, as it is too easy to not do it correctly when using the UART module directly. It also looks like you are using both the UART driver (UART_init() function) and the UART driverlib API at the same time. Either way, you have probably not turned on the Serial power domain before accessing the UART module.

    I want to highlight that the UART driver doesn't carry a "boat load" of overhead. Of course there's going to be some overhead, but I wouldn't dwell on lack of performance if that's what makes you worried. And here's how you send one character with the UART driver:

    char my_char = 'y';
    UART_write(uart_handle, &my_char, 1);

    No need to turn it into a string and so forth.

    If you are using TI-RTOS at the beginning of your (OAD) application, why won't you continue using TI-RTOS in your product application? NoRTOS is a viable option to TI-RTOS if you want to use RTOS objects as well as TI drivers, and I recommend looking into the NoRTOS examples in the SimpleLink SDK on how this is setup and used. You can also read more about NoRTOS in the SimpleLink MCU User's Guide.

     

  • Thanks Edward!

    That link to the SDK overview/usage doc. was fantastic!  I had not found that one on my own and my first look it seems to be just what I need to read.

    There is so much available and depending on ones luck clicking through it you either find the details and be confused or eventually find the thing

    you needed to see/read first.  Thanks again for that link!

    On the UART, I was putting the single char. in a char c[4]; and using that, but it should have dawned on me to simply pint to the char. in memory

    as a pointer and that would do it.

    The actual thing I was stumbling on is imputing 1 char, or sensing one ready from the UART and responding to that rapidly.  The equivalent of just

    calling a function and getting -1 if no char. input or getting the char. itself if one was ready.   So I would think calling UART_Read would be just

    like UART_Write, point to a char. and say 1 char. is the buffer size.    I don't want to block to find there is no character.

    I guess the correct way I should do this is to start a task that monitors the UART input and responds to it if there is data.  The other main task

    can just keep going on what it needs to do.  UART_Read hangs until data comes in (or use callback) and UART_ReadPolling no interrupts

    but also hangs unitl the number of char's is ready to be returned.  (or errors).  I didn't like either of these but if I put them and the MODBUS stuff

    in a task then it can sit there until communicated with.

    I had the same problem with I2S and somehow got that "turned on" so the peripheral device respond and no more exceptions.  I didn't thnk

    the UART was not set up this way (power on) because I called that UART_Init() function, but I should have stepped through it to see what

    it did.   I'll look back into using the mid-level driver in TI-RTOS then if I can get a 2nd task going to handle that part of the project.

    The UART has worked well with that when I was testing it last week as well as Display() worked ok too....

    Thanks,

    Marc Y.

  • Hi Edard,
    I did try your two line example, it does send one character and never retruns for more? I step the code and find I and down
    in the UART_HwiFxn or some of the CC2460Power functions like: PowerCC26XX_standbyPolicy() and SysCtrl_DCDC_VoltageConditionalControl() and looping through these, never getting back to the code I used to send the one
    character to the UART. This is why I did not want to use routines where I would have to step through loads of code that should
    have nothing to do with what I want to happen. Of course I know this stuff is in there for a good reason, it just impedes coding
    and moving forward until every little detail is known about and dealt with.

    Is TI_RTOS trying to 'sleep' or power down and wait for more characters? Why on a write operation?
    Of course it will probably sleep a task in waiting for input from the UART, but on sending through the UART?
    Not clear on how your example should work if I have several characters to send (binary, so they are not a string)
    and that I should get fast return from UART_Write to get the next char. out?

    Any advice?
    Marc Y.
  • On further running I found your example does work, not why, sometimes when I run CCS and step or use break points there is a major delay to get the next display in the debugger. Not sure why but I waited out clicking the RUN and after several seconds I was getting the results I expected. So I think I can go with this method and keep TI-RTOS running.
    Getting character input one at a time might be another story, but I think if I put that in a task I'll be happy with designing around that function using this method.
    Marc Y.
  • What UART params have you configured when opening the UART driver?
  • I should update and close this one.  I forgot and am on to problems with the  GPIO stuff, may open a question on that soon?

    Here is my get and put characters which I got working: (I use "my" initials to use similar function names and not run afoul

    of the standard C library).  I also discovered that the standard printf() in TI's libraries goes to the CCS "console" most of the

    time, it seems to work sometimes and hang up other times probably because I was also driving the UART from my routines

    and mixed using my own printf() and the standard C library ones.

    /*
     *  ======== Utilities ========
     */
    void    my_Putc(UART_Handle uart, char c )
    {
    UART_write( uart, &c, 1);
    }
    void    my_Puts(UART_Handle uart, char *s )
    {
    while(*s) my_Putc( uart,*s++ );
    }
    char    my_Getc(UART_Handle uart)
    {
        char    c;
        int status;
        status = UART_read( uart, &c,1 );
        if (status == 0) {
            UART_write(uart, readErrDisplay, sizeof(readErrDisplay));
            c = 255;    // error exit
        }
        return  c;      // good char. exit
    }
    //

    I open the UART and get the "uart handle" that I pass to these functions making them

    sort of general and call from various places (not reentrant though).

    I also ported K&R type printf() to my code so I don't need to use Display():

    Here it is for those needing something like this:

    //
    //  convert 'num' using 'base' into string
    //
    char *convert(unsigned int num, int base )
    {
        static char Representation[]= "0123456789ABCDEF";
        static char buffer[10]; // check me, if longer numbers!!!
        char *ptr = &buffer[9]; // start at end of buffer
        *ptr = '\0';            // post end of string sentinel
        do
        {  *--ptr = Representation[num % base];  // build string backwards
            num /= base;                         // reduce number by base
        } while( num != 0 );                     // until it's 0!
        return(ptr);                             // return pointer to string num.
    }
    //
    // my printf stand in routine
    //
    int myprintf(char* format,...)
    {
        char *traverse;
        int  i,left, pad, cc, len, maxchr, width;
        char *sptr, str[17];
        va_list arg;
        va_start(arg, format);      // get va-arg's list in order for parsing
        cc = 0;
            traverse = format;      // fetch pointer to format string in statement
            while(*traverse) {
              if(*traverse!='%') {my_Putc(muart,*traverse++); ++cc; continue;}  // copy to output till %
              else ++traverse;                                                  // skip over other characters
              if(*traverse=='%') {my_Putc(muart,*traverse++); ++cc; continue;}  // got %% to send %
              if(*traverse=='-') {left = 1; ++traverse;} else left = 0;         // got - for left justified
              if(*traverse=='0') pad = '0'; else pad = ' ';        // got 0 or space for pad char
              if(isdigit(*traverse)) {                             // got digit as width?
                width = atoi(traverse++);                          // get number for width
                while(isdigit(*traverse)) ++traverse;              // noww skip past digits
                }
              else width = 0;                                      // no width spec.
              if(*traverse=='.') {                                 // got 2.3 type format?
                maxchr = atoi(++traverse);                         // yes, capture max char number
                while(isdigit(*traverse)) ++traverse;              // now skip past digits
                }
              else maxchr = 0;                                     // no, so maxchr is 0 or all
              sptr = str;
              switch(tolower(*traverse++)) {                       // finally, what is the format?
                case 'c': i = va_arg(arg,int);                     // Fetch char argument
                            str[0] = i; str[1] = NULL; break;      // pass the char. to output
                case 's': sptr = va_arg(arg,char *); break;        // pass a string to output
                case 'd': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        if(i<0){ i = -i; *sptr++ = '-'; }          // is it neg?, send sign then
                        sptr = convert((unsigned int)i,10 );       // convert int to string of same
                     break;
                case 'x': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,16 );       // convert to hex string of int
                     break;
                case 'b': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,2 );        // convert to hex string of int
                     break;
                case 'o': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,8 );        // convert to hex string of int
                     break;
                case 'u': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,10 );       // convert to hex string of int
                     break;
                default:  va_end(arg); return (cc);                 // bail on format error??
                }
              len = strlen(sptr);                                   // length of number we are sending
              if(maxchr && maxchr<len) len = maxchr;                // set max. length
              if(width>len) width = width - len; else width = 0;    // adj. if needs pad
              if(!left) while(width--) {my_Putc(muart,pad); ++cc;}  // send prefix pad char's
              while(len--) {my_Putc(muart,*sptr++); ++cc; }         // copy the number (as string) to output
              if(left) while(width--) {my_Putc(muart,pad); ++cc;}   // send pad if left justified
              }
            va_end(arg);                                            // clean up va-args before exit
            return(cc);                                             // return number of char's sent to output
    }

    Example usage:

                        myprintf("\r\nDIO%02x=%08x | DIO%02x=%08x",i,IOCPortConfigureGet(i), i+16,IOCPortConfigureGet(i+16));
                        gp=GPIO_read(Board_GPIO_SCOPE);             myprintf("\r\nDIOs: SCOPE=%02x, ", gp );
                        gp=GPIO_read(Board_GPIO_LED0);                myprintf("LED0=%02x, ", gp );
                        gp=GPIO_read(Board_GPIO_LED1);                myprintf("LED1=%02x, ", gp );
                        gp=GPIO_read(Board_GPIO_MUTE_AMP);    myprintf("MUTE=%02x, ", gp );
                        gp=GPIO_read(Board_GPIO_STBY_AMP);      myprintf("STBY=%02x", gp );

    And you were right, I missed that the UART has to be powered up before access which the

    direct routines didn't do but the mid and high level driver libraries do, so that is all good now.

    Thanks,

    Marc Y.

  • Hi All,

    I found a couple of errors in the "myprintf()" routine when printing decimal negative numbers.  Also was sign extending when printing

    hex values to full integer size even if you had set a width using "04x" you would get 8 char. width when the hex value was over 0x8000.

    So here is a better version (I dare say corrected, but then what else lurks in the routine?):

    //
    //  convert 'num' using 'base' into string
    //
    char *convert(unsigned int num, int base )
    {
        static char Representation[]= "0123456789ABCDEF";
        static char buffer[16]; // check me, if longer numbers!!!
        char *ptr = &buffer[15]; // start at end of buffer
        *ptr = '\0';            // post end of string sentinel
        do
        {  *--ptr = Representation[num % base];  // build string backwards
            num /= base;                         // reduce number by base
        } while( num != 0 );                     // until it's 0!
        return(ptr);                             // return pointer to string num.
    }
    //
    // my printf stand in routine
    //
    int myprintf(char* format,...)
    {
        char *traverse;
        int  i,left, pad, cc, len, maxchr, width;
        char *n, *sptr, str[17];
        va_list arg;
        va_start(arg, format);      // get va-arg's list in order for parsing
        cc = 0;
            traverse = format;      // fetch pointer to format string in statement
            while(*traverse) {
              if(*traverse!='%') {my_Putc(muart,*traverse++); ++cc; continue;}  // copy to output till %
              else ++traverse;                                                  // skip over other characters
              if(*traverse=='%') {my_Putc(muart,*traverse++); ++cc; continue;}  // got %% to send %
              if(*traverse=='-') {left = 1; ++traverse;} else left = 0;         // got - for left justified
              if(*traverse=='0') pad = '0'; else pad = ' ';        // got 0 or space for pad char
              if(isdigit(*traverse)) {                             // got digit as width?
                width = atoi(traverse++);                          // get number for width
                while(isdigit(*traverse)) ++traverse;              // now skip past digits
                }
              else width = 0;                                      // no width spec.
              if(*traverse=='.') {                                 // got 2.3 type format?
                maxchr = atoi(++traverse);                         // yes, capture max char number
                while(isdigit(*traverse)) ++traverse;              // now skip past digits
                }
              else maxchr = 0;                                     // no, so maxchr is 0 or all
              sptr = str;
              switch(tolower(*traverse++)) {                       // finally, what is the format?
                case 'c': i = va_arg(arg,int);                     // Fetch char argument
                            str[0] = i; str[1] = NULL; break;      // pass the char. to output
                case 's': sptr = va_arg(arg,char *); break;        // pass a string to output
                case 'd': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        if(i<0){ i = -i; *sptr++ = '-'; }          // is it neg?, send sign then
                        n = convert((unsigned int)i,10 );              // convert int to string of same
                        if( n ) strcpy( sptr,n );                    // copy over the digits
                        sptr = str;                                    // reset ptr for printing string
                     break;
                case 'x': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,16 );       // convert to hex string of int
                     break;
                case 'b': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,2 );        // convert to hex string of int
                     break;
                case 'o': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,8 );        // convert to hex string of int
                     break;
                case 'u': i = va_arg(arg,int);                     // Fetch Decimal/Integer argument
                        sptr = convert((unsigned int)i,10 );       // convert to hex string of int
                     break;
                default:  va_end(arg); return (cc);                 // bail on format error??
                }
              len = strlen(sptr);                                   // length of number we are sending
              if( width && len>width ) while( --len>width ) ++sptr;    // skip excess on left of num string
              if(maxchr && maxchr<len) len = maxchr;                // set max. length
              if(width>len) width = width - len; else width = 0;    // adj. if needs pad
              if(!left) while(width--) {my_Putc(muart,pad); ++cc;}  // send prefix pad char's
              while(len--) {my_Putc(muart,*sptr++); ++cc; }         // copy the number (as string) to output
              if(left) while(width--) {my_Putc(muart,pad); ++cc;}   // send pad if left justified
              }
            va_end(arg);                                            // clean up va-args before exit
            return(cc);                                             // return number of char's sent to output
    }