Multiple calls of OSSemInit()

Discussion to talk about software related topics only.
DBrunermer
Posts: 67
Joined: Thu Apr 21, 2011 7:06 am
Location: Pittsburgh, PA

Re: Multiple calls of OSSemInit()

Post by DBrunermer »

The docs and manuals don't seem to talk much about priority directly, so I guess I can only assume that they aren't a player here. I mean, the source code in ucos.c, which I will freely admit I do not understand at all, makes a bunch of references to something that looks like priority. These two lines in particular:

Code: Select all

      y = OSTCBCur->OSTCBPrio >> 3;
      x = OSTCBCur->OSTCBPrio & 0x07;
Like I say, I don't know what they mean, so I was just suspicious.

rnixon, I'm not doing that, and I'm not actually reinitializing the sem. I just wondered if I could. And I do initialize it way early, well before I actually create any tasks or hook up the interrupt vectors. I am concerned about a spurious 'Post', though, and that's actually what I'd like to kill. It might be a misplaced concern on my part. But I'll make sure that the Init is as high as it can practically be.

Thanks all, Dan B.
DBrunermer
Posts: 67
Joined: Thu Apr 21, 2011 7:06 am
Location: Pittsburgh, PA

Re: Multiple calls of OSSemInit()

Post by DBrunermer »

So I'm really not making any headway here. I worked on the suggestions last night, tried it this morning, and it's not getting better. Let me show some code; MOD5272 platform. Here are what I think are the relevant snippets from the various things:

Code: Select all

OS_SEM g_datasem; // These are in the declarations of the global space
OS_SEM g_passsem;

// These next lines are a snippets of UserMain()
	OSChangePrio(MAIN_PRIO);	// Set this task priority
    // Insure semaphores are initialized early
	if (OSSemInit( &g_passsem, 0) != OS_NO_ERR )
		iprintf("Pass Semaphore Init Failed");
	if (OSSemInit( &g_datasem, 0) != OS_NO_ERR )
		iprintf("Data Semaphore Init Failed");

// Then later
	// Create TCP Server task
	OSTaskCreate( TcpServerTask,
				 (void  *)TCP_LISTEN_PORT,
                 &TcpServerTaskStack[USER_TASK_STK_SIZE] ,
                 TcpServerTaskStack,
                 MAIN_PRIO - 1); 	// higher priority than UserMain

	// Create TCP Image receiver task
	OSTaskCreate( TcpImageRcvTask,
			(void*) TCP_IMAGE_PORT,
			&TcpImageTaskStack[USER_TASK_STK_SIZE],
			TcpImageTaskStack,
			MAIN_PRIO - 2); // Higher priority than TcpServerTask

	// Create Pass Data Manager task
	OSTaskCreate( PassRunTask,
			(void*) 0,
			&PassTaskStack[USER_TASK_STK_SIZE],
			PassTaskStack,
			MAIN_PRIO - 3); // Higher priority than TcpImageTask

	SetupDataDoneUnit();
	SetupFCDoneDummyUnit();

// The actual pass data management task that won't unPend
void PassRunTask( void * pd )
{
	//bool b_done = false;
	iprintf("In PassRunTask\r\n"); // This message comes thru the diagnostic port
	// This task will run the data feeding portion of the PHC. This is needed because of the new data overrun problem.
	while(1)
	{
		OSSemPend( &g_passsem, 0 ); // Wait for cue to start the pass cycle.
		putchar( '.' ); // This never comes down the port
		*cpldcfg = SET_LAT | SET_POL | SET_BLK;
		*cpldcfg = SET_POL | SET_BLK;
		// Now we need to do the work of shifting in the data
		// Send in the data
		for( int i=0; i<SHIFT_COUNT; i++ ) // You ALWAYS need 32 writes, regardless of bus size or module count.
		{
			*data01 = *g_pCurReadIdx;
			g_pCurReadIdx++;
			OSSemPend( &g_datasem, 0);
		}
		g_LinesRendered++;
		putchar( ',' ); // This never comes down the diagnostic port
		if( g_LinesRendered == g_LinesToRender )
		{
			vector_base.table[70] = (long)&FirePassNLL;
			vector_base.table[90] = (long)&FireDoneDummy;
			putchar( 'd' );
		}
	}
	iprintf("Dumped\r\n");
	return;
}

// The interrupt
INTERRUPT( FireDone, 0x2700 )
{
	// One Fire Cycle just completed
	OSSemPost( &g_passsem );
	putchar('|');    // This message DOES come down the diagnostic port, in a constant unending stream
	sim.icr4 = 0x08000000; // Clear the Interrupt Pending
	sim.icr4 = 0x09000000; // Re-enable the interrupt
	return;
}
 // The other interrupt
INTERRUPT( DataACK, 0x2700 )
{
	// Release the pending write (I think)
	OSSemPost( &g_datasem );
//	putchar('.');
	sim.icr1 = 0x00800000; // Clear IRQ 3, prevent from posting again
	sim.icr1 = 0x00F00000; // Re-enabled /INT3 with priority #5

}

What's basically happening is that a strobe fires a physical High voltage signal, and when it decays below a certain level, the data shifting has to continue. That decay is captured by the FireDone interrupt, and like I say, it's firing. The DataACK fires as well, though it doesn't in this context because the pass manager never kicks in. When I do singular testing of the data shifter, it's fine.

Any clues? Thanks, Dan B.
User avatar
pbreed
Posts: 1091
Joined: Thu Apr 24, 2008 3:58 pm

Re: Multiple calls of OSSemInit()

Post by pbreed »

Several problems here:

1)First you can not do io like putchar from an interrupt...
Hunt down the programmers manual section on interrupts it tells what functions are and are not ok...

2)The external interrupts have to be at their native priority... IE IRQ3 has to be 3.
The register interface looks like you can set it.. but if you the freescale docs say not to.


I'd start by adding the following..
(I do this at some point for every interrupt I ever write... it shows if the interrupt fires, and also shows if it fires too much...
IE you get a 5 interrupts per second on a 1 pulse per second interrupt with noisy edges etc..)

volatile DWORD my_isr_count1;
volatile DWORD my_isr_count2;


Then in each of the interrupts I'd put

First ISR...
isr_count1++;

Second ISR....
isr_count2++;
etc...


Then is a different task Id do

iprintf("%ld ,%ld\r\n",isr_count1,isr_count2);

Make sure the interrupt is firing as you expect...

You did not include the code to setup the interrupts....
My guess is the interrupts aren't firing.... like you expect..
User avatar
pbreed
Posts: 1091
Joined: Thu Apr 24, 2008 3:58 pm

Re: Multiple calls of OSSemInit()

Post by pbreed »

What platform /CPU is this for...
I'll point you to a working external interrupt example for that platform...
DBrunermer
Posts: 67
Joined: Thu Apr 21, 2011 7:06 am
Location: Pittsburgh, PA

Re: Multiple calls of OSSemInit()

Post by DBrunermer »

pbreed - Here are the setups. The interrupts are firing. I see the '|' character streaming from the serial port, it's just that the task waiting on that post never releases. And the whole reason I chose 'putchar' was because it was one of the few functions not on the forbidden list in the manual (P140 of mine). But anyway, it's only in there for diagnosing this problem. If I take it out, it doesn't change the nature of what I'm seeing.

Let me back up a little bit. This high voltage signal is triggered by a time based interrupt at about 2.5kHz(T=400us). The signal lasts about 10us. When it gets below 3V, the next line is advanced. The firing frequency is driven by a time interrupt (TMR1), and that interrupt fires regardless of what else is happening. Is the OS just too slow maybe?

Code: Select all

// Data Done is the same as the old INT3 for external image sync (no encoder)
void SetupDataDoneUnit( void )
{
	sim.pitr &= INT_PITR_VAL; // INT_PITR_VAL = 0xDFFFFFBF
	sim.icr1 = 0x00800000; // Clear the /INT3 PI flag, disable interrupt generation
	vector_base.table[67] = (long)&DataACK;
	sim.icr1 = 0x00F00000; // Re-enabled /INT3 with priority #7
	return;
}

void SetupFCDoneUnit( void )
{
	sim.pitr &= INT_PITR_VAL; // INT_PITR_VAL = 0xDFFFFFBF
	sim.icr4  = 0x08000000;
	vector_base.table[90] = (long)&FireDone;
	sim.icr4  = 0x0D000000;
	return;
}

When you say interrupts have to be at their native priority, do you mean the IPL bits in the ICRx register need to be set to the IRQ number?

Thanks again, Dan B.
User avatar
pbreed
Posts: 1091
Joined: Thu Apr 24, 2008 3:58 pm

Re: Multiple calls of OSSemInit()

Post by pbreed »

putchar is standard I/O just like all the other I/O.

Disregard my ISR level questions if you are not using external IRQ pins....

Calling ANY I/O that calls RTOS functions from inside an ISR can break things... so remove the putchar and
add the interrupt counters and see what happens...

What platform is this?
rnixon
Posts: 833
Joined: Thu Apr 24, 2008 3:59 pm

Re: Multiple calls of OSSemInit()

Post by rnixon »

You mentioned that you did not understand task priorities, so just in case that has something to do with it keep this in mind. A real-time OS is different than something like windows or linux. In an rtos the highest priority task ready to run will run. That's a key statement, I had to screw it up before it sank in. It means that if you write a high priority task that never blocks, none of your other tasks will ever run. The rtos docs describe which tasks block and go through this a bit.

Priorities range from 4 to 63. 63 is the lowest priority and is the rtos idle task that runs if everything else is blocking.
The default priority for UserMain is 50.
I'd have to check, but the system uses 45 and below I think. So you want to use between 46 and 62.

There is a #define MAIN_PRIO that I use when making my own tasks. If I want a higher priority I create other #defines such as #define TASK1_PRIO (MAIN_PRIO - 1), etc.

So if UserMain is at 50 and does this:

UserMain()
while (1)
{
iprintf("I never block\r\n");
}

and you have created a task pending on a semaphore at priority 51

MyTask1()
{
OSSemPend()
}

Task1 will never execute.

If you add a blocking function to UserMain like this

UserMain()
while (1)
{
iprintf("Now I do block\r\n");
OSTimeDly( TICKS_PER_SECOND);
}

then Task1 will execute because priority 50 is blocking and priority 51 can run.

The right way to do it would be to make MyTask1 priority 49, then it would block on OSSemPend() and preempt UserMain when the semaphore was posted even in the first case.
DBrunermer
Posts: 67
Joined: Thu Apr 21, 2011 7:06 am
Location: Pittsburgh, PA

Re: Multiple calls of OSSemInit()

Post by DBrunermer »

It's a MOD5272. Not that it matters, though, as the high-voltage section just committed suicide. And the other question - they are external IRQs, INT3(DataDone) and INT5(FireDone).
Thanks - Dan B.
User avatar
Chris Ruff
Posts: 222
Joined: Thu Apr 24, 2008 4:09 pm
Location: topsail island, nc
Contact:

Re: Multiple calls of OSSemInit()

Post by Chris Ruff »

Ah yes, The sweet smell of outgassing capacitors...

Only one thing smells worse than that: letting the smoke out of a selenium rectifier (you have to have gray hair to remember that)

We here are sorry about your high voltage section..

Chris
Real Programmers don't comment their code. If it was hard to write, it should be hard to understand
rhopf1
Posts: 37
Joined: Mon May 12, 2008 5:57 am

Re: Multiple calls of OSSemInit()

Post by rhopf1 »

If these are simple "done" signals they probably don't belong on interrupts, just poll them in a task loop where you can still use OS operations. Feedback to user interfaces or over-the-wire responses seldom need <50msec processing.

Interrupts can be tricky and usually reserved to something that absolutely has to be altered in <10usec or 100usec or so. Feedback from an interrupt can also be done by simple flags vs semaphores, depends on complexity and how many tasks need access/notify or blocking.
Post Reply