2022-01-11 22:30:29 -05:00
|
|
|
/*
|
2023-07-28 00:06:14 -04:00
|
|
|
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
2022-01-11 22:30:29 -05:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
*/
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* NOTICE
|
|
|
|
* The hal is not public api, don't use in application code.
|
2020-09-11 03:48:08 -04:00
|
|
|
* See readme.md in hal/include/hal/readme.md
|
2019-01-23 04:07:03 -05:00
|
|
|
******************************************************************************/
|
|
|
|
|
2019-04-18 10:13:05 -04:00
|
|
|
// The HAL layer for SPI master (common part)
|
2019-01-23 04:07:03 -05:00
|
|
|
|
2023-12-28 06:58:54 -05:00
|
|
|
// SPI HAL usages (without DMA):
|
2019-01-23 04:07:03 -05:00
|
|
|
// 1. initialize the bus
|
2023-12-28 06:58:54 -05:00
|
|
|
// 2. setup the clock speed (since this takes long time)
|
|
|
|
// 3. call setup_device to update parameters for the specific device
|
|
|
|
// 4. call setup_trans to update parameters for the specific transaction
|
|
|
|
// 5. prepare data to send into hw registers
|
|
|
|
// 6. trigger user defined SPI transaction to start
|
|
|
|
// 7. wait until the user transaction is done
|
|
|
|
// 8. fetch the received data
|
2019-01-23 04:07:03 -05:00
|
|
|
// Parameter to be updated only during ``setup_device`` will be highlighted in the
|
|
|
|
// field comments.
|
|
|
|
|
|
|
|
#pragma once
|
2023-07-28 00:06:14 -04:00
|
|
|
#include "esp_err.h"
|
2021-01-06 21:13:17 -05:00
|
|
|
#include "soc/soc_caps.h"
|
2021-07-09 04:46:27 -04:00
|
|
|
#include "hal/spi_types.h"
|
2023-08-31 07:17:40 -04:00
|
|
|
#include "hal/dma_types.h"
|
2023-09-01 05:51:54 -04:00
|
|
|
#include "soc/gdma_channel.h"
|
2023-07-28 00:06:14 -04:00
|
|
|
#if SOC_GPSPI_SUPPORTED
|
|
|
|
#include "hal/spi_ll.h"
|
|
|
|
#endif
|
2019-01-23 04:07:03 -05:00
|
|
|
|
2023-07-05 05:33:32 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
2023-07-28 00:06:14 -04:00
|
|
|
#if SOC_GPSPI_SUPPORTED
|
|
|
|
|
2023-10-19 03:16:32 -04:00
|
|
|
#if SOC_GDMA_TRIG_PERIPH_SPI2_BUS == SOC_GDMA_BUS_AHB
|
2023-08-31 07:17:40 -04:00
|
|
|
typedef dma_descriptor_align4_t spi_dma_desc_t;
|
2023-10-19 03:16:32 -04:00
|
|
|
#else
|
|
|
|
typedef dma_descriptor_align8_t spi_dma_desc_t;
|
2023-08-31 07:17:40 -04:00
|
|
|
#endif
|
|
|
|
|
2020-09-08 22:21:49 -04:00
|
|
|
/**
|
|
|
|
* Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2022-01-11 22:30:29 -05:00
|
|
|
uint32_t clk_src_hz; ///< Selected SPI clock source speed in Hz
|
2020-09-08 22:21:49 -04:00
|
|
|
uint32_t half_duplex; ///< Whether half duplex mode is used, device specific
|
|
|
|
uint32_t no_compensate; ///< No need to add dummy to compensate the timing, device specific
|
2022-01-11 22:30:29 -05:00
|
|
|
uint32_t expected_freq; ///< Expected frequency in Hz.
|
|
|
|
uint32_t duty_cycle; ///< Expected duty cycle of SPI clock
|
2020-11-10 02:40:01 -05:00
|
|
|
uint32_t input_delay_ns; /**< Maximum delay between SPI launch clock and the data to be valid.
|
|
|
|
* This is used to compensate/calculate the maximum frequency allowed.
|
2020-09-08 22:21:49 -04:00
|
|
|
* Left 0 if not known.
|
|
|
|
*/
|
|
|
|
bool use_gpio; ///< True if the GPIO matrix is used, otherwise false
|
|
|
|
} spi_hal_timing_param_t;
|
|
|
|
|
2019-01-23 04:07:03 -05:00
|
|
|
/**
|
|
|
|
* Timing configuration structure that should be calculated by
|
2020-09-08 22:21:49 -04:00
|
|
|
* ``spi_hal_cal_clock_conf`` at initialization and hold. Filled into the
|
2019-01-23 04:07:03 -05:00
|
|
|
* ``timing_conf`` member of the context of HAL before setup a device.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2020-09-08 22:21:49 -04:00
|
|
|
spi_ll_clock_val_t clock_reg; ///< Register value used by the LL layer
|
2023-01-17 21:56:25 -05:00
|
|
|
spi_clock_source_t clock_source; ///< Clock source of each device used by LL layer
|
2020-09-08 22:21:49 -04:00
|
|
|
int timing_dummy; ///< Extra dummy needed to compensate the timing
|
|
|
|
int timing_miso_delay; ///< Extra miso delay clocks to compensate the timing
|
2019-01-23 04:07:03 -05:00
|
|
|
} spi_hal_timing_conf_t;
|
|
|
|
|
2020-09-08 22:21:49 -04:00
|
|
|
/**
|
|
|
|
* Transaction configuration structure, this should be assigned by driver each time.
|
|
|
|
* All these parameters will be updated to the peripheral every transaction.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
uint16_t cmd; ///< Command value to be sent
|
|
|
|
int cmd_bits; ///< Length (in bits) of the command phase
|
|
|
|
int addr_bits; ///< Length (in bits) of the address phase
|
|
|
|
int dummy_bits; ///< Base length (in bits) of the dummy phase. Note when the compensation is enabled, some extra dummy bits may be appended.
|
|
|
|
int tx_bitlen; ///< TX length, in bits
|
|
|
|
int rx_bitlen; ///< RX length, in bits
|
|
|
|
uint64_t addr; ///< Address value to be sent
|
|
|
|
uint8_t *send_buffer; ///< Data to be sent
|
|
|
|
uint8_t *rcv_buffer; ///< Buffer to hold the receive data.
|
2021-07-09 04:46:27 -04:00
|
|
|
spi_line_mode_t line_mode; ///< SPI line mode of this transaction
|
2021-05-12 23:53:44 -04:00
|
|
|
int cs_keep_active; ///< Keep CS active after transaction
|
2020-09-08 22:21:49 -04:00
|
|
|
} spi_hal_trans_config_t;
|
|
|
|
|
2019-01-23 04:07:03 -05:00
|
|
|
/**
|
|
|
|
* Context that should be maintained by both the driver and the HAL.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2020-09-08 22:21:49 -04:00
|
|
|
/* Configured by driver at initialization, don't touch */
|
|
|
|
spi_dev_t *hw; ///< Beginning address of the peripheral registers.
|
|
|
|
bool dma_enabled; ///< Whether the DMA is enabled, do not update after initialization
|
|
|
|
/* Internal parameters, don't touch */
|
|
|
|
spi_hal_trans_config_t trans_config; ///< Transaction configuration
|
|
|
|
} spi_hal_context_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Device configuration structure, this should be initialised by driver based on different devices respectively.
|
2020-11-10 02:40:01 -05:00
|
|
|
* All these parameters will be updated to the peripheral only when ``spi_hal_setup_device``.
|
2020-09-08 22:21:49 -04:00
|
|
|
* They may not get updated when ``spi_hal_setup_trans``.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2019-01-23 04:07:03 -05:00
|
|
|
int mode; ///< SPI mode, device specific
|
|
|
|
int cs_setup; ///< Setup time of CS active edge before the first SPI clock, device specific
|
|
|
|
int cs_hold; ///< Hold time of CS inactive edge after the last SPI clock, device specific
|
|
|
|
int cs_pin_id; ///< CS pin to use, 0-2, otherwise all the CS pins are not used. Device specific
|
2020-09-08 22:21:49 -04:00
|
|
|
spi_hal_timing_conf_t timing_conf; /**< This structure holds the pre-calculated timing configuration for the device
|
|
|
|
* at initialization, device specific
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
|
|
|
struct {
|
2020-09-08 22:21:49 -04:00
|
|
|
uint32_t sio : 1; ///< Whether to use SIO mode, device specific
|
|
|
|
uint32_t half_duplex : 1; ///< Whether half duplex mode is used, device specific
|
|
|
|
uint32_t tx_lsbfirst : 1; ///< Whether LSB is sent first for TX data, device specific
|
|
|
|
uint32_t rx_lsbfirst : 1; ///< Whether LSB is received first for RX data, device specific
|
|
|
|
uint32_t no_compensate : 1; ///< No need to add dummy to compensate the timing, device specific
|
2022-01-11 22:30:29 -05:00
|
|
|
#if SOC_SPI_AS_CS_SUPPORTED
|
2020-09-08 22:21:49 -04:00
|
|
|
uint32_t as_cs : 1; ///< Whether to toggle the CS while the clock toggles, device specific
|
2019-06-13 02:12:54 -04:00
|
|
|
#endif
|
2020-09-08 22:21:49 -04:00
|
|
|
uint32_t positive_cs : 1; ///< Whether the postive CS feature is abled, device specific
|
2019-01-23 04:07:03 -05:00
|
|
|
};//boolean configurations
|
2020-09-08 22:21:49 -04:00
|
|
|
} spi_hal_dev_config_t;
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Init the peripheral and the context.
|
|
|
|
*
|
2021-01-27 08:56:16 -05:00
|
|
|
* @param hal Context of the HAL layer.
|
2021-03-05 03:20:33 -05:00
|
|
|
* @param host_id Index of the SPI peripheral. 0 for SPI1, 1 for SPI2 and 2 for SPI3.
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
2023-12-28 06:58:54 -05:00
|
|
|
void spi_hal_init(spi_hal_context_t *hal, uint32_t host_id);
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Deinit the peripheral (and the context if needed).
|
|
|
|
*
|
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
*/
|
|
|
|
void spi_hal_deinit(spi_hal_context_t *hal);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Setup device-related configurations according to the settings in the context.
|
|
|
|
*
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
* @param hal_dev Device configuration
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
2020-09-08 22:21:49 -04:00
|
|
|
void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev);
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Setup transaction related configurations according to the settings in the context.
|
|
|
|
*
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
* @param hal_dev Device configuration
|
|
|
|
* @param hal_trans Transaction configuration
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
2020-09-08 22:21:49 -04:00
|
|
|
void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev, const spi_hal_trans_config_t *hal_trans);
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
2023-12-28 06:58:54 -05:00
|
|
|
* Enable/Disable miso/mosi signals on peripheral side
|
2019-01-23 04:07:03 -05:00
|
|
|
*
|
2023-12-28 06:58:54 -05:00
|
|
|
* @param hw Beginning address of the peripheral registers.
|
|
|
|
* @param mosi_ena enable/disable mosi line
|
|
|
|
* @param miso_ena enable/disable miso line
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
2023-12-28 06:58:54 -05:00
|
|
|
void spi_hal_enable_data_line(spi_dev_t *hw, bool mosi_ena, bool miso_ena);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepare tx hardware for a new DMA trans
|
|
|
|
*
|
|
|
|
* @param hw Beginning address of the peripheral registers.
|
|
|
|
*/
|
|
|
|
void spi_hal_hw_prepare_rx(spi_dev_t *hw);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepare tx hardware for a new DMA trans
|
|
|
|
*
|
|
|
|
* @param hw Beginning address of the peripheral registers.
|
|
|
|
*/
|
|
|
|
void spi_hal_hw_prepare_tx(spi_dev_t *hw);
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Trigger start a user-defined transaction.
|
|
|
|
*
|
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
*/
|
|
|
|
void spi_hal_user_start(const spi_hal_context_t *hal);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check whether the transaction is done (trans_done is set).
|
|
|
|
*
|
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
*/
|
|
|
|
bool spi_hal_usr_is_done(const spi_hal_context_t *hal);
|
|
|
|
|
2023-12-28 06:58:54 -05:00
|
|
|
/**
|
|
|
|
* Setup transaction operations, write tx buffer to HW registers
|
|
|
|
*
|
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
* @param hal_trans Transaction configuration.
|
|
|
|
*/
|
|
|
|
void spi_hal_push_tx_buffer(const spi_hal_context_t *hal, const spi_hal_trans_config_t *hal_trans);
|
|
|
|
|
2019-01-23 04:07:03 -05:00
|
|
|
/**
|
|
|
|
* Post transaction operations, mainly fetch data from the buffer.
|
|
|
|
*
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param hal Context of the HAL layer.
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
|
|
|
void spi_hal_fetch_result(const spi_hal_context_t *hal);
|
|
|
|
|
|
|
|
/*----------------------------------------------------------
|
|
|
|
* Utils
|
|
|
|
* ---------------------------------------------------------*/
|
|
|
|
/**
|
2020-07-14 01:55:18 -04:00
|
|
|
* Calculate the configuration of clock and timing. The configuration will be used when ``spi_hal_setup_device``.
|
2019-01-23 04:07:03 -05:00
|
|
|
*
|
|
|
|
* It is highly suggested to do this at initialization, since it takes long time.
|
|
|
|
*
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param timing_param Input parameters to calculate timing configuration
|
|
|
|
* @param out_freq Output of the actual frequency, left NULL if not required.
|
|
|
|
* @param timing_conf Output of the timing configuration.
|
2019-01-23 04:07:03 -05:00
|
|
|
*
|
|
|
|
* @return ESP_OK if desired is available, otherwise fail.
|
|
|
|
*/
|
2020-09-08 22:21:49 -04:00
|
|
|
esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, int *out_freq, spi_hal_timing_conf_t *timing_conf);
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the frequency actual used.
|
|
|
|
*
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param hal Context of the HAL layer.
|
|
|
|
* @param fapb APB clock frequency.
|
|
|
|
* @param hz Desired frequencyc.
|
|
|
|
* @param duty_cycle Desired duty cycle.
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
|
|
|
int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the timing configuration for given parameters.
|
|
|
|
*
|
2023-01-17 21:56:25 -05:00
|
|
|
* @param source_freq_hz Clock freq of selected clock source for SPI in Hz.
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param eff_clk Actual SPI clock frequency
|
|
|
|
* @param gpio_is_used true if the GPIO matrix is used, otherwise false.
|
2019-01-23 04:07:03 -05:00
|
|
|
* @param input_delay_ns Maximum delay between SPI launch clock and the data to
|
2020-09-08 22:21:49 -04:00
|
|
|
* be valid. This is used to compensate/calculate the maximum frequency
|
|
|
|
* allowed. Left 0 if not known.
|
|
|
|
* @param dummy_n Dummy cycles required to correctly read the data.
|
|
|
|
* @param miso_delay_n suggested delay on the MISO line, in APB clocks.
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
2023-01-17 21:56:25 -05:00
|
|
|
void spi_hal_cal_timing(int source_freq_hz, int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n);
|
2019-01-23 04:07:03 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the maximum frequency allowed to read if no compensation is used.
|
|
|
|
*
|
2020-09-08 22:21:49 -04:00
|
|
|
* @param gpio_is_used true if the GPIO matrix is used, otherwise false.
|
2019-01-23 04:07:03 -05:00
|
|
|
* @param input_delay_ns Maximum delay between SPI launch clock and the data to
|
2020-09-08 22:21:49 -04:00
|
|
|
* be valid. This is used to compensate/calculate the maximum frequency
|
|
|
|
* allowed. Left 0 if not known.
|
2019-01-23 04:07:03 -05:00
|
|
|
*/
|
|
|
|
int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns);
|
2023-07-05 05:33:32 -04:00
|
|
|
|
2023-07-28 00:06:14 -04:00
|
|
|
#endif //#if SOC_GPSPI_SUPPORTED
|
|
|
|
|
2023-07-05 05:33:32 -04:00
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|