I am using the RTX mailbox and a lot of it's usage uses casting of the mailbox message to other types - a really quick and clever way to use it(thanks Keil :). When I cast a void * vPointer to a unigned int - like (uint32_t)vPointer - the compiler is happy - but when I cast to a signed char - like (int8_t)vPointer the compiler complains and says:
Source_App\TerminalDrv.c(56): warning: #767-D: conversion from pointer to smaller integer
Now it all works fine ... but what do I do to stop it complaining?
uint32_t TerminalControllerGetChar(int8_t *pcRxedChar ) { void * pvmbxTerminalRx; uint32_t ulNoRxMessage,ulI; ulNoRxMessage = SIZEOF_OS_MBX_RXTERMINAL - os_mbx_check(mbxHandleTerminalRx); if(ulNoRxMessage == 0) return 0 ; else { for(ulI = 0;ulI < ulNoRxMessage ; ulI++) { if(os_mbx_wait(mbxHandleTerminalRx,(void **)&pvmbxTerminalRx,0x0000) == OS_R_OK) { *pcRxedChar = (int8_t)pvmbxTerminalRx; pcRxedChar++; } else { break; } } } return ulNoRxMessage; }
The compiler is perfectly correct & accurate!
You need to cast the void* pointer to a char* pointer - and then dereference that char* pointer to give you the char that it points to!
Except that you sometimes stores an integer in the pointer itself. What happens if you typecast as unsigned first?
Many Thanks Niel.
Quick check here. Andy's note about typecast from void* to char* is only meaningful if your mailbox contains pointers to characters. Is that so? It's quite common, when the data types fits in a pointer, to not allocate any memory for the objects, but instead store the values directly in the pointer. The mailbox routines don't care if they receive real pointers or just arbitrary numbers, as long as the sender and receiver both understands if os_mb_wait() will return a pointer or an integer.
So if your program sends mailbox data like (DRAW_MERGE here is an integer constant)
os_mbx_send(mailbox_draw,(void*)DRAW_MERGE,0);
Then you can't typecast your origianl void pointer into a non-void pointer and then use indirection.
In my case - since I send unsigned data - my receiving code looks like:
void *msg; os_mbx_wait(mailbox_draw,&msg,0xffff); switch ((unsigned)msg) { ... }
That was why I wondered what the compiler would say (assuming you do send the caracters as faked pointer valids) if you instead wrote:
*pcRxedChar = (int8_t)(unsigned)pvmbxTerminalRx;
"... if your mailbox contains pointers to characters"
Agreed.
Hi Per My mailbox sender looks like this - getting interupt data from the USART on a STM32xx part (the relevant section):
void vTerminalInteruptHandler (void) { uint16_t usTermRxChar; if( TerminalUSARTx->SR & USART_RXNE_MASK) { usTermRxChar = (uint16_t)(USART3->DR & (uint16_t)0x01FF); isr_mbx_send(mbxHandleTerminalRx,(void*)usTermRxChar); } }
I added the (unsigned) as you suggested - so now that wait on mailbox part looks like this:
if(os_mbx_wait(mbxHandleTerminalRx,(void **)&pvmbxTerminalRx,0x0000) == OS_R_OK) { *pcRxedChar = (int8_t)(unsigned)pvmbxTerminalRx; pcRxedChar++; }
And now the compiler is happy ... and it works. That is what is so great about the scheme that uses the mailbox pointer to pass data - all the the nasty FIFO business etc is taken care of and you don't have to worry about allocating memory - really works a treat. I use the mailbox a lot and try and fit the data into 32 bits and out of 17x mailboxes that are used -only 4x use the mailbox pointer as intended - as a pointer to a array of message structs. Many thanks.