Noob question about creating threads

Discussion to talk about software related topics only.
ScottM
Posts: 32
Joined: Mon Feb 01, 2010 10:00 am

Re: Noob question about creating threads

Post by ScottM »

MasterFrmMO88 wrote: My question is can I set this up so it runs independent of the TCP function? I'd like the TCP function and the GPIO functions to be able to run simultaneously so the only delay created in the TCP function by the GPIO functions is caused simply by resource use.
Yes, your main application look just reads characters off the TCP stream over and over. The timer interrupt code runs independently, whenever the timer goes off. It looks like threading. Under the covers, what's happening is, whenever the timer goes off, the board stops whatever it's doing (which will most often be, "waiting for a TCP message"), executes your interrupt code, and then seamlessly returns to what it was doing before. Assuming you don't spend much time in the interrupt handler, and in your case you won't, commands will appear to be processed the instant they arrive, and the pins go off as if by magic.

You can also do it with threads. That avoids messing with an interrupt handler, but there's slightly more fuss dealing with getting timing to be accurate.
MasterFrmMO88
Posts: 26
Joined: Wed Oct 19, 2011 8:40 pm

Re: Noob question about creating threads

Post by MasterFrmMO88 »

I've been playing around with the DMA example for a few minutes that's outlined in the documentation: http://www.netburner.com/downloads/mod5 ... -timer.pdf

I've got the interval and code I want to execute in the example working great but when I go to put the code in my TCP program, it wont run the interrupt. I put a small print line so it will print to the MTTTY terminal each time it runs the interrupt and I've tried registering the timer in the main and in the TCP function but I get nothing. Am I just making a dumb mistake or what?

Here's the code in the TCP.cpp file I made:

Code: Select all

extern "C"
{
	void SetIntc( long func, int vector, int level, int prio );
}

INTERRUPT( func_isr, 0x2600 )
{
sim.timer[0].ter |= 0x02; // Clear the DTIM0 reference event flag
iprintf("Check Time");
CheckTime();// Increment interrupt counter
}

int    DestPort;
IPADDR DestIp;
#define TCP_LISTEN_PORT 1988
#define RX_BUFSIZE (4096)
char myip[80];
char RXBuffer[RX_BUFSIZE];

/*-------------------------------------------------------------------
 Convert IP address to a string
 -------------------------------------------------------------------*/
void IPtoString(IPADDR  ia, char* s)
{
	PBYTE ipb= (PBYTE)&ia;
	siprintf(s, "%d.%d.%d.%d",(int)ipb[0],(int)ipb[1],(int)ipb[2],(int)ipb[3]);
}
DWORD TcpServerTaskStack[USER_TASK_STK_SIZE];
/*-------------------------------------------------------------------
 Sends a message to the specified host.
 ------------------------------------------------------------------*/
void TcpServerTask(void * pd)
{
	int matchtest[32];

	sim.timer[0].tmr = 0x001A; // 0000 0000 0001 1010
	sim.timer[0].txmr = 0x00; // 0000 0000
	sim.timer[0].ter |= 0x02; // 0000 0010
	sim.timer[0].trr = 737270;
	sim.timer[0].tcn = 1; // Clear counter
	SetIntc( ( long ) &func_isr, 19, 1, 1 );

	IPtoString(EthernetIP, myip);
	//sprintf(myip, "%lu", EthernetIP);
	//Begins requesting connection here and continues indefinitely.
	while (1)
    	{
		//The next two commands set the Server's IP and Port Number
		DestPort = 43001;
		DestIp = AsciiToIp("192.168.100.2");
		//Updates MTTTY window. For Debugging purposes only. This applies
		//to all iprintf commands.
    	iprintf( "Connecting to: " );
    	ShowIP( DestIp );
    	iprintf( " : %d\r\n", DestPort );
    	/*This is the connect call. It will timeout after 1 second and proceed with the code.
    	The purpose of this timeout is to repeat the previous code for the MTTTY window,
    	this way the module is constantly telling the MTTTY it's trying to connect so, in debugging
    	it won't appear as if the module is frozen or trapped.
    	*/

    	int fdnet = connect( DestIp, 0, DestPort, TICKS_PER_SECOND * 1);
    	sim.timer[0].tmr |= 0x0001; // Enable the DMA timer

    	while (fdnet > 0)
		{
Ridgeglider
Posts: 513
Joined: Sat Apr 26, 2008 7:14 am

Re: Noob question about creating threads

Post by Ridgeglider »

There is no way the ISR can support a printf statement!! However, there are other ways you can make the ISR provide you with a signal. One way might be to toggle a pin, or even an LED although frequently blinking a single LED is too fast to see and so you're likely to need a scope on the pin. Another trick is to increment an 8 bit count and write it to

void putleds( unsigned char c );

That way you see all 8 LEDs flash a rolling over binary count as an indicator of activity.

If you want to provide a more substantive indicator, consider having the ISR post a semaphore to a task that pends on that same semaphore. The task can increment a count variable and then, at some appropriate period that's not too fast, say every 100th count, print the count value to the screen. That way if the DMA is happening at 10msec you'll print the count 1x per second. The same task could print out the variable whose bits correlate to the outputs that are active. Just be sure that you read that variable and don't try to write it in 2 different tasks. This should work as long as the variable is an int or other 32 bit (atomic) type that is read or written in one chunk.
MasterFrmMO88
Posts: 26
Joined: Wed Oct 19, 2011 8:40 pm

Re: Noob question about creating threads

Post by MasterFrmMO88 »

Ridgeglider wrote:There is no way the ISR can support a printf statement!! However, there are other ways you can make the ISR provide you with a signal. One way might be to toggle a pin, or even an LED although frequently blinking a single LED is too fast to see and so you're likely to need a scope on the pin. Another trick is to increment an 8 bit count and write it to

void putleds( unsigned char c );

That way you see all 8 LEDs flash a rolling over binary count as an indicator of activity.

If you want to provide a more substantive indicator, consider having the ISR post a semaphore to a task that pends on that same semaphore. The task can increment a count variable and then, at some appropriate period that's not too fast, say every 100th count, print the count value to the screen. That way if the DMA is happening at 10msec you'll print the count 1x per second. The same task could print out the variable whose bits correlate to the outputs that are active. Just be sure that you read that variable and don't try to write it in 2 different tasks. This should work as long as the variable is an int or other 32 bit (atomic) type that is read or written in one chunk.
I'm not entirely sure how you mean. I was under the impression that it was a simple time that would interrupt the current process to run a separate block of code. Everything I am doing with it now is the exact same stuff it was successfully doing in the example. In the example I had it running the same interval, it would print something to my MTTTY window (using a printf statement) at each tick, then it would run the code attached to the CheckTime(); function. The only difference being, instead of switching pins, it would print to the MTTTY window. It was able to do all this in the example DMA program. The problem doesnt seem to be in the code itself, just the implementation of the DMA timer. I mean, I could be wrong but everything problem solving has taught me is that if code A works in program A, but the same code A doesnt work in program B then it would be an external problem, outside of code A, in program B.

But if this is the case, and I can't execute the code I want with a DMA timer then I'll need help on other suggestions as to how to do this.
User avatar
tod
Posts: 587
Joined: Sat Apr 26, 2008 8:27 am
Location: Southern California
Contact:

Re: Noob question about creating threads

Post by tod »

I think you can execute the code you want, the way you want BUT not inside the Interrupt Service Routine. It shouldn't affect you too much you just have to use OSSemPost/OSSemPend to trigger your code to run outside the ISR.

You probably want to download and read the Interrupt Programming Application Note. This was written for the 5270 but I'm pretty sure it applies to other processors as well.

You will notice this in the comments in the example
/* WARNING WARNING WARNING
Only a very limited set of RTOS functions can be called from
within an interrupt service routine.
Basically, only OS POST functions and LED functions should be used
No I/O (read, write or printf may be called), since they can block. */
MasterFrmMO88
Posts: 26
Joined: Wed Oct 19, 2011 8:40 pm

Re: Noob question about creating threads

Post by MasterFrmMO88 »

Well, I would like to take this moment to apologize to everyone for the frustration. I got it all working now. In my IDE, my Debug Configuration wasn't the same as my Release Configuration. The program would build fine, but I would flash an older version due to the configuration compiling and saving the APP to the wrong folder and me not double checking the dates on the files. :roll:
Post Reply