mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
hal: Add initial ESP32-C3 support
From internal commit 7761d6e8
This commit is contained in:
parent
b68094199f
commit
7c08be5771
@ -76,7 +76,7 @@ int64_t esp_timer_get_time(void) __attribute__((alias("esp_timer_impl_get_time")
|
||||
void IRAM_ATTR esp_timer_impl_set_alarm(uint64_t timestamp)
|
||||
{
|
||||
portENTER_CRITICAL_SAFE(&s_time_update_lock);
|
||||
systimer_hal_set_alarm_value(SYSTIMER_ALARM_2, timestamp);
|
||||
systimer_hal_set_alarm_target(SYSTIMER_ALARM_2, timestamp);
|
||||
portEXIT_CRITICAL_SAFE(&s_time_update_lock);
|
||||
}
|
||||
|
||||
|
@ -9,14 +9,10 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"cpu_hal.c"
|
||||
"rmt_hal.c"
|
||||
"rtc_io_hal.c"
|
||||
"dac_hal.c"
|
||||
"adc_hal.c"
|
||||
"spi_hal.c"
|
||||
"spi_hal_iram.c"
|
||||
"spi_slave_hal.c"
|
||||
"spi_slave_hal_iram.c"
|
||||
"touch_sensor_hal.c"
|
||||
"pcnt_hal.c"
|
||||
"i2s_hal.c"
|
||||
"sigmadelta_hal.c"
|
||||
"timer_hal.c"
|
||||
@ -30,16 +26,20 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"spi_flash_hal.c"
|
||||
"spi_flash_hal_iram.c"
|
||||
"soc_hal.c"
|
||||
"twai_hal.c"
|
||||
"twai_hal_iram.c"
|
||||
"interrupt_controller_hal.c"
|
||||
"sha_hal.c"
|
||||
"twai_hal.c"
|
||||
"twai_hal_iram.c"
|
||||
"${target}/interrupt_descriptor_table.c")
|
||||
|
||||
if(${target} STREQUAL "esp32")
|
||||
list(APPEND srcs
|
||||
"adc_hal.c"
|
||||
"dac_hal.c"
|
||||
"mcpwm_hal.c"
|
||||
"pcnt_hal.c"
|
||||
"sdio_slave_hal.c"
|
||||
"touch_sensor_hal.c"
|
||||
"esp32/adc_hal.c"
|
||||
"esp32/brownout_hal.c"
|
||||
"esp32/touch_sensor_hal.c")
|
||||
@ -50,8 +50,12 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
if(${target} STREQUAL "esp32s2")
|
||||
list(APPEND srcs
|
||||
"adc_hal.c"
|
||||
"dac_hal.c"
|
||||
"pcnt_hal.c"
|
||||
"spi_flash_hal_gpspi.c"
|
||||
"spi_slave_hd_hal.c"
|
||||
"touch_sensor_hal.c"
|
||||
"esp32s2/adc_hal.c"
|
||||
"esp32s2/brownout_hal.c"
|
||||
"esp32s2/cp_dma_hal.c"
|
||||
@ -63,12 +67,25 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
if(${target} STREQUAL "esp32s3")
|
||||
list(APPEND srcs
|
||||
"adc_hal.c"
|
||||
"dac_hal.c"
|
||||
"pcnt_hal.c"
|
||||
"spi_flash_hal_gpspi.c"
|
||||
"spi_slave_hd_hal.c"
|
||||
"touch_sensor_hal.c"
|
||||
"esp32s3/brownout_hal.c"
|
||||
"esp32s3/systimer_hal.c"
|
||||
"esp32s3/touch_sensor_hal.c")
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "esp32c3")
|
||||
list(APPEND srcs
|
||||
"esp32c3/adc_hal.c"
|
||||
"esp32c3/brownout_hal.c"
|
||||
"esp32c3/systimer_hal.c"
|
||||
"esp32c3/hmac_hal.c"
|
||||
"spi_slave_hd_hal.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "soc/adc_periph.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "soc/rtc_io_struct.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -39,7 +39,8 @@ extern "C" {
|
||||
#define SPI_LL_UNUSED_INT_MASK (SPI_INT_EN | SPI_SLV_WR_STA_DONE | SPI_SLV_RD_STA_DONE | SPI_SLV_WR_BUF_DONE | SPI_SLV_RD_BUF_DONE)
|
||||
/// Swap the bit order to its correct place to send
|
||||
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)data<<(32-len))
|
||||
|
||||
/// This is the expected clock frequency
|
||||
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
|
||||
#define SPI_LL_GET_HW(ID) ((ID)==0? &SPI1:((ID)==1? &SPI2 : &SPI3))
|
||||
|
||||
/**
|
||||
@ -157,7 +158,7 @@ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw)
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_cpu_fifo_reset(spi_dev_t *hw)
|
||||
static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
//This is not used in esp32
|
||||
}
|
||||
@ -167,7 +168,32 @@ static inline void spi_ll_cpu_fifo_reset(spi_dev_t *hw)
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_fifo_reset(spi_dev_t *hw)
|
||||
static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
//This is not used in esp32
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA TX FIFO
|
||||
*
|
||||
* On ESP32, this function is not seperated
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
|
||||
hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA RX FIFO
|
||||
*
|
||||
* On ESP32, this function is not seperated
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
|
||||
hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
|
||||
|
255
components/hal/esp32c3/adc_hal.c
Normal file
255
components/hal/esp32c3/adc_hal.c
Normal file
@ -0,0 +1,255 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The HAL layer for ADC (ESP32-C3 specific part)
|
||||
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
void adc_hal_digi_init(void)
|
||||
{
|
||||
adc_hal_init();
|
||||
adc_ll_digi_set_clk_div(SOC_ADC_DIGI_SAR_CLK_DIV_DEFAULT);
|
||||
}
|
||||
|
||||
void adc_hal_digi_deinit(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable(); // boss
|
||||
adc_ll_digi_dma_disable();
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_1);
|
||||
adc_ll_digi_filter_reset(ADC_NUM_2);
|
||||
adc_ll_digi_reset();
|
||||
adc_ll_digi_controller_clk_disable();
|
||||
adc_hal_deinit();
|
||||
}
|
||||
|
||||
static inline void adc_set_init_code(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
uint32_t cal_val = adc_hal_calibration(adc_n, channel, atten, true, false);
|
||||
adc_hal_set_calibration_param(adc_n, cal_val);
|
||||
}
|
||||
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg)
|
||||
{
|
||||
/* If enable digtal controller, adc xpd should always on. */
|
||||
adc_ll_set_power_manage(ADC_POWER_SW_ON);
|
||||
/* Single channel mode or multi channel mode. */
|
||||
adc_ll_digi_set_convert_mode(cfg->conv_mode);
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
if (cfg->adc1_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_1, cfg->adc1_pattern_len);
|
||||
for (int i = 0; i < cfg->adc1_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_1, i, cfg->adc1_pattern[i]);
|
||||
adc_set_init_code(ADC_NUM_1, cfg->adc1_pattern[i].channel, cfg->adc1_pattern[i].atten);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
if (cfg->adc2_pattern_len) {
|
||||
adc_ll_digi_clear_pattern_table(ADC_NUM_2);
|
||||
adc_ll_digi_set_pattern_table_len(ADC_NUM_2, cfg->adc2_pattern_len);
|
||||
for (int i = 0; i < cfg->adc2_pattern_len; i++) {
|
||||
adc_ll_digi_set_pattern_table(ADC_NUM_2, i, cfg->adc2_pattern[i]);
|
||||
adc_set_init_code(ADC_NUM_2, cfg->adc2_pattern[i].channel, cfg->adc2_pattern[i].atten);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_1) {
|
||||
adc_ll_set_controller(ADC_NUM_1, ADC_CTRL_DIG);
|
||||
}
|
||||
if (cfg->conv_mode & ADC_CONV_SINGLE_UNIT_2) {
|
||||
adc_ll_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
|
||||
}
|
||||
adc_ll_digi_set_output_format(cfg->format);
|
||||
if (cfg->conv_limit_en) {
|
||||
adc_ll_digi_set_convert_limit_num(cfg->conv_limit_num);
|
||||
adc_ll_digi_convert_limit_enable();
|
||||
} else {
|
||||
adc_ll_digi_convert_limit_disable();
|
||||
}
|
||||
|
||||
adc_ll_digi_set_trigger_interval(cfg->interval);
|
||||
adc_hal_digi_clk_config(&cfg->dig_clk);
|
||||
adc_ll_digi_dma_set_eof_num(cfg->dma_eof_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Enable clock and select clock source for ADC digital controller.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
|
||||
*
|
||||
* @note ADC and DAC digital controller share the same frequency divider.
|
||||
* Please set a reasonable frequency division factor to meet the sampling frequency of the ADC and the output frequency of the DAC.
|
||||
*
|
||||
* @param clk Refer to ``adc_digi_clk_t``.
|
||||
*/
|
||||
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk)
|
||||
{
|
||||
adc_ll_digi_controller_clk_div(clk->div_num, clk->div_b, clk->div_a);
|
||||
adc_ll_digi_controller_clk_enable(clk->use_apll);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_enable(void)
|
||||
{
|
||||
adc_ll_digi_dma_enable();
|
||||
adc_ll_digi_trigger_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_disable(void)
|
||||
{
|
||||
adc_ll_digi_trigger_disable();
|
||||
adc_ll_digi_dma_disable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @param config Refer to `adc_digi_monitor_t`.
|
||||
*/
|
||||
void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config)
|
||||
{
|
||||
adc_ll_digi_monitor_set_mode(adc_n, config->mode);
|
||||
adc_ll_digi_monitor_set_thres(adc_n, config->threshold);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Config ADC2 module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*/
|
||||
void adc_hal_arbiter_config(adc_arbiter_t *config)
|
||||
{
|
||||
adc_ll_set_arbiter_work_mode(config->mode);
|
||||
adc_ll_set_arbiter_priority(config->rtc_pri, config->dig_pri, config->pwdet_pri);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC calibration setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
#define ADC_HAL_CAL_OFFSET_RANGE (4096)
|
||||
#define ADC_HAL_CAL_TIMES (10)
|
||||
|
||||
static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} };
|
||||
|
||||
static uint32_t adc_hal_read_self_cal(adc_ll_num_t adc_n, int channel)
|
||||
{
|
||||
adc_ll_rtc_start_convert(adc_n, channel);
|
||||
while (adc_ll_rtc_convert_is_done(adc_n) != true);
|
||||
return (uint32_t)adc_ll_rtc_get_convert_value(adc_n);
|
||||
}
|
||||
|
||||
uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal)
|
||||
{
|
||||
if (!force_cal) {
|
||||
if (s_adc_cali_param[adc_n][atten]) {
|
||||
return (uint32_t)s_adc_cali_param[adc_n][atten];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t code_list[ADC_HAL_CAL_TIMES] = {0};
|
||||
uint32_t code_sum = 0;
|
||||
uint32_t code_h = 0;
|
||||
uint32_t code_l = 0;
|
||||
uint32_t chk_code = 0;
|
||||
uint32_t dout = 0;
|
||||
|
||||
adc_hal_set_power_manage(ADC_POWER_SW_ON);
|
||||
if (adc_n == ADC_NUM_2) {
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
adc_hal_arbiter_config(&config);
|
||||
}
|
||||
adc_hal_set_controller(adc_n, ADC_CTRL_RTC); //Set controller
|
||||
|
||||
// adc_hal_arbiter_config(adc_arbiter_t *config)
|
||||
adc_ll_calibration_prepare(adc_n, channel, internal_gnd);
|
||||
|
||||
/* Enable/disable internal connect GND (for calibration). */
|
||||
if (internal_gnd) {
|
||||
adc_ll_rtc_disable_channel(adc_n, channel);
|
||||
adc_ll_set_atten(adc_n, 0, atten); // Note: when disable all channel, HW auto select channel0 atten param.
|
||||
} else {
|
||||
adc_ll_rtc_enable_channel(adc_n, channel);
|
||||
adc_ll_set_atten(adc_n, channel, atten);
|
||||
}
|
||||
|
||||
for (uint8_t rpt = 0 ; rpt < ADC_HAL_CAL_TIMES ; rpt ++) {
|
||||
code_h = ADC_HAL_CAL_OFFSET_RANGE;
|
||||
code_l = 0;
|
||||
chk_code = (code_h + code_l) / 2;
|
||||
adc_ll_set_calibration_param(adc_n, chk_code);
|
||||
dout = adc_hal_read_self_cal(adc_n, channel);
|
||||
while (code_h - code_l > 1) {
|
||||
if (dout == 0) {
|
||||
code_h = chk_code;
|
||||
} else {
|
||||
code_l = chk_code;
|
||||
}
|
||||
chk_code = (code_h + code_l) / 2;
|
||||
adc_ll_set_calibration_param(adc_n, chk_code);
|
||||
dout = adc_hal_read_self_cal(adc_n, channel);
|
||||
if ((code_h - code_l == 1)) {
|
||||
chk_code += 1;
|
||||
adc_ll_set_calibration_param(adc_n, chk_code);
|
||||
dout = adc_hal_read_self_cal(adc_n, channel);
|
||||
}
|
||||
}
|
||||
code_list[rpt] = chk_code;
|
||||
code_sum += chk_code;
|
||||
}
|
||||
code_l = code_list[0];
|
||||
code_h = code_list[0];
|
||||
for (uint8_t i = 0 ; i < ADC_HAL_CAL_TIMES ; i++) {
|
||||
if (code_l > code_list[i]) {
|
||||
code_l = code_list[i];
|
||||
}
|
||||
if (code_h < code_list[i]) {
|
||||
code_h = code_list[i];
|
||||
}
|
||||
}
|
||||
chk_code = code_h + code_l;
|
||||
dout = ((code_sum - chk_code) % (ADC_HAL_CAL_TIMES - 2) < 4)
|
||||
? (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2)
|
||||
: (code_sum - chk_code) / (ADC_HAL_CAL_TIMES - 2) + 1;
|
||||
|
||||
adc_ll_set_calibration_param(adc_n, dout);
|
||||
adc_ll_calibration_finish(adc_n);
|
||||
s_adc_cali_param[adc_n][atten] = (uint16_t)dout;
|
||||
return dout;
|
||||
}
|
36
components/hal/esp32c3/brownout_hal.c
Normal file
36
components/hal/esp32c3/brownout_hal.c
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "hal/brownout_hal.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "i2c_rtc_clk.h"
|
||||
#include "i2c_brownout.h"
|
||||
|
||||
|
||||
void brownout_hal_config(const brownout_hal_config_t *cfg)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2397
|
||||
}
|
||||
|
||||
void brownout_hal_intr_enable(bool enable)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2397
|
||||
}
|
||||
|
||||
void brownout_hal_intr_clear(void)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2397
|
||||
}
|
83
components/hal/esp32c3/hmac_hal.c
Normal file
83
components/hal/esp32c3/hmac_hal.c
Normal file
@ -0,0 +1,83 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "stdio.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
#include "hal/hmac_ll.h"
|
||||
|
||||
void hmac_hal_start(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_start();
|
||||
}
|
||||
|
||||
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_config_output(config);
|
||||
hmac_ll_config_hw_key_id(key_id);
|
||||
hmac_ll_config_finish();
|
||||
hmac_ll_wait_idle();
|
||||
|
||||
uint32_t conf_error = hmac_ll_config_error();
|
||||
if (conf_error) {
|
||||
hmac_ll_calc_finish();
|
||||
return 1;
|
||||
} else if (config != HMAC_OUTPUT_USER) {
|
||||
// In "downstream" mode, this will be the last hmac operation. Make sure HMAC is ready for
|
||||
// the other peripheral.
|
||||
hmac_ll_wait_idle();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hmac_hal_write_one_block_512(const void *block)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_write_block_512(block);
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_one_block();
|
||||
}
|
||||
|
||||
void hmac_hal_write_block_512(const void *block)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_write_block_512(block);
|
||||
}
|
||||
|
||||
void hmac_hal_next_block_padding(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_padding();
|
||||
}
|
||||
|
||||
void hmac_hal_next_block_normal(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_msg_continue();
|
||||
}
|
||||
|
||||
void hmac_hal_read_result_256(void *result)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_read_result_256(result);
|
||||
hmac_ll_calc_finish();
|
||||
}
|
||||
|
||||
void hmac_hal_clean(void)
|
||||
{
|
||||
hmac_ll_wait_idle();
|
||||
hmac_ll_clean();
|
||||
}
|
262
components/hal/esp32c3/include/hal/adc_hal.h
Normal file
262
components/hal/esp32c3/include/hal/adc_hal.h
Normal file
@ -0,0 +1,262 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for ADC (esp32s2 specific part)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/adc_ll.h"
|
||||
#include "hal/adc_types.h"
|
||||
|
||||
#include_next "hal/adc_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Digital controller initialization.
|
||||
*/
|
||||
void adc_hal_digi_init(void);
|
||||
|
||||
/**
|
||||
* Digital controller deinitialization.
|
||||
*/
|
||||
void adc_hal_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* Setting the digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller paramter.
|
||||
*/
|
||||
void adc_hal_digi_controller_config(const adc_digi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* ADC Digital controller output data invert or not.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param inv_en data invert or not.
|
||||
*/
|
||||
#define adc_hal_digi_output_invert(adc_n, inv_en) adc_ll_digi_output_invert(adc_n, inv_en)
|
||||
|
||||
/**
|
||||
* Sets the number of interval clock cycles for the digital controller to trigger the measurement.
|
||||
*
|
||||
* @note The trigger interval should not be less than the sampling time of the SAR ADC.
|
||||
* @param cycle The number of clock cycles for the trigger interval. The unit is the divided clock. Range: 40 ~ 4095.
|
||||
*/
|
||||
#define adc_hal_digi_set_trigger_interval(cycle) adc_ll_digi_set_trigger_interval(cycle)
|
||||
|
||||
/**
|
||||
* Enable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_enable(void);
|
||||
|
||||
/**
|
||||
* Disable digital controller to trigger the measurement.
|
||||
*/
|
||||
void adc_hal_digi_disable(void);
|
||||
|
||||
/**
|
||||
* Set ADC digital controller clock division factor. The clock divided from `APLL` or `APB` clock.
|
||||
* Enable clock and select clock source for ADC digital controller.
|
||||
* Expression: controller_clk = APLL/APB * (div_num + div_b / div_a).
|
||||
*
|
||||
* @param clk Refer to `adc_digi_clk_t`.
|
||||
*/
|
||||
void adc_hal_digi_clk_config(const adc_digi_clk_t *clk);
|
||||
|
||||
/**
|
||||
* Reset adc digital controller filter.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_digi_filter_reset(adc_n) adc_ll_digi_filter_reset(adc_n)
|
||||
|
||||
/**
|
||||
* Set adc digital controller filter factor.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
|
||||
*/
|
||||
#define adc_hal_digi_filter_set_factor(adc_n, factor) adc_ll_digi_filter_set_factor(adc_n, factor)
|
||||
|
||||
/**
|
||||
* Get adc digital controller filter factor.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param factor Expression: filter_data = (k-1)/k * last_data + new_data / k. Set values: (2, 4, 8, 16, 64).
|
||||
*/
|
||||
#define adc_hal_digi_filter_get_factor(adc_n, factor) adc_ll_digi_filter_get_factor(adc_n, factor)
|
||||
|
||||
/**
|
||||
* Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_digi_filter_enable(adc_n, enable) adc_ll_digi_filter_enable(adc_n, enable)
|
||||
|
||||
/**
|
||||
* Get the filtered data of adc digital controller filter.
|
||||
* The data after each measurement and filtering is updated to the DMA by the digital controller. But it can also be obtained manually through this API.
|
||||
*
|
||||
* @note The filter will filter all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @return Filtered data.
|
||||
*/
|
||||
#define adc_hal_digi_filter_read_data(adc_n) adc_ll_digi_filter_read_data(adc_n)
|
||||
|
||||
/**
|
||||
* Config monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
* @param config Refer to `adc_digi_monitor_t`.
|
||||
*/
|
||||
void adc_hal_digi_monitor_config(adc_ll_num_t adc_n, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
* @param adc_n ADC unit.
|
||||
*/
|
||||
#define adc_hal_digi_monitor_enable(adc_n, enable) adc_ll_digi_monitor_enable(adc_n, enable)
|
||||
|
||||
/**
|
||||
* Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_intr_enable(adc_n, intr) adc_ll_digi_intr_enable(adc_n, intr)
|
||||
|
||||
/**
|
||||
* Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_intr_disable(adc_n, intr) adc_ll_digi_intr_disable(adc_n, intr)
|
||||
|
||||
/**
|
||||
* Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @param intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_intr_clear(adc_n, intr) adc_ll_digi_intr_clear(adc_n, intr)
|
||||
|
||||
/**
|
||||
* Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_n ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask.
|
||||
*/
|
||||
#define adc_hal_digi_get_intr_status(adc_n) adc_ll_digi_get_intr_status(adc_n)
|
||||
|
||||
|
||||
/**
|
||||
* Set DMA eof num of adc digital controller.
|
||||
* If the number of measurements reaches `dma_eof_num`, then `dma_in_suc_eof` signal is generated.
|
||||
*
|
||||
* @param num eof num of DMA.
|
||||
*/
|
||||
#define adc_hal_digi_dma_set_eof_num(num) adc_ll_digi_dma_set_eof_num(num)
|
||||
|
||||
/**
|
||||
* Enable output data to DMA from adc digital controller.
|
||||
*/
|
||||
#define adc_hal_digi_dma_enable() adc_ll_digi_dma_enable()
|
||||
|
||||
/**
|
||||
* Disable output data to DMA from adc digital controller.
|
||||
*/
|
||||
#define adc_hal_digi_dma_disable() adc_ll_digi_dma_disable()
|
||||
|
||||
/**
|
||||
* Reset adc digital controller.
|
||||
*/
|
||||
#define adc_hal_digi_reset() adc_ll_digi_reset()
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset RTC controller FSM.
|
||||
*/
|
||||
#define adc_hal_rtc_reset() adc_ll_rtc_reset()
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Config ADC2 module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note The arbiter's working clock is APB_CLK. When the APB_CLK clock drops below 8 MHz, the arbiter must be in shield mode.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
*
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*/
|
||||
void adc_hal_arbiter_config(adc_arbiter_t *config);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
ADC calibration setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Calibrate the ADC according to the parameters.
|
||||
*
|
||||
* @note Different ADC units and different attenuation options use different calibration data (initial data).
|
||||
*
|
||||
* @param adc_n ADC index number.
|
||||
* @param channel adc channel number.
|
||||
* @param internal_gnd true: Disconnect from the IO port and use the internal GND as the calibration voltage.
|
||||
* false: Use IO external voltage as calibration voltage.
|
||||
* @param force_cal true: Do not use the results that have already been verified, and perform the verification again. It will take a long time.
|
||||
* false: Use the result of the last calibration.
|
||||
*
|
||||
* @return
|
||||
* - The calibration result (initial data) to ADC, use `adc_hal_set_calibration_param` to set.
|
||||
*/
|
||||
uint32_t adc_hal_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd, bool force_cal);
|
||||
|
||||
/**
|
||||
* Set the calibration result (initial data) to ADC.
|
||||
*
|
||||
* @note Different ADC units and different attenuation options use different calibration data (initial data).
|
||||
*
|
||||
* @param adc_n ADC index number.
|
||||
*/
|
||||
#define adc_hal_set_calibration_param(adc_n, param) adc_ll_set_calibration_param(adc_n, param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
236
components/hal/esp32c3/include/hal/clk_gate_ll.h
Normal file
236
components/hal/esp32c3/include/hal/clk_gate_ll.h
Normal file
@ -0,0 +1,236 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
#include "soc/dport_access.h"
|
||||
|
||||
static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
|
||||
{
|
||||
switch (periph) {
|
||||
case PERIPH_RMT_MODULE:
|
||||
return SYSTEM_RMT_CLK_EN;
|
||||
case PERIPH_LEDC_MODULE:
|
||||
return SYSTEM_LEDC_CLK_EN;
|
||||
case PERIPH_UART0_MODULE:
|
||||
return SYSTEM_UART_CLK_EN;
|
||||
case PERIPH_UART1_MODULE:
|
||||
return SYSTEM_UART1_CLK_EN;
|
||||
case PERIPH_I2C0_MODULE:
|
||||
return SYSTEM_I2C_EXT0_CLK_EN;
|
||||
case PERIPH_I2S1_MODULE:
|
||||
return SYSTEM_I2S1_CLK_EN;
|
||||
case PERIPH_TIMG0_MODULE:
|
||||
return SYSTEM_TIMERGROUP_CLK_EN;
|
||||
case PERIPH_TIMG1_MODULE:
|
||||
return SYSTEM_TIMERGROUP1_CLK_EN;
|
||||
case PERIPH_UHCI0_MODULE:
|
||||
return SYSTEM_UHCI0_CLK_EN;
|
||||
case PERIPH_SYSTIMER_MODULE:
|
||||
return SYSTEM_SYSTIMER_CLK_EN;
|
||||
case PERIPH_SPI_MODULE:
|
||||
return SYSTEM_SPI01_CLK_EN;
|
||||
case PERIPH_SPI2_MODULE:
|
||||
return SYSTEM_SPI2_CLK_EN;
|
||||
case PERIPH_TWAI_MODULE:
|
||||
return SYSTEM_TWAI_CLK_EN;
|
||||
case PERIPH_GDMA_MODULE:
|
||||
return SYSTEM_DMA_CLK_EN;
|
||||
case PERIPH_AES_MODULE:
|
||||
return SYSTEM_CRYPTO_AES_CLK_EN;
|
||||
case PERIPH_SHA_MODULE:
|
||||
return SYSTEM_CRYPTO_SHA_CLK_EN;
|
||||
case PERIPH_RSA_MODULE:
|
||||
return SYSTEM_CRYPTO_RSA_CLK_EN;
|
||||
case PERIPH_HMAC_MODULE:
|
||||
return SYSTEM_CRYPTO_HMAC_CLK_EN;
|
||||
case PERIPH_DS_MODULE:
|
||||
return SYSTEM_CRYPTO_DS_CLK_EN;
|
||||
case PERIPH_RNG_MODULE:
|
||||
return SYSTEM_WIFI_CLK_RNG_EN;
|
||||
case PERIPH_WIFI_MODULE:
|
||||
return SYSTEM_WIFI_CLK_WIFI_EN_M;
|
||||
case PERIPH_BT_MODULE:
|
||||
return SYSTEM_WIFI_CLK_BT_EN_M;
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
return SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M;
|
||||
case PERIPH_BT_BASEBAND_MODULE:
|
||||
return SYSTEM_BT_BASEBAND_EN;
|
||||
case PERIPH_BT_LC_MODULE:
|
||||
return SYSTEM_BT_LC_EN;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool enable)
|
||||
{
|
||||
|
||||
(void)enable; // unused
|
||||
|
||||
switch (periph) {
|
||||
case PERIPH_RMT_MODULE:
|
||||
return SYSTEM_RMT_RST;
|
||||
case PERIPH_LEDC_MODULE:
|
||||
return SYSTEM_LEDC_RST;
|
||||
case PERIPH_UART0_MODULE:
|
||||
return SYSTEM_UART_RST;
|
||||
case PERIPH_UART1_MODULE:
|
||||
return SYSTEM_UART1_RST;
|
||||
case PERIPH_I2C0_MODULE:
|
||||
return SYSTEM_I2C_EXT0_RST;
|
||||
case PERIPH_I2S1_MODULE:
|
||||
return SYSTEM_I2S1_RST;
|
||||
case PERIPH_TIMG0_MODULE:
|
||||
return SYSTEM_TIMERGROUP_RST;
|
||||
case PERIPH_TIMG1_MODULE:
|
||||
return SYSTEM_TIMERGROUP1_RST;
|
||||
case PERIPH_UHCI0_MODULE:
|
||||
return SYSTEM_UHCI0_RST;
|
||||
case PERIPH_SYSTIMER_MODULE:
|
||||
return SYSTEM_SYSTIMER_RST;
|
||||
case PERIPH_GDMA_MODULE:
|
||||
return SYSTEM_DMA_RST;
|
||||
case PERIPH_SPI_MODULE:
|
||||
return SYSTEM_SPI01_RST;
|
||||
case PERIPH_SPI2_MODULE:
|
||||
return SYSTEM_SPI2_RST;
|
||||
case PERIPH_TWAI_MODULE:
|
||||
return SYSTEM_TWAI_RST;
|
||||
case PERIPH_HMAC_MODULE:
|
||||
return SYSTEM_CRYPTO_HMAC_RST;
|
||||
case PERIPH_AES_MODULE:
|
||||
if (enable == true) {
|
||||
// Clear reset on digital signature, otherwise AES unit is held in reset also.
|
||||
return (SYSTEM_CRYPTO_AES_RST | SYSTEM_CRYPTO_DS_RST);
|
||||
} else {
|
||||
//Don't return other units to reset, as this pulls reset on RSA & SHA units, respectively.
|
||||
return SYSTEM_CRYPTO_AES_RST;
|
||||
}
|
||||
case PERIPH_SHA_MODULE:
|
||||
if (enable == true) {
|
||||
// Clear reset on digital signature and HMAC, otherwise SHA is held in reset
|
||||
return (SYSTEM_CRYPTO_SHA_RST | SYSTEM_CRYPTO_DS_RST | SYSTEM_CRYPTO_HMAC_RST);
|
||||
} else {
|
||||
// Don't assert reset on secure boot, otherwise AES is held in reset
|
||||
return SYSTEM_CRYPTO_SHA_RST;
|
||||
}
|
||||
case PERIPH_RSA_MODULE:
|
||||
if (enable == true) {
|
||||
/* also clear reset on digital signature, otherwise RSA is held in reset */
|
||||
return (SYSTEM_CRYPTO_RSA_RST | SYSTEM_CRYPTO_DS_RST);
|
||||
} else {
|
||||
/* don't reset digital signature unit, as this resets AES also */
|
||||
return SYSTEM_CRYPTO_RSA_RST;
|
||||
}
|
||||
case PERIPH_DS_MODULE:
|
||||
return SYSTEM_CRYPTO_DS_RST;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
|
||||
{
|
||||
switch (periph) {
|
||||
case PERIPH_RNG_MODULE:
|
||||
case PERIPH_WIFI_MODULE:
|
||||
case PERIPH_BT_MODULE:
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
case PERIPH_BT_BASEBAND_MODULE:
|
||||
case PERIPH_BT_LC_MODULE:
|
||||
return SYSTEM_WIFI_CLK_EN_REG;
|
||||
|
||||
case PERIPH_HMAC_MODULE:
|
||||
case PERIPH_DS_MODULE:
|
||||
case PERIPH_AES_MODULE:
|
||||
case PERIPH_RSA_MODULE:
|
||||
case PERIPH_SHA_MODULE:
|
||||
case PERIPH_GDMA_MODULE:
|
||||
return SYSTEM_PERIP_CLK_EN1_REG;
|
||||
default:
|
||||
return SYSTEM_PERIP_CLK_EN0_REG;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
|
||||
{
|
||||
switch (periph) {
|
||||
case PERIPH_RNG_MODULE:
|
||||
case PERIPH_WIFI_MODULE:
|
||||
case PERIPH_BT_MODULE:
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
case PERIPH_BT_BASEBAND_MODULE:
|
||||
case PERIPH_BT_LC_MODULE:
|
||||
return SYSTEM_WIFI_RST_EN_REG;
|
||||
|
||||
case PERIPH_HMAC_MODULE:
|
||||
case PERIPH_DS_MODULE:
|
||||
case PERIPH_AES_MODULE:
|
||||
case PERIPH_RSA_MODULE:
|
||||
case PERIPH_SHA_MODULE:
|
||||
case PERIPH_GDMA_MODULE:
|
||||
return SYSTEM_PERIP_RST_EN1_REG;
|
||||
default:
|
||||
return SYSTEM_PERIP_RST_EN0_REG;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void periph_ll_enable_clk_clear_rst(periph_module_t periph)
|
||||
{
|
||||
DPORT_SET_PERI_REG_MASK(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph));
|
||||
DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, true));
|
||||
}
|
||||
|
||||
static inline void periph_ll_disable_clk_set_rst(periph_module_t periph)
|
||||
{
|
||||
DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph));
|
||||
DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false));
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR periph_ll_wifi_bt_module_enable_clk_clear_rst(void)
|
||||
{
|
||||
DPORT_SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M);
|
||||
DPORT_CLEAR_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0);
|
||||
}
|
||||
|
||||
static inline void IRAM_ATTR periph_ll_wifi_bt_module_disable_clk_set_rst(void)
|
||||
{
|
||||
DPORT_CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M);
|
||||
DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0);
|
||||
}
|
||||
|
||||
static inline void periph_ll_reset(periph_module_t periph)
|
||||
{
|
||||
DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false));
|
||||
DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false));
|
||||
}
|
||||
|
||||
static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph)
|
||||
{
|
||||
return DPORT_REG_GET_BIT(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)) == 0 &&
|
||||
DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0;
|
||||
}
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
150
components/hal/esp32c3/include/hal/cpu_ll.h
Normal file
150
components/hal/esp32c3/include/hal/cpu_ll.h
Normal file
@ -0,0 +1,150 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "soc/cpu_caps.h"
|
||||
#include "esp_bit_defs.h"
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#include "esp_attr.h"
|
||||
#include "riscv/csr.h"
|
||||
|
||||
/*performance counter*/
|
||||
#define CSR_PCER_MACHINE 0x7e0
|
||||
#define CSR_PCMR_MACHINE 0x7e1
|
||||
#define CSR_PCCR_MACHINE 0x7e2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int cpu_ll_get_core_id(void)
|
||||
{
|
||||
#if SOC_CPU_CORES_NUM == 1
|
||||
return 0; // No need to check core ID on single core hardware
|
||||
#else
|
||||
int cpuid;
|
||||
cpuid = RV_READ_CSR(mhartid);
|
||||
return cpuid;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void cpu_ll_enable_cycle_count(void)
|
||||
{
|
||||
RV_WRITE_CSR(CSR_PCER_MACHINE,1);
|
||||
RV_WRITE_CSR(CSR_PCMR_MACHINE,1);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline uint32_t IRAM_ATTR cpu_ll_get_cycle_count(void)
|
||||
{
|
||||
uint32_t result;
|
||||
result = RV_READ_CSR(CSR_PCCR_MACHINE);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void* cpu_ll_get_sp(void)
|
||||
{
|
||||
void *sp;
|
||||
asm volatile ("mv %0, sp;" : "=r" (sp));
|
||||
return sp;
|
||||
}
|
||||
|
||||
static inline void cpu_ll_init_hwloop(void)
|
||||
{
|
||||
// Nothing needed here for ESP32-C3
|
||||
}
|
||||
|
||||
static inline void cpu_ll_set_breakpoint(int id, uint32_t pc)
|
||||
{
|
||||
RV_WRITE_CSR(tselect,id);
|
||||
RV_SET_CSR(CSR_TCONTROL,TCONTROL_MTE);
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_USER|TDATA1_MACHINE|TDATA1_EXECUTE);
|
||||
RV_WRITE_CSR(tdata2,pc);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void cpu_ll_clear_breakpoint(int id)
|
||||
{
|
||||
RV_WRITE_CSR(tselect,id);
|
||||
RV_CLEAR_CSR(CSR_TCONTROL,TCONTROL_MTE);
|
||||
RV_CLEAR_CSR(CSR_TDATA1, TDATA1_USER|TDATA1_MACHINE|TDATA1_EXECUTE);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline uint32_t cpu_ll_ptr_to_pc(const void* addr)
|
||||
{
|
||||
return ((uint32_t) addr);
|
||||
}
|
||||
|
||||
static inline void* cpu_ll_pc_to_ptr(uint32_t pc)
|
||||
{
|
||||
return (void*) ((pc & 0x3fffffff) | 0x40000000);
|
||||
}
|
||||
|
||||
static inline void cpu_ll_set_watchpoint(int id,
|
||||
const void* addr,
|
||||
size_t size,
|
||||
bool on_read,
|
||||
bool on_write)
|
||||
{
|
||||
uint32_t addr_napot;
|
||||
RV_WRITE_CSR(tselect,id);
|
||||
RV_SET_CSR(CSR_TCONTROL,TCONTROL_MTE);
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_USER|TDATA1_MACHINE);
|
||||
RV_SET_CSR_FIELD(CSR_TDATA1, TDATA1_MATCH, 1);
|
||||
addr_napot = ((uint32_t)addr)|((size>>1)-1);
|
||||
if(on_read) {
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_LOAD);
|
||||
}
|
||||
if(on_write) {
|
||||
RV_SET_CSR(CSR_TDATA1, TDATA1_STORE);
|
||||
}
|
||||
RV_WRITE_CSR(tdata2,addr_napot);
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void cpu_ll_clear_watchpoint(int id)
|
||||
{
|
||||
RV_WRITE_CSR(tselect,id);
|
||||
RV_CLEAR_CSR(CSR_TCONTROL,TCONTROL_MTE);
|
||||
RV_CLEAR_CSR(CSR_TDATA1, TDATA1_USER|TDATA1_MACHINE);
|
||||
RV_CLEAR_CSR_FIELD(CSR_TDATA1,TDATA1_MATCH);
|
||||
RV_CLEAR_CSR(CSR_TDATA1, TDATA1_MACHINE);
|
||||
RV_CLEAR_CSR(CSR_TDATA1, TDATA1_LOAD|TDATA1_STORE|TDATA1_EXECUTE);
|
||||
return;
|
||||
}
|
||||
|
||||
FORCE_INLINE_ATTR bool cpu_ll_is_debugger_attached(void)
|
||||
{
|
||||
return REG_GET_BIT(ASSIST_DEBUG_C0RE_0_DEBUG_MODE_REG, ASSIST_DEBUG_CORE_0_DEBUG_MODULE_ACTIVE);
|
||||
}
|
||||
|
||||
static inline void cpu_ll_break(void)
|
||||
{
|
||||
asm volatile("ebreak\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static inline void cpu_ll_set_vecbase(const void* vecbase)
|
||||
{
|
||||
uintptr_t vecbase_int = (uintptr_t)vecbase;
|
||||
vecbase_int |= 1; // Set MODE field to treat MTVEC as a vector base address
|
||||
RV_WRITE_CSR(mtvec, vecbase_int);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
415
components/hal/esp32c3/include/hal/gdma_ll.h
Normal file
415
components/hal/esp32c3/include/hal/gdma_ll.h
Normal file
@ -0,0 +1,415 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/gdma_struct.h"
|
||||
#include "soc/gdma_reg.h"
|
||||
#include "soc/gdma_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GDMA_LL_EVENT_TX_FIFO_UDF (1<<12)
|
||||
#define GDMA_LL_EVENT_TX_FIFO_OVF (1<<11)
|
||||
#define GDMA_LL_EVENT_RX_FIFO_UDF (1<<10)
|
||||
#define GDMA_LL_EVENT_RX_FIFO_OVF (1<<9)
|
||||
#define GDMA_LL_EVENT_TX_TOTAL_EOF (1<<8)
|
||||
#define GDMA_LL_EVENT_RX_DESC_EMPTY (1<<7)
|
||||
#define GDMA_LL_EVENT_TX_DESC_ERROR (1<<6)
|
||||
#define GDMA_LL_EVENT_RX_DESC_ERROR (1<<5)
|
||||
#define GDMA_LL_EVENT_TX_EOF (1<<4)
|
||||
#define GDMA_LL_EVENT_TX_DONE (1<<3)
|
||||
#define GDMA_LL_EVENT_RX_ERR_EOF (1<<2)
|
||||
#define GDMA_LL_EVENT_RX_SUC_EOF (1<<1)
|
||||
#define GDMA_LL_EVENT_RX_DONE (1<<0)
|
||||
|
||||
#define GDMA_LL_TRIG_SRC_SPI2 (0)
|
||||
#define GDMA_LL_TRIG_SRC_UART (2)
|
||||
#define GDMA_LL_TRIG_SRC_I2S0 (3)
|
||||
#define GDMA_LL_TRIG_SRC_AES (6)
|
||||
#define GDMA_LL_TRIG_SRC_SHA (7)
|
||||
#define GDMA_LL_TRIG_SRC_ADC_DAC (8)
|
||||
|
||||
///////////////////////////////////// Common /////////////////////////////////////////
|
||||
/**
|
||||
* @brief Enable DMA channel M2M mode (TX channel n forward data to RX channel n), disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_enable_m2m_mode(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].in.in_conf0.mem_trans_en = enable;
|
||||
if (enable) {
|
||||
// only have to give it a valid value
|
||||
dev->channel[channel].in.in_peri_sel.sel = 0;
|
||||
dev->channel[channel].out.out_peri_sel.sel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get DMA interrupt status word
|
||||
*/
|
||||
static inline uint32_t gdma_ll_get_interrupt_status(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->intr[channel].st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA interrupt
|
||||
*/
|
||||
static inline void gdma_ll_enable_interrupt(gdma_dev_t *dev, uint32_t channel, uint32_t mask, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->intr[channel].ena.val |= mask;
|
||||
} else {
|
||||
dev->intr[channel].ena.val &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear DMA interrupt
|
||||
*/
|
||||
static inline void gdma_ll_clear_interrupt_status(gdma_dev_t *dev, uint32_t channel, uint32_t mask)
|
||||
{
|
||||
dev->intr[channel].clr.val = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA clock gating
|
||||
*/
|
||||
static inline void gdma_ll_enable_clock(gdma_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->misc_conf.clk_en = enable;
|
||||
}
|
||||
|
||||
///////////////////////////////////// RX /////////////////////////////////////////
|
||||
/**
|
||||
* @brief Enable DMA RX channel to check the owner bit in the descriptor, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_rx_enable_owner_check(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].in.in_conf1.in_check_owner = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA RX channel burst reading data, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_rx_enable_data_burst(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].in.in_conf0.in_data_burst_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA RX channel burst reading descriptor link, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_rx_enable_descriptor_burst(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].in.in_conf0.indscr_burst_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset DMA RX channel FSM and FIFO pointer
|
||||
*/
|
||||
static inline void gdma_ll_rx_reset_channel(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].in.in_conf0.in_rst = 1;
|
||||
dev->channel[channel].in.in_conf0.in_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if DMA RX FIFO is full
|
||||
* @param fifo_level only supports level 1
|
||||
*/
|
||||
static inline bool gdma_ll_rx_is_fifo_full(gdma_dev_t *dev, uint32_t channel, uint32_t fifo_level)
|
||||
{
|
||||
return dev->channel[channel].in.infifo_status.val & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if DMA RX FIFO is empty
|
||||
* @param fifo_level only supports level 1
|
||||
*/
|
||||
static inline bool gdma_ll_rx_is_fifo_empty(gdma_dev_t *dev, uint32_t channel, uint32_t fifo_level)
|
||||
{
|
||||
return dev->channel[channel].in.infifo_status.val & 0x02;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of bytes in RX FIFO
|
||||
* @param fifo_level only supports level 1
|
||||
*/
|
||||
static inline uint32_t gdma_ll_rx_get_fifo_bytes(gdma_dev_t *dev, uint32_t channel, uint32_t fifo_level)
|
||||
{
|
||||
return dev->channel[channel].in.infifo_status.infifo_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pop data from DMA RX FIFO
|
||||
*/
|
||||
static inline uint32_t gdma_ll_rx_pop_data(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].in.in_pop.infifo_pop = 1;
|
||||
return dev->channel[channel].in.in_pop.infifo_rdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the descriptor link base address for RX channel
|
||||
*/
|
||||
static inline void gdma_ll_rx_set_desc_addr(gdma_dev_t *dev, uint32_t channel, uint32_t addr)
|
||||
{
|
||||
dev->channel[channel].in.in_link.addr = addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start dealing with RX descriptors
|
||||
*/
|
||||
static inline void gdma_ll_rx_start(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].in.in_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop dealing with RX descriptors
|
||||
*/
|
||||
static inline void gdma_ll_rx_stop(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].in.in_link.stop = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restart a new inlink right after the last descriptor
|
||||
*/
|
||||
static inline void gdma_ll_rx_restart(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].in.in_link.restart = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA RX to return the address of current descriptor when receives error
|
||||
*/
|
||||
static inline void gdma_ll_rx_enable_auto_return(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].in.in_link.auto_ret = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if DMA RX FSM is in IDLE state
|
||||
*/
|
||||
static inline bool gdma_ll_rx_is_fsm_idle(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].in.in_link.park;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get RX success EOF descriptor's address
|
||||
*/
|
||||
static inline uint32_t gdma_ll_rx_get_success_eof_desc_addr(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].in.in_suc_eof_des_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get RX error EOF descriptor's address
|
||||
*/
|
||||
static inline uint32_t gdma_ll_rx_get_error_eof_desc_addr(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].in.in_err_eof_des_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current RX descriptor's address
|
||||
*/
|
||||
static inline uint32_t gdma_ll_rx_get_current_desc_addr(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].in.in_dscr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set priority for DMA RX channel
|
||||
*/
|
||||
static inline void gdma_ll_rx_set_priority(gdma_dev_t *dev, uint32_t channel, uint32_t prio)
|
||||
{
|
||||
dev->channel[channel].in.in_pri.rx_pri = prio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connect DMA RX channel to a given peripheral
|
||||
*/
|
||||
static inline void gdma_ll_rx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id)
|
||||
{
|
||||
dev->channel[channel].in.in_peri_sel.sel = periph_id;
|
||||
}
|
||||
|
||||
///////////////////////////////////// TX /////////////////////////////////////////
|
||||
/**
|
||||
* @brief Enable DMA TX channel to check the owner bit in the descriptor, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_tx_enable_owner_check(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].out.out_conf1.out_check_owner = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA TX channel burst sending data, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_tx_enable_data_burst(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].out.out_conf0.out_data_burst_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA TX channel burst reading descriptor link, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_tx_enable_descriptor_burst(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].out.out_conf0.outdscr_burst_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set TX channel EOF mode
|
||||
*/
|
||||
static inline void gdma_ll_tx_set_eof_mode(gdma_dev_t *dev, uint32_t channel, uint32_t mode)
|
||||
{
|
||||
dev->channel[channel].out.out_conf0.out_eof_mode = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA TX channel automatic write results back to descriptor after all data has been sent out, disabled by default
|
||||
*/
|
||||
static inline void gdma_ll_tx_enable_auto_write_back(gdma_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->channel[channel].out.out_conf0.out_auto_wrback = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset DMA TX channel FSM and FIFO pointer
|
||||
*/
|
||||
static inline void gdma_ll_tx_reset_channel(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].out.out_conf0.out_rst = 1;
|
||||
dev->channel[channel].out.out_conf0.out_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if DMA TX FIFO is full
|
||||
* @param fifo_level only supports level 1
|
||||
*/
|
||||
static inline bool gdma_ll_tx_is_fifo_full(gdma_dev_t *dev, uint32_t channel, uint32_t fifo_level)
|
||||
{
|
||||
return dev->channel[channel].out.outfifo_status.val & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if DMA TX FIFO is empty
|
||||
* @param fifo_level only supports level 1
|
||||
*/
|
||||
static inline bool gdma_ll_tx_is_fifo_empty(gdma_dev_t *dev, uint32_t channel, uint32_t fifo_level)
|
||||
{
|
||||
return dev->channel[channel].out.outfifo_status.val & 0x02;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get number of bytes in TX FIFO
|
||||
* @param fifo_level only supports level 1
|
||||
*/
|
||||
static inline uint32_t gdma_ll_tx_get_fifo_bytes(gdma_dev_t *dev, uint32_t channel, uint32_t fifo_level)
|
||||
{
|
||||
return dev->channel[channel].out.outfifo_status.outfifo_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Push data into DMA TX FIFO
|
||||
*/
|
||||
static inline void gdma_ll_tx_push_data(gdma_dev_t *dev, uint32_t channel, uint32_t data)
|
||||
{
|
||||
dev->channel[channel].out.out_push.outfifo_wdata = data;
|
||||
dev->channel[channel].out.out_push.outfifo_push = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the descriptor link base address for TX channel
|
||||
*/
|
||||
static inline void gdma_ll_tx_set_desc_addr(gdma_dev_t *dev, uint32_t channel, uint32_t addr)
|
||||
{
|
||||
dev->channel[channel].out.out_link.addr = addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start dealing with TX descriptors
|
||||
*/
|
||||
static inline void gdma_ll_tx_start(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].out.out_link.start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop dealing with TX descriptors
|
||||
*/
|
||||
static inline void gdma_ll_tx_stop(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].out.out_link.stop = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restart a new outlink right after the last descriptor
|
||||
*/
|
||||
static inline void gdma_ll_tx_restart(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->channel[channel].out.out_link.restart = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if DMA TX FSM is in IDLE state
|
||||
*/
|
||||
static inline bool gdma_ll_tx_is_fsm_idle(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].out.out_link.park;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get TX EOF descriptor's address
|
||||
*/
|
||||
static inline uint32_t gdma_ll_tx_get_eof_desc_addr(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].out.out_eof_des_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get current TX descriptor's address
|
||||
*/
|
||||
static inline uint32_t gdma_ll_tx_get_current_desc_addr(gdma_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->channel[channel].out.out_dscr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set priority for DMA TX channel
|
||||
*/
|
||||
static inline void gdma_ll_tx_set_priority(gdma_dev_t *dev, uint32_t channel, uint32_t prio)
|
||||
{
|
||||
dev->channel[channel].out.out_pri.tx_pri = prio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connect DMA TX channel to a given peripheral
|
||||
*/
|
||||
static inline void gdma_ll_tx_connect_to_periph(gdma_dev_t *dev, uint32_t channel, uint32_t periph_id)
|
||||
{
|
||||
dev->channel[channel].out.out_peri_sel.sel = periph_id;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
423
components/hal/esp32c3/include/hal/gpio_ll.h
Normal file
423
components/hal/esp32c3/include/hal/gpio_ll.h
Normal file
@ -0,0 +1,423 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The LL layer for ESP32-S3 GPIO register operations
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "hal/gpio_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get GPIO hardware instance with giving gpio num
|
||||
#define GPIO_LL_GET_HW(num) (((num) == 0) ? (&GPIO) : NULL)
|
||||
|
||||
/**
|
||||
* @brief Enable pull-up on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_pullup_en(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable pull-up on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_pullup_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable pull-down on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_pulldown_en(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable pull-down on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_pulldown_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO set interrupt trigger type
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number. If you want to set the trigger type of e.g. of GPIO16, gpio_num should be GPIO_NUM_16 (16);
|
||||
* @param intr_type Interrupt type, select from gpio_int_type_t
|
||||
*/
|
||||
static inline void gpio_ll_set_intr_type(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
{
|
||||
hw->pin[gpio_num].int_type = intr_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO interrupt status
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param core_id interrupt core id
|
||||
* @param status interrupt status
|
||||
*/
|
||||
static inline void gpio_ll_get_intr_status(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
|
||||
{
|
||||
*status = hw->pcpu_int.intr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO interrupt status high
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param core_id interrupt core id
|
||||
* @param status interrupt status high
|
||||
*/
|
||||
static inline void gpio_ll_get_intr_status_high(gpio_dev_t *hw, uint32_t core_id, uint32_t *status)
|
||||
{
|
||||
*status = 0; // Less than 32 GPIOs in ESP32-C3
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear GPIO interrupt status
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param mask interrupt status clear mask
|
||||
*/
|
||||
static inline void gpio_ll_clear_intr_status(gpio_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->status_w1tc.status_w1tc = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear GPIO interrupt status high
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param mask interrupt status high clear mask
|
||||
*/
|
||||
static inline void gpio_ll_clear_intr_status_high(gpio_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
// hw->status1_w1tc.intr_st = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO module interrupt signal
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param core_id Interrupt enabled CPU to corresponding ID
|
||||
* @param gpio_num GPIO number. If you want to enable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
|
||||
*/
|
||||
static inline void gpio_ll_intr_enable_on_core(gpio_dev_t *hw, uint32_t core_id, gpio_num_t gpio_num)
|
||||
{
|
||||
if (core_id == 0) {
|
||||
GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr
|
||||
} else {
|
||||
// GPIO.pin[gpio_num].int_ena = GPIO_APP_CPU_INTR_ENA; //enable pro cpu intr
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO module interrupt signal
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number. If you want to disable the interrupt of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
|
||||
*/
|
||||
static inline void gpio_ll_intr_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
hw->pin[gpio_num].int_ena = 0; //disable GPIO intr
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable input mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_input_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[gpio_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable input mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_input_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable output mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_output_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
hw->enable_w1tc.enable_w1tc = (0x1 << gpio_num);
|
||||
} else {
|
||||
// hw->enable1_w1tc.data = (0x1 << (gpio_num - 32));
|
||||
}
|
||||
|
||||
// Ensure no other output signal is routed via GPIO matrix to this pin
|
||||
REG_WRITE(GPIO_FUNC0_OUT_SEL_CFG_REG + (gpio_num * 4),
|
||||
SIG_GPIO_OUT_IDX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable output mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_output_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
hw->enable_w1ts.enable_w1ts = (0x1 << gpio_num);
|
||||
} else {
|
||||
// hw->enable1_w1ts.data = (0x1 << (gpio_num - 32));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable open-drain mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_od_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
hw->pin[gpio_num].pad_driver = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable open-drain mode on GPIO.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_od_enable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
hw->pin[gpio_num].pad_driver = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO set output level
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number. If you want to set the output level of e.g. GPIO16, gpio_num should be GPIO_NUM_16 (16);
|
||||
* @param level Output level. 0: low ; 1: high
|
||||
*/
|
||||
static inline void gpio_ll_set_level(gpio_dev_t *hw, gpio_num_t gpio_num, uint32_t level)
|
||||
{
|
||||
if (level) {
|
||||
if (gpio_num < 32) {
|
||||
hw->out_w1ts.out_w1ts = (1 << gpio_num);
|
||||
} else {
|
||||
// hw->out1_w1ts.data = (1 << (gpio_num - 32));
|
||||
}
|
||||
} else {
|
||||
if (gpio_num < 32) {
|
||||
hw->out_w1tc.out_w1tc = (1 << gpio_num);
|
||||
} else {
|
||||
// hw->out1_w1tc.data = (1 << (gpio_num - 32));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief GPIO get input level
|
||||
*
|
||||
* @warning If the pad is not configured for input (or input and output) the returned value is always 0.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number. If you want to get the logic level of e.g. pin GPIO16, gpio_num should be GPIO_NUM_16 (16);
|
||||
*
|
||||
* @return
|
||||
* - 0 the GPIO input level is 0
|
||||
* - 1 the GPIO input level is 1
|
||||
*/
|
||||
static inline int gpio_ll_get_level(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
if (gpio_num < 32) {
|
||||
return (hw->in.data >> gpio_num) & 0x1;
|
||||
} else {
|
||||
return 0; // Less than 32 GPIOs in ESP32-C3
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable GPIO wake-up function.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number.
|
||||
* @param intr_type GPIO wake-up type. Only GPIO_INTR_LOW_LEVEL or GPIO_INTR_HIGH_LEVEL can be used.
|
||||
*/
|
||||
static inline void gpio_ll_wakeup_enable(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
{
|
||||
hw->pin[gpio_num].int_type = intr_type;
|
||||
hw->pin[gpio_num].wakeup_enable = 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable GPIO wake-up function.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number
|
||||
*/
|
||||
static inline void gpio_ll_wakeup_disable(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
hw->pin[gpio_num].wakeup_enable = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set GPIO pad drive capability
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number, only support output GPIOs
|
||||
* @param strength Drive capability of the pad
|
||||
*/
|
||||
static inline void gpio_ll_set_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_drive_cap_t strength)
|
||||
{
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, strength, FUN_DRV_S);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get GPIO pad drive capability
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number, only support output GPIOs
|
||||
* @param strength Pointer to accept drive capability of the pad
|
||||
*/
|
||||
static inline void gpio_ll_get_drive_capability(gpio_dev_t *hw, gpio_num_t gpio_num, gpio_drive_cap_t *strength)
|
||||
{
|
||||
*strength = GET_PERI_REG_BITS2(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, FUN_DRV_S);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable all digital gpio pad hold function during Deep-sleep.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
*/
|
||||
static inline void gpio_ll_deep_sleep_hold_en(gpio_dev_t *hw)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable all digital gpio pad hold function during Deep-sleep.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
*/
|
||||
static inline void gpio_ll_deep_sleep_hold_dis(gpio_dev_t *hw)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable gpio pad hold function.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number, only support output GPIOs
|
||||
*/
|
||||
static inline void gpio_ll_hold_en(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable gpio pad hold function.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number, only support output GPIOs
|
||||
*/
|
||||
static inline void gpio_ll_hold_dis(gpio_dev_t *hw, gpio_num_t gpio_num)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set pad input to a peripheral signal through the IOMUX.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num GPIO number of the pad.
|
||||
* @param signal_idx Peripheral signal id to input. One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``.
|
||||
*/
|
||||
static inline void gpio_ll_iomux_in(gpio_dev_t *hw, uint32_t gpio, uint32_t signal_idx)
|
||||
{
|
||||
hw->func_in_sel_cfg[signal_idx].sig_in_sel = 0;
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[gpio]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set peripheral output to an GPIO pad through the IOMUX.
|
||||
*
|
||||
* @param hw Peripheral GPIO hardware instance address.
|
||||
* @param gpio_num gpio_num GPIO number of the pad.
|
||||
* @param func The function number of the peripheral pin to output pin.
|
||||
* One of the ``FUNC_X_*`` of specified pin (X) in ``soc/io_mux_reg.h``.
|
||||
* @param oen_inv True if the output enable needs to be inverted, otherwise False.
|
||||
*/
|
||||
static inline void gpio_ll_iomux_out(gpio_dev_t *hw, uint8_t gpio_num, int func, uint32_t oen_inv)
|
||||
{
|
||||
hw->func_out_sel_cfg[gpio_num].oen_sel = 0;
|
||||
hw->func_out_sel_cfg[gpio_num].oen_inv_sel = oen_inv;
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func);
|
||||
}
|
||||
|
||||
static inline void gpio_ll_force_hold_all(gpio_dev_t *hw)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
|
||||
}
|
||||
|
||||
static inline void gpio_ll_force_unhold_all(gpio_dev_t *hw)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
366
components/hal/esp32c3/include/hal/gpspi_flash_ll.h
Normal file
366
components/hal/esp32c3/include/hal/gpspi_flash_ll.h
Normal file
@ -0,0 +1,366 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The ll is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The Lowlevel layer for SPI Flash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "soc/spi_periph.h"
|
||||
#include "hal/spi_types.h"
|
||||
#include "hal/spi_flash_types.h"
|
||||
#include <sys/param.h> // For MIN/MAX
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//NOTE: These macros are changed on c3 for build. MODIFY these when bringup flash.
|
||||
#define gpspi_flash_ll_get_hw(host_id) ( ((host_id)==SPI2_HOST) ? &GPSPI2 : ({abort();(spi_dev_t*)0;}) )
|
||||
#define gpspi_flash_ll_hw_get_id(dev) ( ((dev) == (void*)&GPSPI2) ? SPI2_HOST : -1 )
|
||||
|
||||
typedef typeof(GPSPI2.clock) gpspi_flash_ll_clock_reg_t;
|
||||
|
||||
//Supported clock register values
|
||||
#define GPSPI_FLASH_LL_CLKREG_VAL_5MHZ ((gpspi_flash_ll_clock_reg_t){.val=0x0000F1CF}) ///< Clock set to 5 MHz
|
||||
#define GPSPI_FLASH_LL_CLKREG_VAL_10MHZ ((gpspi_flash_ll_clock_reg_t){.val=0x000070C7}) ///< Clock set to 10 MHz
|
||||
#define GPSPI_FLASH_LL_CLKREG_VAL_20MHZ ((gpspi_flash_ll_clock_reg_t){.val=0x00003043}) ///< Clock set to 20 MHz
|
||||
#define GPSPI_FLASH_LL_CLKREG_VAL_26MHZ ((gpspi_flash_ll_clock_reg_t){.val=0x00002002}) ///< Clock set to 26 MHz
|
||||
#define GPSPI_FLASH_LL_CLKREG_VAL_40MHZ ((gpspi_flash_ll_clock_reg_t){.val=0x00001001}) ///< Clock set to 40 MHz
|
||||
#define GPSPI_FLASH_LL_CLKREG_VAL_80MHZ ((gpspi_flash_ll_clock_reg_t){.val=0x80000000}) ///< Clock set to 80 MHz
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Control
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset peripheral registers before configuration and starting control
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_reset(spi_dev_t *dev)
|
||||
{
|
||||
dev->user.val = 0;
|
||||
dev->ctrl.val = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the previous operation is done.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if last command is done, otherwise false.
|
||||
*/
|
||||
static inline bool gpspi_flash_ll_cmd_is_done(const spi_dev_t *dev)
|
||||
{
|
||||
return (dev->cmd.val == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read data from the buffer after ``gpspi_flash_ll_read`` is done.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param buffer Buffer to hold the output data
|
||||
* @param read_len Length to get out of the buffer
|
||||
*/
|
||||
static inline void gpspi_flash_ll_get_buffer_data(spi_dev_t *dev, void *buffer, uint32_t read_len)
|
||||
{
|
||||
if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) {
|
||||
// If everything is word-aligned, do a faster memcpy
|
||||
memcpy(buffer, (void *)dev->data_buf, read_len);
|
||||
} else {
|
||||
// Otherwise, slow(er) path copies word by word
|
||||
int copy_len = read_len;
|
||||
for (int i = 0; i < (read_len + 3) / 4; i++) {
|
||||
int word_len = MIN(sizeof(uint32_t), copy_len);
|
||||
uint32_t word = dev->data_buf[i];
|
||||
memcpy(buffer, &word, word_len);
|
||||
buffer = (void *)((intptr_t)buffer + word_len);
|
||||
copy_len -= word_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a word to the data buffer.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param word Data to write at address 0.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_write_word(spi_dev_t *dev, uint32_t word)
|
||||
{
|
||||
dev->data_buf[0] = word;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data to be written in the data buffer.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param buffer Buffer holding the data
|
||||
* @param length Length of data in bytes.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_buffer_data(spi_dev_t *dev, const void *buffer, uint32_t length)
|
||||
{
|
||||
// Load data registers, word at a time
|
||||
int num_words = (length + 3) / 4;
|
||||
for (int i = 0; i < num_words; i++) {
|
||||
uint32_t word = 0;
|
||||
uint32_t word_len = MIN(length, sizeof(word));
|
||||
memcpy(&word, buffer, word_len);
|
||||
dev->data_buf[i] = word;
|
||||
length -= word_len;
|
||||
buffer = (void *)((intptr_t)buffer + word_len);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a user defined transaction. All phases, including command, address, dummy, and the data phases,
|
||||
* should be configured before this is called.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_user_start(spi_dev_t *dev)
|
||||
{
|
||||
dev->cmd.usr = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the host is idle to perform new commands.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if the host is idle, otherwise false
|
||||
*/
|
||||
static inline bool gpspi_flash_ll_host_idle(const spi_dev_t *dev)
|
||||
{
|
||||
abort(); //TODO ESP32-C3 IDF-2204
|
||||
}
|
||||
|
||||
/**
|
||||
* Set phases for user-defined transaction to read
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_read_phase(spi_dev_t *dev)
|
||||
{
|
||||
typeof (dev->user) user = {
|
||||
.usr_command = 1,
|
||||
.usr_mosi = 0,
|
||||
.usr_miso = 1,
|
||||
.usr_addr = 1,
|
||||
};
|
||||
dev->user = user;
|
||||
}
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Select which pin to use for the flash
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param pin Pin ID to use, 0-2. Set to other values to disable all the CS pins.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_cs_pin(spi_dev_t *dev, int pin)
|
||||
{
|
||||
dev->misc.cs0_dis = (pin == 0) ? 0 : 1;
|
||||
dev->misc.cs1_dis = (pin == 1) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the read io mode.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param read_mode I/O mode to use in the following transactions.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_read_mode(spi_dev_t *dev, esp_flash_io_mode_t read_mode)
|
||||
{
|
||||
typeof (dev->ctrl) ctrl = dev->ctrl;
|
||||
typeof (dev->user) user = dev->user;
|
||||
|
||||
ctrl.val &= ~(SPI_FCMD_QUAD_M | SPI_FADDR_QUAD_M | SPI_FREAD_QUAD_M | SPI_FCMD_DUAL_M | SPI_FADDR_DUAL_M | SPI_FREAD_DUAL_M);
|
||||
user.val &= ~(SPI_FWRITE_QUAD_M | SPI_FWRITE_DUAL_M);
|
||||
|
||||
// ctrl.val |= SPI_FAST_RD_MODE_M;
|
||||
switch (read_mode) {
|
||||
case SPI_FLASH_FASTRD:
|
||||
//the default option
|
||||
break;
|
||||
case SPI_FLASH_QIO:
|
||||
ctrl.fread_quad = 1;
|
||||
ctrl.faddr_quad = 1;
|
||||
user.fwrite_quad = 1;
|
||||
break;
|
||||
case SPI_FLASH_QOUT:
|
||||
ctrl.fread_quad = 1;
|
||||
user.fwrite_quad = 1;
|
||||
break;
|
||||
case SPI_FLASH_DIO:
|
||||
ctrl.fread_dual = 1;
|
||||
ctrl.faddr_dual = 1;
|
||||
user.fwrite_dual = 1;
|
||||
break;
|
||||
case SPI_FLASH_DOUT:
|
||||
ctrl.fread_dual = 1;
|
||||
user.fwrite_dual = 1;
|
||||
break;
|
||||
// case SPI_FLASH_SLOWRD:
|
||||
// ctrl.fast_rd_mode = 0;
|
||||
// break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
dev->ctrl = ctrl;
|
||||
dev->user = user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set clock frequency to work at.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param clock_val pointer to the clock value to set
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_clock(spi_dev_t *dev, gpspi_flash_ll_clock_reg_t *clock_val)
|
||||
{
|
||||
dev->clock = *clock_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input length, in bits.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param bitlen Length of input, in bits.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_miso_bitlen(spi_dev_t *dev, uint32_t bitlen)
|
||||
{
|
||||
abort(); //TODO ESP32-C3 IDF-2204
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output length, in bits (not including command, address and dummy
|
||||
* phases)
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param bitlen Length of output, in bits.
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_mosi_bitlen(spi_dev_t *dev, uint32_t bitlen)
|
||||
{
|
||||
abort(); //TODO ESP32-C3 IDF-2204
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the command.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param command Command to send
|
||||
* @param bitlen Length of the command
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_command(spi_dev_t *dev, uint8_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2 = user2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address length that is set in register, in bits.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
*/
|
||||
static inline int gpspi_flash_ll_get_addr_bitlen(spi_dev_t *dev)
|
||||
{
|
||||
return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param bitlen Length of the address, in bits
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_addr_bitlen(spi_dev_t *dev, uint32_t bitlen)
|
||||
{
|
||||
dev->user1.usr_addr_bitlen = (bitlen - 1);
|
||||
dev->user.usr_addr = bitlen ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address to send in user mode. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param addr Address to send
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_usr_address(spi_dev_t *dev, uint32_t addr, uint32_t bitlen)
|
||||
{
|
||||
// The blank region should be all ones
|
||||
uint32_t padding_ones = (bitlen == 32? 0 : UINT32_MAX >> bitlen);
|
||||
dev->addr = (addr << (32 - bitlen)) | padding_ones;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param addr Address to send
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_address(spi_dev_t *dev, uint32_t addr)
|
||||
{
|
||||
dev->addr = addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of dummy cycles.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param dummy_n Cycles of dummy phases
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_dummy(spi_dev_t *dev, uint32_t dummy_n)
|
||||
{
|
||||
dev->user.usr_dummy = dummy_n ? 1 : 0;
|
||||
dev->user1.usr_dummy_cyclelen = dummy_n - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set D/Q output level during dummy phase
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param out_en whether to enable IO output for dummy phase
|
||||
* @param out_level dummy output level
|
||||
*/
|
||||
static inline void gpspi_flash_ll_set_dummy_out(spi_dev_t *dev, uint32_t out_en, uint32_t out_lev)
|
||||
{
|
||||
dev->ctrl.dummy_out = out_en;
|
||||
dev->ctrl.q_pol = out_lev;
|
||||
dev->ctrl.d_pol = out_lev;
|
||||
}
|
||||
|
||||
static inline void gpspi_flash_ll_set_hold(spi_dev_t *dev, uint32_t hold_n)
|
||||
{
|
||||
abort(); //TODO ESP32-C3 IDF-2204
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
109
components/hal/esp32c3/include/hal/hmac_hal.h
Normal file
109
components/hal/esp32c3/include/hal/hmac_hal.h
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use it in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver
|
||||
* the output directly to another peripheral instead, e.g. the Digital Signature peripheral.
|
||||
*/
|
||||
typedef enum {
|
||||
HMAC_OUTPUT_USER = 0, /**< Let user provide a message and read the HMAC result */
|
||||
HMAC_OUTPUT_DS = 1, /**< HMAC is provided to the DS peripheral to decrypt DS private key parameters */
|
||||
HMAC_OUTPUT_JTAG_ENABLE = 2, /**< HMAC is used to enable JTAG after soft-disabling it */
|
||||
HMAC_OUTPUT_ALL = 3 /**< HMAC is used for both as DS input for or enabling JTAG */
|
||||
} hmac_hal_output_t;
|
||||
|
||||
/**
|
||||
* @brief Make the peripheral ready for use.
|
||||
*
|
||||
* This triggers any further steps necessary after enabling the device
|
||||
*/
|
||||
void hmac_hal_start(void);
|
||||
|
||||
/**
|
||||
* @brief Configure which hardware key slot should be used and configure the target of the HMAC output.
|
||||
*
|
||||
* @note Writing out-of-range values is undefined behavior. The user has to ensure that the parameters are in range.
|
||||
*
|
||||
* @param config The target of the HMAC. Possible targets are described in \c hmac_hal_output_t.
|
||||
* See the ESP32C3 TRM for more details.
|
||||
* @param key_id The ID of the hardware key slot to be used.
|
||||
*
|
||||
* @return 0 if the configuration was successful, non-zero if not.
|
||||
* An unsuccessful configuration means that the purpose value in the eFuse of the corresponding key slot
|
||||
* doesn't match to supplied value of \c config.
|
||||
*/
|
||||
uint32_t hmac_hal_configure(hmac_hal_output_t config, uint32_t key_id);
|
||||
|
||||
/**
|
||||
* @brief Write a padded single-block message of 512 bits to the HMAC peripheral.
|
||||
*
|
||||
* The message must not be longer than one block (512 bits) and the padding has to be applied by software before
|
||||
* writing. The padding has to be able to fit into the block after the message.
|
||||
* For more information on HMAC padding, see the ESP32C3 TRM.
|
||||
*/
|
||||
void hmac_hal_write_one_block_512(const void *block);
|
||||
|
||||
/**
|
||||
* @brief Write a message block of 512 bits to the HMAC peripheral.
|
||||
*
|
||||
* This function must be used incombination with \c hmac_hal_next_block_normal() or \c hmac_hal_next_block_padding().
|
||||
* The first message block is written without any prerequisite.
|
||||
* All message blocks which are not the last one, need a call to \c hmac_hal_next_block_normal() before, indicating
|
||||
* to the hardware that a "normal", i.e. non-padded block will follow. This is even the case for a block which begins
|
||||
* padding already but where the padding doesn't fit in (remaining message size > (block size - padding size)).
|
||||
* Before writing the last block which contains the padding, a call to \c hmac_hal_next_block_padding() is necessary
|
||||
* to indicate to the hardware that a block with padding will be written.
|
||||
*
|
||||
* For more information on HMAC padding, see the ESP32C3 TRM.
|
||||
*/
|
||||
void hmac_hal_write_block_512(const void *block);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the hardware that a normal block will be written.
|
||||
*/
|
||||
void hmac_hal_next_block_normal(void);
|
||||
|
||||
/**
|
||||
* @brief Indicate to the hardware that a block with padding will be written.
|
||||
*/
|
||||
void hmac_hal_next_block_padding(void);
|
||||
|
||||
/**
|
||||
* @brief Read the 256 bit HMAC result from the hardware.
|
||||
*/
|
||||
void hmac_hal_read_result_256(void *result);
|
||||
|
||||
/**
|
||||
* @brief Clean the HMAC result provided to other hardware.
|
||||
*/
|
||||
void hmac_hal_clean(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
199
components/hal/esp32c3/include/hal/hmac_ll.h
Normal file
199
components/hal/esp32c3/include/hal/hmac_ll.h
Normal file
@ -0,0 +1,199 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use it in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include "hal/hmac_hal.h"
|
||||
|
||||
#define SHA256_BLOCK_SZ 64
|
||||
#define SHA256_DIGEST_SZ 32
|
||||
|
||||
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG 6
|
||||
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE 7
|
||||
#define EFUSE_KEY_PURPOSE_HMAC_UP 8
|
||||
#define EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL 5
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Makes the peripheral ready for use, after enabling it.
|
||||
*/
|
||||
static inline void hmac_ll_start(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_START_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine where the HMAC output should go.
|
||||
*
|
||||
* The HMAC peripheral can be configured to deliver its output to the user directly, or to deliver
|
||||
* the output directly to another peripheral instead, e.g. the Digital Signature peripheral.
|
||||
*/
|
||||
static inline void hmac_ll_config_output(hmac_hal_output_t config)
|
||||
{
|
||||
switch(config) {
|
||||
case HMAC_OUTPUT_USER:
|
||||
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_UP);
|
||||
break;
|
||||
case HMAC_OUTPUT_DS:
|
||||
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
|
||||
break;
|
||||
case HMAC_OUTPUT_JTAG_ENABLE:
|
||||
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
|
||||
break;
|
||||
case HMAC_OUTPUT_ALL:
|
||||
REG_WRITE(HMAC_SET_PARA_PURPOSE_REG, EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL);
|
||||
break;
|
||||
default:
|
||||
; // do nothing, error will be indicated by hmac_hal_config_error()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Selects which hardware key should be used.
|
||||
*/
|
||||
static inline void hmac_ll_config_hw_key_id(uint32_t key_id)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_PARA_KEY_REG, key_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Apply and check configuration.
|
||||
*
|
||||
* Afterwards, the configuration can be checked for errors with hmac_hal_config_error().
|
||||
*/
|
||||
static inline void hmac_ll_config_finish(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_PARA_FINISH_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Query HMAC error state after configuration actions.
|
||||
*
|
||||
* @return
|
||||
* - 1 or greater on error
|
||||
* - 0 on success
|
||||
*/
|
||||
static inline uint32_t hmac_ll_config_error(void)
|
||||
{
|
||||
return REG_READ(HMAC_QUERY_ERROR_REG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until the HAL is ready for the next interaction.
|
||||
*/
|
||||
static inline void hmac_ll_wait_idle(void)
|
||||
{
|
||||
uint32_t query;
|
||||
do {
|
||||
query = REG_READ(HMAC_QUERY_BUSY_REG);
|
||||
} while(query != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a message block of 512 bits to the HMAC peripheral.
|
||||
*/
|
||||
static inline void hmac_ll_write_block_512(const uint32_t *block)
|
||||
{
|
||||
const size_t REG_WIDTH = sizeof(uint32_t);
|
||||
for (size_t i = 0; i < SHA256_BLOCK_SZ / REG_WIDTH; i++) {
|
||||
REG_WRITE(HMAC_WDATA_BASE + (i * REG_WIDTH), block[i]);
|
||||
}
|
||||
|
||||
REG_WRITE(HMAC_SET_MESSAGE_ONE_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the 256 bit HMAC.
|
||||
*/
|
||||
static inline void hmac_ll_read_result_256(uint32_t *result)
|
||||
{
|
||||
const size_t REG_WIDTH = sizeof(uint32_t);
|
||||
for (size_t i = 0; i < SHA256_DIGEST_SZ / REG_WIDTH; i++) {
|
||||
result[i] = REG_READ(HMAC_RDATA_BASE + (i * REG_WIDTH));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clean the HMAC result provided to other hardware.
|
||||
*/
|
||||
static inline void hmac_ll_clean(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_INVALIDATE_DS_REG, 1);
|
||||
REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals that the following block will be the padded last block.
|
||||
*/
|
||||
static inline void hmac_ll_msg_padding(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_MESSAGE_PAD_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Signals that all blocks have been written and a padding block will automatically be applied by hardware.
|
||||
*
|
||||
* Only applies if the message length is a multiple of 512 bits.
|
||||
* See ESP32C3 TRM HMAC chapter for more details.
|
||||
*/
|
||||
static inline void hmac_ll_msg_end(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_MESSAGE_END_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The message including padding fits into one block, so no further action needs to be taken.
|
||||
*
|
||||
* This is called after the one-block-message has been written.
|
||||
*/
|
||||
static inline void hmac_ll_msg_one_block(void)
|
||||
{
|
||||
REG_WRITE(HMAC_ONE_BLOCK_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Indicate that more blocks will be written after the last block.
|
||||
*/
|
||||
static inline void hmac_ll_msg_continue(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_MESSAGE_ING_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the HMAC result.
|
||||
*
|
||||
* Use this after reading the HMAC result or if aborting after any of the other steps above.
|
||||
*/
|
||||
static inline void hmac_ll_calc_finish(void)
|
||||
{
|
||||
REG_WRITE(HMAC_SET_RESULT_FINISH_REG, 2);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
910
components/hal/esp32c3/include/hal/i2c_ll.h
Normal file
910
components/hal/esp32c3/include/hal/i2c_ll.h
Normal file
@ -0,0 +1,910 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for I2C register operations
|
||||
|
||||
#pragma once
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "hal/i2c_types.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define I2C_LL_INTR_MASK (0x3fff) /*!< I2C all interrupt bitmap */
|
||||
|
||||
/**
|
||||
* @brief I2C hardware cmd register filed.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t byte_num: 8,
|
||||
ack_en: 1,
|
||||
ack_exp: 1,
|
||||
ack_val: 1,
|
||||
op_code: 3,
|
||||
reserved14: 17,
|
||||
done: 1;
|
||||
};
|
||||
uint32_t val;
|
||||
} i2c_hw_cmd_t;
|
||||
|
||||
/**
|
||||
* @brief I2C interrupt event
|
||||
*/
|
||||
typedef enum {
|
||||
I2C_INTR_EVENT_ERR,
|
||||
I2C_INTR_EVENT_ARBIT_LOST, /*!< I2C arbition lost event */
|
||||
I2C_INTR_EVENT_NACK, /*!< I2C NACK event */
|
||||
I2C_INTR_EVENT_TOUT, /*!< I2C time out event */
|
||||
I2C_INTR_EVENT_END_DET, /*!< I2C end detected event */
|
||||
I2C_INTR_EVENT_TRANS_DONE, /*!< I2C trans done event */
|
||||
I2C_INTR_EVENT_RXFIFO_FULL, /*!< I2C rxfifo full event */
|
||||
I2C_INTR_EVENT_TXFIFO_EMPTY, /*!< I2C txfifo empty event */
|
||||
} i2c_intr_event_t;
|
||||
|
||||
/**
|
||||
* @brief Data structure for calculating I2C bus timing.
|
||||
*/
|
||||
typedef struct {
|
||||
uint16_t clkm_div; /*!< I2C core clock devider */
|
||||
uint16_t scl_low; /*!< I2C scl low period */
|
||||
uint16_t scl_high; /*!< I2C scl hight period */
|
||||
uint16_t scl_wait_high; /*!< I2C scl wait_high period */
|
||||
uint16_t sda_hold; /*!< I2C scl low period */
|
||||
uint16_t sda_sample; /*!< I2C sda sample time */
|
||||
uint16_t setup; /*!< I2C start and stop condition setup period */
|
||||
uint16_t hold; /*!< I2C start and stop condition hold period */
|
||||
uint16_t tout; /*!< I2C bus timeout period */
|
||||
} i2c_clk_cal_t;
|
||||
|
||||
// I2C operation mode command
|
||||
#define I2C_LL_CMD_RESTART 6 /*!<I2C restart command */
|
||||
#define I2C_LL_CMD_WRITE 1 /*!<I2C write command */
|
||||
#define I2C_LL_CMD_READ 3 /*!<I2C read command */
|
||||
#define I2C_LL_CMD_STOP 2 /*!<I2C stop command */
|
||||
#define I2C_LL_CMD_END 4 /*!<I2C end command */
|
||||
|
||||
// Get the I2C hardware instance
|
||||
#define I2C_LL_GET_HW(i2c_num) (&I2C0)
|
||||
// Get the I2C hardware FIFO address
|
||||
#define I2C_LL_GET_FIFO_ADDR(i2c_num) (I2C_DATA_APB_REG(i2c_num))
|
||||
// I2C master TX interrupt bitmap
|
||||
#define I2C_LL_MASTER_TX_INT (I2C_NACK_INT_ENA_M|I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
// I2C master RX interrupt bitmap
|
||||
#define I2C_LL_MASTER_RX_INT (I2C_TIME_OUT_INT_ENA_M|I2C_TRANS_COMPLETE_INT_ENA_M|I2C_ARBITRATION_LOST_INT_ENA_M|I2C_END_DETECT_INT_ENA_M)
|
||||
// I2C slave TX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_TX_INT (I2C_TXFIFO_WM_INT_ENA_M)
|
||||
// I2C slave RX interrupt bitmap
|
||||
#define I2C_LL_SLAVE_RX_INT (I2C_RXFIFO_WM_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M)
|
||||
// I2C source clock
|
||||
#define I2C_LL_CLK_SRC_FREQ(src_clk) (((src_clk) == I2C_SCLK_RTC) ? 20*1000*1000 : 40*1000*1000); // Another clock is XTAL clock
|
||||
// delay time after rtc_clk swiching on
|
||||
#define DELAY_RTC_CLK_SWITCH (5)
|
||||
|
||||
/**
|
||||
* @brief Calculate I2C bus frequency
|
||||
* Note that the clock accuracy is affected by the external pull-up resistor,
|
||||
* here we try to to calculate a configuration parameter which is close to the required clock.
|
||||
* But in I2C communication, the clock accuracy is not very concerned.
|
||||
*
|
||||
* @param source_clk I2C source clock
|
||||
* @param bus_freq I2C bus frequency
|
||||
* @param clk_cal Pointer to accept the clock configuration
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2c_clk_cal_t *clk_cal)
|
||||
{
|
||||
uint32_t clkm_div = source_clk / (bus_freq * 1024) +1;
|
||||
uint32_t sclk_freq = source_clk / clkm_div;
|
||||
uint32_t half_cycle = sclk_freq / bus_freq / 2;
|
||||
//SCL
|
||||
clk_cal->clkm_div = clkm_div;
|
||||
clk_cal->scl_low = half_cycle;
|
||||
// default, scl_wait_high < scl_high
|
||||
int scl_wait_high = (bus_freq <= 50000) ? 0 : (half_cycle / 8); // compensate the time when freq > 50K
|
||||
clk_cal->scl_wait_high = scl_wait_high;
|
||||
clk_cal->scl_high = half_cycle - scl_wait_high;
|
||||
clk_cal->sda_hold = half_cycle / 4;
|
||||
// scl_wait_high < sda_sample <= scl_high
|
||||
clk_cal->sda_sample = half_cycle / 2;
|
||||
clk_cal->setup = half_cycle;
|
||||
clk_cal->hold = half_cycle;
|
||||
//default we set the timeout value to about 10 bus cycles
|
||||
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
|
||||
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update I2C configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_update(i2c_dev_t *hw)
|
||||
{
|
||||
hw->ctr.conf_upgate = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the I2C bus timing related register.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param bus_cfg Pointer to the data structure holding the register configuration.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||
{
|
||||
hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1;
|
||||
//scl period
|
||||
hw->scl_low_period.period = bus_cfg->scl_low - 1;
|
||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
||||
//sda sample
|
||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
||||
hw->sda_sample.time = bus_cfg->sda_sample;
|
||||
//setup
|
||||
hw->scl_rstart_setup.time = bus_cfg->setup;
|
||||
hw->scl_stop_setup.time = bus_cfg->setup;
|
||||
//hold
|
||||
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
||||
hw->scl_stop_hold.time = bus_cfg->hold;
|
||||
hw->timeout.time_out_value = bus_cfg->tout;
|
||||
hw->timeout.time_out_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2C txFIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_txfifo_rst(i2c_dev_t *hw)
|
||||
{
|
||||
hw->fifo_conf.tx_fifo_rst = 1;
|
||||
hw->fifo_conf.tx_fifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset I2C rxFIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_rxfifo_rst(i2c_dev_t *hw)
|
||||
{
|
||||
hw->fifo_conf.rx_fifo_rst = 1;
|
||||
hw->fifo_conf.rx_fifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C SCL timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param hight_period The I2C SCL hight period (in core clock cycle, hight_period > 2)
|
||||
* @param low_period The I2C SCL low period (in core clock cycle, low_period > 1)
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void i2c_ll_set_scl_timing(i2c_dev_t *hw, int hight_period, int low_period)
|
||||
{
|
||||
hw->scl_low_period.period = low_period - 1;
|
||||
hw->scl_high_period.period = hight_period - 10;
|
||||
hw->scl_high_period.scl_wait_high_period = hight_period - hw->scl_high_period.period;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C interrupt status
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param mask Interrupt mask needs to be cleared
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_clr_intsts_mask(i2c_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->int_clr.val = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2C interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param mask Interrupt mask needs to be enabled
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_enable_intr_mask(i2c_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->int_ena.val |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param mask Interrupt mask needs to be disabled
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_disable_intr_mask(i2c_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->int_ena.val &= (~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C interrupt status
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return I2C interrupt status
|
||||
*/
|
||||
static inline uint32_t i2c_ll_get_intsts_mask(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->int_status.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C memory access mode, FIFO mode or non-FIFO mode
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param fifo_mode_en Set true to enable FIFO access mode, else, set it false
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_fifo_mode(i2c_dev_t *hw, bool fifo_mode_en)
|
||||
{
|
||||
hw->fifo_conf.nonfifo_en = fifo_mode_en ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C timeout
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param tout_num The I2C timeout value needs to be set (2^tout in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_tout(i2c_dev_t *hw, int tout)
|
||||
{
|
||||
hw->timeout.time_out_value = tout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C slave address
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param slave_addr I2C slave address needs to be set
|
||||
* @param addr_10bit_en Set true to enable 10-bit slave address mode, set false to enable 7-bit address mode
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_slave_addr(i2c_dev_t *hw, uint16_t slave_addr, bool addr_10bit_en)
|
||||
{
|
||||
hw->slave_addr.addr = slave_addr;
|
||||
hw->slave_addr.en_10bit = addr_10bit_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write I2C hardware command register
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param cmd I2C hardware command
|
||||
* @param cmd_idx The index of the command register, should be less than 16
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_write_cmd_reg(i2c_dev_t *hw, i2c_hw_cmd_t cmd, int cmd_idx)
|
||||
{
|
||||
hw->command[cmd_idx].val = cmd.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C start timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param start_setup The start condition setup period (in core clock cycle)
|
||||
* @param start_hold The start condition hold period (in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_start_timing(i2c_dev_t *hw, int start_setup, int start_hold)
|
||||
{
|
||||
hw->scl_rstart_setup.time = start_setup;
|
||||
hw->scl_start_hold.time = start_hold - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C stop timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param stop_setup The stop condition setup period (in core clock cycle)
|
||||
* @param stop_hold The stop condition hold period (in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_stop_timing(i2c_dev_t *hw, int stop_setup, int stop_hold)
|
||||
{
|
||||
hw->scl_stop_setup.time = stop_setup;
|
||||
hw->scl_stop_hold.time = stop_hold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C stop timing
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param sda_sample The SDA sample time (in core clock cycle)
|
||||
* @param sda_hold The SDA hold time (in core clock cycle)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_sda_timing(i2c_dev_t *hw, int sda_sample, int sda_hold)
|
||||
{
|
||||
hw->sda_hold.time = sda_hold;
|
||||
hw->sda_sample.time = sda_sample;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2C txFIFO empty threshold
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param empty_thr The txFIFO empty threshold
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_txfifo_empty_thr(i2c_dev_t *hw, uint8_t empty_thr)
|
||||
{
|
||||
hw->fifo_conf.tx_fifo_wm_thrhd = empty_thr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2C rxFIFO full threshold
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param full_thr The rxFIFO full threshold
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_rxfifo_full_thr(i2c_dev_t *hw, uint8_t full_thr)
|
||||
{
|
||||
hw->fifo_conf.rx_fifo_wm_thrhd = full_thr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the I2C data mode, LSB or MSB
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param tx_mode Tx data bit mode
|
||||
* @param rx_mode Rx data bit mode
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_data_mode(i2c_dev_t *hw, i2c_trans_mode_t tx_mode, i2c_trans_mode_t rx_mode)
|
||||
{
|
||||
hw->ctr.tx_lsb_first = tx_mode;
|
||||
hw->ctr.rx_lsb_first = rx_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the I2C data mode
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param tx_mode Pointer to accept the received bytes mode
|
||||
* @param rx_mode Pointer to accept the sended bytes mode
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_get_data_mode(i2c_dev_t *hw, i2c_trans_mode_t *tx_mode, i2c_trans_mode_t *rx_mode)
|
||||
{
|
||||
*tx_mode = hw->ctr.tx_lsb_first;
|
||||
*rx_mode = hw->ctr.rx_lsb_first;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C sda timing configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param sda_sample Pointer to accept the SDA sample timing configuration
|
||||
* @param sda_hold Pointer to accept the SDA hold timing configuration
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_get_sda_timing(i2c_dev_t *hw, int *sda_sample, int *sda_hold)
|
||||
{
|
||||
*sda_hold = hw->sda_hold.time;
|
||||
*sda_sample = hw->sda_sample.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the I2C hardware version
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return The I2C hardware version
|
||||
*/
|
||||
static inline uint32_t i2c_ll_get_hw_version(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the I2C bus is busy
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return True if I2C state machine is busy, else false will be returned
|
||||
*/
|
||||
static inline bool i2c_ll_is_bus_busy(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->sr.bus_busy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if I2C is master mode
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return True if I2C is master mode, else false will be returned
|
||||
*/
|
||||
static inline bool i2c_ll_is_master_mode(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->ctr.ms_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the rxFIFO readable length
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return RxFIFO readable length
|
||||
*/
|
||||
static inline uint32_t i2c_ll_get_rxfifo_cnt(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->sr.rx_fifo_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C txFIFO writable length
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return TxFIFO writable length
|
||||
*/
|
||||
static inline uint32_t i2c_ll_get_txfifo_len(i2c_dev_t *hw)
|
||||
{
|
||||
return SOC_I2C_FIFO_LEN - hw->sr.tx_fifo_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C timeout configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return The I2C timeout value
|
||||
*/
|
||||
static inline uint32_t i2c_ll_get_tout(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->timeout.time_out_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start I2C transfer
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_trans_start(i2c_dev_t *hw)
|
||||
{
|
||||
hw->ctr.trans_start = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C start timing configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param setup_time Pointer to accept the start condition setup period
|
||||
* @param hold_time Pointer to accept the start condition hold period
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_get_start_timing(i2c_dev_t *hw, int *setup_time, int *hold_time)
|
||||
{
|
||||
*setup_time = hw->scl_rstart_setup.time;
|
||||
*hold_time = hw->scl_start_hold.time + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C stop timing configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param setup_time Pointer to accept the stop condition setup period
|
||||
* @param hold_time Pointer to accept the stop condition hold period
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_get_stop_timing(i2c_dev_t *hw, int *setup_time, int *hold_time)
|
||||
{
|
||||
*setup_time = hw->scl_stop_setup.time;
|
||||
*hold_time = hw->scl_stop_hold.time;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C SCL timing configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param high_period Pointer to accept the SCL high period
|
||||
* @param low_period Pointer to accept the SCL low period
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_get_scl_timing(i2c_dev_t *hw, int *high_period, int *low_period)
|
||||
{
|
||||
*high_period = hw->scl_high_period.period + hw->scl_high_period.scl_wait_high_period;
|
||||
*low_period = hw->scl_low_period.period + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the I2C hardware txFIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param ptr Pointer to data buffer
|
||||
* @param len Amount of data needs to be writen
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void i2c_ll_write_txfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
for (int i = 0; i< len; i++) {
|
||||
hw->fifo_data.data = ptr[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the I2C hardware rxFIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param ptr Pointer to data buffer
|
||||
* @param len Amount of data needs read
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_read_rxfifo(i2c_dev_t *hw, uint8_t *ptr, uint8_t len)
|
||||
{
|
||||
for(int i = 0; i < len; i++) {
|
||||
ptr[i] = hw->fifo_data.data;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure I2C hardware filter
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param filter_num If the glitch period on the line is less than this value, it can be filtered out
|
||||
* If `filter_num == 0`, the filter will be disabled
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_filter(i2c_dev_t *hw, uint8_t filter_num)
|
||||
{
|
||||
if (filter_num > 0) {
|
||||
hw->filter_cfg.scl_thres = filter_num;
|
||||
hw->filter_cfg.sda_thres = filter_num;
|
||||
hw->filter_cfg.scl_en = 1;
|
||||
hw->filter_cfg.sda_en = 1;
|
||||
} else {
|
||||
hw->filter_cfg.scl_en = 0;
|
||||
hw->filter_cfg.sda_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C hardware filter configuration
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return The hardware filter configuration
|
||||
*/
|
||||
static inline uint8_t i2c_ll_get_filter(i2c_dev_t *hw)
|
||||
{
|
||||
return hw->filter_cfg.scl_thres;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2C master TX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_enable_tx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.val = ~0;
|
||||
hw->int_ena.val = I2C_LL_MASTER_TX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2C master RX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_enable_rx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.val = ~0;
|
||||
hw->int_ena.val = I2C_LL_MASTER_RX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C master TX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_disable_tx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.val &= (~I2C_LL_MASTER_TX_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C master RX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_disable_rx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.val &= (~I2C_LL_MASTER_RX_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C master TX interrupt status register
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_clr_tx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.val = I2C_LL_MASTER_TX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C master RX interrupt status register
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_clr_rx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.val = I2C_LL_MASTER_RX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_enable_tx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.val |= I2C_LL_SLAVE_TX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable I2C slave RX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_enable_rx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.val |= I2C_LL_SLAVE_RX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C slave TX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_disable_tx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.val &= (~I2C_LL_SLAVE_TX_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable I2C slave RX interrupt
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_disable_rx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_ena.val &= (~I2C_LL_SLAVE_RX_INT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C slave TX interrupt status register
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_clr_tx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.val = I2C_LL_SLAVE_TX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C slave RX interrupt status register.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_clr_rx_it(i2c_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.val = I2C_LL_SLAVE_RX_INT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reste I2C master FSM. When the master FSM is stuck, call this function to reset the FSM
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_fsm_rst(i2c_dev_t *hw)
|
||||
{
|
||||
hw->ctr.fsm_rst = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear I2C bus, when the slave is stuck in a deadlock and keeps pulling the bus low,
|
||||
* master can controls the SCL bus to generate 9 CLKs.
|
||||
*
|
||||
* Note: The master cannot detect if deadlock happens, but when the scl_st_to interrupt is generated, a deadlock may occur.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_clr_bus(i2c_dev_t *hw)
|
||||
{
|
||||
hw->scl_sp_conf.scl_rst_slv_num = 9;
|
||||
hw->scl_sp_conf.scl_rst_slv_en = 0;
|
||||
hw->ctr.conf_upgate = 1;
|
||||
hw->scl_sp_conf.scl_rst_slv_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set I2C source clock
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param src_clk Source clock of the I2C
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_sclk_t src_clk)
|
||||
{
|
||||
// rtc_clk needs to switch on.
|
||||
if (src_clk == I2C_SCLK_RTC) {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
|
||||
}
|
||||
// src_clk : (1) for RTC_CLK, (0) for XTAL
|
||||
hw->clk_conf.sclk_sel = (src_clk == I2C_SCLK_RTC) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C master interrupt event
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param event Pointer to accept the interrupt event
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
|
||||
{
|
||||
typeof(hw->int_status) int_sts = hw->int_status;
|
||||
if (int_sts.arbitration_lost) {
|
||||
*event = I2C_INTR_EVENT_ARBIT_LOST;
|
||||
} else if (int_sts.nack) {
|
||||
*event = I2C_INTR_EVENT_NACK;
|
||||
} else if (int_sts.time_out) {
|
||||
*event = I2C_INTR_EVENT_TOUT;
|
||||
} else if (int_sts.end_detect) {
|
||||
*event = I2C_INTR_EVENT_END_DET;
|
||||
} else if (int_sts.trans_complete) {
|
||||
*event = I2C_INTR_EVENT_TRANS_DONE;
|
||||
} else {
|
||||
*event = I2C_INTR_EVENT_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get I2C slave interrupt event
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param event Pointer to accept the interrupt event
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_get_event(i2c_dev_t *hw, i2c_intr_event_t *event)
|
||||
{
|
||||
typeof(hw->int_status) int_sts = hw->int_status;
|
||||
if (int_sts.tx_fifo_wm) {
|
||||
*event = I2C_INTR_EVENT_TXFIFO_EMPTY;
|
||||
} else if (int_sts.trans_complete) {
|
||||
*event = I2C_INTR_EVENT_TRANS_DONE;
|
||||
} else if (int_sts.rx_fifo_wm) {
|
||||
*event = I2C_INTR_EVENT_RXFIFO_FULL;
|
||||
} else {
|
||||
*event = I2C_INTR_EVENT_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init I2C master
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_master_init(i2c_dev_t *hw)
|
||||
{
|
||||
typeof(hw->ctr) ctrl_reg;
|
||||
ctrl_reg.val = 0;
|
||||
ctrl_reg.ms_mode = 1;
|
||||
ctrl_reg.clk_en = 1;
|
||||
ctrl_reg.sda_force_out = 1;
|
||||
ctrl_reg.scl_force_out = 1;
|
||||
hw->ctr.val = ctrl_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init I2C slave
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void i2c_ll_slave_init(i2c_dev_t *hw)
|
||||
{
|
||||
typeof(hw->ctr) ctrl_reg;
|
||||
ctrl_reg.val = 0;
|
||||
ctrl_reg.sda_force_out = 1;
|
||||
ctrl_reg.scl_force_out = 1;
|
||||
hw->ctr.val = ctrl_reg.val;
|
||||
hw->fifo_conf.fifo_addr_cfg_en = 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
120
components/hal/esp32c3/include/hal/interrupt_controller_ll.h
Normal file
120
components/hal/esp32c3/include/hal/interrupt_controller_ll.h
Normal file
@ -0,0 +1,120 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupt_core0_reg.h"
|
||||
#include "riscv/interrupt.h"
|
||||
#include "riscv/csr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief enable interrupts specified by the mask
|
||||
*
|
||||
* @param mask bitmask of interrupts that needs to be enabled
|
||||
*/
|
||||
static inline void intr_cntrl_ll_enable_interrupts(uint32_t mask)
|
||||
{
|
||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||
esprv_intc_int_enable(mask);
|
||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief disable interrupts specified by the mask
|
||||
*
|
||||
* @param mask bitmask of interrupts that needs to be disabled
|
||||
*/
|
||||
static inline void intr_cntrl_ll_disable_interrupts(uint32_t mask)
|
||||
{
|
||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||
esprv_intc_int_disable(mask);
|
||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief checks if given interrupt number has a valid handler
|
||||
*
|
||||
* @param intr interrupt number ranged from 0 to 31
|
||||
* @param cpu cpu number ranged betweeen 0 to SOC_CPU_CORES_NUM - 1
|
||||
* @return true for valid handler, false otherwise
|
||||
*/
|
||||
static inline bool intr_cntrl_ll_has_handler(uint8_t intr, uint8_t cpu)
|
||||
{
|
||||
return intr_handler_get(intr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief sets interrupt handler and optional argument of a given interrupt number
|
||||
*
|
||||
* @param intr interrupt number ranged from 0 to 31
|
||||
* @param handler handler invoked when an interrupt occurs
|
||||
* @param arg optional argument to pass to the handler
|
||||
*/
|
||||
static inline void intr_cntrl_ll_set_int_handler(uint8_t intr, interrupt_handler_t handler, void * arg)
|
||||
{
|
||||
intr_handler_set(intr, (void *)handler, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets argument passed to handler of a given interrupt number
|
||||
*
|
||||
* @param intr interrupt number ranged from 0 to 31
|
||||
*
|
||||
* @return argument used by handler of passed interrupt number
|
||||
*/
|
||||
static inline void * intr_cntrl_ll_get_int_handler_arg(uint8_t intr)
|
||||
{
|
||||
return intr_handler_get_arg(intr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables interrupts that are not located in iram
|
||||
*
|
||||
* @param newmask mask of interrupts TO KEEP ENABLED (note: this is probably a bug, see IDF-2308)
|
||||
* @return oldmask previous interrupt mask value
|
||||
*/
|
||||
static inline uint32_t intr_cntrl_ll_disable_int_mask(uint32_t newmask)
|
||||
{
|
||||
// Disable interrupts in order to atomically update the interrupt enable register
|
||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||
|
||||
uint32_t old_int_enable = REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG);
|
||||
REG_WRITE(INTERRUPT_CORE0_CPU_INT_ENABLE_REG, old_int_enable & newmask);
|
||||
|
||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||
return old_int_enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables interrupts that are not located in iram
|
||||
*
|
||||
* @param newmask mask of interrupts needs to be enabled
|
||||
*/
|
||||
static inline void intr_cntrl_ll_enable_int_mask(uint32_t newmask)
|
||||
{
|
||||
unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
|
||||
esprv_intc_int_enable(newmask);
|
||||
RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
518
components/hal/esp32c3/include/hal/ledc_ll.h
Normal file
518
components/hal/esp32c3/include/hal/ledc_ll.h
Normal file
@ -0,0 +1,518 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for LEDC register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "hal/ledc_types.h"
|
||||
#include "soc/ledc_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LEDC_LL_GET_HW() &LEDC
|
||||
|
||||
/**
|
||||
* @brief Set LEDC low speed timer clock
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param slow_clk_sel LEDC low speed timer clock source
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_slow_clk_sel(ledc_dev_t *hw, ledc_slow_clk_sel_t slow_clk_sel)
|
||||
{
|
||||
uint32_t clk_sel_val = 0;
|
||||
if (slow_clk_sel == LEDC_SLOW_CLK_APB) {
|
||||
clk_sel_val = 1;
|
||||
} else if (slow_clk_sel == LEDC_SLOW_CLK_RTC8M) {
|
||||
clk_sel_val = 2;
|
||||
} else if (slow_clk_sel == LEDC_SLOW_CLK_XTAL) {
|
||||
clk_sel_val = 3;
|
||||
}
|
||||
hw->conf.apb_clk_sel = clk_sel_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC low speed timer clock
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param slow_clk_sel LEDC low speed timer clock source
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_slow_clk_sel(ledc_dev_t *hw, ledc_slow_clk_sel_t *slow_clk_sel)
|
||||
{
|
||||
uint32_t clk_sel_val = hw->conf.apb_clk_sel;
|
||||
if (clk_sel_val == 1) {
|
||||
*slow_clk_sel = LEDC_SLOW_CLK_APB;
|
||||
} else if (clk_sel_val == 2) {
|
||||
*slow_clk_sel = LEDC_SLOW_CLK_RTC8M;
|
||||
} else if (clk_sel_val == 3) {
|
||||
*slow_clk_sel = LEDC_SLOW_CLK_XTAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update LEDC low speed timer
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_ls_timer_update(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
{
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.low_speed_update = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset LEDC timer
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_timer_rst(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
{
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.rst = 1;
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pause LEDC timer
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_timer_pause(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
{
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.pause = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume LEDC timer
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_timer_resume(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel)
|
||||
{
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.pause = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC timer clock divider
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
* @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_clock_divider(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider)
|
||||
{
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.clock_divider = clock_divider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC timer clock divider
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
* @param clock_divider Timer clock divide value, the timer clock is divided from the selected clock source
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_clock_divider(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *clock_divider)
|
||||
{
|
||||
*clock_divider = hw->timer_group[speed_mode].timer[timer_sel].conf.clock_divider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC timer clock source
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
* @param clk_src Timer clock source
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_clock_source(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, ledc_clk_src_t clk_src)
|
||||
{
|
||||
if (clk_src == LEDC_REF_TICK) {
|
||||
//REF_TICK can only be used when APB is selected.
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.tick_sel = 1;
|
||||
hw->conf.apb_clk_sel = 1;
|
||||
} else {
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.tick_sel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC timer clock source
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
* @param clk_src Pointer to accept the timer clock source
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_clock_source(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, ledc_clk_src_t *clk_src)
|
||||
{
|
||||
if (hw->timer_group[speed_mode].timer[timer_sel].conf.tick_sel == 1) {
|
||||
*clk_src = LEDC_REF_TICK;
|
||||
} else {
|
||||
*clk_src = LEDC_APB_CLK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC duty resolution
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
* @param duty_resolution Resolution of duty setting in number of bits. The range of duty values is [0, (2**duty_resolution)]
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t duty_resolution)
|
||||
{
|
||||
hw->timer_group[speed_mode].timer[timer_sel].conf.duty_resolution = duty_resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC duty resolution
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
* @param duty_resolution Pointer to accept the resolution of duty setting in number of bits.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_duty_resolution(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t *duty_resolution)
|
||||
{
|
||||
*duty_resolution = hw->timer_group[speed_mode].timer[timer_sel].conf.duty_resolution;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update channel configure when select low speed mode
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_ls_channel_update(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf0.low_speed_update = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC max duty
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param max_duty Pointer to accept the max duty
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_max_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *max_duty)
|
||||
{
|
||||
uint32_t timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel;
|
||||
*max_duty = (1 << (LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC hpoint value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param hpoint_val LEDC hpoint value(max: 0xfffff)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_hpoint(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t hpoint_val)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC hpoint value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param hpoint_val Pointer to accept the LEDC hpoint value(max: 0xfffff)
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_hpoint(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *hpoint_val)
|
||||
{
|
||||
*hpoint_val = hw->channel_group[speed_mode].channel[channel_num].hpoint.hpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC the integer part of duty value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_val LEDC duty value, the range of duty setting is [0, (2**duty_resolution)]
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_int_part(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_val)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].duty.duty = duty_val << 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC duty value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_val Pointer to accept the LEDC duty value
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_duty(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t *duty_val)
|
||||
{
|
||||
*duty_val = (hw->channel_group[speed_mode].channel[channel_num].duty_rd.duty_read >> 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set LEDC duty change direction
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_direction LEDC duty change direction, increase or decrease
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t duty_direction)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc = duty_direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get LEDC duty change direction
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_direction Pointer to accept the LEDC duty change direction, increase or decrease
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_duty_direction(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_duty_direction_t *duty_direction)
|
||||
{
|
||||
*duty_direction = hw->channel_group[speed_mode].channel[channel_num].conf1.duty_inc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the number of increased or decreased times
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_num The number of increased or decreased times
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_num(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_num)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_num = duty_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the duty cycles of increase or decrease
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_cycle The duty cycles
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_cycle(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_cycle)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_cycle = duty_cycle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the step scale of increase or decrease
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_scale The step scale
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_scale(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t duty_scale)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_scale = duty_scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the output enable
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param sig_out_en The output enable status
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_sig_out_en(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool sig_out_en)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf0.sig_out_en = sig_out_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the duty start
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param duty_start The duty start
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_duty_start(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool duty_start)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf1.duty_start = duty_start;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set output idle level
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param idle_level The output idle level
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_idle_level(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, uint32_t idle_level)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf0.idle_lv = idle_level & 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set fade end interrupt enable
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param fade_end_intr_en The fade end interrupt enable status
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_set_fade_end_intr(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, bool fade_end_intr_en)
|
||||
{
|
||||
uint32_t value = hw->int_ena.val;
|
||||
uint32_t int_en_base = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
hw->int_ena.val = fade_end_intr_en ? (value | BIT(int_en_base + channel_num)) : (value & (~(BIT(int_en_base + channel_num))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get fade end interrupt status
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param intr_status The fade end interrupt status
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_fade_end_intr_status(ledc_dev_t *hw, ledc_mode_t speed_mode, uint32_t *intr_status)
|
||||
{
|
||||
uint32_t value = hw->int_st.val;
|
||||
uint32_t int_en_base = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
*intr_status = (value >> int_en_base) & 0xff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear fade end interrupt status
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_clear_fade_end_intr_status(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num)
|
||||
{
|
||||
uint32_t int_en_base = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
hw->int_clr.val = BIT(int_en_base + channel_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set timer index of the specified channel
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param timer_sel LEDC timer index (0-3), select from ledc_timer_t
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_bind_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_timer_t timer_sel)
|
||||
{
|
||||
hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel = timer_sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get timer index of the specified channel
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers
|
||||
* @param speed_mode LEDC speed_mode, high-speed mode or low-speed mode
|
||||
* @param channel_num LEDC channel index (0-7), select from ledc_channel_t
|
||||
* @param timer_sel Pointer to accept the LEDC timer index
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void ledc_ll_get_channel_timer(ledc_dev_t *hw, ledc_mode_t speed_mode, ledc_channel_t channel_num, ledc_timer_t *timer_sel)
|
||||
{
|
||||
*timer_sel = hw->channel_group[speed_mode].channel[channel_num].conf0.timer_sel;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
53
components/hal/esp32c3/include/hal/mpu_ll.h
Normal file
53
components/hal/esp32c3/include/hal/mpu_ll.h
Normal file
@ -0,0 +1,53 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "soc/mpu_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* This LL is currently unused for ESP32-C3 - cleanup is TODO ESP32-C3 IDF-2375 */
|
||||
|
||||
static inline uint32_t mpu_ll_id_to_addr(int id)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline void mpu_ll_set_region_rw(uint32_t addr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline void mpu_ll_set_region_rwx(uint32_t addr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline void mpu_ll_set_region_x(uint32_t addr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
static inline void mpu_ll_set_region_illegal(uint32_t addr)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
254
components/hal/esp32c3/include/hal/mwdt_ll.h
Normal file
254
components/hal/esp32c3/include/hal/mwdt_ll.h
Normal file
@ -0,0 +1,254 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for Timer Group register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/timer_periph.h"
|
||||
#include "hal/wdt_types.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
//Type check wdt_stage_action_t
|
||||
_Static_assert(WDT_STAGE_ACTION_OFF == TIMG_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_INT == TIMG_WDT_STG_SEL_INT, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_RESET_CPU == TIMG_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_RESET_SYSTEM == TIMG_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
//Type check wdt_reset_sig_length_t
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_100ns == TIMG_WDT_RESET_LENGTH_100_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_200ns == TIMG_WDT_RESET_LENGTH_200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_300ns == TIMG_WDT_RESET_LENGTH_300_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_400ns == TIMG_WDT_RESET_LENGTH_400_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_500ns == TIMG_WDT_RESET_LENGTH_500_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_800ns == TIMG_WDT_RESET_LENGTH_800_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_1_6us == TIMG_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_3_2us == TIMG_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
|
||||
/**
|
||||
* @brief Enable the MWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_enable(timg_dev_t *hw)
|
||||
{
|
||||
hw->wdt_config0.en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the MWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @note This function does not disable the flashboot mode. Therefore, given that
|
||||
* the MWDT is disabled using this function, a timeout can still occur
|
||||
* if the flashboot mode is simultaneously enabled.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_disable(timg_dev_t *hw)
|
||||
{
|
||||
hw->wdt_config0.en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the MWDT is enabled
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @return True if the MWDT is enabled, false otherwise
|
||||
*/
|
||||
FORCE_INLINE_ATTR bool mwdt_ll_check_if_enabled(timg_dev_t *hw)
|
||||
{
|
||||
return (hw->wdt_config0.en) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure a particular stage of the MWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param stage Which stage to configure
|
||||
* @param timeout Number of timer ticks for the stage to timeout
|
||||
* @param behavior What action to take when the stage times out
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_config_stage(timg_dev_t *hw, wdt_stage_t stage, uint32_t timeout, wdt_stage_action_t behavior)
|
||||
{
|
||||
switch (stage) {
|
||||
case WDT_STAGE0:
|
||||
hw->wdt_config0.stg0 = behavior;
|
||||
hw->wdt_config2 = timeout;
|
||||
break;
|
||||
case WDT_STAGE1:
|
||||
hw->wdt_config0.stg1 = behavior;
|
||||
hw->wdt_config3 = timeout;
|
||||
break;
|
||||
case WDT_STAGE2:
|
||||
hw->wdt_config0.stg2 = behavior;
|
||||
hw->wdt_config4 = timeout;
|
||||
break;
|
||||
case WDT_STAGE3:
|
||||
hw->wdt_config0.stg3 = behavior;
|
||||
hw->wdt_config5 = timeout;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//Config registers are updated asynchronously
|
||||
hw->wdt_config0.conf_update_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a particular stage of the MWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param stage Which stage to disable
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_disable_stage(timg_dev_t *hw, uint32_t stage)
|
||||
{
|
||||
switch (stage) {
|
||||
case WDT_STAGE0:
|
||||
hw->wdt_config0.stg0 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
case WDT_STAGE1:
|
||||
hw->wdt_config0.stg1 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
case WDT_STAGE2:
|
||||
hw->wdt_config0.stg2 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
case WDT_STAGE3:
|
||||
hw->wdt_config0.stg3 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//Config registers are updated asynchronously
|
||||
hw->wdt_config0.conf_update_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the length of the CPU reset action
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param length Length of CPU reset signal
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_set_cpu_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length)
|
||||
{
|
||||
hw->wdt_config0.cpu_reset_length = length;
|
||||
//Config registers are updated asynchronously
|
||||
hw->wdt_config0.conf_update_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the length of the system reset action
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param length Length of system reset signal
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_set_sys_reset_length(timg_dev_t *hw, wdt_reset_sig_length_t length)
|
||||
{
|
||||
hw->wdt_config0.sys_reset_length = length;
|
||||
//Config registers are updated asynchronously
|
||||
hw->wdt_config0.conf_update_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable the MWDT flashboot mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable True to enable WDT flashboot mode, false to disable WDT flashboot mode.
|
||||
*
|
||||
* @note Flashboot mode is independent and can trigger a WDT timeout event if the
|
||||
* WDT's enable bit is set to 0. Flashboot mode for TG0 is automatically enabled
|
||||
* on flashboot, and should be disabled by software when flashbooting completes.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_set_flashboot_en(timg_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->wdt_config0.flashboot_mod_en = (enable) ? 1 : 0;
|
||||
//Config registers are updated asynchronously
|
||||
hw->wdt_config0.conf_update_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the clock prescaler of the MWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param prescaler Prescaler value between 1 to 65535
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_set_prescaler(timg_dev_t *hw, uint32_t prescaler)
|
||||
{
|
||||
hw->wdt_config1.clk_prescale = prescaler;
|
||||
//Config registers are updated asynchronously
|
||||
hw->wdt_config0.conf_update_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Feed the MWDT
|
||||
*
|
||||
* Resets the current timer count and current stage.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_feed(timg_dev_t *hw)
|
||||
{
|
||||
hw->wdt_feed = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable write protection of the MWDT registers
|
||||
*
|
||||
* Locking the MWDT will prevent any of the MWDT's registers from being modified
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_write_protect_enable(timg_dev_t *hw)
|
||||
{
|
||||
hw->wdt_wprotect = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable write protection of the MWDT registers
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_write_protect_disable(timg_dev_t *hw)
|
||||
{
|
||||
hw->wdt_wprotect = TIMG_WDT_WKEY_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the MWDT interrupt status.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_clear_intr_status(timg_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.wdt = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the interrupt enable bit for the MWDT interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param enable Whether to enable the MWDT interrupt
|
||||
*/
|
||||
FORCE_INLINE_ATTR void mwdt_ll_set_intr_enable(timg_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->int_ena.wdt = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
500
components/hal/esp32c3/include/hal/rmt_ll.h
Normal file
500
components/hal/esp32c3/include/hal/rmt_ll.h
Normal file
@ -0,0 +1,500 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/rmt_struct.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#define RMT_LL_HW_BASE (&RMT)
|
||||
#define RMT_LL_MEM_BASE (&RMTMEM)
|
||||
|
||||
// Note: TX and RX channel number are all index from zero in the LL driver
|
||||
// i.e. tx_channel belongs to [0,2], and rx_channel belongs to [0,2]
|
||||
|
||||
static inline void rmt_ll_enable_drive_clock(rmt_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->sys_conf.clk_en = enable; // register clock gating
|
||||
dev->sys_conf.mem_clk_force_on = enable; // memory clock gating
|
||||
}
|
||||
|
||||
static inline void rmt_ll_power_down_mem(rmt_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->sys_conf.mem_force_pu = !enable;
|
||||
dev->sys_conf.mem_force_pd = enable;
|
||||
}
|
||||
|
||||
static inline bool rmt_ll_is_mem_power_down(rmt_dev_t *dev)
|
||||
{
|
||||
// the RTC domain can also power down RMT memory
|
||||
// so it's probably not enough to detect whether it's powered down or not
|
||||
// mem_force_pd has higher priority than mem_force_pu
|
||||
return (dev->sys_conf.mem_force_pd) || !(dev->sys_conf.mem_force_pu);
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_mem_access(rmt_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->sys_conf.fifo_mask = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_set_counter_clock_src(rmt_dev_t *dev, uint32_t channel, uint8_t src, uint8_t div_num, uint8_t div_a, uint8_t div_b)
|
||||
{
|
||||
// Formula: rmt_sclk = module_clock_src / (1 + div_num + div_a / div_b)
|
||||
dev->sys_conf.sclk_active = 0;
|
||||
dev->sys_conf.sclk_sel = src;
|
||||
dev->sys_conf.sclk_div_num = div_num;
|
||||
dev->sys_conf.sclk_div_a = div_a;
|
||||
dev->sys_conf.sclk_div_b = div_b;
|
||||
dev->sys_conf.sclk_active = 1;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_counter_clock_src(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->sys_conf.sclk_sel;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->ref_cnt_rst.val |= (1 << channel);
|
||||
dev->ref_cnt_rst.val &= ~(1 << channel);
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_reset_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->ref_cnt_rst.val |= (1 << (channel + 2));
|
||||
dev->ref_cnt_rst.val &= ~(1 << (channel + 2));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->tx_conf[channel].mem_rd_rst = 1;
|
||||
dev->tx_conf[channel].mem_rd_rst = 0;
|
||||
dev->tx_conf[channel].mem_rst = 1;
|
||||
dev->tx_conf[channel].mem_rst = 0;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_reset_pointer(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.mem_wr_rst = 1;
|
||||
dev->rx_conf[channel].conf1.mem_wr_rst = 0;
|
||||
dev->rx_conf[channel].conf1.mem_rst = 1;
|
||||
dev->rx_conf[channel].conf1.mem_rst = 0;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_start(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->tx_conf[channel].conf_update = 1;
|
||||
dev->tx_conf[channel].tx_start = 1;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_stop(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->tx_conf[channel].tx_stop = 1;
|
||||
dev->tx_conf[channel].conf_update = 1;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_enable(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.rx_en = enable;
|
||||
dev->rx_conf[channel].conf1.conf_update = 1;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
|
||||
{
|
||||
dev->tx_conf[channel].mem_size = block_num;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_mem_blocks(rmt_dev_t *dev, uint32_t channel, uint8_t block_num)
|
||||
{
|
||||
dev->rx_conf[channel].conf0.mem_size = block_num;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_tx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_conf[channel].mem_size;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_rx_get_mem_blocks(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->rx_conf[channel].conf0.mem_size;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
|
||||
{
|
||||
dev->tx_conf[channel].div_cnt = div;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_counter_clock_div(rmt_dev_t *dev, uint32_t channel, uint32_t div)
|
||||
{
|
||||
dev->rx_conf[channel].conf0.div_cnt = div;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_tx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_conf[channel].div_cnt;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_rx_get_counter_clock_div(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->rx_conf[channel].conf0.div_cnt;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_conf[channel].mem_tx_wrap_en = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_idle_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
|
||||
{
|
||||
dev->rx_conf[channel].conf0.idle_thres = thres;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_rx_get_idle_thres(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->rx_conf[channel].conf0.idle_thres;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_mem_owner(rmt_dev_t *dev, uint32_t channel, uint8_t owner)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.mem_owner = owner;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_rx_get_mem_owner(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->rx_conf[channel].conf1.mem_owner;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_loop(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_conf[channel].tx_conti_mode = enable;
|
||||
}
|
||||
|
||||
static inline bool rmt_ll_is_tx_loop_enabled(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_conf[channel].tx_conti_mode;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_loop_count(rmt_dev_t *dev, uint32_t channel, uint32_t count)
|
||||
{
|
||||
dev->tx_lim[channel].tx_loop_num = count;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_reset_loop(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->tx_lim[channel].loop_count_reset = 1;
|
||||
dev->tx_lim[channel].loop_count_reset = 0;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_loop_count(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_lim[channel].tx_loop_cnt_en = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_sync(rmt_dev_t *dev, bool enable)
|
||||
{
|
||||
dev->tx_sim.en = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_add_channel_to_group(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->tx_sim.val |= 1 << channel;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_tx_remove_channel_from_group(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->tx_sim.val &= ~(1 << channel);
|
||||
return dev->tx_sim.val & 0x03;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_enable_filter(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.rx_filter_en = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_filter_thres(rmt_dev_t *dev, uint32_t channel, uint32_t thres)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.rx_filter_thres = thres;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_idle(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_conf[channel].idle_out_en = enable;
|
||||
}
|
||||
|
||||
static inline bool rmt_ll_is_tx_idle_enabled(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_conf[channel].idle_out_en;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_idle_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
|
||||
{
|
||||
dev->tx_conf[channel].idle_out_lv = level;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_tx_get_idle_level(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_conf[channel].idle_out_lv;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_rx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->rx_status[channel].val;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_tx_get_channel_status(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->tx_status[channel].val;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
|
||||
{
|
||||
dev->tx_lim[channel].limit = limit;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_limit(rmt_dev_t *dev, uint32_t channel, uint32_t limit)
|
||||
{
|
||||
dev->rx_lim[channel].rx_lim = limit;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_rx_get_limit(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
return dev->rx_lim[channel].rx_lim;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_tx_end_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << channel);
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << channel);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 4));
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << (channel + 4));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_rx_end_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 2));
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << (channel + 2));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 6));
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << (channel + 6));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 8));
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << (channel + 8));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 12));
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << (channel + 12));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_enable_rx_thres_interrupt(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
dev->int_ena.val |= (1 << (channel + 10));
|
||||
} else {
|
||||
dev->int_ena.val &= ~(1 << (channel + 10));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_end_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_rx_end_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 2));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 4));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_rx_err_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 6));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_thres_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 8));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_tx_loop_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 12));
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clear_rx_thres_interrupt(rmt_dev_t *dev, uint32_t channel)
|
||||
{
|
||||
dev->int_clr.val = (1 << (channel + 10));
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_end_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return dev->int_st.val & 0x03;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_rx_end_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 2) & 0x03;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_err_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 4) & 0x03;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_rx_err_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 6) & 0x03;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_thres_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 8) & 0x03;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_rx_thres_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 10) & 0x03;
|
||||
}
|
||||
|
||||
static inline uint32_t rmt_ll_get_tx_loop_interrupt_status(rmt_dev_t *dev)
|
||||
{
|
||||
return (dev->int_st.val >> 12) & 0x03;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
|
||||
{
|
||||
// In case the compiler optimise a 32bit instruction (e.g. s32i) into two 16bit instruction (e.g. s16i, which is not allowed to access a register)
|
||||
// We take care of the "read-modify-write" procedure by ourselves.
|
||||
typeof(dev->tx_carrier[0]) reg;
|
||||
reg.high = high_ticks;
|
||||
reg.low = low_ticks;
|
||||
dev->tx_carrier[channel].val = reg.val;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t high_ticks, uint32_t low_ticks)
|
||||
{
|
||||
typeof(dev->rx_carrier[0]) reg;
|
||||
reg.high_thres = high_ticks;
|
||||
reg.low_thres = low_ticks;
|
||||
dev->rx_carrier[channel].val = reg.val;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
|
||||
{
|
||||
*high_ticks = dev->tx_carrier[channel].high;
|
||||
*low_ticks = dev->tx_carrier[channel].low;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_get_carrier_high_low_ticks(rmt_dev_t *dev, uint32_t channel, uint32_t *high_ticks, uint32_t *low_ticks)
|
||||
{
|
||||
*high_ticks = dev->rx_carrier[channel].high_thres;
|
||||
*low_ticks = dev->rx_carrier[channel].low_thres;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_enable_carrier_modulation(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_conf[channel].carrier_en = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_enable_carrier_demodulation(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->rx_conf[channel].conf0.carrier_en = enable;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_tx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
|
||||
{
|
||||
dev->tx_conf[channel].carrier_out_lv = level;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_set_carrier_level(rmt_dev_t *dev, uint32_t channel, uint8_t level)
|
||||
{
|
||||
dev->rx_conf[channel].conf0.carrier_out_lv = level;
|
||||
}
|
||||
|
||||
// set true, enable carrier in all RMT state (idle, reading, sending)
|
||||
// set false, enable carrier only in sending state (i.e. there're effective data in RAM to be sent)
|
||||
static inline void rmt_ll_tx_set_carrier_always_on(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->tx_conf[channel].carrier_eff_en = !enable;
|
||||
}
|
||||
|
||||
//Writes items to the specified TX channel memory with the given offset and writen length.
|
||||
//the caller should ensure that (length + off) <= (memory block * SOC_RMT_CHANNEL_MEM_WORDS)
|
||||
static inline void rmt_ll_write_memory(rmt_mem_t *mem, uint32_t channel, const rmt_item32_t *data, uint32_t length, uint32_t off)
|
||||
{
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
mem->chan[channel].data32[i + off].val = data[i].val;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void rmt_ll_rx_enable_pingpong(rmt_dev_t *dev, uint32_t channel, bool enable)
|
||||
{
|
||||
dev->rx_conf[channel].conf1.mem_rx_wrap_en = enable;
|
||||
}
|
||||
|
||||
/************************************************************************************************
|
||||
* Following Low Level APIs only used for backward compatible, will be deprecated in the IDF v5.0
|
||||
***********************************************************************************************/
|
||||
|
||||
static inline void rmt_ll_set_intr_enable_mask(uint32_t mask)
|
||||
{
|
||||
RMT.int_ena.val |= mask;
|
||||
}
|
||||
|
||||
static inline void rmt_ll_clr_intr_enable_mask(uint32_t mask)
|
||||
{
|
||||
RMT.int_ena.val &= (~mask);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
48
components/hal/esp32c3/include/hal/rtc_cntl_ll.h
Normal file
48
components/hal/esp32c3/include/hal/rtc_cntl_ll.h
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void rtc_cntl_ll_set_wakeup_timer(uint64_t t)
|
||||
{
|
||||
abort(); // ESP32-C3 TODO IDF-2106
|
||||
}
|
||||
|
||||
static inline uint32_t rtc_cntl_ll_ext1_get_wakeup_pins(void)
|
||||
{
|
||||
abort(); // ESP32-C3 TODO IDF-2106
|
||||
}
|
||||
|
||||
static inline void rtc_cntl_ll_ext1_set_wakeup_pins(uint32_t mask, int mode)
|
||||
{
|
||||
abort(); // ESP32-C3 TODO IDF-2106
|
||||
}
|
||||
|
||||
static inline void rtc_cntl_ll_ext1_clear_wakeup_pins(void)
|
||||
{
|
||||
abort(); // ESP32-C3 TODO IDF-2106
|
||||
REG_SET_BIT(RTC_CNTL_GPIO_WAKEUP_REG, RTC_CNTL_GPIO_WAKEUP_STATUS_CLR);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
311
components/hal/esp32c3/include/hal/rwdt_ll.h
Normal file
311
components/hal/esp32c3/include/hal/rwdt_ll.h
Normal file
@ -0,0 +1,311 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for Timer Group register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/wdt_types.h"
|
||||
#include "soc/rtc_cntl_periph.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
//Type check wdt_stage_action_t
|
||||
_Static_assert(WDT_STAGE_ACTION_OFF == RTC_WDT_STG_SEL_OFF, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_INT == RTC_WDT_STG_SEL_INT, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_RESET_CPU == RTC_WDT_STG_SEL_RESET_CPU, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_RESET_SYSTEM == RTC_WDT_STG_SEL_RESET_SYSTEM, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
_Static_assert(WDT_STAGE_ACTION_RESET_RTC == RTC_WDT_STG_SEL_RESET_RTC, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_stage_action_t");
|
||||
//Type check wdt_reset_sig_length_t
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_100ns == RTC_WDT_RESET_LENGTH_100_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_200ns == RTC_WDT_RESET_LENGTH_200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_300ns == RTC_WDT_RESET_LENGTH_300_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_400ns == RTC_WDT_RESET_LENGTH_400_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_500ns == RTC_WDT_RESET_LENGTH_500_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_800ns == RTC_WDT_RESET_LENGTH_800_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_1_6us == RTC_WDT_RESET_LENGTH_1600_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
_Static_assert(WDT_RESET_SIG_LENGTH_3_2us == RTC_WDT_RESET_LENGTH_3200_NS, "Add mapping to LL watchdog timeout behavior, since it's no longer naturally compatible with wdt_reset_sig_length_t");
|
||||
|
||||
/**
|
||||
* @brief Enable the RWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_enable(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->wdt_config0.en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the RWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @note This function does not disable the flashboot mode. Therefore, given that
|
||||
* the MWDT is disabled using this function, a timeout can still occur
|
||||
* if the flashboot mode is simultaneously enabled.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_disable(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->wdt_config0.en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the RWDT is enabled
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @return True if RTC WDT is enabled
|
||||
*/
|
||||
FORCE_INLINE_ATTR bool rwdt_ll_check_if_enabled(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
return (hw->wdt_config0.en) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure a particular stage of the RWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param stage Which stage to configure
|
||||
* @param timeout Number of timer ticks for the stage to timeout (see note).
|
||||
* @param behavior What action to take when the stage times out
|
||||
*
|
||||
* @note The value of of RWDT stage 0 timeout register is special, in
|
||||
* that an implicit multiplier is applied to that value to produce
|
||||
* and effective timeout tick value. The multiplier is dependent
|
||||
* on an EFuse value. Therefore, when configuring stage 0, the valid
|
||||
* values for the timeout argument are:
|
||||
* - If Efuse value is 0, any even number between [2,2*UINT32_MAX]
|
||||
* - If Efuse value is 1, any multiple of 4 between [4,4*UINT32_MAX]
|
||||
* - If Efuse value is 2, any multiple of 8 between [8,8*UINT32_MAX]
|
||||
* - If Efuse value is 3, any multiple of 16 between [16,16*UINT32_MAX]
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_config_stage(rtc_cntl_dev_t *hw, wdt_stage_t stage, uint32_t timeout_ticks, wdt_stage_action_t behavior)
|
||||
{
|
||||
switch (stage) {
|
||||
case WDT_STAGE0:
|
||||
hw->wdt_config0.stg0 = behavior;
|
||||
//Account of implicty multiplier applied to stage 0 timeout tick config value
|
||||
hw->wdt_config1 = timeout_ticks >> (1 + REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_WDT_DELAY_SEL));
|
||||
break;
|
||||
case WDT_STAGE1:
|
||||
hw->wdt_config0.stg1 = behavior;
|
||||
hw->wdt_config2 = timeout_ticks;
|
||||
break;
|
||||
case WDT_STAGE2:
|
||||
hw->wdt_config0.stg2 = behavior;
|
||||
hw->wdt_config3 = timeout_ticks;
|
||||
break;
|
||||
case WDT_STAGE3:
|
||||
hw->wdt_config0.stg3 = behavior;
|
||||
hw->wdt_config4 = timeout_ticks;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a particular stage of the RWDT
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param stage Which stage to disable
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_disable_stage(rtc_cntl_dev_t *hw, wdt_stage_t stage)
|
||||
{
|
||||
switch (stage) {
|
||||
case WDT_STAGE0:
|
||||
hw->wdt_config0.stg0 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
case WDT_STAGE1:
|
||||
hw->wdt_config0.stg1 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
case WDT_STAGE2:
|
||||
hw->wdt_config0.stg2 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
case WDT_STAGE3:
|
||||
hw->wdt_config0.stg3 = WDT_STAGE_ACTION_OFF;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the length of the CPU reset action
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param length Length of CPU reset signal
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_cpu_reset_length(rtc_cntl_dev_t *hw, wdt_reset_sig_length_t length)
|
||||
{
|
||||
hw->wdt_config0.cpu_reset_length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the length of the system reset action
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param length Length of system reset signal
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_sys_reset_length(rtc_cntl_dev_t *hw, wdt_reset_sig_length_t length)
|
||||
{
|
||||
hw->wdt_config0.sys_reset_length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable the RWDT flashboot mode.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True to enable RWDT flashboot mode, false to disable RWDT flashboot mode.
|
||||
*
|
||||
* @note Flashboot mode is independent and can trigger a WDT timeout event if the
|
||||
* WDT's enable bit is set to 0. Flashboot mode for RWDT is automatically enabled
|
||||
* on flashboot, and should be disabled by software when flashbooting completes.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_flashboot_en(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->wdt_config0.flashboot_mod_en = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable the CPU0 to be reset on WDT_STAGE_ACTION_RESET_CPU
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True to enable CPU0 to be reset, false to disable.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_procpu_reset_en(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->wdt_config0.procpu_reset_en = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable the CPU1 to be reset on WDT_STAGE_ACTION_RESET_CPU
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True to enable CPU1 to be reset, false to disable.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_appcpu_reset_en(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->wdt_config0.appcpu_reset_en = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable the RWDT pause during sleep functionality
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True to enable, false to disable.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_pause_in_sleep_en(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->wdt_config0.pause_in_slp = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable chip reset on RWDT timeout.
|
||||
*
|
||||
* A chip reset also resets the analog portion of the chip. It will appear as a
|
||||
* POWERON reset rather than an RTC reset.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True to enable, false to disable.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_en(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->wdt_config0.chip_reset_en = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set width of chip reset signal
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param width Width of chip reset signal in terms of number of RTC_SLOW_CLK cycles
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_chip_reset_width(rtc_cntl_dev_t *hw, uint32_t width)
|
||||
{
|
||||
hw->wdt_config0.chip_reset_width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Feed the RWDT
|
||||
*
|
||||
* Resets the current timer count and current stage.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_feed(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->wdt_feed.feed = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable write protection of the RWDT registers
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_write_protect_enable(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->wdt_wprotect = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable write protection of the RWDT registers
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_write_protect_disable(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->wdt_wprotect = RTC_CNTL_WDT_WKEY_VALUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the RWDT interrupt.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @param enable True to enable RWDT interrupt, false to disable.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_set_intr_enable(rtc_cntl_dev_t *hw, bool enable)
|
||||
{
|
||||
hw->int_ena.rtc_wdt = (enable) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the RWDT interrupt has been triggered
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
* @return True if the RWDT interrupt was triggered
|
||||
*/
|
||||
FORCE_INLINE_ATTR bool rwdt_ll_check_intr_status(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
return (hw->int_st.rtc_wdt) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the RWDT interrupt status.
|
||||
*
|
||||
* @param hw Start address of the peripheral registers.
|
||||
*/
|
||||
FORCE_INLINE_ATTR void rwdt_ll_clear_intr_status(rtc_cntl_dev_t *hw)
|
||||
{
|
||||
hw->int_clr.rtc_wdt = 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
154
components/hal/esp32c3/include/hal/sha_ll.h
Normal file
154
components/hal/esp32c3/include/hal/sha_ll.h
Normal file
@ -0,0 +1,154 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include "soc/dport_access.h"
|
||||
#include "hal/sha_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @brief Start a new SHA block conversions (no initial hash in HW)
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
*/
|
||||
static inline void sha_ll_start_block(esp_sha_type sha_type)
|
||||
{
|
||||
REG_WRITE(SHA_MODE_REG, sha_type);
|
||||
REG_WRITE(SHA_START_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Continue a SHA block conversion (initial hash in HW)
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
*/
|
||||
static inline void sha_ll_continue_block(esp_sha_type sha_type)
|
||||
{
|
||||
REG_WRITE(SHA_MODE_REG, sha_type);
|
||||
REG_WRITE(SHA_CONTINUE_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start a new SHA message conversion using DMA (no initial hash in HW)
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
*/
|
||||
static inline void sha_ll_start_dma(esp_sha_type sha_type)
|
||||
{
|
||||
REG_WRITE(SHA_MODE_REG, sha_type);
|
||||
REG_WRITE(SHA_DMA_START_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Continue a SHA message conversion using DMA (initial hash in HW)
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
*/
|
||||
static inline void sha_ll_continue_dma(esp_sha_type sha_type)
|
||||
{
|
||||
REG_WRITE(SHA_MODE_REG, sha_type);
|
||||
REG_WRITE(SHA_DMA_CONTINUE_REG, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load the current hash digest to digest register
|
||||
*
|
||||
* @note Happens automatically on ESP32S3
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
*/
|
||||
static inline void sha_ll_load(esp_sha_type sha_type)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the number of message blocks to be hashed
|
||||
*
|
||||
* @note DMA operation only
|
||||
*
|
||||
* @param num_blocks Number of message blocks to process
|
||||
*/
|
||||
static inline void sha_ll_set_block_num(size_t num_blocks)
|
||||
{
|
||||
REG_WRITE(SHA_BLOCK_NUM_REG, num_blocks);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the SHA engine is currently busy hashing a block
|
||||
*
|
||||
* @return true SHA engine busy
|
||||
* @return false SHA engine idle
|
||||
*/
|
||||
static inline bool sha_ll_busy(void)
|
||||
{
|
||||
return REG_READ(SHA_BUSY_REG);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a text (message) block to the SHA engine
|
||||
*
|
||||
* @param input_text Input buffer to be written to the SHA engine
|
||||
* @param block_word_len Number of words in block
|
||||
*/
|
||||
static inline void sha_ll_fill_text_block(const void *input_text, size_t block_word_len)
|
||||
{
|
||||
uint32_t *data_words = (uint32_t *)input_text;
|
||||
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
|
||||
|
||||
for (int i = 0; i < block_word_len; i++) {
|
||||
REG_WRITE(®_addr_buf[i], data_words[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the message digest from the SHA engine
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
* @param digest_state Buffer that message digest will be written to
|
||||
* @param digest_word_len Length of the message digest
|
||||
*/
|
||||
static inline void sha_ll_read_digest(esp_sha_type sha_type, void *digest_state, size_t digest_word_len)
|
||||
{
|
||||
uint32_t *digest_state_words = (uint32_t *)digest_state;
|
||||
|
||||
esp_dport_access_read_buffer(digest_state_words, SHA_H_BASE, digest_word_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the message digest to the SHA engine
|
||||
*
|
||||
* @param sha_type The SHA algorithm type
|
||||
* @param digest_state Message digest to be written to SHA engine
|
||||
* @param digest_word_len Length of the message digest
|
||||
*/
|
||||
static inline void sha_ll_write_digest(esp_sha_type sha_type, void *digest_state, size_t digest_word_len)
|
||||
{
|
||||
uint32_t *digest_state_words = (uint32_t *)digest_state;
|
||||
uint32_t *reg_addr_buf = (uint32_t *)(SHA_H_BASE);
|
||||
|
||||
for (int i = 0; i < digest_word_len; i++) {
|
||||
REG_WRITE(®_addr_buf[i], digest_state_words[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
73
components/hal/esp32c3/include/hal/sigmadelta_ll.h
Normal file
73
components/hal/esp32c3/include/hal/sigmadelta_ll.h
Normal file
@ -0,0 +1,73 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The LL layer for ESP32 SIGMADELTA register operations
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "soc/sigmadelta_periph.h"
|
||||
#include "hal/sigmadelta_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Get SIGMADELTA hardware instance with giving sigmadelta num
|
||||
#define SIGMADELTA_LL_GET_HW(num) (((num) == 0) ? (&SIGMADELTA) : NULL)
|
||||
|
||||
/**
|
||||
* @brief Set Sigma-delta enable
|
||||
*
|
||||
* @param hw Peripheral SIGMADELTA hardware instance address.
|
||||
* @param en Sigma-delta enable value
|
||||
*/
|
||||
static inline void sigmadelta_ll_set_en(gpio_sd_dev_t *hw, bool en)
|
||||
{
|
||||
hw->misc.function_clk_en = en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Sigma-delta channel duty.
|
||||
*
|
||||
* @param hw Peripheral SIGMADELTA hardware instance address.
|
||||
* @param channel Sigma-delta channel number
|
||||
* @param duty Sigma-delta duty of one channel, the value ranges from -128 to 127, recommended range is -90 ~ 90.
|
||||
* The waveform is more like a random one in this range.
|
||||
*/
|
||||
static inline void sigmadelta_ll_set_duty(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, int8_t duty)
|
||||
{
|
||||
hw->channel[channel].duty = duty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Sigma-delta channel's clock pre-scale value.
|
||||
*
|
||||
* @param hw Peripheral SIGMADELTA hardware instance address.
|
||||
* @param channel Sigma-delta channel number
|
||||
* @param val The divider of source clock, ranges from 0 to 255
|
||||
*/
|
||||
static inline void sigmadelta_ll_set_prescale(gpio_sd_dev_t *hw, sigmadelta_channel_t channel, uint8_t prescale)
|
||||
{
|
||||
hw->channel[channel].prescale = prescale;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
52
components/hal/esp32c3/include/hal/soc_ll.h
Normal file
52
components/hal/esp32c3/include/hal/soc_ll.h
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void soc_ll_stall_core(int core)
|
||||
{
|
||||
const int rtc_cntl_c1_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C1_M};
|
||||
const int rtc_cntl_c1_s[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C1_S};
|
||||
const int rtc_cntl_c0_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C0_M};
|
||||
const int rtc_cntl_c0_s[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C0_S};
|
||||
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m[core]);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21 << rtc_cntl_c1_s[core]);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m[core]);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2 << rtc_cntl_c0_s[core]);
|
||||
}
|
||||
|
||||
static inline void soc_ll_unstall_core(int core)
|
||||
{
|
||||
const int rtc_cntl_c1_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C1_M};
|
||||
const int rtc_cntl_c0_m[SOC_CPU_CORES_NUM] = {RTC_CNTL_SW_STALL_PROCPU_C0_M};
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, rtc_cntl_c1_m[core]);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, rtc_cntl_c0_m[core]);
|
||||
}
|
||||
|
||||
static inline void soc_ll_reset_core(int core)
|
||||
{
|
||||
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
109
components/hal/esp32c3/include/hal/spi_flash_ll.h
Normal file
109
components/hal/esp32c3/include/hal/spi_flash_ll.h
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The ll is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The Lowlevel layer for SPI Flash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gpspi_flash_ll.h"
|
||||
#include "spimem_flash_ll.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// For esp32s2, spimem is equivalent to traditional spi peripherals found
|
||||
// in esp32. Let the spi flash clock reg definitions reflect this.
|
||||
#define SPI_FLASH_LL_CLKREG_VAL_5MHZ {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_5MHZ}
|
||||
#define SPI_FLASH_LL_CLKREG_VAL_10MHZ {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_10MHZ}
|
||||
#define SPI_FLASH_LL_CLKREG_VAL_20MHZ {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_20MHZ}
|
||||
#define SPI_FLASH_LL_CLKREG_VAL_26MHZ {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_26MHZ}
|
||||
#define SPI_FLASH_LL_CLKREG_VAL_40MHZ {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_40MHZ}
|
||||
#define SPI_FLASH_LL_CLKREG_VAL_80MHZ {.spimem=SPIMEM_FLASH_LL_CLKREG_VAL_80MHZ}
|
||||
|
||||
#define spi_flash_ll_get_hw(host_id) (((host_id)<=SPI1_HOST ? (spi_dev_t*) spimem_flash_ll_get_hw(host_id) \
|
||||
: gpspi_flash_ll_get_hw(host_id)))
|
||||
|
||||
#define spi_flash_ll_hw_get_id(dev) ({int dev_id = spimem_flash_ll_hw_get_id(dev); \
|
||||
if (dev_id < 0) {\
|
||||
dev_id = gpspi_flash_ll_hw_get_id(dev);\
|
||||
}\
|
||||
dev_id; \
|
||||
})
|
||||
|
||||
|
||||
typedef union {
|
||||
gpspi_flash_ll_clock_reg_t gpspi;
|
||||
spimem_flash_ll_clock_reg_t spimem;
|
||||
} spi_flash_ll_clock_reg_t;
|
||||
|
||||
#ifdef GPSPI_BUILD
|
||||
#define spi_flash_ll_reset(dev) gpspi_flash_ll_reset((spi_dev_t*)dev)
|
||||
#define spi_flash_ll_cmd_is_done(dev) gpspi_flash_ll_cmd_is_done((spi_dev_t*)dev)
|
||||
#define spi_flash_ll_get_buffer_data(dev, buffer, read_len) gpspi_flash_ll_get_buffer_data((spi_dev_t*)dev, buffer, read_len)
|
||||
#define spi_flash_ll_set_buffer_data(dev, buffer, len) gpspi_flash_ll_set_buffer_data((spi_dev_t*)dev, buffer, len)
|
||||
#define spi_flash_ll_user_start(dev) gpspi_flash_ll_user_start((spi_dev_t*)dev)
|
||||
#define spi_flash_ll_host_idle(dev) gpspi_flash_ll_host_idle((spi_dev_t*)dev)
|
||||
#define spi_flash_ll_read_phase(dev) gpspi_flash_ll_read_phase((spi_dev_t*)dev)
|
||||
#define spi_flash_ll_set_cs_pin(dev, pin) gpspi_flash_ll_set_cs_pin((spi_dev_t*)dev, pin)
|
||||
#define spi_flash_ll_set_read_mode(dev, read_mode) gpspi_flash_ll_set_read_mode((spi_dev_t*)dev, read_mode)
|
||||
#define spi_flash_ll_set_clock(dev, clk) gpspi_flash_ll_set_clock((spi_dev_t*)dev, (gpspi_flash_ll_clock_reg_t*)clk)
|
||||
#define spi_flash_ll_set_miso_bitlen(dev, bitlen) gpspi_flash_ll_set_miso_bitlen((spi_dev_t*)dev, bitlen)
|
||||
#define spi_flash_ll_set_mosi_bitlen(dev, bitlen) gpspi_flash_ll_set_mosi_bitlen((spi_dev_t*)dev, bitlen)
|
||||
#define spi_flash_ll_set_command(dev, cmd, bitlen) gpspi_flash_ll_set_command((spi_dev_t*)dev, cmd, bitlen)
|
||||
#define spi_flash_ll_set_addr_bitlen(dev, bitlen) gpspi_flash_ll_set_addr_bitlen((spi_dev_t*)dev, bitlen)
|
||||
#define spi_flash_ll_get_addr_bitlen(dev) gpspi_flash_ll_get_addr_bitlen((spi_dev_t*)dev)
|
||||
#define spi_flash_ll_set_address(dev, addr) gpspi_flash_ll_set_address((spi_dev_t*)dev, addr)
|
||||
#define spi_flash_ll_set_usr_address(dev, addr, bitlen) gpspi_flash_ll_set_usr_address((spi_dev_t*)dev, addr, bitlen)
|
||||
#define spi_flash_ll_set_dummy(dev, dummy) gpspi_flash_ll_set_dummy((spi_dev_t*)dev, dummy)
|
||||
#define spi_flash_ll_set_dummy_out(dev, en, lev) gpspi_flash_ll_set_dummy_out((spi_dev_t*)dev, en, lev)
|
||||
#define spi_flash_ll_set_hold(dev, hold_n) gpspi_flash_ll_set_hold((spi_dev_t*)dev, hold_n)
|
||||
#else
|
||||
#define spi_flash_ll_reset(dev) spimem_flash_ll_reset((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_cmd_is_done(dev) spimem_flash_ll_cmd_is_done((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_erase_chip(dev) spimem_flash_ll_erase_chip((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_erase_sector(dev) spimem_flash_ll_erase_sector((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_erase_block(dev) spimem_flash_ll_erase_block((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_set_write_protect(dev, wp) spimem_flash_ll_set_write_protect((spi_mem_dev_t*)dev, wp)
|
||||
#define spi_flash_ll_get_buffer_data(dev, buffer, read_len) spimem_flash_ll_get_buffer_data((spi_mem_dev_t*)dev, buffer, read_len)
|
||||
#define spi_flash_ll_set_buffer_data(dev, buffer, len) spimem_flash_ll_set_buffer_data((spi_mem_dev_t*)dev, buffer, len)
|
||||
#define spi_flash_ll_program_page(dev, buffer, len) spimem_flash_ll_program_page((spi_mem_dev_t*)dev, buffer, len)
|
||||
#define spi_flash_ll_user_start(dev) spimem_flash_ll_user_start((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_host_idle(dev) spimem_flash_ll_host_idle((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_read_phase(dev) spimem_flash_ll_read_phase((spi_mem_dev_t*)dev)
|
||||
#define spi_flash_ll_set_cs_pin(dev, pin) spimem_flash_ll_set_cs_pin((spi_mem_dev_t*)dev, pin)
|
||||
#define spi_flash_ll_set_read_mode(dev, read_mode) spimem_flash_ll_set_read_mode((spi_mem_dev_t*)dev, read_mode)
|
||||
#define spi_flash_ll_set_clock(dev, clk) spimem_flash_ll_set_clock((spi_mem_dev_t*)dev, (spimem_flash_ll_clock_reg_t*)clk)
|
||||
#define spi_flash_ll_set_miso_bitlen(dev, bitlen) spimem_flash_ll_set_miso_bitlen((spi_mem_dev_t*)dev, bitlen)
|
||||
#define spi_flash_ll_set_mosi_bitlen(dev, bitlen) spimem_flash_ll_set_mosi_bitlen((spi_mem_dev_t*)dev, bitlen)
|
||||
#define spi_flash_ll_set_command(dev, cmd, bitlen) spimem_flash_ll_set_command((spi_mem_dev_t*)dev, cmd, bitlen)
|
||||
#define spi_flash_ll_set_addr_bitlen(dev, bitlen) spimem_flash_ll_set_addr_bitlen((spi_mem_dev_t*)dev, bitlen)
|
||||
#define spi_flash_ll_get_addr_bitlen(dev) spimem_flash_ll_get_addr_bitlen((spi_mem_dev_t*) dev)
|
||||
#define spi_flash_ll_set_address(dev, addr) spimem_flash_ll_set_address((spi_mem_dev_t*)dev, addr)
|
||||
#define spi_flash_ll_set_usr_address(dev, addr, bitlen) spimem_flash_ll_set_usr_address((spi_mem_dev_t*)dev, addr, bitlen)
|
||||
#define spi_flash_ll_set_dummy(dev, dummy) spimem_flash_ll_set_dummy((spi_mem_dev_t*)dev, dummy)
|
||||
#define spi_flash_ll_set_dummy_out(dev, en, lev) spimem_flash_ll_set_dummy_out((spi_mem_dev_t*)dev, en, lev)
|
||||
#define spi_flash_ll_set_hold(dev, hold_n) spimem_flash_ll_set_hold((spi_mem_dev_t*)dev, hold_n)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
1090
components/hal/esp32c3/include/hal/spi_ll.h
Normal file
1090
components/hal/esp32c3/include/hal/spi_ll.h
Normal file
File diff suppressed because it is too large
Load Diff
413
components/hal/esp32c3/include/hal/spimem_flash_ll.h
Normal file
413
components/hal/esp32c3/include/hal/spimem_flash_ll.h
Normal file
@ -0,0 +1,413 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The ll is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The Lowlevel layer for SPI Flash
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/param.h> // For MIN/MAX
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "soc/spi_periph.h"
|
||||
#include "hal/spi_types.h"
|
||||
#include "hal/spi_flash_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define spimem_flash_ll_get_hw(host_id) (((host_id)==SPI1_HOST ? &SPIMEM1 : NULL ))
|
||||
#define spimem_flash_ll_hw_get_id(dev) ((dev) == (void*)&SPIMEM1? SPI1_HOST: -1)
|
||||
|
||||
typedef typeof(SPIMEM1.clock) spimem_flash_ll_clock_reg_t;
|
||||
|
||||
//Supported clock register values
|
||||
#define SPIMEM_FLASH_LL_CLKREG_VAL_5MHZ ((spimem_flash_ll_clock_reg_t){.val=0x000F070F}) ///< Clock set to 5 MHz
|
||||
#define SPIMEM_FLASH_LL_CLKREG_VAL_10MHZ ((spimem_flash_ll_clock_reg_t){.val=0x00070307}) ///< Clock set to 10 MHz
|
||||
#define SPIMEM_FLASH_LL_CLKREG_VAL_20MHZ ((spimem_flash_ll_clock_reg_t){.val=0x00030103}) ///< Clock set to 20 MHz
|
||||
#define SPIMEM_FLASH_LL_CLKREG_VAL_26MHZ ((spimem_flash_ll_clock_reg_t){.val=0x00020002}) ///< Clock set to 26 MHz
|
||||
#define SPIMEM_FLASH_LL_CLKREG_VAL_40MHZ ((spimem_flash_ll_clock_reg_t){.val=0x00010001}) ///< Clock set to 40 MHz
|
||||
#define SPIMEM_FLASH_LL_CLKREG_VAL_80MHZ ((spimem_flash_ll_clock_reg_t){.val=0x80000000}) ///< Clock set to 80 MHz
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Control
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Reset peripheral registers before configuration and starting control
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_reset(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->user.val = 0;
|
||||
dev->ctrl.val = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the previous operation is done.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if last command is done, otherwise false.
|
||||
*/
|
||||
static inline bool spimem_flash_ll_cmd_is_done(const spi_mem_dev_t *dev)
|
||||
{
|
||||
return (dev->cmd.val == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase the flash chip.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_erase_chip(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->cmd.flash_ce = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase the sector, the address should be set by spimem_flash_ll_set_address.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_erase_sector(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->ctrl.val = 0;
|
||||
dev->cmd.flash_se = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase the block, the address should be set by spimem_flash_ll_set_address.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_erase_block(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->cmd.flash_be = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/disable write protection for the flash chip.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param wp true to enable the protection, false to disable (write enable).
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_write_protect(spi_mem_dev_t *dev, bool wp)
|
||||
{
|
||||
if (wp) {
|
||||
dev->cmd.flash_wrdi = 1;
|
||||
} else {
|
||||
dev->cmd.flash_wren = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the read data from the buffer after ``spimem_flash_ll_read`` is done.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param buffer Buffer to hold the output data
|
||||
* @param read_len Length to get out of the buffer
|
||||
*/
|
||||
static inline void spimem_flash_ll_get_buffer_data(spi_mem_dev_t *dev, void *buffer, uint32_t read_len)
|
||||
{
|
||||
if (((intptr_t)buffer % 4 == 0) && (read_len % 4 == 0)) {
|
||||
// If everything is word-aligned, do a faster memcpy
|
||||
memcpy(buffer, (void *)dev->data_buf, read_len);
|
||||
} else {
|
||||
// Otherwise, slow(er) path copies word by word
|
||||
int copy_len = read_len;
|
||||
for (int i = 0; i < (read_len + 3) / 4; i++) {
|
||||
int word_len = MIN(sizeof(uint32_t), copy_len);
|
||||
uint32_t word = dev->data_buf[i];
|
||||
memcpy(buffer, &word, word_len);
|
||||
buffer = (void *)((intptr_t)buffer + word_len);
|
||||
copy_len -= word_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the data to be written in the data buffer.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param buffer Buffer holding the data
|
||||
* @param length Length of data in bytes.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_buffer_data(spi_mem_dev_t *dev, const void *buffer, uint32_t length)
|
||||
{
|
||||
// Load data registers, word at a time
|
||||
int num_words = (length + 3) / 4;
|
||||
for (int i = 0; i < num_words; i++) {
|
||||
uint32_t word = 0;
|
||||
uint32_t word_len = MIN(length, sizeof(word));
|
||||
memcpy(&word, buffer, word_len);
|
||||
dev->data_buf[i] = word;
|
||||
length -= word_len;
|
||||
buffer = (void *)((intptr_t)buffer + word_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Program a page of the flash chip. Call ``spimem_flash_ll_set_address`` before
|
||||
* this to set the address to program.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param buffer Buffer holding the data to program
|
||||
* @param length Length to program.
|
||||
*/
|
||||
static inline void spimem_flash_ll_program_page(spi_mem_dev_t *dev, const void *buffer, uint32_t length)
|
||||
{
|
||||
dev->user.usr_dummy = 0;
|
||||
spimem_flash_ll_set_buffer_data(dev, buffer, length);
|
||||
dev->cmd.flash_pp = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a user defined transaction. All phases, including command, address, dummy, and the data phases,
|
||||
* should be configured before this is called.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_user_start(spi_mem_dev_t *dev)
|
||||
{
|
||||
dev->cmd.usr = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the host is idle to perform new commands.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return true if the host is idle, otherwise false
|
||||
*/
|
||||
static inline bool spimem_flash_ll_host_idle(const spi_mem_dev_t *dev)
|
||||
{
|
||||
return dev->fsm.spi0_mst_st == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set phases for user-defined transaction to read
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spimem_flash_ll_read_phase(spi_mem_dev_t *dev)
|
||||
{
|
||||
typeof (dev->user) user = {
|
||||
.usr_command = 1,
|
||||
.usr_mosi = 0,
|
||||
.usr_miso = 1,
|
||||
.usr_addr = 1,
|
||||
};
|
||||
dev->user = user;
|
||||
}
|
||||
/*------------------------------------------------------------------------------
|
||||
* Configs
|
||||
*----------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Select which pin to use for the flash
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param pin Pin ID to use, 0-2. Set to other values to disable all the CS pins.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_cs_pin(spi_mem_dev_t *dev, int pin)
|
||||
{
|
||||
dev->misc.cs0_dis = (pin == 0) ? 0 : 1;
|
||||
dev->misc.cs1_dis = (pin == 1) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the read io mode.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param read_mode I/O mode to use in the following transactions.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_read_mode(spi_mem_dev_t *dev, esp_flash_io_mode_t read_mode)
|
||||
{
|
||||
typeof (dev->ctrl) ctrl = dev->ctrl;
|
||||
ctrl.val &= ~(SPI_MEM_FREAD_QIO_M | SPI_MEM_FREAD_QUAD_M | SPI_MEM_FREAD_DIO_M | SPI_MEM_FREAD_DUAL_M);
|
||||
ctrl.val |= SPI_MEM_FASTRD_MODE_M;
|
||||
switch (read_mode) {
|
||||
case SPI_FLASH_FASTRD:
|
||||
//the default option
|
||||
break;
|
||||
case SPI_FLASH_QIO:
|
||||
ctrl.fread_qio = 1;
|
||||
break;
|
||||
case SPI_FLASH_QOUT:
|
||||
ctrl.fread_quad = 1;
|
||||
break;
|
||||
case SPI_FLASH_DIO:
|
||||
ctrl.fread_dio = 1;
|
||||
break;
|
||||
case SPI_FLASH_DOUT:
|
||||
ctrl.fread_dual = 1;
|
||||
break;
|
||||
case SPI_FLASH_SLOWRD:
|
||||
ctrl.fastrd_mode = 0;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
dev->ctrl = ctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set clock frequency to work at.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param clock_val pointer to the clock value to set
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_clock(spi_mem_dev_t *dev, spimem_flash_ll_clock_reg_t *clock_val)
|
||||
{
|
||||
dev->clock = *clock_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the input length, in bits.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param bitlen Length of input, in bits.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_miso_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_miso = bitlen > 0;
|
||||
dev->miso_dlen.usr_miso_bit_len = bitlen ? (bitlen - 1) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the output length, in bits (not including command, address and dummy
|
||||
* phases)
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param bitlen Length of output, in bits.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_mosi_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_mosi = bitlen > 0;
|
||||
dev->mosi_dlen.usr_mosi_bit_len = bitlen ? (bitlen - 1) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the command.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param command Command to send
|
||||
* @param bitlen Length of the command
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_command(spi_mem_dev_t *dev, uint32_t command, uint32_t bitlen)
|
||||
{
|
||||
dev->user.usr_command = 1;
|
||||
typeof(dev->user2) user2 = {
|
||||
.usr_command_value = command,
|
||||
.usr_command_bitlen = (bitlen - 1),
|
||||
};
|
||||
dev->user2 = user2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address length that is set in register, in bits.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
*
|
||||
*/
|
||||
static inline int spimem_flash_ll_get_addr_bitlen(spi_mem_dev_t *dev)
|
||||
{
|
||||
return dev->user.usr_addr ? dev->user1.usr_addr_bitlen + 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address length to send, in bits. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param bitlen Length of the address, in bits
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_addr_bitlen(spi_mem_dev_t *dev, uint32_t bitlen)
|
||||
{
|
||||
dev->user1.usr_addr_bitlen = (bitlen - 1);
|
||||
dev->user.usr_addr = bitlen ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address to send. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param addr Address to send
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_address(spi_mem_dev_t *dev, uint32_t addr)
|
||||
{
|
||||
dev->addr = addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the address to send in user mode. Should be called before commands that requires the address e.g. erase sector, read, write...
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param addr Address to send
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_usr_address(spi_mem_dev_t *dev, uint32_t addr, uint32_t bitlen)
|
||||
{
|
||||
(void)bitlen;
|
||||
spimem_flash_ll_set_address(dev, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the length of dummy cycles.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param dummy_n Cycles of dummy phases
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_dummy(spi_mem_dev_t *dev, uint32_t dummy_n)
|
||||
{
|
||||
dev->user.usr_dummy = dummy_n ? 1 : 0;
|
||||
dev->user1.usr_dummy_cyclelen = dummy_n - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set D/Q output level during dummy phase
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param out_en whether to enable IO output for dummy phase
|
||||
* @param out_level dummy output level
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_dummy_out(spi_mem_dev_t *dev, uint32_t out_en, uint32_t out_lev)
|
||||
{
|
||||
dev->ctrl.fdummy_out = out_en;
|
||||
dev->ctrl.q_pol = out_lev;
|
||||
dev->ctrl.d_pol = out_lev;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set CS hold time.
|
||||
*
|
||||
* @param dev Beginning address of the peripheral registers.
|
||||
* @param hold_n CS hold time config used by the host.
|
||||
*/
|
||||
static inline void spimem_flash_ll_set_hold(spi_mem_dev_t *dev, uint32_t hold_n)
|
||||
{
|
||||
dev->ctrl2.cs_hold_time = hold_n - 1;
|
||||
dev->user.cs_hold = (hold_n > 0? 1: 0);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
153
components/hal/esp32c3/include/hal/systimer_ll.h
Normal file
153
components/hal/esp32c3/include/hal/systimer_ll.h
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/systimer_reg.h"
|
||||
|
||||
// All these functions get invoked either from ISR or HAL that linked to IRAM.
|
||||
// Always inline these functions even no gcc optimization is applied.
|
||||
|
||||
/*******************counter*************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_clock(void)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_CONF_REG, SYS_TIMER_CLK_EN);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_counter(uint32_t counter_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_CONF_REG, 1 << (30 - counter_id));
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_can_stall_by_cpu(uint32_t counter_id, uint32_t cpu_id, bool can)
|
||||
{
|
||||
if (can) {
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_CONF_REG, 1 << ((28 - counter_id * 2) - cpu_id));
|
||||
} else {
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_CONF_REG, 1 << ((28 - counter_id * 2) - cpu_id));
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_counter_snapshot(uint32_t counter_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_UNIT0_OP_REG + 4 * counter_id, 1 << 30);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_counter_value_valid(uint32_t counter_id)
|
||||
{
|
||||
return REG_GET_BIT(SYS_TIMER_SYSTIMER_UNIT0_OP_REG + 4 * counter_id, 1 << 29);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_counter_value(uint32_t counter_id, uint64_t value)
|
||||
{
|
||||
REG_WRITE(SYS_TIMER_SYSTIMER_UNIT0_LOAD_LO_REG + 8 * counter_id, value & 0xFFFFFFFF);
|
||||
REG_WRITE(SYS_TIMER_SYSTIMER_UNIT0_LOAD_HI_REG, (value >> 32) & 0xFFFFF);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_low(uint32_t counter_id)
|
||||
{
|
||||
return REG_READ(SYS_TIMER_SYSTIMER_UNIT0_VALUE_LO_REG + 8 * counter_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint32_t systimer_ll_get_counter_value_high(uint32_t counter_id)
|
||||
{
|
||||
return REG_READ(SYS_TIMER_SYSTIMER_UNIT0_VALUE_HI_REG + 8 * counter_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_counter_value(uint32_t counter_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_UNIT0_LOAD_REG + 4 * counter_id, SYS_TIMER_TIMER_UNIT0_LOAD);
|
||||
}
|
||||
|
||||
/*******************alarm*************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
REG_WRITE(SYS_TIMER_SYSTIMER_TARGET0_LO_REG + alarm_id * 8, value & 0xFFFFFFFF);
|
||||
REG_WRITE(SYS_TIMER_SYSTIMER_TARGET0_HI_REG + alarm_id * 8, (value >> 32) & 0xFFFFF);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t) REG_READ(SYS_TIMER_SYSTIMER_TARGET0_HI_REG + alarm_id * 8) << 32) \
|
||||
| REG_READ(SYS_TIMER_SYSTIMER_TARGET0_LO_REG + alarm_id * 8);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_connect_alarm_counter(uint32_t alarm_id, uint32_t counter_id)
|
||||
{
|
||||
REG_SET_FIELD(SYS_TIMER_SYSTIMER_TARGET0_CONF_REG + 4 * alarm_id, SYS_TIMER_TARGET0_TIMER_UNIT_SEL, counter_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_oneshot(uint32_t alarm_id)
|
||||
{
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_TARGET0_CONF_REG + alarm_id * 4, SYS_TIMER_TARGET0_PERIOD_MODE);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_period(uint32_t alarm_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_TARGET0_CONF_REG + alarm_id * 4, SYS_TIMER_TARGET0_PERIOD_MODE);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_period(uint32_t alarm_id, uint32_t period)
|
||||
{
|
||||
REG_SET_FIELD(SYS_TIMER_SYSTIMER_TARGET0_CONF_REG + alarm_id * 4, SYS_TIMER_TARGET0_PERIOD, period);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_apply_alarm_value(uint32_t alarm_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_COMP0_LOAD_REG + alarm_id * 4, SYS_TIMER_TIMER_COMP0_LOAD);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_disable_alarm(uint32_t alarm_id)
|
||||
{
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_CONF_REG, 1 << (24 - alarm_id));
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm(uint32_t alarm_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_CONF_REG, 1 << (24 - alarm_id));
|
||||
}
|
||||
|
||||
/*******************interrupt*************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_enable_alarm_int(uint32_t alarm_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_INT_ENA_REG, 1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_disable_alarm_int(uint32_t alarm_id)
|
||||
{
|
||||
REG_CLR_BIT(SYS_TIMER_SYSTIMER_INT_ENA_REG, 1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline bool systimer_ll_is_alarm_int_fired(uint32_t alarm_id)
|
||||
{
|
||||
return REG_GET_BIT(SYS_TIMER_SYSTIMER_INT_RAW_REG, 1 << alarm_id);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_clear_alarm_int(uint32_t alarm_id)
|
||||
{
|
||||
REG_SET_BIT(SYS_TIMER_SYSTIMER_INT_CLR_REG, 1 << alarm_id);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
436
components/hal/esp32c3/include/hal/timer_ll.h
Normal file
436
components/hal/esp32c3/include/hal/timer_ll.h
Normal file
@ -0,0 +1,436 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for Timer Group register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "hal/timer_types.h"
|
||||
#include "soc/timer_periph.h"
|
||||
|
||||
_Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
|
||||
_Static_assert(TIMER_INTR_WDT == TIMG_WDT_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
|
||||
|
||||
typedef struct {
|
||||
timg_dev_t *dev;
|
||||
timer_idx_t idx;
|
||||
} timer_ll_context_t;
|
||||
|
||||
// Get timer group instance with giving group number
|
||||
#define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1))
|
||||
|
||||
/**
|
||||
* @brief Set timer clock prescale value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param divider Prescale value
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint16_t divider)
|
||||
{
|
||||
int timer_en = hw->hw_timer[timer_num].config.enable;
|
||||
hw->hw_timer[timer_num].config.enable = 0;
|
||||
hw->hw_timer[timer_num].config.divider = divider;
|
||||
hw->hw_timer[timer_num].config.enable = timer_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get timer clock prescale value
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param divider Pointer to accept the prescale value
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider)
|
||||
{
|
||||
uint32_t d = hw->hw_timer[timer_num].config.divider;
|
||||
if (d == 0) {
|
||||
d = 65536;
|
||||
}
|
||||
*divider = d;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load counter value into time-base counter
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param load_val Counter value
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val)
|
||||
{
|
||||
hw->hw_timer[timer_num].load_high.load_hi = (uint32_t) (load_val >> 32);
|
||||
hw->hw_timer[timer_num].load_low = (uint32_t) load_val;
|
||||
hw->hw_timer[timer_num].reload = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get counter value from time-base counter
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param timer_val Pointer to accept the counter value
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val)
|
||||
{
|
||||
hw->hw_timer[timer_num].update.update = 1;
|
||||
while (hw->hw_timer[timer_num].update.update) {}
|
||||
*timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high.hi << 32) | (hw->hw_timer[timer_num].cnt_low);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set counter mode, include increment mode and decrement mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param increase_en True to increment mode, fasle to decrement mode
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en)
|
||||
{
|
||||
hw->hw_timer[timer_num].config.increase = increase_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get counter mode, include increment mode and decrement mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return
|
||||
* - true Increment mode
|
||||
* - false Decrement mode
|
||||
*/
|
||||
static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
return hw->hw_timer[timer_num].config.increase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set counter status, enable or disable counter.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param counter_en True to enable counter, false to disable counter
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en)
|
||||
{
|
||||
hw->hw_timer[timer_num].config.enable = counter_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get counter status.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return
|
||||
* - true Enable counter
|
||||
* - false Disable conuter
|
||||
*/
|
||||
static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
return hw->hw_timer[timer_num].config.enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set auto reload mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en)
|
||||
{
|
||||
hw->hw_timer[timer_num].config.autoreload = auto_reload_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get auto reload mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return
|
||||
* - true Enable auto reload mode
|
||||
* - false Disable auto reload mode
|
||||
*/
|
||||
FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
return hw->hw_timer[timer_num].config.autoreload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the counter value to trigger the alarm.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param alarm_value Counter value to trigger the alarm
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value)
|
||||
{
|
||||
hw->hw_timer[timer_num].alarm_high.alarm_hi = (uint32_t) (alarm_value >> 32);
|
||||
hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the counter value to trigger the alarm.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param alarm_value Pointer to accept the counter value to trigger the alarm
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value)
|
||||
{
|
||||
*alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high.alarm_hi << 32) | (hw->hw_timer[timer_num].alarm_low);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the alarm status, enable or disable the alarm.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param alarm_en True to enable alarm, false to disable alarm
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en)
|
||||
{
|
||||
hw->hw_timer[timer_num].config.alarm_en = alarm_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the alarm status.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return
|
||||
* - true Enable alarm
|
||||
* - false Disable alarm
|
||||
*/
|
||||
static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
return hw->hw_timer[timer_num].config.alarm_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable timer interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
hw->int_ena.val |= BIT(timer_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable timer interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
hw->int_ena.val &= (~BIT(timer_num));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable timer interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
hw->int_clr.val |= BIT(timer_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param intr_status Interrupt status
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
|
||||
{
|
||||
*intr_status = hw->int_st.val & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get interrupt raw status.
|
||||
*
|
||||
* @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
|
||||
* @param intr_raw_status Interrupt raw status
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
|
||||
{
|
||||
timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
|
||||
*intr_raw_status = hw->int_raw.val & 0x01;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the level interrupt status, enable or disable the level interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param level_int_en True to enable level interrupt, false to disable level interrupt
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en)
|
||||
{
|
||||
switch (timer_num) {
|
||||
case 0:
|
||||
hw->int_ena.t0 = level_int_en;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the level interrupt status.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return
|
||||
* - true Enable level interrupt
|
||||
* - false Disable level interrupt
|
||||
*/
|
||||
static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
bool enable = false;
|
||||
switch (timer_num) {
|
||||
case 0:
|
||||
enable = hw->int_ena.t0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the edge interrupt status, enable or disable the edge interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
* @param edge_int_en True to enable edge interrupt, false to disable edge interrupt
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en)
|
||||
{
|
||||
// edge interrupt is not supported on C3
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the edge interrupt status.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param timer_num The timer number
|
||||
*
|
||||
* @return
|
||||
* - true Enable edge interrupt
|
||||
* - false Disable edge interrupt
|
||||
*/
|
||||
static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
// edge interrupt is not supported on C3
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status register address.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return uint32_t Interrupt status register address
|
||||
*/
|
||||
static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw)
|
||||
{
|
||||
return (uint32_t) & (hw->int_st.val);
|
||||
}
|
||||
|
||||
static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
return (1U << timer_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set clock source.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
* @param use_xtal_en True to use XTAL clock, flase to use APB clock
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void timer_ll_set_use_xtal(timg_dev_t *hw, timer_idx_t timer_num, bool use_xtal_en)
|
||||
{
|
||||
hw->hw_timer[timer_num].config.use_xtal = use_xtal_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get clock source.
|
||||
*
|
||||
* @param hal Context of the HAL layer
|
||||
*
|
||||
* @return
|
||||
* - true Use XTAL clock
|
||||
* - false Use APB clock
|
||||
*/
|
||||
static inline bool timer_ll_get_use_xtal(timg_dev_t *hw, timer_idx_t timer_num)
|
||||
{
|
||||
return hw->hw_timer[timer_num].config.use_xtal;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
703
components/hal/esp32c3/include/hal/twai_ll.h
Normal file
703
components/hal/esp32c3/include/hal/twai_ll.h
Normal file
@ -0,0 +1,703 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The ll is not public api, don't use in application code.
|
||||
* See readme.md in soc/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The Lowlevel layer for TWAI
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "hal/twai_types.h"
|
||||
#include "soc/twai_periph.h"
|
||||
|
||||
/* ------------------------- Defines and Typedefs --------------------------- */
|
||||
|
||||
#define TWAI_LL_STATUS_RBS (0x1 << 0)
|
||||
#define TWAI_LL_STATUS_DOS (0x1 << 1)
|
||||
#define TWAI_LL_STATUS_TBS (0x1 << 2)
|
||||
#define TWAI_LL_STATUS_TCS (0x1 << 3)
|
||||
#define TWAI_LL_STATUS_RS (0x1 << 4)
|
||||
#define TWAI_LL_STATUS_TS (0x1 << 5)
|
||||
#define TWAI_LL_STATUS_ES (0x1 << 6)
|
||||
#define TWAI_LL_STATUS_BS (0x1 << 7)
|
||||
|
||||
#define TWAI_LL_INTR_RI (0x1 << 0)
|
||||
#define TWAI_LL_INTR_TI (0x1 << 1)
|
||||
#define TWAI_LL_INTR_EI (0x1 << 2)
|
||||
//Data overrun interrupt not supported in SW due to HW peculiarities
|
||||
#define TWAI_LL_INTR_EPI (0x1 << 5)
|
||||
#define TWAI_LL_INTR_ALI (0x1 << 6)
|
||||
#define TWAI_LL_INTR_BEI (0x1 << 7)
|
||||
|
||||
/*
|
||||
* The following frame structure has an NEARLY identical bit field layout to
|
||||
* each byte of the TX buffer. This allows for formatting and parsing frames to
|
||||
* be done outside of time critical regions (i.e., ISRs). All the ISR needs to
|
||||
* do is to copy byte by byte to/from the TX/RX buffer. The two reserved bits in
|
||||
* TX buffer are used in the frame structure to store the self_reception and
|
||||
* single_shot flags which in turn indicate the type of transmission to execute.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
struct {
|
||||
uint8_t dlc: 4; //Data length code (0 to 8) of the frame
|
||||
uint8_t self_reception: 1; //This frame should be transmitted using self reception command
|
||||
uint8_t single_shot: 1; //This frame should be transmitted using single shot command
|
||||
uint8_t rtr: 1; //This frame is a remote transmission request
|
||||
uint8_t frame_format: 1; //Format of the frame (1 = extended, 0 = standard)
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
uint8_t id[2]; //11 bit standard frame identifier
|
||||
uint8_t data[8]; //Data bytes (0 to 8)
|
||||
uint8_t reserved8[2];
|
||||
} standard;
|
||||
struct {
|
||||
uint8_t id[4]; //29 bit extended frame identifier
|
||||
uint8_t data[8]; //Data bytes (0 to 8)
|
||||
} extended;
|
||||
};
|
||||
};
|
||||
uint8_t bytes[13];
|
||||
} __attribute__((packed)) twai_ll_frame_buffer_t;
|
||||
|
||||
/* ---------------------------- Mode Register ------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Enter reset mode
|
||||
*
|
||||
* When in reset mode, the TWAI controller is effectively disconnected from the
|
||||
* TWAI bus and will not participate in any bus activates. Reset mode is required
|
||||
* in order to write the majority of configuration registers.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return true if reset mode was entered successfully
|
||||
*
|
||||
* @note Reset mode is automatically entered on BUS OFF condition
|
||||
*/
|
||||
static inline bool twai_ll_enter_reset_mode(twai_dev_t *hw)
|
||||
{
|
||||
hw->mode_reg.rm = 1;
|
||||
return hw->mode_reg.rm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit reset mode
|
||||
*
|
||||
* When not in reset mode, the TWAI controller will take part in bus activities
|
||||
* (e.g., send/receive/acknowledge messages and error frames) depending on the
|
||||
* operating mode.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return true if reset mode was exit successfully
|
||||
*
|
||||
* @note Reset mode must be exit to initiate BUS OFF recovery
|
||||
*/
|
||||
static inline bool twai_ll_exit_reset_mode(twai_dev_t *hw)
|
||||
{
|
||||
hw->mode_reg.rm = 0;
|
||||
return !(hw->mode_reg.rm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if in reset mode
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return true if in reset mode
|
||||
*/
|
||||
static inline bool twai_ll_is_in_reset_mode(twai_dev_t *hw)
|
||||
{
|
||||
return hw->mode_reg.rm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set operating mode of TWAI controller
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param mode Operating mode
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_mode(twai_dev_t *hw, twai_mode_t mode)
|
||||
{
|
||||
if (mode == TWAI_MODE_NORMAL) { //Normal Operating mode
|
||||
hw->mode_reg.lom = 0;
|
||||
hw->mode_reg.stm = 0;
|
||||
} else if (mode == TWAI_MODE_NO_ACK) { //Self Test Mode (No Ack)
|
||||
hw->mode_reg.lom = 0;
|
||||
hw->mode_reg.stm = 1;
|
||||
} else if (mode == TWAI_MODE_LISTEN_ONLY) { //Listen Only Mode
|
||||
hw->mode_reg.lom = 1;
|
||||
hw->mode_reg.stm = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------- Command Register ----------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Set TX command
|
||||
*
|
||||
* Setting the TX command will cause the TWAI controller to attempt to transmit
|
||||
* the frame stored in the TX buffer. The TX buffer will be occupied (i.e.,
|
||||
* locked) until TX completes.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*
|
||||
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||
* release and clear data overrun) in order to prevent the other commands
|
||||
* overwriting this latched TX bit with 0.
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_tx(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.tr = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set single shot TX command
|
||||
*
|
||||
* Similar to setting TX command, but the TWAI controller will not automatically
|
||||
* retry transmission upon an error (e.g., due to an acknowledgement error).
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*
|
||||
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||
* release and clear data overrun) in order to prevent the other commands
|
||||
* overwriting this latched TX bit with 0.
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_tx_single_shot(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.val = 0x03; //Writing to TR and AT simultaneously
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Aborts TX
|
||||
*
|
||||
* Frames awaiting TX will be aborted. Frames already being TX are not aborted.
|
||||
* Transmission Complete Status bit is automatically set to 1.
|
||||
* Similar to setting TX command, but the TWAI controller will not automatically
|
||||
* retry transmission upon an error (e.g., due to acknowledge error).
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*
|
||||
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||
* release and clear data overrun) in order to prevent the other commands
|
||||
* overwriting this latched TX bit with 0.
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_abort_tx(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.at = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release RX buffer
|
||||
*
|
||||
* Rotates RX buffer to the next frame in the RX FIFO.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_release_rx_buffer(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.rrb = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear data overrun
|
||||
*
|
||||
* Clears the data overrun status bit
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_clear_data_overrun(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.cdo = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set self reception single shot command
|
||||
*
|
||||
* Similar to setting TX command, but the TWAI controller also simultaneously
|
||||
* receive the transmitted frame and is generally used for self testing
|
||||
* purposes. The TWAI controller will not ACK the received message, so consider
|
||||
* using the NO_ACK operating mode.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*
|
||||
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||
* release and clear data overrun) in order to prevent the other commands
|
||||
* overwriting this latched TX bit with 0.
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_self_rx_request(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.srr = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set self reception request command
|
||||
*
|
||||
* Similar to setting the self reception request, but the TWAI controller will
|
||||
* not automatically retry transmission upon an error (e.g., due to and
|
||||
* acknowledgement error).
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*
|
||||
* @note Transmit commands should be called last (i.e., after handling buffer
|
||||
* release and clear data overrun) in order to prevent the other commands
|
||||
* overwriting this latched TX bit with 0.
|
||||
*/
|
||||
static inline void twai_ll_set_cmd_self_rx_single_shot(twai_dev_t *hw)
|
||||
{
|
||||
hw->command_reg.val = 0x12;
|
||||
}
|
||||
|
||||
/* --------------------------- Status Register ------------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Get all status bits
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return Status bits
|
||||
*/
|
||||
static inline uint32_t twai_ll_get_status(twai_dev_t *hw)
|
||||
{
|
||||
return hw->status_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if RX FIFO overrun status bit is set
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return Overrun status bit
|
||||
*/
|
||||
static inline bool twai_ll_is_fifo_overrun(twai_dev_t *hw)
|
||||
{
|
||||
return hw->status_reg.dos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if previously TX was successful
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return Whether previous TX was successful
|
||||
*/
|
||||
static inline bool twai_ll_is_last_tx_successful(twai_dev_t *hw)
|
||||
{
|
||||
return hw->status_reg.tcs;
|
||||
}
|
||||
|
||||
//Todo: Add stand alone status bit check functions when necessary
|
||||
|
||||
/* -------------------------- Interrupt Register ---------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Get currently set interrupts
|
||||
*
|
||||
* Reading the interrupt registers will automatically clear all interrupts
|
||||
* except for the Receive Interrupt.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return Bit mask of set interrupts
|
||||
*/
|
||||
static inline uint32_t twai_ll_get_and_clear_intrs(twai_dev_t *hw)
|
||||
{
|
||||
return hw->interrupt_reg.val;
|
||||
}
|
||||
|
||||
/* ----------------------- Interrupt Enable Register ------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Set which interrupts are enabled
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param Bit mask of interrupts to enable
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_enabled_intrs(twai_dev_t *hw, uint32_t intr_mask)
|
||||
{
|
||||
#ifdef TWAI_BRP_DIV_SUPPORTED
|
||||
//ESP32 Rev 2 has brp div. Need to mask when setting
|
||||
hw->interrupt_enable_reg.val = (hw->interrupt_enable_reg.val & 0x10) | intr_mask;
|
||||
#else
|
||||
hw->interrupt_enable_reg.val = intr_mask;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ------------------------ Bus Timing Registers --------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Set bus timing
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param brp Baud Rate Prescaler
|
||||
* @param sjw Synchronization Jump Width
|
||||
* @param tseg1 Timing Segment 1
|
||||
* @param tseg2 Timing Segment 2
|
||||
* @param triple_sampling Triple Sampling enable/disable
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
* @note ESP32 rev 2 or later can support a x2 brp by setting a brp_div bit,
|
||||
* allowing the brp to go from a maximum of 128 to 256.
|
||||
*/
|
||||
static inline void twai_ll_set_bus_timing(twai_dev_t *hw, uint32_t brp, uint32_t sjw, uint32_t tseg1, uint32_t tseg2, bool triple_sampling)
|
||||
{
|
||||
#ifdef TWAI_BRP_DIV_SUPPORTED
|
||||
if (brp > TWAI_BRP_DIV_THRESH) {
|
||||
//Need to set brp_div bit
|
||||
hw->interrupt_enable_reg.brp_div = 1;
|
||||
brp /= 2;
|
||||
}
|
||||
#endif
|
||||
hw->bus_timing_0_reg.brp = (brp / 2) - 1;
|
||||
hw->bus_timing_0_reg.sjw = sjw - 1;
|
||||
hw->bus_timing_1_reg.tseg1 = tseg1 - 1;
|
||||
hw->bus_timing_1_reg.tseg2 = tseg2 - 1;
|
||||
hw->bus_timing_1_reg.sam = triple_sampling;
|
||||
}
|
||||
|
||||
/* ----------------------------- ALC Register ------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Clear Arbitration Lost Capture Register
|
||||
*
|
||||
* Reading the ALC register rearms the Arbitration Lost Interrupt
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*/
|
||||
static inline void twai_ll_clear_arb_lost_cap(twai_dev_t *hw)
|
||||
{
|
||||
(void)hw->arbitration_lost_captue_reg.val;
|
||||
//Todo: Decode ALC register
|
||||
}
|
||||
|
||||
/* ----------------------------- ECC Register ------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Clear Error Code Capture register
|
||||
*
|
||||
* Reading the ECC register rearms the Bus Error Interrupt
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*/
|
||||
static inline void twai_ll_clear_err_code_cap(twai_dev_t *hw)
|
||||
{
|
||||
(void)hw->error_code_capture_reg.val;
|
||||
//Todo: Decode error code capture
|
||||
}
|
||||
|
||||
/* ----------------------------- EWL Register ------------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Set Error Warning Limit
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param ewl Error Warning Limit
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_err_warn_lim(twai_dev_t *hw, uint32_t ewl)
|
||||
{
|
||||
hw->error_warning_limit_reg.ewl = ewl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Error Warning Limit
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return Error Warning Limit
|
||||
*/
|
||||
static inline uint32_t twai_ll_get_err_warn_lim(twai_dev_t *hw)
|
||||
{
|
||||
return hw->error_warning_limit_reg.val;
|
||||
}
|
||||
|
||||
/* ------------------------ RX Error Count Register ------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Get RX Error Counter
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return REC value
|
||||
*
|
||||
* @note REC is not frozen in reset mode. Listen only mode will freeze it. A BUS
|
||||
* OFF condition automatically sets the REC to 0.
|
||||
*/
|
||||
static inline uint32_t twai_ll_get_rec(twai_dev_t *hw)
|
||||
{
|
||||
return hw->rx_error_counter_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set RX Error Counter
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param rec REC value
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_rec(twai_dev_t *hw, uint32_t rec)
|
||||
{
|
||||
hw->rx_error_counter_reg.rxerr = rec;
|
||||
}
|
||||
|
||||
/* ------------------------ TX Error Count Register ------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Get TX Error Counter
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return TEC value
|
||||
*
|
||||
* @note A BUS OFF condition will automatically set this to 128
|
||||
*/
|
||||
static inline uint32_t twai_ll_get_tec(twai_dev_t *hw)
|
||||
{
|
||||
return hw->tx_error_counter_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set TX Error Counter
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param tec TEC value
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_tec(twai_dev_t *hw, uint32_t tec)
|
||||
{
|
||||
hw->tx_error_counter_reg.txerr = tec;
|
||||
}
|
||||
|
||||
/* ---------------------- Acceptance Filter Registers ----------------------- */
|
||||
|
||||
/**
|
||||
* @brief Set Acceptance Filter
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param code Acceptance Code
|
||||
* @param mask Acceptance Mask
|
||||
* @param single_filter Whether to enable single filter mode
|
||||
*
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_set_acc_filter(twai_dev_t* hw, uint32_t code, uint32_t mask, bool single_filter)
|
||||
{
|
||||
uint32_t code_swapped = __builtin_bswap32(code);
|
||||
uint32_t mask_swapped = __builtin_bswap32(mask);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
hw->acceptance_filter.acr[i].byte = ((code_swapped >> (i * 8)) & 0xFF);
|
||||
hw->acceptance_filter.amr[i].byte = ((mask_swapped >> (i * 8)) & 0xFF);
|
||||
}
|
||||
hw->mode_reg.afm = single_filter;
|
||||
}
|
||||
|
||||
/* ------------------------- TX/RX Buffer Registers ------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Copy a formatted TWAI frame into TX buffer for transmission
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param tx_frame Pointer to formatted frame
|
||||
*
|
||||
* @note Call twai_ll_format_frame_buffer() to format a frame
|
||||
*/
|
||||
static inline void twai_ll_set_tx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t *tx_frame)
|
||||
{
|
||||
//Copy formatted frame into TX buffer
|
||||
for (int i = 0; i < 13; i++) {
|
||||
hw->tx_rx_buffer[i].val = tx_frame->bytes[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy a received frame from the RX buffer for parsing
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param rx_frame Pointer to store formatted frame
|
||||
*
|
||||
* @note Call twai_ll_prase_frame_buffer() to parse the formatted frame
|
||||
*/
|
||||
static inline void twai_ll_get_rx_buffer(twai_dev_t *hw, twai_ll_frame_buffer_t *rx_frame)
|
||||
{
|
||||
//Copy RX buffer registers into frame
|
||||
for (int i = 0; i < 13; i++) {
|
||||
rx_frame->bytes[i] = hw->tx_rx_buffer[i].byte;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format contents of a TWAI frame into layout of TX Buffer
|
||||
*
|
||||
* @param[in] id 11 or 29bit ID
|
||||
* @param[in] dlc Data length code
|
||||
* @param[in] data Pointer to an 8 byte array containing data. NULL if no data
|
||||
* @param[in] format Type of TWAI frame
|
||||
* @param[in] single_shot Frame will not be retransmitted on failure
|
||||
* @param[in] self_rx Frame will also be simultaneously received
|
||||
* @param[out] tx_frame Pointer to store formatted frame
|
||||
*/
|
||||
static inline void twai_ll_format_frame_buffer(uint32_t id, uint8_t dlc, const uint8_t *data,
|
||||
uint32_t flags, twai_ll_frame_buffer_t *tx_frame)
|
||||
{
|
||||
/* This function encodes a message into a frame structure. The frame structure has
|
||||
an identical layout to the TX buffer, allowing the frame structure to be directly
|
||||
copied into TX buffer. */
|
||||
bool is_extd = flags & TWAI_MSG_FLAG_EXTD;
|
||||
bool is_rtr = flags & TWAI_MSG_FLAG_RTR;
|
||||
|
||||
//Set frame information
|
||||
tx_frame->dlc = dlc;
|
||||
tx_frame->frame_format = is_extd;
|
||||
tx_frame->rtr = is_rtr;
|
||||
tx_frame->self_reception = (flags & TWAI_MSG_FLAG_SELF) ? 1 : 0;
|
||||
tx_frame->single_shot = (flags & TWAI_MSG_FLAG_SS) ? 1 : 0;
|
||||
|
||||
//Set ID
|
||||
if (is_extd) {
|
||||
uint32_t id_temp = __builtin_bswap32((id & TWAI_EXTD_ID_MASK) << 3); //((id << 3) >> 8*(3-i))
|
||||
for (int i = 0; i < 4; i++) {
|
||||
tx_frame->extended.id[i] = (id_temp >> (8 * i)) & 0xFF;
|
||||
}
|
||||
} else {
|
||||
uint32_t id_temp = __builtin_bswap16((id & TWAI_STD_ID_MASK) << 5); //((id << 5) >> 8*(1-i))
|
||||
for (int i = 0; i < 2; i++) {
|
||||
tx_frame->standard.id[i] = (id_temp >> (8 * i)) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//Set Data
|
||||
uint8_t *data_buffer = (is_extd) ? tx_frame->extended.data : tx_frame->standard.data;
|
||||
if (!is_rtr) {
|
||||
for (int i = 0; (i < dlc) && (i < TWAI_FRAME_MAX_DLC); i++) {
|
||||
data_buffer[i] = data[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Parse formatted TWAI frame (RX Buffer Layout) into its contents
|
||||
*
|
||||
* @param[in] rx_frame Pointer to formatted frame
|
||||
* @param[out] id 11 or 29bit ID
|
||||
* @param[out] dlc Data length code
|
||||
* @param[out] data Data. Left over bytes set to 0.
|
||||
* @param[out] format Type of TWAI frame
|
||||
*/
|
||||
static inline void twai_ll_prase_frame_buffer(twai_ll_frame_buffer_t *rx_frame, uint32_t *id, uint8_t *dlc,
|
||||
uint8_t *data, uint32_t *flags)
|
||||
{
|
||||
//This function decodes a frame structure into it's constituent components.
|
||||
|
||||
//Copy frame information
|
||||
*dlc = rx_frame->dlc;
|
||||
uint32_t flags_temp = 0;
|
||||
flags_temp |= (rx_frame->frame_format) ? TWAI_MSG_FLAG_EXTD : 0;
|
||||
flags_temp |= (rx_frame->rtr) ? TWAI_MSG_FLAG_RTR : 0;
|
||||
flags_temp |= (rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_MSG_FLAG_DLC_NON_COMP : 0;
|
||||
*flags = flags_temp;
|
||||
|
||||
//Copy ID
|
||||
if (rx_frame->frame_format) {
|
||||
uint32_t id_temp = 0;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
id_temp |= rx_frame->extended.id[i] << (8 * i);
|
||||
}
|
||||
id_temp = __builtin_bswap32(id_temp) >> 3; //((byte[i] << 8*(3-i)) >> 3)
|
||||
*id = id_temp & TWAI_EXTD_ID_MASK;
|
||||
} else {
|
||||
uint32_t id_temp = 0;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
id_temp |= rx_frame->standard.id[i] << (8 * i);
|
||||
}
|
||||
id_temp = __builtin_bswap16(id_temp) >> 5; //((byte[i] << 8*(1-i)) >> 5)
|
||||
*id = id_temp & TWAI_STD_ID_MASK;
|
||||
}
|
||||
|
||||
//Copy data
|
||||
uint8_t *data_buffer = (rx_frame->frame_format) ? rx_frame->extended.data : rx_frame->standard.data;
|
||||
int data_length = (rx_frame->rtr) ? 0 : ((rx_frame->dlc > TWAI_FRAME_MAX_DLC) ? TWAI_FRAME_MAX_DLC : rx_frame->dlc);
|
||||
for (int i = 0; i < data_length; i++) {
|
||||
data[i] = data_buffer[i];
|
||||
}
|
||||
//Set remaining bytes of data to 0
|
||||
for (int i = data_length; i < TWAI_FRAME_MAX_DLC; i++) {
|
||||
data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* ----------------------- RX Message Count Register ------------------------ */
|
||||
|
||||
/**
|
||||
* @brief Get RX Message Counter
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @return RX Message Counter
|
||||
*/
|
||||
static inline uint32_t twai_ll_get_rx_msg_count(twai_dev_t *hw)
|
||||
{
|
||||
return hw->rx_message_counter_reg.val;
|
||||
}
|
||||
|
||||
/* ------------------------- Clock Divider Register ------------------------- */
|
||||
|
||||
/**
|
||||
* @brief Set CLKOUT Divider and enable/disable
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
* @param divider Divider for CLKOUT. Set to 0 to disable CLKOUT
|
||||
*/
|
||||
static inline void twai_ll_set_clkout(twai_dev_t *hw, uint32_t divider)
|
||||
{
|
||||
/* Configure CLKOUT. CLKOUT is a pre-scaled version of APB CLK. Divider can be
|
||||
1, or any even number from 2 to 14. Set to out of range value (0) to disable
|
||||
CLKOUT. */
|
||||
|
||||
if (divider >= 2 && divider <= 14) {
|
||||
TWAI.clock_divider_reg.co = 0;
|
||||
TWAI.clock_divider_reg.cd = (divider / 2) - 1;
|
||||
} else if (divider == 1) {
|
||||
TWAI.clock_divider_reg.co = 0;
|
||||
TWAI.clock_divider_reg.cd = 7;
|
||||
} else {
|
||||
TWAI.clock_divider_reg.co = 1;
|
||||
TWAI.clock_divider_reg.cd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set register address mapping to extended mode
|
||||
*
|
||||
* Extended mode register address mapping consists of more registers and extra
|
||||
* features.
|
||||
*
|
||||
* @param hw Start address of the TWAI registers
|
||||
*
|
||||
* @note Must be called before setting any configuration
|
||||
* @note Must be called in reset mode
|
||||
*/
|
||||
static inline void twai_ll_enable_extended_reg_layout(twai_dev_t *hw)
|
||||
{
|
||||
hw->clock_divider_reg.cm = 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
833
components/hal/esp32c3/include/hal/uart_ll.h
Normal file
833
components/hal/esp32c3/include/hal/uart_ll.h
Normal file
@ -0,0 +1,833 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for UART register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
|
||||
#pragma once
|
||||
#include "hal/uart_types.h"
|
||||
#include "soc/uart_periph.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// The default fifo depth
|
||||
#define UART_LL_FIFO_DEF_LEN (SOC_UART_FIFO_LEN)
|
||||
// Get UART hardware instance with giving uart num
|
||||
#define UART_LL_GET_HW(num) (((num) == 0) ? (&UART0) : (&UART1))
|
||||
|
||||
// TODO ESP32-C3 IDF-2117 check these values are correct (copied from S2)
|
||||
#define UART_LL_MIN_WAKEUP_THRESH (2)
|
||||
#define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask
|
||||
|
||||
// Define UART interrupts
|
||||
typedef enum {
|
||||
UART_INTR_RXFIFO_FULL = (0x1 << 0),
|
||||
UART_INTR_TXFIFO_EMPTY = (0x1 << 1),
|
||||
UART_INTR_PARITY_ERR = (0x1 << 2),
|
||||
UART_INTR_FRAM_ERR = (0x1 << 3),
|
||||
UART_INTR_RXFIFO_OVF = (0x1 << 4),
|
||||
UART_INTR_DSR_CHG = (0x1 << 5),
|
||||
UART_INTR_CTS_CHG = (0x1 << 6),
|
||||
UART_INTR_BRK_DET = (0x1 << 7),
|
||||
UART_INTR_RXFIFO_TOUT = (0x1 << 8),
|
||||
UART_INTR_SW_XON = (0x1 << 9),
|
||||
UART_INTR_SW_XOFF = (0x1 << 10),
|
||||
UART_INTR_GLITCH_DET = (0x1 << 11),
|
||||
UART_INTR_TX_BRK_DONE = (0x1 << 12),
|
||||
UART_INTR_TX_BRK_IDLE = (0x1 << 13),
|
||||
UART_INTR_TX_DONE = (0x1 << 14),
|
||||
UART_INTR_RS485_PARITY_ERR = (0x1 << 15),
|
||||
UART_INTR_RS485_FRM_ERR = (0x1 << 16),
|
||||
UART_INTR_RS485_CLASH = (0x1 << 17),
|
||||
UART_INTR_CMD_CHAR_DET = (0x1 << 18),
|
||||
} uart_intr_t;
|
||||
|
||||
static inline void uart_ll_reset_core(uart_dev_t *hw) {
|
||||
hw->clk_conf.rst_core = 1;
|
||||
hw->clk_conf.rst_core = 0;
|
||||
}
|
||||
|
||||
static inline void uart_ll_sclk_enable(uart_dev_t *hw) {
|
||||
hw->clk_conf.sclk_en = 1;
|
||||
hw->clk_conf.rx_sclk_en = 1;
|
||||
hw->clk_conf.tx_sclk_en = 1;
|
||||
}
|
||||
|
||||
static inline void uart_ll_sclk_disable(uart_dev_t *hw) {
|
||||
hw->clk_conf.sclk_en = 0;
|
||||
hw->clk_conf.rx_sclk_en = 0;
|
||||
hw->clk_conf.tx_sclk_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the baud-rate.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param baud The baud rate to be set. When the source clock is APB, the max baud rate is `UART_LL_BITRATE_MAX`
|
||||
* @param source_clk The UART source clock. The source clock can be APB clock or REF_TICK.
|
||||
* If the source clock is REF_TICK, the UART can still work when the APB changes.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_set_baudrate(uart_dev_t *hw, uart_sclk_t source_clk, uint32_t baud)
|
||||
{
|
||||
const int sclk_div = 1;
|
||||
uint32_t sclk_freq = (source_clk == UART_SCLK_APB) ? APB_CLK_FREQ : REF_CLK_FREQ;
|
||||
uint32_t clk_div = ((sclk_freq) << 4) / baud;
|
||||
// The baud rate configuration register is divided into
|
||||
// an integer part and a fractional part.
|
||||
hw->clk_div.div_int = clk_div >> 4;
|
||||
hw->clk_div.div_frag = clk_div & 0xf;
|
||||
hw->clk_conf.sclk_div_num = sclk_div - 1;//7;//255;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current baud-rate.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return The current baudrate
|
||||
*/
|
||||
static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw)
|
||||
{
|
||||
uint32_t src_clk = APB_CLK_FREQ;
|
||||
typeof(hw->clk_div) div_reg = hw->clk_div;
|
||||
return ((src_clk << 4)) / ((div_reg.div_int << 4) | div_reg.div_frag);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the UART interrupt based on the given mask.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param mask The bitmap of the interrupts need to be enabled.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_ena_intr_mask(uart_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->int_ena.val |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the UART interrupt based on the given mask.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param mask The bitmap of the interrupts need to be disabled.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_disable_intr_mask(uart_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->int_ena.val &= (~mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART interrupt status.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return The UART interrupt status.
|
||||
*/
|
||||
static inline uint32_t uart_ll_get_intsts_mask(uart_dev_t *hw)
|
||||
{
|
||||
return hw->int_st.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the UART interrupt status based on the given mask.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param mask The bitmap of the interrupts need to be cleared.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_clr_intsts_mask(uart_dev_t *hw, uint32_t mask)
|
||||
{
|
||||
hw->int_clr.val = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get status of enabled interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return interrupt enable value
|
||||
*/
|
||||
static inline uint32_t uart_ll_get_intr_ena_status(uart_dev_t *hw)
|
||||
{
|
||||
return hw->int_ena.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the UART rxfifo.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param buf The data buffer. The buffer size should be large than 128 byts.
|
||||
* @param rd_len The data length needs to be read.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_t rd_len)
|
||||
{
|
||||
for (int i = 0; i < (int)rd_len; i++) {
|
||||
buf[i] = hw->ahb_fifo.rw_byte;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write byte to the UART txfifo.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param buf The data buffer.
|
||||
* @param wr_len The data length needs to be writen.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_write_txfifo(uart_dev_t *hw, const uint8_t *buf, uint32_t wr_len)
|
||||
{
|
||||
for (int i = 0; i < (int)wr_len; i++) {
|
||||
hw->ahb_fifo.rw_byte = buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the UART hw rxfifo.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_rxfifo_rst(uart_dev_t *hw)
|
||||
{
|
||||
hw->conf0.rxfifo_rst = 1;
|
||||
hw->conf0.rxfifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the UART hw txfifo.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_txfifo_rst(uart_dev_t *hw)
|
||||
{
|
||||
hw->conf0.txfifo_rst = 1;
|
||||
hw->conf0.txfifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the length of readable data in UART rxfifo.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return The readable data length in rxfifo.
|
||||
*/
|
||||
static inline uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw)
|
||||
{
|
||||
return hw->status.rxfifo_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the writable data length of UART txfifo.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return The data length of txfifo can be written.
|
||||
*/
|
||||
static inline uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw)
|
||||
{
|
||||
return UART_LL_FIFO_DEF_LEN - hw->status.txfifo_cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART stop bit.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param stop_bit The stop bit number to be set.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_bit)
|
||||
{
|
||||
hw->conf0.stop_bit_num = stop_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the configuration of the UART stop bit.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param stop_bit The pointer to accept the stop bit configuration
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_get_stop_bits(uart_dev_t *hw, uart_stop_bits_t *stop_bit)
|
||||
{
|
||||
*stop_bit = hw->conf0.stop_bit_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART parity check mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param parity_mode The parity check mode to be set.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_parity(uart_dev_t *hw, uart_parity_t parity_mode)
|
||||
{
|
||||
if (parity_mode != UART_PARITY_DISABLE) {
|
||||
hw->conf0.parity = parity_mode & 0x1;
|
||||
}
|
||||
hw->conf0.parity_en = (parity_mode >> 1) & 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART parity check mode configuration.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param parity_mode The pointer to accept the parity check mode configuration.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_get_parity(uart_dev_t *hw, uart_parity_t *parity_mode)
|
||||
{
|
||||
if (hw->conf0.parity_en) {
|
||||
*parity_mode = 0X2 | hw->conf0.parity;
|
||||
} else {
|
||||
*parity_mode = UART_PARITY_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the UART rxfifo full threshold value. When the data in rxfifo is more than the threshold value,
|
||||
* it will produce rxfifo_full_int_raw interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param full_thrhd The full threshold value of the rxfifo. `full_thrhd` should be less than `UART_LL_FIFO_DEF_LEN`.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thrhd)
|
||||
{
|
||||
hw->conf1.rxfifo_full_thrhd = full_thrhd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the txfifo empty threshold. when the data length in txfifo is less than threshold value,
|
||||
* it will produce txfifo_empty_int_raw interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param empty_thrhd The empty threshold of txfifo.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_txfifo_empty_thr(uart_dev_t *hw, uint16_t empty_thrhd)
|
||||
{
|
||||
hw->conf1.txfifo_empty_thrhd = empty_thrhd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the UART rx-idle threshold value. when receiver takes more time than rx_idle_thrhd to receive a byte data,
|
||||
* it will produce frame end signal for uhci to stop receiving data.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param rx_idle_thr The rx-idle threshold to be set.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_rx_idle_thr(uart_dev_t *hw, uint32_t rx_idle_thr)
|
||||
{
|
||||
hw->idle_conf.rx_idle_thrhd = rx_idle_thr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the duration time between transfers.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param idle_num the duration time between transfers.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num)
|
||||
{
|
||||
hw->idle_conf.tx_idle_num = idle_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the transmiter to send break chars.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param break_num The number of the break chars need to be send.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num)
|
||||
{
|
||||
if (break_num > 0) {
|
||||
hw->txbrk_conf.tx_brk_num = break_num;
|
||||
hw->conf0.txd_brk = 1;
|
||||
} else {
|
||||
hw->conf0.txd_brk = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART hardware flow control.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param flow_ctrl The hw flow control configuration.
|
||||
* @param rx_thrs The rx flow control signal will be active if the data length in rxfifo is more than this value.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t flow_ctrl, uint32_t rx_thrs)
|
||||
{
|
||||
//only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set.
|
||||
if (flow_ctrl & UART_HW_FLOWCTRL_RTS) {
|
||||
hw->mem_conf.rx_flow_thrhd = rx_thrs;
|
||||
hw->conf1.rx_flow_en = 1;
|
||||
} else {
|
||||
hw->conf1.rx_flow_en = 0;
|
||||
}
|
||||
if (flow_ctrl & UART_HW_FLOWCTRL_CTS) {
|
||||
hw->conf0.tx_flow_en = 1;
|
||||
} else {
|
||||
hw->conf0.tx_flow_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the hardware flow control.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param flow_ctrl A pointer to accept the hw flow control configuration.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t *flow_ctrl)
|
||||
{
|
||||
*flow_ctrl = UART_HW_FLOWCTRL_DISABLE;
|
||||
if (hw->conf1.rx_flow_en) {
|
||||
*flow_ctrl |= UART_HW_FLOWCTRL_RTS;
|
||||
}
|
||||
if (hw->conf0.tx_flow_en) {
|
||||
*flow_ctrl |= UART_HW_FLOWCTRL_CTS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the software flow control.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param flow_ctrl The UART sofware flow control settings.
|
||||
* @param sw_flow_ctrl_en Set true to enable software flow control, otherwise set it false.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t *flow_ctrl, bool sw_flow_ctrl_en)
|
||||
{
|
||||
if (sw_flow_ctrl_en) {
|
||||
hw->flow_conf.xonoff_del = 1;
|
||||
hw->flow_conf.sw_flow_con_en = 1;
|
||||
hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd;
|
||||
hw->swfc_conf0.xoff_threshold = flow_ctrl->xoff_thrd;
|
||||
hw->swfc_conf1.xon_char = flow_ctrl->xon_char;
|
||||
hw->swfc_conf0.xoff_char = flow_ctrl->xoff_char;
|
||||
} else {
|
||||
hw->flow_conf.sw_flow_con_en = 0;
|
||||
hw->flow_conf.xonoff_del = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the AT cmd char. When the receiver receives a continuous AT cmd char, it will produce at_cmd_char_det interrupt.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd_char The AT cmd char configuration.The configuration member is:
|
||||
* - cmd_char The AT cmd character
|
||||
* - char_num The number of received AT cmd char must be equal to or greater than this value
|
||||
* - gap_tout The interval between each AT cmd char, when the duration is less than this value, it will not take this data as AT cmd char
|
||||
* - pre_idle The idle time before the first AT cmd char, when the duration is less than this value, it will not take the previous data as the last AT cmd char
|
||||
* - post_idle The idle time after the last AT cmd char, when the duration is less than this value, it will not take this data as the first AT cmd char
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char)
|
||||
{
|
||||
hw->at_cmd_char.data = cmd_char->cmd_char;
|
||||
hw->at_cmd_char.char_num = cmd_char->char_num;
|
||||
hw->at_cmd_postcnt.post_idle_num = cmd_char->post_idle;
|
||||
hw->at_cmd_precnt.pre_idle_num = cmd_char->pre_idle;
|
||||
hw->at_cmd_gaptout.rx_gap_tout = cmd_char->gap_tout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the UART data bit mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param data_bit The data bit mode to be set.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_data_bit_num(uart_dev_t *hw, uart_word_length_t data_bit)
|
||||
{
|
||||
hw->conf0.bit_num = data_bit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART source clock.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param source_clk The pointer to accept the UART source clock configuration.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_get_sclk(uart_dev_t *hw, uart_sclk_t *source_clk)
|
||||
{
|
||||
*source_clk = UART_SCLK_APB;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the rts active level.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param level The rts active level, 0 or 1.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_rts_active_level(uart_dev_t *hw, int level)
|
||||
{
|
||||
hw->conf0.sw_rts = level & 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the dtr active level.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param level The dtr active level, 0 or 1.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level)
|
||||
{
|
||||
hw->conf0.sw_dtr = level & 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the UART wakeup threshold.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param wakeup_thrd The wakeup threshold value to be set. When the input rx edge changes more than this value,
|
||||
* the UART will active from light sleeping mode.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd)
|
||||
{
|
||||
hw->sleep_conf.active_threshold = wakeup_thrd - SOC_UART_MIN_WAKEUP_THRESH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART work in normal mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_mode_normal(uart_dev_t *hw)
|
||||
{
|
||||
hw->rs485_conf.en = 0;
|
||||
hw->rs485_conf.tx_rx_en = 0;
|
||||
hw->rs485_conf.rx_busy_tx_en = 0;
|
||||
hw->conf0.irda_en = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART work in rs485_app_ctrl mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw)
|
||||
{
|
||||
// Application software control, remove echo
|
||||
hw->rs485_conf.rx_busy_tx_en = 1;
|
||||
hw->conf0.irda_en = 0;
|
||||
hw->conf0.sw_rts = 0;
|
||||
hw->conf0.irda_en = 0;
|
||||
hw->rs485_conf.dl0_en = 1;
|
||||
hw->rs485_conf.dl1_en = 1;
|
||||
hw->rs485_conf.en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART work in rs485_half_duplex mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw)
|
||||
{
|
||||
// Half duplex mode
|
||||
hw->rs485_conf.tx_rx_en = 0;
|
||||
// Setting this bit will allow data to be transmitted while receiving data(full-duplex mode).
|
||||
// But note that this full-duplex mode has no conflict detection function
|
||||
hw->rs485_conf.rx_busy_tx_en = 0;
|
||||
hw->conf0.irda_en = 0;
|
||||
hw->rs485_conf.dl0_en = 1;
|
||||
hw->rs485_conf.dl1_en = 1;
|
||||
hw->rs485_conf.en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART work in collision_detect mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_mode_collision_detect(uart_dev_t *hw)
|
||||
{
|
||||
hw->conf0.irda_en = 0;
|
||||
// Enable full-duplex mode
|
||||
hw->rs485_conf.tx_rx_en = 1;
|
||||
// Transmitter should send data when the receiver is busy,
|
||||
hw->rs485_conf.rx_busy_tx_en = 1;
|
||||
hw->rs485_conf.dl0_en = 1;
|
||||
hw->rs485_conf.dl1_en = 1;
|
||||
hw->rs485_conf.en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the UART work in irda mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_mode_irda(uart_dev_t *hw)
|
||||
{
|
||||
hw->rs485_conf.en = 0;
|
||||
hw->rs485_conf.tx_rx_en = 0;
|
||||
hw->rs485_conf.rx_busy_tx_en = 0;
|
||||
hw->conf0.sw_rts = 0;
|
||||
hw->conf0.irda_en = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set uart mode.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param mode The UART mode to be set.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode)
|
||||
{
|
||||
switch (mode) {
|
||||
default:
|
||||
case UART_MODE_UART:
|
||||
uart_ll_set_mode_normal(hw);
|
||||
break;
|
||||
case UART_MODE_RS485_COLLISION_DETECT:
|
||||
uart_ll_set_mode_collision_detect(hw);
|
||||
break;
|
||||
case UART_MODE_RS485_APP_CTRL:
|
||||
uart_ll_set_mode_rs485_app_ctrl(hw);
|
||||
break;
|
||||
case UART_MODE_RS485_HALF_DUPLEX:
|
||||
uart_ll_set_mode_rs485_half_duplex(hw);
|
||||
break;
|
||||
case UART_MODE_IRDA:
|
||||
uart_ll_set_mode_irda(hw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART AT cmd char configuration.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param cmd_char The Pointer to accept value of UART AT cmd char.
|
||||
* @param char_num Pointer to accept the repeat number of UART AT cmd char.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num)
|
||||
{
|
||||
*cmd_char = hw->at_cmd_char.data;
|
||||
*char_num = hw->at_cmd_char.char_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART wakeup threshold value.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return The UART wakeup threshold value.
|
||||
*/
|
||||
static inline uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw)
|
||||
{
|
||||
return hw->sleep_conf.active_threshold + SOC_UART_MIN_WAKEUP_THRESH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the UART data bit configuration.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param data_bit The pointer to accept the UART data bit configuration.
|
||||
*
|
||||
* @return The bit mode.
|
||||
*/
|
||||
static inline void uart_ll_get_data_bit_num(uart_dev_t *hw, uart_word_length_t *data_bit)
|
||||
{
|
||||
*data_bit = hw->conf0.bit_num;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the UART sending state machine is in the IDLE state.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return True if the state machine is in the IDLE state, otherwise false is returned.
|
||||
*/
|
||||
static inline bool uart_ll_is_tx_idle(uart_dev_t *hw)
|
||||
{
|
||||
return ((hw->status.txfifo_cnt == 0) && (hw->fsm_status.st_utx_out == 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the UART rts flow control is enabled.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return True if hw rts flow control is enabled, otherwise false is returned.
|
||||
*/
|
||||
static inline bool uart_ll_is_hw_rts_en(uart_dev_t *hw)
|
||||
{
|
||||
return hw->conf1.rx_flow_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the UART cts flow control is enabled.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return True if hw cts flow control is enabled, otherwise false is returned.
|
||||
*/
|
||||
static inline bool uart_ll_is_hw_cts_en(uart_dev_t *hw)
|
||||
{
|
||||
return hw->conf0.tx_flow_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure TX signal loop back to RX module, just for the testing purposes
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param loop_back_en Set ture to enable the loop back function, else set it false.
|
||||
*
|
||||
* @return None
|
||||
*/
|
||||
static inline void uart_ll_set_loop_back(uart_dev_t *hw, bool loop_back_en)
|
||||
{
|
||||
hw->conf0.loopback = loop_back_en;
|
||||
}
|
||||
|
||||
static inline void uart_ll_xon_force_on(uart_dev_t *hw, bool always_on)
|
||||
{
|
||||
hw->flow_conf.force_xon = 1;
|
||||
if(!always_on) {
|
||||
hw->flow_conf.force_xon = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Inverse the UART signal with the given mask.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param inv_mask The UART signal bitmap needs to be inversed.
|
||||
* Use the ORred mask of `uart_signal_inv_t`;
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask)
|
||||
{
|
||||
typeof(hw->conf0) conf0_reg = hw->conf0;
|
||||
conf0_reg.irda_tx_inv = (inv_mask & UART_SIGNAL_IRDA_TX_INV) ? 1 : 0;
|
||||
conf0_reg.irda_rx_inv = (inv_mask & UART_SIGNAL_IRDA_RX_INV) ? 1 : 0;
|
||||
conf0_reg.rxd_inv = (inv_mask & UART_SIGNAL_RXD_INV) ? 1 : 0;
|
||||
conf0_reg.cts_inv = (inv_mask & UART_SIGNAL_CTS_INV) ? 1 : 0;
|
||||
conf0_reg.dsr_inv = (inv_mask & UART_SIGNAL_DSR_INV) ? 1 : 0;
|
||||
conf0_reg.txd_inv = (inv_mask & UART_SIGNAL_TXD_INV) ? 1 : 0;
|
||||
conf0_reg.rts_inv = (inv_mask & UART_SIGNAL_RTS_INV) ? 1 : 0;
|
||||
conf0_reg.dtr_inv = (inv_mask & UART_SIGNAL_DTR_INV) ? 1 : 0;
|
||||
hw->conf0.val = conf0_reg.val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the timeout value for receiver receiving a byte, and enable rx timeout function.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
* @param tout_thrd The timeout value as UART bit time. The rx timeout function will be disabled if `tout_thrd == 0`.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd)
|
||||
{
|
||||
uint16_t tout_val = tout_thrd;
|
||||
if(tout_thrd > 0) {
|
||||
hw->mem_conf.rx_tout_thrhd = tout_val;
|
||||
hw->conf1.rx_tout_en = 1;
|
||||
} else {
|
||||
hw->conf1.rx_tout_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the timeout value for receiver receiving a byte.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0.
|
||||
*/
|
||||
static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw)
|
||||
{
|
||||
uint16_t tout_thrd = 0;
|
||||
if(hw->conf1.rx_tout_en > 0) {
|
||||
tout_thrd = hw->mem_conf.rx_tout_thrhd;
|
||||
}
|
||||
return tout_thrd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get UART maximum timeout threshold.
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*
|
||||
* @return maximum timeout threshold.
|
||||
*/
|
||||
static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw)
|
||||
{
|
||||
return UART_RX_TOUT_THRHD_V;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
174
components/hal/esp32c3/include/hal/uhci_ll.h
Normal file
174
components/hal/esp32c3/include/hal/uhci_ll.h
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// The LL layer for UHCI register operations.
|
||||
// Note that most of the register operations in this layer are non-atomic operations.
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include "uhci_types.h"
|
||||
#include "uhci_struct.h"
|
||||
#include "gdma_struct.h"
|
||||
|
||||
#define UHCI_DMA_INDEX 0
|
||||
|
||||
#define UHCI_LL_GET_HW(num) (((num) == 0) ? (&UHCI0) : (NULL))
|
||||
|
||||
static inline void uhci_ll_init(uhci_dev_t *hw)
|
||||
{
|
||||
typeof(hw->conf0) conf0_reg;
|
||||
hw->conf0.clk_en = 1;
|
||||
conf0_reg.val = 0;
|
||||
conf0_reg.clk_en = 1;
|
||||
hw->conf0.val = conf0_reg.val;
|
||||
hw->conf1.val = 0;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_attach_uart_port(uhci_dev_t *hw, int uart_num)
|
||||
{
|
||||
abort(); // TODO ESP32-C3 IDF-2117
|
||||
}
|
||||
|
||||
static inline void uhci_ll_set_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_char)
|
||||
{
|
||||
if (seper_char->sub_chr_en) {
|
||||
typeof(hw->esc_conf0) esc_conf0_reg = hw->esc_conf0;
|
||||
esc_conf0_reg.seper_char = seper_char->seper_chr;
|
||||
esc_conf0_reg.seper_esc_char0 = seper_char->sub_chr1;
|
||||
esc_conf0_reg.seper_esc_char1 = seper_char->sub_chr2;
|
||||
hw->esc_conf0.val = esc_conf0_reg.val;
|
||||
hw->escape_conf.tx_c0_esc_en = 1;
|
||||
hw->escape_conf.rx_c0_esc_en = 1;
|
||||
} else {
|
||||
hw->escape_conf.tx_c0_esc_en = 0;
|
||||
hw->escape_conf.rx_c0_esc_en = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void uhci_ll_get_seper_chr(uhci_dev_t *hw, uhci_seper_chr_t *seper_chr)
|
||||
{
|
||||
(void)hw;
|
||||
(void)seper_chr;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_set_swflow_ctrl_sub_chr(uhci_dev_t *hw, uhci_swflow_ctrl_sub_chr_t *sub_ctr)
|
||||
{
|
||||
typeof(hw->escape_conf) escape_conf_reg = hw->escape_conf;
|
||||
if (sub_ctr->flow_en == 1) {
|
||||
typeof(hw->esc_conf2) esc_conf2_reg = hw->esc_conf2;
|
||||
typeof(hw->esc_conf3) esc_conf3_reg = hw->esc_conf3;
|
||||
esc_conf2_reg.seq1 = sub_ctr->xon_chr;
|
||||
esc_conf2_reg.seq1_char0 = sub_ctr->xon_sub1;
|
||||
esc_conf2_reg.seq1_char1 = sub_ctr->xon_sub2;
|
||||
esc_conf3_reg.seq2 = sub_ctr->xoff_chr;
|
||||
esc_conf3_reg.seq2_char0 = sub_ctr->xoff_sub1;
|
||||
esc_conf3_reg.seq2_char1 = sub_ctr->xoff_sub2;
|
||||
escape_conf_reg.tx_11_esc_en = 1;
|
||||
escape_conf_reg.tx_13_esc_en = 1;
|
||||
escape_conf_reg.rx_11_esc_en = 1;
|
||||
escape_conf_reg.rx_13_esc_en = 1;
|
||||
hw->esc_conf2.val = esc_conf2_reg.val;
|
||||
hw->esc_conf3.val = esc_conf3_reg.val;
|
||||
} else {
|
||||
escape_conf_reg.tx_11_esc_en = 0;
|
||||
escape_conf_reg.tx_13_esc_en = 0;
|
||||
escape_conf_reg.rx_11_esc_en = 0;
|
||||
escape_conf_reg.rx_13_esc_en = 0;
|
||||
}
|
||||
hw->escape_conf.val = escape_conf_reg.val;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_dma_in_reset(uhci_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.conf0[UHCI_DMA_INDEX].in_rst = 1;
|
||||
GDMA.conf0[UHCI_DMA_INDEX].in_rst = 0;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_dma_out_reset(uhci_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.conf0[UHCI_DMA_INDEX].out_rst = 1;
|
||||
GDMA.conf0[UHCI_DMA_INDEX].out_rst = 0;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_enable_intr(uhci_dev_t *hw, uint32_t intr_mask)
|
||||
{
|
||||
hw->int_ena.val |= intr_mask;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_disable_intr(uhci_dev_t *hw, uint32_t intr_mask)
|
||||
{
|
||||
hw->int_ena.val &= (~intr_mask);
|
||||
}
|
||||
|
||||
static inline void uhci_ll_clear_intr(uhci_dev_t *hw, uint32_t intr_mask)
|
||||
{
|
||||
hw->int_clr.val = intr_mask;
|
||||
}
|
||||
|
||||
static inline uint32_t uhci_ll_get_intr(uhci_dev_t *hw)
|
||||
{
|
||||
return hw->int_st.val;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_set_rx_dma(uhci_dev_t *hw, uint32_t addr)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.in_link[UHCI_DMA_INDEX].addr = addr;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_set_tx_dma(uhci_dev_t *hw, uint32_t addr)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.out_link[UHCI_DMA_INDEX].addr = addr;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_rx_dma_start(uhci_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.in_link[UHCI_DMA_INDEX].start = 1;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_tx_dma_start(uhci_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.out_link[UHCI_DMA_INDEX].start = 1;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_rx_dma_stop(uhci_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.in_link[UHCI_DMA_INDEX].stop = 1;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_tx_dma_stop(uhci_dev_t *hw)
|
||||
{
|
||||
(void)hw;
|
||||
GDMA.out_link[UHCI_DMA_INDEX].stop = 1;
|
||||
}
|
||||
|
||||
static inline void uhci_ll_set_eof_mode(uhci_dev_t *hw, uint32_t eof_mode)
|
||||
{
|
||||
if (eof_mode & UHCI_RX_BREAK_CHR_EOF) {
|
||||
hw->conf0.uart_rx_brk_eof_en = 1;
|
||||
}
|
||||
if (eof_mode & UHCI_RX_IDLE_EOF) {
|
||||
hw->conf0.uart_idle_eof_en = 1;
|
||||
}
|
||||
if (eof_mode & UHCI_RX_LEN_EOF) {
|
||||
hw->conf0.len_eof_en = 1;
|
||||
}
|
||||
}
|
61
components/hal/esp32c3/interrupt_descriptor_table.c
Normal file
61
components/hal/esp32c3/interrupt_descriptor_table.c
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/interrupt_controller_hal.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
// TODO ESP32-C3 IDF-2126 check this table is correct, some interrupts may be unnecessarily reserved or not reserved
|
||||
// or marked as the wrong type
|
||||
|
||||
//This is basically a software-readable version of the interrupt usage table in include/soc/soc.h
|
||||
const int_desc_t interrupt_descriptor_table[32] = {
|
||||
{ 1, INTTP_LEVEL, {INTDESC_RESVD } }, //0
|
||||
{ 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //1
|
||||
{ 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //2
|
||||
{ 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //3
|
||||
{ 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //4
|
||||
{ 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //5
|
||||
{ 1, INTTP_NA, {INTDESC_NORMAL } }, //6
|
||||
{ 1, INTTP_NA, {INTDESC_NORMAL } }, //7
|
||||
{ 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //8
|
||||
{ 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //9
|
||||
{ 1, INTTP_EDGE, {INTDESC_NORMAL } }, //10
|
||||
{ 3, INTTP_NA, {INTDESC_NORMAL } }, //11
|
||||
{ 1, INTTP_LEVEL, {INTDESC_SPECIAL } }, //12
|
||||
{ 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //13
|
||||
{ 7, INTTP_LEVEL, {INTDESC_NORMAL } }, //14
|
||||
{ 3, INTTP_NA, {INTDESC_NORMAL } }, //15
|
||||
{ 5, INTTP_NA, {INTDESC_NORMAL } }, //16
|
||||
{ 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //17
|
||||
{ 1, INTTP_LEVEL, {INTDESC_NORMAL } }, //18
|
||||
{ 2, INTTP_LEVEL, {INTDESC_NORMAL } }, //19
|
||||
{ 2, INTTP_LEVEL, {INTDESC_NORMAL } }, //20
|
||||
{ 2, INTTP_LEVEL, {INTDESC_NORMAL } }, //21
|
||||
{ 3, INTTP_EDGE, {INTDESC_NORMAL } }, //22
|
||||
{ 3, INTTP_LEVEL, {INTDESC_NORMAL } }, //23
|
||||
{ 4, INTTP_LEVEL, {INTDESC_NORMAL } }, //24
|
||||
{ 4, INTTP_LEVEL, {INTDESC_NORMAL } }, //25
|
||||
{ 5, INTTP_LEVEL, {INTDESC_NORMAL } }, //26
|
||||
{ 3, INTTP_LEVEL, {INTDESC_NORMAL } }, //27
|
||||
{ 4, INTTP_EDGE, {INTDESC_NORMAL } }, //28
|
||||
{ 3, INTTP_NA, {INTDESC_NORMAL } }, //29
|
||||
{ 4, INTTP_EDGE, {INTDESC_NORMAL } }, //30
|
||||
{ 5, INTTP_LEVEL, {INTDESC_NORMAL } }, //31
|
||||
};
|
||||
|
||||
const int_desc_t *interrupt_controller_hal_desc_table(void)
|
||||
{
|
||||
return interrupt_descriptor_table;
|
||||
}
|
123
components/hal/esp32c3/systimer_hal.c
Normal file
123
components/hal/esp32c3/systimer_hal.c
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sys/param.h>
|
||||
#include "hal/systimer_hal.h"
|
||||
#include "hal/systimer_ll.h"
|
||||
#include "hal/systimer_types.h"
|
||||
#include "soc/systimer_caps.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
|
||||
#define SYSTIMER_TICKS_PER_US (16) // Systimer clock source is fixed to 16MHz
|
||||
|
||||
uint64_t systimer_hal_get_counter_value(systimer_counter_id_t counter_id)
|
||||
{
|
||||
uint32_t lo, lo_start, hi;
|
||||
/* Set the "update" bit and wait for acknowledgment */
|
||||
systimer_ll_counter_snapshot(counter_id);
|
||||
while (!systimer_ll_is_counter_value_valid(counter_id));
|
||||
/* Read LO, HI, then LO again, check that LO returns the same value.
|
||||
* This accounts for the case when an interrupt may happen between reading
|
||||
* HI and LO values, and this function may get called from the ISR.
|
||||
* In this case, the repeated read will return consistent values.
|
||||
*/
|
||||
lo_start = systimer_ll_get_counter_value_low(counter_id);
|
||||
do {
|
||||
lo = lo_start;
|
||||
hi = systimer_ll_get_counter_value_high(counter_id);
|
||||
lo_start = systimer_ll_get_counter_value_low(counter_id);
|
||||
} while (lo_start != lo);
|
||||
|
||||
systimer_counter_value_t result = {
|
||||
.lo = lo,
|
||||
.hi = hi
|
||||
};
|
||||
|
||||
return result.val;
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_time(systimer_counter_id_t counter_id)
|
||||
{
|
||||
return systimer_hal_get_counter_value(counter_id) / SYSTIMER_TICKS_PER_US;
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_target(systimer_alarm_id_t alarm_id, uint64_t target)
|
||||
{
|
||||
systimer_counter_value_t alarm = { .val = target * SYSTIMER_TICKS_PER_US};
|
||||
systimer_ll_disable_alarm(alarm_id);
|
||||
systimer_ll_set_alarm_target(alarm_id, alarm.val);
|
||||
systimer_ll_apply_alarm_value(alarm_id);
|
||||
systimer_ll_enable_alarm(alarm_id);
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_period(systimer_alarm_id_t alarm_id, uint32_t period)
|
||||
{
|
||||
systimer_ll_disable_alarm(alarm_id);
|
||||
systimer_ll_set_alarm_period(alarm_id, period * SYSTIMER_TICKS_PER_US);
|
||||
systimer_ll_apply_alarm_value(alarm_id);
|
||||
systimer_ll_enable_alarm(alarm_id);
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_alarm_value(systimer_alarm_id_t alarm_id)
|
||||
{
|
||||
return systimer_ll_get_alarm_target(alarm_id);
|
||||
}
|
||||
|
||||
void systimer_hal_enable_alarm_int(systimer_alarm_id_t alarm_id)
|
||||
{
|
||||
systimer_ll_enable_alarm_int(alarm_id);
|
||||
}
|
||||
|
||||
void systimer_hal_on_apb_freq_update(uint32_t apb_ticks_per_us)
|
||||
{
|
||||
/* Nothing to do here, SYSTIMER clock is independent of APB clock */
|
||||
(void)apb_ticks_per_us;
|
||||
}
|
||||
|
||||
void systimer_hal_counter_value_advance(systimer_counter_id_t counter_id, int64_t time_us)
|
||||
{
|
||||
systimer_counter_value_t new_count = { .val = systimer_hal_get_counter_value(counter_id) + time_us * SYSTIMER_TICKS_PER_US };
|
||||
systimer_ll_set_counter_value(counter_id, new_count.val);
|
||||
systimer_ll_apply_counter_value(counter_id);
|
||||
}
|
||||
|
||||
void systimer_hal_enable_counter(systimer_counter_id_t counter_id)
|
||||
{
|
||||
systimer_ll_enable_counter(counter_id);
|
||||
}
|
||||
|
||||
void systimer_hal_init(void)
|
||||
{
|
||||
periph_ll_enable_clk_clear_rst(PERIPH_SYSTIMER_MODULE);
|
||||
systimer_ll_enable_clock();
|
||||
}
|
||||
|
||||
void systimer_hal_select_alarm_mode(systimer_alarm_id_t alarm_id, systimer_alarm_mode_t mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case SYSTIMER_ALARM_MODE_ONESHOT:
|
||||
systimer_ll_enable_alarm_oneshot(alarm_id);
|
||||
break;
|
||||
case SYSTIMER_ALARM_MODE_PERIOD:
|
||||
systimer_ll_enable_alarm_period(alarm_id);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void systimer_hal_connect_alarm_counter(systimer_alarm_id_t alarm_id, systimer_counter_id_t counter_id)
|
||||
{
|
||||
systimer_ll_connect_alarm_counter(alarm_id, counter_id);
|
||||
}
|
@ -40,7 +40,8 @@ extern "C" {
|
||||
#define SPI_LL_UNUSED_INT_MASK (SPI_INT_TRANS_DONE_EN | SPI_INT_WR_DMA_DONE_EN | SPI_INT_RD_DMA_DONE_EN | SPI_INT_WR_BUF_DONE_EN | SPI_INT_RD_BUF_DONE_EN)
|
||||
/// Swap the bit order to its correct place to send
|
||||
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)data<<(32-len))
|
||||
|
||||
/// This is the expected clock frequency
|
||||
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
|
||||
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3))
|
||||
|
||||
/**
|
||||
@ -198,21 +199,46 @@ static inline uint32_t spi_ll_get_running_cmd(spi_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI CPU FIFO
|
||||
* Reset SPI CPU TX FIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_cpu_fifo_reset(spi_dev_t *hw)
|
||||
static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
//This is not used in esp32s2
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA FIFO
|
||||
* Reset SPI CPU RX FIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_fifo_reset(spi_dev_t *hw)
|
||||
static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
//This is not used in esp32s2
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA TX FIFO
|
||||
*
|
||||
* On ESP32S2, this function is not seperated
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
|
||||
hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA RX FIFO
|
||||
*
|
||||
* On ESP32S2, this function is not seperated
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
|
||||
hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
|
||||
|
@ -18,7 +18,7 @@
|
||||
* See readme.md in hal/include/hal/readme.md
|
||||
******************************************************************************/
|
||||
|
||||
// The HAL layer for touch sensor (esp32s2 specific part)
|
||||
// The HAL layer for touch sensor (ESP32-S2 specific part)
|
||||
|
||||
#pragma once
|
||||
|
||||
@ -202,7 +202,7 @@ void touch_hal_filter_get_config(touch_filter_config_t *filter_info);
|
||||
* Set filter mode. The input of the filter is the raw value of touch reading,
|
||||
* and the output of the filter is involved in the judgment of the touch state.
|
||||
*
|
||||
* @param mode Filter mode type. Refer to ``touch_filter_mode_t``.
|
||||
* @param mode Filter mode type. Refer to `touch_filter_mode_t`.
|
||||
*/
|
||||
#define touch_hal_filter_set_filter_mode(mode) touch_ll_filter_set_filter_mode(mode)
|
||||
|
||||
@ -210,7 +210,7 @@ void touch_hal_filter_get_config(touch_filter_config_t *filter_info);
|
||||
* Get filter mode. The input of the filter is the raw value of touch reading,
|
||||
* and the output of the filter is involved in the judgment of the touch state.
|
||||
*
|
||||
* @param mode Filter mode type. Refer to ``touch_filter_mode_t``.
|
||||
* @param mode Filter mode type. Refer to `touch_filter_mode_t`.
|
||||
*/
|
||||
#define touch_hal_filter_get_filter_mode(mode) touch_ll_filter_get_filter_mode(mode)
|
||||
|
||||
|
@ -691,7 +691,7 @@ static inline void touch_ll_filter_get_filter_mode(touch_filter_mode_t *mode)
|
||||
* Set filter mode. The input to the filter is raw data and the output is the smooth data.
|
||||
* The smooth data is used to determine the touch status.
|
||||
*
|
||||
* @param mode Filter mode type. Refer to ``touch_smooth_mode_t``.
|
||||
* @param mode Filter mode type. Refer to `touch_smooth_mode_t`.
|
||||
*/
|
||||
static inline void touch_ll_filter_set_smooth_mode(touch_smooth_mode_t mode)
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ uint64_t systimer_hal_get_time(systimer_counter_id_t counter_id)
|
||||
return systimer_hal_get_counter_value(counter_id) / SYSTIMER_TICKS_PER_US;
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_value(systimer_alarm_id_t alarm_id, uint64_t timestamp)
|
||||
void systimer_hal_set_alarm_target(systimer_alarm_id_t alarm_id, uint64_t timestamp)
|
||||
{
|
||||
int64_t offset = SYSTIMER_TICKS_PER_US * 2;
|
||||
uint64_t now_time = systimer_hal_get_counter_value(SYSTIMER_COUNTER_0);
|
||||
|
@ -34,17 +34,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// Registers to reset during initialization. Don't use in app.
|
||||
#define SPI_LL_CPU_FIFO_RST_MASK (SPI_BUF_AFIFO_RST | SPI_RX_AFIFO_RST)
|
||||
/// Registers to reset during initialization. Don't use in app.
|
||||
#define SPI_LL_DMA_FIFO_RST_MASK (SPI_DMA_AFIFO_RST | SPI_RX_AFIFO_RST)
|
||||
|
||||
|
||||
/// Interrupt not used. Don't use in app.
|
||||
#define SPI_LL_UNUSED_INT_MASK (SPI_TRANS_DONE_INT_ENA | SPI_SLV_WR_DMA_DONE_INT_ENA | SPI_SLV_RD_DMA_DONE_INT_ENA | SPI_SLV_WR_BUF_DONE_INT_ENA | SPI_SLV_RD_BUF_DONE_INT_ENA)
|
||||
/// Swap the bit order to its correct place to send
|
||||
#define HAL_SPI_SWAP_DATA_TX(data, len) HAL_SWAP32((uint32_t)data<<(32-len))
|
||||
|
||||
/// This is the expected clock frequency
|
||||
#define SPI_LL_PERIPH_CLK_FREQ (80 * 1000000)
|
||||
#define SPI_LL_GET_HW(ID) ((ID)==0? ({abort();NULL;}):((ID)==1? &GPSPI2 : &GPSPI3))
|
||||
|
||||
/**
|
||||
@ -223,25 +218,51 @@ static inline void spi_ll_slave_reset(spi_dev_t *hw)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI CPU FIFO
|
||||
* Reset SPI CPU TX FIFO
|
||||
*
|
||||
* On ESP32S3, this function is not seperated
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_cpu_fifo_reset(spi_dev_t *hw)
|
||||
static inline void spi_ll_cpu_tx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.val |= SPI_LL_CPU_FIFO_RST_MASK;
|
||||
hw->dma_conf.val &= ~SPI_LL_CPU_FIFO_RST_MASK;
|
||||
hw->dma_conf.buf_afifo_rst = 1;
|
||||
hw->dma_conf.buf_afifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA FIFO
|
||||
* Reset SPI CPU RX FIFO
|
||||
*
|
||||
* On ESP32S3, this function is not seperated
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_fifo_reset(spi_dev_t *hw)
|
||||
static inline void spi_ll_cpu_rx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.val |= SPI_LL_DMA_FIFO_RST_MASK;
|
||||
hw->dma_conf.val &= ~SPI_LL_DMA_FIFO_RST_MASK;
|
||||
hw->dma_conf.rx_afifo_rst = 1;
|
||||
hw->dma_conf.rx_afifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA TX FIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_tx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.dma_afifo_rst = 1;
|
||||
hw->dma_conf.dma_afifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset SPI DMA RX FIFO
|
||||
*
|
||||
* @param hw Beginning address of the peripheral registers.
|
||||
*/
|
||||
static inline void spi_ll_dma_rx_fifo_reset(spi_dev_t *hw)
|
||||
{
|
||||
hw->dma_conf.rx_afifo_rst = 1;
|
||||
hw->dma_conf.rx_afifo_rst = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,13 +79,13 @@ __attribute__((always_inline)) static inline void systimer_ll_apply_counter_valu
|
||||
|
||||
/*******************alarm*************************/
|
||||
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_value(uint32_t alarm_id, uint64_t value)
|
||||
__attribute__((always_inline)) static inline void systimer_ll_set_alarm_target(uint32_t alarm_id, uint64_t value)
|
||||
{
|
||||
REG_WRITE(SYS_TIMER_SYSTIMER_TARGET0_LO_REG + alarm_id * 8, value & 0xFFFFFFFF);
|
||||
REG_WRITE(SYS_TIMER_SYSTIMER_TARGET0_HI_REG + alarm_id * 8, (value >> 32) & 0xFFFFF);
|
||||
}
|
||||
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_value(uint32_t alarm_id)
|
||||
__attribute__((always_inline)) static inline uint64_t systimer_ll_get_alarm_target(uint32_t alarm_id)
|
||||
{
|
||||
return ((uint64_t) REG_READ(SYS_TIMER_SYSTIMER_TARGET0_HI_REG + alarm_id * 8) << 32) \
|
||||
| REG_READ(SYS_TIMER_SYSTIMER_TARGET0_LO_REG + alarm_id * 8);
|
||||
|
@ -52,18 +52,26 @@ uint64_t systimer_hal_get_time(systimer_counter_id_t counter_id)
|
||||
return systimer_hal_get_counter_value(counter_id) / SYSTIMER_TICKS_PER_US;
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_value(systimer_alarm_id_t alarm_id, uint64_t timestamp)
|
||||
void systimer_hal_set_alarm_target(systimer_alarm_id_t alarm_id, uint64_t target)
|
||||
{
|
||||
systimer_counter_value_t alarm = { .val = timestamp * SYSTIMER_TICKS_PER_US};
|
||||
systimer_counter_value_t alarm = { .val = target * SYSTIMER_TICKS_PER_US};
|
||||
systimer_ll_disable_alarm(alarm_id);
|
||||
systimer_ll_set_alarm_value(alarm_id, alarm.val);
|
||||
systimer_ll_set_alarm_target(alarm_id, alarm.val);
|
||||
systimer_ll_apply_alarm_value(alarm_id);
|
||||
systimer_ll_enable_alarm(alarm_id);
|
||||
}
|
||||
|
||||
void systimer_hal_set_alarm_period(systimer_alarm_id_t alarm_id, uint32_t period)
|
||||
{
|
||||
systimer_ll_disable_alarm(alarm_id);
|
||||
systimer_ll_set_alarm_period(alarm_id, period * SYSTIMER_TICKS_PER_US);
|
||||
systimer_ll_apply_alarm_value(alarm_id);
|
||||
systimer_ll_enable_alarm(alarm_id);
|
||||
}
|
||||
|
||||
uint64_t systimer_hal_get_alarm_value(systimer_alarm_id_t alarm_id)
|
||||
{
|
||||
return systimer_ll_get_alarm_value(alarm_id);
|
||||
return systimer_ll_get_alarm_target(alarm_id);
|
||||
}
|
||||
|
||||
void systimer_hal_enable_alarm_int(systimer_alarm_id_t alarm_id)
|
||||
|
@ -129,7 +129,7 @@ typedef struct {
|
||||
- 1: 10 bit;
|
||||
- 2: 11 bit;
|
||||
- 3: 12 bit. */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#else
|
||||
uint8_t reserved: 2; /*!< reserved0 */
|
||||
#endif
|
||||
uint8_t channel: 4; /*!< ADC channel index. */
|
||||
@ -238,7 +238,7 @@ typedef struct {
|
||||
adc_digi_pattern_table_t *adc2_pattern; /*!<Refer to `adc1_pattern` */
|
||||
adc_digi_convert_mode_t conv_mode; /*!<ADC conversion mode for digital controller. See ``adc_digi_convert_mode_t``. */
|
||||
adc_digi_output_format_t format; /*!<ADC output data format for digital controller. See ``adc_digi_output_format_t``. */
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t interval; /*!<The number of interval clock cycles for the digital controller to trigger the measurement.
|
||||
The unit is the divided clock. Range: 40 ~ 4095.
|
||||
Expression: `trigger_meas_freq` = `controller_clk` / 2 / interval. Refer to ``adc_digi_clk_t``.
|
||||
@ -251,7 +251,8 @@ typedef struct {
|
||||
#endif
|
||||
} adc_digi_config_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
/**
|
||||
* @brief ADC arbiter work mode option.
|
||||
*
|
||||
|
@ -158,12 +158,13 @@ typedef enum {
|
||||
GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
|
||||
GPIO_NUM_20 = 20, /*!< GPIO20, input and output */
|
||||
GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
|
||||
#if SOC_GPIO_PIN_COUNT > 22
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
GPIO_NUM_22 = 22, /*!< GPIO22, input and output */
|
||||
GPIO_NUM_23 = 23, /*!< GPIO23, input and output */
|
||||
|
||||
GPIO_NUM_25 = 25, /*!< GPIO25, input and output */
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
/* Note: The missing IO is because it is used inside the chip. */
|
||||
GPIO_NUM_26 = 26, /*!< GPIO26, input and output */
|
||||
GPIO_NUM_27 = 27, /*!< GPIO27, input and output */
|
||||
@ -179,6 +180,7 @@ typedef enum {
|
||||
GPIO_NUM_37 = 37, /*!< GPIO37, input mode only(ESP32) / input and output(ESP32-S2) */
|
||||
GPIO_NUM_38 = 38, /*!< GPIO38, input mode only(ESP32) / input and output(ESP32-S2) */
|
||||
GPIO_NUM_39 = 39, /*!< GPIO39, input mode only(ESP32) / input and output(ESP32-S2) */
|
||||
#endif // SOC_GPIO_PIN_COUNT > 22
|
||||
#if SOC_GPIO_PIN_COUNT > 40
|
||||
GPIO_NUM_40 = 40, /*!< GPIO40, input and output */
|
||||
GPIO_NUM_41 = 41, /*!< GPIO41, input and output */
|
||||
@ -187,7 +189,7 @@ typedef enum {
|
||||
GPIO_NUM_44 = 44, /*!< GPIO44, input and output */
|
||||
GPIO_NUM_45 = 45, /*!< GPIO45, input and output */
|
||||
GPIO_NUM_46 = 46, /*!< GPIO46, input mode only */
|
||||
#endif
|
||||
#endif // GPIO_PIN_COUNT > 40
|
||||
GPIO_NUM_MAX,
|
||||
/** @endcond */
|
||||
} gpio_num_t;
|
||||
|
@ -52,7 +52,7 @@ __attribute__((pure)) int interrupt_controller_hal_desc_level(int interrupt_num
|
||||
* @param cpu_number CPU number between 0 and SOC_CPU_CORES_NUM - 1
|
||||
* @return flags for that interrupt number
|
||||
*/
|
||||
__attribute__((pure)) uint32_t interrupt_controller_hal_desc_flags(int interrupt_number, int cpu_number);
|
||||
__attribute__((pure)) int_desc_flag_t interrupt_controller_hal_desc_flags(int interrupt_number, int cpu_number);
|
||||
|
||||
/**
|
||||
* @brief Gets the interrupt type given an interrupt number.
|
||||
|
@ -84,8 +84,10 @@ typedef enum {
|
||||
LEDC_CHANNEL_3, /*!< LEDC channel 3 */
|
||||
LEDC_CHANNEL_4, /*!< LEDC channel 4 */
|
||||
LEDC_CHANNEL_5, /*!< LEDC channel 5 */
|
||||
#if SOC_LEDC_CHANNEL_NUM > 6
|
||||
LEDC_CHANNEL_6, /*!< LEDC channel 6 */
|
||||
LEDC_CHANNEL_7, /*!< LEDC channel 7 */
|
||||
#endif
|
||||
LEDC_CHANNEL_MAX,
|
||||
} ledc_channel_t;
|
||||
|
||||
@ -104,12 +106,14 @@ typedef enum {
|
||||
LEDC_TIMER_12_BIT, /*!< LEDC PWM duty resolution of 12 bits */
|
||||
LEDC_TIMER_13_BIT, /*!< LEDC PWM duty resolution of 13 bits */
|
||||
LEDC_TIMER_14_BIT, /*!< LEDC PWM duty resolution of 14 bits */
|
||||
#if SOC_LEDC_TIMER_BIT_WIDE_NUM > 14
|
||||
LEDC_TIMER_15_BIT, /*!< LEDC PWM duty resolution of 15 bits */
|
||||
LEDC_TIMER_16_BIT, /*!< LEDC PWM duty resolution of 16 bits */
|
||||
LEDC_TIMER_17_BIT, /*!< LEDC PWM duty resolution of 17 bits */
|
||||
LEDC_TIMER_18_BIT, /*!< LEDC PWM duty resolution of 18 bits */
|
||||
LEDC_TIMER_19_BIT, /*!< LEDC PWM duty resolution of 19 bits */
|
||||
LEDC_TIMER_20_BIT, /*!< LEDC PWM duty resolution of 20 bits */
|
||||
#endif
|
||||
LEDC_TIMER_BIT_MAX,
|
||||
} ledc_timer_bit_t;
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/rtc_io_ll.h"
|
||||
#include <esp_err.h>
|
||||
|
||||
@ -38,6 +39,8 @@ extern "C" {
|
||||
*/
|
||||
#define rtcio_hal_function_select(rtcio_num, func) rtcio_ll_function_select(rtcio_num, func)
|
||||
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
/**
|
||||
* Enable rtcio output.
|
||||
*
|
||||
@ -164,6 +167,10 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
|
||||
*/
|
||||
#define rtcio_hal_pulldown_disable(rtcio_num) rtcio_ll_pulldown_disable(rtcio_num)
|
||||
|
||||
#endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
#if SOC_RTCIO_HOLD_SUPPORTED
|
||||
|
||||
/**
|
||||
* Enable force hold function for RTC IO pad.
|
||||
*
|
||||
@ -204,6 +211,10 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
|
||||
*/
|
||||
#define rtcio_hal_unhold_all() rtcio_ll_force_unhold_all()
|
||||
|
||||
#endif // SOC_RTCIO_HOLD_SUPPORTED
|
||||
|
||||
#if SOC_RTCIO_WAKE_SUPPORTED
|
||||
|
||||
/**
|
||||
* Enable wakeup function and set wakeup type from light sleep status for rtcio.
|
||||
*
|
||||
@ -227,6 +238,10 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
|
||||
*/
|
||||
#define rtcio_hal_ext0_set_wakeup_pin(rtcio_num, level) rtcio_ll_ext0_set_wakeup_pin(rtcio_num, level)
|
||||
|
||||
#endif
|
||||
|
||||
#if SOC_RTCIO_HOLD_SUPPORTED || SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
/**
|
||||
* Helper function to disconnect internal circuits from an RTC IO
|
||||
* This function disables input, output, pullup, pulldown, and enables
|
||||
@ -242,6 +257,8 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode);
|
||||
*/
|
||||
void rtcio_hal_isolate(int rtc_num);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -26,6 +26,9 @@ typedef SHA_TYPE esp_sha_type;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/sha.h"
|
||||
typedef SHA_TYPE esp_sha_type;
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/sha.h"
|
||||
typedef SHA_TYPE esp_sha_type;
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -49,8 +49,8 @@ FLAG_ATTR(spi_event_t)
|
||||
#define SPI_HOST SPI1_HOST
|
||||
#define HSPI_HOST SPI2_HOST
|
||||
#define VSPI_HOST SPI3_HOST
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master and SPI Slave driver on ESP32-S2
|
||||
#else // !CONFIG_IDF_TARGET_ESP32
|
||||
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master and SPI Slave driver on ESP32-S2 and later
|
||||
#define SPI_HOST SPI1_HOST
|
||||
#define FSPI_HOST SPI2_HOST
|
||||
#define HSPI_HOST SPI3_HOST
|
||||
|
@ -36,10 +36,15 @@ uint64_t systimer_hal_get_counter_value(systimer_counter_id_t counter_id);
|
||||
*/
|
||||
uint64_t systimer_hal_get_time(systimer_counter_id_t counter_id);
|
||||
|
||||
/**
|
||||
* @brief set alarm time
|
||||
/*
|
||||
* @brief set alarm target value (used in one-shot mode)
|
||||
*/
|
||||
void systimer_hal_set_alarm_value(systimer_alarm_id_t alarm_id, uint64_t timestamp);
|
||||
void systimer_hal_set_alarm_target(systimer_alarm_id_t alarm_id, uint64_t target);
|
||||
|
||||
/**
|
||||
* @brief set alarm period value (used in period mode)
|
||||
*/
|
||||
void systimer_hal_set_alarm_period(systimer_alarm_id_t alarm_id, uint32_t period);
|
||||
|
||||
/**
|
||||
* @brief get alarm time
|
||||
|
@ -132,7 +132,9 @@ typedef enum {
|
||||
#define TOUCH_TRIGGER_MODE_DEFAULT (TOUCH_TRIGGER_BELOW) /*!<Interrupts can be triggered if sensor value gets below or above threshold */
|
||||
#define TOUCH_TRIGGER_SOURCE_DEFAULT (TOUCH_TRIGGER_SOURCE_SET1) /*!<The wakeup trigger source can be SET1 or both SET1 and SET2 */
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#endif // CONFIG_IDF_TARGET ESP32
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* Excessive total time will slow down the touch response.
|
||||
* Too small measurement time will not be sampled enough, resulting in inaccurate measurements.
|
||||
@ -146,9 +148,6 @@ typedef enum {
|
||||
The timer frequency is 8Mhz.
|
||||
Recommended typical value: Modify this value to make the measurement time around 1ms.
|
||||
Range: 0 ~ 0xffff */
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_INTR_MASK_DONE = BIT(0), /*!<Measurement done for one of the enabled channels. */
|
||||
@ -287,4 +286,4 @@ typedef struct {
|
||||
bool en_proximity; /*!<enable proximity function for sleep pad */
|
||||
} touch_pad_sleep_channel_t;
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
#endif // !CONFIG_IDF_TARGET_ESP32
|
||||
|
@ -16,6 +16,8 @@
|
||||
|
||||
#include "hal/rtc_io_hal.h"
|
||||
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
void rtcio_hal_set_direction(int rtcio_num, rtc_gpio_mode_t mode)
|
||||
{
|
||||
switch (mode) {
|
||||
@ -90,3 +92,5 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -101,9 +101,11 @@ static inline void sha_hal_dma_init(lldesc_t *input)
|
||||
|
||||
gdma_ll_tx_connect_to_periph(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, DMA_PERIPH_SHA);
|
||||
|
||||
#if SOC_GDMA_SUPPORT_EXTMEM
|
||||
/* Atleast 40 bytes when accessing external RAM */
|
||||
gdma_ll_tx_extend_fifo_size_to(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, 40);
|
||||
gdma_ll_tx_set_block_size_psram(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, GDMA_OUT_EXT_MEM_BK_SIZE_16B);
|
||||
#endif //SOC_GDMA_SUPPORT_EXTMEM
|
||||
|
||||
/* Set descriptors */
|
||||
gdma_ll_tx_set_desc_addr(&GDMA, SOC_GDMA_SHA_DMA_CHANNEL, (uint32_t)input);
|
||||
|
@ -42,7 +42,7 @@ static const spi_flash_hal_clock_config_t spi_flash_clk_cfg_reg[ESP_FLASH_SPEED_
|
||||
{1, SPI_FLASH_LL_CLKREG_VAL_80MHZ},
|
||||
};
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
static const spi_flash_hal_clock_config_t spi_flash_gpspi_clk_cfg_reg[ESP_FLASH_SPEED_MAX] = {
|
||||
{16, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_5MHZ}},
|
||||
{8, {.gpspi=GPSPI_FLASH_LL_CLKREG_VAL_10MHZ}},
|
||||
|
@ -11,6 +11,19 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifndef CONFIG_SPI_FLASH_NEW_ROM_API
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
// - SPI1~3 on ESP32
|
||||
// The common part is in spi_flash_hal_common.inc
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
// - SPI1~3 on ESP32
|
||||
// The common part is in spi_flash_hal_common.inc
|
||||
|
||||
// HAL for
|
||||
// - MEMSPI
|
||||
@ -74,12 +87,12 @@ bool spi_flash_hal_host_idle(spi_flash_host_inst_t *host)
|
||||
if ((void*) dev == spi_flash_ll_get_hw(SPI_HOST)) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
idle &= spi_flash_ll_host_idle(&SPI0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
idle &= spi_flash_ll_host_idle(&SPIMEM0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#else
|
||||
idle &= spi_flash_ll_host_idle(&SPIMEM0);
|
||||
#endif
|
||||
}
|
||||
|
||||
return idle;
|
||||
}
|
||||
|
||||
#endif // !CONFIG_SPI_FLASH_NEW_ROM_API
|
||||
|
@ -81,7 +81,7 @@ esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, int
|
||||
{
|
||||
spi_hal_timing_conf_t temp_conf;
|
||||
|
||||
int eff_clk_n = spi_ll_master_cal_clock(APB_CLK_FREQ, timing_param->clock_speed_hz, timing_param->duty_cycle, &temp_conf.clock_reg);
|
||||
int eff_clk_n = spi_ll_master_cal_clock(SPI_LL_PERIPH_CLK_FREQ, timing_param->clock_speed_hz, timing_param->duty_cycle, &temp_conf.clock_reg);
|
||||
|
||||
//When the speed is too fast, we may need to use dummy cycles to compensate the reading.
|
||||
//But these don't work for full-duplex connections.
|
||||
|
@ -138,8 +138,6 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
|
||||
{
|
||||
spi_dev_t *hw = hal->hw;
|
||||
|
||||
spi_ll_dma_fifo_reset(hal->hw);
|
||||
|
||||
//Fill DMA descriptors
|
||||
if (trans->rcv_buffer) {
|
||||
if (!hal->dma_enabled) {
|
||||
@ -148,7 +146,7 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
|
||||
lldesc_setup_link(hal->dma_config.dmadesc_rx, trans->rcv_buffer, ((trans->rx_bitlen + 7) / 8), true);
|
||||
|
||||
spi_dma_ll_rx_reset(hal->dma_in);
|
||||
|
||||
spi_ll_dma_rx_fifo_reset(hal->dma_in);
|
||||
spi_ll_dma_rx_enable(hal->hw, 1);
|
||||
spi_dma_ll_rx_start(hal->dma_in, hal->dma_config.dmadesc_rx);
|
||||
}
|
||||
@ -169,7 +167,7 @@ void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *de
|
||||
lldesc_setup_link(hal->dma_config.dmadesc_tx, trans->send_buffer, (trans->tx_bitlen + 7) / 8, false);
|
||||
|
||||
spi_dma_ll_tx_reset(hal->dma_out);
|
||||
|
||||
spi_ll_dma_tx_fifo_reset(hal->dma_in);
|
||||
spi_ll_dma_tx_enable(hal->hw, 1);
|
||||
spi_dma_ll_tx_start(hal->dma_out, hal->dma_config.dmadesc_tx);
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ void spi_slave_hal_user_start(const spi_slave_hal_context_t *hal)
|
||||
void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
|
||||
{
|
||||
if (hal->use_dma) {
|
||||
spi_ll_dma_fifo_reset(hal->hw);
|
||||
|
||||
//Fill DMA descriptors
|
||||
if (hal->rx_buffer) {
|
||||
@ -41,6 +40,7 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
|
||||
|
||||
//reset dma inlink, this should be reset before spi related reset
|
||||
spi_dma_ll_rx_reset(hal->dma_in);
|
||||
spi_ll_dma_rx_fifo_reset(hal->dma_in);
|
||||
spi_ll_slave_reset(hal->hw);
|
||||
spi_ll_infifo_full_clr(hal->hw);
|
||||
|
||||
@ -49,9 +49,9 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
|
||||
}
|
||||
if (hal->tx_buffer) {
|
||||
lldesc_setup_link(hal->dmadesc_tx, hal->tx_buffer, (hal->bitlen + 7) / 8, false);
|
||||
|
||||
//reset dma outlink, this should be reset before spi related reset
|
||||
spi_dma_ll_tx_reset(hal->dma_out);
|
||||
spi_ll_dma_tx_fifo_reset(hal->dma_out);
|
||||
spi_ll_slave_reset(hal->hw);
|
||||
spi_ll_outfifo_empty_clr(hal->hw);
|
||||
|
||||
@ -65,7 +65,7 @@ void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal)
|
||||
spi_ll_write_buffer(hal->hw, hal->tx_buffer, hal->bitlen);
|
||||
}
|
||||
|
||||
spi_ll_cpu_fifo_reset(hal->hw);
|
||||
spi_ll_cpu_tx_fifo_reset(hal->hw);
|
||||
}
|
||||
|
||||
spi_ll_slave_set_rx_bitlen(hal->hw, hal->bitlen);
|
||||
|
@ -106,7 +106,7 @@ void spi_slave_hd_hal_rxdma(spi_slave_hd_hal_context_t *hal, uint8_t *out_buf, s
|
||||
{
|
||||
lldesc_setup_link(hal->dmadesc_rx, out_buf, len, true);
|
||||
|
||||
spi_ll_dma_fifo_reset(hal->dev);
|
||||
spi_ll_dma_rx_fifo_reset(hal->dev);
|
||||
spi_dma_ll_rx_reset(hal->dma_in);
|
||||
spi_ll_slave_reset(hal->dev);
|
||||
spi_ll_infifo_full_clr(hal->dev);
|
||||
@ -121,7 +121,7 @@ void spi_slave_hd_hal_txdma(spi_slave_hd_hal_context_t *hal, uint8_t *data, size
|
||||
{
|
||||
lldesc_setup_link(hal->dmadesc_tx, data, len, false);
|
||||
|
||||
spi_ll_dma_fifo_reset(hal->dev);
|
||||
spi_ll_dma_tx_fifo_reset(hal->dev);
|
||||
spi_dma_ll_tx_reset(hal->dma_out);
|
||||
spi_ll_slave_reset(hal->dev);
|
||||
spi_ll_outfifo_empty_clr(hal->dev);
|
||||
|
@ -69,9 +69,11 @@ void wdt_hal_init(wdt_hal_context_t *hal, wdt_inst_t wdt_inst, uint32_t prescale
|
||||
mwdt_ll_disable_stage(hal->mwdt_dev, 1);
|
||||
mwdt_ll_disable_stage(hal->mwdt_dev, 2);
|
||||
mwdt_ll_disable_stage(hal->mwdt_dev, 3);
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
//Enable or disable level interrupt. Edge interrupt is always disabled.
|
||||
mwdt_ll_set_edge_intr(hal->mwdt_dev, false);
|
||||
mwdt_ll_set_level_intr(hal->mwdt_dev, enable_intr);
|
||||
#endif
|
||||
mwdt_ll_clear_intr_status(hal->mwdt_dev);
|
||||
mwdt_ll_set_intr_enable(hal->mwdt_dev, enable_intr);
|
||||
//Set default values
|
||||
|
Loading…
Reference in New Issue
Block a user