Calling main function from another function in C - c

I have a main function that runs a few functions during initialization and then runs a while loop that waits for commands from the UART.
When I see a specific command (let's say reset), I call a function that returns a value. I want to do the following things:
Save the returned value
Start the main function again with the returned value. The returned value is required during initialization of the functions in main.
I am newbie in C and I am not able to figure out a way save variable value in main.

The way I understand things, you essentially have the following setup:
int main(int argc, char *argv[]) {
int value = something_from_last_reset;
perform_initialization(value);
while(1) {
int next_command = wait_for_command();
if(next_command == RESET_COMMAND) {
value = get_value();
// somehow restart main() with this new value
}
}
return 0;
}
Here's one approach you could take:
// global
int value = some_initial_value;
void event_loop() {
while(1) {
int next_command = wait_for_command();
if(next_command == RESET_COMMAND) {
value = get_value();
return; // break out of the function call
}
}
}
int main(int argc, char *argv[]) {
while(1) {
perform_initialization(value);
event_loop();
}
return 0;
}
This essentially lets you "escape" from the event loop and perform the initialization all over again.

just wrap your main into infinity-loop.
int main(void)
{
int init_val = 0;
while (1)
{
// your code ...
init_val = some_function();
}
}

In theory this is possible, but it kind of breaks paradigms, and repetitively calling a function without ever letting it finish and return will quickly fill up your call stack, unless you take measures to unwind it behind the compiler's back.
A more common solution would be to write your main() function as one giant infinite while {1} loop. You can do all of your operation in an innner loop or whatever, and have clauses such that if you get your desired new value you can fall through to the bottom and loop back, effectively re-running the body of main with the new state.

Related

Passing int arguments in mbed::Callback

#include "mbed.h"
#include <Callback.h>
InterruptIn up(p14);
void toggle1(int *player)
{
printf("%d \n", *player);
}
int main()
{
int player = 1;
up.rise(callback(toggle1, &player));
}
In the mbed callback function, why the result is not 1? It is 12784.
You are allowing your main function to return. After it returns, player will be out of scope so it might be overwritten with something else. In general, you never want to return from main in an embedded system, so I recommend adding while (1) {} at the end of your main function.
Also, using callback is a source of unnecessary complication and potential errors. I would just put player in a global variable (and mark it as volatile). Then you can simply do up.read(&toggle1).

How can I go to the beginning of main function from a sub function in C programing language?

I am writing a C code, this code consist with many sub functions and also within a sub function there is another sub function after execution of this sub sub function I need to go back in the beginning of main function.
My question is how can I exit from this function and come back main function?
As this code is too big That is why I have not include this code in here.I think return; cant do this thing because it returns only to the function where it got function call. I am beginner in C programming so please suggest what thing I have to do for this?
THIS ANSWER NEEDS A HEALTH HAZARD - THIS IS THE WRONG WAY TO PROGRAM
You can use setjmp and longjmp to do this.
But PLEASE do everything in your power to avoid this - by thinking about the design of the code beforehand
C maintains a stack of nested functions. If your main program calls function one and that calls function two, you can only get back to the main program by unwinding the stack using a return statement in each function (therefore from two back to one, and then back to main). So I don't think you can do what you're wanting. You can terminate the program completely with the exit statement.
Jumping across function boundaries is contrary to structured programming, and while possible (using setjmp(), longjmp()) is inappropriate and unnecessary in this case.
You need not treat function calls as simple sub-routines - they take arguments and return values; the return value in particular is useful in this case for providing information to the caller for controlling program flow.
Based on your (somewhat confusing) diagram:
typedef enum tStatus
{
STATUS_FAIL ;
STATUS_SUCCESS ;
} tStatus;
void function1( void ) ;
tStatus function2( void ) ;
tStatus function1n( void ) ;
int main()
{
for(;;)
{
// statement1
// statement2
function1() ;
if( function2() == STATUS_SUCCESS )
{
// statement3
}
}
return 0 ;
}
void function1( void )
{
// do something
}
tStatus function2( void )
{
// statement1
// statement2
tStatus status = function1n() ;
if( status == STATUS_SUCCESS )
{
// statement n
}
return status ;
}
tStatus function1n( void )
{
tStatus status = STATUS_FAIL ;
// statement1
if( !condition)
{
status = STATUS_SUCCESS ;
// statement n
}
return status ;
}
If you follow the code flow, you will see that when in function1n() condition is true then STATUS_FAIL is returned to function2(), which returns STATUS_FAIL to main() which then causes control flow to return to the top of the main() loop.
Note that most simple bare-metal embedded systems do not return from main() so an indefinite loop is the normal implementation when no OS or RTOS is used.
Make the inner function return a value rather than void. Use that value in the middle function to determine if you should return to main.
int main(void) {
f2();
return 0;
}
void f2(void) {
if (f1()) return;
/* ... */
}
int f1(void) {
if (condition true) return 1;
/* ... */
return 0;
}

how to call a sub function only once within an periodically function call

I'm beginner with c and have a simple question:
I have a function myfunction() which is called periodically every 100 ms.
Within this function I have to call an other function but only once at the first call at beginn of myfunction(), but no periodically.
void myfunction() // function is called periodically every 100 ms
{
...
mySubfunction(); // this function have to be called only once in the first call of myFunction() and than skipped each time after that.
} ...
How to realize this in c?
Use static? Something along the lines of
void myfunction() // function is called periodically every 100 ms
{
static int once = 1;
if (once) {
mySubfunction();
once = 0;
}
}
The variable once in the example will be initalized only once and retain its value between invocations because of static keyword.
Be aware of implications in multithreaded environment, see this question.
you can have something like
static int flag = 1
void myfunction() // function is called periodically every 100 ms
{
if(flag)
{
mySubfunction();
flag = 0;
}
}
...
on first look task is very simply, can be next code:
void func()
{
static LONG first = TRUE;
if (_InterlockedExchange(&first, FALSE))
{
subfunc();
}
// some code
}
this give 100% guarantee that subfunc() will be called once and only once even if several thread in concurrent call your func()
but what be if // some code depended on result of subfunc ? in this case task become already not trivial. need some synchronization. and here already depended from os or compiler. in Windows, begin from Vista understand this problem and add function InitOnceExecuteOnce - read Using One-Time Initialization
if your subfunc() have no in and out parameters code can be very simply:
BOOL CALLBACK InitOnceCallback(PINIT_ONCE /*InitOnce*/, PVOID /*Parameter*/,PVOID* /*Context*/)
{
subfunc();
return TRUE;
}
void func()
{
static INIT_ONCE once = RTL_RUN_ONCE_INIT;
if (InitOnceExecuteOnce(&once, InitOnceCallback, 0, 0))
{
// somecode
}
// error init
}
also some modern compilers can correct handle static one time initialization. say latest versions of CL. with it code can be next:
void func()
{
static char tag = (subfunc(), 0);
// some code
}
here CL internally call special functions (implemented in CRT) _Init_thread_header, _Init_thread_footer - implementation can be look in crt source code - thread_safe_statics.cpp
This may be more advanced than you're looking for, but you could use function pointers and change which function gets called.
// Function declarations
void mySubfunction(void);
void myNormalfunction(void);
// Function pointer, which can be changed at run time.
static void (*myfunction)(void) = mySubfunction;
void mySubfunction(void)
{
// Do the sub-function stuff.
// Change the function pointer to the normal function.
myfunction = myNormalfunction();
// Do the normal function stuff (if necessary on the first call).
myNormalfunction();
}
void myNormalfunction(void)
{
// Etc.
}
int main(void)
{
int x;
for(x = 0; x < 3; x++)
{
// Call myfunction as you usually would.
myfunction();
}
return 0;
}

map function pointers to specific numbers at runtime

I have a problem that i can even start to work on because i don't get it how can be done.
So we have a code
int test_handler() {
printf("Test handler called\n");
return 1;
}
// Test your implementation here
int main()
{
register_irq_handler(30, &test_handler);
do_interrupt(29); // no handler registered at this position, should return zero
do_interrupt(30); // calls handler at position 30, expected output: Test handler called
return 0;
}
I need to make those functions register_irq_handler, do_interrupt(29).
But i have no clue how to start, i am looking for a little help to send me on the right direction.
How i store 30 to point to this function when we don't have a global variable to store that "connection" or i am missing something.
You can't do it without a global variable (why would having a global variable be a problem?).
You probably need something like this:
// array of 30 function pointers (all automatically initialized to NULL upon startup)
static int(*functionpointers[30])();
void register_irq_handler(int no, int(*fp)())
{
functionpointers[no] = fp;
}
int do_interrupt(int no)
{
if (functionpointers[no] != NULL)
{
// is registered (!= NULL) call it
return (*functionpointer[no])();
}
else
{
// not registered, just return 0
return 0;
}
}
Disclaimer
This is non tested non error checking code just to give you an idea.

switching up/down the stack with getcontext/setcontext

I am trying to understand if getcontext/setcontext will work correctly in a specific scenario.
I can see how setcontext() can be used to unwind the stack back to a certain place in history.
#include <stdio.h>
#include <ucontext.h>
int rollback = 0;
ucontext_t context;
void func(void)
{
setcontext(cp);
}
int main(void)
{
getcontext(&context);
if (rollback == 0)
{
printf("getcontext has been called\n");
rollback++;
func();
}
else
{
printf("setcontext has been called\n");
}
}
But I was wondering if after an unwind you can re-wind back to a place that was in the future? I suppose this depends on the getcontext() call captures a copy of the stack and I can't find the exact details in the documentation.
#include <stdio.h>
#include <ucontext.h>
int rollback = 0;
int backToFuture = 0;
ucontext_t context;
ucontext_t futureContext;
void func(void)
{
// Some complex calc
if (some-condition)
{
getcontext(&futureContext); // After returning I want to come back
// here to carry on with my work.
if (backToFuture == 0)
{
setcontext(&context); // rewind to get stuff-done
}
}
// Finishe work
}
int main(void)
{
getcontext(&context);
if (rollback == 0)
{
printf("getcontext has been called\n");
rollback++;
func();
// eventually always return here.
}
else
{
printf("setcontext has been called\n");
// Do specialized work that needed to be done
// May involve function calls.
//
// I worry that anything the adds new stack frames
// will disrupt the saved state of futureContext
//
// But without detailed information I can not be sure
// if this is an allowed senario.
backToFuture = 1;
setcontext(&futureContext);
}
}
getcontext doesn't copy stack, it only dumps registers (including stack pointer) and a little context data like signal mask, etc.
When you jump down the stack it invalidates the top context. Even if you won't do any function calls think about the signal handler that can execute there. If you want to jump between two stacks you need to makecontext.
I added variable that demonstrates that your code is invalid:
void func(void)
{
// Some complex calc
if (1)
{
volatile int neverChange = 1;
getcontext(&futureContext); // After returning I want to come back
// here to carry on with my work.
printf("neverchange = %d\n", neverChange);
if (backToFuture == 0)
{
setcontext(&context); // rewind to get stuff-done
}
}
// Finishe work
}
On my machine it results in:
getcontext has been called
neverchange = 1
setcontext has been called
neverchange = 32767

Resources