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.
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
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
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.
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
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
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