From 4fc5b696fad6b10620dcd49149bf64b829e38f77 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Sun, 7 Jun 2009 10:27:48 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@1019 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- demos/ARMCM3-STM32F103-GCC/board.c | 23 ++- demos/ARMCM3-STM32F103-GCC/board.h | 21 +-- demos/ARMCM3-STM32F103-GCC/main.c | 7 +- docs/src/main.dox | 35 ++-- ports/ARMCM3-STM32F103/ioports_lld.h | 216 ---------------------- ports/ARMCM3-STM32F103/pal_lld.h | 233 ++++++++++++++++++++++++ ports/ARMCM3-STM32F103/port.dox | 4 +- src/include/ioports.h | 317 --------------------------------- src/lib/pal.c | 70 ++++++++ src/lib/pal.h | 335 +++++++++++++++++++++++++++++++++++ 10 files changed, 678 insertions(+), 583 deletions(-) delete mode 100644 ports/ARMCM3-STM32F103/ioports_lld.h create mode 100644 ports/ARMCM3-STM32F103/pal_lld.h delete mode 100644 src/include/ioports.h create mode 100644 src/lib/pal.c create mode 100644 src/lib/pal.h diff --git a/demos/ARMCM3-STM32F103-GCC/board.c b/demos/ARMCM3-STM32F103-GCC/board.c index 2c73879f7..52701992a 100644 --- a/demos/ARMCM3-STM32F103-GCC/board.c +++ b/demos/ARMCM3-STM32F103-GCC/board.c @@ -18,6 +18,7 @@ */ #include +#include #include #include "board.h" @@ -59,23 +60,21 @@ void hwinit0(void) { ; /* - * I/O ports initialization as specified in board.h. Note that being this - * a low level initialization routine it is OK to invoke directly the - * low level port functions. + * I/O ports initialization as specified in board.h. */ - ioport_init_lld(); + palInit(); - ioport_stm32_setup_lld(IOPORT_A, VAL_GPIOACRH, VAL_GPIOACRL); - ioport_write_lld(IOPORT_A, VAL_GPIOAODR); + pal_lld_stm32_setup(IOPORT_A, VAL_GPIOACRH, VAL_GPIOACRL); + palWritePort(IOPORT_A, VAL_GPIOAODR); - ioport_stm32_setup_lld(IOPORT_B, VAL_GPIOBCRH, VAL_GPIOBCRL); - ioport_write_lld(IOPORT_B, VAL_GPIOBODR); + pal_lld_stm32_setup(IOPORT_B, VAL_GPIOBCRH, VAL_GPIOBCRL); + palWritePort(IOPORT_B, VAL_GPIOBODR); - ioport_stm32_setup_lld(IOPORT_C, VAL_GPIOCCRH, VAL_GPIOCCRL); - ioport_write_lld(IOPORT_C, VAL_GPIOCODR); + pal_lld_stm32_setup(IOPORT_C, VAL_GPIOCCRH, VAL_GPIOCCRL); + palWritePort(IOPORT_C, VAL_GPIOCODR); - ioport_stm32_setup_lld(IOPORT_D, VAL_GPIODCRH, VAL_GPIODCRL); - ioport_write_lld(IOPORT_D, VAL_GPIODODR); + pal_lld_stm32_setup(IOPORT_D, VAL_GPIODCRH, VAL_GPIODCRL); + palWritePort(IOPORT_D, VAL_GPIODODR); } /* diff --git a/demos/ARMCM3-STM32F103-GCC/board.h b/demos/ARMCM3-STM32F103-GCC/board.h index 236b4787b..250b2b2d2 100644 --- a/demos/ARMCM3-STM32F103-GCC/board.h +++ b/demos/ARMCM3-STM32F103-GCC/board.h @@ -32,15 +32,6 @@ #define TRUE (!FALSE) #endif -/* - * This module requires the port driver. - */ -#ifndef _IOPORTS_LLD_H_ -#include "ioports.h" -#endif - -#define BOARD_OLIMEX_STM32_P103 - /* * Uncomment this if you want a 48MHz system clock, else it will be 72MHz. */ @@ -130,13 +121,13 @@ /* * IO pins assignments. */ -#define GPIOA_BUTTON IOPORT_BIT(0) +#define GPIOA_BUTTON 0 -#define GPIOC_MMCWP IOPORT_BIT(6) -#define GPIOC_MMCCP IOPORT_BIT(7) -#define GPIOC_CANCNTL IOPORT_BIT(10) -#define GPIOC_DISC IOPORT_BIT(11) -#define GPIOC_LED IOPORT_BIT(12) +#define GPIOC_MMCWP 6 +#define GPIOC_MMCCP 7 +#define GPIOC_CANCNTL 10 +#define GPIOC_DISC 11 +#define GPIOC_LED 12 /* * All inputs with pullups unless otherwise specified. diff --git a/demos/ARMCM3-STM32F103-GCC/main.c b/demos/ARMCM3-STM32F103-GCC/main.c index 81a9af702..f89131d37 100644 --- a/demos/ARMCM3-STM32F103-GCC/main.c +++ b/demos/ARMCM3-STM32F103-GCC/main.c @@ -18,6 +18,7 @@ */ #include +#include #include #include "board.h" @@ -30,9 +31,9 @@ static WORKING_AREA(waThread1, 128); static msg_t Thread1(void *arg) { while (TRUE) { - chPortClear(IOPORT_C, GPIOC_LED); + palClearPad(IOPORT_C, GPIOC_LED); chThdSleepMilliseconds(500); - chPortSet(IOPORT_C, GPIOC_LED); + palSetPad(IOPORT_C, GPIOC_LED); chThdSleepMilliseconds(500); } return 0; @@ -54,7 +55,7 @@ int main(int argc, char **argv) { * sleeping in a loop and check the button state. */ while (TRUE) { - if (chPortRead(IOPORT_A) & GPIOA_BUTTON) + if (palReadPad(IOPORT_A, GPIOA_BUTTON)) TestThread(&COM2); chThdSleepMilliseconds(500); } diff --git a/docs/src/main.dox b/docs/src/main.dox index c92192fff..24d7acda1 100644 --- a/docs/src/main.dox +++ b/docs/src/main.dox @@ -355,26 +355,25 @@ */ /** - * @defgroup IOPorts Abstract I/O Ports - * @brief Abstract digital I/O ports. + * @defgroup PAL I/O Ports Abstraction Layer (PAL) + * @brief I/O Ports Abstraction Layer * @details This module defines an abstract interface for digital I/O ports. * Note that I/O ports functions are just a set of macros. The macros - * have default software implementation that can be redefined by an - * @ref IOPortsLLD if the target hardware supports special features like, as - * example, atomic bit set/reset/masking. Please refer to the documentation - * of the low level drivers for each port.
- * This abstraction system has the advantage to make the access to the I/O - * ports platform independent and still be optimized for the specific - * architecture.
+ * have default software implementations that can be redefined in a + * @ref PAL_LLD if the target hardware supports special features like, as + * example, atomic bit set/reset/masking. Please refer to the ports specific + * documentation for details.
+ * The @ref PAL has the advantage to make the access to the I/O ports platform + * independent and still be optimized for the specific architectures.
* Currently the I/O ports interface does not handle physical port programming * like direction, pull up/down resistors etc. The interface only allows input * and output operations but this may change in future releases.
- * Note that the @ref IOPortsLLD may also offer non standard macro and - * functions in order to support specific features but, of course, the use of - * such interfaces would not be portable. + * Note that the @ref PAL_LLD may also offer non standard macro and functions + * in order to support specific features but, of course, the use of such + * interfaces would not be portable. * *

Implementation Rules

- * In implementing an @ref IOPortsLLD there are some rules/behaviors that + * In implementing an @ref PAL_LLD there are some rules/behaviors that * should be respected. * *

Writing on input pads

@@ -406,7 +405,7 @@ * The behavior is not specified. * *

Usage

- * The use of I/O ports requires the inclusion of the header file @p ioports.h, + * The use of I/O ports requires the inclusion of the header file @p pal.h, * this file is not automatically included @p ch.h like the other header * files. * @@ -414,12 +413,12 @@ */ /** - * @defgroup IOPortsLLD I/O Ports Low Level Driver - * @brief Digital I/O ports low level driver template. + * @defgroup PAL_LLD PAL Low Level Driver + * @brief @ref PAL low level driver template. * @details This file is a template for an I/O port low level driver. This - * file implements the prysical layer of an I/O port driver. + * file implements the physical layer of an I/O port driver. * - * @ingroup IOPorts + * @ingroup PAL */ /** diff --git a/ports/ARMCM3-STM32F103/ioports_lld.h b/ports/ARMCM3-STM32F103/ioports_lld.h deleted file mode 100644 index df12f4bd5..000000000 --- a/ports/ARMCM3-STM32F103/ioports_lld.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ports/ARMCM3-STM32F103/ioports_lld.h - * @brief STM32 GPIO low level driver - * @addtogroup STM32F103_IOPORTS - * @{ - */ - -#ifndef _IOPORTS_LLD_H_ -#define _IOPORTS_LLD_H_ - -/* - * Tricks required to make the TRUE/FALSE declaration inside the library - * compatible. - */ -#ifndef __STM32F10x_MAP_H -#undef FALSE -#undef TRUE -#include "stm32f10x_map.h" -#define FALSE 0 -#define TRUE (!FALSE) -#endif - -/*===========================================================================*/ -/* I/O Ports Types and constants. */ -/*===========================================================================*/ - -/** - * @brief Width, in bits, of an I/O port. - */ -#define IOPORTS_WIDTH 16 - -/** - * @brief Digital I/O port sized unsigned type. - */ -typedef uint32_t ioportmask_t; - -/** - * @brief Port Identifier. - * @details This type can be a scalar or some kind of pointer, do not make - * any assumption about it, use the provided macros when populating - * variables of this type. - */ -typedef GPIO_TypeDef * ioportid_t; - -/*===========================================================================*/ -/* I/O Ports Identifiers. */ -/* The low level driver wraps the definitions already present in the STM32 */ -/* firmware library. */ -/*===========================================================================*/ - -/** - * @brief GPIO port A identifier. - */ -#if defined(_GPIOA) || defined(__DOXYGEN__) -#define IOPORT_A GPIOA -#endif - -/** - * @brief GPIO port A identifier. - */ -#if defined(_GPIOB) || defined(__DOXYGEN__) -#define IOPORT_B GPIOB -#endif - -/** - * @brief GPIO port A identifier. - */ -#if defined(_GPIOC) || defined(__DOXYGEN__) -#define IOPORT_C GPIOC -#endif - -/** - * @brief GPIO port A identifier. - */ -#if defined(_GPIOD) || defined(__DOXYGEN__) -#define IOPORT_D GPIOD -#endif - -/** - * @brief GPIO port A identifier. - */ -#if defined(_GPIOE) || defined(__DOXYGEN__) -#define IOPORT_E GPIOE -#endif - -/*===========================================================================*/ -/* Implementation, some of the following macros could be implemented as */ -/* functions, please put them in a file named ioports_lld.c if so. */ -/*===========================================================================*/ - -/** - * @brief GPIO ports subsystem initialization. - * @details Ports A-D enabled, AFIO enabled. - */ -#define ioport_init_lld() { \ - RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | \ - RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | \ - RCC_APB2ENR_IOPDEN; \ -} - -/** - * @brief Writes a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be written on the specified port - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_write_lld(port, bits) ((port)->ODR = (bits)) - -/** - * @brief Reads an I/O port. - * - * @param[in] port the port identifier - * @return the port bits - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_read_lld(port) ((port)->IDR) - -/** - * @brief Sets a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be ORed on the specified port - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_set_lld(port, bits) ((port)->BSRR = (bits)) - -/** - * @brief Clears a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be cleared on the specified port - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_clear_lld(port, bits) ((port)->BRR = (bits)) - -/** - * @brief Toggles a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be XORed on the specified port - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_toggle_lld(port, bits) ((port)->ODR ^= (bits)) - -/** - * @brief Writes a value on an I/O bus. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] bits the bits to be written on the I/O bus. Values exceeding - * the bus width are masked so most significant bits are lost. - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_writebus_lld(bus, bits) { \ - (bus)->bus_portid->BSRR = ((((~(bits)) << (bus)->bus_offset) & \ - (bus)->bus_mask) << 16) | \ - (((bits) << (bus)->bus_offset) & \ - (bus)->bus_mask); \ -} - -/** - * @brief Reads a value from an I/O bus. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @return the bus bits - * - * @note This function is not meant to be invoked directly by the application - * code. - */ -#define ioport_readbus_lld(bus) \ - (((bus)->bus_portid->IDR & (bus)->bus_mask) >> (bus)->bus_offset) - -/** - * @brief GPIO port setup. - * @details This function initializes a GPIO port, note that this functionality - * is STM32 specific and non portable. - */ -#define ioport_stm32_setup_lld(port, crh, crl) { \ - (port)->CRH = (crh); \ - (port)->CRL = (crl); \ -} - -#endif /* _IOPORTS_LLD_H_ */ - -/** @} */ diff --git a/ports/ARMCM3-STM32F103/pal_lld.h b/ports/ARMCM3-STM32F103/pal_lld.h new file mode 100644 index 000000000..7c1bb4399 --- /dev/null +++ b/ports/ARMCM3-STM32F103/pal_lld.h @@ -0,0 +1,233 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file ports/ARMCM3-STM32F103/pal_lld.h + * @brief STM32 GPIO low level driver + * @addtogroup STM32F103_PAL + * @{ + */ + +#ifndef _PAL_LLD_H_ +#define _PAL_LLD_H_ + +/* + * Tricks required to make the TRUE/FALSE declaration inside the library + * compatible. + */ +#ifndef __STM32F10x_MAP_H +#undef FALSE +#undef TRUE +#include "stm32f10x_map.h" +#define FALSE 0 +#define TRUE (!FALSE) +#endif + +/*===========================================================================*/ +/* I/O Ports Types and constants. */ +/*===========================================================================*/ + +/** + * @brief Width, in bits, of an I/O port. + */ +#define PAL_IOPORTS_WIDTH 16 + +/** + * @brief Digital I/O port sized unsigned type. + */ +typedef uint32_t ioportmask_t; + +/** + * @brief Port Identifier. + * @details This type can be a scalar or some kind of pointer, do not make + * any assumption about it, use the provided macros when populating + * variables of this type. + */ +typedef GPIO_TypeDef * ioportid_t; + +/*===========================================================================*/ +/* I/O Ports Identifiers. */ +/* The low level driver wraps the definitions already present in the STM32 */ +/* firmware library. */ +/*===========================================================================*/ + +/** + * @brief GPIO port A identifier. + */ +#if defined(_GPIOA) || defined(__DOXYGEN__) +#define IOPORT_A GPIOA +#endif + +/** + * @brief GPIO port A identifier. + */ +#if defined(_GPIOB) || defined(__DOXYGEN__) +#define IOPORT_B GPIOB +#endif + +/** + * @brief GPIO port A identifier. + */ +#if defined(_GPIOC) || defined(__DOXYGEN__) +#define IOPORT_C GPIOC +#endif + +/** + * @brief GPIO port A identifier. + */ +#if defined(_GPIOD) || defined(__DOXYGEN__) +#define IOPORT_D GPIOD +#endif + +/** + * @brief GPIO port A identifier. + */ +#if defined(_GPIOE) || defined(__DOXYGEN__) +#define IOPORT_E GPIOE +#endif + +/*===========================================================================*/ +/* Implementation, some of the following macros could be implemented as */ +/* functions, please put them in a file named ioports_lld.c if so. */ +/*===========================================================================*/ + +/** + * @brief GPIO ports subsystem initialization. + * @details Ports A-D enabled, AFIO enabled. + */ +#define pal_lld_init() { \ + RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPAEN | \ + RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | \ + RCC_APB2ENR_IOPDEN; \ +} + +/** + * @brief Reads an I/O port. + * @details This function is implemented by reading the GPIO IDR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @return the port bits + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_readport(port) ((port)->IDR) + +/** + * @brief Reads the output latch. + * @details This function is implemented by reading the GPIO oDR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @return The latched logical states. + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_readlatch(port) ((port)->ODR) + +/** + * @brief Writes on a I/O port. + * @details This function is implemented by writing the GPIO ODR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be written on the specified port + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_writeport(port, bits) ((port)->ODR = (bits)) + +/** + * @brief Sets a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be ORed on the specified port + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_setport(port, bits) ((port)->BSRR = (bits)) + +/** + * @brief Clears a bits mask on a I/O port. + * @details This function is implemented by writing the GPIO BRR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be cleared on the specified port + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_clearport(port, bits) ((port)->BRR = (bits)) + +/** + * @brief Writes a group of bits. + * @details This function is implemented by writing the GPIO BSRR register, the + * implementation has no side effects. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits the bits to be written. Values exceeding the group width + * are masked. + * @return The group logical states. + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_writegroup(port, mask, offset, bits) { \ + (bus)->bus_portid->BSRR = ((~(bits) & (mask)) << (16 + (offset))) | \ + ((bits) & (mask)) << (offset); \ +} + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @param[out] value the logical value, the value must be @p 0 or @p 1 + * + * @note This function is not meant to be invoked directly by the application + * code. + */ +#define pal_lld_writepad(port, pad, value) { \ + (bus)->bus_portid->BSRR = (((~(value) & 1) << ((pad) + 16)) | \ + ((((value) & 1) << (pad))); \ +} + +/** + * @brief GPIO port setup. + * @details This function initializes a GPIO port, note that this functionality + * is STM32 specific and non portable. It does not have a + * corresponding PAL API. + */ +#define pal_lld_stm32_setup(port, crh, crl) { \ + (port)->CRH = (crh); \ + (port)->CRL = (crl); \ +} + +#endif /* _PAL_LLD_H_ */ + +/** @} */ diff --git a/ports/ARMCM3-STM32F103/port.dox b/ports/ARMCM3-STM32F103/port.dox index 32049f969..244fdb20e 100644 --- a/ports/ARMCM3-STM32F103/port.dox +++ b/ports/ARMCM3-STM32F103/port.dox @@ -29,12 +29,12 @@ */ /** - * @defgroup STM32F103_IOPORTS I/O Ports Support + * @defgroup STM32F103_PAL I/O Ports Support * @brief I/O Ports peripherals support. * @details This module supports the STM32F103 GPIO controller. The STM32 * controller is very flexible and allows to implement all the recommended * behaviors for the I/O port driver. It supports the following features (see - * @ref IOPorts): + * @ref PAL): * - 16 bits wide ports. * - Atomic set/reset functions. * - Atomic set+reset function (atomic bus operations). diff --git a/src/include/ioports.h b/src/include/ioports.h deleted file mode 100644 index 8dd608fbe..000000000 --- a/src/include/ioports.h +++ /dev/null @@ -1,317 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -/** - * @file ioports.h - * @brief I/O ports - * @addtogroup IOPorts - * @{ - */ - -#ifndef _IOPORTS_H_ -#define _IOPORTS_H_ - -#ifndef _IOPORTS_LLD_H_ -#include "ioports_lld.h" -#endif - -/** - * @brief Port bit helper macro. - * @details This macro calculates the mask of a bit within a port. - */ -#define IOPORT_BIT(n) ((ioportmask_t)(1 << (n))) - -/** - * @brief Port bus mask helper macro. - * @details This macro calculates the proper bus mask starting from the width - * and the offset. - * - * @param[in] width the width, in bits, of the I/O bus - * @param[in] offset the offset, within the port, of the I/O bus. The offset - * must be specified as offset from the least significant bit. - */ -#define IOPORT_BUS_MASK(width, offset) \ - ((ioportmask_t)(((1 << (width)) - 1) << (offset))) - -/** - * @brief I/O bus descriptor. - * @details This structure describes a group of contiguous digital I/O lines - * that have to be handled as bus. - * @note I/O operations on a bus do not affect I/O lines on the same port but - * not belonging to the bus. - */ -typedef struct { - /** Port identifier. */ - ioportid_t bus_portid; - /** Mask of the I/O lines that form the bus. The lines must be contiguous. - * The mask must be pre-shifted and also defines the bus width. */ - ioportmask_t bus_mask; - /** Offset, within the port, of the least significant bit of the bus. */ - uint_fast8_t bus_offset; -} IOBus; - -/** - * @brief Reads an I/O port. - * - * @param[in] port the port identifier - * @return The port logical states. - * - * @note The default implementation always return zero and computes the - * parameter eventual side effects. - */ -#if !defined(ioport_read_lld) || defined(__DOXYGEN__) -#define chPortRead(port) ((void)(port), 0) -#else -#define chPortRead(port) ioport_read_lld(port) -#endif - -/** - * @brief Writes a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be written on the specified port - * - * @note The default implementation does nothing except computing the - * parameters eventual side effects. - */ -#if !defined(ioport_write_lld) || defined(__DOXYGEN__) -#define chPortWrite(port, bits) ((void)(port), (void)(bits)) -#else -#define chPortWrite(port, bits) ioport_write_lld(port, bits) -#endif - -/** - * @brief Sets a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be ORed on the specified port - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - */ -#if !defined(ioport_set_lld) || defined(__DOXYGEN__) -#define chPortSet(port, bits) { \ - ioport_t p = (port); \ - chPortWrite(p, chPortRead(p) | (bits)); \ -} -#else -#define chPortSet(port, bits) ioport_set_lld(port, bits) -#endif - -/** - * @brief Clears a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be cleared on the specified port - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - */ -#if !defined(ioport_clear_lld) || defined(__DOXYGEN__) -#define chPortClear(port, bits) { \ - ioport_t p = (port); \ - chPortWrite(p, chPortRead(p) & ~(bits)); \ -} -#else -#define chPortClear(port, bits) ioport_clear_lld(port, bits) -#endif - -/** - * @brief Toggles a bits mask on a I/O port. - * - * @param[in] port the port identifier - * @param[in] bits the bits to be XORed on the specified port - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - */ -#if !defined(ioport_toggle_lld) || defined(__DOXYGEN__) -#define chPortToggle(port, bits) { \ - ioport_t p = (port); \ - chPortWrite(p, chPortRead(p) ^ (bits)); \ -} -#else -#define chPortToggle(port, bits) ioport_toggle_lld(port, bits) -#endif - -/** - * @brief Reads a value from an I/O bus. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @return The bus logical states. - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation not necessarily optimal. Low level drivers - * may optimize the function by using specific hardware or coding. - * @note The default implementation evaluates the parameter three times, be - * careful with side effects. - */ -#if !defined(ioport_readbus_lld) || defined(__DOXYGEN__) -#define chPortReadBus(bus) \ - ((chPortRead((bus)->bus_port) >> (bus)->bus_offset) & (bus)->bus_mask) -#else -#define chPortReadBus(bus) ioport_readbus_lld(bus) -#endif - -/** - * @brief Writes a value on an I/O bus. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @param[in] bits the bits to be written on the I/O bus. Values exceeding - * the bus width are masked so most significant bits are lost. - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - */ -#if !defined(ioport_writebus_lld) || defined(__DOXYGEN__) -#define chPortWriteBus(bus, bits) { \ - IOBus *b = (bus); \ - chPortWrite(b->bus_port, (chPortRead(b->bus_port) & ~b->bus_mask) | \ - (((bits) << b->bus_offset) & b->bus_mask)); \ -} -#else -#define chPortWriteBus(bus, bits) ioport_writebus_lld(bus, bits) -#endif - -/** - * @brief Reads an input pad logical state. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * @return The logical state. - * @retval 0 low logical state. - * @retval 1 high logical state. - * - * @note The default implementation not necessarily optimal. Low level drivers - * may optimize the function by using specific hardware or coding. - * @note The default implementation internally uses the @p chPortRead(). - */ -#if !defined(ioport_readpad_lld) || defined(__DOXYGEN__) -#define chPortReadPad(port, pad) ((chPortRead(port) >> (pad)) & 1) -#else -#define chPortReadPad(port, pad) ioport_readpad_lld(port, pad) -#endif - -/** - * @brief Writes a logical state on an output pad. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * @param[out] value the logical value, the value must be @p 0 or @p 1 - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p chPortRead() and - * @p chPortWrite(). - */ -#if !defined(ioport_writepad_lld) || defined(__DOXYGEN__) -#define chPortWritePad(port, pad, value) { - ioport_t p = (port); \ - chPortWrite(p, (chPortRead(p) & ~IOPORT_BIT(pad)) | \ - ((value & 1) << pad)); \ -} -#else -#define chPortWritePad(port, pad, value) ioport_writepad_lld(port, pad, value) -#endif - -/** - * @brief Sets a pad logical state to @p 1. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p chPortSet(). - */ -#if !defined(ioport_setpad_lld) || defined(__DOXYGEN__) -#define chPortSetPad(port, pad) chPortSet(port, IOPORT_BIT(pad)) -#else -#define chPortSetPad(port, pad) ioport_setpad_lld(port, pad) -#endif - -/** - * @brief Clears a pad logical state to @p 0. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p chPortClear(). - */ -#if !defined(ioport_clearpad_lld) || defined(__DOXYGEN__) -#define chPortClearPad(port, pad) chPortClear(port, IOPORT_BIT(pad)) -#else -#define chPortClearPad(port, pad) ioport_clearpad_lld(port, pad) -#endif - -/** - * @brief Toggles a pad logical state. - * - * @param[in] port the port identifier - * @param[in] pad the pad number within the port - * - * @note The operation is not guaranteed to be atomic on all the architectures, - * for atomicity and/or portability reasons you may need to enclose port - * I/O operations between @p chSysLock() and @p chSysUnlock(). - * @note The default implementation is non atomic and not necessarily - * optimal. Low level drivers may optimize the function by using - * specific hardware or coding. - * @note The default implementation internally uses the @p chPortToggle(). - */ -#if !defined(ioport_togglepad_lld) || defined(__DOXYGEN__) -#define chPortTogglePad(port, pad) ioport_toggle_lld(port, IOPORT_BIT(pad)) -#else -#define chPortTogglePad(port, pad) ioport_togglepad_lld(port, pad) -#endif - -#endif /* _IOPORTS_H_ */ - -/** @} */ diff --git a/src/lib/pal.c b/src/lib/pal.c new file mode 100644 index 000000000..045c35c20 --- /dev/null +++ b/src/lib/pal.c @@ -0,0 +1,70 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file pal.c + * @brief I/O Ports Abstraction Layer code + * @addtogroup PAL + * @{ + */ + +/** + * @brief Read from an I/O bus. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @return The bus logical states. + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The function internally uses the @p palReadGroup() macro. The use of + * this function is preferred when you value code size, readability and + * error checking over speed. + */ +ioportmask_t palReadBus(IOBus *bus) { + + chDbgCheck((bus != NULL) && + (bus->bus_offset > PAL_IOPORTS_WIDTH), "palReadBus"); + + return palReadGroup(bus->bus_port, bus->bus_mask, bus->bus_offset); +} + +/** + * @brief Write to an I/O bus. + * + * @param[in] bus the I/O bus, pointer to a @p IOBus structure + * @param[in] bits the bits to be written on the I/O bus. Values exceeding + * the bus width are masked so most significant bits are lost. + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + */ +void palWriteBus(IOBus *bus, ioportmask_t bits) { + + chDbgCheck((bus != NULL) && + (bus->bus_offset > PAL_IOPORTS_WIDTH), "palWriteBus"); + + palWriteBus(bus->bus_port, bus->bus_mask, bus->bus_offset, bits); +} + +/** @} */ diff --git a/src/lib/pal.h b/src/lib/pal.h new file mode 100644 index 000000000..11137c6cb --- /dev/null +++ b/src/lib/pal.h @@ -0,0 +1,335 @@ +/* + ChibiOS/RT - Copyright (C) 2006-2007 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/** + * @file pal.h + * @brief I/O Ports Abstraction Layer macros, types and structures + * @addtogroup PAL + * @{ + */ + +#ifndef _PAL_H_ +#define _PAL_H_ + +#ifndef _PAL_LLD_H_ +#include "pal_lld.h" +#endif + +/** + * @brief Port bit helper macro. + * @details This macro calculates the mask of a bit within a port. + * + * @param[in] n the bit position within the port + * @return The bit mask. + */ +#define PAL_PORT_BIT(n) ((ioportmask_t)(1 << (n))) + + +/** + * @brief Bits group mask helper. + * @details This macro calculates the mask of a bits group. + * + * @param[in] the group width + * @return The group mask. + */ +#define PAL_GROUP_MASK(width) ((ioportmask_t)(1 << (width)) - 1) + +/** + * @brief I/O bus descriptor. + * @details This structure describes a group of contiguous digital I/O lines + * that have to be handled as bus. + * @note I/O operations on a bus do not affect I/O lines on the same port but + * not belonging to the bus. + */ +typedef struct { + /** Port identifier. */ + ioportid_t bus_portid; + /** Bus mask aligned to port bit 0. The bus mask implicitly define the bus + * width. */ + ioportmask_t bus_mask; + /** Offset, within the port, of the least significant bit of the bus. */ + uint_fast8_t bus_offset; +} IOBus; + +/** + * @brief PAL subsystem initialization. + */ +#define palInit() pal_lld_init() + +/** + * @brief Reads the physical I/O port states. + * + * @param[in] port the port identifier + * @return The port logical states. + * + * @note The default implementation always return zero and computes the + * parameter eventual side effects. + */ +#if !defined(pal_lld_readport) || defined(__DOXYGEN__) +#define palReadPort(port) ((void)(port), 0) +#else +#define palReadPort(port) pal_lld_readport(port) +#endif + +/** + * @brief Reads the output latch. + * @details The purpose of this function is to read back the latched output + * value. + * + * @param[in] port the port identifier + * @return The latched logical states. + * + * @note The default implementation always return zero and computes the + * parameter eventual side effects. + */ +#if !defined(pal_lld_readlatch) || defined(__DOXYGEN__) +#define palReadLatch(port) ((void)(port), 0) +#else +#define palReadLatch(port) pal_lld_readlatch(port) +#endif + +/** + * @brief Writes a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be written on the specified port + * + * @note The default implementation does nothing except computing the + * parameters eventual side effects. + */ +#if !defined(pal_lld_writeport) || defined(__DOXYGEN__) +#define palWritePort(port, bits) ((void)(port), (void)(bits)) +#else +#define palWritePort(port, bits) pal_lld_writeport(port, bits) +#endif + +/** + * @brief Sets a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be ORed on the specified port + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + */ +#if !defined(pal_lld_setport) || defined(__DOXYGEN__) +#define palSetPort(port, bits) { \ + palWritePort(port, palReadLatch(p) | (bits)); \ +} +#else +#define palSetPort(port, bits) pal_lld_setport(port, bits) +#endif + +/** + * @brief Clears a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be cleared on the specified port + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + */ +#if !defined(pal_lld_clearport) || defined(__DOXYGEN__) +#define palClearPort(port, bits) { \ + palWritePort(port, palReadLatch(p) & ~(bits)); \ +} +#else +#define palClearPort(port, bits) pal_lld_clearport(port, bits) +#endif + +/** + * @brief Toggles a bits mask on a I/O port. + * + * @param[in] port the port identifier + * @param[in] bits the bits to be XORed on the specified port + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + */ +#if !defined(pal_lld_toggleport) || defined(__DOXYGEN__) +#define palTogglePort(port, bits) { \ + palWritePort(port, palReadLatch(port) ^ (bits)); \ +} +#else +#define palTogglePort(port, bits) pal_lld_toggleport(port, bits) +#endif + +/** + * @brief Reads a group of bits. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] offset the group bit offset within the port + * @return The group logical states. + */ +#if !defined(pal_lld_readgroup) || defined(__DOXYGEN__) +#define palReadGroup(port, mask, offset) \ + ((palReadPort(port) >> (offset)) & (mask)) +#else +#define palReadGroup(port, mask, offset) pal_lld_readgroup(port, mask, offset) +#endif + +/** + * @brief Writes a group of bits. + * + * @param[in] port the port identifier + * @param[in] mask the group mask + * @param[in] offset the group bit offset within the port + * @param[in] bits the bits to be written. Values exceeding the group width + * are masked. + * @return The group logical states. + */ +#if !defined(pal_lld_writegroup) || defined(__DOXYGEN__) +#define palWriteGroup(port, mask, offset, bits) { \ + palWritePort(port, (palReadLatch(port) & ~((mask) << (offset))) | \ + (((bits) & (mask)) << (offset))); \ +} +#else +#define palWriteGroup(port, mask, offset, bits) \ + pal_lld_writegroup(port, mask, offset, bits) +#endif + +/** + * @brief Reads an input pad logical state. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @return The logical state. + * @retval 0 low logical state. + * @retval 1 high logical state. + * + * @note The default implementation not necessarily optimal. Low level drivers + * may optimize the function by using specific hardware or coding. + * @note The default implementation internally uses the @p palReadPort(). + */ +#if !defined(pal_lld_readpad) || defined(__DOXYGEN__) +#define palReadPad(port, pad) ((palReadPort(port) >> (pad)) & 1) +#else +#define palReadPad(port, pad) pal_lld_readpad(port, pad) +#endif + +/** + * @brief Writes a logical state on an output pad. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * @param[out] value the logical value, the value must be @p 0 or @p 1 + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palReadLatch() and + * @p palWritePort(). + */ +#if !defined(pal_lld_writepad) || defined(__DOXYGEN__) +#define palWritePad(port, pad, value) { \ + palWritePort(port, (palReadLatch(port) & ~PAL_PORT_BIT(pad)) | \ + (((value) & 1) << pad)); \ +} +#else +#define palWritePad(port, pad, value) pal_lld_writepad(port, pad, value) +#endif + +/** + * @brief Sets a pad logical state to @p 1. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palSetPort(). + */ +#if !defined(pal_lld_setpad) || defined(__DOXYGEN__) +#define palSetPad(port, pad) palSetPort(port, PAL_PORT_BIT(pad)) +#else +#define palSetPad(port, pad) pal_lld_setpad(port, pad) +#endif + +/** + * @brief Clears a pad logical state to @p 0. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palClearPort(). + */ +#if !defined(pal_lld_clearpad) || defined(__DOXYGEN__) +#define palClearPad(port, pad) palClearPort(port, PAL_PORT_BIT(pad)) +#else +#define palClearPad(port, pad) pal_lld_clearpad(port, pad) +#endif + +/** + * @brief Toggles a pad logical state. + * + * @param[in] port the port identifier + * @param[in] pad the pad number within the port + * + * @note The operation is not guaranteed to be atomic on all the architectures, + * for atomicity and/or portability reasons you may need to enclose port + * I/O operations between @p chSysLock() and @p chSysUnlock(). + * @note The default implementation is non atomic and not necessarily + * optimal. Low level drivers may optimize the function by using + * specific hardware or coding. + * @note The default implementation internally uses the @p palTogglePort(). + */ +#if !defined(pal_lld_togglepad) || defined(__DOXYGEN__) +#define palTogglePad(port, pad) palTogglePort(port, PAL_PORT_BIT(pad)) +#else +#define palTogglePad(port, pad) pal_lld_togglepad(port, pad) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + ioportmask_t palReadBus(IOBus *bus); + void palWriteBus(IOBus *bus, ioportmask_t bits); +#ifdef __cplusplus +} +#endif + +#endif /* _PAL_H_ */ + +/** @} */ -- cgit v1.2.3