Go Down

Topic: Assembler error, SoftwareSerial, add even parity bit (Read 1 time) previous topic - next topic

AlyTech

Using serial communication on a Mega2560 board, I need to talk to devices with which "even" parity is required (no way to select "no" parity on those devices).
Then, when sending data, I have to add one bit ("0" if not inverted, because I have 8 data bits) between data bits and stop bit, and when receiving data, I have to read one bit between data bits and stop bit.
I created "ParitySoftwareSerial" library, based on "SoftwareSerial".
If I just modify function "write" by adding :
Code: [Select]

  //...
  if (_inverse_logic)
  {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
        //...
    }
    // write the even parity bit : we sent 8 bits, so we send "1" :
    tx_pin_write(HIGH);
    tunedDelay(_tx_delay);
    //...
  }
  else
  {
    for (byte mask = 0x01; mask; mask <<= 1)
    {
        //...
    }
    // write the even parity bit : we sent 8 bits, so we send "0" :
    tx_pin_write(LOW);
    tunedDelay(_tx_delay);
    //...
  }
  //...

...when I recompile my sketch using the libray, it works.

But when I modify "recv" by adding :
Code: [Select]

    //...
    // Read each of the 8 bits
    for (uint8_t i=0x1; i; i <<= 1)
    {
        //...
    }
    // skip the parity bit
    tunedDelay(_rx_delay_stopbit); // I use delay defined for stop bit...
    DebugPulse(_DEBUG_PIN2, 1);
    // skip the stop bit
    //...

I receive a compiler error :
Code: [Select]

Assembler messages:
C:\Users\Alytech\AppData\Local\Temp/cczbUxov.s:227: Error: register r24, r26, r28 or r30 required


And if I just commentthe two added lines (by adding "//" in front of them), compiling is ok.

Does anyone have an idea or can show me where to search to get an answer to my problem ?

Thank you very much in advance !

MarkT

Well recv() has a workaround for certain versions of avr-gcc (saving some registers on the stack in assembler) - there is a compiler issue under OSX with some versions of avr-gcc - perhaps this is hitting you too?
[ I won't respond to messages, use the forum please ]

AlyTech

I could see effectively that, at the beginning and end of function "recv", there are some "push/pop" for registers under certain circumstances :
Code: [Select]

#if GCC_VERSION < 40302
// Work-around for avr-gcc 4.3.0 OSX version bug
// Preserve the registers that the compiler misses
// (courtesy of Arduino forum user *etracer*)
  asm volatile(
    "push r18 \n\t"
    "push r19 \n\t"
    "push r20 \n\t"
    "push r21 \n\t"
    "push r22 \n\t"
    "push r23 \n\t"
    "push r26 \n\t"
    "push r27 \n\t"
    ::);
#endif 


But I am running MS-Windows 7 Pro (not Mac OSX). Are they some known bugs in such a situation too ?
Anywya, I don't care, I just want things to work. How can I solve this ?

Thank You in advance for Your precious help !

AWOL

Have you tried wrapping the stop bit handling in a two iteration for loop?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

MarkT

I don't know the details, but its a bug triggered when an interrupt routine calls another routine.  If interrupt routine does all the work itself rather than calling a subroutine, I suspect that might cure things - so you'd need to re-write a copy of SoftwareSerial to do things this way.

The underlying problem is probably that the calling convention used in avr-gcc is not the same as that used by the hardware interrupt-handling.

It might be worth investigating which version of avr-gcc you have and what the current version is - try upgrading to that (but be prepared to back-out again!).  I know my (elderly) ubuntu install is using v. 4.3.5, if you post the complete SoftwareSerial mod you have some of us could test if it compiles on their installs.
[ I won't respond to messages, use the forum please ]

pylon

It doesn't look related but change tunedDelay() the following routine:

Code: [Select]
/* static */
inline void SoftwareSerial7e1::tunedDelay(volatile uint16_t delay) {
  volatile uint8_t tmp=0;
  asm volatile("sbiw    %0, 0x01 \n\t"
    "ldi %1, 0xFF \n\t"
    "cpi %A0, 0xFF \n\t"
    "cpc %B0, %1 \n\t"
    "brne .-10 \n\t"
    : "+r" (delay), "+a" (tmp)
    : "0" (delay)
    );
   
}


Note the added volatile statements. For me it compiles so.

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy