Upgrading software from NDK 1.6 to 2.x

Discussion to talk about software related topics only.
rhyde
Posts: 2
Joined: Sat Oct 18, 2014 10:31 am

Upgrading software from NDK 1.6 to 2.x

Post by rhyde »

I'm experiencing problems with some old (5-10 years) software I wrote using v1.6 (or thereabouts).
In particular, critical sections don't seem to be working.
Using OS_CRIT objects with OSCritEnter and OSCritLeave works with the old NDK.
Compile and run with the 2.x NDK (using same MOD55415 board) and the critical sections don't seem to work.
The higher priority task grabs the critical section and never relinquishes it.
Thanks,
Randy Hyde
ttribelli
Posts: 5
Joined: Sun Jan 02, 2022 1:05 am

Re: Upgrading software from NDK 1.6 to 2.x

Post by ttribelli »

I converted

OS_CRIT i2cCS;
OSCritInit( &i2cCS );
OSCritEnter( &i2cCS, 0 );
OSCritLeave( &i2cCS );

to

OS_CRIT i2cCS;
i2cCS.Init();
i2cCS.Enter( WAIT_FOREVER );
i2cCS.Leave();

Still doesn't work. Using 2.9.5.

Both compile and run, they just fail differently. Only one thread runs in the old, neither runs in the new.

In the old code if I added a call to OSTimeDly() to the higher priority thread the lower priority thread would run as expected. However the critical section of the lower priority thread would be preempted as soon as the timer expired and the higher priority thread unblocked. OS_CRIT no longer seems to protect against unblocking.
ttribelli
Posts: 5
Joined: Sun Jan 02, 2022 1:05 am

Re: Upgrading software from NDK 1.6 to 2.x

Post by ttribelli »

The conversion of old code seems to be unnecessary. Implementation (ucos.h) calls class members.

inline BYTE OSCritInit( OS_CRIT *pCrit ) { return pCrit->Init(); }
inline BYTE OSCritEnter( OS_CRIT *pCrit, WORD timeout ) { return pCrit->Enter(timeout); }
inline BYTE OSCritLeave( OS_CRIT *pCrit ) { return pCrit->Leave(); }
User avatar
TomNB
Posts: 569
Joined: Tue May 10, 2016 8:22 am

Re: Upgrading software from NDK 1.6 to 2.x

Post by TomNB »

Hello Randy,

Wow, 1.6! thats about 10 years ago. I don't think I can summarize all that has changed since then. From your last post I can't tell if you have it working or not, but if not, have you looked at the example for a comparison: \nburn\examples\StandardStack\RTOS\OSCrit. The preferred method is an object now, but the older way should work too. By 2.x you mean 2.9.5, correct?
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Upgrading software from NDK 1.6 to 2.x

Post by pbreed »

What does your new current UserMain look like?

Try adding:
#include <taskmon.h>

Then near the begning of user main add:
EnableTaskMonitor();

And running the utility TaskScan.
Are you using OSLock anywhere?
ttribelli
Posts: 5
Joined: Sun Jan 02, 2022 1:05 am

Re: Upgrading software from NDK 1.6 to 2.x

Post by ttribelli »

Randy is about to get on a plane for vacation. So naturally this is when problems are found. :-)

I'm working with Randy and I'll fill in. Be warned, I am new to NetBurner and µC/OS. NDK 2.9.5 is my starting point. Randy and I both have MOD54415, his is revision 1.something I believe, mine 2.2.

The old style source code compiles and runs, ucos.h has a wrapper that converts the old calls into object member calls. I've modernized it anyways, same problems. An outline of the code is below. While the secondary thread is in its critical section I will see the main thread preempt and enter its critical section when the timer expires and main unblocks. Both threads in the critical section at the same time, the secondary thread blocked. Each thread is outputting triangle to a separate DAC and I can see the preemption on my oscilloscope. In the screen capture below yellow is the main thread, magenta the secondary.

The NetBurner example code is pretty similar, except we have infinite loops in both main and our secondary thread. One other difference that I see is the call:
OSCriticalSectionObj UserMainCriticalSection( osCritObj );
I'll look into this call.

No OSLock().

I haven't used TaskScan or TaskMon yet. I just relied on the oscilloscope.

Tony

Code: Select all

#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <multichanneli2c.h>

#define ever ;;

OS_CRIT i2cCS;

void DACout( int adrs ) {
    i2cCS.Enter( 0 );
    MultiChannel_I2CSendBuf();
    i2cCS.Leave();
}

void thread0x63( void *parm ) {
    for(ever) {
        DACout( 0x63 );
    }
}

void UserMain(void * pd)
{
    InitializeStack();
    OSChangePrio(MAIN_PRIO);
    EnableAutoUpdate();

    i2cCS.Init();

    OSTaskCreate(
        thread0x63,
        NULL,
        (void*)&thread0x63_stack[thread0x63_STK_SIZE],
        (void *)thread0x63_stack,
        MAIN_PRIO + 1);

    for(ever) {
        DACout( 0x62 );

        OSTimeDly( TICKS_PER_SECOND * 3 );
    }
}
OS_CRIT.png
OS_CRIT.png (19.46 KiB) Viewed 5584 times
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Upgrading software from NDK 1.6 to 2.x

Post by pbreed »

Please not that the rtos system is strict priority based.
Unless something causes it to block the highest priority task will always run.
So if two tasks are waiting for the OS_CRIT the high priority task will ALWAYS win.
The lower priority task may never run.

Not exactly sure what your showing on the scope?
The call
MultiChannel_I2CSendBuf(); does nto take an address or anything else not sure how your getting a saw tooth from that?
ttribelli
Posts: 5
Joined: Sun Jan 02, 2022 1:05 am

Re: Upgrading software from NDK 1.6 to 2.x

Post by ttribelli »

Yes I understand that an unblocked higher priority thread will immediately be scheduled and run, preempting any lower priority thread.

Perhaps the code outline was a little too brief, DACout's critical section is inside a for loop. Actually there are two for loops, one for the rising edge and one for the falling edge of the triangle waveform.

Ignore the oscilloscope screen capture, its actually something with debugging code in it. Its probably a bad idea to spend your time debugging the debugging code. :-)

Also ignore the OSTimeDly call in the main loop, that is debugging code too. It did not exist in the original 1.6 era code.

Let me try a second attempt at stating the problem. Under 2.9.5 the higher priority thread never blocks, never allowing the lower priority thread to be scheduled. This code used to work under 1.6, perhaps something behind the scenes used to occasionally block the higher priority thread (UserMain), or maybe the call to MultiChannel_I2CSendBuf() blocked? So we now seem to need to add some sort of explicit blocking in the main thread? I just want to check that I am not missing something? Something in configuration that enables that 1.6 era behavior?
sulliwk06
Posts: 118
Joined: Tue Sep 17, 2013 7:14 am

Re: Upgrading software from NDK 1.6 to 2.x

Post by sulliwk06 »

The explicit blocking should be whatever you are using to evenly space out your DACout calls in each thread. So that would either be an OSTimeDly or pending on some resource that is made available at specific intervals.
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Upgrading software from NDK 1.6 to 2.x

Post by pbreed »

Mod54415...
Your probably best served setting up a fixed interval to drive the DAC(s)

Create two tasks, and two semaphores....
Have each task block on the a differnt semaphore...

The set up a fixed interval sem trigger...

Use the function:
#include <pitr_sem.h>

int InitPitOSSem(int timer, OS_SEM *p_toSem, int pit_per_sec);
This will post to a semaphore at a fixed interval.....
This wakes one dac task, then have that task post to the other sem triggering the other task...

This is how I would set up fixed interval multiple DAC outputs...
Or just double the interval speed and ping/pong between the two dacs in the single output...
Post Reply