femtoos_headers/femtoos_port.h

Go to the documentation of this file.
00001 /*
00002  * Femto OS v 0.91 - Copyright (C) 2008-2009 Ruud Vlaming
00003  *
00004  * This file is part of the Femto OS distribution.
00005  *
00006  * This program is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, version 3 of the License.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * Please note that, due to the GPLv3 license, for application of this
00019  * work and/or combined work in embedded systems special obligations apply.
00020  * If these are not to you liking, please know the Femto OS is dual
00021  * licensed. A commercial license and support are available.
00022  * See http://www.femtoos.org/ for details.
00023  */
00024 
00025 #ifndef FEMTOOS_PORT_H
00026 #define FEMTOOS_PORT_H
00027 
00039 #include "femtoos_globals.h"
00040 #include "femtoos_constants.h"
00041 
00047 #define portFlashReadByte(byteType, byteVar) ((byteType) pgm_read_byte(&(byteVar)))
00048 
00049 
00055 #define portFlashReadWord(wordType, wordVar) ((wordType) pgm_read_word(&(wordVar)))
00056 
00057 
00063 #define portFlashReadStruc(strucType, strucPointer, strucFieldType, strucField) ((strucFieldType) pgm_read_word(&(((strucType *)pgm_read_word(&strucPointer))->strucField)))
00064 
00065 
00072 #define portInitCPUStatusRegister   0x00
00073 
00074 
00084 #if (cfgSysSqueezeState == cfgTrue) && (cfgIntTickTrack == cfgTrue)
00085   #define portInitModeInterruptLoc     (0)
00086   #define portInitGlobalInterruptLoc   (SREG_H)
00087   #define portInitTickInterruptLoc     (SREG_I)
00088 #elif (cfgSysSqueezeState == cfgTrue) && (cfgIntTickTrack == cfgFalse)
00089   #define portInitModeInterruptLoc     (0)
00090   #define portInitGlobalInterruptLoc   (SREG_H)
00091   #define portInitTickInterruptLoc     (0)
00092 #elif (cfgSysSqueezeState == cfgFalse) && (cfgIntTickTrack == cfgTrue)
00093   #define portInitModeInterruptLoc     (SREG_I)
00094   #define portInitGlobalInterruptLoc   (SREG_H)
00095   #define portInitTickInterruptLoc     (SREG_T)
00096 #elif (cfgSysSqueezeState == cfgFalse) && (cfgIntTickTrack == cfgFalse)
00097   #define portInitModeInterruptLoc     (0)
00098   #define portInitGlobalInterruptLoc   (SREG_I)
00099   #define portInitTickInterruptLoc     (0)
00100 #endif
00101 
00102 
00108 #define portBarrier()                        asm volatile ( "" ::: "memory" )
00109 
00114 #define portNop()                            asm volatile ( "nop" :: )
00115 
00116 
00123 #define portEnableGlobalInterrupts()         asm volatile ( "sei" ::: "memory" )
00124 
00125 
00132 #define portDisableGlobalInterrupts()        asm volatile ( "cli" ::: "memory" )
00133 
00134 
00142 #if (cfgSysSqueezeState == cfgFalse)
00143   /* The devAuxSysRegBit is assumed to be zero upon entry, signaling per default that the
00144    * interrupts are switched off. The value of the I bit is copied to the ARB bit. */
00145   #define portResqueGlobalInterruptState()            \
00146     asm volatile ( "brid 67f                \n\t"     \
00147                    "cli                     \n\t"     \
00148                    "sbi %[_ASR_],%[_ARB_]   \n\t"     \
00149                    "67:          " ::                 \
00150                    [_ARB_]       "i" (devAuxSysRegBit),     \
00151                    [_ASR_]       "i" (_SFR_IO_ADDR(devAuxSysReg)))
00152 #else
00153   /* We signal with the H bit being zero that we originate from a manual Yield. The old
00154    * value of the I bit is copied to the H bit and the I bit is cleaned. The code below is
00155    * tricky. First we clean the H bit, and subsequently test if interrupts are enabled. If
00156    * so we must set the H bit and clean the I bit. The rest is unimportant, since we came from
00157    * a manual call. To save we first clean H and test for I afterwards. But what if an interrupt
00158    * comes after cleaning H and before the test? H could be set again when we return, since
00159    * the H bit may be not conserved due to our own approach. The point is, it does not matter. If
00160    * I was cleaned before, interrupts are not possible so H stays reset, and if I was not,
00161    * H will be set anyway. So we do not fear an interrupt here.
00162    * */
00163   #define portResqueGlobalInterruptState()                        \
00164     asm volatile ( "clh           \n\t"      /* Clear H bit  */   \
00165                    "brid 67f      \n\t"                           \
00166                    "cli           \n\t"      /* Clean I bit  */   \
00167                    "seh           \n\t"      /* Set H bit    */   \
00168                    "67:         " ::                              \
00169                    [_Hb_]       "i" (preBitSet1(0x00,SREG_H)) )
00170 #endif
00171 
00172 
00182 #if (cfgSysSqueezeState == cfgFalse)
00183   #define portResqueGlobalInterruptActive()            \
00184     asm volatile ( "sbi %[_ASR_],%[_ARB_]" ::          \
00185                    [_ARB_]  "i" (devAuxSysRegBit),     \
00186                    [_ASR_]  "i" (_SFR_IO_ADDR(devAuxSysReg)))
00187 #else
00188     /* We only need to set the H bit to signal we come from an interrupt. The interrupt is
00189      * already disabled. The original status of the H bit is permanently lost. */
00190   #define portResqueGlobalInterruptActive()  \
00191     asm volatile ( "seh " :: )
00192 #endif
00193 
00194 
00199 void portReboot(void) __attribute__ ( ( naked, noreturn ) ) ;
00200 
00201 
00210 #define portFSWriteReady() ((devEECR & (1 << devEEPE)) == 0)
00211 
00212 
00223 void portFSWriteByte(Taddress pAddress, Tbyte bValue);
00224 
00225 
00230 Tbyte portFSReadByte(Taddress pAddress);
00231 
00232 
00239 #define portGetFullStack(field) \
00240   asm volatile ( "in %A0,__SP_L__     \n\t" \
00241                  "in %B0,__SP_H__   " :"=r" (field) : )
00242 
00249 #define portGetReducedStack(field) \
00250   asm volatile ( "in %A0,__SP_L__     \n\t" \
00251                  "ldi %B0, 0x00   " :"=r" (field) : )
00252 
00259 #define portSetFullStack(field) \
00260   asm volatile ( "out __SP_L__, %A0     \n\t" \
00261                  "out __SP_H__, %B0 " : : "r" (field) : "memory" )
00262 
00268 #define portSetReducedStack(field) \
00269   asm volatile ( "out __SP_L__, %A0 " : : "r" (field) : "memory")
00270 
00271 
00277 #define portSwapNibbles(field)  \
00278   asm volatile("swap %0" : "=r" (field) : "0" (field));
00279 
00280 
00286 #if (devFLASHsize <= 0x1000UL)
00287   #define defJUMP  "rjmp"
00288   #define defCALL  "rcall"
00289 #else
00290   #define defJUMP  "jmp"
00291   #define defCALL  "call"
00292 #endif
00293 
00294 #define portJump(destination) asm volatile ( defJUMP " " #destination :: )
00295 
00305 #define portEventRegister devAuxEventReg
00306 
00312 #define defEventRegisterAtomicOperation defAuxEventRegLowIO
00313 #define defEqualAuxiliaryRegisters      preEqualMacros(devAuxSysReg,devAuxEventReg)
00314 
00326 #if (devCLKPCE == cfgUndefined)
00327   #if (cfgSysClockDivider != 1)
00328     #error "cfgSysClockDivider can only be 1 for this device (no clock prescaler)."
00329   #endif
00330 #else
00331   #if (cfgSysClockDivider == 1)
00332     #define defClockPrescaleBits 0x00
00333   #elif (cfgSysClockDivider == 2)
00334     #define defClockPrescaleBits 0x01
00335   #elif (cfgSysClockDivider == 4)
00336     #define defClockPrescaleBits 0x02
00337   #elif (cfgSysClockDivider == 8)
00338     #define defClockPrescaleBits 0x03
00339   #elif (cfgSysClockDivider == 16)
00340     #define defClockPrescaleBits 0x04
00341   #elif (cfgSysClockDivider == 32)
00342     #define defClockPrescaleBits 0x05
00343   #elif (cfgSysClockDivider == 64)
00344     #define defClockPrescaleBits 0x06
00345   #elif (cfgSysClockDivider == 128)
00346     #define defClockPrescaleBits 0x07
00347   #elif (cfgSysClockDivider == 256)
00348     #define defClockPrescaleBits 0x08
00349   #else
00350     #error "cfgSysClockDivider was not recognized for this device."
00351   #endif
00352 #endif
00353 
00354 
00362 #define defTimerPrescaleBits    (DefPrescaler(cfgSysSubTickDivider))
00363 
00368 #if defined(devPrescale_1024)
00369   #define defDelayPrescaleBits devPrescale_1024
00370 #elif defined(devPrescale_512)
00371   #define defDelayPrescaleBits devPrescale_512
00372 #elif defined(devPrescale_256)
00373   #define defDelayPrescaleBits devPrescale_256
00374 #elif defined(devPrescale_128)
00375   #define defDelayPrescaleBits devPrescale_128
00376 #elif defined(devPrescale_64)
00377   #define defDelayPrescaleBits devPrescale_64
00378 #elif defined(devPrescale_32)
00379   #define defDelayPrescaleBits devPrescale_32
00380 #elif defined(devPrescale_16)
00381   #define defDelayPrescaleBits devPrescale_16
00382 #elif defined(devPrescale_8)
00383   #define defDelayPrescaleBits devPrescale_8
00384 #elif defined(devPrescale_4)
00385   #define defDelayPrescaleBits devPrescale_4
00386 #elif defined(devPrescale_2)
00387   #define defDelayPrescaleBits devPrescale_2
00388 #elif defined(devPrescale_1)
00389   #define defDelayPrescaleBits devPrescale_1
00390 #else
00391   #error "No prescaler value for the delay loop possible."
00392 #endif
00393 
00400 #if (cfgNumSleepPeriod < 384)
00401   #define defWatchDogPrescaleBits  0x04
00402   #define defSleepRealPeriod        256
00403 #elif (cfgNumSleepPeriod < 768)
00404   #define defWatchDogPrescaleBits  0x05
00405   #define defSleepRealPeriod        512
00406 #elif (cfgNumSleepPeriod < 1536)
00407   #define defWatchDogPrescaleBits  0x06
00408   #define defSleepRealPeriod       1024
00409 #elif (cfgNumSleepPeriod < 3072) || (devWDP3 == cfgUndefined)
00410   #define defWatchDogPrescaleBits  0x07
00411   #define defSleepRealPeriod       2048
00412 #elif (cfgNumSleepPeriod < 6144)
00413   #define defWatchDogPrescaleBits  0x08
00414   #define defSleepRealPeriod       4096
00415 #else
00416   #define defWatchDogPrescaleBits  0x09
00417   #define defSleepRealPeriod       8192
00418 #endif
00419 
00420 
00428 void portEnterGlobalInterrupts(void) __attribute__ ( ( naked, noinline ) );
00429 
00430 
00438 void portExitGlobalInterrupts(void)  __attribute__ ( ( naked, noinline ) );
00439 
00440 
00448 void portEnterTickInterrupts(void) __attribute__ ( ( naked, noinline ) );
00449 
00450 
00458 void portExitTickInterrupts(void) __attribute__ ( ( naked, noinline ) );
00459 
00468 void portDisableTickInterrupts(void) __attribute__ ( ( naked, noinline ) );
00469 
00470 
00479 void portEnableTickInterrupts(void)__attribute__ ( ( naked, noinline ) );
00480 
00486 #if (defSysGCCstartup == cfgReplace)
00487   #define portInit()
00488 #else
00489   void portInit(void);
00490 #endif
00491 
00492 
00500 void portTrace(Tuint08 uiEvent);
00501 
00502 
00509 void portIdle(void)  __attribute__ ( ( noreturn, naked ) );
00510 
00511 
00529 void portSleep(Tuint08 uiTickBlockMinDelay);
00530 
00542 void portShowError(Tuint08 uiMessage, Tuint08 uiCallId, Tuint08 uiInfoTask);
00543 
00550 void portShowReset(void);
00551 
00552 
00559 #if (true)
00560   #define portInitContext(TaskStart,StackTop,RegisterUse,InterruptStart) privInitContext(TaskStart,StackTop,RegisterUse,InterruptStart)
00561 #else
00562   /* This is your prototype. Specify a function which intializes the context of each
00563    * task and sets the return addresses.  */
00564   Taddress portInitContext(Taddress pTaskStart, Taddress pStackTop, Tuint08 uiRegisterCount, Tuint08 uiInterruptStart);
00565 #endif
00566 
00567 
00575 void portEnterISR(void)  __attribute__ ( ( naked, noinline, used ) );
00576 
00577 
00584 void portBeginISR(void)  __attribute__ ( ( naked, noinline, used ) );
00585 
00586 
00593 void portReturnISR(void)  __attribute__ ( ( naked, noinline, used ) );
00594 
00595 
00602 void portYieldISR(void)  __attribute__ ( ( naked, noinline, used ) );
00603 
00604 
00611 void portSaveContext(void)  __attribute__ ( ( naked, noinline, used ) );
00612 
00613 
00619 void portRestoreContext(void)  __attribute__ ( ( naked, noinline, used ) );
00620 
00621 
00626 void portSetupTimerInterrupt(void);
00627 
00628 
00635 Tuint08 portReadTimer(void);
00636 
00637 
00644 Tbool portCheckTimer(void);
00645 
00646 
00652 Tuint08 portReadAndResetTimer(Tuint08 uiSubTickInterrupt);
00653 
00654 
00658 void devSigTimerCompare(void) __attribute__ ( ( signal, naked, used, externally_visible ) );
00659 
00660 
00665 void devSigTimerOverflow(void) __attribute__ ( ( signal, naked, used, externally_visible ) );
00666 
00667 
00672 #if defined(devSigWatchdogTimeout)
00673   void devSigWatchdogTimeout(void) __attribute__ ( ( signal, naked, used, externally_visible ) );
00674 #endif
00675 
00676 
00677 #endif /* FEMTOOS_PORT_H */

Generated on Fri Oct 16 00:05:21 2009 for FemtoOS by  doxygen 1.5.2