diff --git a/src/include/ioports.h b/src/include/ioports.h index 5fd330d51..8dd608fbe 100644 --- a/src/include/ioports.h +++ b/src/include/ioports.h @@ -66,6 +66,21 @@ typedef struct { 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. * @@ -81,21 +96,6 @@ typedef struct { #define chPortWrite(port, bits) ioport_write_lld(port, bits) #endif -/** - * @brief Reads an I/O port. - * - * @param[in] port the port identifier - * @return the port bits - * - * @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 Sets a bits mask on a I/O port. * @@ -105,7 +105,7 @@ typedef struct { * @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 atomical and not necessarily + * @note The default implementation is non atomic and not necessarily * optimal. Low level drivers may optimize the function by using * specific hardware or coding. */ @@ -127,7 +127,7 @@ typedef struct { * @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 atomical and not necessarily + * @note The default implementation is non atomic and not necessarily * optimal. Low level drivers may optimize the function by using * specific hardware or coding. */ @@ -149,7 +149,7 @@ typedef struct { * @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 atomical and not necessarily + * @note The default implementation is non atomic and not necessarily * optimal. Low level drivers may optimize the function by using * specific hardware or coding. */ @@ -163,34 +163,10 @@ typedef struct { #endif /** - * @brief Writes a value on an I/O bus. + * @brief Reads a value from 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 atomical 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 a value from an I/O bus. - * - * @param[in] bus the I/O bus, pointer to a @p IOBus structure - * @return the bus bits + * @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 @@ -207,6 +183,135 @@ typedef struct { #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_ */ /** @} */