Hi! I have a problem with UART0 output to my computer (only TX). The MCU I am using is MSP430F169 and I initialize the UART with the code at the end of the message. I use IAR V3.30A for compiling and debugging (company policy). UART0 works fine for a while, until something like 160-170 characters have been outputted. I have a circular buffer to supply for characters. The buffer setup has worked perfectly in my previous MSP430 devices (for the exact same purpose). It seems not that the buffer causes trouble, as spying the variables reveals nothing special there, but what worries me is thate I find the register IE1 to have changed when the UART output ceases: IE1 == 0x01 (i.e. IE1 == WDTIE) which means that IE1 & UTXIE0 == 0. No surprise that UTX output has stopped. So if I understand the situation correctly, something has changed the IE1 register and the UART TX is not active anymore. What could do that? I find nothing of the kind in the code, so this should be something processor internal. Searching the MSP430x1xx Family User's Guide doesn't reveal anything for me about this subject. Thanks in advance for any advice. -- Iiro Jantunen * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * void uart0_init(void) { _DINT(); // disable interrupts U0CTL |= SWRST; // set SWRST first to make sure USART is off // set the baud rate to 115 200 UBR00 = 0x45; UBR10 = 0x00; UMCTL0 = 0x00; // the UART mode U0CTL &= SWRST; // unset all else than SWRST U0CTL |= CHAR; // USART Control Register // Use 8-bit data, 1 stop bit, no parity check U0TCTL = SSEL0+SSEL1; // Transmit Control Register // Use SMCLK for baud-rate generation ME1 |= UTXE0; // Enable UART0 transmit (Module Enable 1) U0CTL &= ~SWRST;// clear SWRST IE1 |= UTXIE0; // Enable UART0 tx interrupts (Interrupt Enable 1) IFG1 |= UTXIFG0;// USART transmitter ready (Interrupt Flag Register 1) P3DIR |= BIT4; // Use P3.4 as TX for USART0-module (output) P3SEL |= BIT4; _EINT(); // enable interrupts } char uart0_putchar(unsigned char c) { u16 in; // holds temporary the new transmit in = uart0_tx_wr + 1; // calculate the new transmitt write pointer value if (in >= UART0_BUF_SIZE) // check if the buffer size is exceeded in = 0; // buffer size exceeded -> put the pointer to the start of the buffer if (in == uart0_tx_rd) // check if the new transmit write pointer is the same as the transmit // read pointer which would mean that the buffer is full return 0; // buffer is full else // buffer is not full { uart0_tx_buffer[uart0_tx_wr] = c; // put character into buffer _DINT(); // disable interrupts if (uart0_tx_off) // check if no sending is in process { uart0_tx_rd = in; // set transmit read pointer uart0_tx_off = 0; // set the flag, that sending is in process U0TXBUF = c; // send the character -> send interrupt is triggered } uart0_tx_wr = in; // update transmit write pointer _EINT(); // enable interrupts } return 1; // sending successful }
Problem with register IE1 (UART TX problem)
Started by ●January 16, 2006
Reply by ●January 17, 20062006-01-17
Iiro,
These registers are low in memory - a write to a NULL pointer can cause
this - if you "run out of memory" - anything that
can cause a pointer to be 0x0000 - will cause this to happen. You can put
breakpoints on these values to monitor. This is
a 'weakness' in the MSP430 architecture and tools in my opinion.
Important
system level registers should not be located
beginning at address 0x0000 - at least not in my opinion. I think this is
what is happening to you.
Regards,
John W.
----- Original Message -----
From: "iirojan" <iiro.jantunen@iiro...>
To: <msp430@msp4...>
Sent: Monday, January 16, 2006 12:51 AM
Subject: [msp430] Problem with register IE1 (UART TX problem)
> Hi!
>
> I have a problem with UART0 output to my computer (only TX). The MCU I
> am using is MSP430F169 and I initialize the UART with the code at the
> end of the message. I use IAR V3.30A for compiling and debugging
> (company policy).
>
> UART0 works fine for a while, until something like 160-170 characters
> have been outputted. I have a circular buffer to supply for
> characters. The buffer setup has worked perfectly in my previous
> MSP430 devices (for the exact same purpose). It seems not that the
> buffer causes trouble, as spying the variables reveals nothing special
> there, but what worries me is thate I find the register IE1 to have
> changed when the UART output ceases:
>
> IE1 == 0x01 (i.e. IE1 == WDTIE)
>
> which means that IE1 & UTXIE0 == 0. No surprise that UTX output has
> stopped.
>
> So if I understand the situation correctly, something has changed the
> IE1 register and the UART TX is not active anymore. What could do
> that? I find nothing of the kind in the code, so this should be
> something processor internal. Searching the MSP430x1xx Family User's
> Guide doesn't reveal anything for me about this subject.
>
> Thanks in advance for any advice.
>
> -- Iiro Jantunen
>
> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
>
> void uart0_init(void)
> {
> _DINT(); // disable interrupts
>
> U0CTL |= SWRST; // set SWRST first to make sure USART is off
>
> // set the baud rate to 115 200
> UBR00 = 0x45;
> UBR10 = 0x00;
> UMCTL0 = 0x00;
>
> // the UART mode
> U0CTL &= SWRST; // unset all else than SWRST
> U0CTL |= CHAR; // USART Control Register
> // Use 8-bit data, 1 stop bit, no parity check
> U0TCTL = SSEL0+SSEL1; // Transmit Control Register
> // Use SMCLK for baud-rate generation
>
> ME1 |= UTXE0; // Enable UART0 transmit (Module Enable 1)
>
> U0CTL &= ~SWRST;// clear SWRST
>
> IE1 |= UTXIE0; // Enable UART0 tx interrupts (Interrupt Enable 1)
>
> IFG1 |= UTXIFG0;// USART transmitter ready (Interrupt Flag Register 1)
> P3DIR |= BIT4; // Use P3.4 as TX for USART0-module (output)
> P3SEL |= BIT4;
>
> _EINT(); // enable interrupts
> }
>
> char uart0_putchar(unsigned char c)
> {
> u16 in; // holds temporary the new transmit
> in = uart0_tx_wr + 1;
> // calculate the new transmitt write pointer value
> if (in >= UART0_BUF_SIZE)
> // check if the buffer size is exceeded
> in = 0;
> // buffer size exceeded -> put the pointer to the start of the
> buffer
>
> if (in == uart0_tx_rd)
> // check if the new transmit write pointer is the same as the transmit
> // read pointer which would mean that the buffer is full
> return 0; // buffer is full
> else // buffer is not full
> {
> uart0_tx_buffer[uart0_tx_wr] = c; // put character into buffer
> _DINT(); // disable interrupts
> if (uart0_tx_off) // check if no sending is in process
> {
> uart0_tx_rd = in; // set transmit read pointer
> uart0_tx_off = 0; // set the flag, that sending is in process
> U0TXBUF = c; // send the character -> send interrupt is
> triggered
> }
> uart0_tx_wr = in; // update transmit write pointer
> _EINT(); // enable interrupts
> }
> return 1; // sending successful
> }
>
>
>
>
>
>
>
>
> .
>
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
>
Reply by ●January 17, 20062006-01-17
Perhaps it should also be annunciated that you should NEVER write to a VOID
*.
(including a NULL of course).
A void pointer could be holding any address, including 0, so personally I
wouldn't hold that
against the MSP430, it's a violation of C.
B rgds
Kris
-----Original Message-----
From: msp430@msp4... [mailto:msp430@msp4...] On Behalf Of John C. Westmoreland,
P.E.
Sent: Tuesday, 17 January 2006 5:12 PM
To: msp430@msp4...
Subject: Re: [msp430] Problem with register IE1 (UART TX problem)
Iiro,
These registers are low in memory - a write to a NULL pointer can cause
this - if you "run out of memory" - anything that
can cause a pointer to be 0x0000 - will cause this to happen. You can put
breakpoints on these values to monitor. This is
a 'weakness' in the MSP430 architecture and tools in my opinion.
Important
system level registers should not be located
beginning at address 0x0000 - at least not in my opinion. I think this is
what is happening to you.
Regards,
John W.
----- Original Message -----
From: "iirojan" <iiro.jantunen@iiro...>
To: <msp430@msp4...>
Sent: Monday, January 16, 2006 12:51 AM
Subject: [msp430] Problem with register IE1 (UART TX problem)
> Hi!
>
> I have a problem with UART0 output to my computer (only TX). The MCU I
> am using is MSP430F169 and I initialize the UART with the code at the
> end of the message. I use IAR V3.30A for compiling and debugging
> (company policy).
>
> UART0 works fine for a while, until something like 160-170 characters
> have been outputted. I have a circular buffer to supply for
> characters. The buffer setup has worked perfectly in my previous
> MSP430 devices (for the exact same purpose). It seems not that the
> buffer causes trouble, as spying the variables reveals nothing special
> there, but what worries me is thate I find the register IE1 to have
> changed when the UART output ceases:
>
> IE1 == 0x01 (i.e. IE1 == WDTIE)
>
> which means that IE1 & UTXIE0 == 0. No surprise that UTX output has
> stopped.
>
> So if I understand the situation correctly, something has changed the
> IE1 register and the UART TX is not active anymore. What could do
> that? I find nothing of the kind in the code, so this should be
> something processor internal. Searching the MSP430x1xx Family User's
> Guide doesn't reveal anything for me about this subject.
>
> Thanks in advance for any advice.
>
> -- Iiro Jantunen
>
> * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
>
> void uart0_init(void)
> {
> _DINT(); // disable interrupts
>
> U0CTL |= SWRST; // set SWRST first to make sure USART is off
>
> // set the baud rate to 115 200
> UBR00 = 0x45;
> UBR10 = 0x00;
> UMCTL0 = 0x00;
>
> // the UART mode
> U0CTL &= SWRST; // unset all else than SWRST
> U0CTL |= CHAR; // USART Control Register
> // Use 8-bit data, 1 stop bit, no parity check
> U0TCTL = SSEL0+SSEL1; // Transmit Control Register
> // Use SMCLK for baud-rate generation
>
> ME1 |= UTXE0; // Enable UART0 transmit (Module Enable 1)
>
> U0CTL &= ~SWRST;// clear SWRST
>
> IE1 |= UTXIE0; // Enable UART0 tx interrupts (Interrupt Enable 1)
>
> IFG1 |= UTXIFG0;// USART transmitter ready (Interrupt Flag Register 1)
> P3DIR |= BIT4; // Use P3.4 as TX for USART0-module (output)
> P3SEL |= BIT4;
>
> _EINT(); // enable interrupts
> }
>
> char uart0_putchar(unsigned char c)
> {
> u16 in; // holds temporary the new transmit
> in = uart0_tx_wr + 1;
> // calculate the new transmitt write pointer value
> if (in >= UART0_BUF_SIZE)
> // check if the buffer size is exceeded
> in = 0;
> // buffer size exceeded -> put the pointer to the start of the
> buffer
>
> if (in == uart0_tx_rd)
> // check if the new transmit write pointer is the same as the transmit
> // read pointer which would mean that the buffer is full
> return 0; // buffer is full
> else // buffer is not full
> {
> uart0_tx_buffer[uart0_tx_wr] = c; // put character into buffer
> _DINT(); // disable interrupts
> if (uart0_tx_off) // check if no sending is in process
> {
> uart0_tx_rd = in; // set transmit read pointer
> uart0_tx_off = 0; // set the flag, that sending is in process
> U0TXBUF = c; // send the character -> send interrupt is
> triggered
> }
> uart0_tx_wr = in; // update transmit write pointer
> _EINT(); // enable interrupts
> }
> return 1; // sending successful
> }
>
>
>
>
>
>
>
>
> .
>
>
> Yahoo! Groups Links
>
>
>
>
>
>
>
>
.
Yahoo! Groups Links
Reply by ●January 17, 20062006-01-17
"John C. Westmoreland, P.E." <john@w...> wrote: > These registers are low in memory - a write to a NULL pointer can cause > this - if you "run out of memory" - anything that > can cause a pointer to be 0x0000 - will cause this to happen. You can put > breakpoints on these values to monitor. This is > a 'weakness' in the MSP430 architecture and tools in my opinion. Important > system level registers should not be located > beginning at address 0x0000 - at least not in my opinion. I think this is > what is happening to you. Propably this is exactly what is happening to me. I'm reimplementing a code contributed by a project partner to my company a few years ago. The code implements nanoIP, with a radio interface. The code is poorly written, virtually uncommented, and plagued by difficult to resolve errors. The code is particularly poor about pointers, with a few clear errors like (ri stands for radio interface): uint8_t *ri_count; // [1] global variable ri_count++; // [2] ri_count = responses; // [3] uint8_t *responses ri_count = 0; // [4] if ((uint8_t) ri_count == 1) // [5] if (*ri_count < ri_limit) // [6] response = &(response[*ri_count]); // [7] *ri_count = *ri_count + 1; // [8] [4] and [5] can not be right, that's for sure. But is [2] right? By syntax yes, but neither I or the writer of the code (who has long forgotten this project) can be sure is it good for the functionality without an extensive analysis of the code as a whole. So, propably I have not found all the errors in the code yet. Thanks for the good hint, I'll try to find the remaining errors. -- Iiro Jantunen
Reply by ●January 17, 20062006-01-17
iirojan wrote: > Propably this is exactly what is happening to me. I'm reimplementing a > code contributed by a project partner to my company a few years ago. Good idea to rewrite it, line for line, using clean and type-correct code. You'll find pretty-much all the errors without having to do much design (assuming it all worked once). It's much quicker to rewrite things that you might think. > The code is particularly poor about pointers, with a few clear > errors like (ri stands for radio interface): > uint8_t *ri_count; // [1] global variable No problem there, ri_count points at a uint8_t (presumable a byte) > ri_count++; // [2] Ok, point to the next byte - no drama. > ri_count = responses; // [3] uint8_t *responses point to the same thing that "responses" points to. > ri_count = 0; // [4] No problem here, you're just nullifying the pointer. > if ((uint8_t) ri_count == 1) // [5] Hmm, that's not good, using the pointer as an integer. > if (*ri_count < ri_limit) // [6] if "ri_limit" is a uint8_t, that's fine, as long as ri_count isn't null. > response = &(response[*ri_count]); // [7] This is the same as response += *ri_count; which could be valid, if the value of *ri_count has been checked and won't make response point somewhere illegal. > *ri_count = *ri_count + 1; // [8] Same as *ri_count++, quite legal. > [4] and [5] can not be right, that's for sure. It's possible that the code is ok(-ish) and it's mainly your understanding of C that's flawed. But without the context, I couldn't say. A lot of communications code is wrapping and unwrapping strings of bytes in envelope headers that can be represented by structures. A mistake that beginners make is not to declare structures for the headers, preferring to pack bytes manually instead. Clifford Heath.
Reply by ●January 17, 20062006-01-17
"iirojan" <iiro.jantunen@h...> wrote:
> ri_count = 0; // [4]
OK. Found the problem. Here the pointer ri_count points to memory
address 0 which seems to be IE1. At least this declaration zeroes the IE1.
The trouble seems to be the fact that the original code does not
initialize the "uint8_t *ri_count" at all.
As the ri_count is an global pointer variable, I have trouble
understanding a correct way to initialize it. What is the correct way
(all in global variables)?
char variableA = 0; // initializes nicely
char variableA; // initializes nicely, only does not have a value
char *variableA; // does not initialize at all
char *variableA = malloc(sizeof(char)*10); // does not compile
Of course I could initialize it in init() function, but is it the
correct way?
char *variableA;
void init() {
variableA = malloc(sizeof(char)*10);
}
So what should I do?
--
Iiro Jantunen
Reply by ●January 17, 20062006-01-17
Clifford Heath <cjh@m...> wrote: > Good idea to rewrite it, line for line, using clean > and type-correct code. You'll find pretty-much all > the errors without having to do much design (assuming > it all worked once). It's much quicker to rewrite > things that you might think. Not a very good idea, as far as I found out. The code was "ready to use" as I was told and I was not allocated time to work with it. The code, nanoIP, is quite a complex pile of spaghetti, and I have never before written code for communications software. It has taken an eternity, and I still do not understand most of the logic, ridden with sockets, handlers and interrupts. The functionality of the code, including SPI link to a FPGA, is strictly defined - so I have little possibility to change the structure of the code without complete understanding what I am doing. The code was also written to be used in both MSP430 and AVR microcontrollers and the interoperability was avhieved by using a mess of #ifdef MSP430 ... #ifdef AVR and a few other preprocessor variables. The resulting code was poorly debuggable by Doxygen, because it has little chance of understanding the ifdef mess (should functionA() refer to the definition inside #ifdef MSP430 or #ifdef AVR or other). What I am writing is an sensor server on MSP430, so that (as OSI model states) the layer structure inside the microcontroller is about as follows: SSI (Simple Sensor Interface protocol, see http://ssi-protocol.net) nanoUDP/nanoIP (see http://www.cwc.oulu.fi/nanoip/) radio_interface/upper layer interface SPI ... Thanks for all the hints and suggestions, though. -- Iiro Jantunen
Reply by ●January 17, 20062006-01-17
> ...The code was "ready to use" > ...The code, nanoIP, is quite a complex pile of spaghetti, These facts are contradictory. Which one is true? > and I have never before written code for communications software. Then even if nanoIP was ready to use, you're not ready to use it. > ...a mess of #ifdef MSP430 ... #ifdef AVR and a few other preprocessor So get a copy of scpp and remove all the AVR ifdefs. I'd leave the MSP430 ones though, so you can tell where there are device dependencies. > > ri_count = 0; // [4] > OK. Found the problem. Here the pointer ri_count points to memory > address 0 which seems to be IE1. At least this declaration zeroes the IE1. No it doesn't. It zeroes the pointer. You'd need then to say *ri_count = 0; to zero IE1. A book on C would help also. All your global variables are initialised, whether you declare values for them or not. This is defined by the C language, and if you don't know it, I don't like your chances.
Reply by ●January 17, 20062006-01-17
Hi,
> The code was also written to be used in both
MSP430 and AVR
> microcontrollers and the interoperability was avhieved by using a mess
> of #ifdef MSP430 ... #ifdef AVR and a few other preprocessor
> variables. The resulting code was poorly debuggable by Doxygen,
> because it has little chance of understanding the ifdef mess (should
> functionA() refer to the definition inside #ifdef MSP430 or #ifdef AVR
> or other).
You can provide preprocess symbols to Doxygen.
If you use the WIN GUI, it's one of the options in "Advanced".
B rgds
Kris
Reply by ●January 18, 20062006-01-18
"Clifford Heath" <cjh@m...> wrote: > > ...The code was "ready to use" > > ...The code, nanoIP, is quite a complex pile of spaghetti, > > These facts are contradictory. Which one is true? Both. "Ready to use" meaned that the code worked in another emebedded system setup, on the same type of processor and quite similar architecture. > > and I have never before written code for communications software. > > Then even if nanoIP was ready to use, you're not ready to use it. Exactly. But I'm not here to discuss the distribution of work in my project. Sufficient to say, communications sw layers should have been work of some other people, but they just dumped me the nanoIP code saying that it works in their device. They have been helping me to sort out the mess, but the trouble is that they have not written the code themselves, but or partner years ago - which means they could not tell where the problem lies. > So get a copy of scpp and remove all the AVR ifdefs. I'd leave > the MSP430 ones though, so you can tell where there are device > dependencies. I did it already, manually. Took time, though. The AVR and MSP430 ifdefs were not the only ifdefs... :( > > > ri_count = 0; // [4] > > OK. Found the problem. Here the pointer ri_count points to memory > > address 0 which seems to be IE1. At least this declaration zeroes the > IE1. > > No it doesn't. It zeroes the pointer. You'd need then to say > *ri_count = 0; > to zero IE1. Sorry about my erraneous copying. What was there, was "*ri_count = 0". And that one zeroes the IE1. At least I saw that happening when debugging single steps with IAR. It must be frustrating to read this badly written posts. Sorry about critical typing errors. > A book on C would help also. All your global variables are > initialised, whether you declare values for them or not. > This is defined by the C language, and if you don't know it, > I don't like your chances. I have studied and written C code. Just that I could not find any reference (from the books I have) on what does a declaration like char *pointerA; in global variables exactly do? Where the pointer points to? How much room is in the memory area pointed? I think that is not very self-explaining as code. Thanks for information! -- Iiro Jantunen