mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Core kernel code:
+ Introduce xSemaphoreGenericGiveFromISR() as an optimisation when giving semaphores and mutexes from an interrupt. Demo applications: + Update IntSemTest.c to provide more code coverage in xSemaphoreGenericGiveFromISR(). + Ensure the MMU is turned on in the RZ IAR demo. It was already on in the RZ ARM demo.
This commit is contained in:
parent
b3c040fc27
commit
3b0854bf96
|
@ -39,7 +39,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Wnd3>
|
<Wnd0>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab>
|
<Tab>
|
||||||
<Identity>TabID-6824-27546</Identity>
|
<Identity>TabID-6824-27546</Identity>
|
||||||
|
@ -55,7 +55,7 @@
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab><Identity>TabID-11794-23690</Identity><TabName>Find in Files</TabName><Factory>Find-in-Files</Factory><Session/></Tab></Tabs>
|
<Tab><Identity>TabID-11794-23690</Identity><TabName>Find in Files</TabName><Factory>Find-in-Files</Factory><Session/></Tab></Tabs>
|
||||||
|
|
||||||
<SelectedTab>0</SelectedTab></Wnd3><Wnd4>
|
<SelectedTab>0</SelectedTab></Wnd0><Wnd1>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab>
|
<Tab>
|
||||||
<Identity>TabID-17573-27549</Identity>
|
<Identity>TabID-17573-27549</Identity>
|
||||||
|
@ -67,20 +67,20 @@
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
<SelectedTab>0</SelectedTab></Wnd4><Wnd5><Tabs><Tab><Identity>TabID-8721-7680</Identity><TabName>Disassembly</TabName><Factory>Disassembly</Factory><Session/></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd5></Windows>
|
<SelectedTab>0</SelectedTab></Wnd1><Wnd2><Tabs><Tab><Identity>TabID-8721-7680</Identity><TabName>Disassembly</TabName><Factory>Disassembly</Factory><Session/></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd2></Windows>
|
||||||
<Editor>
|
<Editor>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Full-Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>8123</SelStart2><SelEnd2>8123</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Blinky-Demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>9979</SelStart2><SelEnd2>9979</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>112</YPos2><SelStart2>6090</SelStart2><SelEnd2>6090</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\cstartup.s</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>132</YPos2><SelStart2>5456</SelStart2><SelEnd2>5456</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\LowLevelInitialise.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>24</YPos2><SelStart2>1341</SelStart2><SelEnd2>1341</SelEnd2></Tab><ActiveTab>4</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\modules\armv7a_cp15_drv.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>727</YPos2><SelStart2>20604</SelStart2><SelEnd2>20604</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
|
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Blinky-Demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>122</YPos2><SelStart2>6348</SelStart2><SelEnd2>6348</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\cstartup.s</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>120</YPos2><SelStart2>3672</SelStart2><SelEnd2>3672</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\LowLevelInitialise.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>14</YPos2><SelStart2>1080</SelStart2><SelEnd2>1080</SelEnd2></Tab><ActiveTab>3</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\modules\armv7a_cp15_drv.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>573</YPos2><SelStart2>16780</SelStart2><SelEnd2>16780</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\LEDs.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>4247</SelStart2><SelEnd2>4247</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\RenesasFiles\board_settings\siochar.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>4669</SelStart2><SelEnd2>4669</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Full-Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>340</YPos2><SelStart2>17554</SelStart2><SelEnd2>17554</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
|
||||||
<Positions>
|
<Positions>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Top><Row0><Sizes><Toolbar-00D172A8><key>iaridepm.enu1</key></Toolbar-00D172A8></Sizes></Row0><Row1><Sizes><Toolbar-12B3ABF8><key>debuggergui.enu1</key></Toolbar-12B3ABF8></Sizes></Row1></Top><Left><Row0><Sizes><Wnd4><Rect><Top>-2</Top><Left>-2</Left><Bottom>718</Bottom><Right>302</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>180952</sizeVertCX><sizeVertCY>731707</sizeVertCY></Rect></Wnd4></Sizes></Row0></Left><Right><Row0><Sizes><Wnd5><Rect><Top>-2</Top><Left>-2</Left><Bottom>718</Bottom><Right>699</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>417262</sizeVertCX><sizeVertCY>731707</sizeVertCY></Rect></Wnd5></Sizes></Row0></Right><Bottom><Row0><Sizes><Wnd3><Rect><Top>-2</Top><Left>-2</Left><Bottom>198</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>200</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd3></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
|
<Top><Row0><Sizes><Toolbar-00D672A8><key>iaridepm.enu1</key></Toolbar-00D672A8></Sizes></Row0><Row1><Sizes><Toolbar-07472A10><key>debuggergui.enu1</key></Toolbar-07472A10></Sizes></Row1></Top><Left><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>718</Bottom><Right>302</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>180952</sizeVertCX><sizeVertCY>731707</sizeVertCY></Rect></Wnd1></Sizes></Row0></Left><Right><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>718</Bottom><Right>699</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>417262</sizeVertCX><sizeVertCY>731707</sizeVertCY></Rect></Wnd2></Sizes></Row0></Right><Bottom><Row0><Sizes><Wnd0><Rect><Top>-2</Top><Left>-2</Left><Bottom>198</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>200</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd0></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
|
||||||
</Desktop>
|
</Desktop>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ Watch0=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
|
||||||
Watch1=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
|
Watch1=_ 0 "" 0 "" 0 "" 0 "" 0 0 0 0
|
||||||
CStepIntDis=_ 0
|
CStepIntDis=_ 0
|
||||||
[DebugChecksum]
|
[DebugChecksum]
|
||||||
Checksum=-1045357403
|
Checksum=72368941
|
||||||
[Jet]
|
[Jet]
|
||||||
JetConnSerialNo=73866
|
JetConnSerialNo=73866
|
||||||
JetConnFoundProbes=
|
JetConnFoundProbes=
|
||||||
|
@ -109,7 +109,8 @@ Exclusions=
|
||||||
[Disassemble mode]
|
[Disassemble mode]
|
||||||
mode=0
|
mode=0
|
||||||
[Breakpoints2]
|
[Breakpoints2]
|
||||||
Count=0
|
Bp0=_ 1 "EMUL_CODE" "{$PROJ_DIR$\..\Source\main.c}.136.2" 0 0 1 "" 0 "" 0
|
||||||
|
Count=1
|
||||||
[Aliases]
|
[Aliases]
|
||||||
Count=0
|
Count=0
|
||||||
SuppressDialog=0
|
SuppressDialog=0
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
<Factory>Workspace</Factory>
|
<Factory>Workspace</Factory>
|
||||||
<Session>
|
<Session>
|
||||||
|
|
||||||
<NodeDict><ExpandedNode>RTOSDemo</ExpandedNode><ExpandedNode>RTOSDemo/Blinky-Demo</ExpandedNode></NodeDict></Session>
|
<NodeDict><ExpandedNode>RTOSDemo</ExpandedNode></NodeDict></Session>
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
|
@ -58,20 +58,20 @@
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab><Identity>TabID-959-438</Identity><TabName>Ambiguous Definitions</TabName><Factory>Select-Ambiguous-Definitions</Factory><Session/></Tab><Tab><Identity>TabID-21579-10611</Identity><TabName>Find All Declarations</TabName><Factory>Find-All-Declarations</Factory><Session/></Tab></Tabs>
|
<Tab><Identity>TabID-959-438</Identity><TabName>Ambiguous Definitions</TabName><Factory>Select-Ambiguous-Definitions</Factory><Session/></Tab><Tab><Identity>TabID-21579-10611</Identity><TabName>Find All Declarations</TabName><Factory>Find-All-Declarations</Factory><Session/></Tab></Tabs>
|
||||||
|
|
||||||
<SelectedTab>1</SelectedTab></Wnd3></Windows>
|
<SelectedTab>3</SelectedTab></Wnd3></Windows>
|
||||||
<Editor>
|
<Editor>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Full-Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>8123</SelStart2><SelEnd2>8123</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Blinky-Demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>112</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\cstartup.s</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>132</YPos2><SelStart2>5456</SelStart2><SelEnd2>5456</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\LowLevelInitialise.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>14</YPos2><SelStart2>1341</SelStart2><SelEnd2>1341</SelEnd2></Tab><ActiveTab>4</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\modules\armv7a_cp15_drv.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>727</YPos2><SelStart2>20604</SelStart2><SelEnd2>20604</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
|
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Blinky-Demo\main_blinky.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>122</YPos2><SelStart2>6348</SelStart2><SelEnd2>6348</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\cstartup.s</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>120</YPos2><SelStart2>3672</SelStart2><SelEnd2>3672</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\LowLevelInitialise.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>23</YPos2><SelStart2>1067</SelStart2><SelEnd2>1082</SelEnd2></Tab><ActiveTab>3</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\modules\armv7a_cp15_drv.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>283</YPos2><SelStart2>8523</SelStart2><SelEnd2>8523</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\LEDs.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>64</YPos2><SelStart2>4247</SelStart2><SelEnd2>4247</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\RenesasFiles\board_settings\siochar.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>63</YPos2><SelStart2>4669</SelStart2><SelEnd2>4669</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\Source\Full-Demo\main_full.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>340</YPos2><SelStart2>17554</SelStart2><SelEnd2>17554</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
|
||||||
<Positions>
|
<Positions>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Top><Row0><Sizes><Toolbar-00D172A8><key>iaridepm.enu1</key></Toolbar-00D172A8></Sizes></Row0><Row1><Sizes/></Row1></Top><Left><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>693</Bottom><Right>380</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>227381</sizeVertCX><sizeVertCY>706301</sizeVertCY></Rect></Wnd2></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd3><Rect><Top>-2</Top><Left>-2</Left><Bottom>247</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>249</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>253049</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd3></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
|
<Top><Row0><Sizes><Toolbar-00D672A8><key>iaridepm.enu1</key></Toolbar-00D672A8></Sizes></Row0><Row1><Sizes/></Row1></Top><Left><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>693</Bottom><Right>380</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>119048</sizeHorzCX><sizeHorzCY>203252</sizeHorzCY><sizeVertCX>227381</sizeVertCX><sizeVertCY>706301</sizeVertCY></Rect></Wnd2></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd3><Rect><Top>-2</Top><Left>-2</Left><Bottom>247</Bottom><Right>1682</Right><x>-2</x><y>-2</y><xscreen>1684</xscreen><yscreen>249</yscreen><sizeHorzCX>1002381</sizeHorzCX><sizeHorzCY>253049</sizeHorzCY><sizeVertCX>119048</sizeVertCX><sizeVertCY>203252</sizeVertCY></Rect></Wnd3></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
|
||||||
</Desktop>
|
</Desktop>
|
||||||
</Workspace>
|
</Workspace>
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -91,6 +91,10 @@
|
||||||
/* A block time of 0 means 'don't block'. */
|
/* A block time of 0 means 'don't block'. */
|
||||||
#define intsemNO_BLOCK 0
|
#define intsemNO_BLOCK 0
|
||||||
|
|
||||||
|
/* The maximum count value for the counting semaphore given from an
|
||||||
|
interrupt. */
|
||||||
|
#define intsemMAX_COUNT 3
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -106,6 +110,26 @@
|
||||||
static void vInterruptMutexSlaveTask( void *pvParameters );
|
static void vInterruptMutexSlaveTask( void *pvParameters );
|
||||||
static void vInterruptMutexMasterTask( void *pvParameters );
|
static void vInterruptMutexMasterTask( void *pvParameters );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A test whereby the master takes the shared and interrupt mutexes in that
|
||||||
|
* order, then gives them back in the same order, ensuring the priority
|
||||||
|
* inheritance is behaving as expected at each step.
|
||||||
|
*/
|
||||||
|
static void prvTakeAndGiveInTheSameOrder( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A test whereby the master takes the shared and interrupt mutexes in that
|
||||||
|
* order, then gives them back in the opposite order to which they were taken,
|
||||||
|
* ensuring the priority inheritance is behaving as expected at each step.
|
||||||
|
*/
|
||||||
|
static void prvTakeAndGiveInTheOppositeOrder( void );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A simple task that interacts with an interrupt using a counting semaphore,
|
||||||
|
* primarily for code coverage purposes.
|
||||||
|
*/
|
||||||
|
static void vInterruptCountingSemaphoreTask( void *pvParameters );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
/* Flag that will be latched to pdTRUE should any unexpected behaviour be
|
||||||
|
@ -114,7 +138,7 @@ static volatile BaseType_t xErrorDetected = pdFALSE;
|
||||||
|
|
||||||
/* Counters that are incremented on each cycle of a test. This is used to
|
/* Counters that are incremented on each cycle of a test. This is used to
|
||||||
detect a stalled task - a test that is no longer running. */
|
detect a stalled task - a test that is no longer running. */
|
||||||
static volatile uint32_t ulMasterLoops = 0;
|
static volatile uint32_t ulMasterLoops = 0, ulCountingSemaphoreLoops = 0;
|
||||||
|
|
||||||
/* Handles of the test tasks that must be accessed from other test tasks. */
|
/* Handles of the test tasks that must be accessed from other test tasks. */
|
||||||
static TaskHandle_t xSlaveHandle;
|
static TaskHandle_t xSlaveHandle;
|
||||||
|
@ -124,6 +148,9 @@ not be used given in interrupts (and definitely never taken in an interrupt)
|
||||||
there are some circumstances when it may be desirable. */
|
there are some circumstances when it may be desirable. */
|
||||||
static SemaphoreHandle_t xISRMutex = NULL;
|
static SemaphoreHandle_t xISRMutex = NULL;
|
||||||
|
|
||||||
|
/* A counting semaphore which is given from an interrupt. */
|
||||||
|
static SemaphoreHandle_t xISRCountingSemaphore = NULL;
|
||||||
|
|
||||||
/* A mutex which is shared between the master and slave tasks - the master
|
/* A mutex which is shared between the master and slave tasks - the master
|
||||||
does both sharing of this mutex with the slave and receiving a mutex from the
|
does both sharing of this mutex with the slave and receiving a mutex from the
|
||||||
interrupt. */
|
interrupt. */
|
||||||
|
@ -132,15 +159,20 @@ static SemaphoreHandle_t xMasterSlaveMutex = NULL;
|
||||||
/* Flag that allows the master task to control when the interrupt gives or does
|
/* Flag that allows the master task to control when the interrupt gives or does
|
||||||
not give the mutex. There is no mutual exclusion on this variable, but this is
|
not give the mutex. There is no mutual exclusion on this variable, but this is
|
||||||
only test code and it should be fine in the 32=bit test environment. */
|
only test code and it should be fine in the 32=bit test environment. */
|
||||||
static BaseType_t xOkToGiveMutex = pdFALSE;
|
static BaseType_t xOkToGiveMutex = pdFALSE, xOkToGiveCountingSemaphore = pdFALSE;
|
||||||
|
|
||||||
|
/* Used to coordinate timing between tasks and the interrupt. */
|
||||||
|
const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vStartInterruptSemaphoreTasks( void )
|
void vStartInterruptSemaphoreTasks( void )
|
||||||
{
|
{
|
||||||
/* Create the mutex that is given from an interrupt. */
|
/* Create the semaphores that are given from an interrupt. */
|
||||||
xISRMutex = xSemaphoreCreateMutex();
|
xISRMutex = xSemaphoreCreateMutex();
|
||||||
configASSERT( xISRMutex );
|
configASSERT( xISRMutex );
|
||||||
|
xISRCountingSemaphore = xSemaphoreCreateCounting( intsemMAX_COUNT, 0 );
|
||||||
|
configASSERT( xISRCountingSemaphore );
|
||||||
|
|
||||||
/* Create the mutex that is shared between the master and slave tasks (the
|
/* Create the mutex that is shared between the master and slave tasks (the
|
||||||
master receives a mutex from an interrupt and shares a mutex with the
|
master receives a mutex from an interrupt and shares a mutex with the
|
||||||
|
@ -151,163 +183,26 @@ void vStartInterruptSemaphoreTasks( void )
|
||||||
/* Create the tasks that share mutexes between then and with interrupts. */
|
/* Create the tasks that share mutexes between then and with interrupts. */
|
||||||
xTaskCreate( vInterruptMutexSlaveTask, "IntMuS", configMINIMAL_STACK_SIZE, NULL, intsemSLAVE_PRIORITY, &xSlaveHandle );
|
xTaskCreate( vInterruptMutexSlaveTask, "IntMuS", configMINIMAL_STACK_SIZE, NULL, intsemSLAVE_PRIORITY, &xSlaveHandle );
|
||||||
xTaskCreate( vInterruptMutexMasterTask, "IntMuM", configMINIMAL_STACK_SIZE, NULL, intsemMASTER_PRIORITY, NULL );
|
xTaskCreate( vInterruptMutexMasterTask, "IntMuM", configMINIMAL_STACK_SIZE, NULL, intsemMASTER_PRIORITY, NULL );
|
||||||
|
|
||||||
|
/* Create the task that blocks on the counting semaphore. */
|
||||||
|
xTaskCreate( vInterruptCountingSemaphoreTask, "IntCnt", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void vInterruptMutexMasterTask( void *pvParameters )
|
static void vInterruptMutexMasterTask( void *pvParameters )
|
||||||
{
|
{
|
||||||
const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );
|
|
||||||
|
|
||||||
/* Just to avoid compiler warnings. */
|
/* Just to avoid compiler warnings. */
|
||||||
( void ) pvParameters;
|
( void ) pvParameters;
|
||||||
|
|
||||||
for( ;; )
|
for( ;; )
|
||||||
{
|
{
|
||||||
/* Ensure the slave is suspended, and that this task is running at the
|
prvTakeAndGiveInTheSameOrder();
|
||||||
lower priority as expected as the start conditions. */
|
|
||||||
#if( INCLUDE_eTaskGetState == 1 )
|
|
||||||
{
|
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
|
||||||
}
|
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take the semaphore that is shared with the slave. */
|
|
||||||
if( xSemaphoreTake( xMasterSlaveMutex, intsemNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This task now has the mutex. Unsuspend the slave so it too
|
|
||||||
attempts to take the mutex. */
|
|
||||||
vTaskResume( xSlaveHandle );
|
|
||||||
|
|
||||||
/* The slave has the higher priority so should now have executed and
|
|
||||||
blocked on the semaphore. */
|
|
||||||
#if( INCLUDE_eTaskGetState == 1 )
|
|
||||||
{
|
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
|
||||||
}
|
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
|
||||||
|
|
||||||
/* This task should now have inherited the priority of the slave
|
|
||||||
task. */
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now wait a little longer than the time between ISR gives to also
|
|
||||||
obtain the ISR mutex. */
|
|
||||||
xOkToGiveMutex = pdTRUE;
|
|
||||||
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
xOkToGiveMutex = pdFALSE;
|
|
||||||
|
|
||||||
/* Attempting to take again immediately should fail as the mutex is
|
|
||||||
already held. */
|
|
||||||
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Should still be at the priority of the slave task. */
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Give back the ISR semaphore to ensure the priority is not
|
|
||||||
disinherited as the shared mutex (which the higher priority task is
|
|
||||||
attempting to obtain) is still held. */
|
|
||||||
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finally give back the shared mutex. This time the higher priority
|
|
||||||
task should run before this task runs again - so this task should have
|
|
||||||
disinherited the priority and the higher priority task should be in the
|
|
||||||
suspended state again. */
|
|
||||||
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if( INCLUDE_eTaskGetState == 1 )
|
|
||||||
{
|
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
|
||||||
}
|
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
|
||||||
|
|
||||||
/* Ensure not to starve out other tests. */
|
/* Ensure not to starve out other tests. */
|
||||||
ulMasterLoops++;
|
ulMasterLoops++;
|
||||||
vTaskDelay( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );
|
vTaskDelay( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS );
|
||||||
|
|
||||||
|
prvTakeAndGiveInTheOppositeOrder();
|
||||||
/* Repeat exactly up to the point where the mutexes are given back.
|
|
||||||
This time the shared mutex is given back first. */
|
|
||||||
if( xSemaphoreTake( xMasterSlaveMutex, intsemNO_BLOCK ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskResume( xSlaveHandle );
|
|
||||||
|
|
||||||
#if( INCLUDE_eTaskGetState == 1 )
|
|
||||||
{
|
|
||||||
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
|
||||||
}
|
|
||||||
#endif /* INCLUDE_eTaskGetState */
|
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
xOkToGiveMutex = pdTRUE;
|
|
||||||
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
xOkToGiveMutex = pdFALSE;
|
|
||||||
|
|
||||||
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is where the differences start as this time the shared mutex is
|
|
||||||
given back first. This time to the higher priority task should run
|
|
||||||
before this task gets to the point of releasing the interrupt mutex - so
|
|
||||||
this task should have disinherited the priority and the higher priority
|
|
||||||
task should be in the suspended state again. */
|
|
||||||
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
|
||||||
{
|
|
||||||
xErrorDetected = pdTRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Give back the interrupt semaphore too, so the mutex held count goes
|
|
||||||
back to 0. The mutex will then have to be reset so the ISR can give it
|
|
||||||
in the next cycle. */
|
|
||||||
xSemaphoreGive( xISRMutex );
|
|
||||||
xQueueReset( ( QueueHandle_t ) xISRMutex );
|
|
||||||
|
|
||||||
/* Ensure not to starve out other tests. */
|
/* Ensure not to starve out other tests. */
|
||||||
ulMasterLoops++;
|
ulMasterLoops++;
|
||||||
|
@ -316,6 +211,201 @@ const TickType_t xInterruptGivePeriod = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIV
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTakeAndGiveInTheSameOrder( void )
|
||||||
|
{
|
||||||
|
/* Ensure the slave is suspended, and that this task is running at the
|
||||||
|
lower priority as expected as the start conditions. */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take the semaphore that is shared with the slave. */
|
||||||
|
if( xSemaphoreTake( xMasterSlaveMutex, intsemNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This task now has the mutex. Unsuspend the slave so it too
|
||||||
|
attempts to take the mutex. */
|
||||||
|
vTaskResume( xSlaveHandle );
|
||||||
|
|
||||||
|
/* The slave has the higher priority so should now have executed and
|
||||||
|
blocked on the semaphore. */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* This task should now have inherited the priority of the slave
|
||||||
|
task. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now wait a little longer than the time between ISR gives to also
|
||||||
|
obtain the ISR mutex. */
|
||||||
|
xOkToGiveMutex = pdTRUE;
|
||||||
|
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
xOkToGiveMutex = pdFALSE;
|
||||||
|
|
||||||
|
/* Attempting to take again immediately should fail as the mutex is
|
||||||
|
already held. */
|
||||||
|
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should still be at the priority of the slave task. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give back the ISR semaphore to ensure the priority is not
|
||||||
|
disinherited as the shared mutex (which the higher priority task is
|
||||||
|
attempting to obtain) is still held. */
|
||||||
|
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally give back the shared mutex. This time the higher priority
|
||||||
|
task should run before this task runs again - so this task should have
|
||||||
|
disinherited the priority and the higher priority task should be in the
|
||||||
|
suspended state again. */
|
||||||
|
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* Reset the mutex ready for the next round. */
|
||||||
|
xQueueReset( xISRMutex );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void prvTakeAndGiveInTheOppositeOrder( void )
|
||||||
|
{
|
||||||
|
/* Ensure the slave is suspended, and that this task is running at the
|
||||||
|
lower priority as expected as the start conditions. */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xSlaveHandle ) == eSuspended );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take the semaphore that is shared with the slave. */
|
||||||
|
if( xSemaphoreTake( xMasterSlaveMutex, intsemNO_BLOCK ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This task now has the mutex. Unsuspend the slave so it too
|
||||||
|
attempts to take the mutex. */
|
||||||
|
vTaskResume( xSlaveHandle );
|
||||||
|
|
||||||
|
/* The slave has the higher priority so should now have executed and
|
||||||
|
blocked on the semaphore. */
|
||||||
|
#if( INCLUDE_eTaskGetState == 1 )
|
||||||
|
{
|
||||||
|
configASSERT( eTaskGetState( xSlaveHandle ) == eBlocked );
|
||||||
|
}
|
||||||
|
#endif /* INCLUDE_eTaskGetState */
|
||||||
|
|
||||||
|
/* This task should now have inherited the priority of the slave
|
||||||
|
task. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now wait a little longer than the time between ISR gives to also
|
||||||
|
obtain the ISR mutex. */
|
||||||
|
xOkToGiveMutex = pdTRUE;
|
||||||
|
if( xSemaphoreTake( xISRMutex, ( xInterruptGivePeriod * 2 ) ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
xOkToGiveMutex = pdFALSE;
|
||||||
|
|
||||||
|
/* Attempting to take again immediately should fail as the mutex is
|
||||||
|
already held. */
|
||||||
|
if( xSemaphoreTake( xISRMutex, intsemNO_BLOCK ) != pdFAIL )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should still be at the priority of the slave task. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give back the shared semaphore to ensure the priority is not disinherited
|
||||||
|
as the ISR mutex is still held. The higher priority slave task should run
|
||||||
|
before this task runs again. */
|
||||||
|
if( xSemaphoreGive( xMasterSlaveMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Should still be at the priority of the slave task as this task still
|
||||||
|
holds one semaphore (this is a simplification in the priority inheritance
|
||||||
|
mechanism. */
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemSLAVE_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Give back the ISR semaphore, which should result in the priority being
|
||||||
|
disinherited as it was the last mutex held. */
|
||||||
|
if( xSemaphoreGive( xISRMutex ) != pdPASS )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxTaskPriorityGet( NULL ) != intsemMASTER_PRIORITY )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the mutex ready for the next round. */
|
||||||
|
xQueueReset( xISRMutex );
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
static void vInterruptMutexSlaveTask( void *pvParameters )
|
static void vInterruptMutexSlaveTask( void *pvParameters )
|
||||||
{
|
{
|
||||||
/* Just to avoid compiler warnings. */
|
/* Just to avoid compiler warnings. */
|
||||||
|
@ -343,9 +433,76 @@ static void vInterruptMutexSlaveTask( void *pvParameters )
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void vInterruptCountingSemaphoreTask( void *pvParameters )
|
||||||
|
{
|
||||||
|
BaseType_t xCount;
|
||||||
|
const TickType_t xDelay = pdMS_TO_TICKS( intsemINTERRUPT_MUTEX_GIVE_PERIOD_MS ) * ( intsemMAX_COUNT + 1 );
|
||||||
|
|
||||||
|
( void ) pvParameters;
|
||||||
|
|
||||||
|
for( ;; )
|
||||||
|
{
|
||||||
|
/* Expect to start with the counting semaphore empty. */
|
||||||
|
if( uxQueueMessagesWaiting( ( QueueHandle_t ) xISRCountingSemaphore ) != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait until it is expected that the interrupt will have filled the
|
||||||
|
counting semaphore. */
|
||||||
|
xOkToGiveCountingSemaphore = pdTRUE;
|
||||||
|
vTaskDelay( xDelay );
|
||||||
|
xOkToGiveCountingSemaphore = pdFALSE;
|
||||||
|
|
||||||
|
/* Now it is expected that the counting semaphore is full. */
|
||||||
|
if( uxQueueMessagesWaiting( ( QueueHandle_t ) xISRCountingSemaphore ) != intsemMAX_COUNT )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( uxQueueSpacesAvailable( ( QueueHandle_t ) xISRCountingSemaphore ) != 0 )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulCountingSemaphoreLoops++;
|
||||||
|
|
||||||
|
/* Expect to be able to take the counting semaphore intsemMAX_COUNT
|
||||||
|
times. A block time of 0 is used as the semaphore should already be
|
||||||
|
there. */
|
||||||
|
xCount = 0;
|
||||||
|
while( xSemaphoreTake( xISRCountingSemaphore, 0 ) == pdPASS )
|
||||||
|
{
|
||||||
|
xCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xCount != intsemMAX_COUNT )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now raise the priority of this task so it runs immediately that the
|
||||||
|
semaphore is given from the interrupt. */
|
||||||
|
vTaskPrioritySet( NULL, configMAX_PRIORITIES - 1 );
|
||||||
|
|
||||||
|
/* Block to wait for the semaphore to be given from the interrupt. */
|
||||||
|
xOkToGiveCountingSemaphore = pdTRUE;
|
||||||
|
xSemaphoreTake( xISRCountingSemaphore, portMAX_DELAY );
|
||||||
|
xSemaphoreTake( xISRCountingSemaphore, portMAX_DELAY );
|
||||||
|
xOkToGiveCountingSemaphore = pdFALSE;
|
||||||
|
|
||||||
|
/* Reset the priority so as not to disturbe other tests too much. */
|
||||||
|
vTaskPrioritySet( NULL, tskIDLE_PRIORITY );
|
||||||
|
|
||||||
|
ulCountingSemaphoreLoops++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
void vInterruptSemaphorePeriodicTest( void )
|
void vInterruptSemaphorePeriodicTest( void )
|
||||||
{
|
{
|
||||||
static TickType_t xLastGiveTime = 0;
|
static TickType_t xLastGiveTime = 0;
|
||||||
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
TickType_t xTimeNow;
|
TickType_t xTimeNow;
|
||||||
|
|
||||||
/* No mutual exclusion on xOkToGiveMutex, but this is only test code (and
|
/* No mutual exclusion on xOkToGiveMutex, but this is only test code (and
|
||||||
|
@ -356,20 +513,30 @@ TickType_t xTimeNow;
|
||||||
configASSERT( xISRMutex );
|
configASSERT( xISRMutex );
|
||||||
if( xOkToGiveMutex != pdFALSE )
|
if( xOkToGiveMutex != pdFALSE )
|
||||||
{
|
{
|
||||||
|
/* Null is used as the second parameter in this give, and non-NULL
|
||||||
|
in the other gives for code coverage reasons. */
|
||||||
xSemaphoreGiveFromISR( xISRMutex, NULL );
|
xSemaphoreGiveFromISR( xISRMutex, NULL );
|
||||||
|
|
||||||
/* Second give attempt should fail. */
|
/* Second give attempt should fail. */
|
||||||
configASSERT( xSemaphoreGiveFromISR( xISRMutex, NULL ) == pdFAIL );
|
configASSERT( xSemaphoreGiveFromISR( xISRMutex, &xHigherPriorityTaskWoken ) == pdFAIL );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( xOkToGiveCountingSemaphore != pdFALSE )
|
||||||
|
{
|
||||||
|
xSemaphoreGiveFromISR( xISRCountingSemaphore, &xHigherPriorityTaskWoken );
|
||||||
}
|
}
|
||||||
xLastGiveTime = xTimeNow;
|
xLastGiveTime = xTimeNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove compiler warnings about the value being set but not used. */
|
||||||
|
( void ) xHigherPriorityTaskWoken;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* This is called to check that all the created tasks are still running. */
|
/* This is called to check that all the created tasks are still running. */
|
||||||
BaseType_t xAreInterruptSemaphoreTasksStillRunning( void )
|
BaseType_t xAreInterruptSemaphoreTasksStillRunning( void )
|
||||||
{
|
{
|
||||||
static uint32_t ulLastMasterLoopCounter = 0;
|
static uint32_t ulLastMasterLoopCounter = 0, ulLastCountingSemaphoreLoops = 0;
|
||||||
|
|
||||||
/* If the demo tasks are running then it is expected that the loop counters
|
/* If the demo tasks are running then it is expected that the loop counters
|
||||||
will have changed since this function was last called. */
|
will have changed since this function was last called. */
|
||||||
|
@ -380,6 +547,13 @@ static uint32_t ulLastMasterLoopCounter = 0;
|
||||||
|
|
||||||
ulLastMasterLoopCounter = ulMasterLoops;
|
ulLastMasterLoopCounter = ulMasterLoops;
|
||||||
|
|
||||||
|
if( ulLastCountingSemaphoreLoops == ulCountingSemaphoreLoops )
|
||||||
|
{
|
||||||
|
xErrorDetected = pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulLastCountingSemaphoreLoops = ulCountingSemaphoreLoops++;
|
||||||
|
|
||||||
/* Errors detected in the task itself will have latched xErrorDetected
|
/* Errors detected in the task itself will have latched xErrorDetected
|
||||||
to true. */
|
to true. */
|
||||||
|
|
||||||
|
|
|
@ -1269,7 +1269,8 @@ uint32_t ulVarToSend, ulValReceived;
|
||||||
*
|
*
|
||||||
* It is preferred that the macros xQueueSendFromISR(),
|
* It is preferred that the macros xQueueSendFromISR(),
|
||||||
* xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place
|
* xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place
|
||||||
* of calling this function directly.
|
* of calling this function directly. xQueueGenericGiveFromISR() is an
|
||||||
|
* equivalent for use by semaphores that don't actually copy any data.
|
||||||
*
|
*
|
||||||
* Post an item on a queue. It is safe to use this function from within an
|
* Post an item on a queue. It is safe to use this function from within an
|
||||||
* interrupt service routine.
|
* interrupt service routine.
|
||||||
|
@ -1333,6 +1334,7 @@ uint32_t ulVarToSend, ulValReceived;
|
||||||
* \ingroup QueueManagement
|
* \ingroup QueueManagement
|
||||||
*/
|
*/
|
||||||
BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
|
BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, const void * const pvItemToQueue, BaseType_t * const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition ) PRIVILEGED_FUNCTION;
|
||||||
|
BaseType_t xQueueGenericGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* queue. h
|
* queue. h
|
||||||
|
|
|
@ -605,7 +605,7 @@ typedef QueueHandle_t SemaphoreHandle_t;
|
||||||
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
|
* \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR
|
||||||
* \ingroup Semaphores
|
* \ingroup Semaphores
|
||||||
*/
|
*/
|
||||||
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK )
|
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGenericGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* semphr. h
|
* semphr. h
|
||||||
|
|
|
@ -1074,20 +1074,12 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||||
{
|
{
|
||||||
traceQUEUE_SEND_FROM_ISR( pxQueue );
|
traceQUEUE_SEND_FROM_ISR( pxQueue );
|
||||||
|
|
||||||
if( prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition ) != pdFALSE )
|
/* A task can only have an inherited priority if it is a mutex
|
||||||
{
|
holder - and if there is a mutex holder then the mutex cannot be
|
||||||
/* This is a special case that can only be executed if a task
|
given from an ISR. Therefore, unlike the xQueueGenericGive()
|
||||||
holds multiple mutexes and then gives the mutexes back in an
|
function, there is no need to determine the need for priority
|
||||||
order that is different to that in which they were taken. */
|
disinheritance here or to clear the mutex holder TCB member. */
|
||||||
if( pxHigherPriorityTaskWoken != NULL )
|
( void ) prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
|
||||||
{
|
|
||||||
*pxHigherPriorityTaskWoken = pdTRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mtCOVERAGE_TEST_MARKER();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The event list is not altered if the queue is locked. This will
|
/* The event list is not altered if the queue is locked. This will
|
||||||
be done when the queue is unlocked later. */
|
be done when the queue is unlocked later. */
|
||||||
|
@ -1194,6 +1186,160 @@ Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||||
}
|
}
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
|
BaseType_t xQueueGenericGiveFromISR( QueueHandle_t xQueue, BaseType_t * const pxHigherPriorityTaskWoken )
|
||||||
|
{
|
||||||
|
BaseType_t xReturn;
|
||||||
|
UBaseType_t uxSavedInterruptStatus;
|
||||||
|
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
|
||||||
|
|
||||||
|
configASSERT( pxQueue );
|
||||||
|
|
||||||
|
/* xQueueGenericSendFromISR() should be used in the item size is not 0. */
|
||||||
|
configASSERT( pxQueue->uxItemSize == 0 );
|
||||||
|
|
||||||
|
/* RTOS ports that support interrupt nesting have the concept of a maximum
|
||||||
|
system call (or maximum API call) interrupt priority. Interrupts that are
|
||||||
|
above the maximum system call priority are kept permanently enabled, even
|
||||||
|
when the RTOS kernel is in a critical section, but cannot make any calls to
|
||||||
|
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
|
||||||
|
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
|
||||||
|
failure if a FreeRTOS API function is called from an interrupt that has been
|
||||||
|
assigned a priority above the configured maximum system call priority.
|
||||||
|
Only FreeRTOS functions that end in FromISR can be called from interrupts
|
||||||
|
that have been assigned a priority at or (logically) below the maximum
|
||||||
|
system call interrupt priority. FreeRTOS maintains a separate interrupt
|
||||||
|
safe API to ensure interrupt entry is as fast and as simple as possible.
|
||||||
|
More information (albeit Cortex-M specific) is provided on the following
|
||||||
|
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
|
||||||
|
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
|
||||||
|
|
||||||
|
/* Similar to xQueueGenericSendFromISR() but used with semaphores where the
|
||||||
|
item size is 0. Don't directly wake a task that was blocked on a queue
|
||||||
|
read, instead return a flag to say whether a context switch is required or
|
||||||
|
not (i.e. has a task with a higher priority than us been woken by this
|
||||||
|
post). */
|
||||||
|
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
|
||||||
|
{
|
||||||
|
/* When the queue is used to implement a semaphore no data is ever
|
||||||
|
moved through the queue but it is still valid to see if the queue 'has
|
||||||
|
space'. */
|
||||||
|
if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
|
||||||
|
{
|
||||||
|
traceQUEUE_SEND_FROM_ISR( pxQueue );
|
||||||
|
|
||||||
|
/* A task can only have an inherited priority if it is a mutex
|
||||||
|
holder - and if there is a mutex holder then the mutex cannot be
|
||||||
|
given from an ISR. Therefore, unlike the xQueueGenericGive()
|
||||||
|
function, there is no need to determine the need for priority
|
||||||
|
disinheritance here or to clear the mutex holder TCB member. */
|
||||||
|
|
||||||
|
++( pxQueue->uxMessagesWaiting );
|
||||||
|
|
||||||
|
/* The event list is not altered if the queue is locked. This will
|
||||||
|
be done when the queue is unlocked later. */
|
||||||
|
if( pxQueue->xTxLock == queueUNLOCKED )
|
||||||
|
{
|
||||||
|
#if ( configUSE_QUEUE_SETS == 1 )
|
||||||
|
{
|
||||||
|
if( pxQueue->pxQueueSetContainer != NULL )
|
||||||
|
{
|
||||||
|
if( prvNotifyQueueSetContainer( pxQueue, queueSEND_TO_BACK ) == pdTRUE )
|
||||||
|
{
|
||||||
|
/* The semaphore is a member of a queue set, and
|
||||||
|
posting to the queue set caused a higher priority
|
||||||
|
task to unblock. A context switch is required. */
|
||||||
|
if( pxHigherPriorityTaskWoken != NULL )
|
||||||
|
{
|
||||||
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
|
||||||
|
{
|
||||||
|
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The task waiting has a higher priority so
|
||||||
|
record that a context switch is required. */
|
||||||
|
if( pxHigherPriorityTaskWoken != NULL )
|
||||||
|
{
|
||||||
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* configUSE_QUEUE_SETS */
|
||||||
|
{
|
||||||
|
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) == pdFALSE )
|
||||||
|
{
|
||||||
|
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
|
||||||
|
{
|
||||||
|
/* The task waiting has a higher priority so record that a
|
||||||
|
context switch is required. */
|
||||||
|
if( pxHigherPriorityTaskWoken != NULL )
|
||||||
|
{
|
||||||
|
*pxHigherPriorityTaskWoken = pdTRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mtCOVERAGE_TEST_MARKER();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* configUSE_QUEUE_SETS */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Increment the lock count so the task that unlocks the queue
|
||||||
|
knows that data was posted while it was locked. */
|
||||||
|
++( pxQueue->xTxLock );
|
||||||
|
}
|
||||||
|
|
||||||
|
xReturn = pdPASS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue );
|
||||||
|
xReturn = errQUEUE_FULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus ); //0.36
|
||||||
|
|
||||||
|
return xReturn;
|
||||||
|
}
|
||||||
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
|
BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeeking )
|
||||||
{
|
{
|
||||||
BaseType_t xEntryTimeSet = pdFALSE;
|
BaseType_t xEntryTimeSet = pdFALSE;
|
||||||
|
|
|
@ -3254,8 +3254,11 @@ TCB_t *pxTCB;
|
||||||
/* Only disinherit if no other mutexes are held. */
|
/* Only disinherit if no other mutexes are held. */
|
||||||
if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
|
if( pxTCB->uxMutexesHeld == ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
/* The holding task must be the running task to be able to give
|
/* A task can only have an inhertied priority if it holds
|
||||||
the mutex back. Remove the holding task from the ready list. */
|
the mutex. If the mutex is held by a task then it cannot be
|
||||||
|
given from an interrupt, and if a mutex is given by the
|
||||||
|
holding task then it must be the running state task. Remove
|
||||||
|
the holding task from the ready list. */
|
||||||
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
|
if( uxListRemove( &( pxTCB->xGenericListItem ) ) == ( UBaseType_t ) 0 )
|
||||||
{
|
{
|
||||||
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
taskRESET_READY_PRIORITY( pxTCB->uxPriority );
|
||||||
|
@ -3265,8 +3268,8 @@ TCB_t *pxTCB;
|
||||||
mtCOVERAGE_TEST_MARKER();
|
mtCOVERAGE_TEST_MARKER();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Disinherit the priority before adding the task into the new
|
/* Disinherit the priority before adding the task into the
|
||||||
ready list. */
|
new ready list. */
|
||||||
traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
|
traceTASK_PRIORITY_DISINHERIT( pxTCB, pxTCB->uxBasePriority );
|
||||||
pxTCB->uxPriority = pxTCB->uxBasePriority;
|
pxTCB->uxPriority = pxTCB->uxBasePriority;
|
||||||
|
|
||||||
|
@ -3279,7 +3282,11 @@ TCB_t *pxTCB;
|
||||||
/* Return true to indicate that a context switch is required.
|
/* Return true to indicate that a context switch is required.
|
||||||
This is only actually required in the corner case whereby
|
This is only actually required in the corner case whereby
|
||||||
multiple mutexes were held and the mutexes were given back
|
multiple mutexes were held and the mutexes were given back
|
||||||
in an order different to that in which they were taken. */
|
in an order different to that in which they were taken.
|
||||||
|
If a context switch did not occur when the first mutex was
|
||||||
|
returned, even if a task was waiting on it, then a context
|
||||||
|
switch should occur when the last mutex is returned whether
|
||||||
|
a task is waiting on it or not. */
|
||||||
xReturn = pdTRUE;
|
xReturn = pdTRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue