Jump to content

ThreadX RTOS


Mad River

Recommended Posts

Hi,

I am currenty working on a project which uses Synergy S3 as uController and ThreadX as RTOS,

As ThreadX is not presented in the supported RTOS list, I will have to create a "ugfx/src/gos/gos_threadx.c" and "ugfx/src/gos/gos_threadx.h".

Is there a guide on how to do it?

If not, which tips can you give me to help me do it?

 

Thank you!

Link to comment
Share on other sites

Going through your files...

  • If your operating system has no memory allocation routine or memory free routine you can do what the Raw32 port does... in the bottom of your gos_threadx.h file include the following code...
    #define GOS_NEED_X_HEAP TRUE
    #include "gos_x_heap.h"

    What this does is include a uGFX provided gfxAlloc(), gfxRealloc() and gfxFree() routine. Make sure you also define a GFX_OS_HEAP_SIZE in your gfxconf.h to indicate what heap size you want.

  • gfxYield() is releases the remaining time slice to another thread. All multi-threaded operating systems will have one.

  • With regard to gfxThreadMe(), gfxThreadWait() - these again are multi-threading functions. Whilst uGFX does not use them, they are officially part of the uGFX API and should be implemented on any complete implementation. It looks like you are using an old version of the library as the current FreeRTOS implementation does provide these functions. Try downloading the current version from the repository at http://git.ugfx.io

  • For semaphores - it is VERY important that you implement the limit. Lots of stuff won't work properly without it. Look through the other operating systems to see how they handle it if the operating system doesn't provide that feature.

  • For gfxSemWaitI() - if your operating system doesn't provide a suitable routine just define it as equivalent to gfxSemWait() with an immediate timeout. Just don't try calling it from an interrupt context. This is largely used by various drivers to signal back to uGFX when an event happens.

  • For gfxSemSignal() - the complexity is all about avoiding windows of opportunity that can cause the semaphore to not work properly. Getting semaphores to work correctly can be very complex. Look at the discussion in the forum on the recent updates to FreeRTOS gos port for exactly that reason. (I think you are working from the broken version).

I hope that helps.

Link to comment
Share on other sites

2 hours ago, Mad River said:

I am using version 2.7, which I downloaded from the uGFX official site. isn't it the lastest version?

 

The 2.7 version is the stable release. To have the latest version of µGFX you should use the git repository. You can find more information about this on this wiki page.

Link to comment
Share on other sites

Hi @inmarket,

I started the port again, from scratch.

Below I listed the remain question.

I also attached the new files.

 

(1)

Quote

gfxYield() is releases the remaining time slice to another thread. All multi-threaded operating systems will have one.

I have tx_thread_relinquish(VOID), which does:

This service relinquishes processor control to other ready-to-run threads at the same or higher priority.

 

Should it do what is required? (1)

 

(2)

About gfxSystemLock() and gfxSystemUnlock(), I have tx_interrupt_control(UINT new_posture), which does:

This service enables or disables interrupts as specified by the input parameter new_posture.

tx_interrupt_control(TX_INT_DISABLE);

/* Perform critical operations that need interrupts locked-out.... */

/* Restore previous interrupt lockout posture. */

tx_interrupt_control(TX_INT_ENABLE);

 

Should it do what is required? (2)

 

(3)

About gfxThreadMe(), I have tx_thread_identify(VOID), which does:

This service returns a pointer to the currently executing thread. If no thread is executing, this service returns a null pointer.

 

Should it do what is required? (3)

 

(4)

void _gosDeinit(void)
{
    #if !GFX_OS_NO_INIT
        vTaskDelete(0); // TODO! Why 0 is passed as parameter? Shouldn't it be the task handle?
    #endif
}

Why 0 is passed as parameter? Shouldn't it be the task handle? (4)

 

(5)

// TODO! ThreadX resolution delay is 1ms, is it a problem?
void gfxSleepMicroseconds(delaytime_t ms)
{
    // delay milli seconds - microsecond resolution delay is not supported in FreeRTOS
    tx_thread_sleep(gfxMillisecondsToTicks(ms/1000)); // ALTERED! vTaskDelay(gfxMillisecondsToTicks(ms/1000));
    // vUsDelay(ms%1000);
}

 

ThreadX resolution delay is 1ms, is it a problem? (5)

 

(6)

void gfxMutexInit(gfxMutex *pmutex)
{
    // TODO! Should I use TX_INHERIT or TX_NO_INHERIT?
    tx_mutex_create(pmutex. "Mutex", TX_INHERIT);

}

 

I have a addition parameter, which specifies:

Specifies whether or not this mutex supports priority inheritance. If this value is TX_INHERIT, then priority inheritance is supported. However, if TX_NO_INHERIT is specified, priority inheritance is not supported by this mutex.

 

Should I use TX_INHERIT or TX_NO_INHERIT? (6)

 

(7)

Quote

For semaphores - it is VERY important that you implement the limit. Lots of stuff won't work properly without it. Look through the other operating systems to see how they handle it if the operating system doesn't provide that feature.

I have tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling), which does:

This service puts an instance into the specified counting semaphore, which in reality increments the counting semaphore by one. If the counting semaphore’s current value is greater than or equal to the specified ceiling, the instance will not be put and a TX_CEILING_EXCEEDED error will be returned.

 

Should it do what is required? (7)

 

(8)

Quote

For gfxSemWaitI() - if your operating system doesn't provide a suitable routine just define it as equivalent to gfxSemWait() with an immediate timeout. Just don't try calling it from an interrupt context. This is largely used by various drivers to signal back to uGFX when an event happens.

 

The documentation from ThreadX says that the tx_semaphore_get() can be called from a ISR.

Allowed From

Initialization, threads, timers, and ISRs

 

So, my gfxSemWaitI(gfxSem* psem) is (like you suggested) equal to gfxSemWait(gfxSem* psem, delaytime_t ms) but with a immediate timeout.

 

(9)

The gfxSemSignal(gfxSem* psem) and gfxSemSignalI(gfxSem* psem) follows the same logic as (8).

 

(10)

gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param)
{
    gfxThreadHandle task;

    (void) stackarea;

// uGFX expresses stack size in bytes - TheadX also express it in bytes
// ALTERED!
//    // uGFX expresses stack size in bytes - FreeRTOS in "Stack Words"
//    stacksz /= sizeof(StackType_t);

  if (stacksz < TX_MINIMUM_STACK)
      stacksz = TX_MINIMUM_STACK;
    
// ALTERED!
//    if (stacksz < configMINIMAL_STACK_SIZE)
//        stacksz = configMINIMAL_STACK_SIZE;

  // TODO!  ThreadX can't pass a pointer as argument to the task function.
  //        We can only pass a uint32_t.
  //        Is it a problem?
  if(tx_thread_create(&task, "uGFX_TASK", fn, 0, stackarea, stacksz, prio, 0, 1, 1) != SSP_SUCCESS)
      return 0;

//    task = 0;
//    if (xTaskCreate(fn, "uGFX_TASK", stacksz, param, prio, &task) != pdPASS)
//        return 0;

    return task;
}

ThreadX can't pass a pointer as argument to the task function.
We can only pass a uint32_t.
Is it a problem? (10)

 

gos_threadx.c

gos_threadx.h

Link to comment
Share on other sites

1, 2, 3 & 7: yes.

4. The 0 is a special flag to FreeRTOS to shut down all threads. _gosDeInit is unlikely to ever be called in an embedded environment so it can quite safely usuallyvne left as an empty function.

5. Microsecond delays are seldom provided by os's and are not used by uGFX itself however a driver might try to use it. Rounding it to milliseconds is what most gos implementations do.

6. I have no idea. Take a guess or read the doco to understand its significance in threadx.

8 & 9. Great.

10. No problem as pointers and uint32_t are (usually) the same size. The only time it might be a problem is if you are on a 64bit pointer cpu however i suspect threadx doesn't support that. Just typecast the param pointer to a uint32_t. 

 

Link to comment
Share on other sites

Regarding 6: That flag controls the priority inheritance behavior of the mutex. The problem you have with mutex on operating systems with thread priorities is that when a lower priority thread has a mutex and a higher priority thread is waiting on that mutex the higher priority thread can't do anything for an awful lot of time because the lower priority thread is blocking the mutex. Because the lower priority thread gets less CPU time it also requires more time to do the job and release the mutex. This results in the fact that a lower priority thread can block a higher priority thread which is a huge problem. That problem is called priority inheritance. To prevent that problem most operating systems provide a mutex that has priority inheritance support. What that does is temporarily increasing the lower priority thread's priority to the same priority level as the level of the higher priority thread that is waiting on the mutex. This way the lower priority thread gets more CPU and is thus able to release the mutex a lot earlier and no longer blocks the higher priority thread that long. It's really a basic operating system problem and a basic feature: https://en.wikipedia.org/wiki/Priority_inversion

In your case I'd simply use TX_INHERIT to enable the feature.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...