Hello, I'm reporting a bug here, since I'm 99,9% sure it's not a real bug and you guys can help me! :D
I'm having troubles with the optimization levels of the avr-gcc compiler. My code works fine if i'm using -o0 or -o1, but it doesn't work if I use -o2.
I'm using the MACB of a UC3A. In general the Ethernet communication works fine, but in a certain part of my code - with -o2 on - a packet is not sent when it should be. I believe the error is in this part of the code:
My code calls an Ethernet driver function and gives the driver a pointer to a struct, which contains the data to be sent out and a pointer to the size of the data (*int). Immediately after the driver has been called, the size of the data is reset to zero:
//Set the size pointer stTx.puiSize=&stCommunication.stTx.uiBufferSize; //Write to ethernet driver dev_eth_write(&stTx); // Initialise size to zero stCommunication.stTx.uiBufferSize=0;
The Ethernet driver function formulates the packet headers and calls the software framework function lMACBSend to send out the packet:
int dev_eth_write( const transmit_struct *stPtr ) { // Set protocol parameters ucaEthHeader[ APCI_PROT_PLACE + APCI_HEADER_PLACE_OFFSET ] = stPtr->uiProtId; // Set destination mac address memcpy( &ucaEthHeader[ETH_HEADER_PLACE_OFFSET + ETH_DEST_MAC_PLACE], stPtr->pucMac, ETH_DEST_MAC_SIZE); // Copy header data to the frame memcpy(ucaEthernetUserData, ucaEthHeader, CONST_ETH_HEADER_SIZE); // Copy user data to the frame memcpy( &ucaEthernetUserData[ CONST_ETH_HEADER_SIZE ], stPtr->pucData, *stPtr->puiSize); // Send the data lMACBSend(&AVR32_MACB, ucaEthernetUserData, *stPtr->puiSize + CONST_ETH_HEADER_SIZE,TRUE); return 0; }
I use this same function for sending data all the time and it works just fine. Only when -o2 is used and the code above calls the function, nothing is sent out.
If I modify the Ethernet driver slightly by introducing a variable 'a' which contains the size of the packet and change the call to lMACBSend to use the variable 'a' as the size, everything suddenly works!
int dev_eth_write( const transmit_struct *stPtr ) { // Copy size to a int a = *stPtr->puiSize+CONST_ETH_HEADER_SIZE; // Set protocol parameters ucaEthHeader[ APCI_PROT_PLACE + APCI_HEADER_PLACE_OFFSET ] = stPtr->uiProtId; // Set destination mac address memcpy( &ucaEthHeader[ETH_HEADER_PLACE_OFFSET + ETH_DEST_MAC_PLACE], stPtr->pucMac, ETH_DEST_MAC_SIZE); // Copy header data to the frame memcpy(ucaEthernetUserData, ucaEthHeader, CONST_ETH_HEADER_SIZE); // Copy user data to the frame memcpy( &ucaEthernetUserData[ CONST_ETH_HEADER_SIZE ], stPtr->pucData, *stPtr->puiSize); // Send the data with size a lMACBSend(&AVR32_MACB, ucaEthernetUserData, a,TRUE); return 0; }
Or if I add a gpio toggle between the call to the driver and setting the size to zero, everything works.
Have you heard of anything like this before? Any ideas on how to investigate this further and fix this? There are some minor differences in the disassemblies with and without 'a', but I don't understand (optimized) assembler enough to spot any problems. :(