ChibiOS/RT
2.5.1
pal.h
Go to the documentation of this file.
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012 Giovanni Di Sirio.
00004 
00005     This file is part of ChibiOS/RT.
00006 
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011 
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 /**
00022  * @file    pal.h
00023  * @brief   I/O Ports Abstraction Layer macros, types and structures.
00024  *
00025  * @addtogroup PAL
00026  * @{
00027  */
00028 
00029 #ifndef _PAL_H_
00030 #define _PAL_H_
00031 
00032 #if HAL_USE_PAL || defined(__DOXYGEN__)
00033 
00034 /*===========================================================================*/
00035 /* Driver constants.                                                         */
00036 /*===========================================================================*/
00037 
00038 /**
00039  * @name    Pads mode constants
00040  * @{
00041  */
00042 /**
00043  * @brief   After reset state.
00044  * @details The state itself is not specified and is architecture dependent,
00045  *          it is guaranteed to be equal to the after-reset state. It is
00046  *          usually an input state.
00047  */
00048 #define PAL_MODE_RESET                  0
00049 
00050 /**
00051  * @brief   Safe state for <b>unconnected</b> pads.
00052  * @details The state itself is not specified and is architecture dependent,
00053  *          it may be mapped on @p PAL_MODE_INPUT_PULLUP,
00054  *          @p PAL_MODE_INPUT_PULLDOWN or @p PAL_MODE_OUTPUT_PUSHPULL as
00055  *          example.
00056  */
00057 #define PAL_MODE_UNCONNECTED            1
00058 
00059 /**
00060  * @brief   Regular input high-Z pad.
00061  */
00062 #define PAL_MODE_INPUT                  2
00063 
00064 /**
00065  * @brief   Input pad with weak pull up resistor.
00066  */
00067 #define PAL_MODE_INPUT_PULLUP           3
00068 
00069 /**
00070  * @brief   Input pad with weak pull down resistor.
00071  */
00072 #define PAL_MODE_INPUT_PULLDOWN         4
00073 
00074 /**
00075  * @brief   Analog input mode.
00076  */
00077 #define PAL_MODE_INPUT_ANALOG           5
00078 
00079 /**
00080  * @brief   Push-pull output pad.
00081  */
00082 #define PAL_MODE_OUTPUT_PUSHPULL        6
00083 
00084 /**
00085  * @brief   Open-drain output pad.
00086  */
00087 #define PAL_MODE_OUTPUT_OPENDRAIN       7
00088 /** @} */
00089 
00090 /**
00091  * @name    Logic level constants
00092  * @{
00093  */
00094 /**
00095  * @brief   Logical low state.
00096  */
00097 #define PAL_LOW                         0
00098 
00099 /**
00100  * @brief   Logical high state.
00101  */
00102 #define PAL_HIGH                        1
00103 /** @} */
00104 
00105 /*===========================================================================*/
00106 /* Driver pre-compile time settings.                                         */
00107 /*===========================================================================*/
00108 
00109 /*===========================================================================*/
00110 /* Derived constants and error checks.                                       */
00111 /*===========================================================================*/
00112 
00113 /*===========================================================================*/
00114 /* Driver data structures and types.                                         */
00115 /*===========================================================================*/
00116 
00117 #include "pal_lld.h"
00118 
00119 /**
00120  * @brief   I/O bus descriptor.
00121  * @details This structure describes a group of contiguous digital I/O lines
00122  *          that have to be handled as bus.
00123  * @note    I/O operations on a bus do not affect I/O lines on the same port but
00124  *          not belonging to the bus.
00125  */
00126 typedef struct {
00127   /**
00128    * @brief Port identifier.
00129    */
00130   ioportid_t            portid;
00131   /**
00132    * @brief Bus mask aligned to port bit 0.
00133    * @note  The bus mask implicitly define the bus width. A logical AND is
00134    *        performed on the bus data.
00135    */
00136   ioportmask_t          mask;
00137   /**
00138    * @brief Offset, within the port, of the least significant bit of the bus.
00139    */
00140   uint_fast8_t          offset;
00141 } IOBus;
00142 
00143 /*===========================================================================*/
00144 /* Driver macros.                                                            */
00145 /*===========================================================================*/
00146 
00147 /**
00148  * @brief   Port bit helper macro.
00149  * @details This macro calculates the mask of a bit within a port.
00150  *
00151  * @param[in] n         bit position within the port
00152  * @return              The bit mask.
00153  */
00154 #if !defined(PAL_PORT_BIT) || defined(__DOXYGEN__)
00155 #define PAL_PORT_BIT(n) ((ioportmask_t)(1 << (n)))
00156 #endif
00157 
00158 /**
00159  * @brief   Bits group mask helper.
00160  * @details This macro calculates the mask of a bits group.
00161  *
00162  * @param[in] width         group width
00163  * @return                  The group mask.
00164  */
00165 #if !defined(PAL_GROUP_MASK) || defined(__DOXYGEN__)
00166 #define PAL_GROUP_MASK(width) ((ioportmask_t)(1 << (width)) - 1)
00167 #endif
00168 
00169 /**
00170  * @brief   Data part of a static I/O bus initializer.
00171  * @details This macro should be used when statically initializing an I/O bus
00172  *          that is part of a bigger structure.
00173  *
00174  * @param[in] name      name of the IOBus variable
00175  * @param[in] port      I/O port descriptor
00176  * @param[in] width     bus width in bits
00177  * @param[in] offset     bus bit offset within the port
00178  */
00179 #define _IOBUS_DATA(name, port, width, offset)                              \
00180   {port, PAL_GROUP_MASK(width), offset}
00181 
00182 /**
00183  * @brief   Static I/O bus initializer.
00184  *
00185  * @param[in] name      name of the IOBus variable
00186  * @param[in] port      I/O port descriptor
00187  * @param[in] width     bus width in bits
00188  * @param[in] offset    bus bit offset within the port
00189  */
00190 #define IOBUS_DECL(name, port, width, offset)                               \
00191   IOBus name = _IOBUS_DATA(name, port, width, offset)
00192 
00193 /**
00194  * @name    Macro Functions
00195  * @{
00196  */
00197 /**
00198  * @brief   PAL subsystem initialization.
00199  * @note    This function is implicitly invoked by @p halInit(), there is
00200  *          no need to explicitly initialize the driver.
00201  *
00202  * @param[in] config pointer to an architecture specific configuration
00203  *            structure. This structure is defined in the low level driver
00204  *            header.
00205  *
00206  * @init
00207  */
00208 #define palInit(config) pal_lld_init(config)
00209 
00210 /**
00211  * @brief   Reads the physical I/O port states.
00212  * @note    The default implementation always return zero and computes the
00213  *          parameter eventual side effects.
00214  *
00215  * @param[in] port      port identifier
00216  * @return              The port logical states.
00217  *
00218  * @api
00219  */
00220 #if !defined(pal_lld_readport) || defined(__DOXYGEN__)
00221 #define palReadPort(port) ((void)(port), 0)
00222 #else
00223 #define palReadPort(port) pal_lld_readport(port)
00224 #endif
00225 
00226 /**
00227  * @brief   Reads the output latch.
00228  * @details The purpose of this function is to read back the latched output
00229  *          value.
00230  * @note    The default implementation always return zero and computes the
00231  *          parameter eventual side effects.
00232  *
00233  * @param[in] port      port identifier
00234  * @return              The latched logical states.
00235  *
00236  * @api
00237  */
00238 #if !defined(pal_lld_readlatch) || defined(__DOXYGEN__)
00239 #define palReadLatch(port) ((void)(port), 0)
00240 #else
00241 #define palReadLatch(port) pal_lld_readlatch(port)
00242 #endif
00243 
00244 /**
00245  * @brief   Writes a bits mask on a I/O port.
00246  * @note    The default implementation does nothing except computing the
00247  *          parameters eventual side effects.
00248  *
00249  * @param[in] port      port identifier
00250  * @param[in] bits      bits to be written on the specified port
00251  *
00252  * @api
00253  */
00254 #if !defined(pal_lld_writeport) || defined(__DOXYGEN__)
00255 #define palWritePort(port, bits) ((void)(port), (void)(bits))
00256 #else
00257 #define palWritePort(port, bits) pal_lld_writeport(port, bits)
00258 #endif
00259 
00260 /**
00261  * @brief   Sets a bits mask on a I/O port.
00262  * @note    The operation is not guaranteed to be atomic on all the
00263  *          architectures, for atomicity and/or portability reasons you may
00264  *          need to enclose port I/O operations between @p chSysLock() and
00265  *          @p chSysUnlock().
00266  * @note    The default implementation is non atomic and not necessarily
00267  *          optimal. Low level drivers may  optimize the function by using
00268  *          specific hardware or coding.
00269  *
00270  * @param[in] port      port identifier
00271  * @param[in] bits      bits to be ORed on the specified port
00272  *
00273  * @api
00274  */
00275 #if !defined(pal_lld_setport) || defined(__DOXYGEN__)
00276 #define palSetPort(port, bits)                                              \
00277   palWritePort(port, palReadLatch(port) | (bits))
00278 #else
00279 #define palSetPort(port, bits) pal_lld_setport(port, bits)
00280 #endif
00281 
00282 /**
00283  * @brief   Clears a bits mask on a I/O port.
00284  * @note    The operation is not guaranteed to be atomic on all the
00285  *          architectures,  for atomicity and/or portability reasons you may
00286  *          need to enclose port I/O operations between @p chSysLock() and
00287  *          @p chSysUnlock().
00288  * @note    The default implementation is non atomic and not necessarily
00289  *          optimal. Low level drivers may  optimize the function by using
00290  *          specific hardware or coding.
00291  *
00292  * @param[in] port      port identifier
00293  * @param[in] bits      bits to be cleared on the specified port
00294  *
00295  * @api
00296  */
00297 #if !defined(pal_lld_clearport) || defined(__DOXYGEN__)
00298 #define palClearPort(port, bits)                                            \
00299   palWritePort(port, palReadLatch(port) & ~(bits))
00300 #else
00301 #define palClearPort(port, bits) pal_lld_clearport(port, bits)
00302 #endif
00303 
00304 /**
00305  * @brief   Toggles a bits mask on a I/O port.
00306  * @note    The operation is not guaranteed to be atomic on all the
00307  *          architectures, for atomicity and/or portability reasons you may
00308  *          need to enclose port I/O operations between @p chSysLock() and
00309  *          @p chSysUnlock().
00310  * @note    The default implementation is non atomic and not necessarily
00311  *          optimal. Low level drivers may  optimize the function by using
00312  *          specific hardware or coding.
00313  *
00314  * @param[in] port      port identifier
00315  * @param[in] bits      bits to be XORed on the specified port
00316  *
00317  * @api
00318  */
00319 #if !defined(pal_lld_toggleport) || defined(__DOXYGEN__)
00320 #define palTogglePort(port, bits)                                           \
00321   palWritePort(port, palReadLatch(port) ^ (bits))
00322 #else
00323 #define palTogglePort(port, bits) pal_lld_toggleport(port, bits)
00324 #endif
00325 
00326 /**
00327  * @brief   Reads a group of bits.
00328  *
00329  * @param[in] port      port identifier
00330  * @param[in] mask      group mask, a logical AND is performed on the input
00331  *                      data
00332  * @param[in] offset    group bit offset within the port
00333  * @return              The group logical states.
00334  *
00335  * @api
00336  */
00337 #if !defined(pal_lld_readgroup) || defined(__DOXYGEN__)
00338 #define palReadGroup(port, mask, offset)                                    \
00339   ((palReadPort(port) >> (offset)) & (mask))
00340 #else
00341 #define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset)
00342 #endif
00343 
00344 /**
00345  * @brief   Writes a group of bits.
00346  *
00347  * @param[in] port      port identifier
00348  * @param[in] mask      group mask, a logical AND is performed on the
00349  *                      output  data
00350  * @param[in] offset    group bit offset within the port
00351  * @param[in] bits      bits to be written. Values exceeding the group
00352  *                      width are masked.
00353  *
00354  * @api
00355  */
00356 #if !defined(pal_lld_writegroup) || defined(__DOXYGEN__)
00357 #define palWriteGroup(port, mask, offset, bits)                             \
00358   palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) |         \
00359                      (((bits) & (mask)) << (offset)))
00360 #else
00361 #define palWriteGroup(port, mask, offset, bits)                             \
00362   pal_lld_writegroup(port, mask, offset, bits)
00363 #endif
00364 
00365 
00366 /**
00367  * @brief   Pads group mode setup.
00368  * @details This function programs a pads group belonging to the same port
00369  *          with the specified mode.
00370  * @note    Programming an unknown or unsupported mode is silently ignored.
00371  *
00372  * @param[in] port      port identifier
00373  * @param[in] mask      group mask
00374  * @param[in] offset    group bit offset within the port
00375  * @param[in] mode      group mode
00376  *
00377  * @api
00378  */
00379 #if !defined(pal_lld_setgroupmode) || defined(__DOXYGEN__)
00380 #define palSetGroupMode(port, mask, offset, mode)
00381 #else
00382 #define palSetGroupMode(port, mask, offset, mode)                           \
00383   pal_lld_setgroupmode(port, mask, offset, mode)
00384 #endif
00385 
00386 /**
00387  * @brief   Reads an input pad logical state.
00388  * @note    The default implementation not necessarily optimal. Low level
00389  *          drivers may  optimize the function by using specific hardware
00390  *          or coding.
00391  * @note    The default implementation internally uses the @p palReadPort().
00392  *
00393  * @param[in] port      port identifier
00394  * @param[in] pad       pad number within the port
00395  * @return              The logical state.
00396  * @retval PAL_LOW      low logical state.
00397  * @retval PAL_HIGH     high logical state.
00398  *
00399  * @api
00400  */
00401 #if !defined(pal_lld_readpad) || defined(__DOXYGEN__)
00402 #define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1)
00403 #else
00404 #define palReadPad(port, pad) pal_lld_readpad(port, pad)
00405 #endif
00406 
00407 /**
00408  * @brief   Writes a logical state on an output pad.
00409  * @note    The operation is not guaranteed to be atomic on all the
00410  *          architectures, for atomicity and/or portability reasons you may
00411  *          need to enclose port I/O operations between @p chSysLock() and
00412  *          @p chSysUnlock().
00413  * @note    The default implementation is non atomic and not necessarily
00414  *          optimal. Low level drivers may  optimize the function by using
00415  *          specific hardware or coding.
00416  * @note    The default implementation internally uses the @p palReadLatch()
00417  *          and @p palWritePort().
00418  *
00419  * @param[in] port      port identifier
00420  * @param[in] pad       pad number within the port
00421  * @param[in] bit       logical value, the value must be @p PAL_LOW or
00422  *                      @p PAL_HIGH
00423  *
00424  * @api
00425  */
00426 #if !defined(pal_lld_writepad) || defined(__DOXYGEN__)
00427 #define palWritePad(port, pad, bit)                                         \
00428   palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) |            \
00429                      (((bit) & 1) << pad))
00430 #else
00431 #define palWritePad(port, pad, bit) pal_lld_writepad(port, pad, bit)
00432 #endif
00433 
00434 /**
00435  * @brief   Sets a pad logical state to @p PAL_HIGH.
00436  * @note    The operation is not guaranteed to be atomic on all the
00437  *          architectures, for atomicity and/or portability reasons you may
00438  *          need to enclose port I/O operations between @p chSysLock() and
00439  *          @p chSysUnlock().
00440  * @note    The default implementation is non atomic and not necessarily
00441  *          optimal. Low level drivers may  optimize the function by using
00442  *          specific hardware or coding.
00443  * @note    The default implementation internally uses the @p palSetPort().
00444  *
00445  * @param[in] port      port identifier
00446  * @param[in] pad       pad number within the port
00447  *
00448  * @api
00449  */
00450 #if !defined(pal_lld_setpad) || defined(__DOXYGEN__)
00451 #define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad))
00452 #else
00453 #define palSetPad(port, pad) pal_lld_setpad(port, pad)
00454 #endif
00455 
00456 /**
00457  * @brief   Clears a pad logical state to @p PAL_LOW.
00458  * @note    The operation is not guaranteed to be atomic on all the
00459  *          architectures, for atomicity and/or portability reasons you may
00460  *          need to enclose port I/O operations between @p chSysLock() and
00461  *          @p chSysUnlock().
00462  * @note    The default implementation is non atomic and not necessarily
00463  *          optimal. Low level drivers may  optimize the function by using
00464  *          specific hardware or coding.
00465  * @note    The default implementation internally uses the @p palClearPort().
00466  *
00467  * @param[in] port      port identifier
00468  * @param[in] pad       pad number within the port
00469  *
00470  * @api
00471  */
00472 #if !defined(pal_lld_clearpad) || defined(__DOXYGEN__)
00473 #define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad))
00474 #else
00475 #define palClearPad(port, pad) pal_lld_clearpad(port, pad)
00476 #endif
00477 
00478 /**
00479  * @brief   Toggles a pad logical state.
00480  * @note    The operation is not guaranteed to be atomic on all the
00481  *          architectures, for atomicity and/or portability reasons you may
00482  *          need to enclose port I/O operations between @p chSysLock() and
00483  *          @p chSysUnlock().
00484  * @note    The default implementation is non atomic and not necessarily
00485  *          optimal. Low level drivers may  optimize the function by using
00486  *          specific hardware or coding.
00487  * @note    The default implementation internally uses the @p palTogglePort().
00488  *
00489  * @param[in] port      port identifier
00490  * @param[in] pad       pad number within the port
00491  *
00492  * @api
00493  */
00494 #if !defined(pal_lld_togglepad) || defined(__DOXYGEN__)
00495 #define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad))
00496 #else
00497 #define palTogglePad(port, pad) pal_lld_togglepad(port, pad)
00498 #endif
00499 
00500 /**
00501  * @brief   Pad mode setup.
00502  * @details This function programs a pad with the specified mode.
00503  * @note    The default implementation not necessarily optimal. Low level
00504  *          drivers may  optimize the function by using specific hardware
00505  *          or coding.
00506  * @note    Programming an unknown or unsupported mode is silently ignored.
00507  *
00508  * @param[in] port      port identifier
00509  * @param[in] pad       pad number within the port
00510  * @param[in] mode      pad mode
00511  *
00512  * @api
00513  */
00514 #if !defined(pal_lld_setpadmode) || defined(__DOXYGEN__)
00515 #define palSetPadMode(port, pad, mode)                                      \
00516   palSetGroupMode(port, PAL_PORT_BIT(pad), 0, mode)
00517 #else
00518 #define palSetPadMode(port, pad, mode) pal_lld_setpadmode(port, pad, mode)
00519 #endif
00520 /** @} */
00521 
00522 /*===========================================================================*/
00523 /* External declarations.                                                    */
00524 /*===========================================================================*/
00525 
00526 #ifdef __cplusplus
00527 extern "C" {
00528 #endif
00529   ioportmask_t palReadBus(IOBus *bus);
00530   void palWriteBus(IOBus *bus, ioportmask_t bits);
00531   void palSetBusMode(IOBus *bus, iomode_t mode);
00532 #ifdef __cplusplus
00533 }
00534 #endif
00535 
00536 #endif /* _PAL_H_ */
00537 
00538 #endif /* HAL_USE_PAL */
00539 
00540 /** @} */