Jump to content
43oh

UART produces strange results


Recommended Posts

Hi!

 

I'm haivng an unusual problem with UART0 on Tiva C Launchpad. I'm also using Code Composer Studio 5.5.

 

What I'm trying to do right now is to do A/D conversion on the microcontroller and send data to a PC via the serial port. Basically, my program right now sets up peripherals and then goes into a while(1) loop where it samples data from the ADC and then sends them via UART. I'm not using interrupts at this point at all.

 

My code looks like this:

unsigned const int BaudRate=5000000;//I've tried with lower data rates, but they're not the problem here.

int main(void)
{
	ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);

	//Setting up serial port
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
	while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_UART0))
	{//Often goes into fault interrupt if this isn't here
	}
    ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
	{
	}

    ROM_GPIOPinConfigure(GPIO_PA0_U0RX);
    ROM_GPIOPinConfigure(GPIO_PA1_U0TX);
    ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    ROM_UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), BaudRate,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_EVEN));
    ROM_UARTFIFOEnable(UART0_BASE);

//blah blah a bit more setting things up and so on

	while(1)
	{

			ROM_ADCIntClear(ADC0_BASE, 3);//clearing interrupt
			while(!ROM_ADCIntStatus(ADC0_BASE, 3, false))//waiting for ADC to finish
			{
			}
			ROM_ADCSequenceDataGet(ADC0_BASE, 3, adcData);
                        //Here we first convert digit into char and then sent it via UART.
			firstDigit=(char)(((int)'0')+(adcData[0]/1000));
			UARTCharPut(UART0_BASE,firstDigit);

			secondDigit=(char)(((int)'0')+((adcData[0]/100)%10));
			UARTCharPut(UART0_BASE,secondDigit);

			thirdDigit=(char)(((int)'0')+((adcData[0]/10)%10));
			UARTCharPut(UART0_BASE,thirdDigit);

			fourthDigit=(char)(((int)'0')+(adcData[0]%10));;
			UARTCharPut(UART0_BASE,fourthDigit);

			//ROM_UARTCharPut(UART0_BASE,' ');
			UARTCharPut(UART0_BASE,'\n');
			UARTCharPut(UART0_BASE,'\r');

//some more bit wiggling and similar stuff
      }

So what basically happens is that quite often I get missing characters in the output. For example:

 

2002034
2032
2029
2034
2036
20322006
2029
2037
2035
2002031
2029
2037
2032
2037
2031
0022035
2031
2033
2030
    20
2033
2034
2032
2050
2047
20302034
2032
2053
2049
2200037
2039

As I wrote in code comment, this doesn't seem to be related to data rate. I've tried with lower rates such as 115200 b/s and even 9600 b/s and on both cases I have same problems. I've looked at the TXD test via on the PCB with a scope and the data itself looks OK (well to me at least).

 

I've tried stepping through the loop in the debugger, but every time I go through it in the debugger, I get correct output.

 

Also if I compile the program in release mode, the output will almost always skip the new line characters and all digits will get grouped together.  One more thing I initially tried is to use the non-blocking character put, but it had even worse results. For example, it would commonly print single character numerous times and then skip some other characters. I also experimented using ROM and flash versions of functions, but there seems to be no difference between their behavior as far as I can tell.

 

 

I have a feeling that I'm missing something simple here, but I'm not sure what.

Link to post
Share on other sites

I have a couple of tips that might help to troubleshoot your problem:

 

As an experiment, set the UART to a standard baud rate, say, 115200 (just to make sure the baud rate can't be the problem). Then, set the configuration of the UART to 8N1 or 8 data bits, no parity bit, 1 stop bit. Afterward, try replacing the ADC related statements in the while loop with a constant value that you might expect to read out from the ADC instead (such as 2030) and have your code work with that number.

 

I can definitely see how the non-blocking version of UARTCharPut could cause problems in this scenario. Code executing faster than the UART can transmit data can cause a buffer overflow to occur.

Link to post
Share on other sites

Interesting suggestion!

 

First, a bit of calculation:

At the end of my loop, I move a pin high and low. After doing some measurements on how quickly that happens, I've noticed that the loop frequency is around 125 kHz. When using serial port in the traditional way, we  have 1 start bit, 8 data bits and one stop bit. So that's 10 bits per loop iteration. If I don't want to overfill the FIFOs, I'll need data rate of at least  1 250 000, so I'll need to do the debugging until the Launchpad works stable at that frequency. Obviously I can't calculate... The ADC is 12 bit, so I'll need at least two bytes for payload, giving me a minimum 20 bits per loop ineration, so the data rate needs to be 2.5 Mb/s, which probably isn't feasible on launchpad using ICDI connection.

 

 

Next, I tried what you suggested: I disabled the AD conversion and set adcData[0]=2030;

 

After that I noticed two strage things: When I power down the Launchpad and connect it to my computer, I get gibberish in terminal. I've checked the serial port freqeuncy with my scope and it's correctly set to 115200.

The exact message I'm getting from the port is 0x8292829A repeated several times.

 

When I try to debug the Launchpad using CCS, it starts working correctly until I power it down. So I get the whole number and CR LF correctly every time. If I remember correctly, the MCU used here stores its configuration registers even after core reset. I can conclude from that that the debug in CCS sets up something that I initially missed when setting up the UART.

 

 

Next, I set the rate back to 5 000 000 and checked  how things work. I got same results as I posted in my original post. I'm out of time to debug right now, but my next step will be to connect a TTL serial to USB adapter (assuming I can find one fast enough in the first place!) direclty to the TXD via on the Launchpad and see if the problem is with the top or the bottom microcontroller on the Launchpad.

Link to post
Share on other sites

5000000 is not a meaningful baud rate. Unless you get things working reliably at 9600 I would not experiment with that.

 

The most common error I run into is misconfiguration of the serial parameters either on the PC or the MCU side. Your code above uses the quite uncommon even parity bit (UART_CONFIG_PAR_EVEN). Typically, serial is operated with 8N1, i.e. 8 bit, no partity bit, one stop bit.

 

So in summary, try:

- 9600 Baud

- 8 bit, no parity, one stop (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)

- make sure you set the exact same parameters on the PC side, also turn off XON/XOFF flow control in your terminal software

 

If that doesn't work, strip down your example to only initialize UART and send a few characters in a loop.

 

And if that still doesn't work, post the full code of the stripped down example and a screenshot of your terminal settings and we'll see from there.

Link to post
Share on other sites

Here's the code:

/*
 * main.c
 */
#define TARGET_IS_BLIZZARD_RB1
//#define UART_BUFFERED

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/gpio.h"
#include "driverlib/debug.h"
#include "driverlib/rom.h"
#include "inc/hw_gpio.h"
#include "driverlib/adc.h"
#include "driverlib/fpu.h"
#include "driverlib/interrupt.h"
#include "driverlib/timer.h"
#include "inc/tm4c123gh6pm.h"
#include "utils/uartstdio.h"
#include "driverlib/uart.h"
#include "driverlib/pin_map.h"

uint32_t adcData[4];

static unsigned const int BaudRate=9600;

char firstDigit,secondDigit,thirdDigit,fourthDigit;


int main(void)
{
	//80 MHz = 400 MHz/2/2.5
	SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);

	//Serial port settings
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0))
	{
	}
	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
	while(!ROM_SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA))
	{
	}
	GPIOPadConfigSet(GPIO_PORTA_BASE,GPIO_PIN_0|GPIO_PIN_1,GPIO_STRENGTH_8MA,GPIO_PIN_TYPE_STD);
	UARTFIFOEnable(UART0_BASE);
	GPIOPinConfigure(GPIO_PA0_U0RX);
	GPIOPinConfigure(GPIO_PA1_U0TX);
	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
	UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), BaudRate,(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE));

	while(1)
	{
		adcData[0]=2030;

			firstDigit=(char)(((int)'0')+(adcData[0]/1000));
			UARTCharPut(UART0_BASE,firstDigit);

			secondDigit=(char)(((int)'0')+((adcData[0]/100)%10));
			UARTCharPut(UART0_BASE,secondDigit);

			thirdDigit=(char)(((int)'0')+((adcData[0]/10)%10));
			UARTCharPut(UART0_BASE,thirdDigit);

			fourthDigit=(char)(((int)'0')+(adcData[0]%10));;
			UARTCharPut(UART0_BASE,fourthDigit);

			UARTCharPut(UART0_BASE,'\n');
			UARTCharPut(UART0_BASE,'\r');
	}
}

I've attached a screenshot of a terminal emulator I'm using and a screenshot of the TXD via on the Launchpad. As soon as I enter debug mode once in CCS, I start to get expected results with 9600 bits per second.

 

 

post-2826-14264605348632_thumb.png

post-2826-14264605349067_thumb.png

Link to post
Share on other sites

Hi,

5000000 is a defined baud rate in the user  manual, maximum is 10,000,000. But there are some problems with operating at these speeds. There were discussions on stellaris_arm forum on this subject, seems the experiments were between two boards, back-to-back, and not between a board and PC, due to both hardware and software problems. 

 

About even parity - not unusual, some protocols/applications uses that.

 

About the code posted: usually it is recommended that after enabling the peripheral to wait for a while (which is done) and after that, use UARTDisable() function before doing further configurations, then when finished, use UARTEnable().

Problems can be from the FIFO - it is enabled as standard, not configured and its length could not match the number of transmitted characters. Perhaps would be better to be disabled, since the use of UARTCharPut is non-blocking (i.e. waits until the DR register is empty, then loaded with the new character).

Also, in the first post the results are seen as real numbers (2032, 2029, etc), while in another post the result "0x8292829A" is meaningless - did the algorithm changed? 

Another observation: if the data is transformed in decimal, then the number of characters to be sent is double than transmitting directly in binary form (still does not explain 0x8292…since at 12 bits maximum conversion is 0x0FFF…)

L

Link to post
Share on other sites

Hi!

 

First about the hex... The algorithm didn't change at all, it's that I just couldn't think of a way to post the characters that I got on screen, so I switeched the terminal to hex and put the code I'm getting. When the test was done, I had the ADC disabled and the value set manually to 2030; I was sending characters '2' '0' '3' '0' '\r' 'n' from the serial port at the time.

 

 

Do you have any sources for the UARTDisable()->Configure->UARTEnable() workflow? I think I read somewhere about UART being enabled even though it should be disabled by default, but I don't think I've hear of disable->enable so I'd like to read a bit more about it.

Link to post
Share on other sites

Hi,

The disable/enable UART is stated in the user's manual - I used this in my projects. The functions are defined in the driverlib, you may call them with ROM_ prefix as usual. The driverlib/uart.h is already included. It seems you have experience with some other micro controllers, but please note this one is a big/complicated, so the first thing to do is to read/note the differences with other micro controllers. The same apply also to ADC -> sample sequencer - first disable the sequencer, configure it, then enable it back. 

 

One more problem: if you really send  '2' '0' '3' '0' '\r' 'n', then on the console I expect to see '2030' and then two characters corresponding to \r\n, but in your picture I can see only 2 and another character, so I think you may have some other problems with the transmission. As @@chicken suggested, check it at lower speed first.

L

Link to post
Share on other sites

Hi @@Lyon!

 

I must have missed that part of the manual. I'll just have to read more carefully! I mostly focused on the examples from the workshop (which now seems like it was a bad idea) and I haven't seen TI use disable->enable workflow there at all.

 

I do have experience with other microcontrollers. I used Atmel AVR and Microchip PIC18 in the past. AVR was relatively easy to work with and PIC18 required digging up some not-very-easy-to-find documentation, but both were much easier to comprehend. Also bugs on them weren't as smart as Tiva C bugs: There they'd usually stay in place and wait for me to fix them. Here, they're activelly trying to hide. :)

 

Anyway, about the picture I posted: UART there is set to run at 9600 b/s. I really don't see the point in setting the speed lower.

 

The code I posted is running on the microcontroller. The characters you see have the hex code I posted earlier.

Do note that at the time I was using the FIFO and didn't have the disable->enable. At that time, I'd the output shown on the picture until I start the debugger. As soon as I do that, it would start sending 2030LFCR corectly. In any case, since I started disabling and then enabling the UART, I don't think I have had such problem, or I at least can't remember it happening.

 

I've found a post by Texas Instruments employee where they claim to test the in-circuit debug interface virtual serial port, which is what I'm using, at 115200 b/s. Here's the link to the thread: http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/271337.aspx?pi297168=2

 

In any case the UART seems to be working fine now at 9600 b/s.

 

What's bothering me the most here is that my workflow looks a bit like this: I have a problem-> I change settings numerous times-> The problem seems to disappear and I have no idea why.

Here's an example: I changed the ADC part so that instead of sending data directly over serial port, it would store 4096 samples in RAM and then send them all at 115200 b/s. Yesterday I'd regularly get one missed CR LF pair per 4096 samples, but today same code works fine.

Link to post
Share on other sites

Hi,

I understand you - that's why I said in a previous post the Cortex-Mx is big/complicated, at least at the beginning. What I can say this micro has a special debugging machine inside, is able to show you the address of buggy code line (in some instances) and also the type of bug. So if you like to know more about, look for application note spma043.pdf - Diagnosing software.. at TI page for TM4C micro controllers. Worth the effort to read and learn.

About other micro controllers, I avoided both AVR and Microchip (although I made a project once based on 8-bit Microchip) - did not liked at all first and then what I needed was not covered by such micros.

 

As for your software - better to make less changes or to ask about a particular behavior; maybe you acted as for previous micros, which I know makes sometimes particular habits, unusual for Cortex. Try to read/understand the TI's driver library, the code is available. And no rush.

 

Good luck,

L

Link to post
Share on other sites

Thanks for your support!

 

I'm going to make some changes in the way I develop the code: First, I'm going to set up a version control system and then I'm going do a commit every time I program the microcontroller. Hopefully this will help me narrow down the minor changes I'm making that could be affecting things. Then I'm going to actually reset the Lauhcnpad after every programming, since I had issues with previous configuration remaining in registers.

 

I'll also study the debug giude in detail.

 

As for no rush, normally I tend to postpone my projects until the last possible moment. Fortunatelly, with my current project this is not the case. I have more than enough time not to rush and to study everything thoroughly.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...