Not coherent compiler behavior.....

08 Jan 2012

Hi all. This is my first post on the forum. I have the mbed since almost a week, and I like how fast you can do things but I think I can't trust the compiler... here's my problem: I'm doing a library for a 802.15.4 module and here's my main.cpp

#include "mbed.h"
#include "Uz2400d.h"

Uz2400d zb(p5, p6, p7, p8, p9, p10);   // mosi miso sclk cs reset interrup
DigitalOut myled(LED1);
DigitalOut led4(LED4);
DigitalOut test(p21);
Serial pc(USBTX, USBRX);

unsigned char reto, reto1, reto2, reto3;
unsigned char asd[4];

void interrupcion(void)
{
    
    myled = 1;
    wait(0.2);
    myled = 0;
    wait(0.2);

    reto = zb.lee_reg(SADRL);
    if(reto != 0x34)
    {
        pc.printf("Asdasd");
    }
    reto1 = zb.lee_reg(SADRH);
    reto2 = zb.lee_reg(PANIDL);
    reto3 = zb.lee_reg(PANIDH);
    pc.printf("SADRL=%x, SADRH=%x,PANIDL=%x, PANIDH=%x\n", reto, reto1, reto2, reto3);
 
}

int main() {

    zb.attachInte(&interrupcion);
    wait(2);
    pc.printf("Que mierda... \n");
    zb.wr_reg(SADRL, 0x34);
    zb.wr_reg(SADRH, 0x12);
    zb.wr_reg(PANIDL, 0x78);
    zb.wr_reg(PANIDH, 0x56);
    
    
    while(1) 
    {
        test = 1;
        led4 = 1;
        wait(2);
        test = 0;
        led4 = 0;
        wait(2);
        
    }
}

The code above is just to test some of the library functions and it works fine. Here's the output:

Que mierda... 
SADRL=34, SADRH=12,PANIDL=78, PANIDH=56

But if I change the first "wait" in the main from 2 to 3 seconds the output changes to:

Que mierda... 
AsdasdSADRL=0, SADRH=0,PANIDL=0, PANIDH=0

Do someone knows if there's something I can do?.. besides of saying "ok" and moving away from this and hoping that this simple errors don't ocurr?

Anyway... tahnks in advance and sorry for the disorder in my code...

08 Jan 2012

Hi Rolando,

Glad you are getting on well!

In general, the compiler can be trusted; it is usually the interaction of code, logic, etc we express where problems arise, which is usually not the compilers fault!

Although I don't know exactly what your library "Uz2400d" does, it appears you are attaching an interrupt callback to it called "interrupcion", which in your first example is getting fired at some point after "Que mierda..." is printed and the registers have been assigned in main(), as the register values are printed out.

In your second example, this would suggest the extended delay after setting up the interrupt means that the interrupt now fires between "Que mierda..." being printed, but before the registers are assigned.

So it could well be the expected behaviour.

Just as an aside, it is not generally a good idea to printf both within main and in interrupt routines, as they might get tangled up in their use of the library (e.g. main starts printing, but be interrupted and the interrupt code start printing, causing the internal buffers/logic of printf to become corrupt). I realise you are just debugging here, but just something where you have to be careful if you want to be able to trust your code.

Hope this helps you track down your problem.

Simon

08 Jan 2012

Hi Simon, Thanks for your fast response and sorry if I didn't put all the information like the lib functions nor the test circuit. I'll do it now =).

- The test circuit: (I don't have a sch program at the moment)

/media/uploads/rolox82/circ.jpg

As you can see the only pin that I'm not connecting to the module is the interrupt pin p10, for testing purpouses I'm controlling the interrupt with the pin p21 (test).

- Uz2400d.h:

#ifndef MBED_Uz2400d_H
#define MBED_Uz2400d_H

#include "mbed.h"

#define    PANIDL        0x01
#define    PANIDH        0x02
#define    SADRL        0x03
#define    SADRH        0x04
/////////////////////////////////////

class Uz2400d {
public:
    // Constructor.
    Uz2400d(PinName mosi, PinName miso ,PinName sclk, PinName cs, PinName reset, PinName interr);

    // the same of InterruptIn.fall but for the ease of use.
    void attachInte( void (*fpointer)(void) );

    // read and write registers of the module
    unsigned char lee_reg( unsigned int dir_reg );
    void wr_reg( unsigned int dir_reg, unsigned char dato );       
      
private:  

    SPI _spi;
    DigitalOut _cs;
    DigitalOut _reset;
    InterruptIn _interr;

};

#endif

- The Uz2400d.cpp:

#include "Uz2400d.h"
#include "mbed.h"

//constructor
Uz2400d::Uz2400d(PinName mosi, PinName miso ,PinName sclk, PinName cs, PinName reset, PinName interr) : 
    _spi(mosi, miso, sclk), _cs(cs), _reset(reset) , _interr(interr) {

    _cs = 1;
    _reset = 1;
    
}

void Uz2400d::attachInte( void (*fpointer)(void) )
{
    _interr.mode(PullUp);
    _interr.fall(fpointer); 
    
}

// leer registro
unsigned char Uz2400d::lee_reg( unsigned int dir_reg )
{
    unsigned int retorno;  
    
    _cs = 0;

    if ( dir_reg < 256 )    // es un registro corto
    {                           
        dir_reg = (dir_reg << 1) & 0x7E;
        _spi.write( dir_reg );
        retorno = _spi.write(0xFF);
    }
    else
    {    
        dir_reg = ( ( dir_reg | 0x400 ) << 5 );
        dir_reg = dir_reg & 0xFFE0;
        _spi.write( (char)(dir_reg>>8) );
        _spi.write( (char)dir_reg );
        retorno = _spi.write(0xFF);
    }
    
    _cs = 1;
    return retorno;
}

// escribir en un registro.
void Uz2400d::wr_reg( unsigned int dir_reg, unsigned char dato )
{  
    _cs = 0;

    if ( dir_reg < 256 )    // es un registro corto
    {                           
        dir_reg = (dir_reg << 1) & 0x7F;
        dir_reg = dir_reg | 0x1;                // el 1 es para escribir... 

        _spi.write( dir_reg );
        _spi.write(dato);
    }
    else
    {    

        dir_reg = ( ( dir_reg | 0x400 ) << 5 );
        dir_reg = dir_reg | 0x10;

        _spi.write( (char)(dir_reg>>8) );
        _spi.write( (char)dir_reg );
        _spi.write( dato );
   
    }

    _cs = 1;
}

As you can see the code is very simple. The recommendation of not insert printf in the interrupt is a good advice, I know it. But as I'm not getting unespected interrupts I don't think it would be a problem.

In my original post I've only put the first two outputs but as I'm controlling the interrupt every 4 seconds I get the same line at the output and with the same results. I've repeated several times both outputs so it's not a isolated problem that I have 1 time.

I'm going to try the code without the module and put MOSI directly connected to MISO to not have any external component.

I know that I'm probably have something wrong, but it's worth to spot the problem.

I've worked with another compilers on microchips pics16/18/24, and sometimes I have to insert asm codes to bypass compiler problems. One of them was a problem in the #define of two pointers that were exactly the same but with different memory address; the first one worked fine and it was pointing at the right direction, but the second one pointed with 1 byte offset.

As we all who are working with the MBED dont have access to the machine code nor a debugger is very difficult to see what's going on...

Well, I'm not very used to forums and I hate take time form others... so thank you very much in advance.

  • Edited:

Humm.. I've tested it without the module and works ok... with both times... so I'm trying now with slowing the spi (the datasheet says that it support 5Mhz)... weird..... I'm glad to see that it seems the cause is not the compiler nor mbed

  • Edited2:

Wow.... With 100khz spi I have the same problem in both tests... but with 2Mhz SpI I have no problem at all... Well I think this problem is solved =). I'm very glad to see it wasn't the compiler.

08 Jan 2012

Hi Rolando,

your interrupt input (p10) is connected to output pin test (p21). The interrupt input is pulled up and responds to a falling edge. However, you have not initialised test to logic high before you attach the interrupt input pin to its interrupt callback function in zb.attachInte(&interrupcion).

That might lead to some random behaviour. Try this:

int main() {

    test = 1;

    zb.attachInte(&interrupcion);
    wait(2);
    pc.printf("Que mierda... \n");
    zb.wr_reg(SADRL, 0x34);
    zb.wr_reg(SADRH, 0x12);
...

08 Jan 2012

Hi Wim.

Yes, you're right, I haven't initialized it. Thanks for pointing it =).

But this can be only a problem the first time and I was getting the same response every time, not random.

Anyways, I've spotted the problem and it was the speed of the SPI. As I said in my *Edited2 comment It was a module spi speed issue.

Thank you again.

Rolando.