pikapython/package/ESP32/pika_hal_ESP32_SPI.c

273 lines
7.3 KiB
C
Raw Permalink Normal View History

#include "../PikaStdDevice/pika_hal.h"
#include "driver/spi_master.h"
#include "driver/spi_slave.h"
#include "pika_hal.h"
#define TEMP_MOSI_IO 11 // 这里应该备多组i2c的io以对应不同I2Cx
#define TEMP_MISO_IO -1
#define TEMP_SCLK_IO 12
#define TEMP_CS_IO 10
#define TEMP_QUEUE_SIZE 128 // 这里是开启dma传输时用于队列传输的大小通常大于spi一次性发送的数据如果不使能DMA则不用管
typedef struct
{
spi_bus_config_t buscfg;
PIKA_HAL_SPI_MASTER_OR_SLAVE master_or_slave;
unsigned int time_out;
union
{
spi_device_interface_config_t devcfg;
spi_slave_interface_config_t slvcfg;
};
spi_device_handle_t devhandle;
int host_id;
} esp_spi_t;
int pika_hal_platform_SPI_open(pika_dev *dev, char *name)
{
esp_spi_t *platform_spi = pikaMalloc(sizeof(esp_spi_t));
memset(platform_spi, 0, sizeof(esp_spi_t));
dev->platform_data = platform_spi;
int spi_num = fast_atoi(name + 3);
if (!(name[0] == 'S' && name[1] == 'P' && name[2] == 'I') || spi_num >= SPI_HOST_MAX)
{
__platform_printf("SPI: Open %s failed\r\n", name);
goto err;
}
platform_spi->host_id = spi_num - 1;
return 0;
err:
return -1;
}
int pika_hal_platform_SPI_close(pika_dev *dev)
{
esp_spi_t *platform_spi = (esp_spi_t *)dev->platform_data;
if (NULL == platform_spi)
{
goto err;
}
pikaFree(platform_spi, sizeof(esp_spi_t));
return 0;
err:
return -1;
}
int pika_hal_platform_SPI_ioctl_config(pika_dev *dev,
pika_hal_SPI_config *cfg)
{
if (dev->is_enabled)
{
goto err;
}
esp_spi_t *platform_spi = (esp_spi_t *)dev->platform_data;
platform_spi->buscfg.mosi_io_num = TEMP_MOSI_IO;
platform_spi->buscfg.miso_io_num = TEMP_MISO_IO;
platform_spi->buscfg.sclk_io_num = TEMP_SCLK_IO;
platform_spi->buscfg.quadwp_io_num = -1;
platform_spi->buscfg.quadhd_io_num = -1;
platform_spi->buscfg.max_transfer_sz = 4000,
platform_spi->master_or_slave = cfg->master_or_slave;
platform_spi->time_out = cfg->timeout;
if (cfg->master_or_slave == PIKA_HAL_SPI_MASTER)
{
platform_spi->devcfg.clock_speed_hz = cfg->speed;
// platform_spi->devcfg.mode = cfg->mode;
switch(cfg->mode){
case PIKA_HAL_SPI_MODE_0:
platform_spi->devcfg.mode = 0;
break;
case PIKA_HAL_SPI_MODE_1:
platform_spi->devcfg.mode = 1;
break;
case PIKA_HAL_SPI_MODE_2:
platform_spi->devcfg.mode = 2;
break;
case PIKA_HAL_SPI_MODE_3:
platform_spi->devcfg.mode = 3;
break;
default:
platform_spi->devcfg.mode = 0;
break;
}
platform_spi->devcfg.spics_io_num = TEMP_CS_IO;
platform_spi->devcfg.queue_size = TEMP_QUEUE_SIZE;
}
else if (cfg->master_or_slave == PIKA_HAL_SPI_SLAVE)
{
// platform_spi->slvcfg.mode = cfg->mode;
switch(cfg->mode){
case PIKA_HAL_SPI_MODE_0:
platform_spi->slvcfg.mode = 0;
break;
case PIKA_HAL_SPI_MODE_1:
platform_spi->slvcfg.mode = 1;
break;
case PIKA_HAL_SPI_MODE_2:
platform_spi->slvcfg.mode = 2;
break;
case PIKA_HAL_SPI_MODE_3:
platform_spi->slvcfg.mode = 3;
break;
default:
platform_spi->slvcfg.mode = 0;
break;
}
platform_spi->slvcfg.spics_io_num = TEMP_CS_IO;
platform_spi->slvcfg.queue_size = TEMP_QUEUE_SIZE;
platform_spi->slvcfg.flags = 0;
platform_spi->slvcfg.post_setup_cb = NULL;
platform_spi->slvcfg.post_trans_cb = NULL;
}
else
{
goto err;
}
return 0;
err:
return -1;
}
int pika_hal_platform_SPI_ioctl_enable(pika_dev *dev)
{
if (dev->is_enabled)
{
goto err;
}
esp_spi_t *platform_spi = (esp_spi_t *)dev->platform_data;
int ret = 0;
if (platform_spi->master_or_slave == PIKA_HAL_SPI_MASTER)
{
ret = spi_bus_initialize(platform_spi->host_id, &platform_spi->buscfg, SPI_DMA_CH_AUTO);
if (ret != ESP_OK)
{
goto err;
}
ret = spi_bus_add_device(platform_spi->host_id, &platform_spi->devcfg, &platform_spi->devhandle);
if (ret != ESP_OK)
{
goto err;
}
}
else if (platform_spi->master_or_slave == PIKA_HAL_SPI_SLAVE)
{
ret = spi_slave_initialize(platform_spi->host_id, &platform_spi->buscfg, &platform_spi->slvcfg, SPI_DMA_CH_AUTO);
if (ret != ESP_OK)
{
goto err;
}
}
return 0;
err:
return -1;
}
int pika_hal_platform_SPI_ioctl_disable(pika_dev *dev)
{
if (!dev->is_enabled)
{
goto err;
}
esp_spi_t *platform_spi = (esp_spi_t *)dev->platform_data;
if (platform_spi->master_or_slave == PIKA_HAL_SPI_MASTER)
{
spi_bus_remove_device(platform_spi->devhandle);
spi_bus_free(platform_spi->host_id);
}
else if (platform_spi->master_or_slave == PIKA_HAL_SPI_SLAVE)
{
spi_slave_free(platform_spi->host_id);
}
return 0;
err:
return -1;
}
int pika_hal_platform_SPI_write(pika_dev *dev, void *buf, size_t count)
{
esp_spi_t *platform_spi = (esp_spi_t *)dev->platform_data;
if (platform_spi->master_or_slave == PIKA_HAL_SPI_MASTER)
{
spi_transaction_t t = {0};
t.length = 8 * count;
t.tx_buffer = buf;
// E (1388) spi_master: check_trans_valid(774): SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits
// t.flags = SPI_TRANS_USE_TXDATA;
esp_err_t ret = spi_device_polling_transmit(platform_spi->devhandle, &t);
if (ret != ESP_OK)
{
goto err;
}
}
else if (platform_spi->master_or_slave == PIKA_HAL_SPI_SLAVE)
{
spi_slave_transaction_t t;
t.length = count * 8;
t.tx_buffer = buf;
t.rx_buffer = NULL;
esp_err_t ret = spi_slave_transmit(platform_spi->host_id, &t, platform_spi->time_out);
if (ret != ESP_OK)
{
goto err;
}
}
return 0;
err:
return -1;
}
int pika_hal_platform_SPI_read(pika_dev *dev, void *buf, size_t count)
{
esp_spi_t *platform_spi = (esp_spi_t *)dev->platform_data;
if (platform_spi->master_or_slave == PIKA_HAL_SPI_MASTER)
{
spi_device_acquire_bus(platform_spi->devhandle, portMAX_DELAY);
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = 8 * count;
t.flags = SPI_TRANS_USE_RXDATA;
t.rx_buffer = buf;
esp_err_t ret = spi_device_polling_transmit(platform_spi->devhandle, &t);
spi_device_release_bus(platform_spi->devhandle);
if (ret != ESP_OK)
{
goto err;
}
}
else if (platform_spi->master_or_slave == PIKA_HAL_SPI_SLAVE)
{
static spi_slave_transaction_t t;
t.length = count * 8;
t.tx_buffer = NULL;
t.rx_buffer = buf;
esp_err_t ret = spi_slave_transmit(platform_spi->host_id, &t, platform_spi->time_out);
if (ret != ESP_OK)
{
goto err;
}
}
return 0;
err:
return -1;
}