View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 566 Location: Ottawa, Ontario, Canada
|
Structure passed to function [SOLVED] |
Posted: Wed Mar 08, 2017 9:00 am |
|
|
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
|
|
Posted: Wed Mar 08, 2017 9:20 am |
|
|
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
|
|
Posted: Wed Mar 08, 2017 9:21 am |
|
|
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: 19539
|
|
Posted: Wed Mar 08, 2017 9:24 am |
|
|
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
|
|
Posted: Wed Mar 08, 2017 9:35 am |
|
|
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
|
|
Posted: Wed Mar 08, 2017 9:41 am |
|
|
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: 19539
|
|
Posted: Wed Mar 08, 2017 11:43 am |
|
|
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
|
|
Posted: Wed Mar 08, 2017 11:50 am |
|
|
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: 19539
|
|
Posted: Wed Mar 08, 2017 11:58 am |
|
|
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. |
|
|
|