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.

TM4C1294NCPDT: Having trouble running ROM functions in interrupt, getting Fault ISR's

Part Number: TM4C1294NCPDT

I have a function that is called by the Systick Interrupt to load characters from my Transmit Buffer in Software into the part's Uart4 TX buffer.  It is intended to add up to 10 characters per interrupt, if they are available and there is room in the part''s TX buffer.  The function is shown below:

/*******************************************************************************

   Function:      Uart4_Load_TX_Buffer


   Description:   This function is called by the SysTick Interrupt routine and
                  loads up to 10 characters from the Uart4 circular buffer into
                  the Part's TX Buffer.  The routine returns when either the
                  part TX Buffer is full, ten characters have been loaded or
                  there are no more characters available to be sent.

   Parameters:    None

   Returns:       Nothing

*******************************************************************************/
void Uart4_Load_TX_Buffer(void)
{
int index = 0;

    // Disable Interrupts
   ROM_IntMasterDisable();

   // check to see if all conditions met
   while ( index < 10 &&
           Com4_TX_Head != Com4_TX_Tail &&
           //ROM_UARTSpaceAvail(UART4_BASE)
           UARTSpaceAvail(UART4_BASE)
         )
      {
      // increment the index
      ++index;

      // send the next character to the part TX Buffer
  //    ROM_UARTCharPutNonBlocking(UART4_BASE, Com4_TX_Buffer[Com4_TX_Tail]);

      // Increment the buffer tail
      ++Com4_TX_Tail;

      // Check for wraparound
      if (Com4_TX_Tail >= Com4TXBufferSize)
         {
         // reset to beginning of buffer
         Com4_TX_Tail = 0;
         }
      }

   // Enable Interrupts
   ROM_IntMasterEnable();
}

1. If I take out the Space available test and the CHarPut the function runs without failure,

2. If I add any of the Space Available and Char Puts I get Fault ISr's, and I am not sure why.

3. Are there any restrictions to using those functions within interrupts?

4. Is there a special order in which to initialize the UART that would allow the functions to work?

5. Since I am using the Systick interrupt to load the TX buffer is there a recommended UART setup for the UART? I am assuming I don't need to use the TX interrupt since I am filling the buffer based on availability of character space.65. Is there an example that actually uses these functions within interrupts where I can see what needs to be set up in the interrupt and the UART to make these functions run? I have problems when the documentation is written to the most trivial form and leaves out actual examples to show how the functions actually work.

  • mike fontes said:
    I have a function that is called by the Systick Interrupt to load characters from my Transmit Buffer in Software into the part's Uart4 TX buffer

    Why would you do that rather than use the transmit interrupt? I do agree that the transmit interrupt isn't especially well implemented on this UART but still...

    mike fontes said:
    2. If I add any of the Space Available and Char Puts I get Fault ISr's, and I am not sure why.

    I think you should probably figure that out.

    Robert

  • Robert,

    I may need to put more information in my local software buffer than the UART can hold so I am just portioning out the information in groups of characters until the complete software buffer is emptied. I am using the Systick because it is available without adding a third interrupt.

    I have debugged by stepping the program and I know the failures occur when the calls to the ROM based Uart functions, or their library equivalents are made. I am assuming there is something wrong with how the UART is set up, but don't have a solid example where these functions are used, to determine why the processor gets a FaultISR. That is why I asked the questions above.

    You are right that I need to figure out why I am getting the FaultISRs. My problem is that I am not sure what to look for as I have not had to deal with these in my other Tiva, Stellaris and ST Arm projects. I am asking for some help in how to determine what the system doesn't like since I think I am using the functions correctly. I think there is some issue with the setup of the UART, but don't know where to look to find a complete C implementation using those functions.

    Sincerely,

    Mike Fontes
  • mike fontes said:
    I may need to put more information in my local software buffer than the UART can hold so I am just portioning out the information in groups of characters until the complete software buffer is emptied. I am using the Systick because it is available without adding a third interrupt.

    Technically it wouldn't be a third interrupt (probably be cleaner if it was actually). Still the code is probably cleaner if logically independent functions don't share the same interrupt.

    One thing you do have to watch for is that the transmit interrupt only occurs on passing the FIFO threshold, not on empty. A rather unfortunate oversight on the part of the UART designers.

    mike fontes said:
    You are right that I need to figure out why I am getting the FaultISRs. My problem is that I am not sure what to look for as I have not had to deal with these in my other Tiva, Stellaris and ST Arm projects. I am asking for some help in how to determine what the system doesn't like since I think I am using the functions correctly. I think there is some issue with the setup of the UART, but don't know where to look to find a complete C implementation using those functions.

    I'm pretty sure there is a serial example with the TIVAWare libraries.

    There's also a TI app note on troubleshooting faults. The fault registers will tell you the source of the fault, you then need to figure out what that means but it's a lot closer than "I ended up in the Fault ISR".

    Robert

  • Robert,

    My plan is to not use the UART Transmit interrupt at all and just fill the transmit buffer as it is emptied using the Systick handler function I showed in my first post. The command structure I use would not be blocking and would complete most of my transfers within 50 ms, which is plenty fast for the short commands and data replies.

    I was able to trace into the disassembly to the line where the fault occurred, and can look at the registers. I hadn't been able to determine what the register values were telling me yet, as I have not looked in the part datasheet yet.

    Can you tell me where to find the fault troubleshooting app note?

    I still think it is complaining about the setup of the UART, but I am not sure what to give it since I don't want the TX interrupt. I only want to be able to load the UART FIFO and know when it has characters available.

    I have seen oversimplified use of the PutChar NONBlocking function in the uart_echo example, but they don't check to see if there is space in the buffer, they just stuff the character in. I need actual buffering to protect against losses where my buffer can have a 32 characater command sent and there is only 16 characters of space in the hardware.

    Sincerely,

    Mike Fontes
  • mike fontes said:
    My plan is to not use the UART Transmit interrupt at all and just fill the transmit buffer as it is emptied using the Systick handler function I showed in my first post.

    I realize that, I just think it's a bad idea to mix functionality like that. It's asking for trouble.

    mike fontes said:
    Can you tell me where to find the fault troubleshooting app note?

    From the first link in e2e.ti.com/search

    http://www.ti.com/lit/an/spma043/spma043.pdf

    mike fontes said:
    I have seen oversimplified use of the PutChar NONBlocking function in the uart_echo example, but they don't check to see if there is space in the buffer, they just stuff the character in. I need actual buffering to protect against losses where my buffer can have a 32 characater command sent and there is only 16 characters of space in the hardware.

    Then the stepwise addition of that check to the example code seems in order.

    Robert

    I still suggest using the transmit interrupt rather than cobbling a transmit interrupt out of the systick interrupt.

  • Mike,
    If you have 32 bytes to send, it already justifies creating a more robust transmission solution.
    The idea is:
    - Send whatever you can directly to the uart hardware fifo buffer, byte by byte, until full.
    - Copy the rest to a separate transmission ram buffer and go back to your main application
    - From then, two options: either revisit the "ram-to-fifo transmission when you get a TX interrupt", or continuously poll at low priority to check if there is more stuff to be sent and fifo space where to put it.
    With some proper organization, this can reliably transmit your command, even way more than 32 bits - your limitations will be the size of the intermediate buffer and the physical speed of the uart channel. You will also be able to "send more command" (to the intermediate buffer, of course) even before the previous one is fully transmitted out of the MCU.
    Bruno
  • Bruno,

    I agree with you.  I thought my setup would work.

    1. I created my ram buffer of 256 characters. I load it using a simple PutChar function that takes care of the circular buffer requirements, including the checks for wraparound.

    2. I was planning on using the Systick as my poll to add characters to the FIFO as space became available by calling the original function I posted.  I was willing to use a fw microseconds during each systick to take care of checking whether there was space in the FIFO and some more to put up to 10 characters per SyStick into the FIFO.  That gave me the polling that you describe.

    3. The problem I hit was that every time I tried one of the ROM or library based UART function calls to put or check the FIFO I got FaultISRs.  I have not had a chance yet to determine what the Fault cause is due to some scheduling priorities, but will try to check on it tonight.

    4. What I don't understand is why it should be a problem to check the FIFO register values and write to the FIFO when in the SYStick interrupt. With the master disabled there should be no interrupt priority overrides.

    5. I have used this basic setup on several M3 and MSP430 systems in the past 15 or so years, so I am confused at the failures.  Usually I just have to modify the low level register calls and the rest of the C software ports quite easily.

    Sincerely,

    Mike Fontes

  • While I think it's a flawed architecture I don't think using Systick is causing your present problems.

    mike fontes said:
    3. The problem I hit was that every time I tried one of the ROM or library based UART function calls to put or check the FIFO I got FaultISRs.  I have not had a chance yet to determine what the Fault cause is due to some scheduling priorities, but will try to check on it tonight.

    This is number one. I don't think it's anything to do with the ROM functions either (unless you've tried with the normal functions and they worked).

    I suspect it's a memory issue. You have enabled the peripheral haven't you?

    I would try with the non ROM variants first, there's not a great deal of advantage to the ROM'd variants.

    Robert

  • Robert,

    If you check the original code you will see that I had commented out the ROM version of the chars available and tried the driverlib version instead of the ROM version. There was no change in the result, as I still got the FaultISRs.

    I tried several different UART setups with and with out the TX interrupt enabled, and with different buffer fill interrupt combinations, with no difference noticed in my result. That is why I added the original post. I could not find an example that used a RAM buffer that needed to be fed by some polling technique, as Bruno defined, and I thought I was doing with my interrupt routine. All the versions I found were designed to transmit less than a full FIFO of data, although one of them would have allowed more and crashed because it did not look at the boolean result returned when the FIFO was filled and just continued sending additional characters.

    In MSP430s I have been able to transmit and receive data strings of several hundred characters to Bluetooth modules using this basic structure. I just have to figure out how to get this version running.

    Based on what you have seen how would you attack the problem of the polling to recharge the FIFO as Bruno discussed? I get worried when there are two ways for the FIFO to be filled when you need to start the TX interrupt system by loading an initial character or two from one routine and then perform the polling updates to the FIFO from another.

    I am open to trying different ideas if my work tonight doesn't find the problem. It is always good to see how others solve similar problems.

    Sincerely,

    Mike Fontes
  • mike fontes said:

    If you check the original code you will see that I had commented out the ROM version of the chars available and tried the driverlib version instead of the ROM version.

    So you did.

    mike fontes said:
    I tried several different UART setups with and with out the TX interrupt enabled, and with different buffer fill interrupt combinations, with no difference noticed in my result.

    My bigger question was the enabling of the peripheral, not its configuration. Reading/writing an peripheral that is not enabled can result in a fault. I think reading from and empty FIFO or writing to a full one is unlikely to. I do use the check on FIFO full so I know it doesn't cause a fault.

    mike fontes said:
    Based on what you have seen how would you attack the problem of the polling to recharge the FIFO as Bruno discussed?

    First I'd find and fix the Fault. Everything else is secondary.

    mike fontes said:
    I get worried when there are two ways for the FIFO to be filled

    Two ways? There's only one that I'm aware of. Other than the handling of the FIFO threshold this is a fairly conventional UART.

    Robert

  • Mike,

    Having seen that you confirmed ROM_ or TivaWare functions produce the same issue (as expected), maybe you are simply having "a very basic problem"? Did you try to increase your stack and see if things work? I'm a fan of cranking up TM4C129 directly up to 4096 bytes.

    Now, one other factor is that is "assumed" is that your circular buffer solution is fully solved - it probably is, but did you make sure? It is not unusual that memory corruption past buffer limits cause ISR faults, and these can be tricky.

    Still, you mentioned "you will debug the fault ISR later after some priorities". Face the dragon! While debugging these faults, at first sound painful and hard, most of them clarify the reason after the first or second phase of analysis - and these painful "60 minutes until you get used to it", will save you 120 minutes that linger through your fingers trying to guess causes...

    Good luck there and let us know the (good) results!

    Bruno

  • Bruno,

    You made me laugh!.  The priorities I was talking about were not on the order of the debug.  I have kidney problems and am getting ready for dialysis, so sometimes I have to set the fun stuff aside to handle the health stuff.

    I am sure the ram buffereing is good because it has been tested over about 8 different projects.  I test for wraparound and update the heads and tails of the buffers accordingly.

    I do agree that I need to determine the fault issue first, and I think I might up the stack, as you mentioned. It is my opinion that I was using the ROM functons correctly so there is a setup issue involved. That is why I was asking if there were a more complete example to look at.

    Maybe once I have this working an app note should be considered.

    Sincerely,

    Mike Fontes

  • Mike, can you show us your setup code? You've shown us the buffer code but I don't see the setup code.

    Robert
  • Oh my!!! You make me blush on shame!!!
    By all means, PLEASE do take care of your health before dealing with these nasty bytes!!!!
    Robert seems to be having such an inspired week, I'll keep looking here and will help if I spot anything, but let me lay low for now and see his precious next step...
    Cheers
    Bruno
  • Robert,

    I have done some debugging and will give you the details.  First, the code below is the init for the UART4.  Sorry for the incomplete comments but I am not sure what is right yet so I don't want to document too much until I am sure what is staying and what is going.

    /*******************************************************************************

       Function:      Init_Uart4


       Description:   This function is called by the

       Parameters:    None

       Returns:       Nothing

    *******************************************************************************/
    void Init_Uart4(void)
    {
       // Disable Interrupts
       ROM_IntDisable(INT_UART4);

       // Set GPIO A0 and A1 as UART pins.
       GPIOPinConfigure(GPIO_PA2_U4RX);
       GPIOPinConfigure(GPIO_PA3_U4TX);
       ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3);

       // Configure the UART for 115,200, 8-N-1 operation.
       ROM_UARTConfigSetExpClk(UART4_BASE, g_ui32SysClock, 115200,
                               (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                UART_CONFIG_PAR_NONE));

       // Enable the UART interrupt.
       ROM_UARTIntEnable(UART4_BASE, UART_INT_RX | UART_INT_RT);

       ROM_UARTFIFOEnable(UART4_BASE);
       ROM_UARTFIFOLevelSet(UART4_BASE, 16, 1);

       ROM_UARTEnable(UART4_BASE);

       // Enable Interrupts
       ROM_IntEnable(INT_UART4);
    }

    I have debugged the code until I hit the FAULT ISR numerous times now.  Below is the CCS Debug Screen just before I get the fault.

    I am in the Disassembly pane on the right getting ready to perform the blx on line 92c. I can see in the previous code where the index is tested and the buffer is tested to have characters, so I know those parts of the code are actually working. The next step will cause the FaultISR.  What I know is that it is a failure when trying to read the TXFF bit of the UARTFR register of UART 4.  I got the register info from the NVIC registers per the app note you pointed me to.  The error makes sense because it is the read caused by the ROM_UARTSpaceAvail call.  One thing that bothers me is that when I try to read the values in the UART Registers I get the UNABLE TO READ indications as shown in the register pane.  Keep in mind that if I scroll to it I can read the contents of the NVIC registers.

    I am still under the impression that I have set up the UART incorrectly, but am not sure what I have done wrong.  I did set the stack to 4K like Bruno suggested, but with no change in functionality..

    Please let me know if you want any additional information.

    Sincerely,

    Mike Fontes

  • mike fontes said:
    I have done some debugging and will give you the details.  First, the code below is the init for the UART4. 

    Thanks, it would be useful to use the past code option </> icon in the use rich formatting. Simply pasting the code inline often causes a loss of formatting. As a bonus the paste code numbers the lines for easy reference.

    There's also no attached image.

    Having said that, assuming there is no missing initialization code I can make a pretty good guess as to the issue.

    Nowhere do you initialize the peripherals, neither the UART, nor the ports are initialized. You head straight into configuring them without initialization.

    You need to first initialize them with a SysCtlPeripheralEnable call and then verify that they have powered on and are ready with checks using SysCtlPeripheralReady calls. As an optimization I enable all of the peripherals before checking that they are ready.

    You are probably getting a memory fault at an address in the UART address space (you can verify that by checking the fault registers).

    Robert

  • Robert,

    I got it!  I had already been enabling the UART4 peripheral in the startup, but I have moved it to the Init_Uart4 function.  However that was not the issue.  The real problem is that you must also enable the GPIOA peripheral for the Faults to go away. It seems the enabling of the UART does not enable the GPIO pins it is tied to automatically.  i changed the init to the following and it is working fine. 

    /*******************************************************************************
    
       Function:      Init_Uart4
    
    
       Description:   This function is called by the main program to initialize Uart4
    
       Parameters:    None
    
       Returns:       Nothing
    
    *******************************************************************************/
    void Init_Uart4(void)
    {
      // bool ready = FALSE;
    
       // Disable Interrupts
       ROM_IntDisable(INT_UART4);
    
       // enable the peripherals used by the UART
       // IMPORTANT!! The GPIOA peripheral must be enabled to avoid FaultISRs
       ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART4);
       ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
    
      // ready = ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_UART4);
    
       // Set GPIO A0 and A1 as UART pins.
       GPIOPinConfigure(GPIO_PA2_U4RX);
       GPIOPinConfigure(GPIO_PA3_U4TX);
       ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_3);
    
       // Configure the UART for 115,200, 8-N-1 operation.
       ROM_UARTConfigSetExpClk(UART4_BASE, g_ui32SysClock, 115200,
                               (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                                UART_CONFIG_PAR_NONE));
    
       // Enable the UART interrupt.
       ROM_UARTIntEnable(UART4_BASE, UART_INT_RX | UART_INT_RT);
    
       // Set up FIFO
       ROM_UARTFIFOEnable(UART4_BASE);
       ROM_UARTFIFOLevelSet(UART4_BASE, 16, 1);
       
       // Set no flow control on this UART
       ROM_UARTFlowControlSet(UART4_BASE, UART_FLOWCONTROL_NONE);
    
       ROM_UARTEnable(UART4_BASE);
    
       // Enable Interrupts
       ROM_IntEnable(INT_UART4);
    }
    

    It definitely was a setup issue. Thanks for your help.

    Sincerely,

    Mike Fontes

  • mike fontes said:
    I got it!  I had already been enabling the UART4 peripheral in the startup, but I have moved it to the Init_Uart4 function.  However that was not the issue.  The real problem is that you must also enable the GPIOA peripheral for the Faults to go away.

    As I said, I couldn't find either in your code.

    Good you found it.

    One thing, you still aren't checking if the peripherals are enabled. You really should, otherwise you may be depending on marginal timing.

    Robert