Problem with init() (in wiring.c) when my init of the UART (unsolved)

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.

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:

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.

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);
}
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.

Do you how to solve this?

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

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)

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.

Main .ino file:

#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;
        }
}

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

#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);
}

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

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

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.

#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);

}

//<>
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
}

syrinx:
Main .ino file:

#include "bluevmega.cpp"

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

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

What do you mean? Not compiling?

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.

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().

It seems that it works if hwsetup() is launched from main()

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

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.

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

I was obliged to add this:

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?

Thanks a lot Nick!

Since I've added this code:

int main()
{
	setup();
	loop();
}

I'm able to init the UART from setup() (without conflict with init() from wiring.c)
and all is working better, even millis()!

I hope I won't have a new problem soon...

Thank you very much.

Yes, well I should point out that normally 'loop' loops. That is:

while (true)
  loop ();
    // 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

If you're going to re-initialize peripherals AFTER the arduino core functions (init()) have already set them up, you'll need to assume that none of the "initial values" from the datasheet are still correct. That means, in the worst case, that you should explicitly initialized ALL registers associated with a peripheral using "="; no assuming that certain bits are already in the correct state, no assuming that whole registers are set "right" for your application... Here (for example) you haven't done anything with TCCR4A, and you're assuming some state in TIFR4.

So, why are you bothering to use the Arduino IDE? Since you seem to be prepared to write your own from-scratch code, it sounds like you don't "need" the arduino libraries. Since you ARE using different initializations, I don't think you can count on other Arduino libraries continuing to work correctly. And I doubt that it's because of the wonderful Arduino editor! That leaves the "upload" button - did you know that you can upload arbitrary .hex files to an arduino board (via its bootloader) using the avrdude command?

I did like this because I have taken from someone some codes done without librairy. If he would have written a lib, it would have been a lot better.

I solve the problem by adding the good inits of TIMERS to be able to still use millis()
and to start my code like this:

void loop()
{ for (;;) {
}