Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Adding timer for digital clock.

Xenon02

Full Member level 3
Joined
Nov 12, 2022
Messages
157
Helped
0
Reputation
0
Reaction score
0
Trophy points
16
Activity points
2,205
Hello !

I've been wondering if adding timer for my digital clock is a good idea.

I've added RTC to calculate the time and then every second the timer triggers the interrupt to update the time on my LCD screen and I wondered if it's a good idea.
Because there are other processes in the main and wondered if they are in the middle of executing the code and then it is interupted then if it's ok or not. I also added the timer to make sure that it will update every 1 second just thinking if I couldn't make it better but didn't want to add the update function into main while place because it would update with different time than constant 1 second. But also interupting the code that is executed right in the middle or anywhere else (for example uart I want to send 8 bytes and then interrupt occures and while he was sending second byte or third byte).

I mean I know that I have to remember about times etc. but wondered if it's a good idea because I couldn't find a better solution and DMA I guess, didn't know how to trigger update function.
 
As the ISR starts, it will save some or all internal registers somewhere - typically on the stack. It is then free to use those internal registers in the ISR to execute your code. When that is done it will restore the saved values of the internal registers - typically copy them back from the stack.

It goes into ISR copies the value of register A that is 0 uses this variable to be updated to, it modifies the register A which is now 1 and then restores the value from this register A which is again 0.

Or rather it uses A stores the new data in different register like B and never updates the register A ? And then restores to old value from A? What does it mean restore ? If A was modified the whole program uses the same register so calling it at the begging and at the end is weird. It's like the thing ISR does never changes the variable or anything inside of him because it always overwrites what he saved at the beginning. So like he restores the A value from the start. I don't get it.

Then adding volatile changes how ISR works I guess ? So that it add another step to update A register with new value from B register ?

Sounds weird but what I will see in debugger ? When I have it pointed in A++ inside of ISR ? It uses variable A which is stored in register A. But new value is stored in register B from ISR.

Because I see that in assembler it doesn't make comparison again but in debugging it will point at while to check the condition and go on. So here I see two different scenarios which in one it jumps to label without comparison and second in which it checks the comparison. And the debugger what it sees is still a mystery I don't understand.
--- Updated ---

I still don't get the registers it uses the A and restores the A and what happened to the operations ? What I see in the debugger? What I see in the while breakpoint and in ISR breakpoint. In assembler it skips the comparison and jumps to label in C code the breakpoint points at while condition and the comparison.

Ehhh should I accept that it works this way ? Because I used variable without this volatile and it worked. The more I read the more I am confused. It reads something it operates with it then restores to old value, something is stored in memory randomly I guess ?

Sorry for wasting time.
 
Last edited:
The problem is, that the C code doesn´t show what happens in detail.

A microcontroller has a limited number of registers to work with. (registers, not SRAM memory)

They use the registers in main() .. but they also use registers in ISR. The same registers!.
So when performing a main loop, the registers (all of them) are consantly used to perform different operations with different content.

Now when an ISR is about to run ...#
* the compiler knows the ISR uses R1, R5, R17, R18 (just as example)
* but these registers currently contain important values for operations performed in main(), they must have the same values when the ISR is finished for the main() to work correctly.
* so before performing operations in ISR it needs to "save" the main()_contents of R1, R5, R17, R18
* now the ISR can change the content of R1, R5...... to perform ISR operations
* after the ISR has finished it´s job it needs to restor the (old) values for the main loop.

****
Example:
* in main loop - just before ISR is executed - it has value "X" in register1
* ISR starts, ISR saves the value of register1 (X) into SRAM (stack?)
* ISR uses register 1 with it´s own values, loads with abc, changes to def ... anything,performs oeprations
* before returing to main() it restores value "X" into register1.

--> so the main() never knows that the ISR used and altered the value of register1.
The main() will never know that there was in ISR performed at all. (unless it really checks the variable that contains the flags set by the ISR)

***
Back to C:
I´m not sure what the debugger shows. I guess you can see the value of variables.
But are you able to see the contents of the raw microcontroller_registers?

***
Anyways: don´t rely on "it worked last time" ... when using variables that are modified in ISR and READ in main() it may work (especially on small programs with low register usage) but you don´t have a guarantee.
If you do your job correctly, then use the "volatile" statement on these variables. Then you can be sure. It´s not "luck" anymore.

Klaus
 
Now when an ISR is about to run ...#
* the compiler knows the ISR uses R1, R5, R17, R18 (just as example)
* but these registers currently contain important values for operations performed in main(), they must have the same values when the ISR is finished for the main() to work correctly.
* so before performing operations in ISR it needs to "save" the main()_contents of R1, R5, R17, R18
* now the ISR can change the content of R1, R5...... to perform ISR operations
* after the ISR has finished it´s job it needs to restor the (old) values for the main loop.

A okey,
So basically all variables are saved in SRAM/memory and registers just takes the variables value from memory and saves in registers for calculation etc.

*So when ISR takes these registers value saves them in SRAM and makes calculations like m = m + 1 or m++; in those registers.

*After calculating this m++; it overwrites the old "m" variable value inside the SRAM

*Then the ISR registers takes from SRAM the old registers value and returns to main.

The only thing the ISR changes was the variable "m" inside the memory SRAM. That's what I understood even though it wasn't written because the calculations must go somewhere I guess. So I deduced that maybe if overwrites the value of variable "m" not in registers but in memory. This would make sense for this code :


Code:
label:
move the value of variable 'm' to internal register A
if A != 1 then go to done
go to label
done:

Because it says that variable "m" is passed to the register. So if ISR updated the m variable in SRAM (it always does) and the "move the value" is after label then it sees the changes of "m". So ISR changes the memory value and not the registers.

I think something like that I deduced maybe correctly.

PS.
I also read something like that :
The reason you're seeing a strange difference is because, due to optimizations (and this is pure speculation), the A in main isn't the same A as in the ISR internally anymore.

So like two different "A" which is a variable name now and not register name.
Sounded weird, because it reads from the memory that is reserved for this variable and it is passed to ISR if it uses variable A.
 
So like two different "A" which is a variable name now and not register name.
No there are not two different variables "A".

But there is the "A" in SRAM (the real variable) and main() copies the content into a register.
While the ISR correctly updates the variable in SRAM...
the main misses to update it´s copy in the register (if not set to "volatile") and works with the mature value of "A" in the register.

Klaus
 
No there are not two different variables "A".

But there is the "A" in SRAM (the real variable) and main() copies the content into a register.
While the ISR correctly updates the variable in SRAM...
the main misses to update it´s copy in the register (if not set to "volatile") and works with the mature value of "A" in the register.

So I understand that what I said before "So like two different "A" which is a variable name now and not register name." is correct. Or rather what I said before PS is correct.

This PS was rather a thing I have found and from this quote I thought like wait two different variable A. Weird ;D So I automatically gave here the quote to check if the quote was wrong etc.

Back to C:
I´m not sure what the debugger shows. I guess you can see the value of variables.
But are you able to see the contents of the raw microcontroller_registers?

Yea I also thought what I would see in simple break point like in this one :


Code:
int A = 0;

int main()
{
while(A != 1)
{

//Do something

}
}

void ISR()

{

A++; <------ breakpoint

}

And after exiting the ISR what I will see here :


Code:
int A = 0;

int main()
{
while(A != 1) <------ breakpoint
{

//Do something

}
}

void ISR()

{

A++;

}

Like if the A is from the memory SRAM and ISR changes the SRAM, so theoretically it will go to while loop and because it is optimized it doesn;t probably compare actual A with 1 rather it will skip it and goes into inside the while loop but it will still show that A is equal the new value from SRAM that was updated by ISR. But the while loop will work differently because it was optimized as you said. At least that's what I've thought from simple pseudo assembler code that inside the loop the value from register A isn't passed into SRAM, so the new value of variable "A" (not register A) is not changed inside the loop so the variable "A" should show the new value but the while loop condition is ignored/ or compares the old variable value even though it says m = 1 or A = 1. Hard to follow in the debugger I guess ?

I belive so from what I written in last post before PS.
 
Last edited:
Hi,

seems you don´t see the register at all. (in the debugger)
Register is machine level (assembler)
C is not at register level.

I try to find an example:
Let´s say in a restaurant you ask for coffee.
The waiter comes with a cup and a pot. He pours the coffe from the pot into your cup.
Now you complain that the coffee is too cold.
The waiter puts the pot on the oven to make it hot.
Still the coffee in your cup stays cold. ;-)

Pot = variable "A"
cup = register (with the content of the pot .... before heating)

Klaus
 
seems you don´t see the register at all. (in the debugger)
Register is machine level (assembler)
C is not at register level.

Yea I understood that the C and debugger are not at the register level so I tried to nibble the information what I will see in the debugging process.
Like you said the registers stays intact which doesn't change the value, the memory variable will change though through ISR.

So I thought that ISR changes the variable value and saves in SRAM/RAM some nice place, and when the breakpoint will point at while loop the variable still will be visible as A = 1 ? (of course the register which is not visible. Compiler saw that variable is nonvolatile so he still thinks A is equal 0 which is saved in register1 so he doesn't have to check what variable A has now), so the while process I won't know what happens there but I will still see that A is equal 1 because it is saved in SRAM and debugger sees variable value as A = 1 ? So this would be the error I could find through debugger.

I don't know if what I say is understandable, I want to point that I understand that in while register1 is compared to 1 and not actual value of variable "A". I wanted to know what I will see using debugger when I exit the ISR function which changes A from 0 to 1 and he will go to while loop will A still remain as 1 ? in while of course this new A won't be compared with value 1 rather register1. So it will pass the expression A!=1 although debugger shows variable A = 1 so this will be the error for me that points "yup it passed something he wasn't meant to so change the A into volatile"

I try to find an example:
Let´s say in a restaurant you ask for coffee.
The waiter comes with a cup and a pot. He pours the coffe from the pot into your cup.
Now you complain that the coffee is too cold.
The waiter puts the pot on the oven to make it hot.
Still the coffee in your cup stays cold. ;-)

Dang the cold coffee ;>
 
I don't know if what I say is understandable,
Same with me.

I don´t have experience with the debugger. So I can´t say whether the debugger shows the SRAM value or the register value.

But I think it´s clear now that a "volatile" statement makes sense.

Heavy discussions, today.

Klaus
 
But I think it´s clear now that a "volatile" statement makes sense.

Heavy discussions, today.

Yup it is clear after many examples more of the pseudo code examples I got it. Post#42 was very helpfull.
Have a nice day.

I don´t have experience with the debugger. So I can´t say whether the debugger shows the SRAM value or the register value.

O okey I thought that maybe you knew how it would look like using breakpoints in debugging etc ;D
Maybe someone else have more experience in it.
 
Hi,

one problem in explaining these things is that there are many different microcontrollers.
The one works this way, the other works differently.
The one saves registers in stack, the other in SRAM, the other does a complete register set swap.

And there are different people, with different ways to learn things. I´m the one who learns with "pictures". I`m not good in learning text. But as soon as I can transform a problem into a picture, it´s burnt in. (this does not mean that I don´t forget or don´t make mistakes. sadly).
Others find "pictures" like the cup of coffee annoying.

Klaus
 
one problem in explaining these things is that there are many different microcontrollers.
The one works this way, the other works differently.
The one saves registers in stack, the other in SRAM, the other does a complete register set swap.

And there are different people, with different ways to learn things. I´m the one who learns with "pictures". I`m not good in learning text. But as soon as I can transform a problem into a picture, it´s burnt in. (this does not mean that I don´t forget or don´t make mistakes. sadly).
Others find "pictures" like the cup of coffee annoying.

I have grasped the idea that the operation works in registers and the variables can be stored in SRAM or other places like you've said, same goes to registers context (value that they had initially). Mostly is as I see from many websites I read identical (like operations in registers etc.), the difference can be where the data is saved like context of registers and variables value.

About learning, it depends for me because I usually don't understand the simple explanations or to complex explanations (hard to balance), like if I hear a simple definition or something that can be simplified then I usually find gaps in logics or something that wasn't mentioned. And this is the point I usually get lost because I find something that wasn't mentioned or I heard something about something.

Thanks for the help understanding it. I'll try to learn how debugger works maybe from C forums, or so. But if anyone has an idea, leave a sign.

PS.

There is still a thing even if I use volatile that I deduced in post#20. I don't deny using volatile, but rather how to deal with the timer to have as small delay that is not stacking. Like first delay was 200 us another delay is 300 us and the delays are stacking up to the moment where 1 minut can be skipped because of delay.
 
Last edited:
Hi,
from post#20: Is this what you mean?
Although there is another problem. Let's say this 1s passed, then the main loop sees this flag is on then the function of updating the screen is being executed so some time passes and it is way past 1s and is propagating more and more times the screen refreshes to the point where the delay is not 1 s but it can be 1 minute.
Another thing is what if I have more stuff to do inside main loop ? The time delay might be even bigger.
I´m not sure, but a think there is a misunderstanding.
The Interrupt becomes triggered every 1s. the ISR is processed maybe a couple of microseconds later. It is short in processing time. Let´s say the ISR needs 100us.
Then it returns to main() ... now there are about 999900 microseconds left for the main() to do it´s job. It can immediately check the flag, or after 17ms or 562ms. It does not matter. It does not take 1s as you wrote. So plenty of time to do a UART communication, a push button task, an ADC sample ....
--> the main() can see the flag immediately after the ISR has been processed.

The delay for ISR processing time does not add up.
the delay befor the task in main() is performed does not add up.
the processing time for the display does not add up.
--> The timing may be jittery, but it is accurate. It gets triggered every 1000000us. The absolute error is determined by the XTAL frequency. (= harware)

Indeed if you want to do a software RTC then you may do this iwth a 1s interrupt, count seconds from 0...59, and when the seconds jump from 59 to 0 a new minute starts. You may set a flag for a display update.

But recommend to use a much better granularity: An interrupt every 10ms, count 0..99 until 1s ... then count seconds 0...59, then count minutes from 0...59.. and so on.

Klaus
 

LaTeX Commands Quick-Menu:

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top