Mega644 bit test problem

View: New views
6 Messages — Rating Filter:   Alert me  

Mega644 bit test problem

by Robert von Knobloch :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hallo,

I am writing code for an ATMega 644P and have come across some very
strange behaviour.
A small part of the code is required to read an asynchronous serial
signal (data & clock - low speed) over PORTB pins.
The relevant code snippet is:

snip
#define CLOCK_TIMEOUT    2000
#define ASYNCPIN    PORTB
#define ASYNCCLK    0
#define ASYNCDATA    3

    for (i = 0 ; i < 16 ; ++i)
    {
        while ((ASYNCPIN & _BV(ASYNCCLK)) != 0)        // Wait for clock low
        {
        if (mSecdowncnt == 0)
        {
            noclock = 1;
            break;                    // Timeout
        }
        }

        result = result >> 1;
        if ((ASYNCPIN & _BV(ASYNCDATA)) != 0)
        {
        result |= 0x8000;
        }

        while ((ASYNCPIN & _BV(ASYNCCLK)) != 1)        // Wait for clock
high
        {
        if (mSecdowncnt == 0)
        {
            noclock = 1;
            break;                    // Timeout
        }
        }
        if (noclock == 1)
        {
        break;
        }
    }
/snip

This works fine. I want, however to use portb bits 1 & 3 for clock &
data. I simply change to #define ASYNCCLK    1
and re-compile
Now, nothing works and the code generated is much smaller (0xe5 bytes
instead of 0x193 bytes for the working variant).

I am using OPTIMIZE       = -O1 -fno-inline in my Makefile

Does anyone know why simply changing a bit-mask should have such a
serious effect ?

Best regards,

Robert von Knobloch



_______________________________________________
AVR-chat mailing list
AVR-chat@...
http://lists.nongnu.org/mailman/listinfo/avr-chat

Re: Mega644 bit test problem

by Piotr Nikiel :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On May 8, 2009, at 11:41 AM, Robert von Knobloch wrote:

> Hallo,
>
> I am writing code for an ATMega 644P and have come across some very
> strange behaviour.
> A small part of the code is required to read an asynchronous serial
> signal (data & clock - low speed) over PORTB pins.
> The relevant code snippet is:
>
> snip
> #define CLOCK_TIMEOUT    2000
> #define ASYNCPIN    PORTB
> #define ASYNCCLK    0
> #define ASYNCDATA    3
>
>     for (i = 0 ; i < 16 ; ++i)
>     {
>         while ((ASYNCPIN & _BV(ASYNCCLK)) != 0)        // Wait for  
> clock low
>
(...)
Sorry for out of topic, but  shouldn't you use PINB instead of PORTB  
when reading pin state?

Regards,
PN



_______________________________________________
AVR-chat mailing list
AVR-chat@...
http://lists.nongnu.org/mailman/listinfo/avr-chat

Re: Mega644 bit test problem

by David VanHorn-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I don't see where you set the appropriate DDR pin.

--
There is no computer problem which cannot be solved by proper
application of a sufficiently large hammer.


_______________________________________________
AVR-chat mailing list
AVR-chat@...
http://lists.nongnu.org/mailman/listinfo/avr-chat

Re: Mega644 bit test problem

by Tarmigan :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

(Reading through some very old email, it looks like this one might not
have been resolved...)

On Fri, May 8, 2009 at 2:41 AM, Robert von Knobloch<bob@...> wrote:

> Hallo,
>
> I am writing code for an ATMega 644P and have come across some very
> strange behaviour.
> A small part of the code is required to read an asynchronous serial
> signal (data & clock - low speed) over PORTB pins.
> The relevant code snippet is:
>
> snip
> #define CLOCK_TIMEOUT    2000
> #define ASYNCPIN    PORTB
> #define ASYNCCLK    0
> #define ASYNCDATA    3
>
>    for (i = 0 ; i < 16 ; ++i)
>    {
>        while ((ASYNCPIN & _BV(ASYNCCLK)) != 0)        // Wait for clock low
>        {
>        if (mSecdowncnt == 0)
>        {
>            noclock = 1;
>            break;                    // Timeout
>        }
>        }
>
>        result = result >> 1;
>        if ((ASYNCPIN & _BV(ASYNCDATA)) != 0)
>        {
>        result |= 0x8000;
>        }
>
>        while ((ASYNCPIN & _BV(ASYNCCLK)) != 1)        // Wait for clock

This line is probably the problem.

> This works fine. I want, however to use portb bits 1 & 3 for clock &
> data. I simply change to #define ASYNCCLK    1
> and re-compile
> Now, nothing works and the code generated is much smaller (0xe5 bytes
> instead of 0x193 bytes for the working variant).

_BV(0)==1 but _BV(1)==2, so when you do ((value & _BV(1)) != 1), it's
never false because the possible values of (ASYNCPIN & _BV(1)) are 0
or 2, never 1.

I would try to write these kinds of statements as
        while( !(ASYNCPIN & _BV(ASYNCCLK)) ) {
                  blah, blah;
        }

-Tarmigan


_______________________________________________
AVR-chat mailing list
AVR-chat@...
http://lists.nongnu.org/mailman/listinfo/avr-chat

Re: Mega644 bit test problem

by Erwan MARC-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

tarmigan a écrit :

>> snip
>> #define CLOCK_TIMEOUT    2000
>> #define ASYNCPIN    PORTB
>> #define ASYNCCLK    0
>> #define ASYNCDATA    3
>>
>>    for (i = 0 ; i < 16 ; ++i)
>>    {
>>        while ((ASYNCPIN & _BV(ASYNCCLK)) != 0)        // Wait for clock low
>>        {
>>        if (mSecdowncnt == 0)
>>        {
>>            noclock = 1;
>>            break;                    // Timeout
>>        }
>>        }
>>
>>        result = result >> 1;
>>        if ((ASYNCPIN & _BV(ASYNCDATA)) != 0)
>>        {
>>        result |= 0x8000;
>>        }
>>
>>        while ((ASYNCPIN & _BV(ASYNCCLK)) != 1)        // Wait for clock
>>    
>
> This line is probably the problem.
>
>  
>> This works fine. I want, however to use portb bits 1 & 3 for clock &
>> data. I simply change to #define ASYNCCLK    1
>> and re-compile
>> Now, nothing works and the code generated is much smaller (0xe5 bytes
>> instead of 0x193 bytes for the working variant).
>>    
>
> _BV(0)==1 but _BV(1)==2, so when you do ((value & _BV(1)) != 1), it's
> never false because the possible values of (ASYNCPIN & _BV(1)) are 0
> or 2, never 1.
>
> I would try to write these kinds of statements as
>         while( !(ASYNCPIN & _BV(ASYNCCLK)) ) {
>                   blah, blah;
>         }
>
> -Tarmigan
>
>
>  
Another way to to that is (data & MASK == MASK): this will solve
question in any situation if MASK is modified and doesn't assume the
fact that for C language "!=0" stands for TRUE.





_______________________________________________
AVR-chat mailing list
AVR-chat@...
http://lists.nongnu.org/mailman/listinfo/avr-chat

Parent Message unknown Re: Mega644 bit test problem

by Neil-78 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

> > Hallo,
> >
> > I am writing code for an ATMega 644P and have come across some very
> > strange behaviour.
> > A small part of the code is required to read an asynchronous serial
> > signal (data & clock - low speed) over PORTB pins.
> > The relevant code snippet is:
> >
> > snip
> > #define CLOCK_TIMEOUT ? ?2000
> > #define ASYNCPIN ? ?PORTB
> > #define ASYNCCLK ? ?0
> > #define ASYNCDATA ? ?3
> >
> > ? ?for (i = 0 ; i < 16 ; ++i)
> > ? ?{
> > ? ? ? ?while ((ASYNCPIN & _BV(ASYNCCLK)) != 0) ? ? ? ?// Wait for clock low
> > ? ? ? ?{
> > ? ? ? ?if (mSecdowncnt == 0)
> > ? ? ? ?{
> > ? ? ? ? ? ?noclock = 1;
> > ? ? ? ? ? ?break; ? ? ? ? ? ? ? ? ? ?// Timeout
> > ? ? ? ?}
> > ? ? ? ?}
> >
> > ? ? ? ?result = result >> 1;
> > ? ? ? ?if ((ASYNCPIN & _BV(ASYNCDATA)) != 0)
> > ? ? ? ?{
> > ? ? ? ?result |= 0x8000;
> > ? ? ? ?}
> >
> > ? ? ? ?while ((ASYNCPIN & _BV(ASYNCCLK)) != 1) ? ? ? ?// Wait for clock
>
> This line is probably the problem.
>
> > This works fine. I want, however to use portb bits 1 & 3 for clock &
> > data. I simply change to #define ASYNCCLK ? ?1
> > and re-compile
> > Now, nothing works and the code generated is much smaller (0xe5 bytes
> > instead of 0x193 bytes for the working variant).
>
> _BV(0)==1 but _BV(1)==2, so when you do ((value & _BV(1)) != 1), it's
> never false because the possible values of (ASYNCPIN & _BV(1)) are 0
> or 2, never 1.
>
> I would try to write these kinds of statements as
>         while( !(ASYNCPIN & _BV(ASYNCCLK)) ) {
>                   blah, blah;
>         }
>

..would:

  while( bit_is_clear( ASYNCPIN, ASYNCCLK));

work as well?  it would be easier to understand.

- neil



_______________________________________________
AVR-chat mailing list
AVR-chat@...
http://lists.nongnu.org/mailman/listinfo/avr-chat