views:

27

answers:

2

Hello. I'm using stm32f103 with GCC and have a task, which can be described with following pseudocode:

void http_server() {
  transmit(data, len);
  event = waitfor(data_sent_event | disconnect_event | send_timeout_event);
}

void tcp_interrupt() {
  if (int_reg & DATA_SENT) {
    emit(data_send_event);
  }
}

void main.c() {
  run_task(http_server);
}

I know, that all embedded OSes offer such functionality, but they are too huge for this single task. I don't need preemption, mutexes, queues and other features. Just waiting for flags in secondary tasks and raising these flags in interrupts. Hope someone knows good tutorial on this topic or have a piece of code of context switching and wait implementation.

+1  A: 

You will probably need to use an interrupt driven finite state machine.

doron
Yes, that's possible approach. But code will look ugly with long switches. That's why I'm looking for wait() implementation. Then all this can be done in much more clear way.
cos
The only other option is a non-preemptive scheduler but this involves multiple stacks (ie more memory)
doron
Sure, I agree on multiple stacks. But I need a piece of code or tutorial to see how it can be implemented.
cos
Unless you want to implement a full blown scheduler, you are probably better off sticking with a FSM
doron
A: 

There are a number of IP stacks that are independent of an operating system, or even interrupts. lwip (light weight ip) comes to mind. I used it indirectly as it was provided by xilinx. the freedos folks may have had one, certainly the crynwr packet drivers come to mind to which there were no doubt stacks built.

As far as the perhaps more simpler question. Your code is sitting in a foreground task in the waitfor() function which appears to want to be an infinite loop waiting for some global variables to change. And an interrupt comes along calls the interrupt handler which with a lot of stack work (to know it is a tcp interrupt) calls tcp_interrupt which modifies the flags, interrupt finishes and now waitfor sees the global flag change. The context switch is the interrupt which is built into the processor, no need for an operating system or anything fancy, a global variable or two and the isr. The context switch and flags/events are a freebie compared to the tcp/ip stack. udp is significantly easier, do you really need tcp btw?

If you want more than one of these waitfor() active, basically you don want to only have the one forground task sitting in one waitfor(). Then I would do one of two things. have the foreground task poll, instead of a waitfor(something) change it to an if(checkfor(something)) { then do something }.

Or setup your system so that the interrupt handler, which in your pseudo code is already very complicated to know this is tcp packet data, examines the tcp header deeper and knows to call the http_server() thing for port 80 events, and other functions for other events that you might have had a waitfor. So in this case instead of a multitasking series of functions that are waitfor()ing, create a single list of the events, and look for them in the ISR. Use a timer and interrupt and globals for the timeouts (reset a counter when a packet arrives, bump the counter on a timer interrupt if the counter reaches N then a timeout has occurred, call the timeout task handler function).

dwelch