From 31c382527c2a7cda8175dd5025be4a5cd50fc161 Mon Sep 17 00:00:00 2001 From: rtel Date: Sun, 4 Mar 2018 19:25:14 +0000 Subject: [PATCH] Introduce xMessageBufferNextLengthBytes() and tests for the same. Add call to traceTASK_SWITCHED_IN() in vTaskStartScheduler() so trace tools can see the first task to run. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2531 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../Demo/Common/Minimal/MessageBufferDemo.c | 45 ++++++++++++++++-- FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo | Bin 49664 -> 59904 bytes FreeRTOS/Source/include/message_buffer.h | 19 ++++++++ FreeRTOS/Source/include/mpu_prototypes.h | 1 + FreeRTOS/Source/include/mpu_wrappers.h | 1 + FreeRTOS/Source/include/stream_buffer.h | 2 + .../Source/portable/Common/mpu_wrappers.c | 12 +++++ FreeRTOS/Source/stream_buffer.c | 42 ++++++++++++++++ FreeRTOS/Source/tasks.c | 2 + 9 files changed, 121 insertions(+), 3 deletions(-) diff --git a/FreeRTOS/Demo/Common/Minimal/MessageBufferDemo.c b/FreeRTOS/Demo/Common/Minimal/MessageBufferDemo.c index 852b8f000..4422b2bd5 100644 --- a/FreeRTOS/Demo/Common/Minimal/MessageBufferDemo.c +++ b/FreeRTOS/Demo/Common/Minimal/MessageBufferDemo.c @@ -156,7 +156,7 @@ MessageBufferHandle_t xMessageBuffer; static void prvSingleTaskTests( MessageBufferHandle_t xMessageBuffer ) { -size_t xReturned, xItem, xExpectedSpace; +size_t xReturned, xItem, xExpectedSpace, xNextLength; const size_t xMax6ByteMessages = mbMESSAGE_BUFFER_LENGTH_BYTES / ( 6 + mbBYTES_TO_STORE_MESSAGE_LENGTH ); const size_t x6ByteLength = 6, x17ByteLength = 17; uint8_t *pucFullBuffer, *pucData, *pucReadData; @@ -177,11 +177,15 @@ UBaseType_t uxOriginalPriority; pucReadData = pucData + x17ByteLength; /* Nothing has been added or removed yet, so expect the free space to be - exactly as created. */ + exactly as created and the length of the next message to be 0. */ xExpectedSpace = xMessageBufferSpaceAvailable( xMessageBuffer ); configASSERT( xExpectedSpace == mbMESSAGE_BUFFER_LENGTH_BYTES ); configASSERT( xMessageBufferIsEmpty( xMessageBuffer ) == pdTRUE ); - + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == 0 ); + /* In case configASSERT() is not define. */ + ( void ) xExpectedSpace; + ( void ) xNextLength; /* The buffer is 50 bytes long. When an item is added to the buffer an additional 4 bytes are added to hold the item's size. That means adding @@ -215,6 +219,11 @@ UBaseType_t uxOriginalPriority; xReturned = xMessageBufferSpaceAvailable( xMessageBuffer ); configASSERT( xReturned == xExpectedSpace ); ( void ) xReturned; /* In case configASSERT() is not defined. */ + + /* Only 6 byte messages are written. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == x6ByteLength ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ } /* Now the buffer should be full, and attempting to add anything will should @@ -255,6 +264,11 @@ UBaseType_t uxOriginalPriority; configASSERT( xReturned == 0 ); ( void ) xReturned; /* In case configASSERT() is not defined. */ + /* Should still be at least one 6 byte message still available. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == x6ByteLength ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ + /* Read the next 6 bytes out. The 'FromISR' version is used to give it some exercise as a block time is not used. THa requires the code to be in a critical section so this test can be run with FreeRTOS ports that @@ -284,6 +298,11 @@ UBaseType_t uxOriginalPriority; configASSERT( xMessageBufferIsEmpty( xMessageBuffer ) == pdTRUE ); xExpectedSpace = xMessageBufferSpaceAvailable( xMessageBuffer ); configASSERT( xExpectedSpace == mbMESSAGE_BUFFER_LENGTH_BYTES ); + ( void ) xExpectedSpace; /* In case configASSERT() is not defined. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == 0 ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ + /* Reading with a timeout should also fail after the appropriate time. The priority is temporarily boosted in this part of the test to keep the @@ -320,6 +339,11 @@ UBaseType_t uxOriginalPriority; configASSERT( xReturned == x17ByteLength ); ( void ) xReturned; /* In case configASSERT() is not defined. */ + /* Only 17 byte messages are written. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == x17ByteLength ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ + /* The space in the buffer will have reduced by the amount of user data written into the buffer and the amount of space used to store the length of the data written into the buffer. */ @@ -334,6 +358,12 @@ UBaseType_t uxOriginalPriority; /* Does the data read out match that expected? */ configASSERT( memcmp( ( void * ) pucData, ( void * ) pucReadData, x17ByteLength ) == 0 ); + + /* Don't expect any messages to be available as the data was read out + again. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == 0 ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ } /* The buffer should be empty again. */ @@ -357,10 +387,19 @@ UBaseType_t uxOriginalPriority; configASSERT( xReturned == 0 ); ( void ) xReturned; /* In case configASSERT() is not defined. */ + /* Don't expect any messages to be available as the above were too large to + get written. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == 0 ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ + /* Can write mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ) bytes though. */ xReturned = xMessageBufferSend( xMessageBuffer, ( const void * ) pc55ByteString, mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ), mbDONT_BLOCK ); configASSERT( xReturned == mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ) ); ( void ) xReturned; /* In case configASSERT() is not defined. */ + xNextLength = xMessageBufferNextLengthBytes( xMessageBuffer ); + configASSERT( xNextLength == ( mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) ); + ( void ) xNextLength; /* In case configASSERT() is not defined. */ xReturned = xMessageBufferReceive( xMessageBuffer, ( void * ) pucFullBuffer, mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ), mbDONT_BLOCK ); configASSERT( xReturned == ( mbMESSAGE_BUFFER_LENGTH_BYTES - sizeof( size_t ) ) ); ( void ) xReturned; /* In case configASSERT() is not defined. */ diff --git a/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo b/FreeRTOS/Demo/WIN32-MSVC/.vs/WIN32/v14/.suo index 87d803022f5336a90ac661e095bfa862fae8593d..bb4718846ff2e2ac0118868b0a9b0feb09583b50 100644 GIT binary patch delta 4992 zcmeHLdvui55x;kngWM>gx{GD5Dvj zf(=|4Qy^v`XyAfSO>|m_o*k;?xZ=5Re2!|~66D;9xDBxmp-0dNW2ml1$wjG_P>Xt2 zOrWW~3MFR9S0i^VQQ%Kb&+ft&E#MBU?Fa|r1_a5IpVlLK5N<>!j>`Yc^ZxGNenZcb zaw?M}5cWLv&BO`A5ea*q`02%#l##qkbxJ(V6xEgqA)vZJE9^MPy_(AT4i}BS;MlPhCKwAnt zGyGAMIj1=OAaC?0LCJ1JilRUgqDNK3;U!s~`~Y%}z-4^}wLmS41pi6}_zglNMHnnc zGLWf+3x*mcS0jgZhXRW))(NfWkTz7`v=f^T(A+$$(L$# zWEM5XU7?m14xT)-f+8ggNhUms#0dlyD}tQA3(jX1i@Gg-9{c2eD)G7p>bJTambwgh zL!$=6(N^)~E)|E$KoJBpbVHe)pgS~O^yJ*f16f9yQZi&h*vuRRl{!ia8%>0Ujphn+ z$>wnrJ=bfqT(TK1FZdwtVC|9VTMwTw{i!{EhbeQ=!ld(PTc#T0uK?Ym`nWg0Jy-tz zgZI~NdGD9a&X_~*j!7I@R2GIv|v7r^`lSx`26vHU!8UK`_-%vTg+>t+OvmtREU zRSeW}IIdYTBwUIsH|%)+p}LPh8U8ToL|@X%ZQ=Q|KxYa$gpE9j1(%Tii_2Z>1Wa>C<0ZqMrD!_WU*d;jj2*6q6|_3Ue5 z+bO~^fdV5}axF@Kv5|10>UB9wBh{hJAYNEJoewSi^L1oTgI+r$Kk&|x1Fv|!>*9WR zc07A9XkvPribvALKIWa`dJ0U`RCMFB$RvK#(p#q5@Y-`@@Q$T;P2J3eEe~s9t$0b= zSTn0)b*zCISvFE#%*i@fBXYxXIk+Xi_vs0H!TF^xmR|W){-uW0i(@9}4r};hsPpb< z2kLR-*Mehh@W#R!acBRM^Vg-y)s|ZQTRA_dw4akkU{F364bdDN;eoWWt5$K}v~V0p zN53kPwd8&hPp8#N2hTFh5xODgg*bA0!6ac4FPD-u>@Lxx!Ly?16+YQ#;%HNb4Ca?) zP23On@x8ZC!Hjle(4$3vyHIDi0~*2slYLGqFPa)Yzv%PBGH-tA`hQ7eI5L7A(FjIQMYukn^6^ zHjJ|sj~kC&TZ$tHM_|de5s4yR;+ws$2t;K0uk*~q+UMThFNmM)b zSXnWQzA!h+gU=tjS(WT5IR9|3*6r!BwK&$adfVG=Jvr8m8wa$8e60q*>>`a?lbx3* zr_l3=jB+-;mkn(tZR8A)OT$Sl?Oa< zbg+EyumZj_awhRZ%!sj~3MSwgMMaQeHv3wtDQ0%^c63xYg!UY3HJOs~h4LYRFHwj_ ziAM()^4OY?35;b0JxD{`-3egMOcB-3otP>o+rDQ0CCvC-TIN_+k-aL(-ml8xknnXT ze0Uv+=J9nXf)5}~7n|_aDIOm?Iq_@J)RNiZT>g5!+o9&bdJJ~XpwUscqSnwLbefxr z^ed`N72TbV-1gpHO<7g1$ynJ{;Pn~`EEb_m->0>f`P@||;tBc{rG`em#@kiep%*Ik zKC81kx1c@0tlzYu&fqg?ZtiKxb(vR`w|X0mD_r%4_ExvXTD76cT5ejd*Ba}Da=pQ1 zTvk4)udy1|_tiA&yX{r=Mt5Ve+qTYQGWhBW^@jY8YJKG$#!jcn(5r7TRk}KsHRb#C zZT3RFr_<5C+}Ekmx0O~btF^l|t>vZ8?!H>o>+7;qG-)@OyF1EF27Qgw)lluNZs}ZB zrKe)Dm)74==e0PDMoMV7_(XidE_&Qb<=oF+M!F1X0W5p=iSO*YRVE!Sy=C8Uuir3f z9PQ1L*lRJPuVTV@!t5WnP7$0F!I+t>qZ6%nRyg=qjm(h_vbaeTcUoxT@l$lth%fE@ zf3i$Wmc#5`bWqxn)o#Ad2E>PM>+2;;fLned614hwlQO~ c)m7VZq?5QK#-|)ru?%NPQx;sama3uqw2=_K{Zm zf;~2p)FR>|)l|hD`iQj=N}3qbq@Ho~`QW~(I+ME1x&OLKy z?!Ete?iu$*gZm{zy?v}K`I{n1;cyM${=mQhM-8+wGxc<(M|kASLh$W`u#<)r6APbx4>3_WgylcN9@QmHc%Y;^hf2!d<`$5a<={3{Qtq>)ENwtij&U1FQjY7AVthdQIKPia4U41V z10n|@%)`0qBGW-rOjNu-ItKQ?mo;I?oFmD)K?q5bfdK>oBM1hezy!>I_Z0>k4lE!7 zL;?jwfoKo|tRNPQ0;2)H7Y{qe@83UNLSohbJtJm0AiSzm1o0UL?iSTN;xh3G@ZF&| z6K%%l;RI=YmdAvNQ=OB7<5Uw_Or4f#9;HTnM_ZJg;xgS-7MKN}e(K<$D0lcJblL$o zZ@5EHr<_mfnjqR{dDT0!NhlphqSD)TS1-9`Zz?U>H_J&U9Sd8+WpD0!VP$Os2f}_O zK0_+?7DByKkr-n;fz>7I=nN*1M)GFu~uC12~E9WKbz z=F(glt-@1~LMchLam?kAvoRCH=$0e zDSusfoep7^M%uo&0wwu;$z)Qezen|%al_YFV$IOk*0Msz@@$@-2>PZmkrrm<4j)^u zwhhleoWfxKh3WZ+0Gc+p?QQJ%mmE<~9r-J@6g6Xn>>c{HFMFvkW}aDajq7kA?T!1mLw$w)O6=;^No(JIvEYsT>V~`K zFMhz$PbGCyyQj2MPx0PTqzh8LrcAftTrRofar1^&ia5@~9(2A1><6H2VRL5OK=60) z2j~Si!7Xqb+yQ;yPjDC91O4DW(EqUF!RhNZOMJbzcZP3 z?aB##A7{zGGFj5D?^gs>9FSYKnsRh2-pkW+zM3P`p3{dZy4FgnS8Z7%lbon(>hX5bvQGB2s-$YR z_+04;eNsuF z30gw)PX@ZOHjS>IQfPz tO}tzxsQr_6s;XX3mFG-UZx13lWjb|_3nlf_c8X55k}E$^v!Ce>`3p*$1?B(% diff --git a/FreeRTOS/Source/include/message_buffer.h b/FreeRTOS/Source/include/message_buffer.h index 8be974041..752cbe7d8 100644 --- a/FreeRTOS/Source/include/message_buffer.h +++ b/FreeRTOS/Source/include/message_buffer.h @@ -693,6 +693,25 @@ size_t xMessageBufferSpaceAvailable( MessageBufferHandle_t xMessageBuffer ) ); */ #define xMessageBufferSpaceAvailable( xMessageBuffer ) xStreamBufferSpacesAvailable( ( StreamBufferHandle_t ) xMessageBuffer ) +/** + * message_buffer.h +
+ size_t xMessageBufferNextLengthBytes( MessageBufferHandle_t xMessageBuffer ) );
+ 
+ * Returns the length (in bytes) of the next message in a message buffer. + * Useful if xMessageBufferReceive() returned 0 because the size of the buffer + * passed into xMessageBufferReceive() was too small to hold the next message. + * + * @param xMessageBuffer The handle of the message buffer being queried. + * + * @return The length (in bytes) of the next message in the message buffer, or 0 + * if the message buffer is empty. + * + * \defgroup xMessageBufferNextLengthBytes xMessageBufferNextLengthBytes + * \ingroup MessageBufferManagement + */ +#define xMessageBufferNextLengthBytes( xMessageBuffer ) xStreamBufferNextMessageLengthBytes( ( StreamBufferHandle_t ) xMessageBuffer ) PRIVILEGED_FUNCTION; + /** * message_buffer.h * diff --git a/FreeRTOS/Source/include/mpu_prototypes.h b/FreeRTOS/Source/include/mpu_prototypes.h index a08d748fb..d015cf750 100644 --- a/FreeRTOS/Source/include/mpu_prototypes.h +++ b/FreeRTOS/Source/include/mpu_prototypes.h @@ -138,6 +138,7 @@ UBaseType_t MPU_uxEventGroupGetNumber( void* xEventGroup ); size_t MPU_xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait ); size_t MPU_xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, BaseType_t * const pxHigherPriorityTaskWoken ); size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait ); +size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ); size_t MPU_xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, BaseType_t * const pxHigherPriorityTaskWoken ); void MPU_vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer ); BaseType_t MPU_xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer ); diff --git a/FreeRTOS/Source/include/mpu_wrappers.h b/FreeRTOS/Source/include/mpu_wrappers.h index 1e97ae4c8..3ab181f2f 100644 --- a/FreeRTOS/Source/include/mpu_wrappers.h +++ b/FreeRTOS/Source/include/mpu_wrappers.h @@ -142,6 +142,7 @@ only for ports that are using the MPU. */ #define xStreamBufferSend MPU_xStreamBufferSend #define xStreamBufferSendFromISR MPU_xStreamBufferSendFromISR #define xStreamBufferReceive MPU_xStreamBufferReceive + #define xStreamBufferNextMessageLengthBytes MPU_xStreamBufferNextMessageLengthBytes #define xStreamBufferReceiveFromISR MPU_xStreamBufferReceiveFromISR #define vStreamBufferDelete MPU_vStreamBufferDelete #define xStreamBufferIsFull MPU_xStreamBufferIsFull diff --git a/FreeRTOS/Source/include/stream_buffer.h b/FreeRTOS/Source/include/stream_buffer.h index f967dd284..560d3d40a 100644 --- a/FreeRTOS/Source/include/stream_buffer.h +++ b/FreeRTOS/Source/include/stream_buffer.h @@ -839,6 +839,8 @@ StreamBufferHandle_t xStreamBufferGenericCreateStatic( size_t xBufferSizeBytes, uint8_t * const pucStreamBufferStorageArea, StaticStreamBuffer_t * const pxStaticStreamBuffer ) PRIVILEGED_FUNCTION; +size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; + #if( configUSE_TRACE_FACILITY == 1 ) void vStreamBufferSetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer, UBaseType_t uxStreamBufferNumber ) PRIVILEGED_FUNCTION; UBaseType_t uxStreamBufferGetStreamBufferNumber( StreamBufferHandle_t xStreamBuffer ) PRIVILEGED_FUNCTION; diff --git a/FreeRTOS/Source/portable/Common/mpu_wrappers.c b/FreeRTOS/Source/portable/Common/mpu_wrappers.c index 73cfdf223..5bdbc100c 100644 --- a/FreeRTOS/Source/portable/Common/mpu_wrappers.c +++ b/FreeRTOS/Source/portable/Common/mpu_wrappers.c @@ -1136,6 +1136,18 @@ BaseType_t xRunningPrivileged = xPortRaisePrivilege(); } /*-----------------------------------------------------------*/ +size_t MPU_xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) +{ +size_t xReturn; +BaseType_t xRunningPrivileged = xPortRaisePrivilege(); + + xReturn = xStreamBufferNextMessageLengthBytes( xStreamBuffer ); + vPortResetPrivilege( xRunningPrivileged ); + + return xReturn; +} +/*-----------------------------------------------------------*/ + size_t MPU_xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait ) { size_t xReturn; diff --git a/FreeRTOS/Source/stream_buffer.c b/FreeRTOS/Source/stream_buffer.c index 40619108a..963a35593 100644 --- a/FreeRTOS/Source/stream_buffer.c +++ b/FreeRTOS/Source/stream_buffer.c @@ -792,6 +792,48 @@ size_t xReceivedLength = 0, xBytesAvailable, xBytesToStoreMessageLength; } /*-----------------------------------------------------------*/ +size_t xStreamBufferNextMessageLengthBytes( StreamBufferHandle_t xStreamBuffer ) +{ +StreamBuffer_t * const pxStreamBuffer = ( StreamBuffer_t * ) xStreamBuffer; /*lint !e9087 !e9079 Safe cast as StreamBufferHandle_t is opaque Streambuffer_t. */ +size_t xReturn, xBytesAvailable, xOriginalTail; + + configASSERT( pxStreamBuffer ); + + /* Ensure the stream buffer is being used as a message buffer. */ + if( ( pxStreamBuffer->ucFlags & sbFLAGS_IS_MESSAGE_BUFFER ) != ( uint8_t ) 0 ) + { + xBytesAvailable = prvBytesInBuffer( pxStreamBuffer ); + if( xBytesAvailable > sbBYTES_TO_STORE_MESSAGE_LENGTH ) + { + /* The number of bytes available is greater than the number of bytes + required to hold the length of the next message, so another message + is available. Return its length without removing the length bytes + from the buffer. A copy of the tail is stored so the buffer can be + returned to its prior state as the message is not actually being + removed from the buffer. */ + xOriginalTail = pxStreamBuffer->xTail; + ( void ) prvReadBytesFromBuffer( pxStreamBuffer, ( uint8_t * ) &xReturn, sbBYTES_TO_STORE_MESSAGE_LENGTH, xBytesAvailable ); + pxStreamBuffer->xTail = xOriginalTail; + } + else + { + /* The minimum amount of bytes in a message buffer is + ( sbBYTES_TO_STORE_MESSAGE_LENGTH + 1 ), so if xBytesAvailable is + less than sbBYTES_TO_STORE_MESSAGE_LENGTH the only other valid + value is 0. */ + configASSERT( xBytesAvailable == 0 ); + xReturn = 0; + } + } + else + { + xReturn = 0; + } + + return xReturn; +} +/*-----------------------------------------------------------*/ + size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index 268c17c62..3a0cbf4e9 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -1994,6 +1994,8 @@ BaseType_t xReturn; FreeRTOSConfig.h file. */ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); + traceTASK_SWITCHED_IN(); + /* Setting up the timer tick is hardware specific and thus in the portable interface. */ if( xPortStartScheduler() != pdFALSE ) -- 2.39.5