yyrkoon

gpio interrupts

21 posts in this topic

Is it possible for an interrupt on one GPIO pin to affect the output on another pin ? I am toggling P1.5 externally, and some how it is affecting the output of another pin ( P2.1 ). How I know this is fact, as P2.1 is hooked up the the RESET pin on another processor, and that processor immediately resets. Even though the code does not act on anything right now.

 

Below is literally all I have, except for pin setup. The code compiles fine, and uploads onto hte launchpadd v1.5(g2553) just fine.

int main(void)
{
        WDTCTL = WDTPW + WDTHOLD;               // Stop watchdog timer

        setup();

        __enable_interrupt();

        // Main loop
        while(1){
                // Pet the dog.
                WDTCTL = WDTPW | WDTCNTCL;

        }
        return 0;
}
__attribute__( (interrupt (TIMER1_A0_VECTOR)) )
void TIMER1_A0_ISR(void)
{

        if (counter++ > 100){                     // ~1 Second
                counter = 1;
                //seconds++;

        }
}

__attribute__( (interrupt (PORT1_VECTOR)) )
void PORT1_ISR(void)
{

        if(P1IFG & BIT0){
                flags |= HALT;
                P1IFG &= (~BIT0);
        }

        if(P1IFG & BIT5){

                if(flags & ENABLED){            // We've been enabled by the host.
                     
                }
                else{                           // Not yet enabled by the host.
             
                }

                P1IFG &= (~BIT5);
        }
}

Share this post


Link to post
Share on other sites

@@spirilis thanks for the response. I could, but i think we've isolated the problem to our internally designed board. The board we're hooked up to is a beaglebone black. The board between the two is a custom controller board that I can not talk much about.

 

But the problem lies with a chip that is a bi directional gate( bi-directional transistor ) which is a newly designed chip that my buddy obviously has never had experience with. So, with the MSP430 off our custom board, toggling P9.27 on the beaglebone triggers( somehow ) RESETn. But with the beaglebone off the custom board too, this does not happen. There are no direct shorts between these pin on the beaglebone. So me being the non electronic engineer guy assumed there had to be some glitch in my software that I was unaware of.

 

So I misspoke earlier. I did not know for a fact that P1.5 was effecting P2.1. I simply meant that on the other side of the isolation the pins were somehow toggling one another.

Share this post


Link to post
Share on other sites


void setup(void)

{

        DCOCTL = 0;

        DCOCTL = CALDCO_1MHZ;

        BCSCTL1 = CALBC1_1MHZ;

        BCSCTL2 = DIVS_0;

 

        /* Timer1 A0*/

        TA1CCR0 = 1250;                         // Count overflow frequency

        TA1CTL = TASSEL_2 + ID_3 + MC_1;        // SMCLK/8  upmode

                                                // ( 1000000 / 8 ) / 1250 == 10ms tick

        TA1CCTL0 = CCIE;

 

        P1SEL &= (~BIT0 + BIT5);                // Set P1.0 and P1.5 SEL as GPIO

        P1DIR &= (~BIT0 + BIT5);                // Set P1.0 and P1.5 SEL as Input

        P1IES |= (BIT0) + (BIT5);               // Falling Edge 1 -> 0

        P1IFG &= (~BIT0 + BIT5);                // Clear interrupt flag for P1.5

        P1IE |=  (BIT0) + (BIT5);               // Enable interrupt for P1.5

 

        P2DIR |= BIT1 + BIT3;

        P2OUT |= BIT1;                          // Beaglebone RESET_N active low - Normal high

        P2OUT &= (~BIT3);                       // Beaglebone battery connection active low - Disconnected high

}

Share this post


Link to post
Share on other sites

So, this chip, the bi direction gate. Has 2 channels. A and B. Then each channel has two sides, 1, and 2. From the table in the pin description, the wording makes it sound as though the channels work together. When in fact, the pins 1, and 1 complete the circuit when the enable pin is toggled. So toggling A1 from one side, will toggle B1 the same on the other side. Where the datasheet made it seem as A1, and A2 was the relation. . . So with our design as it stood, I was toggling RESETn directly from P9.27 on the beagleobne . . . managed to corrupt the image I had on the sdcard too :/

 

Anyway, we had to use this specific chip for our design as regular opti-couplers were not working correctly in the original design. And the Beaglebone's pins have to be isolated at system up.

Share this post


Link to post
Share on other sites

Sounds like a level shifter, like a TXB0102 or similar?  I've had some experience with those.  Yeah the whole idea is A1 & B1 talk together, A2 & B2 talk together.  If it's a bidirectional "sensing" type of chip like the TXB, on top of that you have to acknowledge that the drive strength on the outputs are limited, e.g. they don't recommend using pullups or pulldowns lower than 50K ohms in value on any of the pins intended to receive output from one of the channels...

 

Where I've used the TXB is to power down the A-side voltage (on the TXB at least, VccA must be <= VccB, also the EN pin is attached to the Vcc(A) net.  The host MCU turns off a PFET supplying Vcc(A) so that the TXB shuts down, and all the hardware on the A-side shuts down so it uses no power (think MAX31855 thermocouple chip... has no native way to shut itself off so it just keeps drinking current nonstop unless you surround it with a mousetrap like this).

yyrkoon likes this

Share this post


Link to post
Share on other sites

Yeah, I think that's it @@spirilis. I think it's definately at least a TXB part. But 3 of us all fairly smart people could not make heads nor tails of the datasheet table that describes the pin functions.

 

So right now, I'm experiencing another issue in my code. I'm trying to setup a pulse counter on one of the gpio's and it's not working the way I'd expect. These g2553's only have edge detection on interrupt right ? So like if my external pin in always low, and I'm clearing the interrupt flag on a falling edge interrupt. It wont count multiple interrupts. Will it ?

 

EDIT:

 

By the way, the way we figured out how the part works. My buddy soldered resistors to all the pins, just to have something to get a scope probe attached to. Then we just starting feeding 3v3 into each side of each channel and observed what was going on . . .

spirilis likes this

Share this post


Link to post
Share on other sites

So, my problem with gpio interrupt "pulse counting" was some sort of logic flaw. I changed the code to do the same thing slightly differently, and everything seems to work fine.

Share this post


Link to post
Share on other sites

I'm curious about this snippet of code. Your use of brackets is confusing to me. Particularly these 3 lines.

 

...
        P1SEL &= (~BIT0 + BIT5);                // Set P1.0 and P1.5 SEL as GPIO
        P1DIR &= (~BIT0 + BIT5);                // Set P1.0 and P1.5 SEL as Input
        P1IFG &= (~BIT0 + BIT5);                // Clear interrupt flag for P1.5
...

 

To me this feels like it will be performing function A. Which results in an overflow. Is this your intent?


A. (~BIT0 + BIT5) == (~0x01 + 0x20) == (0xFE + 0x20) == (0x11E) == 0x1E <- After it's put into a 8bit register

B. ~(BIT0 + BIT5) == ~(0x01 + 0x20) == ~(0x21) == 0xDE

Doesn't look related to your issue. But still looks like a bug.

yyrkoon, Rickta59 and tripwire like this

Share this post


Link to post
Share on other sites

I'm curious about this snippet of code. Your use of brackets is confusing to me. Particularly these 3 lines.

 

 

To me this feels like it will be performing function A. Which results in an overflow. Is this your intent?


A. (~BIT0 + BIT5) == (~0x01 + 0x20) == (0xFE + 0x20) == (0x11E) == 0x1E <- After it's put into a 8bit register

B. ~(BIT0 + BIT5) == ~(0x01 + 0x20) == ~(0x21) == 0xDE

Doesn't look related to your issue. But still looks like a bug.

Yeah that was wrong. I fixed that earlier.

Share this post


Link to post
Share on other sites

@@greeeg

 

My fix was actually slightly different though. I mention this in case it may help new players understand things better. I keep the ~ bit operator inside of brackets for the sake of operator seperation. Like so.

        P1SEL &= (~BIT0) + (~BIT5);             // Set P1.0 and P1.5 SEL as GPIO
        P1DIR &= (~BIT0) + (~BIT5);             // Set P1.0 and P1.5 SEL as Input
        P1IES |= BIT0 + BIT5;                   // Falling Edge 1 -> 0
        P1IFG &= (~BIT0) + (~BIT5);             // Clear interrupt flag for P1.5
        P1IE |=  BIT0 + BIT5;                   // Enable interrupt for P1.5

Share this post


Link to post
Share on other sites

 

@@greeeg

 

My fix was actually slightly different though. I mention this in case it may help new players understand things better. I keep the ~ bit operator inside of brackets for the sake of operator seperation. Like so.

        P1SEL &= (~BIT0) + (~BIT5);             // Set P1.0 and P1.5 SEL as GPIO
        P1DIR &= (~BIT0) + (~BIT5);             // Set P1.0 and P1.5 SEL as Input
        P1IES |= BIT0 + BIT5;                   // Falling Edge 1 -> 0
        P1IFG &= (~BIT0) + (~BIT5);             // Clear interrupt flag for P1.5
        P1IE |=  BIT0 + BIT5;                   // Enable interrupt for P1.5

 

Isn't this still producing the wrong result??

 

After negating , if you add you'll get an overflow....

(~BIT0) + (~BIT5) == (~0x01) + (~0x20) == (0xFE) + (0xDF) == (0x1DD)

If you insist on negating within brackets then you should be using AND operations to receive the required result, not ADD.

(~BIT0) & (~BIT5) == (~0x01) & (~0x20) == (0xFE) & (0xDF) == (0xDE)
terjeio and tripwire like this

Share this post


Link to post
Share on other sites

 

Isn't this still producing the wrong result??

 

After negating , if you add you'll get an overflow....

(~BIT0) + (~BIT5) == (~0x01) + (~0x20) == (0xFE) + (0xDF) == (0x1DD)

If you insist on negating within brackets then you should be using AND operations to receive the required result, not ADD.

(~BIT0) & (~BIT5) == (~0x01) & (~0x20) == (0xFE) & (0xDF) == (0xDE)

According to my calculator. Your example, and mine both are wrong. Except while my way while wrong still overflows while giving me BIT0 set to 1. -34 versus -35 in decimal.

 

Either way, I think I'm done trying to configure bits as such. And I'll start using hard coded values i know are correct. LOGICAL BITWISE OR, also overflows ( - 1 ).

Share this post


Link to post
Share on other sites


"use strict";

 

(function() {

        var BIT0 = 0x0001;

        var BIT5 = 0x0020;

 

        var test = (~BIT0) & (~BIT5);

 

        process.stdout.write(test + '\n');

 

})();

 

william@beaglebone:~/dev/javascript$ node wd.js

-34


"use strict";

 

(function() {

        var BIT0 = 0x0001;

        var BIT5 = 0x0020;

 

        var test = (~BIT0) + (~BIT5);

 

        process.stdout.write(test + '\n');

 

})();

 

william@beaglebone:~/dev/javascript$ node wd.js

-35


"use strict";

 

(function() {

        var BIT0 = 0x0001;

        var BIT5 = 0x0020;

 

        var test = (~BIT0) + (~BIT5);

 

        process.stdout.write(test.toString(2) + '\n');

 

})();

 

william@beaglebone:~/dev/javascript$ node wd.js

-100011

Share this post


Link to post
Share on other sites

The best interactive calculator to do architecture specific math is gdb.  For example:
 

$ msp430-elf-gdb -q
(gdb) set $BIT0=(1<<0)
(gdb) set $BIT5=(1<<5)
(gdb) print/x (~$BIT0) + (~$BIT5)
$1 = 0xffdd
(gdb) p/t (unsigned char)0xffdd
$12 = 11011101
(gdb) p/t (unsigned char)~0xffdd
$11 = 100010

 
In the msp430-elf-gdb session above I created a couple of convience variables ($BIT0 and $BIT5). You could also just use (1<<n) for any BITN.  The print command will output decimal by default. However, you can change the base by providing  /x (hex), or  /d (decimal), or /t (binary).  To perform any calculation you just just type the c code. (~(1<<0) + ~(1<<5) and you get the result.
 
So the result using incorrect bit flipping is 0xFFDE. However, P1DIR is only 8 bits on the msp430g2553 so it only uses the LSB (0xDE). However that result is wrong. That would targeting BIT1 instead of BIT0
 
You want to add all the BITs together before flipping them

$ msp430-elf-gdb -q
(gdb) set $BIT0=(1<<0)
(gdb) set $BIT5=(1<<5)
(gdb) print/x ~($BIT0|$BIT5)         
$2 = 0xffde
(gdb) print/x (unsigned char)0xffde
$3 = 0xde
(gdb) print/t (unsigned char)0xffde
$4 = 11011110
(gdb) print/t (unsigned char)~0xffde
$5 = 100001

So the right answer is 0xFFDE which turns out to be just 0xDE when used to set P1DIR.

 

Using the print/t binary output you can easily see which bits are on and which bits are off. (BIT5 and BIT0) 0b100001

 

You also have to remember that any number that isn't qualified in code with a size is going to default to size of int. If I run this code using the gdb that comes with my linux 64 bit machine. You see it defaults to the x86 normal size int.  In the case below it becomes 0xffffffde

$ gdb -q
(gdb) p/x ~((1<<0)|(1<<5))
$1 = 0xffffffde
(gdb)

Using the architecture specifc gdb, makes a handy bit and hex calculator that you can just type into.

 

-rick

greeeg, Fmilburn and yyrkoon like this

Share this post


Link to post
Share on other sites

Also, it being early for me this morning I forgot the whole point bit clear operator is to clear bits, not set them. So @@greeeg numbers or closer to correct than mine.

 

But either way, I think I'm done using bit operaors when I can hand hard code hex values that are exactly correc for what I want / need.

Share this post


Link to post
Share on other sites

The best interactive calculator to do architecture specific math is gdb.  For example:

 

$ msp430-elf-gdb -q
(gdb) set $BIT0=(1<<0)
(gdb) set $BIT5=(1<<5)
(gdb) print/x (~$BIT0) + (~$BIT5)
$1 = 0xffdd
(gdb) p/t (unsigned char)0xffdd
$12 = 11011101
(gdb) p/t (unsigned char)~0xffdd
$11 = 100010

 

In the msp430-elf-gdb session above I created a couple of convience variables ($BIT0 and $BIT5). You could also just use (1<<n) for any BITN.  The print command will output decimal by default. However, you can change the base by providing  /x (hex), or  /d (decimal), or /t (binary).  To perform any calculation you just just type the c code. (~(1<<0) + ~(1<<5) and you get the result.

 

So the result using incorrect bit flipping is 0xFFDE. However, P1DIR is only 8 bits on the msp430g2553 so it only uses the LSB (0xDE). However that result is wrong. That would targeting BIT1 instead of BIT0

 

You want to add all the BITs together before flipping them

$ msp430-elf-gdb -q
(gdb) set $BIT0=(1<<0)
(gdb) set $BIT5=(1<<5)
(gdb) print/x (~$BIT0) + (~$BIT5)
$1 = 0xffdd
(gdb) print/x ~($BIT0|$BIT5)         
$2 = 0xffde
(gdb) print/x (unsigned char)0xffde
$3 = 0xde
(gdb) print/t (unsigned char)0xffde
$4 = 11011110
(gdb) print/t (unsigned char)~0xffde
$5 = 100001

So the right answer is 0xFFDE which turns out to be just 0xDE when used to set P1DIR.

 

Using the print/t binary output you can easily see which bits are on and which bits are off. (BIT5 and BIT0) 0b100001

 

You also have to remember that any number that isn't qualified in code with a size is going to default to size of int. If I run this code using the gdb that comes with my linux 64 bit machine. You see it defaults to the x86 normal size int.  In the case below it becomes 0xffffffde

$ gdb -q
(gdb) p/x ~((1<<0)|(1<<5))
$1 = 0xffffffde
(gdb)

Using the specific gdb for the architecture you are using make a handy bit and hex calculator that you can just type into.

 

-rick

cool use case for gdb Rick ! I still prefer javascript though . . . toString(base) is pretty handy.

Share this post


Link to post
Share on other sites

The problem with using javascript it it doesn't know that your target environment is limited to 16 bit.  Try a different example, add 0xffff + 0x0001 .. 
 
 

$ cat testme.js 
"use strict";

(function() {
        var BIT0 = 0x0001;
        var BIT5 = 0xffff;

        var test = (BIT0) + (BIT5);

        process.stdout.write('0x' +test.toString(16) + '\n');

})();
$ node testme.js 
0x10000
$ 

Now try it with msp430-elf-gdb:
 

$ msp430-elf-gdb -q
(gdb) print/x 0xffff+0x0001
$1 = 0x0
(gdb) 

So the answer with javascript is '0x10000' and the answer with msp430-elf-gdb is '0'. However for the msp430g2553 0 is the right answer.

 

msp430-elf-gdb knows about C math and it knows about the size of integers on an msp430. Which when you start moving up the chain of msp430 parts it changes. The results also change depending on which compiler mode you are using, 16 bit for small model and 20 bits for large. 

 

As long as you keep in mind that you have to turn the javascript results into 16 bit math you will be ok. But it is yet another thing to remember.

 

-rick

greeeg and yyrkoon like this

Share this post


Link to post
Share on other sites

More fun with gdb, try this with an MSP-EXP430G2 launchpad

 

o Open 2 xterm or 2 command windows that have msp430-elf-gdb and mspdebug in your path

 

o In the first xterm run: 

 $ mspdebug rf2500 'gdb'
 

o In the second xterm run an msp430-elf-gdb session

$ msp430-elf-gdb -q -ex 'target remote :2000' 
Remote debugging using :2000
0x0000ffff in ?? ()
(gdb) printf "create convenience variables\n"
create convenience variables
(gdb) set $P1OUT=(unsigned char *)0x21
(gdb) set $P1DIR=(unsigned char *)0x22
(gdb) printf "set all the P1 pins low\n"
set all the P1 pins low
(gdb) set *$P1OUT=0
(gdb) printf "set all the P1 pins into output\n"
set all the P1 pins into output
(gdb) set *$P1DIR=0xff
(gdb) printf "TURN on both LED pins (BIT0 and BIT6)\n"           
TURN on both LED pins (BIT0 and BIT6)
(gdb) set *$P1OUT=((1<<0)|(1<<6))       
(gdb) printf "TURN off the RED LED pin\n" 
TURN off the RED LED pin
(gdb) set *$P1OUT=~((1<<0))              
(gdb) printf "TURN on the RED LED and turn off the GREEN LED pin\n"
TURN on the RED LED and turn off the GREEN LED pin
(gdb) set *$P1OUT=((1<<0) | ~(1<<6))         
(gdb) quit 
                              
msp430-elf-gdb lets you read and write the Special function varialbles that control the ports. Using it interactively like this I'm not sure we even need a programming language :) All you need is a connection to mspdebug through msp430-elf-gdb (CCS supplied) or msp430-gdb (Energia supplied)

-rick

yyrkoon likes this

Share this post


Link to post
Share on other sites

The standard Windows calculator in Programmer mode (Alt+3) is quite handy too...

Yes, thats the calculator I use. So now, that I actually know what the registers do, I will start doing something like:

 

P1DIR = 0x21;

 

Instead of wracking my brain to try and remember everything while attempting to do binary in my head. When I should really be focusing on the program flow. In the past I just copied stuff I did not fully understand. But now that I've spent a good amount of time in the datasheet, I get "it".

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now