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
    }


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?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
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.

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?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Go Up