Go Down

Topic: Problem with init() (in wiring.c) when my init of the UART (unsolved) (Read 1 time) previous topic - next topic

syrinx

Hello.

I have a conflict with the ini() from wiring.c and my own init of the UARTs.

This is working well. The Arduino is doing what it should be.
Code: [Select]
void init()
{
   cli();
   v1state = inmsgstate = inmsglen = polarity = bitcnt = 0;

   DDRB = _BV(PB7); // PB7/LED
   // UART init
#include <util/setbaud.h>
UBRR3H = UBRR0H = UBRRH_VALUE;
UBRR3L = UBRR0L = UBRRL_VALUE;
#if USE_2X
   UCSR3A = UCSR0A = _BV(U2X3);
#endif
UCSR3C = UCSR0C = _BV(UCSZ30) | _BV(UCSZ31);       // 8N1
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);    // Enable TX and RX

   // Timer init
   GTCCR = 0;                  //_BV(PSR10);         /* reset prescaler */

   // trigger on falling edge (default), noise cancel
   // lower 3 bits is div, off,1,8,64,256,1024,extfall,extris ; CS12,11,10
   TCCR4B = _BV(ICNC1) | _BV(CS11);

   // clear and enable Input Capture interrupt
   TIFR4 |= _BV(ICF4) | _BV(TOV4) | _BV(OCF4A) | _BV(OCF4B);
   TIMSK4 = _BV(ICIE4);        // enable input capture only

   sei();                      // enable interrupts
   // and sleep between events
   set_sleep_mode(SLEEP_MODE_IDLE);
}


When I want to add this code in py own project, I get a conflict with init() of wiring.c.
This error:

Quote
C:\Users\syrinx\AppData\Local\Temp\build6135219376461108096.tmp\core.a -LC:\Users\syrinx\AppData\Local\Temp\build6135219376461108096.tmp -lm
core.a(wiring.c.o): In function `init':
C:\Portable\Arduino\arduino-1.0.3\hardware\arduino\cores\arduino/wiring.c:193: multiple definition of `init'
bluevirq.c.o:C:\Users\syrinx\AppData\Local\Temp\build6135219376461108096.tmp/bluevirq.c:347: first defined here


Then I've started to change the function and to rename is hwsetup() and to call it from setup(), or even from main(). I don't have compiling error, but the Arduino is not doing its job. I guess the UARTs are not well set. But as I change almost nothing, I think the UARTs are set too late or there is a conflict with init() from wiring.c
But I don't have any error during compiling.

Code: [Select]
void hwsetup()
{
   cli();
   v1state = inmsgstate = inmsglen = polarity = bitcnt = 0;

   DDRB = _BV(PB7); // PB7/LED
   // UART init
#include <util/setbaud.h>
UBRR3H = UBRR0H = UBRRH_VALUE;
UBRR3L = UBRR0L = UBRRL_VALUE;
#if USE_2X
   UCSR3A = UCSR0A = _BV(U2X3);
#endif
UCSR3C = UCSR0C = _BV(UCSZ30) | _BV(UCSZ31);       // 8N1
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);    // Enable TX and RX

   // Timer init
   GTCCR = 0;                  //_BV(PSR10);         /* reset prescaler */

   // trigger on falling edge (default), noise cancel
   // lower 3 bits is div, off,1,8,64,256,1024,extfall,extris ; CS12,11,10
   TCCR4B = _BV(ICNC1) | _BV(CS11);

   // clear and enable Input Capture interrupt
   TIFR4 |= _BV(ICF4) | _BV(TOV4) | _BV(OCF4A) | _BV(OCF4B);
   TIMSK4 = _BV(ICIE4);        // enable input capture only

   sei();                      // enable interrupts
   // and sleep between events
   set_sleep_mode(SLEEP_MODE_IDLE);
}


Code: [Select]

void loop()
{   hwsetup();
....
}


I should add that all is in 2 different files but it's working well before to add some codes of my own. I use <EEPROM.h> and "XBee.h".

Do you how to solve this? Should I create a library which, I guess, will be called before setup()?

Thank you.

PaulS

Quote
Do you how to solve this?

Rename your init() function. The Arduino provides one. You shouldn't.

syrinx

It's what I did: I rename it into hwsetup(). I call it from main() or even setup(), I don't have compiling error, but the Arduino is not working well.

(sorry, I didn't write correctly the hwsetup(), I've just changed)

PaulS

Quote
but the Arduino is not working well.

Oh, well, that's a real shame.

If you showed some code, and explained what "is not working well" means, perhaps we could do more than sympathize.


syrinx

#4
Jan 20, 2013, 07:46 am Last Edit: Jan 20, 2013, 07:55 am by syrinx Reason: 1
Main .ino file:
Code: [Select]
#include "bluevmega.cpp"

void setup()
{

Serial.begin(57600);
delay(1000);
}

void loop()
{  
hwsetup(); [b]// GLOW: added beacuse I've renamed init() into hwsetup() !!!!!!!!!!!![/b]

int ret;
   unsigned char lastdisp[12];
Serial.println("V1MegaTool");
   for (;;) {
for (;;) {
ret = readpkt(respget); [b]// FX: STAY BLOCKED HERE !!! (GLOW)[/b]
if (ret < 5)
               continue;
           if (respget[3] == INFDISPLAYDATA)
               break;
       }
       if(legacy > 32)
           printser(pullp(PSTR("LEGACY! only V works\r\n")));  
inbuf[inhead++] = Serial.read();
           printser(pullp(PSTR("Mute (ESP)Hold systemUp mainDisp Euro Custom\r\n")));
           lastdisp[0] = 0;
           while (1) {
ret = readpkt(respget);
               if (ret < 5) {
                   continue;
}
               if (respget[3] == INFDISPLAYDATA && memcmp(lastdisp, respget, 12)) {
showinfdisp();
                   memcpy(lastdisp, respget, 12);
               }
if (Serial.available() >= 1 ) {
inbuf[inhead++] = Serial.read();
}
   }
           break;
       }
}

syrinx

A part of the file bluevirq.c:
Please notice that there if hwsetup() was name init() the Arduino will work.

Code: [Select]
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

//#define F_CPU         18432000
#ifndef F_CPU
#define F_CPU   16000000
#endif
#define BAUD 57600

#define PRESCALE1 8
#define BITTIME(x) ( ((x) * F_CPU) / PRESCALE1 / BAUD)

/*-------------------------------------------------------------------------*/
#define INMSGSIZE 24
unsigned char inbuf[256], v1buf[256];
volatile unsigned char v1head = 0, v1tail = 0, inhead = 0, intail = 0;
static volatile unsigned int bitcnt;
static unsigned int frametime;
// Time Slice processor
// This counts character times to find the slot to transmit.  
// Each slot is 45 character times wide
// FIXME - doesn't try to resync or otherwise avoid collisions with other devices
ISR(TIMER4_COMPB_vect)
{
   OCR4B += BITTIME(10);
   frametime++;

   if (frametime < 45 * slice)
       return;

   if (inmsgstate != 4) {      // nothing for this frame
       TIMSK4 &= ~_BV(OCIE4B); // slice processor off
       UCSR3B &= ~_BV(TXEN0);  // TX off - just in case
       frametime = 0;
       return;
   }
   if (
#ifdef ANYSLICE
     (slice == 0 && frametime == 1) ||
#endif
     frametime == 45 * slice) {        // At current time slice

       // Holdoff for late previous time slice
       if (bitcnt)
           frametime--;
       else
           UCSR3B |= _BV(TXEN0);       // TX on
       return;
   }

   if (frametime >= 45 * (slice + 1)) {        // end of time slice
       TIMSK4 &= ~_BV(OCIE4B); // slice processor off
       UCSR3B &= ~_BV(TXEN0);  // TX off
       frametime = 0;
       inmsgstate = 0;
       return;
   }

   if (!(frametime & 1)) {     // Data Out Pacing, every other frame until done
       unsigned char ptr = (frametime - (45 * slice + 1)) >> 1;
       if (ptr < inmsglen)
           UDR3 = inmsgbuf[ptr];
       if (ptr > inmsglen)
           UCSR3B &= ~_BV(TXEN0);      // TX off
   }
}
static unsigned char outchar;   // bitbang UART receive register
static unsigned char polarity;  // which edge are we looking for
volatile unsigned legacy;
//Stopbit for software UART
ISR(TIMER4_COMPA_vect)
{
   TIMSK4 &= ~_BV(OCIE4A);     // disable
   if (!polarity) {            // not break condition
       while (bitcnt < 10) {   // fill in one bits up to stop bit
           bitcnt++;
           outchar >>= 1;
           outchar |= 0x80;
       }
       if (transp)
           UDR0 = outchar;
       else
           v1buf[v1head++] = outchar;
       dostate(outchar);
       if(legacy)
           legacy--;
   }
   else {                      // break, reset things for next start bit
       TCCR4B &= ~_BV(ICES1);
       polarity = 0;
   }
   bitcnt = 0;
}

// Software UART via edges
char legbits[36] = "+medcbap87654321gfKALFFFSSSRRRIXMNOP";
unsigned long legimg;
ISR(TIMER4_CAPT_vect)
{
   static unsigned lastedge;
   unsigned thisedge = ICR4;
   TCCR4B ^= _BV(ICES1);
   unsigned width = thisedge - lastedge;
   lastedge = thisedge;
   polarity ^= 1;

// Legacy Mode
#define LEGABIT (504)
#define USTICS(us) ((us) * (F_CPU/PRESCALE1)/1000000)
   if( legacy > 100 ) {
       if( width < USTICS(LEGABIT)/5 ) { // normal bits for ESP
           bitcnt = 0;
           legacy--;
           return;
       }
       if( width > USTICS(LEGABIT)*2 ) { // 9.58 mS nominal
           PORTB ^= _BV(PB7);
           bitcnt = 0;
           ;//UDR2 = UDR0 = '\n';
           return;
       }
       if( polarity )
           return;
       ++bitcnt;
       legimg <<= 1;
       if( width <  USTICS(LEGABIT)/2 ) {
           if( bitcnt < 37 ) {
               ;//UDR2 = UDR0 = legbits[bitcnt-1];
               legimg |= 1;
           }
       return;
   }
   if(width > USTICS(LEGABIT) - 25 && width < USTICS(LEGABIT) + 25 ) {
       if( (++legacy & 1023) == 0 ) {
           PORTB ^= _BV(PB7);
           UDR0 = 'L';
       }
       legacy &= 4095;
   }
   /* toggle interrupt on rising/falling edge */
   if (polarity && !bitcnt) { // start bit
       OCR4A = lastedge + BITTIME(9) + BITTIME(1) / 2;
       TIFR4 |= _BV(OCF4A);    /* clear compare match interrupt */
       TIMSK4 |= _BV(OCIE4A);  /* enable compare match interrupt */
       bitcnt = 1;
       return;
   }
   width += BITTIME(1) / 2;    // round up
   while (width >= BITTIME(1)) {       // Shift in bits based on width
       width -= BITTIME(1);
       bitcnt++;
       outchar >>= 1;
       if (polarity)
           outchar |= 0x80;
   }
}

//void init() // GLOW: if it is 'void init()' it will work !!!!!!!!!!!!!!
void hwsetup()
{
   cli();
   v1state = inmsgstate = inmsglen = polarity = bitcnt = 0;

   DDRB = _BV(PB7); // PB7/LED
   // UART init
#include <util/setbaud.h>
UBRR3H = UBRR0H = UBRRH_VALUE;
UBRR3L = UBRR0L = UBRRL_VALUE;
#if USE_2X
   UCSR3A = UCSR0A = _BV(U2X3);
#endif
UCSR3C = UCSR0C = _BV(UCSZ30) | _BV(UCSZ31);       // 8N1
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);    // Enable TX and RX
   // for UART1, only TX is enabled, and only when sending in the right timeslice

   // Timer init
   GTCCR = 0;                  //_BV(PSR10);         /* reset prescaler */

   // trigger on falling edge (default), noise cancel
   // lower 3 bits is div, off,1,8,64,256,1024,extfall,extris ; CS12,11,10
   TCCR4B = _BV(ICNC1) | _BV(CS11);

   // clear and enable Input Capture interrupt
   TIFR4 |= _BV(ICF4) | _BV(TOV4) | _BV(OCF4A) | _BV(OCF4B);
   TIMSK4 = _BV(ICIE4);        // enable input capture only

   sei();                      // enable interrupts
   // and sleep between events
   set_sleep_mode(SLEEP_MODE_IDLE);
}


syrinx

Some functions used in bluevmega.c. I've extracted what you need to see to undertsand the issue.

Code: [Select]
static int readpkt(unsigned char *buf)
{
    unsigned char len, ix;
    buf[0] = 0;
for (;;) {
        while (buf[0] != 0xaa)  // SOF
        {
// GLOW: start to loop here: turning turning turning turning if it's with hwsetup() Working well with init() !!!!!!!!!!!
buf[0] = readv1rx();
        }
buf[1] = readv1rx();    // destination
......


Code: [Select]
extern volatile unsigned char v1head, v1tail, inhead, intail;
extern unsigned char v1buf[], inbuf[];
// LOW LEVEL ROUTINES FOR ARDUINO
// Read one character from the V1 data stream
static int readv1rx(void)
{
    while (v1head == v1tail)
        sleep_mode();
    return v1buf[v1tail++];
}


I hope it's understandable.

Any idea? Thx.

syrinx

As I know that the libs are initialised before setup(), I tried to make a library with this.

But I get the same, it's not working.

Quote
#include "LED13.h" //include the declaration for this class

#include <util/setbaud.h>
#include <avr/sleep.h>
   

    LED13::LED13(){
      
      cli();
      // v1state = inmsgstate = inmsglen = polarity = bitcnt = 0;
      DDRB = _BV(PB7); // PB7/LED
      // UART init
      //#include <util/setbaud.h>
      // Syrinx it was: UBRR2H = UBRR3H = UBRR0H = UBRRH_VALUE;
      UBRR3H = UBRR0H = UBRRH_VALUE;
      // Syrinx it was: UBRR2L = UBRR3L = UBRR0L = UBRRL_VALUE;
      UBRR3L = UBRR0L = UBRRL_VALUE;
      #if USE_2X
      // Syrinx it was: UCSR2A = UCSR3A = UCSR0A = _BV(U2X3);
      UCSR3A = UCSR0A = _BV(U2X3);
      #endif
      // Syrinx it was: UCSR2C = UCSR3C = UCSR0C = _BV(UCSZ30) | _BV(UCSZ31);       // 8N1
      UCSR3C = UCSR0C = _BV(UCSZ30) | _BV(UCSZ31);       // 8N1
      // Syrinx it was: UCSR2B = UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);    // Enable TX and RX
      UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0);    // Enable TX and RX
      // for UART1, only TX is enabled, and only when sending in the right timeslice

      // Timer init
      GTCCR = 0;                  //_BV(PSR10);         /* reset prescaler */

      // trigger on falling edge (default), noise cancel
      // lower 3 bits is div, off,1,8,64,256,1024,extfall,extris ; CS12,11,10
      TCCR4B = _BV(ICNC1) | _BV(CS11);

      // clear and enable Input Capture interrupt
      TIFR4 |= _BV(ICF4) | _BV(TOV4) | _BV(OCF4A) | _BV(OCF4B);
      TIMSK4 = _BV(ICIE4);        // enable input capture only

      sei();                      // enable interrupts
      // and sleep between events
      set_sleep_mode(SLEEP_MODE_IDLE);
      
      
    }
     
    //<<destructor>>
    LED13::~LED13(){/*nothing to destruct*/}
     
    //turn the LED on
    void LED13::on(){

   }
     
    //turn the LED off
    void LED13::off(){
        //digitalWrite(LED_PIN,HIGH); //set the pin HIGH and thus turn LED on
    }
     
    //blink the LED in a period equal to paramterer -time.
    void LED13::blink(int time){
            //on();                   //turn LED on
            //delay(time/2);  //wait half of the wanted period
            //off();                  //turn LED off
            //delay(time/2);  //wait the last half of the wanted period
    }

Nick Gammon


Main .ino file:
Code: [Select]
#include "bluevmega.cpp"



You shouldn't include .cpp files. Why are you doing that?

Quote
But I get the same, it's not working.


What do you mean? Not compiling?
http://www.gammon.com.au/electronics

syrinx

I use "#include "bluevmega.cpp"" to avoid to declare (extern ...) each variables and functions from blevmega in the main .ino file.

When I said the Arduino is not working: it means that compiling is working, the Arduino starts, but the bytes coming in port 49 (RX in) of Arduino Mega are not OK.

I prefer to repeat that almost the same code but with init() is working very well.

syrinx

#10
Jan 20, 2013, 11:33 am Last Edit: Jan 20, 2013, 11:49 am by syrinx Reason: 1
I did:
- I have deleted #include "bluevmega.cpp"
- renamed the 3 files with .ino extension
- moved all the variables at the beginning of the main .ino file

Still not working when the UART init is not named init().

syrinx

#11
Jan 20, 2013, 01:21 pm Last Edit: Jan 20, 2013, 01:31 pm by syrinx Reason: 1
It seems that it works if hwsetup() is launched from main()

Then inside main(), I call loop().

syrinx

#12
Jan 20, 2013, 08:09 pm Last Edit: Jan 20, 2013, 08:11 pm by syrinx Reason: 1
I still have a problem: millis() gives always 0.

It's probably related to interrupts or ini of wiring.c.

Any idea how to solve this?

Thanks.

syrinx

millis() was always at zero. Now it's OK.

I was obliged to add this:

Code: [Select]

int main()
// Syrinx was: #else
// Syrinx was: void init()
// Syrinx was: #endif
{
    hwsetup();
// Enable TIMER0 ( used by millis() )
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
sbi(TCCR0B, CS01);
sbi(TCCR0B, CS00);
sbi(TIMSK0, TOIE0);
setup();
loop();
}


Now millis() is working a gain. As my code is not changing TIMER0 somewhere, it means that init() is not well built. I don't know why.

Nick Gammon

You shouldn't really have a main. The "real" main calls init, setup, and then loop repeatedly. Why not put your setting up in setup?
http://www.gammon.com.au/electronics

Go Up