Pages: [1]   Go Down
Author Topic: Assembler error, SoftwareSerial, add even parity bit  (Read 1336 times)
0 Members and 1 Guest are viewing this topic.
France
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
  //...
  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:
    //...
    // 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:
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 !
Logged

0
Offline Offline
Shannon Member
****
Karma: 160
Posts: 10416
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

[ I won't respond to messages, use the forum please ]

France
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I could see effectively that, at the beginning and end of function "recv", there are some "push/pop" for registers under certain circumstances :
Code:
#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 !
Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24321
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Have you tried wrapping the stop bit handling in a two iteration for loop?
Logged

"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.

0
Offline Offline
Shannon Member
****
Karma: 160
Posts: 10416
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

[ I won't respond to messages, use the forum please ]

Switzerland
Offline Offline
Faraday Member
**
Karma: 96
Posts: 4702
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
/* 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.
Logged

Pages: [1]   Go Up
Jump to: