From 8e7a0fbb268626bec2310ac48b5c88d967d56199 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Fri, 25 May 2018 07:45:18 +0000 Subject: Added an enhanced variant of QSPI named WSPI. QSPI will be deprecated when WSPI will be phased in. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@12043 110e8d01-0319-4d1e-a829-52ad28d1bb01 --- os/hal/include/hal.h | 5 + os/hal/include/hal_wspi.h | 361 ++++++++++++++++++++++++++++++++++++++++++ os/hal/src/hal.c | 3 + os/hal/src/hal_wspi.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 761 insertions(+) create mode 100644 os/hal/include/hal_wspi.h create mode 100644 os/hal/src/hal_wspi.c diff --git a/os/hal/include/hal.h b/os/hal/include/hal.h index 6eb7ccfb8..b464fdcda 100644 --- a/os/hal/include/hal.h +++ b/os/hal/include/hal.h @@ -110,6 +110,10 @@ #define HAL_USE_WDG FALSE #endif +#if !defined(HAL_USE_WSPI) +#define HAL_USE_WSPI FALSE +#endif + /* Low Level HAL support.*/ #include "hal_lld.h" @@ -146,6 +150,7 @@ #include "hal_uart.h" #include "hal_usb.h" #include "hal_wdg.h" +#include "hal_wspi.h" /* * The ST driver is a special case, it is only included if the OSAL is diff --git a/os/hal/include/hal_wspi.h b/os/hal/include/hal_wspi.h new file mode 100644 index 000000000..3d7a9a1aa --- /dev/null +++ b/os/hal/include/hal_wspi.h @@ -0,0 +1,361 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_wspi.h + * @brief WSPI Driver macros and structures. + * + * @addtogroup WSPI + * @{ + */ + +#ifndef HAL_WSPI_H +#define HAL_WSPI_H + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name Transfer options + * @note The Low Level Driver should undef those modes that are not + * supported. The LLD can also define additional modes or reorder + * the bit masks in a more convenient way for the underlying + * implementation. It is important however to maintain the same + * same for the same functionality. + * @{ + */ +#define WSPI_CFG_INSTRUCTION_MODE_MASK (7LU << 0LU) +#define WSPI_CFG_INSTRUCTION_MODE_NONE (0LU << 0LU) +#define WSPI_CFG_INSTRUCTION_MODE_ONE_LINES (1LU << 0LU) +#define WSPI_CFG_INSTRUCTION_MODE_TWO_LINES (2LU << 0LU) +#define WSPI_CFG_INSTRUCTION_MODE_FOUR_LINES (3LU << 0LU) +#define WSPI_CFG_INSTRUCTION_MODE_EIGHT_LINES (4LU << 0LU) + +#define WSPI_CFG_INSTRUCTION_DDR (1LU << 3LU) + +#define WSPI_CFG_INSTRUCTION_SIZE_MASK (3LU << 4LU) +#define WSPI_CFG_INSTRUCTION_SIZE_8 (0LU << 4LU) +#define WSPI_CFG_INSTRUCTION_SIZE_16 (1LU << 4LU) +#define WSPI_CFG_INSTRUCTION_SIZE_24 (2LU << 4LU) +#define WSPI_CFG_INSTRUCTION_SIZE_32 (3LU << 4LU) + +#define WSPI_CFG_ADDR_MODE_MASK (7LU << 8LU) +#define WSPI_CFG_ADDR_MODE_NONE (0LU << 8LU) +#define WSPI_CFG_ADDR_MODE_ONE_LINE (1LU << 8LU) +#define WSPI_CFG_ADDR_MODE_TWO_LINES (2LU << 8LU) +#define WSPI_CFG_ADDR_MODE_FOUR_LINES (3LU << 8LU) +#define WSPI_CFG_ADDR_MODE_EIGHT_LINES (4LU << 8LU) + +#define WSPI_CFG_ADDR_DDR (1LU << 11LU) + +#define WSPI_CFG_ADDR_SIZE_MASK (3LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_8 (0LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_16 (1LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_24 (2LU << 12LU) +#define WSPI_CFG_ADDR_SIZE_32 (3LU << 12LU) + +#define WSPI_CFG_ALT_MODE_MASK (7LU << 16LU) +#define WSPI_CFG_ALT_MODE_NONE (0LU << 16LU) +#define WSPI_CFG_ALT_MODE_ONE_LINE (1LU << 16LU) +#define WSPI_CFG_ALT_MODE_TWO_LINES (2LU << 16LU) +#define WSPI_CFG_ALT_MODE_FOUR_LINES (3LU << 16LU) +#define WSPI_CFG_ALT_MODE_EIGHT_LINES (4LU << 16LU) + +#define WSPI_CFG_ALT_DDR (1LU << 19LU) + +#define WSPI_CFG_ALT_SIZE_MASK (3LU << 20LU) +#define WSPI_CFG_ALT_SIZE_8 (0LU << 20LU) +#define WSPI_CFG_ALT_SIZE_16 (1LU << 20LU) +#define WSPI_CFG_ALT_SIZE_24 (2LU << 20LU) +#define WSPI_CFG_ALT_SIZE_32 (3LU << 20LU) + +#define WSPI_CFG_DATA_MODE_MASK (7LU << 24LU) +#define WSPI_CFG_DATA_MODE_NONE (0LU << 24LU) +#define WSPI_CFG_DATA_MODE_ONE_LINE (1LU << 24LU) +#define WSPI_CFG_DATA_MODE_TWO_LINES (2LU << 24LU) +#define WSPI_CFG_DATA_MODE_FOUR_LINES (3LU << 24LU) +#define WSPI_CFG_DATA_MODE_EIGHT_LINES (4LU << 24LU) + +#define WSPI_CFG_DATA_DDR (1LU << 27LU) + +#define WSPI_CFG_SIOO (1LU << 31LU) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name WSPI configuration options + * @{ + */ +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_WAIT) || defined(__DOXYGEN__) +#define WSPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p wspiAcquireBus() and @p wspiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(WSPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define WSPI_USE_MUTUAL_EXCLUSION TRUE +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + WSPI_UNINIT = 0, /**< Not initialized. */ + WSPI_STOP = 1, /**< Stopped. */ + WSPI_READY = 2, /**< Ready. */ + WSPI_ACTIVE = 3, /**< Exchanging data. */ + WSPI_COMPLETE = 4, /**< Asynchronous operation complete. */ + WSPI_MEMMAP = 5 /**< In memory mapped mode. */ +} wspistate_t; + +/** + * @brief Type of a WSPI command descriptor. + */ +typedef struct { + /** + * @brief Transfer configuration field. + */ + uint32_t cfg; + /** + * @brief Command phase data. + */ + uint32_t cmd; + /** + * @brief Address phase data. + */ + uint32_t addr; + /** + * @brief Alternate phase data. + */ + uint32_t alt; + /** + * @brief Number of dummy cycles to be inserted. + */ + uint32_t dummy; +} wspi_command_t; + +#include "hal_wspi_lld.h" + +#if !defined(WSPI_SUPPORTS_MEMMAP) +#error "low level does not define WSPI_SUPPORTS_MEMMAP" +#endif + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Sends a command without data phase. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * + * @iclass + */ +#define wspiStartCommandI(wspip, cmdp) { \ + osalDbgAssert(((cmdp)->cfg & WSPI_CFG_DATA_MODE_MASK) == \ + WSPI_CFG_DATA_MODE_NONE, \ + "data mode specified"); \ + (wspip)->state = WSPI_ACTIVE; \ + wspi_lld_command(wspip, cmdp); \ +} + +/** + * @brief Sends data over the WSPI bus. + * @details This asynchronous function starts a transmit operation. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send or zero if no data phase + * @param[in] txbuf the pointer to the transmit buffer + * + * @iclass + */ +#define wspiStartSendI(wspip, cmdp, n, txbuf) { \ + osalDbgAssert(((cmdp)->cfg & WSPI_CFG_DATA_MODE_MASK) != \ + WSPI_CFG_DATA_MODE_NONE, \ + "data mode required"); \ + (wspip)->state = WSPI_ACTIVE; \ + wspi_lld_send(wspip, cmdp, n, txbuf); \ +} + +/** + * @brief Receives data from the WSPI bus. + * @details This asynchronous function starts a receive operation. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to receive or zero if no data phase + * @param[out] rxbuf the pointer to the receive buffer + * + * @iclass + */ +#define wspiStartReceiveI(wspip, cmdp, n, rxbuf) { \ + osalDbgAssert(((cmdp)->cfg & WSPI_CFG_DATA_MODE_MASK) != \ + WSPI_CFG_DATA_MODE_NONE, \ + "data mode required"); \ + (wspip)->state = WSPI_ACTIVE; \ + wspi_lld_receive(wspip, cmdp, n, rxbuf); \ +} + +#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a WSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @iclass + */ +#define wspiMapFlashI(wspip, cmdp, addrp) \ + wspi_lld_map_flash(wspip, cmdp, addrp) + +/** + * @brief Maps in memory space a WSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @iclass + */ +#define wspiUnmapFlashI(wspip) \ + wspi_lld_unmap_flash(wspip) +#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ +/** @} */ + +/** + * @name Low level driver helper macros + * @{ + */ +#if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Wakes up the waiting thread. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +#define _wspi_wakeup_isr(wspip) { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(wspip)->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} +#else /* !WSPI_USE_WAIT */ +#define _wspi_wakeup_isr(wspip) +#endif /* !WSPI_USE_WAIT */ + +/** + * @brief Common ISR code. + * @details This code handles the portable part of the ISR code: + * - Callback invocation. + * - Waiting thread wakeup, if any. + * - Driver state transitions. + * . + * @note This macro is meant to be used in the low level drivers + * implementation only. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @notapi + */ +#define _wspi_isr_code(wspip) { \ + if ((wspip)->config->end_cb) { \ + (wspip)->state = WSPI_COMPLETE; \ + (wspip)->config->end_cb(wspip); \ + if ((wspip)->state == WSPI_COMPLETE) \ + (wspip)->state = WSPI_READY; \ + } \ + else \ + (wspip)->state = WSPI_READY; \ + _wspi_wakeup_isr(wspip); \ +} +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void wspiInit(void); + void wspiObjectInit(WSPIDriver *wspip); + void wspiStart(WSPIDriver *wspip, const WSPIConfig *config); + void wspiStop(WSPIDriver *wspip); + void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp); + void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf); + void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf); +#if WSPI_USE_WAIT == TRUE + void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp); + void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf); + void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf); +#endif +#if WSPI_SUPPORTS_MEMMAP == TRUE +void wspiMapFlash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp); +void wspiUnmapFlash(WSPIDriver *wspip); +#endif +#if WSPI_USE_MUTUAL_EXCLUSION == TRUE + void wspiAcquireBus(WSPIDriver *wspip); + void wspiReleaseBus(WSPIDriver *wspip); +#endif +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_WSPI == TRUE */ + +#endif /* HAL_WSPI_H */ + +/** @} */ diff --git a/os/hal/src/hal.c b/os/hal/src/hal.c index 1bfa7550f..42b926619 100644 --- a/os/hal/src/hal.c +++ b/os/hal/src/hal.c @@ -131,6 +131,9 @@ void halInit(void) { #if (HAL_USE_WDG == TRUE) || defined(__DOXYGEN__) wdgInit(); #endif +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + wspiInit(); +#endif /* Community driver overlay initialization.*/ #if defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__) diff --git a/os/hal/src/hal_wspi.c b/os/hal/src/hal_wspi.c new file mode 100644 index 000000000..10a0aec24 --- /dev/null +++ b/os/hal/src/hal_wspi.c @@ -0,0 +1,392 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file hal_wspi.c + * @brief WSPI Driver code. + * + * @addtogroup WSPI + * @{ + */ + +#include "hal.h" + +#if (HAL_USE_WSPI == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief WSPI Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void wspiInit(void) { + + wspi_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p WSPIDriver structure. + * + * @param[out] wspip pointer to the @p WSPIDriver object + * + * @init + */ +void wspiObjectInit(WSPIDriver *wspip) { + + wspip->state = WSPI_STOP; + wspip->config = NULL; +#if WSPI_USE_WAIT == TRUE + wspip->thread = NULL; +#endif +#if WSPI_USE_MUTUAL_EXCLUSION == TRUE + osalMutexObjectInit(&wspip->mutex); +#endif +#if defined(WSPI_DRIVER_EXT_INIT_HOOK) + WSPI_DRIVER_EXT_INIT_HOOK(wspip); +#endif +} + +/** + * @brief Configures and activates the WSPI peripheral. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] config pointer to the @p WSPIConfig object + * + * @api + */ +void wspiStart(WSPIDriver *wspip, const WSPIConfig *config) { + + osalDbgCheck((wspip != NULL) && (config != NULL)); + + osalSysLock(); + + osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY), + "invalid state"); + + wspip->config = config; + wspi_lld_start(wspip); + wspip->state = WSPI_READY; + + osalSysUnlock(); +} + +/** + * @brief Deactivates the WSPI peripheral. + * @note Deactivating the peripheral also enforces a release of the slave + * select line. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @api + */ +void wspiStop(WSPIDriver *wspip) { + + osalDbgCheck(wspip != NULL); + + osalSysLock(); + + osalDbgAssert((wspip->state == WSPI_STOP) || (wspip->state == WSPI_READY), + "invalid state"); + + wspi_lld_stop(wspip); + wspip->config = NULL; + wspip->state = WSPI_STOP; + + osalSysUnlock(); +} + +/** + * @brief Sends a command without data phase. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * + * @api + */ +void wspiStartCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + + wspiStartCommandI(wspip, cmdp); + + osalSysUnlock(); +} + +/** + * @brief Sends a command with data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void wspiStartSend(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + osalDbgCheck((n > 0U) && (txbuf != NULL)); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + + wspiStartSendI(wspip, cmdp, n, txbuf); + + osalSysUnlock(); +} + +/** + * @brief Sends a command then receives data over the WSPI bus. + * @post At the end of the operation the configured callback is invoked. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void wspiStartReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + osalDbgCheck((n > 0U) && (rxbuf != NULL)); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + + wspiStartReceiveI(wspip, cmdp, n, rxbuf); + + osalSysUnlock(); +} + +#if (WSPI_USE_WAIT == TRUE) || defined(__DOXYGEN__) +/** + * @brief Sends a command without data phase. + * @pre In order to use this function the option @p WSPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * + * @api + */ +void wspiCommand(WSPIDriver *wspip, const wspi_command_t *cmdp) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) == WSPI_CFG_DATA_MODE_NONE); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + osalDbgAssert(wspip->config->end_cb == NULL, "has callback"); + + wspiStartCommandI(wspip, cmdp); + (void) osalThreadSuspendS(&wspip->thread); + + osalSysUnlock(); +} + +/** + * @brief Sends a command with data over the WSPI bus. + * @pre In order to use this function the option @p WSPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[in] txbuf the pointer to the transmit buffer + * + * @api + */ +void wspiSend(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, const uint8_t *txbuf) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + osalDbgCheck((n > 0U) && (txbuf != NULL)); + osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + osalDbgAssert(wspip->config->end_cb == NULL, "has callback"); + + wspiStartSendI(wspip, cmdp, n, txbuf); + (void) osalThreadSuspendS(&wspip->thread); + + osalSysUnlock(); +} + +/** + * @brief Sends a command then receives data over the WSPI bus. + * @pre In order to use this function the option @p WSPI_USE_WAIT must be + * enabled. + * @pre In order to use this function the driver must have been configured + * without callbacks (@p end_cb = @p NULL). + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[in] n number of bytes to send + * @param[out] rxbuf the pointer to the receive buffer + * + * @api + */ +void wspiReceive(WSPIDriver *wspip, const wspi_command_t *cmdp, + size_t n, uint8_t *rxbuf) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + osalDbgCheck((n > 0U) && (rxbuf != NULL)); + osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + osalDbgAssert(wspip->config->end_cb == NULL, "has callback"); + + wspiStartReceiveI(wspip, cmdp, n, rxbuf); + (void) osalThreadSuspendS(&wspip->thread); + + osalSysUnlock(); +} +#endif /* WSPI_USE_WAIT == TRUE */ + +#if (WSPI_SUPPORTS_MEMMAP == TRUE) || defined(__DOXYGEN__) +/** + * @brief Maps in memory space a WSPI flash device. + * @pre The memory flash device must be initialized appropriately + * before mapping it in memory space. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * @param[in] cmdp pointer to the command descriptor + * @param[out] addrp pointer to the memory start address of the mapped + * flash or @p NULL + * + * @api + */ +void wspiMapFlash(WSPIDriver *wspip, + const wspi_command_t *cmdp, + uint8_t **addrp) { + + osalDbgCheck((wspip != NULL) && (cmdp != NULL)); + osalDbgCheck((cmdp->cfg & WSPI_CFG_DATA_MODE_MASK) != WSPI_CFG_DATA_MODE_NONE); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_READY, "not ready"); + + wspiMapFlashI(wspip, cmdp, addrp); + wspip->state = WSPI_MEMMAP; + + osalSysUnlock(); +} + +/** + * @brief Unmaps from memory space a WSPI flash device. + * @post The memory flash device must be re-initialized for normal + * commands exchange. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @api + */ +void wspiUnmapFlash(WSPIDriver *wspip) { + + osalDbgCheck(wspip != NULL); + + osalSysLock(); + + osalDbgAssert(wspip->state == WSPI_MEMMAP, "not ready"); + + wspiUnmapFlashI(wspip); + wspip->state = WSPI_READY; + + osalSysUnlock(); +} +#endif /* WSPI_SUPPORTS_MEMMAP == TRUE */ + +#if (WSPI_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the WSPI bus. + * @details This function tries to gain ownership to the WSPI bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @api + */ +void wspiAcquireBus(WSPIDriver *wspip) { + + osalDbgCheck(wspip != NULL); + + osalMutexLock(&wspip->mutex); +} + +/** + * @brief Releases exclusive access to the WSPI bus. + * @pre In order to use this function the option @p WSPI_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] wspip pointer to the @p WSPIDriver object + * + * @api + */ +void wspiReleaseBus(WSPIDriver *wspip) { + + osalDbgCheck(wspip != NULL); + + osalMutexUnlock(&wspip->mutex); +} +#endif /* WSPI_USE_MUTUAL_EXCLUSION == TRUE */ + +#endif /* HAL_USE_WSPI == TRUE */ + +/** @} */ -- cgit v1.2.3