1_SDIO
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "soc/sdmmc_periph.h"
#include "soc/sdio_slave_periph.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_serial_slave_link/essl_sdio.h"
#include "sdkconfig.h"
#include "driver/sdmmc_host.h"
#include "driver/sdspi_host.h"
#define TIMEOUT_MAX UINT32_MAX
#define GPIO_B1 21
#if CONFIG_EXAMPLE_SLAVE_B1
#define SLAVE_PWR_GPIO GPIO_B1
#endif
#define WRITE_BUFFER_LEN 4096
#define READ_BUFFER_LEN 4096
#define SLAVE_BUFFER_SIZE 128
static const char TAG[] = "example_host";
#define SDIO_INTERRUPT_LINE GPIO_NUM_4
#define SLAVE_INTR_NOTIFY 0
#define SLAVE_REG_JOB 0
#define SLAVE_REG_VALUE 1
typedef enum {
JOB_IDLE = 0,
JOB_RESET = 1,
JOB_SEND_INT = 2,
JOB_WRITE_REG = 4,
} example_job_t;
esp_err_t slave_reset(essl_handle_t handle)
{
esp_err_t ret;
ESP_LOGI(TAG, "send reset to slave...");
ret = essl_write_reg(handle, 0, JOB_RESET, NULL, TIMEOUT_MAX);
if (ret != ESP_OK) {
return ret;
}
ret = essl_send_slave_intr(handle, BIT(SLAVE_INTR_NOTIFY), TIMEOUT_MAX);
if (ret != ESP_OK) {
return ret;
}
vTaskDelay(500 / portTICK_PERIOD_MS);
ret = essl_wait_for_ready(handle, TIMEOUT_MAX);
ESP_LOGI(TAG, "slave io ready");
return ret;
}
#ifdef CONFIG_EXAMPLE_SDIO_OVER_SPI
static void gpio_d2_set_high(void)
{
gpio_config_t d2_config = {
.pin_bit_mask = BIT64(SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = true,
};
gpio_config(&d2_config);
gpio_set_level(SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2, 1);
}
#endif
static esp_err_t print_sdio_cis_information(sdmmc_card_t* card)
{
const size_t cis_buffer_size = 256;
uint8_t cis_buffer[cis_buffer_size];
size_t cis_data_len = 1024;
esp_err_t ret = ESP_OK;
ret = sdmmc_io_get_cis_data(card, cis_buffer, cis_buffer_size, &cis_data_len);
if (ret == ESP_ERR_INVALID_SIZE) {
int temp_buf_size = cis_data_len;
uint8_t* temp_buf = malloc(temp_buf_size);
assert(temp_buf);
ESP_LOGW(TAG, "CIS data longer than expected, temporary buffer allocated.");
ret = sdmmc_io_get_cis_data(card, temp_buf, temp_buf_size, &cis_data_len);
ESP_ERROR_CHECK(ret);
sdmmc_io_print_cis_info(temp_buf, cis_data_len, NULL);
free(temp_buf);
} else if (ret == ESP_OK) {
sdmmc_io_print_cis_info(cis_buffer, cis_data_len, NULL);
} else {
ESP_LOGE(TAG, "failed to get the entire CIS data.");
abort();
}
return ESP_OK;
}
esp_err_t slave_init(essl_handle_t* handle)
{
esp_err_t err;
#ifndef CONFIG_EXAMPLE_SDIO_OVER_SPI
sdmmc_host_t config = SDMMC_HOST_DEFAULT();
#ifdef CONFIG_EXAMPLE_SDIO_4BIT
ESP_LOGI(TAG, "Probe using SD 4-bit...\n");
config.flags = SDMMC_HOST_FLAG_4BIT;
#else
ESP_LOGI(TAG, "Probe using SD 1-bit...\n");
config.flags = SDMMC_HOST_FLAG_1BIT;
#endif
#ifdef CONFIG_EXAMPLE_SDIO_HIGHSPEED
config.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
#else
config.max_freq_khz = SDMMC_FREQ_DEFAULT;
#endif
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
err = sdmmc_host_init();
ESP_ERROR_CHECK(err);
err = sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config);
ESP_ERROR_CHECK(err);
#else
sdspi_device_config_t dev_config = SDSPI_DEVICE_CONFIG_DEFAULT();
dev_config.gpio_cs = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3;
dev_config.gpio_int = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1;
err = gpio_install_isr_service(0);
ESP_ERROR_CHECK(err);
spi_bus_config_t bus_config = {
.mosi_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD,
.miso_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0,
.sclk_io_num = SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 4000,
};
err = spi_bus_initialize(dev_config.host_id, &bus_config, 1);
ESP_ERROR_CHECK(err);
sdspi_device_handle_t sdspi_handle;
err = sdspi_host_init();
ESP_ERROR_CHECK(err);
err = sdspi_host_init_device(&slot_config, &sdspi_handle);
ESP_ERROR_CHECK(err);
ESP_LOGI(TAG, "Probe using SPI...\n");
sdmmc_host_t config = SDSPI_HOST_DEFAULT();
config.slot = sdspi_handle;
gpio_d2_set_high();
#endif
sdmmc_card_t *card = (sdmmc_card_t *)malloc(sizeof(sdmmc_card_t));
if (card == NULL) {
return ESP_ERR_NO_MEM;
}
for (;;) {
if (sdmmc_card_init(&config, card) == ESP_OK) {
break;
}
ESP_LOGW(TAG, "slave init failed, retry...");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
sdmmc_card_print_info(stdout, card);
gpio_pullup_en(14);
gpio_pulldown_dis(14);
gpio_pullup_en(15);
gpio_pulldown_dis(15);
gpio_pullup_en(2);
gpio_pulldown_dis(2);
gpio_pullup_en(4);
gpio_pulldown_dis(4);
gpio_pullup_en(12);
gpio_pulldown_dis(12);
gpio_pullup_en(13);
gpio_pulldown_dis(13);
essl_sdio_config_t ser_config = {
.card = card,
.recv_buffer_size = SLAVE_BUFFER_SIZE,
};
err = essl_sdio_init_dev(handle, &ser_config);
ESP_ERROR_CHECK(err);
esp_err_t ret = essl_init(*handle, TIMEOUT_MAX);
ESP_ERROR_CHECK(ret);
ret = print_sdio_cis_information(card);
ESP_ERROR_CHECK(ret);
return ret;
}
void slave_power_on(void)
{
#ifdef SLAVE_PWR_GPIO
int level_active;
#ifdef CONFIG_EXAMPLE_SLAVE_PWR_NEGTIVE_ACTIVE
level_active = 0;
#else
level_active = 1;
#endif
gpio_config_t cfg = {
.pin_bit_mask = BIT64(GPIO_B1),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = false,
.pull_down_en = false,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&cfg);
gpio_set_level(GPIO_B1, !level_active);
vTaskDelay(100);
gpio_set_level(SLAVE_PWR_GPIO, level_active);
vTaskDelay(100);
#endif
}
DMA_ATTR uint8_t rcv_buffer[READ_BUFFER_LEN];
static esp_err_t get_intr(essl_handle_t handle, uint32_t* out_raw, uint32_t* out_st)
{
esp_err_t ret = ESP_OK;
#ifndef CONFIG_EXAMPLE_NO_INTR_LINE
ret = essl_wait_int(handle, 0);
if (ret != ESP_OK) {
return ret;
}
#endif
ret = essl_get_intr(handle, out_raw, out_st, TIMEOUT_MAX);
if (ret != ESP_OK) return ret;
ret = essl_clear_intr(handle, *out_raw, TIMEOUT_MAX);
if (ret != ESP_OK) return ret;
ESP_LOGD(TAG, "intr: %08"PRIX32, *out_raw);
return ESP_OK;
}
esp_err_t process_event(essl_handle_t handle)
{
uint32_t intr_raw, intr_st;
esp_err_t ret = get_intr(handle, &intr_raw, &intr_st);
if (ret == ESP_ERR_TIMEOUT) {
return ret;
}
ESP_ERROR_CHECK(ret);
for (int i = 0; i < 8; i++) {
if (intr_raw & BIT(i)) {
ESP_LOGI(TAG, "host int: %d", i);
}
}
const int wait_ms = 50;
if (intr_raw & HOST_SLC0_RX_NEW_PACKET_INT_ST) {
ESP_LOGD(TAG, "new packet coming");
while (1) {
size_t size_read = READ_BUFFER_LEN;
ret = essl_get_packet(handle, rcv_buffer, READ_BUFFER_LEN, &size_read, wait_ms);
if (ret == ESP_ERR_NOT_FOUND) {
ESP_LOGE(TAG, "interrupt but no data can be read");
break;
} else if (ret != ESP_OK && ret != ESP_ERR_NOT_FINISHED) {
ESP_LOGE(TAG, "rx packet error: %08X", ret);
return ret;
}
ESP_LOGI(TAG, "receive data, size: %d", size_read);
ESP_LOG_BUFFER_HEXDUMP(TAG, rcv_buffer, size_read, ESP_LOG_INFO);
if (ret == ESP_OK) {
break;
}
}
}
return ESP_OK;
}
static inline esp_err_t slave_inform_job(essl_handle_t handle, example_job_t job)
{
esp_err_t ret;
ret = essl_write_reg(handle, SLAVE_REG_JOB, job, NULL, TIMEOUT_MAX);
ESP_ERROR_CHECK(ret);
ret = essl_send_slave_intr(handle, BIT(SLAVE_INTR_NOTIFY), TIMEOUT_MAX);
ESP_ERROR_CHECK(ret);
return ret;
}
void job_write_reg(essl_handle_t handle, int value)
{
esp_err_t ret;
uint8_t reg_read[60];
ESP_LOGI(TAG, "========JOB: write slave reg========");
ret = essl_write_reg(handle, SLAVE_REG_VALUE, value, NULL, TIMEOUT_MAX);
ESP_ERROR_CHECK(ret);
ret = slave_inform_job(handle, JOB_WRITE_REG);
ESP_ERROR_CHECK(ret);
vTaskDelay(10);
for (int i = 0; i < 60; i++) {
ESP_LOGD(TAG, "reading register %d", i);
ret = essl_read_reg(handle, i, ®_read[i], TIMEOUT_MAX);
ESP_ERROR_CHECK(ret);
}
ESP_LOGI(TAG, "read registers:");
ESP_LOG_BUFFER_HEXDUMP(TAG, reg_read, 64, ESP_LOG_INFO);
}
int packet_len[] = {6, 12, 1024, 512, 3, 513, 517};
DMA_ATTR uint8_t send_buffer[READ_BUFFER_LEN];
void job_fifo(essl_handle_t handle)
{
for (int i = 0; i < READ_BUFFER_LEN; i++) {
send_buffer[i] = 0x46 + i * 5;
}
esp_err_t ret;
int pointer = 0;
ESP_LOGI(TAG, "========JOB: send fifos========");
for (int i = 0; i < sizeof(packet_len) / sizeof(int); i++) {
const int wait_ms = 50;
int length = packet_len[i];
ret = essl_send_packet(handle, send_buffer + pointer, length, wait_ms);
if (ret == ESP_ERR_TIMEOUT) {
ESP_LOGD(TAG, "several packets are expected to timeout.");
} else {
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "send packet length: %d", length);
}
pointer += (length + 3) & (~3);
}
}
void job_getint(essl_handle_t handle)
{
ESP_LOGI(TAG, "========JOB: get interrupts from slave========");
slave_inform_job(handle, JOB_SEND_INT);
}
void app_main(void)
{
essl_handle_t handle;
esp_err_t err;
slave_power_on();
ESP_LOGI(TAG, "host ready, start initializing slave...");
err = slave_init(&handle);
ESP_ERROR_CHECK(err);
err = slave_reset(handle);
ESP_ERROR_CHECK(err);
uint32_t start, end;
job_write_reg(handle, 10);
int times = 2;
while (1) {
job_getint(handle);
start = xTaskGetTickCount();
while (1) {
process_event(handle);
vTaskDelay(1);
end = xTaskGetTickCount();
if ((end - start) * 1000 / CONFIG_FREERTOS_HZ > 5000) {
break;
}
}
if (--times == 0) {
break;
}
};
while (1) {
job_fifo(handle);
start = xTaskGetTickCount();
while (1) {
process_event(handle);
vTaskDelay(1);
end = xTaskGetTickCount();
if ((end - start) * 1000 / CONFIG_FREERTOS_HZ > 2000) {
break;
}
}
}
}
2_分区表
3_I2S
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
/* I2C port and GPIOs */
/* I2S port and GPIOs */
/* Example configurations */
static const char *TAG = "i2s_es8311"
static const char err_reason[][30] = {"input param is invalid",
"operation timeout"
}
static i2s_chan_handle_t tx_handle = NULL
static i2s_chan_handle_t rx_handle = NULL
/* Import music file as buffer */
extern const uint8_t music_pcm_start[] asm("_binary_canon_pcm_start")
extern const uint8_t music_pcm_end[] asm("_binary_canon_pcm_end")
static esp_err_t es8311_codec_init(void)
{
/* Initialize I2C peripheral */
i2c_config_t es_i2c_cfg = {
.sda_io_num = I2C_SDA_IO,
.scl_io_num = I2C_SCL_IO,
.mode = I2C_MODE_MASTER,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000,
}
ESP_RETURN_ON_ERROR(i2c_param_config(I2C_NUM, &es_i2c_cfg), TAG, "config i2c failed")
ESP_RETURN_ON_ERROR(i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0), TAG, "install i2c driver failed")
/* Initialize es8311 codec */
es8311_handle_t es_handle = es8311_create(I2C_NUM, ES8311_ADDRRES_0)
ESP_RETURN_ON_FALSE(es_handle, ESP_FAIL, TAG, "es8311 create failed")
es8311_clock_config_t es_clk = {
.mclk_inverted = false,
.sclk_inverted = false,
.mclk_from_mclk_pin = true,
.mclk_frequency = EXAMPLE_MCLK_FREQ_HZ,
.sample_frequency = EXAMPLE_SAMPLE_RATE
}
ESP_ERROR_CHECK(es8311_init(es_handle, &es_clk, ES8311_RESOLUTION_16, ES8311_RESOLUTION_16))
ESP_RETURN_ON_ERROR(es8311_sample_frequency_config(es_handle, EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE, EXAMPLE_SAMPLE_RATE), TAG, "set es8311 sample frequency failed")
ESP_RETURN_ON_ERROR(es8311_voice_volume_set(es_handle, EXAMPLE_VOICE_VOLUME, NULL), TAG, "set es8311 volume failed")
ESP_RETURN_ON_ERROR(es8311_microphone_config(es_handle, false), TAG, "set es8311 microphone failed")
ESP_RETURN_ON_ERROR(es8311_microphone_gain_set(es_handle, EXAMPLE_MIC_GAIN), TAG, "set es8311 microphone gain faield")
return ESP_OK
}
static esp_err_t i2s_driver_init(void)
{
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER)
chan_cfg.auto_clear = true
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle))
i2s_std_config_t std_cfg = {
.clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(EXAMPLE_SAMPLE_RATE),
.slot_cfg = I2S_STD_PHILIP_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO),
.gpio_cfg = {
.mclk = I2S_MCK_IO,
.bclk = I2S_BCK_IO,
.ws = I2S_WS_IO,
.dout = I2S_DO_IO,
.din = I2S_DI_IO,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
},
},
}
std_cfg.clk_cfg.mclk_multiple = EXAMPLE_MCLK_MULTIPLE
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg))
ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg))
ESP_ERROR_CHECK(i2s_channel_enable(tx_handle))
ESP_ERROR_CHECK(i2s_channel_enable(rx_handle))
return ESP_OK
}
static void i2s_music(void *args)
{
esp_err_t ret = ESP_OK
size_t bytes_write = 0
while (1) {
/* Write music to earphone */
ret = i2s_channel_write(tx_handle, music_pcm_start, music_pcm_end - music_pcm_start, &bytes_write, portMAX_DELAY)
if (ret != ESP_OK) {
/* Since we set timeout to 'portMAX_DELAY' in 'i2s_channel_write'
so you won't reach here unless you set other timeout value,
if timeout detected, it means write operation failed. */
ESP_LOGE(TAG, "[music] i2s write failed, %s", err_reason[ret == ESP_ERR_TIMEOUT])
abort()
}
if (bytes_write > 0) {
ESP_LOGI(TAG, "[music] i2s music played, %d bytes are written.", bytes_write)
} else {
ESP_LOGE(TAG, "[music] i2s music play falied.")
abort()
}
vTaskDelay(1000 / portTICK_PERIOD_MS)
}
vTaskDelete(NULL)
}
static void i2s_echo(void *args)
{
int *mic_data = malloc(EXAMPLE_RECV_BUF_SIZE)
if (!mic_data) {
ESP_LOGE(TAG, "[echo] No memory for read data buffer")
abort()
}
esp_err_t ret = ESP_OK
size_t bytes_read = 0
size_t bytes_write = 0
ESP_LOGI(TAG, "[echo] Echo start")
while (1) {
memset(mic_data, 0, EXAMPLE_RECV_BUF_SIZE)
/* Read sample data from mic */
ret = i2s_channel_read(rx_handle, mic_data, EXAMPLE_RECV_BUF_SIZE, &bytes_read, 1000)
if (ret != ESP_OK) {
ESP_LOGE(TAG, "[echo] i2s read failed, %s", err_reason[ret == ESP_ERR_TIMEOUT])
abort()
}
/* Write sample data to earphone */
ret = i2s_channel_write(tx_handle, mic_data, EXAMPLE_RECV_BUF_SIZE, &bytes_write, 1000)
if (ret != ESP_OK) {
ESP_LOGE(TAG, "[echo] i2s write failed, %s", err_reason[ret == ESP_ERR_TIMEOUT])
abort()
}
if (bytes_read != bytes_write) {
ESP_LOGW(TAG, "[echo] %d bytes read but only %d bytes are written", bytes_read, bytes_write)
}
}
vTaskDelete(NULL)
}
void app_main(void)
{
printf("i2s es8311 codec example start\n-----------------------------\n")
/* Initialize i2s peripheral */
if (i2s_driver_init() != ESP_OK) {
ESP_LOGE(TAG, "i2s driver init failed")
abort()
} else {
ESP_LOGI(TAG, "i2s driver init success")
}
/* Initialize i2c peripheral and config es8311 codec by i2c */
if (es8311_codec_init() != ESP_OK) {
ESP_LOGE(TAG, "es8311 codec init failed")
abort()
} else {
ESP_LOGI(TAG, "es8311 codec init success")
}
/* Play a piece of music in music mode */
xTaskCreate(i2s_music, "i2s_music", 4096, NULL, 5, NULL)
/* Echo the sound from MIC in echo mode */
xTaskCreate(i2s_echo, "i2s_echo", 8192, NULL, 5, NULL)
}