refactor(hspi): Refactor hspi driver for esp8266 idf

This commit is contained in:
XiongYu
2018-07-09 21:27:37 +08:00
parent ce8fb1e67f
commit d4f2388a18
25 changed files with 2554 additions and 437 deletions

View File

@ -0,0 +1,658 @@
// Copyright 2015-2018 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 <string.h>
#include <stdint.h>
#include "FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp8266/eagle_soc.h"
#include "esp8266/spi_struct.h"
#include "esp8266/pin_mux_register.h"
#include "esp_libc.h"
#include "esp_heap_caps.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#include "rom/ets_sys.h"
#include "spi.h"
#define ENTER_CRITICAL() portENTER_CRITICAL()
#define EXIT_CRITICAL() portEXIT_CRITICAL()
static const char *TAG = "spi";
#define SPI_CHECK(a, str, ret_val) \
if (!(a)) { \
ESP_LOGE(TAG,"%s(%d): %s", __FUNCTION__, __LINE__, str); \
return (ret_val); \
}
#define spi_intr_enable() _xt_isr_unmask(1 << ETS_SPI_INUM)
#define spi_intr_disable() _xt_isr_mask(1 << ETS_SPI_INUM)
#define spi_intr_register(a, b) _xt_isr_attach(ETS_SPI_INUM, (a), (b))
// SPI interrupt status register address definition for determining the interrupt source
#define DPORT_SPI_INT_STATUS_REG 0x3ff00020
#define DPORT_SPI_INT_STATUS_SPI0 BIT4
#define DPORT_SPI_INT_STATUS_SPI1 BIT7
typedef struct {
spi_mode_t mode;
spi_interface_t interface;
SemaphoreHandle_t trans_mux;
spi_event_callback_t event_cb;
} spi_object_t;
static spi_object_t *spi_object[SPI_NUM_MAX] = {NULL, NULL};
// DRAM_ATTR is required to avoid SPI array placed in flash, due to accessed from ISR
static DRAM_ATTR spi_dev_t *const SPI[SPI_NUM_MAX] = {&SPI0, &SPI1};
esp_err_t spi_get_clk_div(spi_host_t host, spi_clk_div_t *clk_div)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(clk_div, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
if (SPI[host]->clock.clk_equ_sysclk) {
*clk_div = SPI_80MHz_DIV;
}
*clk_div = SPI[host]->clock.clkcnt_n + 1;
return ESP_OK;
}
esp_err_t spi_set_clk_div(spi_host_t host, spi_clk_div_t *clk_div)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(clk_div, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
ENTER_CRITICAL();
if (SPI_MASTER_MODE == spi_object[host]->mode) {
if (SPI_80MHz_DIV == *clk_div) {
switch (host) {
case CSPI_HOST: {
SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK);
}
break;
case HSPI_HOST: {
SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK);
}
break;
}
SPI[host]->clock.clk_equ_sysclk = true;
} else {
// Configure the IO_MUX clock (required, otherwise the clock output will be confusing)
switch (host) {
case CSPI_HOST: {
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYS_CLK);
}
break;
case HSPI_HOST: {
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK);
}
break;
}
// FRE(SCLK) = clk_equ_sysclk ? 80MHz : APB_CLK(80MHz) / clkdiv_pre / clkcnt
SPI[host]->clock.clk_equ_sysclk = false;
SPI[host]->clock.clkdiv_pre = 0;
SPI[host]->clock.clkcnt_n = *clk_div - 1;
// In the master mode clkcnt_h = floor((clkcnt_n+1)/2-1). In the slave mode it must be 0
SPI[host]->clock.clkcnt_h = *clk_div / 2 - 1;
// In the master mode clkcnt_l = clkcnt_n. In the slave mode it must be 0
SPI[host]->clock.clkcnt_l = *clk_div - 1;
}
} else {
// Slave mode must be set to 0
SPI[host]->clock.val = 0;
}
EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t spi_get_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(intr_enable, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
intr_enable->val = (SPI[host]->slave.val >> 5) & 0x1F;
return ESP_OK;
}
esp_err_t spi_set_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(intr_enable, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
ENTER_CRITICAL();
SPI[host]->slave.rd_buf_inten = intr_enable->read_buffer;
SPI[host]->slave.wr_buf_inten = intr_enable->write_buffer;
SPI[host]->slave.rd_sta_inten = intr_enable->read_status;
SPI[host]->slave.wr_sta_inten = intr_enable->write_status;
SPI[host]->slave.trans_inten = intr_enable->trans_done;
// Clear interrupt status register
SPI[host]->slave.rd_buf_done = false;
SPI[host]->slave.wr_buf_done = false;
SPI[host]->slave.rd_sta_done = false;
SPI[host]->slave.wr_sta_done = false;
SPI[host]->slave.trans_done = false;
EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t spi_get_mode(spi_host_t host, spi_mode_t *mode)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(mode, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
*mode = spi_object[host]->mode;
return ESP_OK;
}
esp_err_t spi_set_mode(spi_host_t host, spi_mode_t *mode)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(mode, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
spi_object[host]->mode = *mode;
ENTER_CRITICAL();
// Disable flash operation mode
SPI[host]->user.flash_mode = false;
if (SPI_MASTER_MODE == *mode) {
// Set to Master mode
SPI[host]->pin.slave_mode = false;
SPI[host]->slave.slave_mode = false;
// Master uses the entire hardware buffer to improve transmission speed
SPI[host]->user.usr_mosi_highpart = false;
SPI[host]->user.usr_miso_highpart = false;
SPI[host]->user.usr_mosi = true;
// Create hardware cs in advance
SPI[host]->user.cs_setup = true;
// Hysteresis to keep hardware cs
SPI[host]->user.cs_hold = true;
SPI[host]->user.duplex = true;
SPI[host]->user.ck_i_edge = true;
SPI[host]->ctrl2.mosi_delay_num = 0;
SPI[host]->ctrl2.miso_delay_num = 1;
} else {
// Set to Slave mode
SPI[host]->pin.slave_mode = true;
SPI[host]->slave.slave_mode = true;
SPI[host]->user.usr_miso_highpart = true;
SPI[host]->ctrl2.mosi_delay_num = 1;
SPI[host]->ctrl2.miso_delay_num = 0;
SPI[host]->slave.wr_rd_sta_en = 1;
SPI[host]->slave1.status_bitlen = 31;
SPI[host]->slave1.status_readback = 0;
// Put the slave's miso on the highpart, so you can only send 256bits
// In Slave mode miso, mosi length is the same
SPI[host]->slave1.buf_bitlen = 255;
SPI[host]->cmd.usr = 1;
}
SPI[host]->user.fwrite_dual = false;
SPI[host]->user.fwrite_quad = false;
SPI[host]->user.fwrite_dio = false;
SPI[host]->user.fwrite_qio = false;
SPI[host]->ctrl.fread_dual = false;
SPI[host]->ctrl.fread_quad = false;
SPI[host]->ctrl.fread_dio = false;
SPI[host]->ctrl.fread_qio = false;
SPI[host]->ctrl.fastrd_mode = true;
EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t spi_get_interface(spi_host_t host, spi_interface_t *interface)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(interface, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
*interface = spi_object[host]->interface;
return ESP_OK;
}
esp_err_t spi_set_interface(spi_host_t host, spi_interface_t *interface)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(interface, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
spi_object[host]->interface = *interface;
ENTER_CRITICAL();
switch (host) {
case CSPI_HOST: {
// Initialize SPI IO
PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_CLK_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SPICLK);
if (interface->mosi_en) {
PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_DATA1_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, FUNC_SPID_MOSI);
}
if (interface->miso_en) {
PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_DATA0_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, FUNC_SPIQ_MISO);
}
if (interface->cs_en) {
PIN_PULLUP_EN(PERIPHS_IO_MUX_SD_CMD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, FUNC_SPICS0);
}
}
break;
case HSPI_HOST: {
// Initialize HSPI IO
PIN_PULLUP_EN(PERIPHS_IO_MUX_MTMS_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, FUNC_HSPI_CLK); //GPIO14 is SPI CLK pin (Clock)
if (interface->mosi_en) {
PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_HSPID_MOSI); //GPIO13 is SPI MOSI pin (Master Data Out)
}
if (interface->miso_en) {
PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDI_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, FUNC_HSPIQ_MISO); //GPIO12 is SPI MISO pin (Master Data In)
}
if (interface->cs_en) {
PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_HSPI_CS0);
}
}
break;
}
// Set the clock polarity and phase
SPI[host]->pin.ck_idle_edge = interface->cpol;
if (interface->cpol == interface->cpha) {
SPI[host]->user.ck_out_edge = false;
} else {
SPI[host]->user.ck_out_edge = true;
}
// Set data bit order
SPI[host]->ctrl.wr_bit_order = interface->bit_tx_order;
SPI[host]->ctrl.rd_bit_order = interface->bit_rx_order;
// Set data byte order
SPI[host]->user.wr_byte_order = interface->byte_tx_order;
SPI[host]->user.rd_byte_order = interface->byte_rx_order;
EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t spi_get_dummy(spi_host_t host, uint16_t *bitlen)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(bitlen, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
if (SPI[host]->user.usr_dummy) {
*bitlen = SPI[host]->user1.usr_dummy_cyclelen + 1;
} else {
*bitlen = 0;
}
return ESP_OK;
}
esp_err_t spi_set_dummy(spi_host_t host, uint16_t *bitlen)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(bitlen, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
SPI_CHECK(*bitlen <= 256, "spi dummy must be shorter than 256 bits", ESP_ERR_INVALID_ARG);
ENTER_CRITICAL();
if (*bitlen) {
SPI[host]->user.usr_dummy = 1;
SPI[host]->user1.usr_dummy_cyclelen = *bitlen - 1;
} else {
SPI[host]->user.usr_dummy = 0;
}
EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t spi_get_event_callback(spi_host_t host, spi_event_callback_t *event_cb)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(event_cb, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
*event_cb = spi_object[host]->event_cb;
return ESP_OK;
}
esp_err_t spi_set_event_callback(spi_host_t host, spi_event_callback_t *event_cb)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(event_cb, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
spi_object[host]->event_cb = *event_cb;
return ESP_OK;
}
esp_err_t spi_slave_get_status(spi_host_t host, uint32_t *status)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(SPI_SLAVE_MODE == spi_object[host]->mode, "this function must used by spi slave mode", ESP_FAIL);
SPI_CHECK(status, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
ENTER_CRITICAL();
*status = SPI[host]->wr_status;
EXIT_CRITICAL();
return ESP_OK;
}
esp_err_t spi_slave_set_status(spi_host_t host, uint32_t *status)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(SPI_SLAVE_MODE == spi_object[host]->mode, "this function must used by spi slave mode", ESP_FAIL);
SPI_CHECK(status, "parameter pointer is empty", ESP_ERR_INVALID_ARG);
ENTER_CRITICAL();
SPI[host]->rd_status.val = *status;
EXIT_CRITICAL();
return ESP_OK;
}
static esp_err_t spi_master_trans(spi_host_t host, spi_trans_t trans)
{
SPI_CHECK(trans.bits.cmd <= 16, "spi cmd must be shorter than 16 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans.bits.addr <= 32, "spi addr must be shorter than 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans.bits.mosi <= 512, "spi mosi must be shorter than 512 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans.bits.miso <= 512, "spi miso must be shorter than 512 bits", ESP_ERR_INVALID_ARG);
int x, y;
// Waiting for an incomplete transfer
while (SPI[host]->cmd.usr);
ENTER_CRITICAL();
// Set the cmd length and transfer cmd
if (trans.bits.cmd && trans.cmd) {
SPI[host]->user.usr_command = 1;
SPI[host]->user2.usr_command_bitlen = trans.bits.cmd - 1;
SPI[host]->user2.usr_command_value = *trans.cmd;
} else {
SPI[host]->user.usr_command = 0;
}
// Set addr length and transfer addr
if (trans.bits.addr && trans.addr) {
SPI[host]->user.usr_addr = 1;
SPI[host]->user1.usr_addr_bitlen = trans.bits.addr - 1;
SPI[host]->addr = *trans.addr;
} else {
SPI[host]->user.usr_addr = 0;
}
// Set mosi length and transmit mosi
if (trans.bits.mosi && trans.mosi) {
SPI[host]->user.usr_mosi = 1;
SPI[host]->user1.usr_mosi_bitlen = trans.bits.mosi - 1;
for (x = 0; x < trans.bits.mosi; x += 32) {
y = x / 32;
SPI[host]->data_buf[y] = trans.mosi[y];
}
} else {
SPI[host]->user.usr_mosi = 0;
}
// Set the length of the miso
if (trans.bits.miso && trans.miso) {
SPI[host]->user.usr_miso = 1;
SPI[host]->user1.usr_miso_bitlen = trans.bits.miso - 1;
} else {
SPI[host]->user.usr_miso = 0;
}
// Call the event callback function to send a transfer start event
if (spi_object[host]->event_cb) {
spi_object[host]->event_cb(SPI_TRANS_START_EVENT, NULL);
}
// Start transmission
SPI[host]->cmd.usr = 1;
// Receive miso data
if (trans.bits.miso && trans.miso) {
while (SPI[host]->cmd.usr);
for (x = 0; x < trans.bits.miso; x += 32) {
y = x / 32;
trans.miso[y] = SPI[host]->data_buf[y];
}
}
EXIT_CRITICAL();
return ESP_OK;
}
static esp_err_t spi_slave_trans(spi_host_t host, spi_trans_t trans)
{
SPI_CHECK(trans.bits.cmd >= 3 && trans.bits.cmd <= 16, "spi cmd must be longer than 3 bits and shorter than 16 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans.bits.addr >= 1 && trans.bits.addr <= 32, "spi addr must be longer than 1 bits and shorter than 32 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans.bits.miso <= 256, "spi miso must be shorter than 256 bits", ESP_ERR_INVALID_ARG);
SPI_CHECK(trans.bits.mosi <= 256, "spi mosi must be shorter than 256 bits", ESP_ERR_INVALID_ARG);
int x, y;
ENTER_CRITICAL();
// Set cmd length and receive cmd
SPI[host]->user2.usr_command_bitlen = trans.bits.cmd - 1;
if (trans.cmd) {
*trans.cmd = SPI[host]->user2.usr_command_value;
}
// Set addr length and transfer addr
SPI[host]->slave1.wr_addr_bitlen = trans.bits.addr - 1;
SPI[host]->slave1.rd_addr_bitlen = trans.bits.addr - 1;
if (trans.addr) {
*trans.addr = SPI[host]->addr;
}
// Set the length of the miso and transfer the miso
if (trans.bits.miso && trans.miso) {
for (x = 0; x < trans.bits.miso; x += 32) {
y = x / 32;
SPI[host]->data_buf[y + 8] = trans.miso[y];
}
}
// Call the event callback function to send a transfer start event
if (spi_object[host]->event_cb) {
spi_object[host]->event_cb(SPI_TRANS_START_EVENT, NULL);
}
// Receive mosi data
if (trans.bits.mosi && trans.mosi) {
for (x = 0; x < trans.bits.mosi; x += 32) {
y = x / 32;
trans.mosi[y] = SPI[host]->data_buf[y];
}
}
EXIT_CRITICAL();
return ESP_OK;
}
static esp_err_t spi_trans_static(spi_host_t host, spi_trans_t trans)
{
int ret;
if (SPI_MASTER_MODE == spi_object[host]->mode) {
ret = spi_master_trans(host, trans);
} else {
ret = spi_slave_trans(host, trans);
}
return ret;
}
esp_err_t spi_trans(spi_host_t host, spi_trans_t trans)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
SPI_CHECK(trans.bits.val, "trans bits is empty", ESP_ERR_INVALID_ARG);
int ret;
xSemaphoreTake(spi_object[host]->trans_mux, portMAX_DELAY);
ret = spi_trans_static(host, trans);
xSemaphoreGive(spi_object[host]->trans_mux);
return ret;
}
static IRAM_ATTR void spi_intr(void *arg)
{
spi_host_t host;
uint32_t trans_done;
if (READ_PERI_REG(DPORT_SPI_INT_STATUS_REG) & DPORT_SPI_INT_STATUS_SPI0) { // DPORT_SPI_INT_STATUS_SPI0
trans_done = SPI0.slave.val & 0x1F;
SPI0.slave.val &= ~0x3FF;
host = CSPI_HOST;
} else if (READ_PERI_REG(DPORT_SPI_INT_STATUS_REG) & DPORT_SPI_INT_STATUS_SPI1) { // DPORT_SPI_INT_STATUS_SPI1
trans_done = SPI1.slave.val & 0x1F;
SPI1.slave.val &= ~0x1F;
host = HSPI_HOST;
} else {
return;
}
if (spi_object[host]) {
if (spi_object[host]->event_cb) {
spi_object[host]->event_cb(SPI_TRANS_DONE_EVENT, &trans_done);
}
}
}
esp_err_t spi_deinit(spi_host_t host)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(spi_object[host], "spi has not been initialized yet", ESP_FAIL);
spi_intr_enable_t intr_enable;
// Turn off the current host interrupt enable
intr_enable.val = 0;
spi_set_intr_enable(host, &intr_enable);
// Turn off the SPI interrupt if all other hosts are not initialized
if (host == CSPI_HOST) {
if (spi_object[HSPI_HOST] == NULL) {
spi_intr_disable();
}
} else {
if (spi_object[CSPI_HOST] == NULL) {
spi_intr_disable();
}
}
// Waiting for all transfers to complete
while (SPI[host]->cmd.usr);
// Call the event callback function to send the SPI_DEINIT event
if (spi_object[host]->event_cb) {
spi_object[host]->event_cb(SPI_DEINIT_EVENT, NULL);
}
if (spi_object[host]->trans_mux) {
vSemaphoreDelete(spi_object[host]->trans_mux);
}
free(spi_object[host]);
spi_object[host] = NULL;
return ESP_OK;
}
esp_err_t spi_init(spi_host_t host, spi_config_t *config)
{
SPI_CHECK(host < SPI_NUM_MAX, "host num error", ESP_ERR_INVALID_ARG);
SPI_CHECK(host > CSPI_HOST, "CSPI_HOST can't support now", ESP_FAIL);
SPI_CHECK(NULL == spi_object[host], "spi has been initialized", ESP_FAIL);
spi_object[host] = (spi_object_t *)malloc(sizeof(spi_object_t));
SPI_CHECK(spi_object[host], "malloc fail", ESP_ERR_NO_MEM);
spi_object[host]->trans_mux = xSemaphoreCreateMutex();
if (NULL == spi_object[host]->trans_mux) {
spi_deinit(host);
SPI_CHECK(false, "Semaphore create fail", ESP_ERR_NO_MEM);
}
uint16_t dummy_bitlen = 0;
spi_set_event_callback(host, &config->event_cb);
spi_set_mode(host, &config->mode);
spi_set_interface(host, &config->interface);
spi_set_clk_div(host, &config->clk_div);
spi_set_dummy(host, &dummy_bitlen);
spi_set_intr_enable(host, &config->intr_enable);
spi_intr_register(spi_intr, NULL);
spi_intr_enable();
if (spi_object[host]->event_cb) {
spi_object[host]->event_cb(SPI_INIT_EVENT, NULL);
}
return ESP_OK;
}

View File

@ -0,0 +1,433 @@
// Copyright 2018-2025 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 "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SPI_NUM_MAX 2
// SPI bus CPOL and CPHA definition
#define SPI_CPOL_LOW 0
#define SPI_CPOL_HIGH 1
#define SPI_CPHA_LOW 0
#define SPI_CPHA_HIGH 1
// SPI bus data sequence definition
#define SPI_BIT_ORDER_MSB_FIRST 1
#define SPI_BIT_ORDER_LSB_FIRST 0
#define SPI_BYTE_ORDER_MSB_FIRST 1
#define SPI_BYTE_ORDER_LSB_FIRST 0
// SPI default bus interface parameter definition
// CS_EN:1, MISO_EN:1, MOSI_EN:1, BYTE_TX_ORDER:1, BYTE_TX_ORDER:1, BIT_RX_ORDER:0, BIT_TX_ORDER:0, CPHA:0, CPOL:0
#define SPI_DEFAULT_INTERFACE 0x1F0
// SPI master default interrupt enable definition
// TRANS_DONE: true, WRITE_STATUS: false, READ_STATUS: false, WRITE_BUFFER: false, READ_BUFFER: false
#define SPI_MASTER_DEFAULT_INTR_ENABLE 0x10
// SPI slave default interrupt enable definition
// TRANS_DONE: false, WRITE_STATUS: true, READ_STATUS: true, WRITE_BUFFER: true, READ_BUFFER: ture
#define SPI_SLAVE_DEFAULT_INTR_ENABLE 0x0F
// SPI event definition
#define SPI_INIT_EVENT 0
#define SPI_TRANS_START_EVENT 1
#define SPI_TRANS_DONE_EVENT 2
#define SPI_DEINIT_EVENT 3
#define SPI_MASTER_WRITE_DATA_TO_SLAVE_CMD 2
#define SPI_MASTER_READ_DATA_FROM_SLAVE_CMD 3
#define SPI_MASTER_WRITE_STATUS_TO_SLAVE_CMD 1
#define SPI_MASTER_READ_STATUS_FROM_SLAVE_CMD 4
#define SPI_SLV_RD_BUF_DONE (BIT(0))
#define SPI_SLV_WR_BUF_DONE (BIT(1))
#define SPI_SLV_RD_STA_DONE (BIT(2))
#define SPI_SLV_WR_STA_DONE (BIT(3))
#define SPI_TRANS_DONE (BIT(4))
typedef void (*spi_event_callback_t)(int event, void *arg);
// ESP8266 has two hardware SPI, CSPI and HSPI. Currently, HSPI can be used arbitrarily.
// SPI peripheral enumeration
typedef enum {
CSPI_HOST = 0,
HSPI_HOST
} spi_host_t;
// SPI clock division factor enumeration
typedef enum {
SPI_2MHz_DIV = 40,
SPI_4MHz_DIV = 20,
SPI_5MHz_DIV = 16,
SPI_8MHz_DIV = 10,
SPI_10MHz_DIV = 8,
SPI_16MHz_DIV = 5,
SPI_20MHz_DIV = 4,
SPI_40MHz_DIV = 2,
SPI_80MHz_DIV = 1,
} spi_clk_div_t;
// SPI working mode enumeration
typedef enum {
SPI_MASTER_MODE,
SPI_SLAVE_MODE
} spi_mode_t;
// SPI interrupt enable union type definition
typedef union {
struct {
uint32_t read_buffer: 1;
uint32_t write_buffer: 1;
uint32_t read_status: 1;
uint32_t write_status: 1;
uint32_t trans_done: 1;
uint32_t reserved5: 27;
};
uint32_t val;
} spi_intr_enable_t;
// SPI bus interface parameter union type definition
typedef union {
struct {
uint32_t cpol: 1; // Clock Polarity
uint32_t cpha: 1; // Clock Phase
uint32_t bit_tx_order: 1;
uint32_t bit_rx_order: 1;
uint32_t byte_tx_order: 1;
uint32_t byte_rx_order: 1;
uint32_t mosi_en: 1;
uint32_t miso_en: 1;
uint32_t cs_en: 1;
uint32_t reserved9: 23;
};
uint32_t val;
} spi_interface_t;
// SPI transmission parameter structure type definition
typedef struct {
uint16_t *cmd;
uint32_t *addr;
uint32_t *mosi;
uint32_t *miso;
union {
struct {
uint32_t cmd: 5;
uint32_t addr: 7;
uint32_t mosi: 10;
uint32_t miso: 10;
};
uint32_t val;
} bits;
} spi_trans_t;
// SPI initialization parameter structure type definition
typedef struct {
spi_interface_t interface;
spi_intr_enable_t intr_enable;
spi_event_callback_t event_cb;
spi_mode_t mode;
spi_clk_div_t clk_div;
} spi_config_t;
/**
* @brief Get the SPI clock division factor
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param clk_div Pointer to accept clock division factor
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_get_clk_div(spi_host_t host, spi_clk_div_t *clk_div);
/**
* @brief Get SPI Interrupt Enable
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param intr_enable Pointer to accept interrupt enable
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_get_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable);
/**
* @brief Get SPI working mode
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param mode Pointer to accept working mode
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_get_mode(spi_host_t host, spi_mode_t *mode);
/**
* @brief Get SPI bus interface configuration
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param interface Pointer to accept bus interface configuration
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_get_interface(spi_host_t host, spi_interface_t *interface);
/**
* @brief Get the SPI event callback function
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param event_cb Pointer to accept event callback function
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_get_event_callback(spi_host_t host, spi_event_callback_t *event_cb);
/**
* @brief Set the SPI clock division factor
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param clk_div Pointer to deliver clock division factor
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_set_clk_div(spi_host_t host, spi_clk_div_t *clk_div);
/**
* @brief Set SPI interrupt enable
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param intr_enable Pointer to deliver interrupt enable
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_set_intr_enable(spi_host_t host, spi_intr_enable_t *intr_enable);
/**
* @brief Set the SPI mode of operation
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param mode Pointer to deliver working mode
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_set_mode(spi_host_t host, spi_mode_t *mode);
/**
* @brief Get SPI dummy bitlen
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param bitlen Pointer to accept dummy bitlen
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_get_dummy(spi_host_t host, uint16_t *bitlen);
/**
* @brief Set SPI dummy bitlen
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param bitlen Pointer to deliver dummy bitlen
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_set_dummy(spi_host_t host, uint16_t *bitlen);
/**
* @brief Set SPI bus interface configuration
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param interface Pointer to deliver bus interface configuration
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_set_interface(spi_host_t host, spi_interface_t *interface);
/**
* @brief Set the SPI event callback function
*
* @note This event_cb will be called from an ISR. So there is a stack
* size limit (configurable as "ISR stack size" in menuconfig). This
* limit is smaller compared to a global SPI interrupt handler due
* to the additional level of indirection.
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param event_cb Pointer to deliver event callback function
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_set_event_callback(spi_host_t host, spi_event_callback_t *event_cb);
/**
* @brief Get SPI slave wr_status register
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param status Pointer to accept wr_status register
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_slave_get_status(spi_host_t host, uint32_t *status);
/**
* @brief Set SPI slave rd_status register
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param status Pointer to deliver rd_status register
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_slave_set_status(spi_host_t host, uint32_t *status);
/**
* @brief SPI data transfer function
*
* @note If the bit of the corresponding phase in the transmission parameter is 0, its data will not work.
* For example: trans.bits.cmd = 0, cmd will not be transmitted
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param trans Transmission parameter structure
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_trans(spi_host_t host, spi_trans_t trans);
/**
* @brief Deinit the spi
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @return
* - ESP_OK Success
* - ESP_FAIL spi has not been initialized yet
*/
esp_err_t spi_deinit(spi_host_t host);
/**
* @brief Initialize the spi
*
* @note SPI0 has been used by FLASH and cannot be used by the user temporarily.
*
* @param host SPI peripheral number
* - CSPI_HOST SPI0
* - HSPI_HOST SPI1
*
* @param config Pointer to deliver initialize configuration parameter
*
* @return
* - ESP_OK Success
* - ESP_ERR_NO_MEM malloc fail
* - ESP_FAIL spi has been initialized
*/
esp_err_t spi_init(spi_host_t host, spi_config_t *config);
#ifdef __cplusplus
}
#endif

View File

@ -1,263 +0,0 @@
// Copyright 2018 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.
#ifndef SPI_REGISTER_H_INCLUDED
#define SPI_REGISTER_H_INCLUDED
#include "esp8266/eagle_soc.h"
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
#define SPI_FLASH_READ BIT31
#define SPI_FLASH_WREN BIT30
#define SPI_FLASH_WRDI BIT29
#define SPI_FLASH_RDID BIT28
#define SPI_FLASH_RDSR BIT27
#define SPI_FLASH_WRSR BIT26
#define SPI_FLASH_PP BIT25
#define SPI_FLASH_SE BIT24
#define SPI_FLASH_BE BIT23
#define SPI_FLASH_CE BIT22
#define SPI_FLASH_RES BIT20
#define SPI_USR (BIT(18))
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
#define SPI_WR_BIT_ORDER (BIT(26))
#define SPI_RD_BIT_ORDER (BIT(25))
#define SPI_QIO_MODE (BIT(24))
#define SPI_DIO_MODE (BIT(23))
#define SPI_QOUT_MODE (BIT(20))
#define SPI_DOUT_MODE (BIT(14))
#define SPI_FASTRD_MODE (BIT(13))
#define SPI_CTRL1(i) (REG_SPI_BASE(i) + 0xc)
#define SPI_CS_HOLD_DELAY 0xf
#define SPI_CS_HOLD_DELAY_S 28
#define SPI_CS_HOLD_DELAY_RES 0xfff
#define SPI_CS_HOLD_DELAY_RES_S 16
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
#define SPI_CS_DELAY_NUM 0x0000000F
#define SPI_CS_DELAY_NUM_S 28
#define SPI_CS_DELAY_MODE 0x00000003
#define SPI_CS_DELAY_MODE_S 26
#define SPI_MOSI_DELAY_NUM 0x00000007
#define SPI_MOSI_DELAY_NUM_S 23
#define SPI_MOSI_DELAY_MODE 0x00000003
#define SPI_MOSI_DELAY_MODE_S 21
#define SPI_MISO_DELAY_NUM 0x00000007
#define SPI_MISO_DELAY_NUM_S 18
#define SPI_MISO_DELAY_MODE 0x00000003
#define SPI_MISO_DELAY_MODE_S 16
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
#define SPI_CLK_EQU_SYSCLK (BIT(31))
#define SPI_CLKDIV_PRE 0x00001FFF
#define SPI_CLKDIV_PRE_S 18
#define SPI_CLKCNT_N 0x0000003F
#define SPI_CLKCNT_N_S 12
#define SPI_CLKCNT_H 0x0000003F
#define SPI_CLKCNT_H_S 6
#define SPI_CLKCNT_L 0x0000003F
#define SPI_CLKCNT_L_S 0
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
#define SPI_USR_COMMAND (BIT(31))
#define SPI_USR_ADDR (BIT(30))
#define SPI_USR_DUMMY (BIT(29))
#define SPI_USR_MISO (BIT(28))
#define SPI_USR_MOSI (BIT(27))
#define SPI_USR_MOSI_HIGHPART (BIT(25))
#define SPI_USR_MISO_HIGHPART (BIT(24))
#define SPI_SIO (BIT(16))
#define SPI_FWRITE_QIO (BIT(15))
#define SPI_FWRITE_DIO (BIT(14))
#define SPI_FWRITE_QUAD (BIT(13))
#define SPI_FWRITE_DUAL (BIT(12))
#define SPI_WR_BYTE_ORDER (BIT(11))
#define SPI_RD_BYTE_ORDER (BIT(10))
#define SPI_CK_OUT_EDGE (BIT(7))
#define SPI_CK_I_EDGE (BIT(6))
#define SPI_CS_SETUP (BIT(5))
#define SPI_CS_HOLD (BIT(4))
#define SPI_FLASH_MODE (BIT(2))
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
#define SPI_USR_ADDR_BITLEN 0x0000003F
#define SPI_USR_ADDR_BITLEN_S 26
#define SPI_USR_MOSI_BITLEN 0x000001FF
#define SPI_USR_MOSI_BITLEN_S 17
#define SPI_USR_MISO_BITLEN 0x000001FF
#define SPI_USR_MISO_BITLEN_S 8
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
#define SPI_USR_DUMMY_CYCLELEN_S 0
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
#define SPI_USR_COMMAND_BITLEN 0x0000000F
#define SPI_USR_COMMAND_BITLEN_S 28
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
#define SPI_USR_COMMAND_VALUE_S 0
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
#define SPI_IDLE_EDGE (BIT(29))
#define SPI_CS2_DIS (BIT(2))
#define SPI_CS1_DIS (BIT(1))
#define SPI_CS0_DIS (BIT(0))
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
#define SPI_SYNC_RESET (BIT(31))
#define SPI_SLAVE_MODE (BIT(30))
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
#define SPI_SLV_CMD_DEFINE (BIT(27))
#define SPI_TRANS_CNT 0x0000000F
#define SPI_TRANS_CNT_S 23
#define SPI_TRANS_DONE_EN (BIT(9))
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
#define SLV_SPI_INT_EN 0x0000001f
#define SLV_SPI_INT_EN_S 5
#define SPI_TRANS_DONE (BIT(4))
#define SPI_SLV_WR_STA_DONE (BIT(3))
#define SPI_SLV_RD_STA_DONE (BIT(2))
#define SPI_SLV_WR_BUF_DONE (BIT(1))
#define SPI_SLV_RD_BUF_DONE (BIT(0))
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
#define SPI_SLV_STATUS_BITLEN 0x0000001F
#define SPI_SLV_STATUS_BITLEN_S 27
#define SPI_SLV_BUF_BITLEN 0x000001FF
#define SPI_SLV_BUF_BITLEN_S 16
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
#define SPI_SLV_RD_ADDR_BITLEN_S 10
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
#define SPI_SLV_WR_ADDR_BITLEN_S 4
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8)
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_INT_HOLD_ENA 0x00000003
#define SPI_INT_HOLD_ENA_S 0
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8)
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_ENABLE_AHB BIT17
#define SPI_FLASH_CLK_EQU_SYSCLK BIT12
//SPI flash command
#define SPI_FLASH_READ BIT31
#define SPI_FLASH_WREN BIT30
#define SPI_FLASH_WRDI BIT29
#define SPI_FLASH_RDID BIT28
#define SPI_FLASH_RDSR BIT27
#define SPI_FLASH_WRSR BIT26
#define SPI_FLASH_PP BIT25
#define SPI_FLASH_SE BIT24
#define SPI_FLASH_BE BIT23
#define SPI_FLASH_CE BIT22
#define SPI_FLASH_RES BIT20
#define SPI_FLASH_DPD BIT21
#define SPI_FLASH_HPM BIT19
//SPI address register
#define SPI_FLASH_BYTES_LEN 24
#define SPI_BUFF_BYTE_NUM 32
#define IODATA_START_ADDR BIT0
//SPI status register
#define SPI_FLASH_BUSY_FLAG BIT0
#define SPI_FLASH_WRENABLE_FLAG BIT1
#define SPI_FLASH_BP0 BIT2
#define SPI_FLASH_BP1 BIT3
#define SPI_FLASH_BP2 BIT4
#define SPI_FLASH_TOP_BOT_PRO_FLAG BIT5
#define SPI_FLASH_STATUS_PRO_FLAG BIT7
#define FLASH_WR_PROTECT (SPI_FLASH_BP0|SPI_FLASH_BP1|SPI_FLASH_BP2)
#define SPI 0
#define PERIPHS_SPI_FLASH_C0 SPI_W0(SPI)
#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(SPI)
#define PERIPHS_SPI_FLASH_CMD SPI_CMD(SPI)
#define SPI0_CLK_EQU_SYSCLK BIT8
#define PERIPHS_SPI_FLASH_USRREG (0x60000200 + 0x1c)
#endif // SPI_REGISTER_H_INCLUDED

View File

@ -1,195 +1,268 @@
/*
* ESPRSSIF MIT License
*
* Copyright (c) 2015 <ESPRESSIF SYSTEMS (SHANGHAI) PTE LTD>
*
* Permission is hereby granted for use on ESPRESSIF SYSTEMS ESP8266 only, in which case,
* it is free of charge, to any person obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
// Copyright 2010-2018 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
#ifndef SPI_REGISTER_H_INCLUDED
#define SPI_REGISTER_H_INCLUDED
// 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 "eagle_soc.h"
#pragma once
#define REG_SPI_BASE(i) (0x60000200 - i*0x100)
#include "esp8266/eagle_soc.h"
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
#define SPI_USR (BIT(18))
#ifdef __cplusplus
extern "C" {
#endif
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
#define REG_SPI_BASE(i) (0x60000200-i*0x100)
#define SPI_CMD(i) (REG_SPI_BASE(i) + 0x0)
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
#define SPI_WR_BIT_ORDER (BIT(26))
#define SPI_RD_BIT_ORDER (BIT(25))
#define SPI_QIO_MODE (BIT(24))
#define SPI_DIO_MODE (BIT(23))
#define SPI_QOUT_MODE (BIT(20))
#define SPI_DOUT_MODE (BIT(14))
#define SPI_FASTRD_MODE (BIT(13))
#define SPI_FLASH_READ BIT31
#define SPI_FLASH_WREN BIT30
#define SPI_FLASH_WRDI BIT29
#define SPI_FLASH_RDID BIT28
#define SPI_FLASH_RDSR BIT27
#define SPI_FLASH_WRSR BIT26
#define SPI_FLASH_PP BIT25
#define SPI_FLASH_SE BIT24
#define SPI_FLASH_BE BIT23
#define SPI_FLASH_CE BIT22
#define SPI_FLASH_RES BIT20
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
#define SPI_USR (BIT(18))
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
#define SPI_CS_DELAY_NUM 0x0000000F
#define SPI_CS_DELAY_NUM_S 28
#define SPI_CS_DELAY_MODE 0x00000003
#define SPI_CS_DELAY_MODE_S 26
#define SPI_MOSI_DELAY_NUM 0x00000007
#define SPI_MOSI_DELAY_NUM_S 23
#define SPI_MOSI_DELAY_MODE 0x00000003
#define SPI_MOSI_DELAY_MODE_S 21
#define SPI_MISO_DELAY_NUM 0x00000007
#define SPI_MISO_DELAY_NUM_S 18
#define SPI_MISO_DELAY_MODE 0x00000003
#define SPI_MISO_DELAY_MODE_S 16
#define SPI_ADDR(i) (REG_SPI_BASE(i) + 0x4)
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
#define SPI_CLK_EQU_SYSCLK (BIT(31))
#define SPI_CLKDIV_PRE 0x00001FFF
#define SPI_CLKDIV_PRE_S 18
#define SPI_CLKCNT_N 0x0000003F
#define SPI_CLKCNT_N_S 12
#define SPI_CLKCNT_H 0x0000003F
#define SPI_CLKCNT_H_S 6
#define SPI_CLKCNT_L 0x0000003F
#define SPI_CLKCNT_L_S 0
#define SPI_CTRL(i) (REG_SPI_BASE(i) + 0x8)
#define SPI_WR_BIT_ORDER (BIT(26))
#define SPI_RD_BIT_ORDER (BIT(25))
#define SPI_QIO_MODE (BIT(24))
#define SPI_DIO_MODE (BIT(23))
#define SPI_QOUT_MODE (BIT(20))
#define SPI_DOUT_MODE (BIT(14))
#define SPI_FASTRD_MODE (BIT(13))
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
#define SPI_USR_COMMAND (BIT(31))
#define SPI_USR_ADDR (BIT(30))
#define SPI_USR_DUMMY (BIT(29))
#define SPI_USR_MISO (BIT(28))
#define SPI_USR_MOSI (BIT(27))
#define SPI_USR_MOSI_HIGHPART (BIT(25))
#define SPI_USR_MISO_HIGHPART (BIT(24))
#define SPI_SIO (BIT(16))
#define SPI_FWRITE_QIO (BIT(15))
#define SPI_FWRITE_DIO (BIT(14))
#define SPI_FWRITE_QUAD (BIT(13))
#define SPI_FWRITE_DUAL (BIT(12))
#define SPI_WR_BYTE_ORDER (BIT(11))
#define SPI_RD_BYTE_ORDER (BIT(10))
#define SPI_CK_OUT_EDGE (BIT(7))
#define SPI_CK_I_EDGE (BIT(6))
#define SPI_CS_SETUP (BIT(5))
#define SPI_CS_HOLD (BIT(4))
#define SPI_FLASH_MODE (BIT(2))
#define SPI_CTRL1(i) (REG_SPI_BASE(i) + 0xc)
#define SPI_CS_HOLD_DELAY 0xf
#define SPI_CS_HOLD_DELAY_S 28
#define SPI_CS_HOLD_DELAY_RES 0xfff
#define SPI_CS_HOLD_DELAY_RES_S 16
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
#define SPI_USR_ADDR_BITLEN 0x0000003F
#define SPI_USR_ADDR_BITLEN_S 26
#define SPI_USR_MOSI_BITLEN 0x000001FF
#define SPI_USR_MOSI_BITLEN_S 17
#define SPI_USR_MISO_BITLEN 0x000001FF
#define SPI_USR_MISO_BITLEN_S 8
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
#define SPI_USR_DUMMY_CYCLELEN_S 0
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
#define SPI_USR_COMMAND_BITLEN 0x0000000F
#define SPI_USR_COMMAND_BITLEN_S 28
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
#define SPI_USR_COMMAND_VALUE_S 0
#define SPI_RD_STATUS(i) (REG_SPI_BASE(i) + 0x10)
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
#define SPI_CTRL2(i) (REG_SPI_BASE(i) + 0x14)
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
#define SPI_CS2_DIS (BIT(2))
#define SPI_CS1_DIS (BIT(1))
#define SPI_CS0_DIS (BIT(0))
#define SPI_CS_DELAY_NUM 0x0000000F
#define SPI_CS_DELAY_NUM_S 28
#define SPI_CS_DELAY_MODE 0x00000003
#define SPI_CS_DELAY_MODE_S 26
#define SPI_MOSI_DELAY_NUM 0x00000007
#define SPI_MOSI_DELAY_NUM_S 23
#define SPI_MOSI_DELAY_MODE 0x00000003
#define SPI_MOSI_DELAY_MODE_S 21
#define SPI_MISO_DELAY_NUM 0x00000007
#define SPI_MISO_DELAY_NUM_S 18
#define SPI_MISO_DELAY_MODE 0x00000003
#define SPI_MISO_DELAY_MODE_S 16
#define SPI_CLOCK(i) (REG_SPI_BASE(i) + 0x18)
#define SPI_CLK_EQU_SYSCLK (BIT(31))
#define SPI_CLKDIV_PRE 0x00001FFF
#define SPI_CLKDIV_PRE_S 18
#define SPI_CLKCNT_N 0x0000003F
#define SPI_CLKCNT_N_S 12
#define SPI_CLKCNT_H 0x0000003F
#define SPI_CLKCNT_H_S 6
#define SPI_CLKCNT_L 0x0000003F
#define SPI_CLKCNT_L_S 0
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
#define SPI_SYNC_RESET (BIT(31))
#define SPI_SLAVE_MODE (BIT(30))
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
#define SPI_SLV_CMD_DEFINE (BIT(27))
#define SPI_TRANS_CNT 0x0000000F
#define SPI_TRANS_CNT_S 23
#define SPI_TRANS_DONE_EN (BIT(9))
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
#define SLV_SPI_INT_EN 0x0000001f
#define SLV_SPI_INT_EN_S 5
#define SPI_TRANS_DONE (BIT(4))
#define SPI_SLV_WR_STA_DONE (BIT(3))
#define SPI_SLV_RD_STA_DONE (BIT(2))
#define SPI_SLV_WR_BUF_DONE (BIT(1))
#define SPI_SLV_RD_BUF_DONE (BIT(0))
#define SPI_USER(i) (REG_SPI_BASE(i) + 0x1C)
#define SPI_USR_COMMAND (BIT(31))
#define SPI_USR_ADDR (BIT(30))
#define SPI_USR_DUMMY (BIT(29))
#define SPI_USR_MISO (BIT(28))
#define SPI_USR_MOSI (BIT(27))
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
#define SPI_SLV_STATUS_BITLEN 0x0000001F
#define SPI_SLV_STATUS_BITLEN_S 27
#define SPI_SLV_BUF_BITLEN 0x000001FF
#define SPI_SLV_BUF_BITLEN_S 16
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
#define SPI_SLV_RD_ADDR_BITLEN_S 10
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
#define SPI_SLV_WR_ADDR_BITLEN_S 4
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
#define SPI_USR_MOSI_HIGHPART (BIT(25))
#define SPI_USR_MISO_HIGHPART (BIT(24))
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0x000000FF
#define SPI_SIO (BIT(16))
#define SPI_FWRITE_QIO (BIT(15))
#define SPI_FWRITE_DIO (BIT(14))
#define SPI_FWRITE_QUAD (BIT(13))
#define SPI_FWRITE_DUAL (BIT(12))
#define SPI_WR_BYTE_ORDER (BIT(11))
#define SPI_RD_BYTE_ORDER (BIT(10))
#define SPI_CK_OUT_EDGE (BIT(7))
#define SPI_CK_I_EDGE (BIT(6))
#define SPI_CS_SETUP (BIT(5))
#define SPI_CS_HOLD (BIT(4))
#define SPI_FLASH_MODE (BIT(2))
#define SPI_USER1(i) (REG_SPI_BASE(i) + 0x20)
#define SPI_USR_ADDR_BITLEN 0x0000003F
#define SPI_USR_ADDR_BITLEN_S 26
#define SPI_USR_MOSI_BITLEN 0x000001FF
#define SPI_USR_MOSI_BITLEN_S 17
#define SPI_USR_MISO_BITLEN 0x000001FF
#define SPI_USR_MISO_BITLEN_S 8
#define SPI_USR_DUMMY_CYCLELEN 0x000000FF
#define SPI_USR_DUMMY_CYCLELEN_S 0
#define SPI_USER2(i) (REG_SPI_BASE(i) + 0x24)
#define SPI_USR_COMMAND_BITLEN 0x0000000F
#define SPI_USR_COMMAND_BITLEN_S 28
#define SPI_USR_COMMAND_VALUE 0x0000FFFF
#define SPI_USR_COMMAND_VALUE_S 0
#define SPI_WR_STATUS(i) (REG_SPI_BASE(i) + 0x28)
#define SPI_PIN(i) (REG_SPI_BASE(i) + 0x2C)
#define SPI_IDLE_EDGE (BIT(29))
#define SPI_CS2_DIS (BIT(2))
#define SPI_CS1_DIS (BIT(1))
#define SPI_CS0_DIS (BIT(0))
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
#define SPI_SYNC_RESET (BIT(31))
#define SPI_SLAVE_MODE (BIT(30))
#define SPI_SLV_WR_RD_BUF_EN (BIT(29))
#define SPI_SLV_WR_RD_STA_EN (BIT(28))
#define SPI_SLV_CMD_DEFINE (BIT(27))
#define SPI_TRANS_CNT 0x0000000F
#define SPI_TRANS_CNT_S 23
#define SPI_TRANS_DONE_EN (BIT(9))
#define SPI_SLV_WR_STA_DONE_EN (BIT(8))
#define SPI_SLV_RD_STA_DONE_EN (BIT(7))
#define SPI_SLV_WR_BUF_DONE_EN (BIT(6))
#define SPI_SLV_RD_BUF_DONE_EN (BIT(5))
#define SLV_SPI_INT_EN 0x0000001f
#define SLV_SPI_INT_EN_S 5
#define SPI_TRANS_DONE (BIT(4))
#define SPI_SLV_WR_STA_DONE (BIT(3))
#define SPI_SLV_RD_STA_DONE (BIT(2))
#define SPI_SLV_WR_BUF_DONE (BIT(1))
#define SPI_SLV_RD_BUF_DONE (BIT(0))
#define SPI_SLAVE1(i) (REG_SPI_BASE(i) + 0x34)
#define SPI_SLV_STATUS_BITLEN 0x0000001F
#define SPI_SLV_STATUS_BITLEN_S 27
#define SPI_SLV_BUF_BITLEN 0x000001FF
#define SPI_SLV_BUF_BITLEN_S 16
#define SPI_SLV_RD_ADDR_BITLEN 0x0000003F
#define SPI_SLV_RD_ADDR_BITLEN_S 10
#define SPI_SLV_WR_ADDR_BITLEN 0x0000003F
#define SPI_SLV_WR_ADDR_BITLEN_S 4
#define SPI_SLV_WRSTA_DUMMY_EN (BIT(3))
#define SPI_SLV_RDSTA_DUMMY_EN (BIT(2))
#define SPI_SLV_WRBUF_DUMMY_EN (BIT(1))
#define SPI_SLV_RDBUF_DUMMY_EN (BIT(0))
#define SPI_SLAVE2(i) (REG_SPI_BASE(i) + 0x38)
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRBUF_DUMMY_CYCLELEN_S 24
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_RDBUF_DUMMY_CYCLELEN_S 16
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN 0X000000FF
#define SPI_SLV_WRSTR_DUMMY_CYCLELEN_S 8
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN 0x000000FF
#define SPI_SLV_RDSTR_DUMMY_CYCLELEN_S 0
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
#define SPI_SLAVE3(i) (REG_SPI_BASE(i) + 0x3C)
#define SPI_SLV_WRSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_WRSTA_CMD_VALUE_S 24
#define SPI_SLV_RDSTA_CMD_VALUE 0x000000FF
#define SPI_SLV_RDSTA_CMD_VALUE_S 16
#define SPI_SLV_WRBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_WRBUF_CMD_VALUE_S 8
#define SPI_SLV_RDBUF_CMD_VALUE 0x000000FF
#define SPI_SLV_RDBUF_CMD_VALUE_S 0
#define SPI_W0(i) (REG_SPI_BASE(i) + 0x40)
#define SPI_W1(i) (REG_SPI_BASE(i) + 0x44)
#define SPI_W2(i) (REG_SPI_BASE(i) + 0x48)
#define SPI_W3(i) (REG_SPI_BASE(i) + 0x4C)
#define SPI_W4(i) (REG_SPI_BASE(i) + 0x50)
#define SPI_W5(i) (REG_SPI_BASE(i) + 0x54)
#define SPI_W6(i) (REG_SPI_BASE(i) + 0x58)
#define SPI_W7(i) (REG_SPI_BASE(i) + 0x5C)
#define SPI_W8(i) (REG_SPI_BASE(i) + 0x60)
#define SPI_W9(i) (REG_SPI_BASE(i) + 0x64)
#define SPI_W10(i) (REG_SPI_BASE(i) + 0x68)
#define SPI_W11(i) (REG_SPI_BASE(i) + 0x6C)
#define SPI_W12(i) (REG_SPI_BASE(i) + 0x70)
#define SPI_W13(i) (REG_SPI_BASE(i) + 0x74)
#define SPI_W14(i) (REG_SPI_BASE(i) + 0x78)
#define SPI_W15(i) (REG_SPI_BASE(i) + 0x7C)
#define SPI_W0(i) (REG_SPI_BASE(i) +0x40)
#define SPI_W1(i) (REG_SPI_BASE(i) +0x44)
#define SPI_W2(i) (REG_SPI_BASE(i) +0x48)
#define SPI_W3(i) (REG_SPI_BASE(i) +0x4C)
#define SPI_W4(i) (REG_SPI_BASE(i) +0x50)
#define SPI_W5(i) (REG_SPI_BASE(i) +0x54)
#define SPI_W6(i) (REG_SPI_BASE(i) +0x58)
#define SPI_W7(i) (REG_SPI_BASE(i) +0x5C)
#define SPI_W8(i) (REG_SPI_BASE(i) +0x60)
#define SPI_W9(i) (REG_SPI_BASE(i) +0x64)
#define SPI_W10(i) (REG_SPI_BASE(i) +0x68)
#define SPI_W11(i) (REG_SPI_BASE(i) +0x6C)
#define SPI_W12(i) (REG_SPI_BASE(i) +0x70)
#define SPI_W13(i) (REG_SPI_BASE(i) +0x74)
#define SPI_W14(i) (REG_SPI_BASE(i) +0x78)
#define SPI_W15(i) (REG_SPI_BASE(i) +0x7C)
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8)
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8)
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_INT_HOLD_ENA 0x00000003
#define SPI_INT_HOLD_ENA_S 0
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_INT_HOLD_ENA 0x00000003
#define SPI_INT_HOLD_ENA_S 0
#endif // SPI_REGISTER_H_INCLUDED
#define SPI_EXT2(i) (REG_SPI_BASE(i) + 0xF8)
#define SPI_EXT3(i) (REG_SPI_BASE(i) + 0xFC)
#define SPI_ENABLE_AHB BIT17
#define SPI_FLASH_CLK_EQU_SYSCLK BIT12
//SPI flash command
#define SPI_FLASH_READ BIT31
#define SPI_FLASH_WREN BIT30
#define SPI_FLASH_WRDI BIT29
#define SPI_FLASH_RDID BIT28
#define SPI_FLASH_RDSR BIT27
#define SPI_FLASH_WRSR BIT26
#define SPI_FLASH_PP BIT25
#define SPI_FLASH_SE BIT24
#define SPI_FLASH_BE BIT23
#define SPI_FLASH_CE BIT22
#define SPI_FLASH_RES BIT20
#define SPI_FLASH_DPD BIT21
#define SPI_FLASH_HPM BIT19
//SPI address register
#define SPI_FLASH_BYTES_LEN 24
#define SPI_BUFF_BYTE_NUM 32
#define IODATA_START_ADDR BIT0
//SPI status register
#define SPI_FLASH_BUSY_FLAG BIT0
#define SPI_FLASH_WRENABLE_FLAG BIT1
#define SPI_FLASH_BP0 BIT2
#define SPI_FLASH_BP1 BIT3
#define SPI_FLASH_BP2 BIT4
#define SPI_FLASH_TOP_BOT_PRO_FLAG BIT5
#define SPI_FLASH_STATUS_PRO_FLAG BIT7
#define FLASH_WR_PROTECT (SPI_FLASH_BP0|SPI_FLASH_BP1|SPI_FLASH_BP2)
#define SPI 0
#define PERIPHS_SPI_FLASH_C0 SPI_W0(SPI)
#define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(SPI)
#define PERIPHS_SPI_FLASH_CMD SPI_CMD(SPI)
#define SPI0_CLK_EQU_SYSCLK BIT8
#define PERIPHS_SPI_FLASH_USRREG (0x60000200 + 0x1c)
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,236 @@
// Copyright 2010-2018 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 "esp8266/eagle_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef volatile struct {
union {
struct {
uint32_t reserved0: 18; /*reserved*/
uint32_t usr: 1; /*User define command enable. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_hpm: 1; /*Drive Flash into high performance mode. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_res: 1; /*This bit combined with reg_resandres bit releases Flash from the power-down state or high performance mode and obtains the devices ID. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_dp: 1; /*Drive Flash into power down. An operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_ce: 1; /*Chip erase enable. Chip erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_be: 1; /*Block erase enable(32KB) . Block erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_se: 1; /*Sector erase enable(4KB). Sector erase operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_pp: 1; /*Page program enable(1 byte ~256 bytes data to be programmed). Page program operation will be triggered when the bit is set. The bit will be cleared once the operation done .1: enable 0: disable.*/
uint32_t flash_wrsr: 1; /*Write status register enable. Write status operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_rdsr: 1; /*Read status register-1. Read status operation will be triggered when the bit is set. The bit will be cleared once the operation done.1: enable 0: disable.*/
uint32_t flash_rdid: 1; /*Read JEDEC ID . Read ID command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/
uint32_t flash_wrdi: 1; /*Write flash disable. Write disable command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/
uint32_t flash_wren: 1; /*Write flash enable. Write enable command will be sent when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/
uint32_t flash_read: 1; /*Read flash enable. Read flash operation will be triggered when the bit is set. The bit will be cleared once the operation done. 1: enable 0: disable.*/
};
uint32_t val;
} cmd;
uint32_t addr; /*addr to slave / from master. SPI transfer from the MSB to the LSB. If length > 32 bits, then address continues from MSB of wr_status.*/
union {
struct {
uint32_t clkcnt_l: 4;
uint32_t clkcnt_h: 4;
uint32_t clkcnt_n: 4;
uint32_t clk_equ_sysclk: 1;
uint32_t fastrd_mode: 1; /*This bit enable the bits: spi_fread_qio spi_fread_dio spi_fread_qout and spi_fread_dout. 1: enable 0: disable.*/
uint32_t fread_dual: 1; /*In the read operations read-data phase apply 2 signals. 1: enable 0: disable.*/
uint32_t reserved15: 5; /*reserved*/
uint32_t fread_quad: 1; /*In the read operations read-data phase apply 4 signals. 1: enable 0: disable.*/
uint32_t reserved21: 2; /*reserved*/
uint32_t fread_dio: 1; /*In the read operations address phase and read-data phase apply 2 signals. 1: enable 0: disable.*/
uint32_t fread_qio: 1; /*In the read operations address phase and read-data phase apply 4 signals. 1: enable 0: disable.*/
uint32_t rd_bit_order: 1; /*In read-data (MISO) phase 1: LSB first 0: MSB first*/
uint32_t wr_bit_order: 1; /*In command address write-data (MOSI) phases 1: LSB firs 0: MSB first*/
uint32_t reserved27: 5; /*reserved*/
};
uint32_t val;
} ctrl;
union {
struct {
uint32_t reserved0: 16; /*reserved*/
uint32_t cs_hold_delay_res: 12; /*Delay cycles of resume Flash when resume Flash is enable by spi clock.*/
uint32_t cs_hold_delay: 4; /*SPI cs signal is delayed by spi clock cycles*/
};
uint32_t val;
} ctrl1;
union {
struct {
uint32_t status: 16; /*In the slave mode, it is the status for master to read out.*/
uint32_t wb_mode: 8; /*Mode bits in the flash fast read mode, it is combined with spi_fastrd_mode bit.*/
uint32_t status_ext: 8; /*In the slave mode,it is the status for master to read out.*/
};
uint32_t val;
} rd_status; /*In the slave mode, this register are the status register for the master to read out.*/
union {
struct {
uint32_t reserved0: 16; /*reserved*/
uint32_t miso_delay_mode: 2; /*MISO signals are delayed by spi_clk. 0: zero 1: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by half cycle else delayed by one cycle 2: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by one cycle else delayed by half cycle 3: delayed one cycle*/
uint32_t miso_delay_num: 3; /*MISO signals are delayed by system clock cycles*/
uint32_t mosi_delay_mode: 2; /*MOSI signals are delayed by spi_clk. 0: zero 1: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by half cycle else delayed by one cycle 2: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by one cycle else delayed by half cycle 3: delayed one cycle*/
uint32_t mosi_delay_num: 3; /*MOSI signals are delayed by system clock cycles*/
uint32_t cs_delay_mode: 2; /*spi_cs signal is delayed by spi_clk . 0: zero 1: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by half cycle else delayed by one cycle 2: if spi_ck_out_edge or spi_ck_i_edge is set 1 delayed by one cycle else delayed by half cycle 3: delayed one cycle*/
uint32_t cs_delay_num: 4; /*spi_cs signal is delayed by system clock cycles*/
};
uint32_t val;
} ctrl2;
union {
struct {
uint32_t clkcnt_l: 6; /*In the master mode it must be equal to spi_clkcnt_n. In the slave mode it must be 0.*/
uint32_t clkcnt_h: 6; /*In the master mode it must be floor((spi_clkcnt_n+1)/2-1). In the slave mode it must be 0.*/
uint32_t clkcnt_n: 6; /*In the master mode it is the divider of spi_clk. So spi_clk frequency is system/(spi_clkdiv_pre+1)/(spi_clkcnt_n+1)*/
uint32_t clkdiv_pre: 13; /*In the master mode it is pre-divider of spi_clk.*/
uint32_t clk_equ_sysclk: 1; /*In the master mode 1: spi_clk is eqaul to system 0: spi_clk is divided from system clock.*/
};
uint32_t val;
} clock;
union {
struct {
uint32_t duplex: 1;
uint32_t reserved1: 1; /*reserved*/
uint32_t flash_mode: 1;
uint32_t reserved3: 1; /*reserved*/
uint32_t cs_hold: 1; /*spi cs keep low when spi is in done phase. 1: enable 0: disable.*/
uint32_t cs_setup: 1; /*spi cs is enable when spi is in prepare phase. 1: enable 0: disable.*/
uint32_t ck_i_edge: 1; /*In the slave mode the bit is same as spi_ck_out_edge in master mode. It is combined with spi_miso_delay_mode bits.*/
uint32_t ck_out_edge: 1; /*the bit combined with spi_mosi_delay_mode bits to set mosi signal delay mode.*/
uint32_t reserved8: 2; /*reserved*/
uint32_t rd_byte_order: 1; /*In read-data (MISO) phase 1: big-endian 0: little_endian*/
uint32_t wr_byte_order: 1; /*In command address write-data (MOSI) phases 1: big-endian 0: litte_endian*/
uint32_t fwrite_dual: 1; /*In the write operations read-data phase apply 2 signals*/
uint32_t fwrite_quad: 1; /*In the write operations read-data phase apply 4 signals*/
uint32_t fwrite_dio: 1; /*In the write operations address phase and read-data phase apply 2 signals.*/
uint32_t fwrite_qio: 1; /*In the write operations address phase and read-data phase apply 4 signals.*/
uint32_t sio: 1; /*Set the bit to enable 3-line half duplex communication mosi and miso signals share the same pin. 1: enable 0: disable.*/
uint32_t reserved17: 7; /*reserved*/
uint32_t usr_miso_highpart: 1; /*read-data phase only access to high-part of the buffer spi_w8~spi_w15. 1: enable 0: disable.*/
uint32_t usr_mosi_highpart: 1; /*write-data phase only access to high-part of the buffer spi_w8~spi_w15. 1: enable 0: disable.*/
uint32_t reserved26: 1; /*reserved*/
uint32_t usr_mosi: 1; /*This bit enable the write-data phase of an operation.*/
uint32_t usr_miso: 1; /*This bit enable the read-data phase of an operation.*/
uint32_t usr_dummy: 1; /*This bit enable the dummy phase of an operation.*/
uint32_t usr_addr: 1; /*This bit enable the address phase of an operation.*/
uint32_t usr_command: 1; /*This bit enable the command phase of an operation.*/
};
uint32_t val;
} user;
union {
struct {
uint32_t usr_dummy_cyclelen: 8; /*The length in spi_clk cycles of dummy phase. The register value shall be (cycle_num-1).*/
uint32_t usr_miso_bitlen: 9; /*The length in bits of read-data. The register value shall be (bit_num-1).*/
uint32_t usr_mosi_bitlen: 9; /*The length in bits of write-data. The register value shall be (bit_num-1).*/
uint32_t usr_addr_bitlen: 6; /*The length in bits of address phase. The register value shall be (bit_num-1).*/
};
uint32_t val;
} user1;
union {
struct {
uint32_t usr_command_value: 16; /*The value of command. Output sequence: bit 7-0 and then 15-8.*/
uint32_t reserved16: 12; /*reserved*/
uint32_t usr_command_bitlen: 4; /*The length in bits of command phase. The register value shall be (bit_num-1)*/
};
uint32_t val;
} user2;
uint32_t wr_status; /*In the slave mode this register are the status register for the master to write into. In the master mode this register are the higher 32bits in the 64 bits address condition.*/
union {
struct {
uint32_t cs0_dis: 1; /*SPI CS0 pin enable, 1: disable CS0, 0: spi_cs0 signal is from/to CS0 pin*/
uint32_t cs1_dis: 1; /*SPI CS1 pin enable, 1: disable CS1, 0: spi_cs1 signal is from/to CS1 pin*/
uint32_t cs2_dis: 1; /*SPI CS2 pin enable, 1: disable CS2, 0: spi_cs2 signal is from/to CS2 pin*/
uint32_t reserved3: 16; /*reserved*/
uint32_t slave_mode: 1; /*1: Both CLK and CS are input, 0: Both CLK and CS are output*/
uint32_t reserved20: 9; /*reserved*/
uint32_t ck_idle_edge: 1; /*1: spi clk line is high when idle 0: spi clk line is low when idle*/
uint32_t reserved30: 2; /*reserved*/
};
uint32_t val;
} pin;
union {
struct {
uint32_t rd_buf_done: 1; /*The interrupt raw bit for the completion of read-buffer operation in the slave mode.*/
uint32_t wr_buf_done: 1; /*The interrupt raw bit for the completion of write-buffer operation in the slave mode.*/
uint32_t rd_sta_done: 1; /*The interrupt raw bit for the completion of read-status operation in the slave mode.*/
uint32_t wr_sta_done: 1; /*The interrupt raw bit for the completion of write-status operation in the slave mode.*/
uint32_t trans_done: 1; /*The interrupt raw bit for the completion of any operation in both the master mode and the slave mode.*/
uint32_t rd_buf_inten: 1; /*The interrupt enable bit for the completion of read-buffer operation in the slave mode.*/
uint32_t wr_buf_inten: 1; /*The interrupt enable bit for the completion of write-buffer operation in the slave mode.*/
uint32_t rd_sta_inten: 1; /*The interrupt enable bit for the completion of read-status operation in the slave mode.*/
uint32_t wr_sta_inten: 1; /*The interrupt enable bit for the completion of write-status operation in the slave mode.*/
uint32_t trans_inten: 1; /*The interrupt enable bit for the completion of any operation in both the master mode and the slave mode.*/
uint32_t reserved10: 13; /*reserved*/
uint32_t trans_cnt: 4; /*The operations counter in both the master mode and the slave mode.*/
uint32_t cmd_define: 1; /*1: slave mode commands are defined in SPI_SLAVE3. 0: slave mode commands are fixed as: 1: write-status 2: write-buffer and 3: read-buffer 4: read-status*/
uint32_t wr_rd_sta_en: 1; /*write and read status enable in the slave mode*/
uint32_t wr_rd_buf_en: 1; /*write and read buffer enable in the slave mode*/
uint32_t slave_mode: 1; /*1: slave mode 0: master mode.*/
uint32_t sync_reset: 1; /*Software reset enable, reset the spi clock line cs line and data lines.*/
};
uint32_t val;
} slave;
union {
struct {
uint32_t rdbuf_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for read-buffer operations.*/
uint32_t wrbuf_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for write-buffer operations.*/
uint32_t rdsta_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for read-status operations.*/
uint32_t wrsta_dummy_en: 1; /*In the slave mode it is the enable bit of dummy phase for write-status operations.*/
uint32_t wr_addr_bitlen: 6; /*In the slave mode it is the address length in bits for write-buffer operation. The register value shall be (bit_num-1).*/
uint32_t rd_addr_bitlen: 6; /*In the slave mode it is the address length in bits for read-buffer operation. The register value shall be (bit_num-1).*/
uint32_t buf_bitlen: 9; /*In the slave mode it is the length of buffer bit.*/
uint32_t status_readback: 1; /*In the slave mode it is the bit decide whether master reads rd_status register or wr_status register data. 0: rd_status: 1: wr_status*/
uint32_t reserved25: 1; /*reserved*/
uint32_t status_bitlen: 5; /*In the slave mode it is the length of status bit.*/
};
uint32_t val;
} slave1;
union {
struct {
uint32_t rdsta_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for read-status operations. The register value shall be (cycle_num-1).*/
uint32_t wrsta_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for write-status operations. The register value shall be (cycle_num-1).*/
uint32_t rdbuf_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for read-buffer operations. The register value shall be (cycle_num-1).*/
uint32_t wrbuf_dummy_cyclelen: 8; /*In the slave mode it is the length in spi_clk cycles of dummy phase for write-buffer operations. The register value shall be (cycle_num-1).*/
};
uint32_t val;
} slave2;
union {
struct {
uint32_t rdbuf_cmd_value: 8; /*In the slave mode it is the value of read-buffer command.*/
uint32_t wrbuf_cmd_value: 8; /*In the slave mode it is the value of write-buffer command.*/
uint32_t rdsta_cmd_value: 8; /*In the slave mode it is the value of read-status command.*/
uint32_t wrsta_cmd_value: 8; /*In the slave mode it is the value of write-status command.*/
};
uint32_t val;
} slave3;
uint32_t data_buf[16]; /*data buffer*/
uint32_t reserved_80[30];
uint32_t ext2;
union {
struct {
uint32_t int_hold_ena: 2; /*This register is for two SPI masters to share the same cs clock and data signals. The bits of one SPI are set if the other SPI is busy the SPI will be hold. 1(3): hold at ,idle, phase 2: hold at ,prepare, phase.*/
uint32_t reserved2: 30; /*reserved*/
};
uint32_t val;
} ext3;
} spi_dev_t;
extern spi_dev_t SPI0;
extern spi_dev_t SPI1;
#ifdef __cplusplus
}
#endif

View File

@ -6,5 +6,9 @@ PROVIDE ( uart1 = 0x60000f00 );
PROVIDE ( frc1 = 0x60000600 );
PROVIDE ( rtc_sys_info = 0x60001100 );
PROVIDE ( SLC = 0x60000B00 );
PROVIDE ( I2S = 0x60000e00 );
PROVIDE ( SPI1 = 0x60000100 );
PROVIDE ( SPI0 = 0x60000200 );