Is it safe to call main() from anywhere?

Go To Last Post
59 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm receiving UART in an interrupt vector. If a special string comes in, I want to stop everything I'm doing in my main program, and start it from the start, while not losing any of my current data (boolean values, current UART buffer contents, etc).

So, when I get this string in my uart interrupt vector, I'm calling main() and sei() again.

Is this safe? Is there a better way around this?

Cheers,
Tom Kurowski

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

And what's about the stack? You will get a stack overflow, since you don't remove the return-address and the pushed registers (main() let's me assume, you use C).
The safe way is a flag in main, that restarts main or a reset (without all your variables getting re-initialized - that's compiler-spefic).

/Martin.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Design your program so you don't need to do this!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Although I agree that is one solution, I was hoping maybe someone had an answer that involved using a similar approach to the one I described... and perhaps some information as to why what I described would be a bad decision under the assumption that it is.
;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The stack, as mentioned, is the obvious problem, but some approaches are just wrong. Like coming into the house with muddy shoes, and wrapping your jacket around them to keep from tracking up the house. It's easier, more efficient, and more polite to just take your shoes off.

I know that's not an answer, but why look for trouble when it's easy enough to avoid it all together?

Chuck Baird

"I wish I were dumber so I could be more certain about my opinions. It looks fun." -- Scott Adams

http://www.cbaird.org

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

tkurowski wrote:
I was hoping maybe someone had an answer that involved using a similar approach to the one I described... and perhaps some information as to why what I described would be a bad decision under the assumption that it is.
I doubt that you're going to have anyone recommend your approach because it's obviously bad. mtashal told you why it's bad (stack overflow) and gave you a good way to restructure your program.

Maybe the point you're missing is that main() doesn't ever return to the ISR. Even if it did, (which would cause other problems) you don't want to call a time-consuming program from an ISR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well if there was an easy approach, I missed it and will have to think it over ;p
I thought AVR allowed interrupts within interrupts - thats why I set sei() once I called main() from my interrupt. Exactly what is happening to the stack when I do that (layman's terms)?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Not only is it bad, it doesn't do what you want. Any global variables will be re-initialized, and any local variables will be lost entirely, so your current data hasn't a prayer of a chance.

Quote:
Exactly what is happening to the stack when I do that (layman's terms)?
Nothing at all, which is the problem. Any memory being used by the stack is now locked up and unusable. Unless, of course, you return from main, but I doubt that that would be useful to you.

Regards,
Steve A.

The Board helps those that help themselves.

Last Edited: Wed. Mar 30, 2011 - 05:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First, have you accepted the fact that a properly coded main() routine never returns? Without understanding that, there's not much use in proceeding.

Assuming that you understand this, can you see that calling main() from the ISR prevents the ISR from ever returning from the ISR? It is the return from ISR that pops off registers from the stack which were pushed when the ISR was called. Each new interrupt will push registers on the stack until it overflows.

I see that you are calling main() then calling sei. Because interrupts are normally enabled early in main(), this is why you will continue to get interrupts. Otherwise, you'd get one interrupt and would probably be stuck in main() forever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now thats a good reason to not utilize this approach. Thank you very much everyone.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I take back one thing I said, calling main from within the program will not reset your global variables, that is done before you get to main. But you will still lose your local variables.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This sounds like it's crying out for a flowchart to show the program design. I simply cannot believe that it's not possible to structure this in a different way - perhaps with some kind of "supervisor loop" in main()? But you need to design it properly. Just organically growing programs by tacking new bits on when the need arises is not a great design process. If the algorithm is properly designed in the first place you'll have worked everything out even before you start the coding phase.

(in the old days IT used to consist of "systems analysts" and "programmers". The analysts were the ones with brains paid the big money and programmers were just the "grunts" doing the menial (and not particularly well paid) job of implementing the designs from the analysts - the clever bit in programming is the design phase)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

While there are other ways to do it, I don't see anything wrong with manipulating the stack pointer yourself. I had a very effective last-in first-out multitasking system based on the 680x0 in the Macintosh that recursively called the main routine for each new task and restored the stack pointer on completion or abort, using the stack to save and restore the few global variables needed.

One way to change the exit from an interrupt is to rewrite the stack return address. You could then exit to the main routine, losing stack forever, or move the stack interrupt frame back up the call chain to whatever subroutine you want to return to and resume execution from there, for the main routine SP=RAMEND-sizeof(interruptframe). Don't call subroutines while manipulating the stack pointer of course. If using heaps save the stack pointer after an early allocation and back up only to that.

Or you can just clear the interrupt condition, zap the stack, and jump to main.

It's not all that complicated and usually either works forever or breaks immediately.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you need to reset your program you don't want to call main, nor do you want to jump to address zero since neither will start the CPU as if it was just powered on. The xmega has a software reset command but the atmegas and tinys only have the watchdog. By forcing the watchdog to timeout you will reset the cpu and restart your program. Any variables you need to survive the reset must be put in a noinit region known to the linker so the default initialization code that runs before your main() won't destroy them. Your program will then have to initialize these areas itself. There is a cpu register (MCUSR IIRC) that contains a value indicating the source of the reset (choices of poweron, hardware, watchdog, brownout) so your program can read this and choose to init all variables or not.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is one of those things that is a doss in assembler and tough in C.

A hard reset (CTRL-BRK) in my BASIC interpreter just jmps to the reset vector which then resets the stack and everything ;-).

One cheat that could work is to use a part with a single byte stack pointer. When all those unresolved recursive interrupts build up the stack will just wrap around to 0xFF and overwrite all those return addresses that will never be used ;-)

Cheers,

Joey

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

This is one of those things that is a doss in assembler and tough in C.

OK, I'll bite: Why is it tougher in C than assembler? The "partial clearing" stuff has to be partitioned and handled either way. Unless the magic incantation happens to be a jump into the middle of the C prologue (which could indeed be done in C if the prologue made the label available--oh, wait, you'd have to do that in ASM too--I don't see any magic ASM bullets here.

But that said, I think Tom is way off here. As near as I can guess, it is something like a malformed comms message and the comms engine needs to be restarted.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is something like this usefull for you?

static volatile Isr_Ready;
ISR serial receive()
{
  static uint8_t Byte_Count;

  ++Byte_Count;

  if(Byte_Count >= 10)
  {
    Byte_Count = 0;
    Isr_Ready = 1;
  }
}

void main( void)
{
  for(;;)
  {
    if(Isr_Ready))
      All_Data_Received(); // Also reset Isr_Ready
    Do_Something();
    Do_Something_Else();
  }
}

This is a sort of standard and simplest way for this kind of software. Just buffer the data in the uart interrupt (Circular buffer?) and when there is enough data to do something usefull with then just set a volatile flag variable in the interrupt function. This flag is checked in main() and the rest of the processing is done there. If the functions Do_Something() and Do_Something_Else() take to much time they can also check the Isr_Ready flag and return immediately.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You guys have had some really interesting discussions - thanks for all the input.

The biggest problem with my system is that upon receiving that special string in my circular uart buffer, I have to immediately stop sending. Simply disabling the UART means theres always one character left and its a weird one. I guess I could overwrite the uart send register with 0xFF?

As for manipulating the stack - maybe another day :), Im already learning enough stuff at the moment as it is!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I have to immediately stop sending. Simply disabling the UART means theres always one character left and its a weird one.

So if you simply set TXEN=0 it finishes sending the last one does it? I never knew that. But how does jumping to 0x0000 or main: help this? There's still going to be opcodes fetched/executed and meanwhile the UART is going to keep pumping isn't it? In fact immediately setting TXEN=0 is as close to immediate disabling as you can get isn't it? Even trying for a watchdog reset would take time. I guess you could use an IO line to pull _RESET low and see how that works out for you?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I think I get the picture now. You receive a string--e.g. "STOP!". That implies multiple characters. Where is the sender? On a PC, say? So the sender took 100ms per character to type in the string and Enter to send. About a millisecond a character for transmission. So after spending 500ms typing and 5ms transmitting, you need to stop so immediately that you have to invent a way to make entirely new RTOS-like features never seen before in Computer Science.

How is the receiver going to know if you sent 0 or 1 or 2 or 7 bits, 100us each (say), after the string was sent at an arbitrary time?

Doesn't your send-string have a circular buffer, or some other method of queueing an message? So you simply empty the buffer, so the TXC/UDRE handler thinks it has no more to send. All my apps have a buffer-flush anyway, in case of anomalies though admittedly I think I only use the in RX and not TX.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) When you receive the "stop" command set a flag.
2) in the main loop you can have something like this...

int main()
{
	while(flag != false)
	{
		doMainExecution();
	}
}

//Or possibly this cumbersome way...

int main()
{
	restart:
	
	if(flag != false)
	{
		doSomething();
	}
	else
	{
		flag = false;
		goto restart;
	}
	
	if(flag != false)
	{
		doSomethingElse();
	}
	else
	{
		flag = false;
		goto restart;
	}
}

If you want to totally pre-empt the code mid operation then you will probably want to look at some of the techniques used in pre-emptive RTOS's.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

'Bout the only reason I could see that you would want to stop sending is for handshaking. This is usually done by XON/XOFF characters (look up your ASCII chart). If you receive a XOFF, set a flag to tell the usart tx code to stop sending. If you receive a XON, then reset the flag. All this before the rx char makes it into the circular buffer. When terminal programs talk about software handshaking - this is it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
OK, I'll bite: Why is it tougher in C than assembler?

In assembler all it needs is:

rjmp RESET

(Works for me)

Cheers,

Joey

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

In assembler all it needs is:

In C all it needs is:

((void (*)(void))0x0000)();

which actually generates:

	ldi r30,lo8(0)	 ; 
	ldi r31,hi8(0)	 ; 
	icall

Though most C compilers will support a variant of:

asm("JMP 0");

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

[Sigh] And of course both of you remember that registers are not reset to their default state and for example active interrupts may still trigger.
[/Sigh]
I just wonder how many people read this and think it is a neat trick without even knowing what a stack pointer or initialisation code is.

Doing magic with a USD 7 Logic Analyser: https://www.avrfreaks.net/comment/2421756#comment-2421756

Bunch of old projects with AVR's: http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, that's obvious. The usual use for:

((void (*)(void))0x0000)();

or equivalent is in a bootloader but it would be VERY unwise not to precede it with a WDT reset obviously.

I was simply counteracting the suggestion to to get to 0 was some how "easier" in Asm. In both it can be done with a single statement.

One might say the C is "less efficient" I guess using 3 opcodes and because it does ICALL the stack is inbalanced - but that doesn't matter because the first thing the code at 0x0000 will do is re-init SP before it initialises .data wipes .bss (but not .noinit).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Taken as read, Paul.

As I said it works for me. But then I never make assumptions about the state of registers or SRAM at boot.

My current project includes other reset options, which conciously preserve some registers/data while clearing others.

Touche, though I must accept Clawson's correction.

Cheers,

Joey

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
In assembler all it needs is:

rjmp RESET


Quote:
In C all it needs is:

((void (*)(void))0x0000)();

And likely neither does what the OP asked for. He wanted to do this without losing his data. Certainly this would not be true in C, and you would have to write the assembly with that specifically in mind.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Koshchi wrote:
Quote:
In assembler all it needs is:

rjmp RESET


Quote:
In C all it needs is:

((void (*)(void))0x0000)();

And likely neither does what the OP asked for. He wanted to do this without losing his data. Certainly this would not be true in C, and you would have to write the assembly with that specifically in mind.
With avr-gcc, he wouldn't lose the data in .noinit .
Of course, it would be slightly non-trivial to initialize that data at power-up.

Moderation in all things. -- ancient proverb

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You know what, you're right. Even if I jumped to main, I could still have one lingering character. Its always funny to realize that complicating may just result in the exact same behaviour (or worse). Anyways, the worse part about receiving "STOP" is that everything should actually stop right before receiving STOP. Ideally it would be "STOP*" such that I can read the STOP, turn of Tx, then receive the '*', and move on with my life. But thats not the case, so I guess I'll always have the possibility of incorrect output. I can definitely search for the string in my interrupt receive. That could lessen the possibility, so thats what I'll have to go with.

This is the problem with using pre made modules that you don't realize don't have enough information output when you get them. Oh well! Thanks again for the realization ;)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Anyways, the worse part about receiving "STOP" is that everything should actually stop right before receiving STOP. ...

With XON/XOFF that is not the case--the flow control will have a trigger level in the buffer. And that level will not be "buffer full".

But you haven't really given us the details--we can only surmise from a bit of information here and there.

Even if you do want to "stop ASAP", there is certainly not any need to call main() from anywhere.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No XON/XOFF option unfortunately. But ultimately, as you suggested, my original question has been answered, and you've shed light on the situation in general for me. Thank you very much.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not clear about what is needed or the data structure.

:::::I'm receiving UART in an interrupt vector...

A UART is a hardware device or peripheral attached to the CPU. I assume that data is coming into the UART and is being placed into a queue by the UART's Receive interrupt procedure.

::::If a special string comes in,... Is this a specific byte value or a specific sequence of byte values? It would be MUCH easier to code if this 'special string' were a single specific byte value since then the interrupt routine could check for this value as the bytes are coming into the UART.

::::: I want to stop everything I'm doing in my main program,....
Here the question is How Fast do you want to stop what the main program is doing. If your 'special string' is a specific sentinal value (like for example, 0xaa, a value that would never get sent to the AVR unless the AVR was being signaled to change what it was doing immediately), then the UART interrupt receive routine would set a flag for the Main code. The Main program activity would check for this flag being set at a period determined by 1/10th of the baud rate (the character input rate). Upon acknowledging the activated flag, the main code would go to a procedure that would put the system into the quasi-reset state, and return to Main code.

::: ....and start it from the start, while not losing any of my current data (boolean values, current UART buffer contents, etc).

Everything that you want to remain from the 'special string' event should be set up by the initialization code before the Main code starts running. And the 'special string' event handler code should enter Main as if were a power-on/reset event. Main should not be able to tell whether it is being called by power-on/reset or 'special-string' event.

::: ... stop further UART transmits.
This is done by having two UART queues. One for input and one for output. The output queue is controlled by the UDRE interrupt, which is seperate from the UART receive interrupt. Instead of putting a byte into the UDR and waiting for it to be sent, put the byte into the transmit queue and turn on the UDRE interrupt. The interrupt happens immediately. It gets the byte that you just put into the queue and puts it into the UDR for transmission, then adjusts the output pointer. If the output pointer equals the input pointer, then it turns off the UDRE interrupt. This method allows putting many bytes for transmission into a buffer and letting the UART transmitter run in the background. You can stop transmitting (at the next byte in the queue, not the byte being currently transmitted) by turning off the UDRE interrupt. Untransmitted bytes will be those between the output and the input pointers of the transmit queue.

Hope that this helps. Will be happy to explain in more detail.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Anyways, the worse part about receiving "STOP" is that everything should actually stop right before receiving STOP.

Do I get this right?! "Right before receiving STOP"?!

If you succeed in designing an algorithm that see future events you will be famous!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You did get it right. It's my one disappointment with the module I'm using.

Simonetta, thank you for your input. Perhaps I will further investigate a send queue.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Tell us about this "module". No decent commercial product would require that the rules of the space-time continuum be violated.

I suspect it is standard flow control, and one or even a few characters are allowed.

Or this is a very elaborate troll leading up to April 1.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hehe no trolls.

Wifly by Roving: http://www.sparkfun.com/products...

No flow control. When a connection is open, it is opened, then *OPEN* is sent. I could be sending information during that time. If there was an output pin that could tell me the current connection status that would be nice. Additionally, theres no output based on whether all the information transmitted to the module has been sent, and I'm stuck with adding delay loops throughout my program to ensure the information has been sent over the internet.

Cross my fingers for firmware updates.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can't find a single occurrence of "STOP" (or "stop") in the data sheet. But I do find two pins for "flow control" (the proper term for "handshaking").

So either the "STOP" is not coming from the module, which makes sense since it's only a communication device for 802.11 wireless LAN, but from the device ultimately at the other end of the network connection. (Yes, you can have "conversations" with the module as such, for e.g. establishing communication parameters etc, but I could not find any "STOP" response.)

Or I'm blind. :wink:

Or you got this from some other document.

Or you've been taken for a ride..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Additionally, theres no output based on whether all the information transmitted to the module has been sent

Are you actually meaning to say "there's no output based on whether all the information transmitted to the module has been sent, and has arrived safely at the ultimate receiver".

If so, no there isn't, and that is how "Ethernet" is designed. It is not the responsibility of Ethernet (802.whatever) to handle that. It is handled by protocols stacked on top of the Ethernet protocol. E.g. in the TCP/IP protocol suite (a.k.a. internet) it is the responsibility of TCP, two levels above the physical layer (which often is Ethernet/802.whatever).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This module uses the TCPIP stack, So it should be able to tell me if all data is sent (right?). Incorrect: "There is flow control, but in the latest firmware release, it doesnt work yet" - I read an older firmware upgrade, I can use this now. But doesn't this just guarantee the UART tx and rx arrive properly? Not really an issue for me... i could be way off tho.

There is no STOP, I was using it because it was a good example that someone brought up. I'm actually dealing with "*OPEN*". As *OPEN* comes in, I could be sending data already, rendering the HTTP code Im sending structured improperly (and the page doesnt load right).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does '*' appear in any other string? If not it could be an early indication that "*OPEN*" was on its way.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am possibly very stupid, but I am not getting what is going on here. Assuming that the problem feared is data overrun in the module, then

i) I'd suspect that you'd need to send data from the AVR to the module "pretty fast" in order to overrun it. After all, we are talking about something that can do "1 MBPS sustained data rate",

ii) it looks like the module has flow control implemented (see the pins that I mentioned above).

If this is not a problem re the communication between the AVR and the module, but between the AVR and another "endpoint" then in general there is no way to stop immediately since data can be moving through the net towards the remote end while it just has transmitted the "STOP". The only chance you have is to implement a stop-and-wait protocol (send one "thing", wait for an answer, send next thing, wait for an answer...).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I can change *OPEN* to whatever. I have it sending three percent symbols instead. So I can see that its on its way. The problem being that as soon as the first one is received, i may still be sending other data while the connection is already open.

The send and wait for, send and wait for, send and wait for, would be nice. Really easy if I'm writing a program to talk to the device. But I also want the device to be communicated to over any web browser, where I dont have power over something like "send everything you need, but then send a @@@@@ string to inform all data has been sent". Then again maybe I can, my HTML is horrendously basic.

The quoted speeds are actually hard to attain. Not that it matters, I'm not even approaching them. Sending information over 9600 baud uart is sometimes lost, sometimes I call to close the connection (a uart stream that comes after I send the website data), and all the website data isnt sent to the browser, rendering a page with random buttons with HTML code inside of them instead of nice labels like "On".
I read that the flow control pins can be used to tell me when the module is ready to receive data. Thats not really my problem. I just want to know when a new connection is made and not be sending commands to the module during this time, because then my website looks something like

close
*CLOSE*
exit
EXIT
(html)
(head)
...
(/head)
(/html)

(=<, )=>

You can see why thats annoying!
I can deal with the other problems by adding delay loops, I'm not worried about how fast the webpage is loaded. But i dont want random errors like this, and they can happen.

Anyways, I appreciate your input, and I can understand if you might be getting frustrated and confused with me at this point :)
I would love to hear more if you'd like to say anything. Im just saying don't feel pressured to keep writing back - Afterall, my original question was answered anyways!

Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

You can see why thats annoying!

Err no, perhaps I'm the only one, but your description doesn't make a lot of sense to me. Do you have an overall system diagram and description of the data flow and what's to be achieved. I cannot help thinking you are trying to fit the data into your preconceived solution rather than designing a solution to fit the dataflow. (but then again I don't know as I still cannot picture what's going on!)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I concur with Cliff. What does this device actually do? Where is the HTTP server situated? Etc...

Second: Your HTML might be rusty, but that has nothing to do with the problem at hand (by the little I have grasped so far). The HTTP protocol is a different thing.

When you speak of "a new connection is opened" do you by this mean that the WiFly opens a TCP connection due to a (HTTP) request "from some other end"? Does it do this automagically w/o your HTTP server being allowed to accept or deny this?

If this is the problem then there must be some way to tell the WiFly not to accept new connections since you can not cope with them. You could perhaps send the command to not accept new incoming requests before you send the reply to the one you are actually dealing with?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Annoying: if any data is sent before "(html)", then the HTML code is displayed on the browser, not the desired page (the first line has to be "(html)").

The WiFly is the server.

When I speak of "a new connection is opened", i do mean that the wifly opens a TCP connection due to an HTTP request from some other end. It does it automatically, I have no control over it. I cannot tell the wifly to not accept new connections.

Here is a scenario in which the data is incorrectly sent:

To close a connection, you have to send an "enter command mode" string by sending the "$$$" string. Once in command mode, you can close a connection. If in command mode and about to close the connection, another request comes in (say by hitting refresh, since the Wifly can only handle one client at a time), then command mode is exited automatically. Without knowing this, the uC keeps sending command data like "close" and "exit" (close the connection, exit command mode). Not being in command mode, these commands do nothing - it is now data sent over TCPIP. Subsequently, "close" and "exit" will be the first plain text displayed on your browser. Because the first thing the browser received was not (html), then all subsequent HTML data sent is not 'compiled' into the webpage, but rather displayed as text.

All ( = < and ) = >. Can't post otherwise

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The WiFly is the server.

The HTTP server? E.g. Is it the WiFly that adds the content type headers of the HTTP responses? (I'm reluctant to go through the circa 100 page document myself to verify if this is so or not.) And if so, how does it know what content type to set for individual responses? Not all HTTP responses contain HTML. What if you want to respond with an image?

Quote:
I cannot tell the wifly to not accept new connections.
Are you saying that the WiFly has one connection open - the one you are answering 'now', and it the n opens another one upon receiving another request, and that what you send from the AVR to the WiFly ends up in the wrong connection? If the module actually does open connections for you (i.e. your AVR) and has many of them open at the same time then there must also be some mechanism in the module so that you (again, the AVR) can tell it where some content that you send should end up. If the module supports several open connections but has no means for you to discern between them then it is crap and you should return it. I have a somewhat hard time believing this though - SparkFun is no small time player and generally has a good reputation.

Quote:

I cannot tell the wifly to not accept new connections.

Then you have two options left:
- Just drop the request on the floor.
- Queue it and respond to it when you're done with the one you're working on 'now'.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The Wifly is the server. It adds the content. How does it know? The AVR sends the content. How does the AVR know? I hard coded it. No images, not complications (yet).

It cant open two connections. But hitting refresh for example doesn't set up a new socket (on any of the browsers Ive experimented with, FF, IE, Chrome). So when you hit refresh, it just resends the request header and waits for data. I know I know: "just dont hit refresh". I want to build this as robustly as possible. There are also really annoying things to deal with like the automatic request for the website icon. This shows nothing to the browser user in terms of the browser making another connection. So during this time, if input to the website is made, the browser pops up the Cannot Connect page.
Because its one connection with possibly multiple header requests, I can't queue it, because I run into the same problem as before: i could be sending data to the wifly from the AVR when a new header shows up, resulting in incorrectly structured HTML code.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, new question! (Sometimes a walk with the dog opens ones mind.)

Could it be that the WiFly module is designed to serve a "static" content to anyone sending a request?
And that you are using it in such a mode?
And that you try to change that "static" content while the module is enabled to serve it?

If so, I can understand that things go awry. Take the server in the module down (disable the HTTP server) before you change the content, and then bring it up again, perhaps?

I'm still reluctant to go through a 100 page users guide. Am I getting close to understanding the situation?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hrm.... I can't say that I fully understand your question.

On a quick side note, perhaps you could help me quickly with a WDT problem. I had WDT enabled via fuse. In code: cli(), wdt_reset(), wdt_disable(), wdt_enable(WDTO_8S). I wanted to disable the WDT, so I unprogrammed the fuse, and left: wdt_reset(), wdt_disable(). I can see however, that for some reason the WDT is still enabled and my program is resetting in the millisecond range. How can I fix that?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Hrm.... I can't say that I fully understand your question.


Well, welcome to our reality.. :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Pages