Portability issue of RTOSDemo example's TaskNotify.c and TaskNotifyArray.c for 16bit MCU

Hello,

I’m trying to use RTOSDemo example’s TaskNotify.c and TaskNotifyArray.c with 16bit MCU (Renesas RL78). But several compilers show the following warnings. The reason is that the type of the variable to be right shifted is size_t and the width of size_t is 16bits in my case, but the code attempts to right shift the read value 16bits. Therefore the following prvRand() always returns zero (or unexpected value) but I think this isn’t the designed behavior of the function.

At first, my question is: Is my understanding right? (i.e. this isn’t the designed behavior)

(I modified the code to use uint32_t instead of size_t tentatively. But such modification causes another warning at another place when GNURL78 is used. Probably this another warning will be my next question in my later post.)

GNURL78 (4.9.2.202002):

warning: right shift count >= width of type

ICCRL78 (V4.20.1):

Warning[Pe063]: shift count is too large

CC-RL (V1.10):

W0520063: Shift count is too large

TaskNotify.c

/* Used by the pseudo random number generating function. */
static size_t uxNextRand = 0;
...
void vStartTaskNotifyTask( void  )
{
...
    /* Pseudo seed the random number generator. */
    uxNextRand = ( size_t ) prvRand;
}
...
static UBaseType_t prvRand( void )
{
const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;

    /* Utility function to generate a pseudo random number. */
    uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
    return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );    <---    HERE (Line 730)
}

TaskNotifyArray.c

/* Used by the pseudo random number generating function. */
static size_t uxNextRand = 0;
...
void vStartTaskNotifyArrayTask( void  )
{
...
    /* Pseudo seed the random number generator. */
    uxNextRand = ( size_t ) prvRand;
}
...
static UBaseType_t prvRand( void )
{
const size_t uxMultiplier = ( size_t ) 0x015a4e35, uxIncrement = ( size_t ) 1;

    /* Utility function to generate a pseudo random number. */
    uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
    return( ( uxNextRand >> 16 ) & ( ( size_t ) 0x7fff ) );    <---    HERE (Line 1236)
}

Best regards,
NoMaY

First, I wouldn’t count of demos being written for maximum portability, and that code appears to assume that size_t is 32 bits (might have been better to have used uint32_t for it)

That code is not part of the kernel - just a demo and test that was written since we last worked on anything less than 32-bits. Sometimes size_t is used in place of unit32_t precisely because it scales with the natural word width of the target hardware. That works well between 32 and 64-bit - but evidently in this case not for 16-bit.

Probably the simplest solution here is to change the data type to uin32_t? Would that work for you?

See [Feature Request] Enable use of the TaskNotificationArray.c test file on 16-bit devices · Issue #550 · FreeRTOS/FreeRTOS · GitHub

Hello richard-damon and Richard Barry,

Thank you for replies. My latest code is the following. It works. But there is another issue. In case of GNURL78, if there are no additional cast ‘( uintptr_t )’, compiler reports the following another warning.

...omit.../TaskNotify.c: In function 'vStartTaskNotifyTask':
...omit.../TaskNotify.c:125:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
  uxNextRand = ( uint32_t ) /*( uintptr_t )*/ prvRand;
               ^

To be honest, a few hours ago, by googling, I know this solution using the cast ‘( uintptr_t )’ to remove the above warning. (This warning seems to be famous in 64bit platform but I didn’t know it.)

www.google.com/search?q=pointer-to-int-cast

wiki.sei.cmu.edu/confluence/display/c/INT36-C.+Converting+a+pointer+to+integer+or+integer+to+pointer

TaskNotify.c

/* Used by the pseudo random number generating function. */
static uint32_t uxNextRand = 0;
...
void vStartTaskNotifyTask( void  )
{
...
    /* Pseudo seed the random number generator. */
    uxNextRand = ( uint32_t ) ( uintptr_t ) prvRand;
}
...
static UBaseType_t prvRand( void )
{
const uint32_t uxMultiplier = ( uint32_t ) 0x015a4e35, uxIncrement = ( uint32_t ) 1;

    /* Utility function to generate a pseudo random number. */
    uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
    return( ( UBaseType_t ) ( ( uxNextRand >> 16 ) & ( ( uint32_t ) 0x7fff ) ) );
}

TaskNotifyArray.c

/* Used by the pseudo random number generating function. */
static uint32_t uxNextRand = 0;
...
void vStartTaskNotifyArrayTask( void  )
{
...
    /* Pseudo seed the random number generator. */
    uxNextRand = ( uint32_t ) ( uintptr_t ) prvRand;
}
...
static UBaseType_t prvRand( void )
{
const uint32_t uxMultiplier = ( uint32_t ) 0x015a4e35, uxIncrement = ( uint32_t ) 1;

    /* Utility function to generate a pseudo random number. */
    uxNextRand = ( uxMultiplier * uxNextRand ) + uxIncrement;
    return( ( UBaseType_t ) ( ( uxNextRand >> 16 ) & ( ( uint32_t ) 0x7fff ) ) );
}

Best regards,
NoMaY

setting uxNextRand to the address of prvRand sounds like a strange way to do it, but converting a pointer to an number is supposed to be done to the type of uintptr_t (or a type of the same size).

Note that it could just as properly have been set to any ‘random’ number like 0xDEADBEEF.

Hello richard-damon,

At first, I couldn’t understand what the setting code does. But now I think that (maybe) Richard wanted to add more randomness to RTOSDemo/Test tasks and he noticed that the address of prvRand() can be used as a seed of random number generation. The address of prvRand() are different from each other among various RTOSDemo programs. Moreover the address of prvRand() may change when the program is modified (if code at lower address than the address of prvRand() is added or removed) and the change causes new different random number generation.

Best regards,
NoMaY

[separate to the discussion it should be noted that this prvRand() is not much more than a utility function - it does not generate a truly random number suitable for security purposes - although using the address of a function as a seed is intended to (somewhat) prevent the pattern repeating between different builds]