0

it's the first time I see something like this. I'm starting to suspect it's a hardware fault. whenever I try to send the contents of array "test" and that array is larger than 4 elements or I initialize all elements in the declaration it contains 0xff instead of values I try to initialise with.

this works fine. when I read values from the array in while(sending them to the lcd and uart) both readouts are consistent with test values:

uint8_t i=0;
uint8_t test[4] = {1,2,3,4};
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
 }

this doesn't, it returns 0xff instead of test[i] value:

uint8_t i=0;
uint8_t test[5] = {1,2,3,4,5};
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
 }

but this works! it returns proper values

uint8_t i=0;
uint8_t test[6] = {1,2,3,4,5};
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
 }

this also works:

uint8_t i=0;
uint8_t test[5];
test[0]=1;
test[1]=2;
test[2]=3;
test[3]=4;
test[4]=5;
     while(i<5){
     GLCD_WriteData(test[i]);
     USART_Transmit(test[i]);
     i++;
     }

it works fine when compiled on linux

I swapped out an mcu for a different one and it works the way it should. must be an hardware problem

5
  • 1
    This question is not particularly clear. Please don't just paste code and make us mentally diff it. Explain what the problem is. You say "returns 0xFF" - from where? That code is not shown anywhere. If your problem is in transmitting, why do we care about receive-side results? Isolate the problem. You're transmitting out a UART, right? Well then the obvious debugging step is to see what's actually coming out of the port. Commented Jun 11, 2016 at 12:50
  • 1
    You realize that, even though your array size changes, the bounds of your loop never changes, right? It's always while(i<5). This is why an ARRAY_LENGTH macro is useful. Commented Jun 11, 2016 at 12:51
  • I edited my post to form it properly. the problem is, that when I initialize the array in the way I normaly do it array[]={1,2,3} and it's larger than 4 elements instead of my values it contains 0xff's. when I declare an 6 or more element array and initalize it skipping the last element it works fine. I didn't change (i<5) values out of lazyness, it doesn't affect the problem. if the array has 4 elements it prints them out properly + one junk one, if it has 5 elements it prints 0xff five times, if it has 6 elements but 5 are initialized there are five proper values Commented Jun 11, 2016 at 13:06
  • I assume that in your first block, the while should be while (i<4) {? Commented Jun 11, 2016 at 13:11
  • probably some flow control problem with the port Commented Jun 14, 2016 at 10:14

4 Answers 4

1

In first example you are going out of bounds of array test[4]. You are running while 5 times, when array has only 4 items length.

Sign up to request clarification or add additional context in comments.

1 Comment

Although he said the first example works but the second example doesn't.
0

I think your problem is that you're overloading the USART. I assume that GLCD_WriteData() is VERY quick, and that USART_Transmit() buffers the character for transmission and then quickly returns. I don't know your hardware, so I can't tell - but a four-character buffer for a USART sounds reasonable.

Your five-character examples don't work because the actual character that you're trying to transmit is lost - so it puts an 0xFF in instead. You need to check the state of the USART buffer and wait for it to show that space is available (note NOT empty - that'd be inefficient!).

In the 8250 and 16450 UART chips there are two status bits:

  • TSRE says that the Transmit Shift Register is Empty;
  • THRE says that the Transmit Holding Register is Empty.

THRE can be set even when TSRE isn't - it's busy. I'd test TSRE and not send the next character until there's room - or set up a buffer and an interrupt handler.

1 Comment

the I/O hardware is not the problem, MCU checks the busy flag on the lcd and USART_transmit is just a single character hardware buffer and empty while that stops the program until buffer empty flag is set. I can make an array of 128 elements, assign values to them in a while loop and it will print them out fine. for some weird reason if I do array[5] = {1,2,3,4,5} and read it through a while loop it's all 0xFF. also another thing, if I read it one by one: USART_Transmit(array[0]).. to 5 it's fine, but if I'll add a read by while to that code it suddenly becomes 0xff in both cases
0

If it's not the I/O hardware, then the only other thing that I can think of is the compiler is producing incorrect code. What is the exact declaration of USART_Transmit()? Does it expect a uint8_t? Or something else, like an int (for some reason)?

If it's something else, like int, please try the following code:

while(i<5){
    int c = test[i];         // Whatever USART_Transmit wants
    GLCD_WriteData(test[i]);
    USART_Transmit(c);
    i++;
} // while

If that always works, then you've got a compiler problem, not a hardware problem.

EDIT: Code for USART_Transmit() provided:

void USART_Transmit( uint8_t data ) {
//Wait for empty transmit buffer
while( !( UCSR0A & (1<<UDRE0)) );
//Put data into buffer, sends the data
UDR0 = data;
}

You've got something better than JTAG - you've got an LCD display! Although I don't know how many characters it has, or how long it takes to transmit a character...

You could try something like:

char Hex(uint8_t nibble) {
    return nibble<10 ?
           '0'+nibble :
           'A'+nibble-10;
} // Hex
...
void Send(uint8_t c) {
    uint8_t s;
    UDR0 = c; // Send character NOW: don't wait!
    do {
        s = UCSR0A; // Get current USART state
        //s = UCSR0A & (1<<UDRE0); // Or this: isolate ready bit...
        GLCD_WriteData('x');
        GLCD_WriteData(Hex(s >> 4));  // Write state-hi hex
        GLCD_WriteData(Hex(s & 0xF)); // Write state-lo hex
    } while (!(s & (1<<UDRE0)));      // Until is actually ready
} // Send(c)
...
Send('A');
Send('B');
Send('C');

Assuming that UDRE0 is 3, then that code will result in a sequence like x00x00x00x00x00x08x00x00x00x00x08x00x00x00x08 if it is working. If it produces x08x08x08 then you've got a stuck UCSR0A bit, and it's hardware.

1 Comment

void USART_Transmit( uint8_t data ) { //Wait for empty transmit buffer while( !( UCSR0A & (1<<UDRE0)) ); //Put data into buffer, sends the data UDR0 = data; } your code has the same resault five 0xFF's. I'm sure transmiting works, because if I replace test[i] with just 'i' even if it's an int I get the expected sequence 0-4. I wish I had a JTAG so I could take a peek in to the memory. I'm giving up on this one. I compiled it for other chip I had and it works fine. it will do for now. Thanks for trying to help! I'll just assume the problem is in the silocon
0

Old question, but giving my feedback since this is the first place I got sent while searching solution for same issue, getting even exact same results with the code samples in original question.

For me it was a bad Makefile that caused some sections to be left out by avr-objcopy as far as I know.

For example in my case, the original parameters for building my sample hex that were causing this issue:

${OBJCOPY} -j .text -O ihex led.elf led.hex

What worked a bit better:

${OBJCOPY} -O ihex -R .eeprom led.elf led.hex

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.