uCos task for polled I/O, reasonable speed expectations?
Posted: Fri Nov 24, 2023 1:03 pm
I have a "legacy" system (2017+) running on 5441x and NetBurner 2.8. It polls J2.10 for a trigger and sends a line from a CSV file out the serial port when the trigger is detected. Embedded webserver, ftp server, and SD card code are all straight from examples. This has worked for several years, but I went to speed it up and found that it was missing triggers. So I took the input polling out of my main task and put it in an RTOS task. That's where things get interesting. Depending on some choices, it looks like my new task never runs, MAIN never runs, or my new task runs but misses more triggers than before.
First, the system has been working with 200 mS cycles on a 50% or 75% duty cycle, so the trigger short phase has been at least 50 mS out of 200. Now I want to detect triggers at 3 mS down to 1 mS. Is that practical with 5441X, while still supporting network services?
Next, here is my new task. Big picture, it increments a counter every rising edge.
and this is the initialization in UserMain. In the infinite loop, UserMain checks Trig??Count and reacts appropriately.
As shown, that code prevents UserMain from running: if I click anything on the embedded web page, it errors with a "reset connection" error, and the system doesn't do anything on trigger. Strangely, LED0 and LED1 are ON steady and do not follow the inputs - does that mean that the Trigger task is not really running?
If I uncomment OSTimeDly(0), everything runs and the LEDs follow the inputs, but the system misses more triggers than it did at first. If I uncomment OSFlagPendAllNoWait(&flags, bit_mask) (with OSTimeDly(0) commented), the system acts like it did with both lines commented. Both calls are an attempt at some kind of RTOS yield. If I set the task priority at MAIN_PRIO + 1, the LEDs are off steady, telling me that the task never runs.
Obviously I'm missing something about uCos. So my questions are:
* how short of an input pulse should be detectable?
* is there a better way to detect short input pulses, in a system that is also doing network services?
* if not, how do I get my task the right number of timeslices?
First, the system has been working with 200 mS cycles on a 50% or 75% duty cycle, so the trigger short phase has been at least 50 mS out of 200. Now I want to detect triggers at 3 mS down to 1 mS. Is that practical with 5441X, while still supporting network services?
Next, here is my new task. Big picture, it increments a counter every rising edge.
Code: Select all
DWORD TriggerWatchTaskStack[USER_TASK_STK_SIZE];
uint32_t Trig10Count = 0;
uint32_t Trig29Count = 0;
void TriggerWatchTask(void* pUnused)
{
int lastTrig1 = -1;
int lastTrig2 = -1;
/*
DWORD bit_mask = 0;
OS_FLAGS flags;
flags.current_flags = 0;
flags.pWaitinglist = NULL;
*/
while (TRUE)
{
//OSTimeDly(0); // yield, 0 ticks: misses gaps at 5/sec. -1: the task does not run.
//OSFlagPendAllNoWait(&flags, bit_mask); // no yield, MAIN does not run,
int thisTrig1 = J1[10];
J2[LedIndexes[0]] = thisTrig1;
if (thisTrig1 != lastTrig1)
{
if (lastTrig1 >= 0)
{ // TRIGGER
bool risingEdge = (thisTrig1 == 0) ? true : false;
if (InvertTrigger)
{
risingEdge = ! risingEdge;
}
if (risingEdge)
{
Trig10Count += 1;
}
}
lastTrig1 = thisTrig1;
}
// Secondary trigger: J2.29(UART0.7 RTS)
//triggering seems to work with or without this setting: J2[29].function(0);
int thisTrig2 = J2[29];
J2[LedIndexes[1]] = thisTrig2;
if (thisTrig2 != lastTrig2)
{
if (WebCfgRtsTrigger())
{
if (lastTrig2 >= 0)
{ // TRIGGER
bool risingEdge = (thisTrig2 == 0) ? true : false;
if (risingEdge)
{
Trig29Count += 1;
}
}
lastTrig2 = thisTrig2;
}
}
}
}
Code: Select all
OSTaskCreate( TriggerWatchTask,
(void *)NULL,
&TriggerWatchTaskStack[USER_TASK_STK_SIZE],
TriggerWatchTaskStack,
MAIN_PRIO - 1); // also tried ETHER_SEND_PRIO - 1
If I uncomment OSTimeDly(0), everything runs and the LEDs follow the inputs, but the system misses more triggers than it did at first. If I uncomment OSFlagPendAllNoWait(&flags, bit_mask) (with OSTimeDly(0) commented), the system acts like it did with both lines commented. Both calls are an attempt at some kind of RTOS yield. If I set the task priority at MAIN_PRIO + 1, the LEDs are off steady, telling me that the task never runs.
Obviously I'm missing something about uCos. So my questions are:
* how short of an input pulse should be detectable?
* is there a better way to detect short input pulses, in a system that is also doing network services?
* if not, how do I get my task the right number of timeslices?