More XHAL SPI work. Improvements to code generator.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16283 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2023-06-15 09:21:26 +00:00
parent e9f92cb8ea
commit 6cd76684df
5 changed files with 1120 additions and 29 deletions

View File

@ -136,6 +136,497 @@ SPI_DRIVER_EXT_INIT_HOOK(self);
<dispose>
<implementation><![CDATA[ ]]></implementation>
</dispose>
<regular>
<method name="spiStartIgnoreI" ctype="msg_t">
<brief>Ignores data on the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts the transmission
of a series of idle words on the SPI bus and ignores the received
data.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<param name="n" ctype="size_t" dir="in">Number of frames to be
ignored.
</param>
<return>The operation status.</return>
<iclass />
<implementation><![CDATA[
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_ignore(self, n);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;]]></implementation>
</method>
<method name="spiStartIgnore" ctype="msg_t">
<brief>Ignores data on the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts the transmission
of a series of idle words on the SPI bus and ignores the received
data.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<param name="n" ctype="size_t" dir="in">Number of frames to be
ignored.
</param>
<return>The operation status.</return>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStartIgnoreI(self, n);
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiStartExchangeI" ctype="msg_t">
<brief>Exchanges data on the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts a simultaneous
transmit/receive operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="txbuf" ctype="const void *" dir="in">Pointer to the
transmit buffer.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
receive buffer.
</param>
<return>The operation status.</return>
<iclass />
<implementation><![CDATA[
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U) &&
(rxbuf != NULL) && (txbuf != NULL));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_exchange(self, n, txbuf, rxbuf);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;]]></implementation>
</method>
<method name="spiStartExchange" ctype="msg_t">
<brief>Exchanges data on the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts a simultaneous
transmit/receive operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="txbuf" ctype="const void *" dir="in">Pointer to the
transmit buffer.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
receive buffer.
</param>
<return>The operation status.</return>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStartExchangeI(self, n, txbuf, rxbuf);
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiStartSendI" ctype="msg_t">
<brief>Sends data over the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts a transmit
operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="txbuf" ctype="const void *" dir="in">Pointer to the
transmit buffer.
</param>
<return>The operation status.</return>
<iclass />
<implementation><![CDATA[
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U) && (txbuf != NULL));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_send(self, n, txbuf);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;]]></implementation>
</method>
<method name="spiStartSend" ctype="msg_t">
<brief>Sends data over the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts a transmit
operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="txbuf" ctype="const void *" dir="in">Pointer to the
transmit buffer.
</param>
<return>The operation status.</return>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStartSendI(self, n, txbuf);
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiStartReceiveI" ctype="msg_t">
<brief>Receives data from the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts a receive
operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
receive buffer.
</param>
<return>The operation status.</return>
<iclass />
<implementation><![CDATA[
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U) && (rxbuf != NULL));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_receive(self, n, rxbuf);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;]]></implementation>
</method>
<method name="spiStartReceive" ctype="msg_t">
<brief>Receives data from the SPI bus.</brief>
<details><![CDATA[This asynchronous function starts a receive
operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<post><![CDATA[At the end of the operation the callback is invoked,
if enabled.]]></post>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
receive buffer.
</param>
<return>The operation status.</return>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStartReceiveI(self, n, rxbuf);
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiStopTransferI" ctype="msg_t">
<brief>Stops the ongoing SPI operation.</brief>
<param name="np" ctype="size_t *" dir="out">Pointer to the counter
of frames not yet transferred or @p NULL.
</param>
<return>The operation status.</return>
<iclass />
<implementation><![CDATA[
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck(self != NULL);
osalDbgAssert((self->state == HAL_DRV_STATE_READY) ||
(self->state == HAL_DRV_STATE_ACTIVE) ||
(self->state == HAL_DRV_STATE_COMPLETE),
"invalid state");
if ((self->state == HAL_DRV_STATE_ACTIVE) ||
(self->state == HAL_DRV_STATE_COMPLETE)) {
/* Stopping transfer at low level.*/
msg = spi_lld_stop_transfer(self, sizep);
self->state = HAL_DRV_STATE_READY;
#if SPI_USE_SYNCHRONIZATION == TRUE
osalThreadResumeI(&self->sync_transfer, MSG_RESET);
#endif
}
else {
msg = HAL_RET_SUCCESS;
}
return msg;]]></implementation>
</method>
<method name="spiStopTransfer" ctype="msg_t">
<brief>Stops the ongoing SPI operation.</brief>
<param name="np" ctype="size_t *" dir="out">Pointer to the counter
of frames not yet transferred or @p NULL.
</param>
<return>The operation status.</return>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStopTransferI(self, sizep);
osalOsRescheduleS();
osalSysUnlock();
return msg;]]></implementation>
</method>
<condition check="SPI_USE_SYNCHRONIZATION == TRUE">
<method name="spiSynchronizeS" ctype="msg_t">
<note><![CDATA[This function can only be called by a single thread at time.]]></note>
<param name="timeout" ctype="sysinterval_t" dir="in">Synchronization
timeout.
</param>
<return>The synchronization result.</return>
<retval value="MSG_OK">If operation completed without errors.
</retval>
<retval value="MSG_TIMEOUT">If synchronization timed out.</retval>
<retval value="MSG_RESET">If the transfer has been stopped.</retval>
<sclass />
<implementation><![CDATA[
msg_t msg;
osalDbgCheck(self != NULL);
osalDbgAssert((self->state == HAL_DRV_STATE_ACTIVE) ||
(self->state == HAL_DRV_STATE_READY),
"invalid state");
if (self->state == HAL_DRV_STATE_ACTIVE) {
msg = osalThreadSuspendTimeoutS(&self->sync_transfer, timeout);
}
else {
msg = MSG_OK;
}
return msg;]]></implementation>
</method>
<method name="spiSynchronize" ctype="msg_t">
<note><![CDATA[This function can only be called by a single thread at time.]]></note>
<param name="timeout" ctype="sysinterval_t" dir="in">Synchronization
timeout.
</param>
<return>The synchronization result.</return>
<retval value="MSG_OK">If operation completed without errors.
</retval>
<retval value="MSG_TIMEOUT">If synchronization timed out.</retval>
<retval value="MSG_RESET">If the transfer has been stopped.</retval>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiSynchronizeS(self, timeout);
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiIgnore" ctype="msg_t">
<brief>Ignores data on the SPI bus.</brief>
<details><![CDATA[This synchronous function performs the transmission
of a series of idle words on the SPI bus and ignores the received
data.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<param name="n" ctype="size_t" dir="in">Number of frames to be
ignored.
</param>
<return>The operation status.</return>
<retval value="MSG_OK">If operation completed without errors.
</retval>
<retval value="MSG_TIMEOUT">If synchronization timed out.</retval>
<retval value="MSG_RESET">If the transfer has been stopped.</retval>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStartIgnoreI(self, n);
if (msg == MSG_OK) {
msg = spiSynchronizeS(self, TIME_INFINITE);
}
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiExchange" ctype="msg_t">
<brief>Exchanges data on the SPI bus.</brief>
<details><![CDATA[This synchronous function performs a simultaneous
transmit/receive operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="txbuf" ctype="const void *" dir="in">Pointer to
the
transmit buffer.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
receive buffer.
</param>
<return>The operation status.</return>
<retval value="MSG_OK">If operation completed without errors.
</retval>
<retval value="MSG_TIMEOUT">If synchronization timed out.</retval>
<retval value="MSG_RESET">If the transfer has been stopped.</retval>
<api />
<implementation><![CDATA[
msg_t msg;
osalSysLock();
msg = spiStartExchangeI(self, n, txbuf, rxbuf);
if (msg == MSG_OK) {
msg = spiSynchronizeS(self, TIME_INFINITE);
}
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiSend" ctype="msg_t">
<brief>Sends data over the SPI bus.</brief>
<details><![CDATA[This synchronous function performs a transmit
operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="txbuf" ctype="const void *" dir="in">Pointer to
the
transmit buffer.
</param>
<return>The operation status.</return>
<retval value="MSG_OK">If operation completed without errors.
</retval>
<retval value="MSG_TIMEOUT">If synchronization timed out.</retval>
<retval value="MSG_RESET">If the transfer has been stopped.</retval>
<api />
<implementation><![CDATA[
msg_t msg;
msg = spiStartSendI(self, n, txbuf);
if (msg == MSG_OK) {
msg = spiSynchronizeS(self, TIME_INFINITE);
}
osalSysUnlock();
return msg;]]></implementation>
</method>
<method name="spiReceive" ctype="msg_t">
<brief>Receives data from the SPI bus.</brief>
<details><![CDATA[This synchronous function performs a receive
operation.]]></details>
<pre><![CDATA[A slave must have been selected using @p spiSelectX().]]></pre>
<note><![CDATA[Buffers are organized as uint8_t arrays for frame
sizes below or equal to 8 bits else uint16_t is used.]]></note>
<param name="n" ctype="size_t" dir="in">Number of frames to be
exchanged.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
receive buffer.
</param>
<return>The operation status.</return>
<retval value="MSG_OK">If operation completed without errors.
</retval>
<retval value="MSG_TIMEOUT">If synchronization timed out.</retval>
<retval value="MSG_RESET">If the transfer has been stopped.</retval>
<api />
<implementation><![CDATA[
msg_t msg;
msg = spiStartReceiveI(spip, n, rxbuf);
if (msg == MSG_OK) {
msg = spiSynchronizeS(spip, TIME_INFINITE);
}
osalSysUnlock();
return msg;]]></implementation>
</method>
</condition>
</regular>
<inline>
<condition check="SPI_SELECT_MODE == SPI_SELECT_MODE_LLD">
<method name="spiSelectX" ctype="void">
@ -168,23 +659,23 @@ palSetLine(self->config->ssline);]]></implementation>
<method name="spiSelectX" ctype="void">
<implementation><![CDATA[
palClearPort(self->config->ssport, (spip)->config->ssmask);]]></implementation>
palClearPort(self->config->ssport, self->config->ssmask);]]></implementation>
</method>
<method name="spiUnselectX" ctype="void">
<implementation><![CDATA[
palSetPort(self->config->ssport, (spip)->config->ssmask);]]></implementation>
palSetPort(self->config->ssport, self->config->ssmask);]]></implementation>
</method>
<elseif check="SPI_SELECT_MODE == SPI_SELECT_MODE_PAD" />
<method name="spiSelectX" ctype="void">
<implementation><![CDATA[
palClearPad(self->config->ssport, (spip)->config->sspad);]]></implementation>
palClearPad(self->config->ssport, self->config->sspad);]]></implementation>
</method>
<method name="spiUnselectX" ctype="void">
<implementation><![CDATA[
palSetPad(self->config->ssport, (spip)->config->sspad);]]></implementation>
palSetPad(self->config->ssport, self->config->sspad);]]></implementation>
</method>
</condition>
</inline>

View File

@ -278,6 +278,24 @@ extern "C" {
/* Methods of hal_spi_driver_c.*/
void *__spi_objinit_impl(void *ip, const void *vmt);
void __spi_dispose_impl(void *ip);
msg_t spiStartIgnoreI(void *ip, size_t n);
msg_t spiStartIgnore(void *ip, size_t n);
msg_t spiStartExchangeI(void *ip, size_t n, const void *txbuf, void *rxbuf);
msg_t spiStartExchange(void *ip, size_t n, const void *txbuf, void *rxbuf);
msg_t spiStartSendI(void *ip, size_t n, const void *txbuf);
msg_t spiStartSend(void *ip, size_t n, const void *txbuf);
msg_t spiStartReceiveI(void *ip, size_t n, void *rxbuf);
msg_t spiStartReceive(void *ip, size_t n, void *rxbuf);
msg_t spiStopTransferI(void *ip, size_t *np);
msg_t spiStopTransfer(void *ip, size_t *np);
#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined (__DOXYGEN__)
msg_t spiSynchronizeS(void *ip, sysinterval_t timeout);
msg_t spiSynchronize(void *ip, sysinterval_t timeout);
msg_t spiIgnore(void *ip, size_t n);
msg_t spiExchange(void *ip, size_t n, const void *txbuf, void *rxbuf);
msg_t spiSend(void *ip, size_t n, const void *txbuf);
msg_t spiReceive(void *ip, size_t n, void *rxbuf);
#endif /* SPI_USE_SYNCHRONIZATION == TRUE */
/* Regular functions.*/
void spiInit(void);
#ifdef __cplusplus
@ -370,14 +388,14 @@ CC_FORCE_INLINE
static inline void spiSelectX(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
palClearPort(self->config->ssport, (spip)->config->ssmask);
palClearPort(self->config->ssport, self->config->ssmask);
}
CC_FORCE_INLINE
static inline void spiUnselectX(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
palSetPort(self->config->ssport, (spip)->config->ssmask);
palSetPort(self->config->ssport, self->config->ssmask);
}
#elif SPI_SELECT_MODE == SPI_SELECT_MODE_PAD
@ -385,14 +403,14 @@ CC_FORCE_INLINE
static inline void spiSelectX(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
palClearPad(self->config->ssport, (spip)->config->sspad);
palClearPad(self->config->ssport, self->config->sspad);
}
CC_FORCE_INLINE
static inline void spiUnselectX(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
palSetPad(self->config->ssport, (spip)->config->sspad);
palSetPad(self->config->ssport, self->config->sspad);
}
#endif /* SPI_SELECT_MODE == SPI_SELECT_MODE_LLD */
/** @} */

View File

@ -135,6 +135,573 @@ const struct hal_spi_driver_vmt __hal_spi_driver_vmt = {
.configure = NULL /* Method not found.*/
};
/**
* @name Regular methods of hal_spi_driver_c
* @{
*/
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Ignores data on the SPI bus.
* @details This asynchronous function starts the transmission of a series
* of idle words on the SPI bus and ignores the received data.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be ignored.
* @return The operation status.
*
* @iclass
*/
msg_t spiStartIgnoreI(void *ip, size_t n) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_ignore(self, n);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Ignores data on the SPI bus.
* @details This asynchronous function starts the transmission of a series
* of idle words on the SPI bus and ignores the received data.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be ignored.
* @return The operation status.
*
* @api
*/
msg_t spiStartIgnore(void *ip, size_t n) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStartIgnoreI(self, n);
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Exchanges data on the SPI bus.
* @details This asynchronous function starts a simultaneous
* transmit/receive operation.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[in] txbuf Pointer to the transmit buffer.
* @param[out] rxbuf Pointer to the receive buffer.
* @return The operation status.
*
* @iclass
*/
msg_t spiStartExchangeI(void *ip, size_t n, const void *txbuf, void *rxbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U) &&
(rxbuf != NULL) && (txbuf != NULL));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_exchange(self, n, txbuf, rxbuf);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Exchanges data on the SPI bus.
* @details This asynchronous function starts a simultaneous
* transmit/receive operation.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[in] txbuf Pointer to the transmit buffer.
* @param[out] rxbuf Pointer to the receive buffer.
* @return The operation status.
*
* @api
*/
msg_t spiStartExchange(void *ip, size_t n, const void *txbuf, void *rxbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStartExchangeI(self, n, txbuf, rxbuf);
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Sends data over the SPI bus.
* @details This asynchronous function starts a transmit operation.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[in] txbuf Pointer to the transmit buffer.
* @return The operation status.
*
* @iclass
*/
msg_t spiStartSendI(void *ip, size_t n, const void *txbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U) && (txbuf != NULL));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_send(self, n, txbuf);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Sends data over the SPI bus.
* @details This asynchronous function starts a transmit operation.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[in] txbuf Pointer to the transmit buffer.
* @return The operation status.
*
* @api
*/
msg_t spiStartSend(void *ip, size_t n, const void *txbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStartSendI(self, n, txbuf);
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Receives data from the SPI bus.
* @details This asynchronous function starts a receive operation.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[out] rxbuf Pointer to the receive buffer.
* @return The operation status.
*
* @iclass
*/
msg_t spiStartReceiveI(void *ip, size_t n, void *rxbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck((self != NULL) && (n > 0U) && (rxbuf != NULL));
#if SPI_SUPPORTS_CIRCULAR
osalDbgCheck((self->config->circular == false) || ((n & 1U) == 0U));
#endif
osalDbgAssert(self->state == HAL_DRV_STATE_READY, "not ready");
self->state = HAL_DRV_STATE_ACTIVE;
msg = spi_lld_receive(self, n, rxbuf);
#if SPI_USE_ASSERT_ON_ERROR == TRUE
osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed");
#endif
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Receives data from the SPI bus.
* @details This asynchronous function starts a receive operation.
* @pre A slave must have been selected using @p spiSelectX().
* @post At the end of the operation the callback is invoked, if
* enabled.
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[out] rxbuf Pointer to the receive buffer.
* @return The operation status.
*
* @api
*/
msg_t spiStartReceive(void *ip, size_t n, void *rxbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStartReceiveI(self, n, rxbuf);
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Stops the ongoing SPI operation.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[out] np Pointer to the counter of frames not yet
* transferred or @p NULL.
* @return The operation status.
*
* @iclass
*/
msg_t spiStopTransferI(void *ip, size_t *np) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalDbgCheckClassI();
osalDbgCheck(self != NULL);
osalDbgAssert((self->state == HAL_DRV_STATE_READY) ||
(self->state == HAL_DRV_STATE_ACTIVE) ||
(self->state == HAL_DRV_STATE_COMPLETE),
"invalid state");
if ((self->state == HAL_DRV_STATE_ACTIVE) ||
(self->state == HAL_DRV_STATE_COMPLETE)) {
/* Stopping transfer at low level.*/
msg = spi_lld_stop_transfer(self, sizep);
self->state = HAL_DRV_STATE_READY;
#if SPI_USE_SYNCHRONIZATION == TRUE
osalThreadResumeI(&self->sync_transfer, MSG_RESET);
#endif
}
else {
msg = HAL_RET_SUCCESS;
}
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Stops the ongoing SPI operation.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[out] np Pointer to the counter of frames not yet
* transferred or @p NULL.
* @return The operation status.
*
* @api
*/
msg_t spiStopTransfer(void *ip, size_t *np) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStopTransferI(self, sizep);
osalOsRescheduleS();
osalSysUnlock();
return msg;
}
#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined (__DOXYGEN__)
/**
* @memberof hal_spi_driver_c
* @public
*
* @note This function can only be called by a single thread at time.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] timeout Synchronization timeout.
* @return The synchronization result.
* @retval MSG_OK If operation completed without errors.
* @retval MSG_TIMEOUT If synchronization timed out.
* @retval MSG_RESET If the transfer has been stopped.
*
* @sclass
*/
msg_t spiSynchronizeS(void *ip, sysinterval_t timeout) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalDbgCheck(self != NULL);
osalDbgAssert((self->state == HAL_DRV_STATE_ACTIVE) ||
(self->state == HAL_DRV_STATE_READY),
"invalid state");
if (self->state == HAL_DRV_STATE_ACTIVE) {
msg = osalThreadSuspendTimeoutS(&self->sync_transfer, timeout);
}
else {
msg = MSG_OK;
}
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @note This function can only be called by a single thread at time.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] timeout Synchronization timeout.
* @return The synchronization result.
* @retval MSG_OK If operation completed without errors.
* @retval MSG_TIMEOUT If synchronization timed out.
* @retval MSG_RESET If the transfer has been stopped.
*
* @api
*/
msg_t spiSynchronize(void *ip, sysinterval_t timeout) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiSynchronizeS(self, timeout);
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Ignores data on the SPI bus.
* @details This synchronous function performs the transmission of a series
* of idle words on the SPI bus and ignores the received data.
* @pre A slave must have been selected using @p spiSelectX().
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be ignored.
* @return The operation status.
* @retval MSG_OK If operation completed without errors.
* @retval MSG_TIMEOUT If synchronization timed out.
* @retval MSG_RESET If the transfer has been stopped.
*
* @api
*/
msg_t spiIgnore(void *ip, size_t n) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStartIgnoreI(self, n);
if (msg == MSG_OK) {
msg = spiSynchronizeS(self, TIME_INFINITE);
}
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Exchanges data on the SPI bus.
* @details This synchronous function performs a simultaneous
* transmit/receive operation.
* @pre A slave must have been selected using @p spiSelectX().
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[in] txbuf Pointer to the transmit buffer.
* @param[out] rxbuf Pointer to the receive buffer.
* @return The operation status.
* @retval MSG_OK If operation completed without errors.
* @retval MSG_TIMEOUT If synchronization timed out.
* @retval MSG_RESET If the transfer has been stopped.
*
* @api
*/
msg_t spiExchange(void *ip, size_t n, const void *txbuf, void *rxbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
osalSysLock();
msg = spiStartExchangeI(self, n, txbuf, rxbuf);
if (msg == MSG_OK) {
msg = spiSynchronizeS(self, TIME_INFINITE);
}
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Sends data over the SPI bus.
* @details This synchronous function performs a transmit operation.
* @pre A slave must have been selected using @p spiSelectX().
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[in] txbuf Pointer to the transmit buffer.
* @return The operation status.
* @retval MSG_OK If operation completed without errors.
* @retval MSG_TIMEOUT If synchronization timed out.
* @retval MSG_RESET If the transfer has been stopped.
*
* @api
*/
msg_t spiSend(void *ip, size_t n, const void *txbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
msg = spiStartSendI(self, n, txbuf);
if (msg == MSG_OK) {
msg = spiSynchronizeS(self, TIME_INFINITE);
}
osalSysUnlock();
return msg;
}
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Receives data from the SPI bus.
* @details This synchronous function performs a receive operation.
* @pre A slave must have been selected using @p spiSelectX().
* @note Buffers are organized as uint8_t arrays for frame sizes below
* or equal to 8 bits else uint16_t is used.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] n Number of frames to be exchanged.
* @param[out] rxbuf Pointer to the receive buffer.
* @return The operation status.
* @retval MSG_OK If operation completed without errors.
* @retval MSG_TIMEOUT If synchronization timed out.
* @retval MSG_RESET If the transfer has been stopped.
*
* @api
*/
msg_t spiReceive(void *ip, size_t n, void *rxbuf) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
msg_t msg;
msg = spiStartReceiveI(spip, n, rxbuf);
if (msg == MSG_OK) {
msg = spiSynchronizeS(spip, TIME_INFINITE);
}
osalSysUnlock();
return msg;
}
#endif /* SPI_USE_SYNCHRONIZATION == TRUE */
/** @} */
#endif /* HAL_USE_SPI == TRUE */
/** @} */

View File

@ -688,40 +688,51 @@ ${ccode.MakeVariableDeclaration(ccode.indentation "vmt" vmtctype)}
[#--
-- This macro generates regular methods from an XML node.
--]
[#macro GenerateMethods node=[] classctype="no-ctype" modifiers=[]]
[#list node.* as node]
[#if node?node_name == "method"]
[#local method = node]
[#macro GenerateMethods node=[] classctype="no-ctype" modifiers=[] nodoc=false]
[#list node.* as this]
[#if this?node_name == "method"]
[#local method = this]
[#local methodname = GetNodeName(method)
methodsname = GetMethodShortName(method)
methodretctype = GetMethodCType(method)
methodimpl = method.implementation[0]!""]
[#assign generated = true]
[#if !nodoc]
[@doxygen.EmitFullCommentFromNode indent="" node=method
extraname="ip" extradir="both"
extratext="Pointer to a @p " + classctype + " instance."
memberof=classctype /]
[/#if]
[#if modifiers?seq_contains("static") && modifiers?seq_contains("inline")]
CC_FORCE_INLINE
[/#if]
[@ccode.GeneratePrototypeFromNode modifiers = modifiers
params = ["void *ip"]
node=method /] {
node = method /] {
${classctype} *self = (${classctype} *)ip;
[@ccode.GenerateIndentedCCode indent=ccode.indentation
ccode=methodimpl /]
}
[#elseif node?node_name == "condition"]
[#local condition = node]
[#if this?has_next]
[/#if]
[#elseif this?node_name == "condition"]
[#local condition = this]
[#local condcheck = (condition.@check[0]!"1")?trim]
#if (${condcheck}) || defined (__DOXYGEN__)
[@GenerateMethods node = condition
classctype = classctype
modifiers = modifiers /]
modifiers = modifiers
nodoc = nodoc /]
#endif /* ${condcheck} */
[/#if]
[#if node?has_next]
[#elseif this?node_name == "elseif"]
[#local nodoc = true]
[#local condcheck = (this.@check[0]!"")?trim]
[#if condcheck?length == 0]
#else
[#else]
#elif ${condcheck}
[/#if]
[/#if]
[/#list]
[/#macro]

View File

@ -568,11 +568,13 @@
</xs:complexType>
<xs:complexType name="conditionalRegularMethodsType">
<xs:choice maxOccurs="unbounded" minOccurs="1">
<xs:element name="method" type="regularMethodType"
maxOccurs="1" minOccurs="1"></xs:element>
<xs:element name="condition"
type="conditionalRegularMethodsType" maxOccurs="1" minOccurs="1">
<xs:element name="method" type="regularMethodType" maxOccurs="1"
minOccurs="1">
</xs:element>
<xs:element name="condition" type="conditionalRegularMethodsType"
maxOccurs="1" minOccurs="1">
</xs:element>
<xs:element name="elseif" type="elseifType" maxOccurs="1" minOccurs="1"></xs:element>
</xs:choice>
<xs:attribute name="check" type="xs:string" use="required"></xs:attribute>
</xs:complexType>
@ -604,14 +606,16 @@
<xs:element name="function" type="functionType" maxOccurs="1"
minOccurs="1">
</xs:element>
<xs:element name="group" type="groupedFunctionsType"
maxOccurs="1" minOccurs="1">
<xs:element name="group" type="groupedFunctionsType" maxOccurs="1"
minOccurs="1">
</xs:element>
<xs:element name="condition" type="conditionalFunctionsType"
maxOccurs="1" minOccurs="1">
<xs:element name="condition" type="conditionalFunctionsType" maxOccurs="1"
minOccurs="1">
</xs:element>
<xs:element name="elseif" type="elseifType" maxOccurs="1" minOccurs="1"></xs:element>
<xs:element name="verbatim" type="xs:string" maxOccurs="1"
minOccurs="1">
</xs:element>
<xs:element name="verbatim" type="xs:string" maxOccurs="1"
minOccurs="1"></xs:element>
</xs:choice>
<xs:attribute name="check" type="xs:string" use="required"></xs:attribute>
</xs:complexType>