diff options
| author | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2009-01-19 13:31:37 +0000 | 
|---|---|---|
| committer | gdisirio <gdisirio@35acf78f-673a-0410-8e92-d51de3d6d3f4> | 2009-01-19 13:31:37 +0000 | 
| commit | 0810f1daac3c33d194d573d82ec436021e3e7255 (patch) | |
| tree | 41909345afc1c1e949a18119563243b9adfc8648 /docs/src | |
| parent | f8b4fca89a8dd31989a3d21e4c6fb4175aba4110 (diff) | |
| download | ChibiOS-0810f1daac3c33d194d573d82ec436021e3e7255.tar.gz ChibiOS-0810f1daac3c33d194d573d82ec436021e3e7255.tar.bz2 ChibiOS-0810f1daac3c33d194d573d82ec436021e3e7255.zip  | |
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@643 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'docs/src')
| -rw-r--r-- | docs/src/atomic.dox | 50 | ||||
| -rw-r--r-- | docs/src/saveram.dox | 66 | 
2 files changed, 116 insertions, 0 deletions
diff --git a/docs/src/atomic.dox b/docs/src/atomic.dox new file mode 100644 index 000000000..0f678448b --- /dev/null +++ b/docs/src/atomic.dox @@ -0,0 +1,50 @@ +/**
 + * @page article_atomic Invoking multiple primitives as a single atomic operation
 + * @{
 + * It is often necessary to invoke multiple operations involving a
 + * reschedulation as a single atomic operation.<br>
 + * ChibiOS/RT already implements APIs that perform complex operations, as
 + * example the API @p chSemSignalWait() performs two operations atomically.<br>
 + * If more complex operations are required in your application then it is
 + * possible to build macro-operations, see the following example:
 + * @code
 +  chSysLock();
 + 
 +  chSemSignalI(&sem1);
 +  chSemSignalI(&sem2);
 +  if (tp != NULL) {
 +    chThdResumeI(tp);
 +    tp = NULL;
 +  }
 +  chSchRescheduleS();
 + 
 +  chSysUnlock();
 + * @endcode
 + * The above example performs a signal operation on two semaphores, optionally
 + * resumes a thread, and performs a final reschedulation. The three operations
 + * are performed atomically.<br>
 + * An hypotetical @p chSemSignalSignalWait() operation could be implemented as
 + * follow:
 + * @code
 +  chSysLock();
 + 
 +  chSemSignalI(&sem1);
 +  chSemSignalI(&sem2);
 +  /*
 +   * The "if" is required because the chSemWaitS() does not always internally
 +   * reschedule.
 +   */
 +  if (chSemGetCounter(&sem3) <= 0)
 +    chSemWaitS(&Sem3);
 +  else {
 +    chSemFastWaitS(&sem3);
 +    chSchRescheduleS();
 +  }
 + 
 +  chSysUnlock();
 + * @endcode
 + * In general multiple I-Class APIs can be included and the block is terminated
 + * by an S-Class API that performs a reschedulation. Optionally a
 + * @p chSchRescheduleS() is present at the very end of the block.
 + */
 +/** @} */
 diff --git a/docs/src/saveram.dox b/docs/src/saveram.dox new file mode 100644 index 000000000..fec810c81 --- /dev/null +++ b/docs/src/saveram.dox @@ -0,0 +1,66 @@ +/**
 + * @page article_saveram Saving RAM by declaring thread functions "noreturn"
 + * @{
 + * One of the problems, when writing embedded multi-threaded applications,
 + * is that the thread functions do save the registers in the function
 + * entry code even if the system does not require it, exiting such
 + * a function would terminate the thread so there is no need to preserve
 + * the register values. This can waste tens of bytes for each thread.<br>
 + * Consider the following code: 
 + * @code
 +#include <ch.h>
 + 
 +static WORKING_AREA(waMyThread, 64);
 + 
 +static t_msg MyThread(void *arg) {
 + 
 +  while (!chThdShoudTerminate()) {
 +    /* Do thread inner work */
 +  }
 +  return 1;
 +}
 + 
 +main() {
 +  chSysInit();
 +  ...
 +  chThdCreate(NORMALPRIO, 0, waMyThread, sizeof(waMyThread), MyThread, NULL);
 +  ...
 +  chSysPause();
 +}
 + * @endcode
 + * The resulting ASM code for the thread function would be something like this:
 + * @code
 +MyThread:
 +        stmfd   sp!, {r4, r5, r6, lr}
 +        ...
 +        ldmfd   sp!, {r4, r5, r6, pc}
 + * @endcode
 + * Being that function a thread there is no need to save those registers, in
 + * embedded applications often the RAM is a scarce resource. That space can be
 + * saved by modifying the code as follow, using some advanced GCC extensions: 
 + * @code
 +#include <ch.h>
 + 
 +static BYTE8 waMyThread[UserStackSize(64)];
 + 
 +__attribute__((noreturn)) void MyThread(void *arg) {
 + 
 +  while (!chThdShoudTerminate()) {
 +    /* Do thread inner work */
 +  }
 +  chThdExit(1);
 +}
 + 
 +main() {
 +  chSysInit();
 +  ...
 +  chThdCreate(NORMALPRIO, 0, waMyThread, sizeof(waMyThread), (t_tfunc)MyThread, NULL);
 +  ...
 +  chSysPause();
 +}
 + * @endcode
 + * This will make GCC believe that the function cannot return and there is no
 + * need to save registers. The code will be a bit less readable and less
 + * portable on other compilers however.
 + */
 +/** @} */
  | 
