More SPI-related code in XHAL.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16286 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2023-06-16 11:32:07 +00:00
parent a6e31ca42c
commit e79ef9f801
11 changed files with 511 additions and 83 deletions

View File

@ -17,8 +17,6 @@
<define name="HAL_DRV_STATE_STARTING" value="3U" />
<define name="HAL_DRV_STATE_READY" value="4U" />
<define name="HAL_DRV_STATE_ACTIVE" value="5U" />
<define name="HAL_DRV_STATE_COMPLETE" value="6U" />
<define name="HAL_DRV_STATE_ERROR" value="7U" />
</group>
</definitions_early>
<configs>
@ -66,6 +64,9 @@
<field name="state" ctype="driver_state_t">
<brief>Driver state.</brief>
</field>
<field name="config" ctype="const void$I*">
<brief>Associated configuration structure.</brief>
</field>
<field name="arg" ctype="void$I*">
<brief>Driver argument.</brief>
</field>
@ -89,12 +90,13 @@
<methods>
<objinit callsuper="true">
<implementation><![CDATA[
self->state = HAL_DRV_STATE_STOP;
self->arg = NULL;
self->state = HAL_DRV_STATE_STOP;
self->arg = NULL;
self->config = NULL;
osalMutexObjectInit(&self->mutex);
#if HAL_USE_REGISTRY == TRUE
self->id = 0U;
self->name = "unk";
self->id = 0U;
self->name = "unk";
drv_reg_insert(self);
#endif]]></implementation>
</objinit>

View File

@ -7,6 +7,12 @@
<import>hal_base_driver.xml</import>
</imports>
<public>
<definitions_early>
<group description="Callback-related driver states">
<define name="HAL_DRV_STATE_COMPLETE" value="6U" />
<define name="HAL_DRV_STATE_ERROR" value="7U" />
</group>
</definitions_early>
<types>
<typedef name="hal_cb_t">
<brief>Generic HAL notification callback type.</brief>
@ -29,22 +35,59 @@ self->cb = NULL;]]></implementation>
<dispose>
<implementation><![CDATA[ ]]></implementation>
</dispose>
<inline>
<method name="drvSetCallback" ctype="void">
<brief>Associates a callback to the driver instance.</brief>
<virtual>
<method name="drvSetCallback" ctype="void" shortname="setcb">
<brief>
Associates a callback to the driver instance.
</brief>
<param name="cb" ctype="hal_cb_t">
Callback function to be associated. Passing @p NULL disables the
existing callback, if any.</param>
Callback function to be associated. Passing @p NULL
disables the existing callback, if any.
</param>
<implementation><![CDATA[
self->cb = cb;]]></implementation>
</method>
</virtual>
<inline>
<method name="drvGetCallback" ctype="hal_cb_t">
<brief>Returns the callback associated to the driver instance.</brief>
<implementation><![CDATA[
return self->cb;]]></implementation>
</method>
<method name="drvStateIsCompleteI" ctype="bool">
<brief>Checks for @p HAL_DRV_STATE_COMPLETE state.</brief>
<details><![CDATA[The @p HAL_DRV_STATE_COMPLETE state is used by
those drivers triggering multiple callbacks for a single
asynchronous operation, it marks the last callback in the
sequence.]]></details>
<note><![CDATA[This function is meant to be called exclusively from
the driver callback.]]></note>
<return>The check result.</return>
<retval value="false">If the current state is not @p HAL_DRV_STATE_COMPLETE.</retval>
<retval value="true">If the current state is @p HAL_DRV_STATE_COMPLETE.</retval>
<api />
<implementation><![CDATA[
return (bool)(self->state == HAL_DRV_STATE_COMPLETE);]]></implementation>
</method>
<method name="drvStateIsErrorI" ctype="bool">
<brief>Checks for @p HAL_DRV_STATE_ERROR state.</brief>
<details><![CDATA[The @p HAL_DRV_STATE_ERROR state during a callback
marks an error in an asynchronous operation, the operation is
implicitly stopped and the driver is switched back to its
@p HAL_DRV_STATE_READY state.]]></details>
<note><![CDATA[This function is meant to be called exclusively from
the driver callback.]]></note>
<return>The check result.</return>
<retval value="false">If the current state is not @p HAL_DRV_STATE_ERROR.</retval>
<retval value="true">If the current state is @p HAL_DRV_STATE_ERROR.</retval>
<api />
<implementation><![CDATA[
return (bool)(self->state == HAL_DRV_STATE_ERROR);]]></implementation>
</method>
</inline>
</methods>
</class>

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.chibios.org/xml/schema/ccode/modules.xsd"
name="hal_spi" descr="SPI Driver" check="HAL_USE_SPI == TRUE" editcode="false">
name="hal_spi" descr="SPI Driver" check="HAL_USE_SPI == TRUE"
editcode="false">
<brief>SPI Driver macros and structures.</brief>
<imports>
<import>hal_cb_driver.xml</import>
@ -31,7 +32,8 @@
<brief>Support for thread synchronization API.</brief>
<assert invalid="($N != FALSE) &amp;&amp; ($N != TRUE)" />
</config>
<config name="SPI_SELECT_MODE" default="SPI_SELECT_MODE_PAD">
<config name="SPI_SELECT_MODE"
default="SPI_SELECT_MODE_PAD">
<brief>Handling method for SPI CS line.</brief>
<assert
invalid="($N &lt; SPI_SELECT_MODE_NONE) || ($N &gt; SPI_SELECT_MODE_LLD)" />
@ -53,7 +55,8 @@
</typedef>
<typedef name="SPIConfig">
<brief>Type of structure representing a SPI configuration
(legacy).</brief>
(legacy).
</brief>
<basetype ctype="struct hal_spi_config" />
</typedef>
<typedef name="SPIDriver">
@ -87,13 +90,15 @@
<brief>Enables the slave mode.</brief>
</field>
</condition>
<condition check="SPI_SELECT_MODE == SPI_SELECT_MODE_LINE">
<condition
check="SPI_SELECT_MODE == SPI_SELECT_MODE_LINE">
<field name="ssline" ctype="ioline_t">
<brief>The chip select line.</brief>
<note>Only used in master mode.</note>
</field>
</condition>
<condition check="SPI_SELECT_MODE == SPI_SELECT_MODE_PORT">
<condition
check="SPI_SELECT_MODE == SPI_SELECT_MODE_PORT">
<field name="ssport" ctype="ioportid_t">
<brief>The chip select port.</brief>
<note>Only used in master mode.</note>
@ -103,7 +108,8 @@
<note>Only used in master mode.</note>
</field>
</condition>
<condition check="SPI_SELECT_MODE == SPI_SELECT_MODE_PAD">
<condition
check="SPI_SELECT_MODE == SPI_SELECT_MODE_PAD">
<field name="ssport" ctype="ioportid_t">
<brief>The chip select port.</brief>
<note>Only used in master mode.</note>
@ -126,12 +132,18 @@ SPI_CONFIG_EXT_FIELDS]]></verbatim>
ancestorname="hal_cb_driver" descr="SPI driver">
<brief>Class of a SPI driver.</brief>
<fields>
<condition check="SPI_USE_SYNCHRONIZATION == TRUE">
<field name="sync_transfer" ctype="thread_reference_t">
<brief>Synchronization point for transfer.</brief>
</field>
</condition>
<verbatim><![CDATA[
#if defined(SPI_DRIVER_EXT_FIELS)
SPI_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
spi_lld_driver_fields;]]></verbatim>
</fields>
<methods>
<objinit callsuper="true">
@ -154,7 +166,8 @@ SPI_DRIVER_EXT_INIT_HOOK(self);
<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
<param name="n" ctype="size_t" dir="in">Number of frames
to be
ignored.
</param>
<return>The operation status.</return>
@ -188,7 +201,8 @@ return msg;]]></implementation>
<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
<param name="n" ctype="size_t" dir="in">Number of frames
to be
ignored.
</param>
<return>The operation status.</return>
@ -211,13 +225,16 @@ return msg;]]></implementation>
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
<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
<param name="txbuf" ctype="const void *" dir="in">Pointer
to the
transmit buffer.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
<param name="rxbuf" ctype="void *" dir="out">Pointer to
the
receive buffer.
</param>
<return>The operation status.</return>
@ -253,13 +270,16 @@ return msg;]]></implementation>
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
<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
<param name="txbuf" ctype="const void *" dir="in">Pointer
to the
transmit buffer.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
<param name="rxbuf" ctype="void *" dir="out">Pointer to
the
receive buffer.
</param>
<return>The operation status.</return>
@ -282,10 +302,12 @@ return msg;]]></implementation>
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
<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
<param name="txbuf" ctype="const void *" dir="in">Pointer
to the
transmit buffer.
</param>
<return>The operation status.</return>
@ -320,10 +342,12 @@ return msg;]]></implementation>
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
<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
<param name="txbuf" ctype="const void *" dir="in">Pointer
to the
transmit buffer.
</param>
<return>The operation status.</return>
@ -346,10 +370,12 @@ return msg;]]></implementation>
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
<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
<param name="rxbuf" ctype="void *" dir="out">Pointer to
the
receive buffer.
</param>
<return>The operation status.</return>
@ -384,10 +410,12 @@ return msg;]]></implementation>
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
<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
<param name="rxbuf" ctype="void *" dir="out">Pointer to
the
receive buffer.
</param>
<return>The operation status.</return>
@ -403,7 +431,8 @@ 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
<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>
@ -439,7 +468,8 @@ 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
<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>
@ -459,14 +489,18 @@ return msg;]]></implementation>
<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
<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 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>
<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;
@ -487,14 +521,18 @@ 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
<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 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>
<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;
@ -511,14 +549,18 @@ return msg;]]></implementation>
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
<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 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>
<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;
@ -541,21 +583,27 @@ return msg;]]></implementation>
<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
<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
<param name="txbuf" ctype="const void *" dir="in">Pointer
to
the
transmit buffer.
</param>
<param name="rxbuf" ctype="void *" dir="out">Pointer to the
<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 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>
<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;
@ -578,18 +626,23 @@ return msg;]]></implementation>
<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
<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
<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 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>
<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;
@ -610,17 +663,22 @@ return msg;]]></implementation>
<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
<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
<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 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>
<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;
@ -637,10 +695,12 @@ return msg;]]></implementation>
</condition>
</regular>
<inline>
<condition check="SPI_SELECT_MODE == SPI_SELECT_MODE_LLD">
<condition
check="SPI_SELECT_MODE == SPI_SELECT_MODE_LLD">
<method name="spiSelectX" ctype="void">
<brief>Asserts the slave select signal and prepares for
transfers.</brief>
transfers.
</brief>
<xclass />
<implementation><![CDATA[
@ -653,7 +713,8 @@ spi_lld_select(self);]]></implementation>
spi_lld_unselect(self);]]></implementation>
</method>
<elseif check="SPI_SELECT_MODE == SPI_SELECT_MODE_LINE" />
<elseif
check="SPI_SELECT_MODE == SPI_SELECT_MODE_LINE" />
<method name="spiSelectX" ctype="void">
<implementation><![CDATA[
@ -664,7 +725,8 @@ palClearLine(self->config->ssline);]]></implementation>
palSetLine(self->config->ssline);]]></implementation>
</method>
<elseif check="SPI_SELECT_MODE == SPI_SELECT_MODE_PORT" />
<elseif
check="SPI_SELECT_MODE == SPI_SELECT_MODE_PORT" />
<method name="spiSelectX" ctype="void">
<implementation><![CDATA[
@ -675,7 +737,8 @@ palClearPort(self->config->ssport, self->config->ssmask);]]></implementation>
palSetPort(self->config->ssport, self->config->ssmask);]]></implementation>
</method>
<elseif check="SPI_SELECT_MODE == SPI_SELECT_MODE_PAD" />
<elseif
check="SPI_SELECT_MODE == SPI_SELECT_MODE_PAD" />
<method name="spiSelectX" ctype="void">
<implementation><![CDATA[
@ -687,17 +750,90 @@ palClearPad(self->config->ssport, self->config->sspad);]]></implementation>
palSetPad(self->config->ssport, self->config->sspad);]]></implementation>
</method>
</condition>
<condition check="SPI_USE_SYNCHRONIZATION == TRUE">
<method name="__spi_wakeup_isr" ctype="void">
<brief>Wakes up the waiting thread.</brief>
<note>This function is meant to be used in the low level
drivers implementations only.
</note>
<param name="msg" ctype="msg_t" dir="in">The wakeup
message.
</param>
<notapi />
<implementation><![CDATA[
osalSysLockFromISR();
osalThreadResumeI(&self->sync_transfer, MSG_OK);
osalSysUnlockFromISR();]]></implementation>
</method>
<elseif />
<method name="__spi_wakeup_isr" ctype="void">
<param name="msg" ctype="msg_t" dir="in" />
<implementation><![CDATA[
(void)self;]]></implementation>
</method>
</condition>
<method name="__spi_isr_complete_code" ctype="void">
<brief>Common ISR code in linear mode.</brief>
<details><verbatim><![CDATA[
This code handles the portable part of the ISR code:
- Callback invocation.
- Waiting thread wakeup, if any.
- Driver state transitions.
.
]]></verbatim></details>
<note>This function is meant to be used in the low level
drivers implementations only.
</note>
<notapi />
<implementation><![CDATA[
if (self->config->data_cb) {
self->state = HAL_DRV_STATE_COMPLETE;
self->config->data_cb(spip);
if (self->state == HAL_DRV_STATE_COMPLETE)
self->state = HAL_DRV_STATE_READY;
}
else {
self->state = HAL_DRV_STATE_READY;
}
#if SPI_USE_SYNCHRONIZATION == TRUE
/* Thread wakeup, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&self->sync_transfer, MSG_OK);
osalSysUnlockFromISR();
#endif]]></implementation>
</method>
</inline>
<override>
<method shortname="start">
<implementation><![CDATA[]]></implementation>
</method>
<method shortname="stop">
<implementation><![CDATA[]]></implementation>
</method>
<method shortname="configure">
<implementation><![CDATA[
self->config = config;]]></implementation>
</method>
<method shortname="setcb">
<implementation><![CDATA[
__cbdrv_setcb_impl(self);
spi_lld_setcb(self, cb);]]></implementation>
</method>
</override>
</methods>
</class>
</types>
<functions>
<function name="spiInit" ctype="void">
<brief>SPI Driver initialization.</brief>
<note>
This function is implicitly invoked by @p halInit(), there is no
need to explicitly initialize the driver.
</note>
<note><![CDATA[This function is implicitly invoked by @p halInit(),
there is no need to explicitly initialize the driver.]]></note>
<init />
<implementation><![CDATA[

View File

@ -43,8 +43,6 @@
#define HAL_DRV_STATE_STARTING 3U
#define HAL_DRV_STATE_READY 4U
#define HAL_DRV_STATE_ACTIVE 5U
#define HAL_DRV_STATE_COMPLETE 6U
#define HAL_DRV_STATE_ERROR 7U
/** @} */
/*===========================================================================*/
@ -161,6 +159,10 @@ struct hal_base_driver {
* @brief Driver state.
*/
driver_state_t state;
/**
* @brief Associated configuration structure.
*/
const void *config;
/**
* @brief Driver argument.
*/

View File

@ -90,6 +90,10 @@ struct hal_buffered_serial {
* @brief Driver state.
*/
driver_state_t state;
/**
* @brief Associated configuration structure.
*/
const void *config;
/**
* @brief Driver argument.
*/

View File

@ -31,6 +31,14 @@
/* Module constants. */
/*===========================================================================*/
/**
* @name Callback-related driver states
* @{
*/
#define HAL_DRV_STATE_COMPLETE 6U
#define HAL_DRV_STATE_ERROR 7U
/** @} */
/*===========================================================================*/
/* Module pre-compile time settings. */
/*===========================================================================*/
@ -78,6 +86,7 @@ struct hal_cb_driver_vmt {
void (*stop)(void *ip);
msg_t (*configure)(void *ip, const void *config);
/* From hal_cb_driver_c.*/
void (*setcb)(void *ip, hal_cb_t cb);
};
/**
@ -92,6 +101,10 @@ struct hal_cb_driver {
* @brief Driver state.
*/
driver_state_t state;
/**
* @brief Associated configuration structure.
*/
const void *config;
/**
* @brief Driver argument.
*/
@ -134,6 +147,7 @@ extern "C" {
/* Methods of hal_cb_driver_c.*/
void *__cbdrv_objinit_impl(void *ip, const void *vmt);
void __cbdrv_dispose_impl(void *ip);
void __cbdrv_setcb_impl(void *ip, hal_cb_t cb);
#ifdef __cplusplus
}
#endif
@ -143,7 +157,7 @@ extern "C" {
/*===========================================================================*/
/**
* @name Inline methods of hal_cb_driver_c
* @name Virtual methods of hal_cb_driver_c
* @{
*/
/**
@ -160,9 +174,14 @@ CC_FORCE_INLINE
static inline void drvSetCallback(void *ip, hal_cb_t cb) {
hal_cb_driver_c *self = (hal_cb_driver_c *)ip;
self->cb = cb;
self->vmt->setcb(ip, cb);
}
/** @} */
/**
* @name Inline methods of hal_cb_driver_c
* @{
*/
/**
* @memberof hal_cb_driver_c
* @public
@ -177,6 +196,60 @@ static inline hal_cb_t drvGetCallback(void *ip) {
return self->cb;
}
/**
* @memberof hal_cb_driver_c
* @public
*
* @brief Checks for @p HAL_DRV_STATE_COMPLETE state.
* @details The @p HAL_DRV_STATE_COMPLETE state is used by those drivers
* triggering multiple callbacks for a single asynchronous
* operation, it marks the last callback in the sequence.
* @note This function is meant to be called exclusively from the driver
* callback.
*
* @param[in,out] ip Pointer to a @p hal_cb_driver_c instance.
* @return The check result.
* @retval false If the current state is not @p
* HAL_DRV_STATE_COMPLETE.
* @retval true If the current state is @p
* HAL_DRV_STATE_COMPLETE.
*
* @api
*/
CC_FORCE_INLINE
static inline bool drvStateIsCompleteI(void *ip) {
hal_cb_driver_c *self = (hal_cb_driver_c *)ip;
return (bool)(self->state == HAL_DRV_STATE_COMPLETE);
}
/**
* @memberof hal_cb_driver_c
* @public
*
* @brief Checks for @p HAL_DRV_STATE_ERROR state.
* @details The @p HAL_DRV_STATE_ERROR state during a callback marks an
* error in an asynchronous operation, the operation is implicitly
* stopped and the driver is switched back to its @p
* HAL_DRV_STATE_READY state.
* @note This function is meant to be called exclusively from the driver
* callback.
*
* @param[in,out] ip Pointer to a @p hal_cb_driver_c instance.
* @return The check result.
* @retval false If the current state is not @p
* HAL_DRV_STATE_ERROR.
* @retval true If the current state is @p HAL_DRV_STATE_ERROR.
*
* @api
*/
CC_FORCE_INLINE
static inline bool drvStateIsErrorI(void *ip) {
hal_cb_driver_c *self = (hal_cb_driver_c *)ip;
return (bool)(self->state == HAL_DRV_STATE_ERROR);
}
/** @} */
#endif /* HAL_CB_DRIVER_H */

View File

@ -565,6 +565,10 @@ struct hal_sio_driver {
* @brief Driver state.
*/
driver_state_t state;
/**
* @brief Associated configuration structure.
*/
const void *config;
/**
* @brief Driver argument.
*/
@ -672,6 +676,10 @@ struct hal_buffered_sio {
* @brief Driver state.
*/
driver_state_t state;
/**
* @brief Associated configuration structure.
*/
const void *config;
/**
* @brief Driver argument.
*/

View File

@ -225,6 +225,7 @@ struct hal_spi_driver_vmt {
void (*stop)(void *ip);
msg_t (*configure)(void *ip, const void *config);
/* From hal_cb_driver_c.*/
void (*setcb)(void *ip, hal_cb_t cb);
/* From hal_spi_driver_c.*/
};
@ -240,6 +241,10 @@ struct hal_spi_driver {
* @brief Driver state.
*/
driver_state_t state;
/**
* @brief Associated configuration structure.
*/
const void *config;
/**
* @brief Driver argument.
*/
@ -269,6 +274,12 @@ struct hal_spi_driver {
* @note Can be @p NULL.
*/
hal_cb_t cb;
#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined (__DOXYGEN__)
/**
* @brief Synchronization point for transfer.
*/
thread_reference_t sync_transfer;
#endif /* SPI_USE_SYNCHRONIZATION == TRUE */
#if defined(SPI_DRIVER_EXT_FIELS)
SPI_DRIVER_EXT_FIELDS
#endif
@ -287,6 +298,10 @@ 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 __spi_start_impl(void *ip);
void __spi_stop_impl(void *ip);
msg_t __spi_configure_impl(void *ip, const void *config);
void __spi_setcb_impl(void *ip, hal_cb_t cb);
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);
@ -422,6 +437,74 @@ static inline void spiUnselectX(void *ip) {
palSetPad(self->config->ssport, self->config->sspad);
}
#endif /* SPI_SELECT_MODE == SPI_SELECT_MODE_LLD */
#if (SPI_USE_SYNCHRONIZATION == TRUE) || defined (__DOXYGEN__)
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Wakes up the waiting thread.
* @note This function is meant to be used in the low level drivers
* implementations only.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] msg The wakeup message.
*
* @notapi
*/
CC_FORCE_INLINE
static inline void __spi_wakeup_isr(void *ip, msg_t msg) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
osalSysLockFromISR();
osalThreadResumeI(&self->sync_transfer, MSG_OK);
osalSysUnlockFromISR();
}
#else
CC_FORCE_INLINE
static inline void __spi_wakeup_isr(void *ip, msg_t msg) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
(void)self;
}
#endif /* SPI_USE_SYNCHRONIZATION == TRUE */
/**
* @memberof hal_spi_driver_c
* @public
*
* @brief Common ISR code in linear mode.
* This code handles the portable part of the ISR code:
* - Callback invocation.
* - Waiting thread wakeup, if any.
* - Driver state transitions.
* .
* @note This function is meant to be used in the low level drivers
* implementations only.
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
*
* @notapi
*/
CC_FORCE_INLINE
static inline void __spi_isr_complete_code(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
if (self->config->data_cb) {
self->state = HAL_DRV_STATE_COMPLETE;
self->config->data_cb(spip);
if (self->state == HAL_DRV_STATE_COMPLETE)
self->state = HAL_DRV_STATE_READY;
}
else {
self->state = HAL_DRV_STATE_READY;
}
#if SPI_USE_SYNCHRONIZATION == TRUE
/* Thread wakeup, if any.*/
osalSysLockFromISR();
osalThreadResumeI(&self->sync_transfer, MSG_OK);
osalSysUnlockFromISR();
#endif
}
/** @} */
#endif /* HAL_USE_SPI == TRUE */

View File

@ -218,12 +218,13 @@ void *__drv_objinit_impl(void *ip, const void *vmt) {
__bo_objinit_impl(self, vmt);
/* Initialization code.*/
self->state = HAL_DRV_STATE_STOP;
self->arg = NULL;
self->state = HAL_DRV_STATE_STOP;
self->arg = NULL;
self->config = NULL;
osalMutexObjectInit(&self->mutex);
#if HAL_USE_REGISTRY == TRUE
self->id = 0U;
self->name = "unk";
self->id = 0U;
self->name = "unk";
drv_reg_insert(self);
#endif

View File

@ -104,6 +104,23 @@ void __cbdrv_dispose_impl(void *ip) {
/* Finalization of the ancestors-defined parts.*/
__drv_dispose_impl(self);
}
/**
* @memberof hal_cb_driver_c
* @protected
*
* @brief Implementation of method @p drvSetCallback().
* @note This function is meant to be used by derived classes.
*
* @param[in,out] ip Pointer to a @p hal_cb_driver_c instance.
* @param cb Callback function to be associated. Passing @p
* NULL disables the existing callback, if any.
*/
void __cbdrv_setcb_impl(void *ip, hal_cb_t cb) {
hal_cb_driver_c *self = (hal_cb_driver_c *)ip;
self->cb = cb;
}
/** @} */
/** @} */

View File

@ -122,6 +122,64 @@ void __spi_dispose_impl(void *ip) {
/* Finalization of the ancestors-defined parts.*/
__cbdrv_dispose_impl(self);
}
/**
* @memberof hal_spi_driver_c
* @protected
*
* @brief Override of method @p __drv_start().
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @return The operation status.
*/
msg_t __spi_start_impl(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
}
/**
* @memberof hal_spi_driver_c
* @protected
*
* @brief Override of method @p __drv_stop().
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
*/
void __spi_stop_impl(void *ip) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
}
/**
* @memberof hal_spi_driver_c
* @protected
*
* @brief Override of method @p drvConfigureX().
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param[in] config New driver configuration.
*/
msg_t __spi_configure_impl(void *ip, const void *config) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
self->config = config;
}
/**
* @memberof hal_spi_driver_c
* @protected
*
* @brief Override of method @p drvSetCallback().
*
* @param[in,out] ip Pointer to a @p hal_spi_driver_c instance.
* @param cb Callback function to be associated. Passing @p
* NULL disables the existing callback, if any.
*/
void __spi_setcb_impl(void *ip, hal_cb_t cb) {
hal_spi_driver_c *self = (hal_spi_driver_c *)ip;
__cbdrv_setcb_impl(self);
spi_lld_setcb(self, cb);
}
/** @} */
/**
@ -130,9 +188,10 @@ void __spi_dispose_impl(void *ip) {
*/
const struct hal_spi_driver_vmt __hal_spi_driver_vmt = {
.dispose = __spi_dispose_impl,
.start = NULL /* Method not found.*/,
.stop = NULL /* Method not found.*/,
.configure = NULL /* Method not found.*/
.start = __spi_start_impl,
.stop = __spi_stop_impl,
.configure = __spi_configure_impl,
.setcb = __spi_setcb_impl
};
/**