CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Structure passed to function [SOLVED]

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

Structure passed to function [SOLVED]
PostPosted: Wed Mar 08, 2017 9:00 am     Reply with quote

Compiler: 5.026
Device: PIC24EP512GP806

Another trivial question which should be obvious but I am really not sure what I am doing wrong here.... Note that below is just an example to simplify the code. The interrupt works because it is used by other timers.

The working code is the following:

in .h file:

bool MyTimerActive = FALSE;
unsigned int MyTimerCount = 0;


To start the timer, I do this:

main( )
{
MyTimerActive = TRUE;
}


In timer interrupt function:

#INT_TIMER1
void TIMER1_isr( void )
{
if( MyTimerActive == TRUE )
{
MyTimerCount ++;

if( MyTimerCount == 100 )
{
MyTimerCount = 0;
}
}
}


Above code works just fine. Now, I have many timers and I'd like to clean-up the code a bit so I decided to create a structure which will contain the 'count' and 'IsActive' flags:


I have this structure in my .h file:

typedef struct
{
bool IsActive;
unsigned int Count;

} STIMERBASE;


STIMERBASE MyTimer;



Then I have these two functions:

void TIMER_Start( STIMERBASE TimerID )
{
TimerID.Count = 0;
TimerID.IsActive = TRUE;
fprintf( MONITOR_SERIAL, "\n\r--- Timer started ---" );
}

void TIMER_Stop( STIMERBASE TimerID )
{
TimerID.Count = 0;
TimerID.IsActive = FALSE;
fprintf( MONITOR_SERIAL, "\n\r--- Timer stopped ---" );
}


And when I want to start MyTimer, I *thought* I'd only need to do this:


main()
{
TIMER_Start( Mytimer );
}



And in my Timer interrupt, this is what I have:

#INT_TIMER1
void TIMER1_isr( void )
{
if( MyTimer.IsActive == TRUE )
{
MyTimer.Count +;

if( MyTimer.Count == 100 )
{
Timer_Stop( MyTimer );
}
}
}



PROBLEM: Timer interrupt works but timer never gets stopped therefore I don't even think it gets started.

What am I doing wrong with the structures?


Thanks,

Ben


Last edited by benoitstjean on Thu Mar 09, 2017 10:15 am; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 9:20 am     Reply with quote

Your Timer_Start and Timer_Stop functions are writing to local copies
of the structure elements, but your ISR is looking at the global structure.

You can see this in the .SYM file:
Quote:
000 @SCRATCH
001 @SCRATCH
001 _RETURN_
002 @SCRATCH
003 @SCRATCH
004 rs232_errors
005-006 MyTimer // Global structure
007-008 @sprintf_string
009-00A TIMER_Start.TimerID // Local copies. Note different address.
00B TIMER_Start.@SCRATCH1
00B @PSTRINGC_9600_31766_31767.@SCRATCH1
00C @PSTRINGCN_9600_31766_31767.P1
00C @PRINTF_U_9600_31766_31767.P2
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 9:21 am     Reply with quote

Argh!

So now this works below:

1) I added a '*' in the function;
2) I access the parameters via -> rather than . (dot);

void TIMER_Start( STIMERBASE *TimerID )
{
TimerID->Count = 0;
TimerID->IsActive = TRUE;
fprintf( MONITOR_SERIAL, "\n\r--- Timer started ---" );
}

Ben
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 9:24 am     Reply with quote

There are several errors in what you type, which suggests the problem may be caused by other things:

1) No enable for the interrupt shown.
2) only one '+' in the structure version increment line...
With this it'll never get stopped.
3) having the fprintf in the timer, with the code as shown, would have the interrupt disabled.
4) Code as shown will 'drop off the end', so chip will go to sleep.

As posted there is another problem, with alignment. The bool, will be having to use 16bits to then allow the counter to be correctly aligned.
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 9:35 am     Reply with quote

Hi PCM_Programmer,

I guess we posted at the same time.

Sorry, the stuff you posted doesn't mean much to me unfortunately.

However, is my assumption correct to use an -> rather than a dot?

Thanks,

Ben
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 9:41 am     Reply with quote

Hi TTelmah,

I posted at the same time as you as well!

The reason there are a few typos is mainly because I somewhat re-wrote in the post from scratch given that my code had other significant names...

1) As indicated, it is a simplified version of the code as you can see therefore I didn't put the enable_interrupt function (code has 40K+ lines so I put only what I figured was relevant);

2) Yes, there is a '++' not only '+';

3) All right for that part but now it works;

4) See no.1


As for the bool part, I use an int8. I had tried an int1 but the code crashed. With int8, it works.

But again, now that I modified the internal part of the function to use an arrow rather than a dot, it works.

Ben
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 11:43 am     Reply with quote

Yes. That makes you set the value in the original variable (if you pass a pointer to it), instead of changing the value in a local copy (which isn't going to do much!...).

It's worth keeping alignment 'in mind' in the future. For instance:

Code:

struct
{
    int8 a;
    int16 b;
    int8 d;
} dummy;


Uses 6 bytes of RAM. While:
Code:

struct
{
    int16 b;
    int8 a;
    int8 d;
} dummy;


only uses 4.....

Generally put large variables first, when laying things out in structures.
benoitstjean



Joined: 30 Oct 2007
Posts: 566
Location: Ottawa, Ontario, Canada

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 11:50 am     Reply with quote

Oh, I wasn't aware of that. Thanks, I will definitely look at how I have stuff outlined.

I guess it's the same idea if I have character strings?

So I would have:
Code:

unsigned char MyString1[100];
unsigned char MyString1[50];

unsigned int16 MyVar1;
unsigned int16 MyVar2;

unsigned int8 MyVar3;

instead of:
Code:

unsigned int16 MyVar2;
unsigned char MyString1[50];

unsigned int16 MyVar1;

unsigned int8 MyVar3;

unsigned char MyString1[100];


Thanks again,

Benoit
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Mar 08, 2017 11:58 am     Reply with quote

Strings/chars/int8 are all byte aligned.
Problem is that any larger variable has to be word aligned. So in the 'bad' example, the int8 starts on a word boundary. Then the int16 also has to be put on a word boundary, so a byte is skipped. Then a single byte value again leaves another byte potentially unused...
You can use the __packed__ attribute to store things tightly, but then a standard word access can't be used to fetch word based variables. Potential crash if you try to access a byte aligned word variable using a pointer for example.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group