git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@233 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2008-03-14 16:08:11 +00:00
parent 721061da2a
commit cd679c0920
3 changed files with 486 additions and 9 deletions

View File

@ -59,8 +59,8 @@
* @section naming Naming Conventions * @section naming Naming Conventions
* ChibiOS/RT APIs are all named following this convention: * ChibiOS/RT APIs are all named following this convention:
* \a ch\<group\>\<action\>\<suffix\>(). * \a ch\<group\>\<action\>\<suffix\>().
* The possible groups are: \a Sys, \a Sch, \a VT, \a Thd, \a Sem, \a Evt, * The possible groups are: \a Sys, \a Sch, \a VT, \a Thd, \a Sem, \a Mtx,
* \a Msg, \a IQ, \a OQ, \a HQ,\a FDD, \a HDD. * \a Evt, \a Msg, \a IQ, \a OQ, \a HQ,\a FDD, \a HDD, \a Dbg.
* The suffix is not present for normal APIs but can be one of * The suffix is not present for normal APIs but can be one of
* the following: "I" for APIs meant to be invoked from an interrupt handler * the following: "I" for APIs meant to be invoked from an interrupt handler
* or within the system mutex zone but not from user code, "S" for APIs only * or within the system mutex zone but not from user code, "S" for APIs only
@ -79,6 +79,10 @@
* Note that the currently running thread is not in the ready list, the list * Note that the currently running thread is not in the ready list, the list
* only contains the threads ready to be executed but still actually waiting. * only contains the threads ready to be executed but still actually waiting.
* *
* @section states Threads States Diagram
* The image shows how threads can change their state in ChibiOS/RT.<br>
* @image html states.png
*
* @section warea Thread Working Area * @section warea Thread Working Area
* Each thread has its own stack, a Thread structure and a registers dump * Each thread has its own stack, a Thread structure and a registers dump
* structure. All the structures are allocated into a "Thread working area", * structure. All the structures are allocated into a "Thread working area",
@ -87,7 +91,6 @@
* have as many threads you want as long you have enough available RAM * have as many threads you want as long you have enough available RAM
* memory. The threads do not use any memory outside the allocated working * memory. The threads do not use any memory outside the allocated working
* area.<br> * area.<br>
* @image html workspace.png * @image html workspace.png
* <br> * <br>
* Note that the registers dump is only present when the Thread is not * Note that the registers dump is only present when the Thread is not

474
docs/img/states.svg Normal file
View File

@ -0,0 +1,474 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="350"
height="500"
id="svg2160"
sodipodi:version="0.32"
inkscape:version="0.45.1"
version="1.0"
sodipodi:docbase="C:\Progetti\ChibiOS-RT\docs\img"
sodipodi:docname="states.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="C:\Progetti\ChibiOS-RT\docs\img\states.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs2162">
<marker
inkscape:stockid="Arrow1Mstart"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mstart"
style="overflow:visible">
<path
id="path10108"
d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(0.4,0,0,0.4,4,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Mend"
orient="auto"
refY="0"
refX="0"
id="Arrow1Mend"
style="overflow:visible">
<path
id="path3299"
d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
transform="matrix(-0.4,0,0,-0.4,-4,0)" />
</marker>
<linearGradient
inkscape:collect="always"
id="linearGradient3224">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop3226" />
<stop
style="stop-color:#000000;stop-opacity:0"
offset="1"
id="stop3228" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3224"
id="linearGradient3230"
x1="199.30756"
y1="341.00253"
x2="348.78439"
y2="341.00253"
gradientUnits="userSpaceOnUse" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2"
inkscape:cx="198.03694"
inkscape:cy="300.90085"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
width="350px"
height="500px"
gridspacingx="5px"
gridspacingy="5px"
inkscape:grid-points="false"
inkscape:grid-bbox="true"
gridtolerance="10"
inkscape:object-paths="true"
objecttolerance="1"
guidetolerance="1"
inkscape:window-width="993"
inkscape:window-height="870"
inkscape:window-x="139"
inkscape:window-y="66" />
<metadata
id="metadata2165">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Livello 1"
inkscape:groupmode="layer"
id="layer1">
<flowRoot
xml:space="preserve"
id="flowRoot3188"
transform="translate(-3.1464844,-407.84915)"><flowRegion
id="flowRegion3190"><rect
id="rect3192"
width="97.01046"
height="17.563538"
x="2.9895365"
y="332.43646" /></flowRegion><flowPara
id="flowPara3196">Workspace top</flowPara></flowRoot> <flowRoot
xml:space="preserve"
id="flowRoot3208"
transform="translate(-99.457031,-40.853054)"
style="fill:url(#linearGradient3230);fill-opacity:1"><flowRegion
id="flowRegion3210"
style="fill:url(#linearGradient3230);fill-opacity:1"><rect
id="rect3212"
width="139.31241"
height="50.822121"
x="99.850525"
y="299.55157"
style="fill:url(#linearGradient3230);fill-opacity:1" /></flowRegion><flowPara
id="flowPara3214"
style="fill:url(#linearGradient3230);fill-opacity:1">Thread Structure</flowPara></flowRoot> <path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.6978516px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 100.34893,-51.570166 C 109.31485,-51.570166 109.31485,-51.570166 109.31485,-51.570166"
id="path3491" />
<flowRoot
xml:space="preserve"
id="flowRoot2216"
transform="translate(31.53125,-269.98977)"
style="font-size:12px"><flowRegion
id="flowRegion2218"><rect
id="rect2220"
width="82.01046"
height="17.563538"
x="2.9895365"
y="332.43646"
style="font-size:12px" /></flowRegion><flowPara
id="flowPara2222"
style="font-size:12px">chThdCreate()</flowPara></flowRoot> <g
id="g5159"
transform="translate(-4.4339553e-6,-30.000001)"
style="font-size:12px">
<path
transform="matrix(4.1122708,0,0,2.4522717,-286.36579,142.69295)"
d="M 96 49.875 A 8.125 13.625 0 1 1 79.75,49.875 A 8.125 13.625 0 1 1 96 49.875 z"
sodipodi:ry="13.625"
sodipodi:rx="8.125"
sodipodi:cy="49.875"
sodipodi:cx="87.875"
id="path2230"
style="font-size:3.77881908px;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<flowRoot
transform="translate(-1.9335937,102.06296)"
id="flowRoot5151"
xml:space="preserve"
style="font-size:12px"><flowRegion
id="flowRegion5153"><rect
y="156.5"
x="53"
height="13"
width="53"
id="rect5155"
style="font-size:12px" /></flowRegion><flowPara
id="flowPara5157">Running</flowPara></flowRoot> </g>
<g
id="g5166"
transform="translate(174.99999,-30.000001)"
style="font-size:12px">
<path
transform="matrix(4.1122708,0,0,2.4522717,-286.36579,142.69295)"
d="M 96 49.875 A 8.125 13.625 0 1 1 79.75,49.875 A 8.125 13.625 0 1 1 96 49.875 z"
sodipodi:ry="13.625"
sodipodi:rx="8.125"
sodipodi:cy="49.875"
sodipodi:cx="87.875"
id="path5168"
style="font-size:3.77881908px;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<flowRoot
transform="translate(6.0566406,100.94773)"
id="flowRoot5170"
xml:space="preserve"
style="font-size:12px"><flowRegion
id="flowRegion5172"><rect
y="156.5"
x="53"
height="13"
width="53"
id="rect5174"
style="font-size:12px" /></flowRegion><flowPara
id="flowPara5176">Ready</flowPara></flowRoot> <use
x="0"
y="0"
xlink:href="#path5168"
id="use5178"
width="500"
height="500"
style="font-size:12px" />
<use
x="0"
y="0"
xlink:href="#flowRoot5170"
id="use5180"
width="500"
height="500"
style="font-size:12px" />
</g>
<flowRoot
xml:space="preserve"
id="flowRoot5198"
transform="translate(183.06641,-102.93704)"><flowRegion
id="flowRegion5200"><rect
id="rect5202"
width="53"
height="13"
x="53"
y="156.5" /></flowRegion><flowPara
id="flowPara5204">SuspendedSus</flowPara></flowRoot> <g
id="g5223"
transform="translate(175,-190)"
style="font-size:12px">
<g
id="g5235"
style="font-size:12px">
<path
sodipodi:type="arc"
style="font-size:3.77881908px;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path5225"
sodipodi:cx="87.875"
sodipodi:cy="49.875"
sodipodi:rx="8.125"
sodipodi:ry="13.625"
d="M 96 49.875 A 8.125 13.625 0 1 1 79.75,49.875 A 8.125 13.625 0 1 1 96 49.875 z"
transform="matrix(4.1122708,0,0,2.4522717,-286.36579,142.69295)" />
<flowRoot
xml:space="preserve"
id="flowRoot5227"
transform="translate(-7.9003806,102.20945)"
style="font-size:12px"><flowRegion
id="flowRegion5229"><rect
id="rect5231"
width="62"
height="13.5"
x="53"
y="156.5"
style="font-size:12px" /></flowRegion><flowPara
id="flowPara5233">Suspended</flowPara></flowRoot> </g>
</g>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 120.5,72.75 L 210.5,72.75"
id="path6213" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 99.042893,80.5 L 219.04289,200.5"
id="path7186" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 75,85 L 75,190"
id="path8157" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 116.25,232.75 L 206.25,232.75"
id="path9128" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 95.957107,199.04289 L 205.95711,89.0429"
id="path10297" />
<g
id="g11268"
transform="translate(175,155)"
style="font-size:12px">
<path
transform="matrix(4.1122708,0,0,2.4522717,-286.36579,142.69295)"
d="M 96 49.875 A 8.125 13.625 0 1 1 79.75,49.875 A 8.125 13.625 0 1 1 96 49.875 z"
sodipodi:ry="13.625"
sodipodi:rx="8.125"
sodipodi:cy="49.875"
sodipodi:cx="87.875"
id="path11270"
style="font-size:3.77881908px;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<flowRoot
transform="translate(-1.9335937,102.06296)"
id="flowRoot11272"
xml:space="preserve"
style="font-size:12px"><flowRegion
id="flowRegion11274"><rect
y="156.5"
x="53"
height="13"
width="53"
id="rect11276"
style="font-size:12px" /></flowRegion><flowPara
id="flowPara11278">Sleeping</flowPara></flowRoot> </g>
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="144.6875"
y="303.31641"
id="text12251"><tspan
sodipodi:role="line"
id="tspan12253"
x="144.6875"
y="303.31641">chSchGoSleepS()</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 100,265 L 220,380"
id="path12255" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 209.5,390.94191 L 89.5,275.94191"
id="path13226" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="98"
y="350.82422"
id="text14197"><tspan
sodipodi:role="line"
id="tspan14199"
x="98"
y="350.82422">chSchWakeupS()</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 250,380 L 250,280"
id="path14201" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="253"
y="325.82422"
id="text15172"><tspan
sodipodi:role="line"
id="tspan15174"
x="253"
y="325.82422">chSchWakeupS()</tspan><tspan
sodipodi:role="line"
x="253"
y="335.82422"
id="tspan15176">chSchReadyI()</tspan></text>
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="124.6875"
y="243.31641"
id="text15180"><tspan
sodipodi:role="line"
id="tspan15182"
x="124.6875"
y="243.31641">chSchRescheduleS()</tspan><tspan
sodipodi:role="line"
x="124.6875"
y="253.31641"
id="tspan15184">chSchDoRescheduleI()</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 250,115 L 250,195"
id="path17124" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="258"
y="145.82422"
id="text18099"><tspan
sodipodi:role="line"
id="tspan18101"
x="258"
y="145.82422">chSchWakeupS()</tspan><tspan
sodipodi:role="line"
x="258"
y="155.82422"
id="tspan18103">chSchReadyI()</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Mstart);marker-end:none;stroke-opacity:1"
d="M 105.95711,209.04289 L 215.95711,99.042893"
id="path18105" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="134.6875"
y="93.316406"
id="text20045"><tspan
sodipodi:role="line"
id="tspan20047"
x="134.6875"
y="93.316406">chSchGoSleepS()</tspan></text>
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="118"
y="205.82422"
id="text20049"><tspan
sodipodi:role="line"
id="tspan20051"
x="118"
y="205.82422">chSchWakeupS()</tspan></text>
<path
sodipodi:type="arc"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path20055"
sodipodi:cx="87.875"
sodipodi:cy="49.875"
sodipodi:rx="8.125"
sodipodi:ry="13.625"
d="M 96 49.875 A 8.125 13.625 0 1 1 79.75,49.875 A 8.125 13.625 0 1 1 96 49.875 z"
transform="matrix(4.1122708,0,0,2.4522717,-286.36579,297.69295)" />
<flowRoot
xml:space="preserve"
id="flowRoot20057"
transform="translate(6.0566362,255.94773)"><flowRegion
id="flowRegion20059"><rect
id="rect20061"
width="53"
height="13"
x="53"
y="156.5" /></flowRegion><flowPara
id="flowPara20063">Ready</flowPara></flowRoot> <use
height="500"
width="500"
id="use20065"
xlink:href="#path5168"
y="0"
x="0"
transform="translate(-4.4339552e-6,155)" />
<text
xml:space="preserve"
style="font-size:12px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="57.498047"
y="423.58984"
id="text20088"><tspan
sodipodi:role="line"
id="tspan20090"
x="57.498047"
y="423.58984">Exited</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-end:url(#Arrow1Mend);stroke-opacity:1"
d="M 75,275 C 75,380 75,380 75,380"
id="path20102" />
<text
xml:space="preserve"
style="font-size:8px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="6.203125"
y="320.82422"
id="text21073"><tspan
sodipodi:role="line"
id="tspan21075"
x="6.203125"
y="320.82422">chSchGoSleepS()</tspan><tspan
sodipodi:role="line"
x="6.203125"
y="330.82422"
id="tspan21077">chThdExit()</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -26,8 +26,6 @@
***************************************************************************** *****************************************************************************
Current ports under ./demos: Current ports under ./demos:
Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
MinGW version.
ARM7-LPC214x-GCC - ChibiOS/RT port for ARM7 LPC2148, the demo targets ARM7-LPC214x-GCC - ChibiOS/RT port for ARM7 LPC2148, the demo targets
the Olimex LPC-P2148 board. This port can be easily the Olimex LPC-P2148 board. This port can be easily
modified for any processor into the LPC2000 family or modified for any processor into the LPC2000 family or
@ -39,11 +37,12 @@ ARM7-AT91SAM7X-GCC - Port for Atmel AT91SAM7X256. The demo program targets
ARMCM3-ST32F103-GCC - ARM Cortex-M3 port, work in progress, not complete ARMCM3-ST32F103-GCC - ARM Cortex-M3 port, work in progress, not complete
yet. The demo will target the Olimex STM32-P103 yet. The demo will target the Olimex STM32-P103
board. board.
AVR-AVRmega128-GCC - Port on AVRmega128, experimental. A special thanks to AVR-AVRmega128-GCC - Port on AVRmega128. A special thanks to Vladimir for
Vladimir for the work done on the AVR port. The demo the work done on the AVR port. The demo program
program targets the Olimex AVR-MT-128 mini terminal targets the Olimex AVR-MT-128 mini terminal board.
board.
AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not tested on hardware yet. AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not tested on hardware yet.
Win32-MinGW - ChibiOS/RT simulator and demo into a WIN32 process,
MinGW version.
***************************************************************************** *****************************************************************************
*** Plans *** *** Plans ***
@ -75,6 +74,7 @@ AVR-AT90CANx-GCC - Port on AVR AT90CAN128, not tested on hardware yet.
LPC21xx demos. This saves significant program space. LPC21xx demos. This saves significant program space.
- Started work on ARM Cortex-M3 architecture. The target chip is the ST32F103 - Started work on ARM Cortex-M3 architecture. The target chip is the ST32F103
on a Olimex STM32-P103 board. on a Olimex STM32-P103 board.
- Added a threads state diagram to the documentation.
- Various fixes to the doxigen documentation. - Various fixes to the doxigen documentation.
*** 0.6.0 *** *** 0.6.0 ***