Weird problem - Software serial fails due to large procedure.

Go To Last Post
5 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I’m  using a ATMega328p, which connects to a LCD screen via the HW UART.

There have never been problems, however memory is tight so am using the onboard screen memory to store data. To this end the write to memory code is autogenerated and placed in a procedure:

void WriteDataItems(){
    uchar com[8]={0xAA, 0x90,0x55,0xAA,0x5A,0xA5,0x01,0xDE};
    uchar eof[4]={0xCC,0x33,0xC3,0x3C};
    Serial.clearRx();
    Serial.write(com,8);
    Serial.write(0x00); //mem addr MSB  - (The mem addr is offset due to table)
    Serial.write(0x5A); // mem addr LSB - (The mem addr is offset due to table)
    uchar data0[6]= {0x4D , 0x6F , 0x6E , 0x64 , 0x61 , 0x79};//Data
    Serial.write(data0,6);
    Serial.write(eof, 4);
    while (!Serial.available())
    delay(25);
    Serial.clearRx();
    Serial.write(com,8);
    Serial.write(0x00);
    Serial.write(0x60);
    uchar data1[7]= {0x54 , 0x75 , 0x65 , 0x73 , 0x64 , 0x61 , 0x79};
    Serial.write(data1,7);
    Serial.write(eof, 4);
    while (!Serial.available())

...........and so on.......

WriteDataItems() was called at the end of Setup(), and the Loop() was immediately returned from (else not enough memory to run).

Once done, the original program can use the data. This worked fine until  void WriteDataItems(){ became too large. Then the initialisation of the SoftwareSerial  Emic2 txt to speech module failed:
    
 

  void SoftwareSerial::begin(long speed)
{
 if (baud == speed)
    {
      _rx_delay_centering = pgm_read_word(&table[i].rx_delay_centering);
      _rx_delay_intrabit = pgm_read_word(&table[i].rx_delay_intrabit);
      _rx_delay_stopbit = pgm_read_word(&table[i].rx_delay_stopbit);
      _tx_delay = pgm_read_word(&table[i].tx_delay); //FAILS here kicks back to wiring.c - init()
      break;

So the fail occurs before WriteDataItems() is entered, and basically the program loops between SoftwareSerial begin() and init() [in wiring.c].

 

Had thought it could be some stack issue, but the Data memory seems ok?
Program Memory Usage     :    17812 bytes   54.4 % Full
Data Memory Usage         :    1601 bytes   78.2 % Full

 

Well it does not really matter, since the workaround is to call this before emic2 and return. I just wondered if anyone had an idea as to what is happening? ‘cos I don’t.

 

This topic has a solution.
Last Edited: Thu. Feb 2, 2017 - 10:40 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

78% data could be dangerously high dependent on additional use of stack frame autos. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, something like that could explain the weirdness.

If the write to memory code is omitted the memory usage is:

 

Program Memory Usage     :    9232 bytes   28.2 % Full
Data Memory Usage         :    999 bytes   48.8 % Full

 

The data is written in separately declared arrays:

  uchar data0[6]= {0x4D , 0x6F , 0x6E , 0x64 , 0x61 , 0x79};
    Serial.write(data0,6);

I would of thought that any data memory used would be reclaimed by the -Os optimisation.

There are 22 data arrays ranging from 6 to around 60 Bytes.

 

 

 

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the arrays are constant then put them in progmem. This puts it in flash rather than ram

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, that should be done. Had not realised all consts are copied to RAM.

 

Found a library that does the work; have only used it for strings and it seems to work fine:

http://arduiniana.org/libraries/flash/