Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
void initTimer (void);
void delay (unsigned long milli);
void main (void)
{
//initialize peripherals
initTimer();
//PORTB all outputs
TRISB = 0;
LATB = 0;
TRISA = 0x0F;
ANSA = 0;
unsigned int allon = 0b1111111111111111;
unsigned int counter;
unsigned int zero = 0b0000000000000000;
if (PORTAbits.RA0 == 1 && PORTAbits.RA1 == 1 && PORTAbits.RA2 == 0)
for (counter = 0; counter < 5; counter++)
{
LATB = allon;
delay(SHORT_DELAY);
LATB = zero;
delay(LONG_DELAY);
}
}
I thought this was like the most foolproof code ever, but it doesnt stop after 5 times, not sure whats going on. The variables are set to binary, which determines which outputs are on or off, zero is alloff, and allon is the opposite
Unlike programs in hosted environments (that is running under OS) which can "return" from main by passing control back to the host, embedded bare-metal programs have nowhere to return. So a typical bare-metal program should have an infinite loop somewhere - either as some even-processing loop, periodic task loop or just in the end of the main function in case it has a finite sequence of actions. In your case it seem to be the last one - you only want to blink few times and halt. So the solution is to place
while(1);
in the end of main function such that it will enter infinite idle loop after execution until reset.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I have an inbuilt algorithm in my application. Whenever I run the algorithm, it saves that exact run time in the database. For example, if I run the algorithm at 11.00, it saves that time. And again if I run at 11.05, it saves 11.05 in the database.
I want to detect the number of times it Ran. So that once it runs for 5 times, I need to do some action like changing the values and reset the counter to 0. So that when it reaches 5 iterations, again I should reset the counter.
I am a beginner. It will be helpful if you could help me with the syntax.
MAIN
{
int temp1, temp2, flag = 0, max = 5;
temp1 = GET_INT_VALUE(8,1,84,1,0);
if flag = 0;
while(1)
{
if (templ == temp2)
flag++;
else
flag = 0;
if (flag == max)
{
//sprintf(Message,"SE value is %d",temp2);
PRINTOUT("Message");
flag = 0;
break;
}
}
}
END
The best way is to use a static local variable, like this:
void foo(void) {
static int counter = 0;
counter++;
if(counter > 5) {
counter = 0;
/* Do something every fifth time */
}
}
Note that you can't use a normal local variable (e.g. int counter = 0;) because its contents will be lost when the function returns. The static makes it work more like a global variable (so its value isn't lost when the function returns).
Using a 8-bit AVR micro, I arrived to a simple situation which might not be that easy to solve.
Consider the following snippet:
static volatile uint8_t counter;
//fires often and I need all the values of the counter.
void isr(void) {
counter++;
}
int main (void) {
while(1) {
send_uart(counter);
counter = 0;
delay_ms(1000); //1 sec pause
}
return 0;
}
1.) It can happen that send_uart is followed by an isr which increases the counter, and then the next statement zeroes it out.
Therefore I'll miss one data from the counter.
2.) If I use ATOMIC_BLOCK(ATOMIC_RESTORESTATE) in the main fn, I can avoid the problems declared in (1), but it can happen that I miss an ISR because in this case INTs are disabled for a short time.
Is there a better way to pass information from the main fn to ISR?
If the counter is sampled rather than reset, there won't be any timing issues. Increments happening while sending will be accounted for in the next iteration. The unsigned data type of the counter variables will guarantee well-defined overflow behavior.
uint8_t cs = 0; // counter sample at time of sending
uint8_t n = 0; // counter as last reported
while (1) {
cs = counter; // sample the counter
send_uart((uint8_t)(cs - n)); // report difference between sample and last time
n = cs; // update last reported value
delay_ms(1000);
}
Summary
I'm trying to write an embedded application for an MC9S12VR microcontroller. This is a 16-bit microcontroller but some of the values I deal with are 32 bits wide and while debugging I've captured some anomalous values that seem to be due to torn reads.
I'm writing the firmware for this micro in C89 and running it through the Freescale HC12 compiler, and I'm wondering if anyone has any suggestions on how to prevent them on this particular microcontroller assuming that this is the case.
Details
Part of my application involves driving a motor and estimating its position and speed based on pulses generated by an encoder (a pulse is generated on every full rotation of the motor).
For this to work, I need to configure one of the MCU timers so that I can track the time elapsed between pulses. However, the timer has a clock rate of 3 MHz (after prescaling) and the timer counter register is only 16-bit, so the counter overflows every ~22ms. To compensate, I set up an interrupt handler that fires on a timer counter overflow, and this increments an "overflow" variable by 1:
// TEMP
static volatile unsigned long _timerOverflowsNoReset;
// ...
#ifndef __INTELLISENSE__
__interrupt VectorNumber_Vtimovf
#endif
void timovf_isr(void)
{
// Clear the interrupt.
TFLG2_TOF = 1;
// TEMP
_timerOverflowsNoReset++;
// ...
}
I can then work out the current time from this:
// TEMP
unsigned long MOTOR_GetCurrentTime(void)
{
const unsigned long ticksPerCycle = 0xFFFF;
const unsigned long ticksPerMicrosecond = 3; // 24 MHZ / 8 (prescaler)
const unsigned long ticks = _timerOverflowsNoReset * ticksPerCycle + TCNT;
const unsigned long microseconds = ticks / ticksPerMicrosecond;
return microseconds;
}
In main.c, I've temporarily written some debugging code that drives the motor in one direction and then takes "snapshots" of various data at regular intervals:
// Test
for (iter = 0; iter < 10; iter++)
{
nextWait += SECONDS(secondsPerIteration);
while ((_test2Snapshots[iter].elapsed = MOTOR_GetCurrentTime() - startTime) < nextWait);
_test2Snapshots[iter].position = MOTOR_GetCount();
_test2Snapshots[iter].phase = MOTOR_GetPhase();
_test2Snapshots[iter].time = MOTOR_GetCurrentTime() - startTime;
// ...
In this test I'm reading MOTOR_GetCurrentTime() in two places very close together in code and assign them to properties of a globally available struct.
In almost every case, I find that the first value read is a few microseconds beyond the point the while loop should terminate, and the second read is a few microseconds after that - this is expected. However, occasionally I find the first read is significantly higher than the point the while loop should terminate at, and then the second read is less than the first value (as well as the termination value).
The screenshot below gives an example of this. It took about 20 repeats of the test before I was able to reproduce it. In the code, <snapshot>.elapsed is written to before <snapshot>.time so I expect it to have a slightly smaller value:
For snapshot[8], my application first reads 20010014 (over 10ms beyond where it should have terminated the busy-loop) and then reads 19988209. As I mentioned above, an overflow occurs every 22ms - specifically, a difference in _timerOverflowsNoReset of one unit will produce a difference of 65535 / 3 in the calculated microsecond value. If we account for this:
A difference of 40 isn't that far off the discrepancy I see between my other pairs of reads (~23/24), so my guess is that there's some kind of tear going on involving an off-by-one read of _timerOverflowsNoReset. As in while busy-looping, it will perform one call to MOTOR_GetCurrentTime() that erroneously sees _timerOverflowsNoReset as one greater than it actually is, causing the loop to end early, and then on the next read after that it sees the correct value again.
I have other problems with my application that I'm having trouble pinning down, and I'm hoping that if I resolve this, it might resolve these other problems as well if they share a similar cause.
Edit: Among other changes, I've changed _timerOverflowsNoReset and some other globals from 32-bit unsigned to 16-bit unsigned in the implementation I now have.
You can read this value TWICE:
unsigned long GetTmrOverflowNo()
{
unsigned long ovfl1, ovfl2;
do {
ovfl1 = _timerOverflowsNoReset;
ovfl2 = _timerOverflowsNoReset;
} while (ovfl1 != ovfl2);
return ovfl1;
}
unsigned long MOTOR_GetCurrentTime(void)
{
const unsigned long ticksPerCycle = 0xFFFF;
const unsigned long ticksPerMicrosecond = 3; // 24 MHZ / 8 (prescaler)
const unsigned long ticks = GetTmrOverflowNo() * ticksPerCycle + TCNT;
const unsigned long microseconds = ticks / ticksPerMicrosecond;
return microseconds;
}
If _timerOverflowsNoReset increments much slower then execution of GetTmrOverflowNo(), in worst case inner loop runs only two times. In most cases ovfl1 and ovfl2 will be equal after first run of while() loop.
Calculate the tick count, then check if while doing that the overflow changed, and if so repeat;
#define TCNT_BITS 16 ; // TCNT register width
uint32_t MOTOR_GetCurrentTicks(void)
{
uint32_t ticks = 0 ;
uint32_t overflow_count = 0;
do
{
overflow_count = _timerOverflowsNoReset ;
ticks = (overflow_count << TCNT_BITS) | TCNT;
}
while( overflow_count != _timerOverflowsNoReset ) ;
return ticks ;
}
the while loop will iterate either once or twice no more.
Based on the answers #AlexeyEsaulenko and #jeb provided, I gained understanding into the cause of this problem and how I could tackle it. As both their answers were helpful and the solution I currently have is sort of a mixture of the two, I can't decide which of the two answers to accept, so instead I'll upvote both answers and keep this question open.
This is how I now implement MOTOR_GetCurrentTime:
unsigned long MOTOR_GetCurrentTime(void)
{
const unsigned long ticksPerMicrosecond = 3; // 24 MHZ / 8 (prescaler)
unsigned int countA;
unsigned int countB;
unsigned int timerOverflowsA;
unsigned int timerOverflowsB;
unsigned long ticks;
unsigned long microseconds;
// Loops until TCNT and the timer overflow count can be reliably determined.
do
{
timerOverflowsA = _timerOverflowsNoReset;
countA = TCNT;
timerOverflowsB = _timerOverflowsNoReset;
countB = TCNT;
} while (timerOverflowsA != timerOverflowsB || countA >= countB);
ticks = ((unsigned long)timerOverflowsA << 16) + countA;
microseconds = ticks / ticksPerMicrosecond;
return microseconds;
}
This function might not be as efficient as other proposed answers, but it gives me confidence that it will avoid some of the pitfalls that have been brought to light. It works by repeatedly reading both the timer overflow count and TCNT register twice, and only exiting the loop when the following two conditions are satisfied:
the timer overflow count hasn't changed while reading TCNT for the first time in the loop
the second count is greater than the first count
This basically means that if MOTOR_GetCurrentTime is called around the time that a timer overflow occurs, we wait until we've safely moved on to the next cycle, indicated by the second TCNT read being greater than the first (e.g. 0x0001 > 0x0000).
This does mean that the function blocks until TCNT increments at least once, but since that occurs every 333 nanoseconds I don't see it being problematic.
I've tried running my test 20 times in a row and haven't noticed any tearing, so I believe this works. I'll continue to test and update this answer if I'm wrong and the issue persists.
Edit: As Vroomfondel points out in the comments below, the check I do involving countA and countB also incidentally works for me and can potentially cause the loop to repeat indefinitely if _timerOverflowsNoReset is read fast enough. I'll update this answer when I've come up with something to address this.
The atomic reads are not the main problem here.
It's the problem that the overflow-ISR and TCNT are highly related.
And you get problems when you read first TCNT and then the overflow counter.
Three sample situations:
TCNT=0x0000, Overflow=0 --- okay
TCNT=0xFFFF, Overflow=1 --- fails
TCNT=0x0001, Overflow=1 --- okay again
You got the same problems, when you change the order to: First read overflow, then TCNT.
You could solve it with reading twice the totalOverflow counter.
disable_ints();
uint16_t overflowsA=totalOverflows;
uint16_t cnt = TCNT;
uint16_t overflowsB=totalOverflows;
enable_ints();
uint32_t totalCnt = cnt;
if ( overflowsA != overflowsB )
{
if (cnt < 0x4000)
totalCnt += 0x10000;
}
totalCnt += (uint32_t)overflowsA << 16;
If the totalOverflowCounter changed while reading the TCNT, then it's necessary to check if the value in tcnt is already greater 0 (but below ex. 0x4000) or if tcnt is just before the overflow.
One technique that can be helpful is to maintain two or three values that, collectively, hold overlapping portions of a larger value.
If one knows that a value will be monotonically increasing, and one will never go more than 65,280 counts between calls to "update timer" function, one could use something like:
// Note: Assuming a platform where 16-bit loads and stores are atomic
uint16_t volatile timerHi, timerMed, timerLow;
void updateTimer(void) // Must be only thing that writes timers!
{
timerLow = HARDWARE_TIMER;
timerMed += (uint8_t)((timerLow >> 8) - timerMed);
timerHi += (uint8_t)((timerMed >> 8) - timerHi);
}
uint32_t readTimer(void)
{
uint16_t tempTimerHi = timerHi;
uint16_t tempTimerMed = timerMed;
uint16_t tempTimerLow = timerLow;
tempTimerMed += (uint8_t)((tempTimerLow >> 8) - tempTimerMed);
tempTimerHi += (uint8_t)((tempTimerMed >> 8) - tempTimerHi);
return ((uint32_t)tempTimerHi) << 16) | tempTimerLow;
}
Note that readTimer reads timerHi before it reads timerLow. It's possible that updateTimer might update timerLow or timerMed between the time readTimer reads
timerHi and the time it reads those other values, but if that occurs, it will
notice that the lower part of timerHi needs to be incremented to match the upper
part of the value that got updated later.
This approach can be cascaded to arbitrary length, and need not use a full 8 bits
of overlap. Using 8 bits of overlap, however, makes it possible to form a 32-bit
value by using the upper and lower values while simply ignoring the middle one.
If less overlap were used, all three values would need to take part in the
final computation.
The problem is that the writes to _timerOverflowsNoReset isn't atomic and you don't protect them. This is a bug. Writing atomic from the ISR isn't very important, as the HCS12 blocks the background program during interrupt. But reading atomic in the background program is absolutely necessary.
Also, have in mind that Codewarrior/HCS12 generates somewhat ineffective code for 32 bit arithmetic.
Here is how you can fix it:
Drop unsigned long for the shared variable. In fact you don't need a counter at all, given that your background program can service the variable within 22ms real-time - should be very easy requirement. Keep your 32 bit counter local and away from the ISR.
Ensure that reads of the shared variable are atomic. Disassemble! It must be a single MOV instruction or similar; otherwise you must implement semaphores.
Don't read any volatile variable inside complex expressions. Not only the shared variable but also the TCNT. Your program as it stands has a tight coupling between the slow 32 bit arithmetic algorithm's speed and the timer, which is very bad. You won't be able to reliably read TCNT with any accuracy, and to make things worse you call this function from other complex code.
Your code should be changed to something like this:
static volatile bool overflow;
void timovf_isr(void)
{
// Clear the interrupt.
TFLG2_TOF = 1;
// TEMP
overflow = true;
// ...
}
unsigned long MOTOR_GetCurrentTime(void)
{
bool of = overflow; // read this on a line of its own, ensure this is atomic!
uint16_t tcnt = TCNT; // read this on a line of its own
overflow = false; // ensure this is atomic too
if(of)
{
_timerOverflowsNoReset++;
}
/* calculations here */
return microseconds;
}
If you don't end up with atomic reads, you will have to implement semaphores, block the timer interrupt or write the reading code in inline assembler (my recommendation).
Overall I would say that your design relying on TOF is somewhat questionable. I think it would be better to set up a dedicated timer channel and let it count up a known time unit (10ms?). Any reason why you can't use one of the 8 timer channels for this?
It all boils down to the question of how often you do read the timer and how long the maximum interrupt sequence will be in your system (i.e. the maximum time the timer code can be stopped without making "substantial" progress).
Iff you test for time stamps more often than the cycle time of your hardware timer AND those tests have the guarantee that the end of one test is no further apart from the start of its predecessor than one interval (in your case 22ms), all is well. In the case your code is held up for so long that these preconditions don't hold, the following solution will not work - the question then however is whether the time information coming from such a system has any value at all.
The good thing is that you don't need an interrupt at all - any try to compensate for the inability of the system to satisfy two equally hard RT problems - updating your overflow timer and delivering the hardware time is either futile or ugly plus not meeting the basic system properties.
unsigned long MOTOR_GetCurrentTime(void)
{
static uint16_t last;
static uint16_t hi;
volatile uint16_t now = TCNT;
if (now < last)
{
hi++;
}
last = now;
return now + (hi * 65536UL);
}
BTW: I return ticks, not microseconds. Don't mix concerns.
PS: the caveat is that such a function is not reentrant and in a sense a true singleton.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
This is a follow-up question to Using a thread in C++ to report progress of computations.
Suppose that I have a for loop which executes run_difficult_task() many times, and I would like to infer how far the loop has advanced. I used to write:
int i;
for (i=0; i < 10000; ++i) {
run_difficult_task(i);
if (i % 100 == 0) {
printf("i = %d\n", i);
}
}
but the main problem with such approach is that executing run_difficult_task() might literally take forever (by being stuck in an infinite loop, etc.), so I would like to get a progress report in every k seconds by means of printing out the value of the loop variable i.
I found quite a rich literature on this site regarding object-oriented multithreading (of which I am not really familiar with) in various programming languages, but the questions I found doing this in C-style seem quite outdated. Is there a platform-independent, C11 way to do what I want? If there is not any, then I would be interested in methods working in unix and with gcc.
Note: I do not wish to run various instances of run_difficult_task in parallel (with, for example, OpenMP), but I want to run the for loop and the reporting mechanism in parallel.
Related: How to "multithread" C code and How do I start threads in plain C?
Linux (and also POSIX systems) provide the alarm library call. This allows you to do something after an interval of seconds without interrupting your main thread, and without bothering with multi-threading when you don't really need it. It was very much created for use cases like yours.
You can try using one thread (the worker thread) or possibly two (one that does computations and one that displays output while main is doing something else or just waiting) and some global variables (ugh).
The first thread will be your workhorse doing computations and updating some global variable. The second one (maybe simply the main thread) will then check whether this variable has changed or not and then print the stats (perhaps, that variable will hold the stats, for example, percentage).
What you can try:
int ping = 0, working = 0, data;
// in main thread
for (/* something */){
// spawn worker thread
while (working) {
if (ping) printf("%d\n", data), ping = 0;
}
}
// in worker thread
working = 1;
while (/* something */) {
// do a lot of computations
if (/* some condition */) {
if (! ping) {
data = /* data */
ping = 1;
}
}
}
working = 0;
Here's a simple time based progress indicator that I've often used:
void
progress(int i)
{
time_t tvnow;
static time_t tvlast;
static time_t tvbeg;
if (tvbeg == 0) {
tvbeg = time(NULL);
tvlast = tvbeg - 2;
}
tvnow = time(NULL);
if ((tvnow - tvlast) >= 1) {
printf("\r%ld: i = %d",tvnow - tvbeg,i);
fflush(stdoout);
tvlast = tvnow;
}
}
int i;
for (i=0; i < 10000; ++i) {
run_difficult_task(i);
progress(i);
}
UPDATE:
Does this update if run_difficult_task(i) runs for longer than 2seconds?
No, but I've updated the example to put the progress code in a separate function, which is what I normally do in my own code.
You'll have to add calls to the progress function within run_difficult_task to get finer grain progress--this is something I also do in my own code.
But, notice that I added an elapsed time [in seconds] to the progress.
If you didn't care about that, if run_difficult_task takes longer than 2 seconds to run, there is no progress until it returns as you define it because progress is defined by incrementing i which is done by the outer loop.
For my own stuff, the progress function can handle an arbitrary number of progress indicators from an arbitrary number of worker threads.
So, if that would be of interest to you, and [say] run_difficult_task has some inner loop variables like j, k, l, these could be added to the progress. Or, whatever you wish to report on.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am very new to this programming, trying to seta project up on proteus to add, minus and set an alarm through the use of buttons connected to a PIC. Issue is the count is not saving after the while loop and is being reset.
- button1= ADD, button2=MINUS, button 1+2+3 = ALARM
- cant figure out why overall count is being reset to 0
- Any help would be amazing
#include <main.h>
#ZERO_RAM
int a = 0;
int state;
char data = 'y';
short int flags[3];
char uart_rd;
void main()
{
setup_wdt(WDT_1MS); //~1.0 ms reset
port_a_pullups(0xFF); // Defining PORTA as pullup Resistors
printf("program start" nr); //<------keeps resetting value to 0 HERE
while (TRUE) // infinite loop
{
if (!input(PIN_A1)) // add button
{
if (!flags[0])
{
flags[0] = 1;
a++; // add one to overall count
printf("ADDED, Total= %dnr", a); // prints count
}
}
else
{
flags[0] = 0;
}
if (!input(PIN_A2)) // minus button
{
if (!flags[1])
{
flags[1] = 1;
a--; // take away 1 from count
printf("MINUS, Total= %dnr", a); // print count
}
}
else
{
flags[1] = 0;
}
if ((!input(PIN_A1)) && (!input(PIN_A2)) && (!input(PIN_A3))) // all buttons equal alarm
{
printf("ALARM HAS BEEN SETnr"); // if all buttons are held constant alarm
// is printed through Terminal
}
else
{
flags[2] = 0;
output_high(PIN_A0); // led goes high
delay_ms(500); // flashing LED every cycle
output_low(PIN_A0); // led goes low
printf("Overall Count= %dnr", a); // printf overall count
}
}
}
You have the following bugs:
You never initialize flags anywhere. Sure, static storage duration variables are required by the standard to be initialized to zero. But in embedded systems, there is an incredibly common non-standard extension which removes the "zero-out" part from the start up code. When you create a project you often get an option "minimal startup" or "standard C". Therefore, always initialize all your variables manually in run-time before using them. Robust embedded code makes no assumptions about the default values of variables in neither .datanor .bss segments.
You haven't implemented any debouncing. Please check some beginner tutorial about how to read buttons in embedded systems, to avoid problems with the electro-mechanical signal bounce. The signal bounce causes the code flags[0] = 0; to get executed.
Whenever someone presses a button, your condition for increasing the counter remains true for as long as the button is pressed. The microcontroller is fast enough to run that code many thousand times over during the time a slow human keeps the button pressed. Instead, you should only increase the counter when the button goes from inactive to active. Obviously, the code doing this needs to be located after the debouncing.