AVR gcc, weird array behaviour - c

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

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.

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.

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.

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

Related

AT91 ARM EMAC polling issue

I am using atmel's lwip example. Interfacing with PHY is ok. It can link and even auto negotiate. Netif is going up. But when i start polling netif nothing happens. Ive narrowed down problem to EMAC_Poll
unsigned char EMAC_Poll(unsigned char *pFrame, unsigned int frameSize, unsigned int *pRcvSize)
{
unsigned short bufferLength;
unsigned int tmpFrameSize=0;
unsigned char *pTmpFrame=0;
unsigned int tmpIdx = rxTd.idx;
volatile EmacRxTDescriptor *pRxTd = rxTd.td + rxTd.idx;
ASSERT(pFrame, "F: EMAC_Poll\n\r");
char isFrame = 0;
// Set the default return value
*pRcvSize = 0;
// Process received RxTd
while ((pRxTd->addr & EMAC_RX_OWNERSHIP_BIT) == EMAC_RX_OWNERSHIP_BIT) {
// Never got there.
...
}
return EMAC_RX_NO_DATA;
}
typedef struct {
volatile EmacRxTDescriptor td[RX_BUFFERS];
EMAC_RxCallback rxCb; /// Callback function to be invoked once a frame has been received
unsigned short idx;
} RxTd;
/// Describes the type and attribute of Receive Transfer descriptor.
typedef struct _EmacRxTDescriptor {
unsigned int addr;
unsigned int status;
} __attribute__((packed, aligned(8))) EmacRxTDescriptor, *PEmacRxTDescriptor;
There is while loop, but condition is never goes true.
I have very vague presentation what is RxTd and what exacly this condition means. However i can not see how thise RxTd Would change to pass condition. All references of RxTd leads to same emac.c module. Most of them in that polling function and rest in EMAC_ResetRx function.
static void EMAC_ResetRx(void)
{
unsigned int Index;
unsigned int Address;
// Disable RX
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_RE;
// Setup the RX descriptors.
rxTd.idx = 0;
for(Index = 0; Index < RX_BUFFERS; Index++) {
Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
// Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
rxTd.td[Index].status = 0;
}
rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;
// Receive Buffer Queue Pointer Register
AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
}
I do not realy understand last line, but it looks like that rxTd is auto filled with AT91 itself. If it is so, there may be packing/aligment problem, but Atmel added __attribute__ ((packed, aligned(8))) on RxTd structure definition. Any way, can someone describe mechanism of data input or tell me where proble might be?
By the way i am using gcc, if that matters.
UPD:
Ive checked RSR and notice that it is start with 0, then goes to 2 after second. 2- means new data was captured.
UPD:
So i've read about function of emac in datasheet for my chip. I was right. That RBQP register must point to array of descriptors. Each descriptor consists of address and status field. The datasheet states that "bit zero of address field is written to one to show the buffer has been used". Then ARM uses another rx descriptor from that array. I guess by "has been used" they mean that that buffer is filled with frame data and ready to be processed. This must mean that data just not going to that buffer. But it must be there because REC goes high. Additionaly i've checked that RE in NCR is up and MI is enabled. I have no idea what is wrong.
I've spend whole week to solve it. The funny thing is that if i've dump memory and looked at all those addresses - The data was there whole time! So the key was to disable I and D caching and MMU itself. Hope it will help someone.

Running a block of code from RAM instead of flash

In the following program, what is the meaning of the line of code
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
in the below section of code. I have some idea about what is happening here,In order to overcome read while write violation, copying the code from flash to RAM using the above lines of code. But what is exact meaning of these lines.
static int fnProgram(unsigned long *ptrWord, unsigned long *ptr_ulWord)
{
while ((FTFL_FSTAT & FTFL_STAT_CCIF) == 0) {} // wait for previous commands to complete
if ((FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR)) != 0) { // check for errors in previous command
FTFL_FSTAT = (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_RDCOLERR); // clear old errors
}
FTFL_FCCOB0 = FCMD_PROGRAM; // enter the command sequence
FTFL_FCCOB1 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 16); // set address in flash
FTFL_FCCOB2 = (unsigned char)(((CAST_POINTER_ARITHMETIC)ptrWord) >> 8);
FTFL_FCCOB3 = (unsigned char)((CAST_POINTER_ARITHMETIC)ptrWord);
FTFL_FCCOB7_4 = *ptr_ulWord++; // enter the long word to be programmed
FTFL_FCCOBB_8 = *ptr_ulWord; // enter the second long word to be programmed
uDisable_Interrupt(); // protect this region from interrupts
fnRAM_code((volatile unsigned char *)FLASH_STATUS_REGISTER); // execute the command from SRAM
uEnable_Interrupt(); // safe to accept interrupts again
return (FTFL_FSTAT & (FTFL_STAT_ACCERR | FTFL_STAT_FPVIOL | FTFL_STAT_MGSTAT0)); // if there was an error this will be non-zero
}
The only code that needs to be in RAM is this:
static void fnFlashRoutineInRam(volatile unsigned char *ptrFTFL_BLOCK)
{
*ptrFTFL_BLOCK = FTFL_STAT_CCIF; // launch the command - this clears the FTFL_STAT_CCIF flag (register is FTFL_FSTAT)
while ((*ptrFTFL_BLOCK & FTFL_STAT_CCIF) == 0) {} // wait for the command to terminate
}
This looks like older NXP (former Freescale/Motorola) HCS08, HCS12 or Coldfire. On those devices, you have different cases when writing a flash driver: either you can execute it from flash or you cannot. This entirely depends on which "bank" the program flash belongs to: generally you cannot execute code on a MCU from the very same flash bank it is currently programming.
So ideally you put the flash programming code in another bank, but some devices only have one single flash bank. Then they provide a work-around by executing the code from RAM, which is kind of a quick & dirty fix.
Commonly they solve this by providing an array of raw data op codes. This array of op codes is copied to RAM and then they set a function pointer to point at the RAM address. I suspect fnRAM_code is such a function pointer. The (volatile unsigned char *)FLASH_STATUS_REGISTER part is simply passing on the address of the flash status register. Likely, FLASH_STATUS_REGISTER is synonymous with FSTAT.
The uDisable_Interrupt(); and uEnable_Interrupt(); should correspond to asm SEI and asm CLI respectively, blocking all maskable interrupts from triggering during the flash write, which would potentially cause the write to fail or the program to hang up.
There should be app notes available describing all of this in detail.
Please note that this code is very close to the hardware and relies on tons of poorly-defined behavior. I wouldn't count on it compiling as expected on anything but the Codewarrior compiler. gcc would for example spew out numerous strict aliasing bugs.

Uart receives correct Bytes but in chaotic order

Using Atmel studio 7, with STK600 and 32UC3C MCU
I'm pulling my hair over this.
I'm sending strings of a variable size over UART once every 5 seconds. The String consists of one letter as opcode, then two chars are following that tell the lenght of the following datastring (without the zero, there is never a zero at the end of any of those strings). In most cases the string will be 3 chars in size, because it has no data ("p00").
After investigation I found out that what supposed to be "p00" was in fact "0p0" or "00p" or (only at first try after restarting the micro "p00"). I looked it up in the memory view of the debugger. Then I started hTerm and confirmed that the data was in fact "p00". So after a while hTerm showed me "p00p00p00p00p00p00p00..." while the memory of my circular uart buffer reads "p000p000p0p000p0p000p0p0..."
edit: Actually "0p0" and "00p" are alternating.
The baud rate is 9600. In the past I was only sending single letters. So everything was running well.
This is the code of the Receiver Interrupt:
I tried different variations in code that were all doing the same in a different way. But all of them showed the exact same behavior.
lastWebCMDWritePtr is a uint8_t* type and so is lastWebCMDRingstartPtr.
lastWebCMDRingRXLen is a uint8_t type.
__attribute__((__interrupt__))
void UartISR_forWebserver()
{
*(lastWebCMDWritePtr++) = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
lastWebCMDRingRXLen++;
if(lastWebCMDWritePtr - lastWebCMDRingstartPtr > lastWebCMDRingBufferSIZE)
{
lastWebCMDWritePtr = lastWebCMDRingstartPtr;
}
// Variation 2:
// advanceFifo((uint8_t)((&AVR32_USART0)->rhr & 0x1ff));
// Variation 3:
// if(usart_read_char(&AVR32_USART0, getReadPointer()) == USART_RX_ERROR)
// {
// usart_reset_status(&AVR32_USART0);
// }
//
};
I welcome any of your ideas and advices.
Regarts Someo
P.S. I put the Atmel studio tag in case this has something to do with the myriad of debugger bugs of AS.
For a complete picture you would have to show where and how lastWebCMDWritePtr, lastWebCMDRingRXLen, lastWebCMDRingstartPtr and lastWebCMDRingBufferSIZE are used elsewhere (on the consuming side)
Also I would first try a simpler ISR with no dependencies to other software modules to exclude a hardware resp. register handling problem.
Approach:
#define USART_DEBUG
#define DEBUG_BUF_SIZE 30
__attribute__((__interrupt__))
void UartISR_forWebserver()
{
uint8_t rec_byte;
#ifdef USART_DEBUG
static volatile uint8_t usart_debug_buf[DEBUG_BUF_SIZE]; //circular buffer for debugging
static volatile int usart_debug_buf_index = 0;
#endif
rec_byte = (uint8_t)((&AVR32_USART0)->rhr & 0x1ff);
#ifdef USART_DEBUG
usart_debug_buf_index = usart_debug_buf_index % DEBUG_BUF_SIZE;
usart_debug_buf[usart_debug_buf_index] = rec_byte;
usart_debug_buf_index++
if (!(usart_debug_buf_index < DEBUG_BUF_SIZE)) {
usart_debug_buf_index = 0; //candidate for a breakpoint to see what happened in the past
}
#endif
//uart_recfifo_enqueue(rec_byte);
};

Reading serial port faster

I have a computer software that sends RGB color codes to Arduino using USB. It works fine when they are sent slowly but when tens of them are sent every second it freaks out. What I think happens is that the Arduino serial buffer fills out so quickly that the processor can't handle it the way I'm reading it.
#define INPUT_SIZE 11
void loop() {
if(Serial.available()) {
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
input[size] = 0;
int channelNumber = 0;
char* channel = strtok(input, " ");
while(channel != 0) {
color[channelNumber] = atoi(channel);
channel = strtok(0, " ");
channelNumber++;
}
setColor(color);
}
}
For example the computer might send 255 0 123 where the numbers are separated by space. This works fine when the sending interval is slow enough or the buffer is always filled with only one color code, for example 255 255 255 which is 11 bytes (INPUT_SIZE). However if a color code is not 11 bytes long and a second code is sent immediately, the code still reads 11 bytes from the serial buffer and starts combining the colors and messes them up. How do I avoid this but keep it as efficient as possible?
It is not a matter of reading the serial port faster, it is a matter of not reading a fixed block of 11 characters when the input data has variable length.
You are telling it to read until 11 characters are received or the timeout occurs, but if the first group is fewer than 11 characters, and a second group follows immediately there will be no timeout, and you will partially read the second group. You seem to understand that, so I am not sure how you conclude that "reading faster" will help.
Using your existing data encoding of ASCII decimal space delimited triplets, one solution would be to read the input one character at a time until the entire triplet were read, however you could more simply use the Arduino ReadBytesUntil() function:
#define INPUT_SIZE 3
void loop()
{
if (Serial.available())
{
char rgb_str[3][INPUT_SIZE+1] = {{0},{0},{0}};
Serial.readBytesUntil( " ", rgb_str[0], INPUT_SIZE );
Serial.readBytesUntil( " ", rgb_str[1], INPUT_SIZE );
Serial.readBytesUntil( " ", rgb_str[2], INPUT_SIZE );
for( int channelNumber = 0; channelNumber < 3; channelNumber++)
{
color[channelNumber] = atoi(channel);
}
setColor(color);
}
}
Note that this solution does not require the somewhat heavyweight strtok() processing since the Stream class has done the delimiting work for you.
However there is a simpler and even more efficient solution. In your solution you are sending ASCII decimal strings then requiring the Arduino to spend CPU cycles needlessly extracting the fields and converting to integer values, when you could simply send the byte values directly - leaving if necessary the vastly more powerful PC to do any necessary processing to pack the data thus. Then the code might be simply:
void loop()
{
if( Serial.available() )
{
for( int channelNumber = 0; channelNumber < 3; channelNumber++)
{
color[channelNumber] = Serial.Read() ;
}
setColor(color);
}
}
Note that I have not tested any of above code, and the Arduino documentation is lacking in some cases with respect to descriptions of return values for example. You may need to tweak the code somewhat.
Neither of the above solve the synchronisation problem - i.e. when the colour values are streaming, how do you know which is the start of an RGB triplet? You have to rely on getting the first field value and maintaining count and sync thereafter - which is fine until perhaps the Arduino is started after data stream starts, or is reset, or the PC process is terminated and restarted asynchronously. However that was a problem too with your original implementation, so perhaps a problem to be dealt with elsewhere.
First of all, I agree with #Thomas Padron-McCarthy. Sending character string instead of a byte array(11 bytes instead of 3 bytes, and the parsing process) is wouldsimply be waste of resources. On the other hand, the approach you should follow depends on your sender:
Is it periodic or not
Is is fixed size or not
If it's periodic you can check in the time period of the messages. If not, you need to check the messages before the buffer is full.
If you think printable encoding is not suitable for you somehow; In any case i would add an checksum to the message. Let's say you have fixed size message structure:
typedef struct MyMessage
{
// unsigned char id; // id of a message maybe?
unsigned char colors[3]; // or unsigned char r,g,b; //maybe
unsigned char checksum; // more than one byte could be a more powerful checksum
};
unsigned char calcCheckSum(struct MyMessage msg)
{
//...
}
unsigned int validateCheckSum(struct MyMessage msg)
{
//...
if(valid)
return 1;
else
return 0;
}
Now, you should check every 4 byte (the size of MyMessage) in a sliding window fashion if it is valid or not:
void findMessages( )
{
struct MyMessage* msg;
byte size = Serial.readBytes(input, INPUT_SIZE);
byte msgSize = sizeof(struct MyMessage);
for(int i = 0; i+msgSize <= size; i++)
{
msg = (struct MyMessage*) input[i];
if(validateCheckSum(msg))
{// found a message
processMessage(msg);
}
else
{
//discard this byte, it's a part of a corrupted msg (you are too late to process this one maybe)
}
}
}
If It's not a fixed size, it gets complicated. But i'm guessing you don't need to hear that for this case.
EDIT (2)
I've striked out this edit upon comments.
One last thing, i would use a circular buffer. First add the received bytes into the buffer, then check the bytes in that buffer.
EDIT (3)
I gave thought on comments. I see the point of printable encoded messages. I guess my problem is working in a military company. We don't have printable encoded "fire" arguments here :) There are a lot of messages come and go all the time and decoding/encoding printable encoded messages would be waste of time. Also we use hardwares which usually has very small messages with bitfields. I accept that it could be more easy to examine/understand a printable message.
Hope it helps,
Gokhan.
If faster is really what you want....this is little far fetched.
The fastest way I can think of to meet your needs and provide synchronization is by sending a byte for each color and changing the parity bit in a defined way assuming you can read the parity and bytes value of the character with wrong parity.
You will have to deal with the changing parity and most of the characters will not be human readable, but it's gotta be one of the fastest ways to send three bytes of data.

USART transmit problems on a PIC

I'm trying to send data to an SD card from a PIC18f4580, but the PIC is not sending what it should be.
related global variables:
unsigned char TXBuffer[128]; //tx buffer
unsigned char TXCurrentPos = 0x00; //tracks the next byte to be sent
unsigned char TXEndPos = 0x00; //tracks where new data should be put into the array
I am adding data to a buffer using the following function:
void addToBuffer(char data){
TXBuffer[TXEndPos] = data;
TXEndPos++;
}
And putting the data from the TXBuffer into TXREG with the following interrupt:
else if (PIR1bits.TXIF == 1){
if((TXEndPos - TXCurrentPos) > 0){ // if there is data in the buffer
TXREG = TXBuffer[TXCurrentPos]; // send next byte
TXCurrentPos++; // update to the new position
}
Using an oscilloscope I am able to see that the PIC is sending 0x98, regardless of what I put into the buffer. In fact I never put 0x98 into the buffer.
However, if I replace
TXREG = TXBuffer[TXCurrentPos];
with
TXREG = 0x55;
or
TXREG = TXCurrentPos;
then I get the expected results, that is the PIC will send 0x55 repeatedly, or count up from 0 respectively.
So why does the PIC have trouble sending data from the array, but any other time it is fine? I'll emphasize that transferring is handled in an interrupt, because I feel like that's the root of my issue.
EDIT: It is a circular buffer in the sense that TXEndPos and TXCurrentPos return to 0 when they reach 127.
I also disable the transmit interrupt when TXEndPos - TXCurrentPos == 0, and re-enable it when adding data to the buffer. Really, my code works completely as expected in that if I add 13 characters to TXBuffer in main, my PIC will transmit 13 characters and then stop. The problem is that they are always the same (wrong) character - 0x98.
EDIT2: more complete functions are here: http://pastebin.com/MyYz1Qzq
Perhaps TXBuffer doesn't really contain the data you think it does? Maybe you're not calling addToBuffer or calling it at the wrong time or with the wrong parameter?
You can try something like this in your interrupt handler:
TXBuffer[TXCurrentPos] = TXCurrentPos;
TXREG = TXBuffer[TXCurrentPos];
TXCurrentPos++;
Just to prove to yourself you can read and write to TXBuffer and send that to the USART.
Also try:
TXREG = TXEndPos;
To see if this matches your expectation (= the length of your message).
I am assuming there's some other code we're not seeing here that takes care of starting the transmission. Also assuming this is done per message with the position being reset between messages - i.e. this is not supposed to be a circular buffer.
EDIT: Based on looking at the more recently posted code:
Don't you need to kickstart the transmitter by writign the first byte of your buffer to TXREG? What I would normally do is enable the interrupt and write the first byte into the transmit register and a quick look at the datasheet seems to indicate that's what you need to do. Another thing is I still don't see how you ensure a wraparound from 127 to 0?
Also your main() seems to just end abruptly, where does the execution continue once main ends?
There are a lot of things you are not taking care of. TXBuffer needs to be a circular buffer. Once you increment TXEndPos past 127 then you need to wrap it back to 0. Same for TXCurrrentPos. That also affects the test to see if there's something in the buffer, the > 0 test isn't good enough. Generic advice is available here.
Your code is incomplete, but it looks wrong as-is: what happens if there is nothing to send? You don't seem to load TXREG then, so why would anything be transmitted, be it 0x98 or anything else?
The way it is usually done when this kind of code architecture is used is to turn off TXIE if there is nothing to send (in a else part of the IRQ routine), and turn it on unconditionally at the end of the addToBuffer function (since you then know for sure that there is at least one character to send).
Also, you should test TXEndPos and TXCurrentPos for equality directly, since that would let you use a circular buffer very easily by adding two modulo operations.

Resources