1
\$\begingroup\$

I am quite new to AVR programming and I am currently having some troubles with arrays.

I am trying to write an Arduino code that will be run on a Atmega32u4. The goal is to communicate with a AX12-A Dynamixel servo (Atmega8) that has the publicly available firmware.

Before writing down this Arduino code, I wanted to play around with the firmware code and I realized I was not able to manipulate arrays.

I modified the firmware so the LED on AX12-A is constantly blinking. Here comes some lines of code that make the Atmega8 crash (no blinking) :

uint8_t testArray[5] = {0x42, 0, 0, 0, 0}; 
SendMSG(testArray, 1, 0xFE); // works (the LED is constantly blinking)
// SendMSG(testArray, 0, 0xFE); // works as well

The function SendMsg is just a serial writing. testArray is the data to write, 1 the length and 0xFE is the device to which the data must be sent.

void SendMSG(uint8_t *Array, uint8_t length,uint8_t DestinationID)

To check what the servo is sending, I wrote a small Arduino code uploaded on a Leonardo to "spy" on serial communication. This is what I get with the working snippet:

Response: AA // packet header
Response: 3  // packet length
Response: FE // destination ID
Response: FF // origin ID
Response: 42 // data
Response: BA // checksum
(and this sequence is repeated again and again)

This is exactly what I am supposed to receive. Here is a code snippet that doesn't work (the LED is not blinking):

uint8_t testArray[5] = {0x42, 0x02, 0, 0, 0};
SendMSG(testArray, 1, 0xFE); // doesn't work
// SendMSG(testArray, 0, 0xFE); // doesn't work either

And I don't see anything on serial communication using the previous "serial spy".

And even more surprising:

uint8_t u8Data[50];   // define at begin of main
(...)
u8Data[0] = 3; // this line make the code crash (no blinking)

(...)
if(u8Data[0]==BROADCAST_ID)
(...)
if(u8Data[0]==MY_ID)

So I have an array defined and ANY modification on it will make it crash. Please note I am not doing anything on that array, except checking if its first value is equal to BROADCAST_ID (= 255) or MY_ID (=1 or -1 if error). How do I know this specific line makes my code crash ? Because if I comment it, my LED is blinking normally.

As you can guess, programming becomes very limited when you can't achieve those trivial operation.

I really don't understand why this is happening. Maybe this come from the Makefile used in the github project? (Please note that even if the project's name explicitly mentioned atmega328p, the Makefile seems to be designed for Atmega8).

Note: To flash my Atmega8, I compiled my code using the Makefile in the above github project and then I used RoboPlus to upload on the AX12-A (instructions at the end of this page).

Full code:

/*************************************************
Firmware developed for AX12 servo
ATMega8 processor at 16MHz
by: Ricardo Marinheiro
February 2011
robosavvy
Move Interactive
*************************************************

Changes
V1.0 to V1.2
This version bugs fix:
 - Serial buff reset on test to Message Length keeper and not to buff Length

Improves:
 - Led does not fade, short fast blinks.
 - Fail safe counter created to avoid break on cycling for position,
   when missing previouse messages from previouse servos on chain.
 - Controlling servos just by PWM and cycling for position, the frame, now possible at least at 600fps
 - Fail safe created for speed up syncronization on frame receiving scrambling.

*************************************************/
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <ctype.h>
#include <stdbool.h>

#include "Motor.h"
#include "UtilsAndDefines.h"
#include "Serial.h"
#include "Control.h"
#include "Eprom.h"





#define INIT_DELAY 10 //ms


#define RAMVarSize (EEVarSize+0x0007)
#define GoalPositionLow_Addr    (EEVarSize+0)
#define GoalPositionHi_Addr     (EEVarSize+1)
#define GoalSpeed_Addr          (EEVarSize+2)
#define TemperatureLow_Addr     (EEVarSize+3)
#define TemperatureHi_Addr      (EEVarSize+4)
#define PWMLow_Addr             (EEVarSize+5)
#define PWMHi_Addr              (EEVarSize+6)

// #define true                     1
// #define false                    0


uint16_t GoalPos=0;
uint16_t GoalSpeed=0;
uint16_t PreviouseGoalPos=0;
uint16_t GoalPWM=0;
uint16_t PreviouseGoalPWM=0;

uint16_t DelayMs=0;


void RAMSave (uint8_t address, uint8_t data)
{
    uint16_t temp=data;
    // if you need to have any variables on ram that can be dynamicly configured
    switch (address)
    {
        case GoalPositionLow_Addr:
            GoalPos = ((GoalPos&0xFF00)+temp);
        break;

        case GoalPositionHi_Addr:
            GoalPos = ((GoalPos&0xFF)+(temp<<8));
        break;

        case GoalSpeed_Addr:
            GoalSpeed = data;
        break;

        case PWMLow_Addr:
            GoalPWM=((GoalPWM&0xFF00)+temp);
            PreviouseGoalPWM=GoalPWM+1;
        break;

        case PWMHi_Addr:
            GoalPWM=((GoalPWM&0xFF)+(temp<<8));
            PreviouseGoalPWM=GoalPWM+1;
        break;
    }
}

uint8_t RAMGet (uint8_t address)
{
    // if you need to have any variables on ram that can be dynamicly configured
    uint16_t temp=0;

    switch (address)
    {
        case GoalPositionLow_Addr:
            temp=Position;
            //LED_ON;
            return (temp&0xFF);
        break;

        case GoalPositionHi_Addr:
            temp=Position;
            return ((temp&0xFF00)>>8);
        break;

        case GoalSpeed_Addr:
            temp=Velocity;
            return (temp&0xFF);
        break;

        case TemperatureLow_Addr:
            temp=Temperature;
            return (temp&0xFF);
        break;

        case TemperatureHi_Addr:
            temp=Temperature;
            return ((temp&0xFF00)>>8);
        break;

        case PWMLow_Addr:
            temp=(GoalPWM&0xFF);
        break;

        case PWMHi_Addr:
            temp =((GoalPWM&0xFF)>>8);
        break;
    }
    return temp;
}


#define serviceRoutineReset 6
#define CycleFailSafeReplyDelay 2

int main (void)
{

    uint8_t u8Data[50];
    uint8_t u8BusInitiated=0;
    uint8_t u8ID_Previouse=0;
    uint8_t u8Master_Id=0;
    uint8_t u8SendCycle=0;
    int16_t i16Temp=0;
    uint8_t u8ChangedRom=0;
    uint8_t serviceRoutineCounter=0;
    uint8_t sreg;
    uint8_t u8PreviousCount=0;
    uint16_t LedCounter=0;
    uint16_t LedCounterPWM=3000;
    uint16_t u8Counter=0;

    uint8_t FlashingCounter = 0;
    // uint8_t CycleCounter = 0;
    // uint8_t CycleCount = 3;                  // number of times ID will be displayed by LED
    uint8_t PauseTime = 3;                  // pause time is three flash



    #if defined __AVR_ATmega8__
    WDTCR=0;
    #elif defined __AVR_ATmega328P__
    WDTCSR=0;
    #endif

    Led_Dir |= Led;
    LED_OFF;

    EELoadVars();  // load default variables from EEProm

    InitMotor();
    InitControl();
    //InitSerial((uint16_t)UART_BAUD);
    InitSerial(UART_BAUD);

    sei();

    uint8_t testString[5] = {0x42, 0, 0, 0, 0};

// message composition
// header  length destine devID  Origin_ID  data1   data2         dataN   CRC
// [0xAA]  [0xnn]      [id]       [MY_ID]  [0xd1]  [0xd1]  [...] [0xdn]  [0xzz]
//                \____________________ length _______________________/
//         \________________________ crc _____________________________/
// Length is the data that we can read from the buffer once get msg just assure the message integrity by length and CRC nothing else.


    SetFreeweeling(1000);
    while(1) 
    {

        if(LedCounter==0) {
            LED_ON;
            SendMSG(testString, 2, 0xFE);
        }



        if(LedCounter==LedCounterPWM)
            LED_OFF;

        LedCounter++;


        if(serviceRoutineCounter==0)
        {
            if(SerialPWM != PreviouseGoalPWM)
            {
                RAMSave(PWMLow_Addr,(SerialPWM&0xFF)); // save data to RAM
                RAMSave(PWMHi_Addr,(SerialPWM>>8)); // save data to RAM
                SetFreeweeling(GoalPWM);
                PreviouseGoalPWM=GoalPWM;
            }

            //TimerInterruptServiceRoutine();
            _Control_();

            if(DelayMs)
                DelayMs--;

            //TimerIntON=0;
            serviceRoutineCounter=serviceRoutineReset;
        }
        else
            serviceRoutineCounter--;

        SendChar();
        i16Temp = GetMSG(u8Data,0,3,0);
//#########################################     START COMMAND INTERPRETER   ###################################################################
        if(i16Temp>0)// data avaliable
        {


            if(u8Data[0]==BROADCAST_ID)//destination
            {


                if(u8Data[2]==AX12_START)   /// start or restart the bus
                {
                    u8Master_Id = u8Data[1];
                    u8BusInitiated=1;
                    u8ID_Previouse=0;
                    DelayMs=(MY_ID*INIT_DELAY*10);
                }
                else
                if(u8Data[2]==AX12_WRITE)  /// write
                {

                    i16Temp-=4; // take out the length of destineID + originID + Command + address_of_writing
                    GetMSG(&u8Data[1],3,1,0); //get the address
                    u8Data[2]=4;
                    while(i16Temp)
                    {
                        GetMSG(&u8Data[0],u8Data[2]++,1,0); //get the data
                        if(u8Data[1]<EEVarSize) // test if address is from eeprom
                        {
                            u8ChangedRom=1;
                        //  sreg=SREG;
                            cli();
                            EESave(u8Data[1]++,u8Data[0]); // save data to eeprom
                    //      SREG=sreg;
                            sei();
                        }
                        else
                        if(u8Data[1]<RAMVarSize) // test if address if from RAM
                        {
                            RAMSave(u8Data[1]++,u8Data[0]); // save data to RAM
                        }
                        i16Temp--;
                    }

                    if(GoalPos!=PreviouseGoalPos)
                    {
                        PreviouseGoalPos=GoalPos;
                        SetPosition (GoalPos,GoalSpeed, 100, 0);
                        SerialPWM=GoalPWM=PreviouseGoalPWM=1000;
                    }

                    if(GoalPWM!=PreviouseGoalPWM)
                    {
                        SetFreeweeling(GoalPWM);
                        SerialPWM=PreviouseGoalPWM=GoalPWM;
                        PreviouseGoalPos=0;
                        GoalPos=0;
                    }

                    if(u8ChangedRom)
                    {
                    //  sreg=SREG;
                        cli();
                        EELoadVars();
                    //  SREG=sreg;
                        sei();
                        InitSerial(UART_BAUD);
                        u8ChangedRom=0;
                    }
                    //no reply to Master once is a broadcast


                }
                else
                if(u8Data[2]==AX12_SYNC_WR)   /// sync write
                {
                    // do nothing

                    // temp // total packet length
                    GetMSG(u8Data,3,2,0);
                    //data[0];  // is the adress where to start writing
                    //data[1];  // is the amount of data to write

                    GetMSG(&u8Data[2],6,u8Data[1],1); // read to *data[2] starting on 5 a length of data[1]+1*(ID)
                    //write data to memory eeprom or ram and end
                    for(u8Counter=0;u8Counter<u8Data[1];u8Counter++)
                    {
                        if(u8Data[0]<EEVarSize) // test if address is from eeprom
                        {
                            u8ChangedRom=1;
                        //  sreg=SREG;
                            cli();
                            EESave(u8Data[0]++,u8Data[2+u8Counter]); // save data to eeprom
                        //  SREG=sreg;
                            sei();
                        }
                        else
                        if(u8Data[0]<RAMVarSize) // test if address if from RAM
                        {
                            RAMSave(u8Data[0]++,u8Data[2+u8Counter]); // save data to RAM
                        }
                    }

                    if(GoalPos!=PreviouseGoalPos)
                    {
                        PreviouseGoalPos=GoalPos;
                        SetPosition (GoalPos,GoalSpeed, 100, 0);
                        SerialPWM=GoalPWM=PreviouseGoalPWM=1000;
                    }

                    if(GoalPWM!=PreviouseGoalPWM)
                    {
                        SetFreeweeling(GoalPWM);
                        SerialPWM=PreviouseGoalPWM=GoalPWM;
                        PreviouseGoalPos=0;
                        GoalPos=0;
                    }

                    if(u8ChangedRom)
                    {
                    //  sreg=SREG;
                        cli();
                        EELoadVars();
                    //  SREG=sreg;
                        sei();
                        InitSerial(UART_BAUD);
                        u8ChangedRom=0;
                    }
                }
                else
                if(u8Data[2]==AX12_CYCLE)    /// start the sending cycle
                {
                    if(u8BusInitiated==2) // if the BUS is initiated
                    {
                        u8Master_Id = u8Data[1];
                        if(u8ID_Previouse==0) // means  that there is no servos before me i'm the first
                        {
                            u8Data[0] = ((Position)>>8); //MSB
                            u8Data[1] = Position; //LSB
                            SendMSG(u8Data,2,u8Master_Id);

                            u8SendCycle=0;
                        }
                        else
                        {
                            u8SendCycle=1;
                            DelayMs=(CycleFailSafeReplyDelay*UART_BAUD*u8PreviousCount);
                        }
                    }
                    //else do nothing
                }
                else
                if(u8Data[2]==AX12_RESET)
                {
                //  sreg=SREG;
                    cli();
                    EEPromReset();
                //  SREG=sreg;
                    sei();
                    InitSerial(UART_BAUD);
                }
                else
                {
                    u8Master_Id = u8Data[1];
                    // no recognised command
                    u8Data[0] = AX12_NOK;  // send NOK
                    SendMSG(u8Data,1,u8Master_Id);
                }
            }
            else
            if(u8Data[0]==MY_ID)   //destination is Me
            {


                u8Master_Id = u8Data[1];
                if(u8Data[2]==AX12_WRITE)  /// write
                {
                    i16Temp-=4; // take out the length of destineID + originID + Command + address_of_writing
                    GetMSG(&u8Data[1],3,1,0); //get the address

                    if((i16Temp+u8Data[1])>(RAMVarSize)) // if address+length > RAMVarSize+EEVarSize   send NOK
                    {
                        // no recognised command
                        u8Data[0] = AX12_NOK;  // send NOK
                        SendMSG(u8Data,1,u8Master_Id);
                    }
                    else
                    {
                        u8Data[2]=4;

                        while(i16Temp)
                        {
                            GetMSG(&u8Data[0],u8Data[2]++,1,0); //get the data

                            if(u8Data[1]<EEVarSize) // test if address is from eeprom
                            {
                                u8ChangedRom=1;
                            //  sreg=SREG;
                                cli();
                                EESave(u8Data[1]++,u8Data[0]); // save data to eeprom
                            //  SREG=sreg;
                                sei();
                            }
                            else
                            if(u8Data[1]<RAMVarSize) // test if address if from RAM
                            {
                                RAMSave(u8Data[1]++,u8Data[0]); // save data to RAM
                            }
                            i16Temp--;
                        }

                        if(GoalPos!=PreviouseGoalPos)
                        {
                            PreviouseGoalPos=GoalPos;
                            SetPosition (GoalPos, GoalSpeed, 100, 0);
                            SerialPWM=GoalPWM=PreviouseGoalPWM=1000;
                        }

                        if(GoalPWM!=PreviouseGoalPWM)
                        {

                            SetFreeweeling(GoalPWM);
                            SerialPWM=PreviouseGoalPWM=GoalPWM;
                            PreviouseGoalPos=0;
                            GoalPos=0;
                        }

                        // Load the variables from EEPROM

                        if(u8ChangedRom)
                        {
                        //  sreg=SREG;
                            cli();
                            EELoadVars();
                        //  SREG=sreg;
                            sei();

                            InitSerial(UART_BAUD);
                            u8ChangedRom=0;
                        }

                        u8Data[0] = AX12_OK;  // send OK
                        SendMSG(u8Data,1,u8Master_Id);
                    }

                }
                else
                if(u8Data[2]==AX12_READ)
                {
                    GetMSG(&u8Data[2],3,2,0); //get the address and length

                    if((u8Data[2]+u8Data[3])>(RAMVarSize)) // if address+length > RAMVarSize+EEVarSize   send NOK
                    {
                        // no recognised command
                        u8Data[0] = AX12_NOK;  // send NOK
                        SendMSG(u8Data,1,u8Master_Id);
                    }
                    else
                    {

                        for(i16Temp=0; i16Temp<u8Data[3] ; i16Temp++)
                        {

                            if(u8Data[2]<EEVarSize) // test if address is from eeprom
                            {
                            //  sreg=SREG;
                                cli();
                                u8Data[4+i16Temp] = EEGet(u8Data[2]+i16Temp); // get data from eeprom
                                //SREG=sreg;
                                sei();

                            }
                            else
                            if(u8Data[2]<RAMVarSize) // test if address if from RAM
                            {
                                u8Data[4+i16Temp] = RAMGet(u8Data[2]+i16Temp); // get data from RAM
                            }
                        }


                        SendMSG(&u8Data[4],i16Temp,u8Master_Id); // send data to the requester
                    }

                }
                else
                if(u8Data[2]==AX12_PING)
                {
                    //LED_ON;
                    u8Data[0] = AX12_PING;
                    SendMSG(u8Data,1,u8Master_Id);
                }
                else
                if(u8Data[2]==AX12_RESET)
                {
                    //sreg=SREG;
                    cli();
                    EEPromReset();
                    //SREG=sreg;
                    sei();
                    InitSerial(UART_BAUD);
                    u8Data[0] = AX12_PING;
                    SendMSG(u8Data,1,u8Master_Id);
                }
                else
                {
                    // no recognised command
                    u8Data[0] = AX12_NOK;  // send NOK
                    SendMSG(u8Data,1,u8Master_Id);
                }

            }
            else
            if(u8Data[1]==u8ID_Previouse) // previouse device sent packet its my turn now
            {
                if(u8BusInitiated==2)
                {
                    if(u8SendCycle==1)
                    {
                        u8SendCycle=0;

                        u8Data[0] = ((Position)>>8); //MSB
                        u8Data[1] = Position; //LSB
                        SendMSG(u8Data,2,u8Master_Id);
                    }
                }
            }
            else
            {   // in here we can receive data from other servos


                if(u8BusInitiated==1) // get the previouse ID to know the place in the line
                {
                    u8ID_Previouse = u8Data[1];
                    u8PreviousCount++;
                }
            }

            // free buffer
            GetMSG(0,0,0,1);

        }
//#########################################     END COMMAND INTERPRETER   ###################################################################

        if(u8BusInitiated==1)
        {
            if(DelayMs==0) // our turn to send the data packet for ping of initiation
            {

                u8Data[0] = AX12_PING;
                SendMSG(u8Data,1,u8Master_Id);
                u8BusInitiated=2;
            }
        }
        else if((u8BusInitiated==2)&&(u8SendCycle==1))
        {
            if(DelayMs==0)
            { // this is a fail safe, in case of missing the pack from the previouse servo, does not break the reply chain to the master
                u8SendCycle=0;
                u8Data[0] = ((Position)>>8); //MSB
                u8Data[1] = Position; //LSB
                SendMSG(u8Data,2,u8Master_Id);
            }
        }
    }





}

Serial.c (for SendMSG() )

  /*************************************************
Firmware developed for AX12 servo
ATMega8 processor at 16MHz
by: Ricardo Marinheiro
February 2011
robosavvy
Move Interactive
*************************************************/
#include <util/delay.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <ctype.h>
#include "UtilsAndDefines.h"
#include "Serial.h"
#include "Eprom.h"




// message composition
// header  length destine devID  Origin_ID  data1   data2         dataN   CRC
// [0xAA]  [0xnn]      [id]       [MY_ID]  [0xd1]  [0xd1]  [...] [0xdn]  [0xzz]
//                \____________________ length _______________________/
//         \________________________ crc _____________________________/




uint8_t DataOut[bufferSize+1];
uint8_t DataOutEndPointer=0;
uint8_t DataOutStartPointer=0;
uint8_t DataOutDiffPointer=0;

uint8_t DataIn[2][bufferSize2+1];
uint8_t DataInLen[2]={0,0};
uint8_t DataInBufSelec = 0;


extern uint16_t SerialPWM =0;


void SendMSG(uint8_t *Array, uint8_t length,uint8_t DestinationID)
{
    uint8_t temp = 0xAA; // header
    uint8_t calcCRC=0;  

    SendData(&temp,1);

    temp = (length+2); // data length plus 2 that is the ID + MY_ID length
    calcCRC= crc(&temp, 1, 0); // CRC
    SendData(&temp,1);

    temp = DestinationID;
    calcCRC += crc(&temp, 1, 0); // CRC
    SendData(&temp,1); // ID

    temp = MY_ID;
    calcCRC += crc(&temp, 1, 0); // CRC
    SendData(&temp,1); // MY ID

    SendData(Array,length); //data
    calcCRC +=crc(Array, length, 0); // CRC

    SendData(&calcCRC,1);
}



int8_t GetMSG(uint8_t *Array,uint8_t Start,uint8_t Length, uint8_t free)
{
    static uint8_t selector=0;
    static uint8_t length=0;
    static uint8_t usingMessage=0;

    if(usingMessage==0)
    {
        cli();
        selector=(1-DataInBufSelec);
        if((DataInLen[selector] != 0) && (Length>0))
        {
            if((Start+Length) > DataInLen[selector])
            {
                free=1;
            }
            else
            {
                usingMessage=1;
                length = DataInLen[selector];           
                DataInLen[selector]=0xFF;  /// place 0xFF on the data length so on getChar() no overrite to any data is done,
                                               /// forcing  to rewrite to the same buffer again once this is being used
                sei();
                memcopy(Array,(DataIn[selector]+Start),Length);
            }
        }
        sei();
    }
    else
    {
        if(Length>0)
        {
            if((Start+Length) > length)
            {
                free=1;
            }
            else
            memcopy(Array,(DataIn[selector]+Start),Length);
        }

        if(free==1) //once free is set, reset the buffer to be avaliable
        {
            length=DataInLen[selector]=0x0;
            usingMessage=0;
        }
    }
    return length;
}




uint16_t SendData(uint8_t *Array, uint8_t length)
{
    uint8_t counter=0;

    for(counter=0;counter<length;counter++)
    {
        DataOut[DataOutEndPointer++]=*Array++;

        if(DataOutEndPointer==bufferSize)
        {
            DataOutEndPointer=0;
        }

        if(DataOutDiffPointer<bufferSize)
        {
            DataOutDiffPointer++;
        }
        else
        {
            length=0;
        }
    }

    return counter;
}





void InitSerial(uint16_t SerialSpeed)
{
    HalfDuplexTransceiver_Dir  |=   (HalfDuplexTransceiver_PinOUT|HalfDuplexTransceiver_PinIN);

    UCSRA = bit(U2X); //using double speed
    UCSRB = (bit(RXCIE)|/*bit(UDRIE)|*/bit(RXEN)|bit(TXEN)/*|bit(TXCIE)*/); // enable RX and TX interrupt RX and TX

    UCSRB &= ~(bit(RXB8)|bit(TXB8)|bit(UCSZ2));   // disable  TX and RX nineth bit and reset UCSZ2, this is used with UCSZ1 and UCSZ0 to determine the length of the word
    UCSRC = ~(bit(UMSEL)|bit(UPM0)|bit(UPM1)|bit(USBS)|bit(UCPOL));//disable parity and set assyncronous, set 1stopBit and polarity on rising edge
    UCSRC |= (bit(UCSZ1)|bit(UCSZ0)|bit(UCPOL));
    //   UCSZ2=0 UCSZ1=1 UCSZ0=1 => 8bit length
    UBRRH = ((SerialSpeed)>>8);   //set baud counter high
    UBRRL = (SerialSpeed&0xFF);             //set baud counter low                                                                                                                          
    UCSRA|=bit(TXC);
}





void PrintDecimal (int Data)
{

    volatile uint16_t counter=5, firstNum=0, result=0, temp=0;
    volatile uint16_t divisor=10000;

    if(Data>0)
    {
        while(counter--)
        {
            result=Data/divisor;
            if( (result>0) || (firstNum==1))
            {
                firstNum=1;
                result+=0x30;
                SendData((uint8_t *)&result,1);
                //while(!SendChar());
                result-=0x30;
            }
            Data-=(result*divisor);
            divisor=(divisor/10);
        }
    }
    else
    if(Data<0)
    {
        temp=(Data-0xFFFE);
        while(counter--)
        {
            result=temp/divisor;
            if( (result>0) || (firstNum>0))
            {
                firstNum++;
                result+=0x30;
                if(firstNum==1)
                {
                    SendData("-",1);
                    //while(!SendChar());
                }

                SendData((uint8_t *)&result,1);
                //while(!SendChar());
                result-=0x30;
            }
            Data-=(result*divisor);
            divisor=(divisor/10);
        }
    }
    else
    {
        result=0x30;
        SendData((uint8_t*)&result,1);
    }

}


#define resetTim_Default bufferSize


uint8_t GetChar(void)
{
    (body size reached...)
}

int8_t SendChar(void)
{
    static uint8_t readWrite=0; // this exists only to spare some time on the continuous polling

    if(UCSRA&bit(UDRE))
    {

        if(DataOutDiffPointer>0)
        {
            if(readWrite==0)
            {
                readWrite=1;
                SET_WRITE;
            }
            UDR=DataOut[DataOutStartPointer];   

            DataOutStartPointer++;
            DataOutDiffPointer--;

            if(DataOutStartPointer==bufferSize)
                DataOutStartPointer=0;

            return 1;
        }
    }

    if(DataOutDiffPointer==0)
    {
        if(UCSRA&bit(TXC))
        {
            readWrite=70;
            while(readWrite--){asm("nop");} // this is just to allow the  sending of the last byte complitly before disconnect the reading
            readWrite=0;
            SET_READ;
            UCSRA|=bit(TXC);
        }
        else
        return 0;// mean that ther's nothing to be sent
    }
    else  // mean that uart hard buff is full and no byte could be sent there
    {
        return -1;
    }
}

#if defined __AVR_ATmega8__
ISR (USART_RXC_vect)
#elif defined __AVR_ATmega328P__
ISR (USART_RX_vect)
#endif
{

    GetChar();

}

Serial.h :

#if defined __AVR_ATmega328P__

#endif

#define AX12_PING       0x01
#define AX12_READ       0x02
#define AX12_WRITE      0x03
#define AX12_OK         0x04
#define AX12_MUTE       0x05
#define AX12_START      0x06
#define AX12_CYCLE      0x07
#define AX12_NOK        0x08
#define AX12_RESET      0x09
#define AX12_SYNC_WR    0x83

#define MASTER_ID       254
#define BROADCAST_ID    255

#define HalfDuplexTransceiver_Port      PORTD
#define HalfDuplexTransceiver_Dir       DDRD
#define HalfDuplexTransceiver_PinOUT    BIT7
#define HalfDuplexTransceiver_PinIN     BIT6

#define Baud9600    207
#define Baud57600   34
#define Baud115200  16
#define Baud500000  3
#define Baud1000000 1
#define Baud2000000 0

#define bufferSize 200
#define bufferSize2 250

#define TXByteEmpty (((UCSRA&bit(UDRE))>0)?1:0)
#define TXBuffEmpty (((UCSRA&bit(TXC))>0)?1:0)

#define SET_WRITE HalfDuplexTransceiver_Port|=HalfDuplexTransceiver_PinOUT;HalfDuplexTransceiver_Port&=~HalfDuplexTransceiver_PinIN;

#define SET_READ HalfDuplexTransceiver_Port&=~HalfDuplexTransceiver_PinOUT;HalfDuplexTransceiver_Port|=HalfDuplexTransceiver_PinIN;

uint16_t SerialPWM;

/**
*@brief Function to send raw data to the bus
*@var Array Pointer to the array of data to be sent to the bus
*@var length Length of the data to be sent
*@return none
*/
uint16_t SendData(uint8_t *Array, uint8_t length);

/**
*@brief Function to init all the serial communication system, prepare buffers, port baudrate etc
*@var SerialSpeed Predifined value (on serial.h) to attribute to the serial port prescaler to work at the desired speed
*@return none
*/
void InitSerial(uint16_t SerialSpeed);

/**
*@brief Utility Function to print ascii coded decimal values to the bus
*@var Data value to be printed
*@return none 
*/
void PrintDecimal (int Data);

/**
*@brief Function to be called by main working as polling to the incomming data, and unpack messages from bus
*@var none
*@return 1 if any data on comm port buffer\n0 if none
*/
uint8_t GetChar(void);

/**
*@brief Function to be called by main working as polling to the outgoing data
*@var none
*@return 1 if byte sent to hard buff\n -1 if hard buff full and no byte sent there\n 0 if uart buff empty
*/
int8_t SendChar(void);

/**
*@brief Function to get data message incoming from bus, contained on messages buffer
*@var Array Pointer to the container where to copy data to
*@var Start Buffer postition where to start getting the message
*@var Length Number of bytes to read
*@var free Set buffer free for new messages
*@return 0 if no data message ready to read\n -1 if the Start plus length are bigger than message length\nMessage length if avaliable data to read
*/
int8_t GetMSG(uint8_t *Array,uint8_t Start,uint8_t Length, uint8_t free);

/**
*@brief Function to pack data and send it in a message pack to the bus
*@var Array Pointer to the array of data to be sent
*@var length Length of data to be send
*@return none
*/
void SendMSG(uint8_t *Array, uint8_t length, uint8_t DestinationID);
\$\endgroup\$
  • \$\begingroup\$ How do you know that "it doesn't work"? All you show us are the array initialization, not how you use them. I'm pretty sure the problem is in how you use them or what you expect to happen, not in the array initialization. \$\endgroup\$ – Marcus Müller Nov 19 '18 at 11:14
  • 1
    \$\begingroup\$ That's exactly my point. I am not even using those array (especially u8Data). And as I said, I know it doesn't work because my code is making my AX12-A's LED constanlty blinking and I doesn't with those lines of code. But I admit the code isn't so clear. I am editing it. \$\endgroup\$ – erenaud Nov 19 '18 at 11:50
  • \$\begingroup\$ so you instruct your SendMSG (I don't know if this is your function; in any case, its capitalization is not nice) to send exactly one byte; is it doing that? How do you verify it's (not) doing that? \$\endgroup\$ – Marcus Müller Nov 19 '18 at 12:23
  • \$\begingroup\$ It's not my function and unfortunately, the capitalization is awful for this firmware... I just added some logs results from an Arduino code which spies on serial communication. As you can see, the data is as expected with my working snippet and I don't receive anything with the non working one. \$\endgroup\$ – erenaud Nov 19 '18 at 12:37
  • \$\begingroup\$ For this question to survive, it needs to include full reproducible code which causes the issue. Show the entire sketch, including the code that makes the LED blink and the code of the question being called. The problem is not where you think it is, but rather in something you are not considering, either an invalid program or data sequence which causes undefined behavior, or perhaps a peripheral operation that never completes and causes the function to never return. \$\endgroup\$ – Chris Stratton Nov 19 '18 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.