The new HAL SPI API is shown below. Highlights of the changes are:

* Moved spi_type, transmit/receive callback and argument out of 
hal_spi_settings and into device specific structure. This was done as these are 
the parameters we might expect someone to want to reconfigure an initialized 
SPI with. They are also generic across SPI implementation.
* There is now a blocking and non-blocking API: hal_spi_txrx() is blocking; 
hal_spi_txrx_noblock() is the non-blocking interface. This was done as setting 
the callback to NULL or not NULL to denote blocking/non-blocking was hard to 
see/understand. Furthermore, you should be able to use the HAL in non-blocking 
mode (if you want) with a callback configured.
* If you want to configure the SPI using hal_spi_config, the spi must be 
disabled first (or not yet enabled).
* Made it more clear that if you use greater than 8-bit data words for the SPI, 
you pass an array of uint16_t values to the API.
* Changed ‘len’ to ‘cnt’ in the hal_spi_txrx and hal_spi_txrx_noblock API so 
that it was more obvious we are talking about “number of values” as opposed to 
“bytes"

Comments, as always, appreciated...
/* Prototype for tx/rx callback */
typedef void (*hal_spi_txrx_cb)(void *arg, int len);

/**
 * since one spi device can control multiple devices, some configuration
 * can be changed on the fly from the hal
 */
struct hal_spi_settings {
    uint8_t         data_mode;
    uint8_t         data_order;
    uint8_t         word_size;
    uint32_t        baudrate;
};

/**
 * Initialize the SPI, given by spi_num.
 *
 * @param spi_num The number of the SPI to initialize
 * @param cfg HW/MCU specific configuration,
 *            passed to the underlying implementation, providing extra
 *            configuration.
 * @param spi_type SPI type (master or slave)
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_init(int spi_num, void *cfg, uint8_t spi_type);

/**
 * Configure the spi. Must be called after the spi is initialized (after
 * hal_spi_init is called) and when the spi is disabled (user must call
 * hal_spi_disable if the spi has been enabled through hal_spi_enable prior
 * to calling this function). Can also be used to reconfigure an initialized
 * SPI (assuming it is disabled as described previously).
 *
 * @param spi_num The number of the SPI to configure.
 * @param psettings The settings to configure this SPI with
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_config(int spi_num, struct hal_spi_settings *psettings);

/**
 * Sets the txrx callback (executed at interrupt context) when the
 * buffer is transferred by the master or the slave using the non-blocking API.
 * Cannot be called when the spi is enabled. This callback will also be called
 * when chip select is de-asserted on the slave.
 *
 * NOTE: This callback is only used for the non-blocking interface and must
 * be called prior to using the non-blocking API.
 *
 * @param spi_num   SPI interface on which to set callback
 * @param txrx      Callback function
 * @param arg       Argument to be passed to callback function
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_set_txrx_cb(int spi_num, hal_spi_txrx_cb txrx_cb, void *arg);

/**
 * Enables the SPI. This does not start a transmit or receive operation;
 * it is used for power mgmt. Cannot be called when a SPI transfer is in
 * progress.
 *
 * @param spi_num
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_enable(int spi_num);

/**
 * Disables the SPI. Used for power mgmt. It will halt any current SPI transfers
 * in progress.
 *
 * @param spi_num
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_disable(int spi_num);

/**
 * Blocking call to send a value on the SPI. Returns the value received from the
 * SPI slave.
 *
 * MASTER: Sends the value and returns the received value from the slave.
 * SLAVE: Invalid API. Returns 0xFFFF
 *
 * @param spi_num   Spi interface to use
 * @param val       Value to send
 *
 * @return uint16_t Value received on SPI interface from slave. Returns 0xFFFF
 * if called when the SPI is configured to be a slave
 */
uint16_t hal_spi_tx_val(int spi_num, uint16_t val);

/**
 * Blocking interface to send a buffer and store the received values from the
 * slave. The transmit and receive buffers are either arrays of 8-bit (uint8_t)
 * values or 16-bit values depending on whether the spi is configured for 8 bit
 * data or more than 8 bits per value. The 'cnt' parameter is the number of
 * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
 * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
 * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
 *
 * NOTE: these buffers are in the native endian-ness of the platform.
 *
 *     MASTER: master sends all the values in the buffer and stores the
 *             stores the values in the receive buffer if rxbuf is not NULL.
 *             The txbuf parameter cannot be NULL.
 *     SLAVE: cannot be called for a slave; returns -1
 *
 * @param spi_num   SPI interface to use
 * @param txbuf     Pointer to buffer where values to transmit are stored.
 * @param rxbuf     Pointer to buffer to store values received from peer.
 * @param cnt       Number of 8-bit or 16-bit values to be transferred.
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_txrx(int spi_num, void *txbuf, void *rxbuf, int cnt);

/**
 * Non-blocking interface to send a buffer and store received values. Can be
 * used for both master and slave SPI types. The user must configure the
 * callback (using hal_spi_set_txrx_cb); the txrx callback is executed at
 * interrupt context when the buffer is sent.
 *
 * The transmit and receive buffers are either arrays of 8-bit (uint8_t)
 * values or 16-bit values depending on whether the spi is configured for 8 bit
 * data or more than 8 bits per value. The 'cnt' parameter is the number of
 * 8-bit or 16-bit values. Thus, if 'cnt' is 10, txbuf/rxbuf would point to an
 * array of size 10 (in bytes) if the SPI is using 8-bit data; otherwise
 * txbuf/rxbuf would point to an array of size 20 bytes (ten, uint16_t values).
 *
 * NOTE: these buffers are in the native endian-ness of the platform.
 *
 *     MASTER: master sends all the values in the buffer and stores the
 *             stores the values in the receive buffer if rxbuf is not NULL.
 *             The txbuf parameter cannot be NULL
 *     SLAVE: Slave "preloads" the data to be sent to the master (values
 *            stored in txbuf) and places received data from master in rxbuf
 *            (if not NULL). The txrx callback occurs when len values are
 *            transferred or master de-asserts chip select. If txbuf is NULL,
 *            the slave transfers its default byte. Both rxbuf and txbuf cannot
 *            be NULL.
 *
 * @param spi_num   SPI interface to use
 * @param txbuf     Pointer to buffer where values to transmit are stored.
 * @param rxbuf     Pointer to buffer to store values received from peer.
 * @param cnt       Number of 8-bit or 16-bit values to be transferred.
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_txrx_noblock(int spi_num, void *txbuf, void *rxbuf, int cnt);

/**
 * Sets the default value transferred by the slave. Not valid for master
 *
 * @param spi_num SPI interface to use
 *
 * @return int 0 on success, non-zero error code on failure.
 */
int hal_spi_slave_set_def_tx_val(int spi_num, uint16_t val);

/**
 * This aborts the current transfer but keeps the spi enabled.
 *
 * @param spi_num   SPI interface on which transfer should be aborted.
 *
 * @return int 0 on success, non-zero error code on failure.
 *
 * NOTE: does not return an error if no transfer was in progress.
 */
int hal_spi_abort(int spi_num);
> On Sep 19, 2016, at 4:07 PM, Sterling Hughes <sterl...@apache.org> wrote:
> 
> Howdy:
> 
> We’ve been going over a painstaking review of the various HAL APIs, to make 
> sure we capture all the changes we want to include prior to merge.
> 
> Today, we looked at the driver framework, hal GPIO and SPI, here are the 
> changes we discussed:
> 
> - GPIO needs to re-name the GPIO state enums to have an hal_* in the name
> 
> - Driver functions in adc_dev and elsewhere should be static const to save 
> RAM.
> 
> - HAL GPIO: we should remove set/clear/toggle, and just have 
> hal_gpio_write(pin, val)
> 
> - HAL GPIO: there should be a function hal_gpio_release() so that ports can 
> be turned off when a pin is no longer used.
>       - Q: should hal_gpio_init_in/out follow the more common config(), 
> enable(), disable() paradigm in the rest of the HAL?
> 
> - HAL GPIO: hal_gpio_irq_enable() should by default clear any pending IRQs.  
> We discussed having a bit to check if interrupts were pending, and clear them 
> separately (or whether to make this optional), but couldn’t think of a case 
> where you’d want to enable IRQs, but not clear pending interrupts.
> 
> - Discussion of enums versus #defines for various things (like SPI mode).  No 
> clear conclusion here.  We all agree that enums for error codes are verboten, 
> and that we should be consistent about usage of enums or defines.
>       - Good points for enums: autocompletion in IDEs, debugger shows name vs 
> value, type safety
>       - Bad points for enums: unless packed, they take up a full integer.  
> You need to look up the type of the parameter, which takes up just as much 
> time as looking up the autocompleted value.
>       - We’re kinda mixed, with nobody feeling particularly strongly.  
> Whatever folks think, I think we’d be fine adhering too.
> 
> - OS device APIs are not doxygened, they need to be.
> 
> - HAL SPI: will/chris will respond with changes discussed here.  they’ve also 
> been looking at HAL SPI recently.
> 
> Cheers,
> 
> Sterling
> 

Reply via email to