feat(esp2866): Move driver to esp8266 of components

This commit is contained in:
Dong Heng
2018-04-08 10:38:18 +08:00
parent 3a008481cb
commit 3e1f0b973e
12 changed files with 0 additions and 0 deletions

View File

@ -0,0 +1,43 @@
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libdriver.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

View File

@ -0,0 +1,213 @@
/*
* 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.
*
*/
#include "espressif/esp_common.h"
#include "freertos/portmacro.h"
#include "gpio.h"
void gpio_config(GPIO_ConfigTypeDef *pGPIOConfig)
{
uint16 gpio_pin_mask = pGPIOConfig->GPIO_Pin;
uint32 io_reg;
uint8 io_num = 0;
uint32 pin_reg;
if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Input) {
GPIO_AS_INPUT(gpio_pin_mask);
} else if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Output) {
GPIO_AS_OUTPUT(gpio_pin_mask);
}
do {
if ((gpio_pin_mask >> io_num) & 0x1) {
io_reg = GPIO_PIN_REG(io_num);
if ((0x1 << io_num) & (GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_5)) {
PIN_FUNC_SELECT(io_reg, 0);
} else {
PIN_FUNC_SELECT(io_reg, 3);
}
if (pGPIOConfig->GPIO_Pullup) {
PIN_PULLUP_EN(io_reg);
} else {
PIN_PULLUP_DIS(io_reg);
}
if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Out_OD) {
portENTER_CRITICAL();
pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(io_num));
pin_reg &= (~GPIO_PIN_DRIVER_MASK);
pin_reg |= (GPIO_PAD_DRIVER_ENABLE << GPIO_PIN_DRIVER_LSB);
GPIO_REG_WRITE(GPIO_PIN_ADDR(io_num), pin_reg);
portEXIT_CRITICAL();
} else if (pGPIOConfig->GPIO_Mode == GPIO_Mode_Sigma_Delta) {
portENTER_CRITICAL();
pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(io_num));
pin_reg &= (~GPIO_PIN_SOURCE_MASK);
pin_reg |= (0x1 << GPIO_PIN_SOURCE_LSB);
GPIO_REG_WRITE(GPIO_PIN_ADDR(io_num), pin_reg);
GPIO_REG_WRITE(GPIO_SIGMA_DELTA_ADDRESS, SIGMA_DELTA_ENABLE);
portEXIT_CRITICAL();
}
gpio_pin_intr_state_set(io_num, pGPIOConfig->GPIO_IntrType);
}
io_num++;
} while (io_num < 16);
}
/*
* Change GPIO pin output by setting, clearing, or disabling pins.
* In general, it is expected that a bit will be set in at most one
* of these masks. If a bit is clear in all masks, the output state
* remains unchanged.
*
* There is no particular ordering guaranteed; so if the order of
* writes is significant, calling code should divide a single call
* into multiple calls.
*/
void gpio_output_conf(uint32 set_mask, uint32 clear_mask, uint32 enable_mask, uint32 disable_mask)
{
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, set_mask);
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, clear_mask);
GPIO_REG_WRITE(GPIO_ENABLE_W1TS_ADDRESS, enable_mask);
GPIO_REG_WRITE(GPIO_ENABLE_W1TC_ADDRESS, disable_mask);
}
/*
* Sample the value of GPIO input pins and returns a bitmask.
*/
uint32 gpio_input_get(void)
{
return GPIO_REG_READ(GPIO_IN_ADDRESS);
}
/*
* Register an application-specific interrupt handler for GPIO pin
* interrupts. Once the interrupt handler is called, it will not
* be called again until after a call to gpio_intr_ack. Any GPIO
* interrupts that occur during the interim are masked.
*
* The application-specific handler is called with a mask of
* pending GPIO interrupts. After processing pin interrupts, the
* application-specific handler may wish to use gpio_intr_pending
* to check for any additional pending interrupts before it returns.
*/
void gpio_intr_handler_register(void *fn, void *arg)
{
_xt_isr_attach(ETS_GPIO_INUM, fn, arg);
}
/*
only highlevel and lowlevel intr can use for wakeup
*/
void gpio_pin_wakeup_enable(uint32 i, GPIO_INT_TYPE intr_state)
{
uint32 pin_reg;
if ((intr_state == GPIO_PIN_INTR_LOLEVEL) || (intr_state == GPIO_PIN_INTR_HILEVEL)) {
portENTER_CRITICAL();
pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(i));
pin_reg &= (~GPIO_PIN_INT_TYPE_MASK);
pin_reg |= (intr_state << GPIO_PIN_INT_TYPE_LSB);
pin_reg |= GPIO_PIN_WAKEUP_ENABLE_SET(GPIO_WAKEUP_ENABLE);
GPIO_REG_WRITE(GPIO_PIN_ADDR(i), pin_reg);
portEXIT_CRITICAL();
}
}
void gpio_pin_wakeup_disable(void)
{
uint8 i;
uint32 pin_reg;
for (i = 0; i < GPIO_PIN_COUNT; i++) {
pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(i));
if (pin_reg & GPIO_PIN_WAKEUP_ENABLE_MASK) {
pin_reg &= (~GPIO_PIN_INT_TYPE_MASK);
pin_reg |= (GPIO_PIN_INTR_DISABLE << GPIO_PIN_INT_TYPE_LSB);
pin_reg &= ~(GPIO_PIN_WAKEUP_ENABLE_SET(GPIO_WAKEUP_ENABLE));
GPIO_REG_WRITE(GPIO_PIN_ADDR(i), pin_reg);
}
}
}
void gpio_pin_intr_state_set(uint32 i, GPIO_INT_TYPE intr_state)
{
uint32 pin_reg;
portENTER_CRITICAL();
pin_reg = GPIO_REG_READ(GPIO_PIN_ADDR(i));
pin_reg &= (~GPIO_PIN_INT_TYPE_MASK);
pin_reg |= (intr_state << GPIO_PIN_INT_TYPE_LSB);
GPIO_REG_WRITE(GPIO_PIN_ADDR(i), pin_reg);
portEXIT_CRITICAL();
}
void gpio16_output_conf(void)
{
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC to output rtc_gpio0
WRITE_PERI_REG(RTC_GPIO_CONF,
(READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
WRITE_PERI_REG(RTC_GPIO_ENABLE,
(READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe) | (uint32)0x1); //out enable
}
void gpio16_output_set(uint8 value)
{
WRITE_PERI_REG(RTC_GPIO_OUT,
(READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe) | (uint32)(value & 1));
}
void gpio16_input_conf(void)
{
WRITE_PERI_REG(PAD_XPD_DCDC_CONF,
(READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | (uint32)0x1); // mux configuration for XPD_DCDC and rtc_gpio0 connection
WRITE_PERI_REG(RTC_GPIO_CONF,
(READ_PERI_REG(RTC_GPIO_CONF) & (uint32)0xfffffffe) | (uint32)0x0); //mux configuration for out enable
WRITE_PERI_REG(RTC_GPIO_ENABLE,
READ_PERI_REG(RTC_GPIO_ENABLE) & (uint32)0xfffffffe); //out disable
}
uint8 gpio16_input_get(void)
{
return (uint8)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1);
}

View File

@ -0,0 +1,139 @@
/*
* 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.
*
*/
#include "esp_common.h"
#define US_TO_RTC_TIMER_TICKS(t) \
((t) ? \
(((t) > 0x35A) ? \
(((t) >> 2) * ((APB_CLK_FREQ >> 4) / 250000) + ((t)&0x3) * ((APB_CLK_FREQ >> 4) / 1000000)) : \
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
0)
#define FRC1_ENABLE_TIMER BIT7
#define FRC1_AUTO_LOAD BIT6
typedef enum { // timer provided mode
DIVDED_BY_1 = 0, // timer clock
DIVDED_BY_16 = 4, // divided by 16
DIVDED_BY_256 = 8, // divided by 256
} TIMER_PREDIVED_MODE;
typedef enum { // timer interrupt mode
TM_LEVEL_INT = 1, // level interrupt
TM_EDGE_INT = 0, // edge interrupt
} TIMER_INT_MODE;
#define RTC_REG_WRITE(addr, val) WRITE_PERI_REG(addr, val)
static void (* user_hw_timer_cb)(void) = NULL;
bool frc1_auto_load = false;
static void hw_timer_isr_cb(void *arg)
{
if(frc1_auto_load == false ) {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
DIVDED_BY_16 | TM_EDGE_INT);
}
if (user_hw_timer_cb != NULL) {
(*(user_hw_timer_cb))();
}
}
void hw_timer_disarm(void)
{
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,0);
}
void hw_timer_arm(uint32 val ,bool req)
{
frc1_auto_load = req;
if (frc1_auto_load == true) {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
FRC1_AUTO_LOAD | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
} else {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
}
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val));
}
void hw_timer_set_func(void (* user_hw_timer_cb_set)(void))
{
user_hw_timer_cb = user_hw_timer_cb_set;
}
void hw_timer_init(void)
{
#if 0
if (req == 1) {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
FRC1_AUTO_LOAD | DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
} else {
RTC_REG_WRITE(FRC1_CTRL_ADDRESS,
DIVDED_BY_16 | FRC1_ENABLE_TIMER | TM_EDGE_INT);
}
#endif
_xt_isr_attach(ETS_FRC_TIMER1_INUM, hw_timer_isr_cb, NULL);
TM1_EDGE_INT_ENABLE();
_xt_isr_unmask(1 << ETS_FRC_TIMER1_INUM);
}
//-------------------------------Test Code Below--------------------------------------
#if 0
#include "hw_timer.h"
#define REG_WRITE(_r,_v) (*(volatile uint32 *)(_r)) = (_v)
#define REG_READ(_r) (*(volatile uint32 *)(_r))
#define WDEV_NOW() REG_READ(0x3ff20c00)
uint32 tick_now2 = 0;
void hw_test_timer_cb(void)
{
static uint16 j = 0;
j++;
if ((WDEV_NOW() - tick_now2) >= 1000000) {
static uint32 idx = 1;
tick_now2 = WDEV_NOW();
os_printf("b%u:%d\n", idx++, j);
j = 0;
}
//hw_timer_arm(50);
}
void user_init(void)
{
hw_timer_init();
hw_timer_set_func(hw_test_timer_cb,1);
hw_timer_arm(100);
}
#endif

View File

@ -0,0 +1,319 @@
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: i2c_master.c
*
* Description: i2c master API
*
* Modification history:
* 2014/3/12, v1.0 create this file.
*******************************************************************************/
#include "c_types.h"
#include "esp8266/ets_sys.h"
#include "gpio.h"
#include "i2c_master.h"
LOCAL uint8 m_nLastSDA;
LOCAL uint8 m_nLastSCL;
/******************************************************************************
* FunctionName : i2c_master_setDC
* Description : Internal used function -
* set i2c SDA and SCL bit value for half clk cycle
* Parameters : uint8 SDA
* uint8 SCL
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
i2c_master_setDC(uint8 SDA, uint8 SCL)
{
SDA &= 0x01;
SCL &= 0x01;
m_nLastSDA = SDA;
m_nLastSCL = SCL;
ETS_INTR_LOCK();
if ((0 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_LOW();
} else if ((0 == SDA) && (1 == SCL)) {
I2C_MASTER_SDA_LOW_SCL_HIGH();
} else if ((1 == SDA) && (0 == SCL)) {
I2C_MASTER_SDA_HIGH_SCL_LOW();
} else {
I2C_MASTER_SDA_HIGH_SCL_HIGH();
}
ETS_INTR_UNLOCK();
}
/******************************************************************************
* FunctionName : i2c_master_getDC
* Description : Internal used function -
* get i2c SDA bit value
* Parameters : NONE
* Returns : uint8 - SDA bit value
*******************************************************************************/
LOCAL uint8 ICACHE_FLASH_ATTR
i2c_master_getDC(void)
{
uint8 sda_out;
ETS_INTR_LOCK();
sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
ETS_INTR_UNLOCK();
return sda_out;
}
/******************************************************************************
* FunctionName : i2c_master_init
* Description : initilize I2C bus to enable i2c operations
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_init(void)
{
uint8 i;
i2c_master_setDC(1, 0);
i2c_master_wait(5);
// when SCL = 0, toggle SDA to clear up
i2c_master_setDC(0, 0) ;
i2c_master_wait(5);
i2c_master_setDC(1, 0) ;
i2c_master_wait(5);
// set data_cnt to max value
for (i = 0; i < 28; i++) {
i2c_master_setDC(1, 0);
i2c_master_wait(5); // sda 1, scl 0
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
}
// reset all
i2c_master_stop();
return;
}
/******************************************************************************
* FunctionName : i2c_master_gpio_init
* Description : config SDA and SCL gpio to open-drain output mode,
* mux and gpio num defined in i2c_master.h
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_gpio_init(void)
{
ETS_GPIO_INTR_DISABLE() ;
// ETS_INTR_LOCK();
PIN_FUNC_SELECT(I2C_MASTER_SDA_MUX, I2C_MASTER_SDA_FUNC);
PIN_FUNC_SELECT(I2C_MASTER_SCL_MUX, I2C_MASTER_SCL_FUNC);
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SDA_GPIO));
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO)), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(I2C_MASTER_SCL_GPIO))) | GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE)); //open drain;
GPIO_REG_WRITE(GPIO_ENABLE_ADDRESS, GPIO_REG_READ(GPIO_ENABLE_ADDRESS) | (1 << I2C_MASTER_SCL_GPIO));
I2C_MASTER_SDA_HIGH_SCL_HIGH();
ETS_GPIO_INTR_ENABLE() ;
// ETS_INTR_UNLOCK();
i2c_master_init();
}
/******************************************************************************
* FunctionName : i2c_master_start
* Description : set i2c to send state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_start(void)
{
i2c_master_setDC(1, m_nLastSCL);
i2c_master_wait(5);
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
i2c_master_setDC(0, 1);
i2c_master_wait(5); // sda 0, scl 1
}
/******************************************************************************
* FunctionName : i2c_master_stop
* Description : set i2c to stop sending state
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_stop(void)
{
i2c_master_wait(5);
i2c_master_setDC(0, m_nLastSCL);
i2c_master_wait(5); // sda 0
i2c_master_setDC(0, 1);
i2c_master_wait(5); // sda 0, scl 1
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
}
/******************************************************************************
* FunctionName : i2c_master_setAck
* Description : set ack to i2c bus as level value
* Parameters : uint8 level - 0 or 1
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_setAck(uint8 level)
{
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5);
i2c_master_setDC(level, 0);
i2c_master_wait(5); // sda level, scl 0
i2c_master_setDC(level, 1);
i2c_master_wait(8); // sda level, scl 1
i2c_master_setDC(level, 0);
i2c_master_wait(5); // sda level, scl 0
i2c_master_setDC(1, 0);
i2c_master_wait(5);
}
/******************************************************************************
* FunctionName : i2c_master_getAck
* Description : confirm if peer send ack
* Parameters : NONE
* Returns : uint8 - ack value, 0 or 1
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_getAck(void)
{
uint8 retVal;
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5);
i2c_master_setDC(1, 0);
i2c_master_wait(5);
i2c_master_setDC(1, 1);
i2c_master_wait(5);
retVal = i2c_master_getDC();
i2c_master_wait(5);
i2c_master_setDC(1, 0);
i2c_master_wait(5);
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_checkAck
* Description : get dev response
* Parameters : NONE
* Returns : true : get ack ; false : get nack
*******************************************************************************/
bool ICACHE_FLASH_ATTR
i2c_master_checkAck(void)
{
if(i2c_master_getAck()){
return FALSE;
}else{
return TRUE;
}
}
/******************************************************************************
* FunctionName : i2c_master_send_ack
* Description : response ack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_ack(void)
{
i2c_master_setAck(0x0);
}
/******************************************************************************
* FunctionName : i2c_master_send_nack
* Description : response nack
* Parameters : NONE
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_send_nack(void)
{
i2c_master_setAck(0x1);
}
/******************************************************************************
* FunctionName : i2c_master_readByte
* Description : read Byte from i2c bus
* Parameters : NONE
* Returns : uint8 - readed value
*******************************************************************************/
uint8 ICACHE_FLASH_ATTR
i2c_master_readByte(void)
{
uint8 retVal = 0;
uint8 k, i;
i2c_master_wait(5);
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5); // sda 1, scl 0
for (i = 0; i < 8; i++) {
i2c_master_wait(5);
i2c_master_setDC(1, 0);
i2c_master_wait(5); // sda 1, scl 0
i2c_master_setDC(1, 1);
i2c_master_wait(5); // sda 1, scl 1
k = i2c_master_getDC();
i2c_master_wait(5);
if (i == 7) {
i2c_master_wait(3); ////
}
k <<= (7 - i);
retVal |= k;
}
i2c_master_setDC(1, 0);
i2c_master_wait(5); // sda 1, scl 0
return retVal;
}
/******************************************************************************
* FunctionName : i2c_master_writeByte
* Description : write wrdata value(one byte) into i2c
* Parameters : uint8 wrdata - write value
* Returns : NONE
*******************************************************************************/
void ICACHE_FLASH_ATTR
i2c_master_writeByte(uint8 wrdata)
{
uint8 dat;
sint8 i;
i2c_master_wait(5);
i2c_master_setDC(m_nLastSDA, 0);
i2c_master_wait(5);
for (i = 7; i >= 0; i--) {
dat = wrdata >> i;
i2c_master_setDC(dat, 0);
i2c_master_wait(5);
i2c_master_setDC(dat, 1);
i2c_master_wait(5);
if (i == 0) {
i2c_master_wait(3); ////
}
i2c_master_setDC(dat, 0);
i2c_master_wait(5);
}
}

View File

@ -0,0 +1,523 @@
/**
* spi_interface.c
*
* Defines and Macros for the SPI.
*
* Copyright @ 2015 Espressif System Co., Ltd.
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are NOT permitted except as agreed by
* Espressif System Co., Ltd.
*
* 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.
*/
/**
* @file spi_interface.c
* @brief Defines and Macros for the SPI.
*/
#include "spi_interface.h"
#include "esp8266/eagle_soc.h"
#include "esp8266/ets_sys.h"
#include "esp8266/pin_mux_register.h"
#include "esp_libc.h"
//*****************************************************************************
//
// Make sure all of the definitions in this header have a C binding.
//
//*****************************************************************************
#ifdef __cplusplus
extern "C"
{
#endif
// Show the spi registers.
#define SHOWDEBUG
void __ShowRegValue(const char * func, uint32_t line)
{
#ifndef SHOWDEBUG
int i;
uint32_t regAddr = 0x60000140; // SPI--0x60000240, HSPI--0x60000140;
printf("\r\n FUNC[%s],line[%d]\r\n", func, line);
printf(" SPI_ADDR [0x%08x]\r\n", READ_PERI_REG(SPI_ADDR(SpiNum_HSPI)));
printf(" SPI_CMD [0x%08x]\r\n", READ_PERI_REG(SPI_CMD(SpiNum_HSPI)));
printf(" SPI_CTRL [0x%08x]\r\n", READ_PERI_REG(SPI_CTRL(SpiNum_HSPI)));
printf(" SPI_CTRL2 [0x%08x]\r\n", READ_PERI_REG(SPI_CTRL2(SpiNum_HSPI)));
printf(" SPI_CLOCK [0x%08x]\r\n", READ_PERI_REG(SPI_CLOCK(SpiNum_HSPI)));
printf(" SPI_RD_STATUS [0x%08x]\r\n", READ_PERI_REG(SPI_RD_STATUS(SpiNum_HSPI)));
printf(" SPI_WR_STATUS [0x%08x]\r\n", READ_PERI_REG(SPI_WR_STATUS(SpiNum_HSPI)));
printf(" SPI_USER [0x%08x]\r\n", READ_PERI_REG(SPI_USER(SpiNum_HSPI)));
printf(" SPI_USER1 [0x%08x]\r\n", READ_PERI_REG(SPI_USER1(SpiNum_HSPI)));
printf(" SPI_USER2 [0x%08x]\r\n", READ_PERI_REG(SPI_USER2(SpiNum_HSPI)));
printf(" SPI_PIN [0x%08x]\r\n", READ_PERI_REG(SPI_PIN(SpiNum_HSPI)));
printf(" SPI_SLAVE [0x%08x]\r\n", READ_PERI_REG(SPI_SLAVE(SpiNum_HSPI)));
printf(" SPI_SLAVE1 [0x%08x]\r\n", READ_PERI_REG(SPI_SLAVE1(SpiNum_HSPI)));
printf(" SPI_SLAVE2 [0x%08x]\r\n", READ_PERI_REG(SPI_SLAVE2(SpiNum_HSPI)));
for (i = 0; i < 16; ++i) {
printf(" ADDR[0x%08x],Value[0x%08x]\r\n", regAddr, READ_PERI_REG(regAddr));
regAddr += 4;
}
#endif
}
// Define SPI interrupt enable macro
#define ETS_SPI_INTR_ENABLE() _xt_isr_unmask(1 << ETS_SPI_INUM)
/**
* @brief Based on pAttr initialize SPI module.
*
*/
void ICACHE_FLASH_ATTR SPIInit(SpiNum spiNum, SpiAttr* pAttr)
{
if ((spiNum > SpiNum_HSPI)
|| (NULL == pAttr)) {
return;
}
// SPI_CPOL & SPI_CPHA
switch (pAttr->subMode) {
case SpiSubMode_1:
CLEAR_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE); // CHPA_FALLING_EDGE_SAMPLE
break;
case SpiSubMode_2:
SET_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE); // CHPA_FALLING_EDGE_SAMPLE
break;
case SpiSubMode_3:
SET_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE);
break;
case SpiSubMode_0:
default:
CLEAR_PERI_REG_MASK(SPI_PIN(spiNum), SPI_IDLE_EDGE);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_CK_OUT_EDGE);
// To do nothing
break;
}
// SPI bit order
if (SpiBitOrder_MSBFirst == pAttr->bitOrder) {
CLEAR_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_WR_BIT_ORDER);
CLEAR_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_RD_BIT_ORDER);
} else if (SpiBitOrder_LSBFirst == pAttr->bitOrder) {
SET_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_WR_BIT_ORDER);
SET_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_RD_BIT_ORDER);
} else {
// To do nothing
}
// Disable flash operation mode
// As earlier as better, if not SPI_CTRL2 can not to be set delay cycles.
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_FLASH_MODE);
// SPI mode type
if (SpiMode_Master == pAttr->mode) {
// SPI mode type
CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), SPI_SLAVE_MODE);
// SPI Send buffer
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO_HIGHPART );// By default slave send buffer C0-C7
// SPI Speed
if (1 < (pAttr->speed)) {
CLEAR_PERI_REG_MASK(SPI_CLOCK(spiNum), SPI_CLK_EQU_SYSCLK);
if (spiNum == SpiNum_HSPI) {
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI1_CLK_EQU_SYS_CLK);
}
WRITE_PERI_REG(SPI_CLOCK(spiNum),
((pAttr->speed & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
((((pAttr->speed + 1) / 2 - 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) |
((pAttr->speed & SPI_CLKCNT_L) << SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
} else {
WRITE_PERI_REG(SPI_CLOCK(spiNum), SPI_CLK_EQU_SYSCLK); // 80Mhz speed
}
// By default format:CMD+ADDR+DATA
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_MOSI );
//delay num
SET_PERI_REG_MASK(SPI_CTRL2(spiNum), ((0x1 & SPI_MISO_DELAY_NUM) << SPI_MISO_DELAY_NUM_S));
} else if (SpiMode_Slave == pAttr->mode) {
// BIT19 must do
SET_PERI_REG_MASK(SPI_PIN(spiNum), BIT19);
// SPI mode type
SET_PERI_REG_MASK(SPI_SLAVE(spiNum), SPI_SLAVE_MODE);
// SPI Send buffer
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO_HIGHPART);// By default slave send buffer C8-C15
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);
// If do not set delay cycles, slave not working,master cann't get the data.
SET_PERI_REG_MASK(SPI_CTRL2(spiNum), ((0x1 & SPI_MOSI_DELAY_NUM) << SPI_MOSI_DELAY_NUM_S)); //delay num
// SPI Speed
WRITE_PERI_REG(SPI_CLOCK(spiNum), 0);
// By default format::CMD(8bits)+ADDR(8bits)+DATA(32bytes).
SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN,
7, SPI_USR_COMMAND_BITLEN_S);
SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_WR_ADDR_BITLEN,
7, SPI_SLV_WR_ADDR_BITLEN_S);
SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_RD_ADDR_BITLEN,
7, SPI_SLV_RD_ADDR_BITLEN_S);
SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_BUF_BITLEN,
(32 * 8 - 1), SPI_SLV_BUF_BITLEN_S);
// For 8266 work on slave mode.
SET_PERI_REG_BITS(SPI_SLAVE1(spiNum), SPI_SLV_STATUS_BITLEN,
7, SPI_SLV_STATUS_BITLEN_S);
} else {
// To do nothing
}
//clear Daul or Quad lines transmission mode
CLEAR_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_QIO_MODE | SPI_DIO_MODE | SPI_DOUT_MODE | SPI_QOUT_MODE);
SET_PERI_REG_MASK(SPI_CTRL(spiNum), SPI_FASTRD_MODE);
}
/**
* @brief Set address value by master mode.
*
*/
void ICACHE_FLASH_ATTR SPIMasterCfgAddr(SpiNum spiNum, uint32_t addr)
{
if (spiNum > SpiNum_HSPI) {
return;
}
// Set address
WRITE_PERI_REG(SPI_ADDR(spiNum), addr);
}
/**
* @brief Set command value by master mode.
*
*/
void ICACHE_FLASH_ATTR SPIMasterCfgCmd(SpiNum spiNum, uint32_t cmd)
{
if (spiNum > SpiNum_HSPI) {
return;
}
// SPI_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
// bit15-0 is cmd value.
SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_VALUE, cmd, SPI_USR_COMMAND_VALUE_S);
}
/**
* @brief Send data to slave.
*
*/
int ICACHE_FLASH_ATTR SPIMasterSendData(SpiNum spiNum, SpiData* pInData)
{
char idx = 0;
if ((spiNum > SpiNum_HSPI)
|| (NULL == pInData)
|| (64 < pInData->dataLen)) {
return -1;
}
uint32_t *value = pInData->data;
while (READ_PERI_REG(SPI_CMD(spiNum))&SPI_USR);
// Set command by user.
if (pInData->cmdLen != 0) {
// Max command length 16 bits.
SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN,
((pInData->cmdLen << 3) - 1), SPI_USR_COMMAND_BITLEN_S);
// Enable command
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND);
// Load command
SPIMasterCfgCmd(spiNum, pInData->cmd);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND);
SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN,
0, SPI_USR_COMMAND_BITLEN_S);
}
// Set Address by user.
if (pInData->addrLen == 0) {
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR);
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN,
0, SPI_USR_ADDR_BITLEN_S);
} else {
if (NULL == pInData->addr) {
return -1;
}
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN,
((pInData->addrLen << 3) - 1), SPI_USR_ADDR_BITLEN_S);
// Enable address
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR);
// Load address
SPIMasterCfgAddr(spiNum, *pInData->addr);
}
// Set data by user.
if (pInData->dataLen != 0) {
if (NULL == value) {
return -1;
}
// Enable MOSI
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO);
// Load send buffer
do {
WRITE_PERI_REG((SPI_W0(spiNum) + (idx << 2)), *value++);
} while (++idx < (pInData->dataLen / 4));
// Set data send buffer length.Max data length 64 bytes.
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN, ((pInData->dataLen << 3) - 1), SPI_USR_MOSI_BITLEN_S);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO);
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN,
0, SPI_USR_MOSI_BITLEN_S);
}
// Start send data
SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR);
SHOWREG();
return 0;
}
/**
* @brief Receive data from slave.
*
*/
int ICACHE_FLASH_ATTR SPIMasterRecvData(SpiNum spiNum, SpiData* pOutData)
{
char idx = 0;
if ((spiNum > SpiNum_HSPI)
|| (NULL == pOutData)) {
return -1;
}
uint32_t *value = pOutData->data;
while (READ_PERI_REG(SPI_CMD(spiNum))&SPI_USR);
// Set command by user.
if (pOutData->cmdLen != 0) {
// Max command length 16 bits.
SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN,
((pOutData->cmdLen << 3) - 1), SPI_USR_COMMAND_BITLEN_S);
// Enable command
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND);
// Load command
SPIMasterCfgCmd(spiNum, pOutData->cmd);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_COMMAND);
SET_PERI_REG_BITS(SPI_USER2(spiNum), SPI_USR_COMMAND_BITLEN,
0, SPI_USR_COMMAND_BITLEN_S);
}
// Set Address by user.
if (pOutData->addrLen == 0) {
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR);
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN,
0, SPI_USR_ADDR_BITLEN_S);
} else {
if (NULL == pOutData->addr) {
return -1;
}
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_ADDR_BITLEN,
((pOutData->addrLen << 3) - 1), SPI_USR_ADDR_BITLEN_S);
// Enable address
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_ADDR);
// Load address
SPIMasterCfgAddr(spiNum, *pOutData->addr);
}
// Set data by user.
if (pOutData->dataLen != 0) {
if (NULL == value) {
return -1;
}
// Clear MOSI enable
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);
// Enable MOSI
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO);
// Set data send buffer length.Max data length 64 bytes.
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN, ((pOutData->dataLen << 3) - 1), SPI_USR_MISO_BITLEN_S);
} else {
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO);
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN,
0, SPI_USR_MISO_BITLEN_S);
}
//CLEAR FIFO DATA
int fifo_idx = 0;
do {
WRITE_PERI_REG(SPI_W0(spiNum) + (fifo_idx << 2), 0);
} while (++fifo_idx < (pOutData->dataLen / 4));
// Start send data
SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR);
while (READ_PERI_REG(SPI_CMD(spiNum))&SPI_USR);
// Read data out
do {
*pOutData->data++ = READ_PERI_REG(SPI_W0(spiNum) + (idx << 2));
} while (++idx < (pOutData->dataLen / 4));
SHOWREG();
return 0;
}
/**
* @brief Load data to send buffer by slave mode.
*
*/
int ICACHE_FLASH_ATTR SPISlaveSendData(SpiNum spiNum, uint32_t *pInData, uint8_t outLen)
{
if (NULL == pInData) {
return -1;
}
char i;
for (i = 0; i < outLen; ++i) {
WRITE_PERI_REG((SPI_W8(spiNum) + (i << 2)), *pInData++);
}
return 0;
}
/**
* @brief Configurate slave prepare for receive data.
*
*/
int ICACHE_FLASH_ATTR SPISlaveRecvData(SpiNum spiNum, void(*isrFunc)(void*))
{
if ((spiNum > SpiNum_HSPI)) {
return -1;
}
SPIIntEnable(SpiNum_HSPI, SpiIntSrc_WrStaDoneEn
| SpiIntSrc_RdStaDoneEn | SpiIntSrc_WrBufDoneEn | SpiIntSrc_RdBufDoneEn);
SPIIntDisable(SpiNum_HSPI, SpiIntSrc_TransDoneEn);
// Maybe enable slave transmission liston
SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR);
//
_xt_isr_attach(ETS_SPI_INUM, isrFunc, NULL);
// ETS_SPI_INTR_ATTACH(isrFunc, NULL);
// Enable isr
ETS_SPI_INTR_ENABLE();
SHOWREG();
return 0;
}
/**
* @brief Send data to slave(ESP8266 register of RD_STATUS or WR_STATUS).
*
*/
void ICACHE_FLASH_ATTR SPIMasterSendStatus(SpiNum spiNum, uint8_t data)
{
if (spiNum > SpiNum_HSPI) {
return;
}
while (READ_PERI_REG(SPI_CMD(spiNum))&SPI_USR);
// Enable MOSI
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
// 8bits cmd, 0x04 is eps8266 slave write cmd value
WRITE_PERI_REG(SPI_USER2(spiNum),
((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S)
| MASTER_WRITE_STATUS_TO_SLAVE_CMD);
// Set data send buffer length.
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MOSI_BITLEN,
((sizeof(data) << 3) - 1), SPI_USR_MOSI_BITLEN_S);
WRITE_PERI_REG(SPI_W0(spiNum), (uint32)(data));
// Start SPI
SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR);
SHOWREG();
}
/**
* @brief Receive status register from slave(ESP8266).
*
*/
int ICACHE_FLASH_ATTR SPIMasterRecvStatus(SpiNum spiNum)
{
if (spiNum > SpiNum_HSPI) {
return -1;
}
while (READ_PERI_REG(SPI_CMD(spiNum))&SPI_USR);
// Enable MISO
SET_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MISO);
CLEAR_PERI_REG_MASK(SPI_USER(spiNum), SPI_USR_MOSI | SPI_USR_DUMMY | SPI_USR_ADDR);
// 8bits cmd, 0x06 is eps8266 slave read status cmd value
WRITE_PERI_REG(SPI_USER2(spiNum),
((7 & SPI_USR_COMMAND_BITLEN) << SPI_USR_COMMAND_BITLEN_S)
| MASTER_READ_STATUS_FROM_SLAVE_CMD);
// Set revcive buffer length.
SET_PERI_REG_BITS(SPI_USER1(spiNum), SPI_USR_MISO_BITLEN,
7, SPI_USR_MISO_BITLEN_S);
// start spi module.
SET_PERI_REG_MASK(SPI_CMD(spiNum), SPI_USR);
while (READ_PERI_REG(SPI_CMD(spiNum))&SPI_USR);
uint8_t data = (uint8)(READ_PERI_REG(SPI_W0(spiNum)) & 0xff);
SHOWREG();
return (uint8)(READ_PERI_REG(SPI_W0(spiNum)) & 0xff);
}
/**
* @brief Select SPI CS pin.
*
*/
void ICACHE_FLASH_ATTR SPICsPinSelect(SpiNum spiNum, SpiPinCS pinCs)
{
if (spiNum > SpiNum_HSPI) {
return;
}
// clear select
SET_PERI_REG_BITS(SPI_PIN(spiNum), 3, 0, 0);
SET_PERI_REG_MASK(SPI_PIN(spiNum), pinCs);
}
/**
* @brief Enable SPI interrupt source.
*
*/
void ICACHE_FLASH_ATTR SPIIntEnable(SpiNum spiNum, SpiIntSrc intSrc)
{
if (spiNum > SpiNum_HSPI) {
return;
}
SET_PERI_REG_MASK(SPI_SLAVE(spiNum), intSrc);
}
/**
* @brief Disable SPI interrupt source.
*
*/
void ICACHE_FLASH_ATTR SPIIntDisable(SpiNum spiNum, SpiIntSrc intSrc)
{
if (spiNum > SpiNum_HSPI) {
return;
}
CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), intSrc);
}
/**
* @brief Clear all of SPI interrupt source.
*
*/
void ICACHE_FLASH_ATTR SPIIntClear(SpiNum spiNum)
{
if (spiNum > SpiNum_HSPI) {
return;
}
CLEAR_PERI_REG_MASK(SPI_SLAVE(spiNum), SpiIntSrc_TransDoneEn
| SpiIntSrc_WrStaDoneEn
| SpiIntSrc_RdStaDoneEn
| SpiIntSrc_WrBufDoneEn
| SpiIntSrc_RdBufDoneEn);
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,435 @@
/*
* 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.
*
*/
#include "esp_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "uart.h"
enum {
UART_EVENT_RX_CHAR,
UART_EVENT_MAX
};
typedef struct _os_event_ {
uint32 event;
uint32 param;
} os_event_t;
xTaskHandle xUartTaskHandle;
xQueueHandle xQueueUart;
LOCAL STATUS
uart_tx_one_char(uint8 uart, uint8 TxChar)
{
while (true) {
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
break;
}
}
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
return OK;
}
LOCAL void
uart1_write_char(char c)
{
if (c == '\n') {
uart_tx_one_char(UART1, '\r');
uart_tx_one_char(UART1, '\n');
} else if (c == '\r') {
} else {
uart_tx_one_char(UART1, c);
}
}
LOCAL void
uart0_write_char(char c)
{
if (c == '\n') {
uart_tx_one_char(UART0, '\r');
uart_tx_one_char(UART0, '\n');
} else if (c == '\r') {
} else {
uart_tx_one_char(UART0, c);
}
}
LOCAL void
uart_rx_intr_handler_ssc(void *arg)
{
/* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
* uart1 and uart0 respectively
*/
os_event_t e;
portBASE_TYPE xHigherPriorityTaskWoken;
uint8 RcvChar;
uint8 uart_no = 0;
if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)) {
return;
}
RcvChar = READ_PERI_REG(UART_FIFO(uart_no)) & 0xFF;
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_FULL_INT_CLR);
e.event = UART_EVENT_RX_CHAR;
e.param = RcvChar;
xQueueSendFromISR(xQueueUart, (void *)&e, &xHigherPriorityTaskWoken);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
#if 0
LOCAL void
uart_config(uint8 uart_no, UartDevice *uart)
{
if (uart_no == UART1) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
} else {
/* rcv_buff size if 0x100 */
_xt_isr_attach(ETS_UART_INUM, uart_rx_intr_handler_ssc, NULL);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
}
uart_div_modify(uart_no, UART_CLK_FREQ / (uart->baut_rate));
WRITE_PERI_REG(UART_CONF0(uart_no), uart->exist_parity
| uart->parity
| (uart->stop_bits << UART_STOP_BIT_NUM_S)
| (uart->data_bits << UART_BIT_NUM_S));
//clear rx and tx fifo,not ready
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
if (uart_no == UART0) {
//set rx fifo trigger
WRITE_PERI_REG(UART_CONF1(uart_no),
((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));
} else {
WRITE_PERI_REG(UART_CONF1(uart_no),
((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));
}
//clear all interrupt
WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
//enable rx_interrupt
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA);
}
#endif
LOCAL void
uart_task(void *pvParameters)
{
os_event_t e;
for (;;) {
if (xQueueReceive(xQueueUart, (void *)&e, (portTickType)portMAX_DELAY)) {
switch (e.event) {
case UART_EVENT_RX_CHAR:
printf("%c", e.param);
break;
default:
break;
}
}
}
vTaskDelete(NULL);
}
#if 0
void
uart_init(void)
{
while (READ_PERI_REG(UART_STATUS(0)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S));
while (READ_PERI_REG(UART_STATUS(1)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S));
UART_ConfigTypeDef uart;
uart.baut_rate = BIT_RATE_74880;
uart.data_bits = UART_WordLength_8b;
uart.flow_ctrl = USART_HardwareFlowControl_None;
// uart.exist_parity = PARITY_DIS;
uart.parity = USART_Parity_None;
uart.stop_bits = USART_StopBits_1;
uart_config(UART0, &uart);
uart_config(UART1, &uart);
os_install_putc1(uart1_write_char);
_xt_isr_unmask(1 << ETS_UART_INUM);
xQueueUart = xQueueCreate(32, sizeof(os_event_t));
xTaskCreate(uart_task, (uint8 const *)"uTask", 512, NULL, tskIDLE_PRIORITY + 2, &xUartTaskHandle);
}
#endif
//=================================================================
void
UART_SetWordLength(UART_Port uart_no, UART_WordLength len)
{
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_BIT_NUM, len, UART_BIT_NUM_S);
}
void
UART_SetStopBits(UART_Port uart_no, UART_StopBits bit_num)
{
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_STOP_BIT_NUM, bit_num, UART_STOP_BIT_NUM_S);
}
void
UART_SetLineInverse(UART_Port uart_no, UART_LineLevelInverse inverse_mask)
{
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK);
SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask);
}
void
UART_SetParity(UART_Port uart_no, UART_ParityMode Parity_mode)
{
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN);
if (Parity_mode == USART_Parity_None) {
} else {
SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN);
}
}
void
UART_SetBaudrate(UART_Port uart_no, uint32 baud_rate)
{
uart_div_modify(uart_no, UART_CLK_FREQ / baud_rate);
}
//only when USART_HardwareFlowControl_RTS is set , will the rx_thresh value be set.
void
UART_SetFlowCtrl(UART_Port uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh)
{
if (flow_ctrl & USART_HardwareFlowControl_RTS) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
SET_PERI_REG_BITS(UART_CONF1(uart_no), UART_RX_FLOW_THRHD, rx_thresh, UART_RX_FLOW_THRHD_S);
SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
} else {
CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN);
}
if (flow_ctrl & USART_HardwareFlowControl_CTS) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
} else {
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN);
}
}
void
UART_WaitTxFifoEmpty(UART_Port uart_no) //do not use if tx flow control enabled
{
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S));
}
void
UART_ResetFifo(UART_Port uart_no)
{
SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
}
void
UART_ClearIntrStatus(UART_Port uart_no, uint32 clr_mask)
{
WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
}
void
UART_SetIntrEna(UART_Port uart_no, uint32 ena_mask)
{
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
}
void
UART_intr_handler_register(void *fn, void *arg)
{
_xt_isr_attach(ETS_UART_INUM, fn, arg);
}
void
UART_SetPrintPort(UART_Port uart_no)
{
if (uart_no == 1) {
os_install_putc1(uart1_write_char);
} else {
os_install_putc1(uart0_write_char);
}
}
void
UART_ParamConfig(UART_Port uart_no, UART_ConfigTypeDef *pUARTConfig)
{
if (uart_no == UART1) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
} else {
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
}
UART_SetFlowCtrl(uart_no, pUARTConfig->flow_ctrl, pUARTConfig->UART_RxFlowThresh);
UART_SetBaudrate(uart_no, pUARTConfig->baud_rate);
WRITE_PERI_REG(UART_CONF0(uart_no),
((pUARTConfig->parity == USART_Parity_None) ? 0x0 : (UART_PARITY_EN | pUARTConfig->parity))
| (pUARTConfig->stop_bits << UART_STOP_BIT_NUM_S)
| (pUARTConfig->data_bits << UART_BIT_NUM_S)
| ((pUARTConfig->flow_ctrl & USART_HardwareFlowControl_CTS) ? UART_TX_FLOW_EN : 0x0)
| pUARTConfig->UART_InverseMask);
UART_ResetFifo(uart_no);
}
void
UART_IntrConfig(UART_Port uart_no, UART_IntrConfTypeDef *pUARTIntrConf)
{
uint32 reg_val = 0;
UART_ClearIntrStatus(uart_no, UART_INTR_MASK);
reg_val = READ_PERI_REG(UART_CONF1(uart_no)) & ((UART_RX_FLOW_THRHD << UART_RX_FLOW_THRHD_S) | UART_RX_FLOW_EN) ;
reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_RXFIFO_TOUT_INT_ENA) ?
((((pUARTIntrConf->UART_RX_TimeOutIntrThresh)&UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S) | UART_RX_TOUT_EN) : 0);
reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_RXFIFO_FULL_INT_ENA) ?
(((pUARTIntrConf->UART_RX_FifoFullIntrThresh)&UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) : 0);
reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_TXFIFO_EMPTY_INT_ENA) ?
(((pUARTIntrConf->UART_TX_FifoEmptyIntrThresh)&UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) : 0);
WRITE_PERI_REG(UART_CONF1(uart_no), reg_val);
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_INTR_MASK);
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), pUARTIntrConf->UART_IntrEnMask);
}
LOCAL void
uart0_rx_intr_handler(void *para)
{
/* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
* uart1 and uart0 respectively
*/
uint8 RcvChar;
uint8 uart_no = UART0;//UartDev.buff_uart_no;
uint8 fifo_len = 0;
uint8 buf_idx = 0;
uint8 fifo_tmp[128] = {0};
uint32 uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
while (uart_intr_status != 0x0) {
if (UART_FRM_ERR_INT_ST == (uart_intr_status & UART_FRM_ERR_INT_ST)) {
//printf("FRM_ERR\r\n");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
} else if (UART_RXFIFO_FULL_INT_ST == (uart_intr_status & UART_RXFIFO_FULL_INT_ST)) {
printf("full\r\n");
fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
buf_idx = 0;
while (buf_idx < fifo_len) {
uart_tx_one_char(UART0, READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
buf_idx++;
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
} else if (UART_RXFIFO_TOUT_INT_ST == (uart_intr_status & UART_RXFIFO_TOUT_INT_ST)) {
printf("tout\r\n");
fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
buf_idx = 0;
while (buf_idx < fifo_len) {
uart_tx_one_char(UART0, READ_PERI_REG(UART_FIFO(UART0)) & 0xFF);
buf_idx++;
}
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
} else if (UART_TXFIFO_EMPTY_INT_ST == (uart_intr_status & UART_TXFIFO_EMPTY_INT_ST)) {
printf("empty\n\r");
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
} else {
//skip
}
uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
}
}
void
uart_init_new(void)
{
UART_WaitTxFifoEmpty(UART0);
UART_WaitTxFifoEmpty(UART1);
UART_ConfigTypeDef uart_config;
uart_config.baud_rate = BIT_RATE_74880;
uart_config.data_bits = UART_WordLength_8b;
uart_config.parity = USART_Parity_None;
uart_config.stop_bits = USART_StopBits_1;
uart_config.flow_ctrl = USART_HardwareFlowControl_None;
uart_config.UART_RxFlowThresh = 120;
uart_config.UART_InverseMask = UART_None_Inverse;
UART_ParamConfig(UART0, &uart_config);
UART_IntrConfTypeDef uart_intr;
uart_intr.UART_IntrEnMask = UART_RXFIFO_TOUT_INT_ENA | UART_FRM_ERR_INT_ENA | UART_RXFIFO_FULL_INT_ENA | UART_TXFIFO_EMPTY_INT_ENA;
uart_intr.UART_RX_FifoFullIntrThresh = 10;
uart_intr.UART_RX_TimeOutIntrThresh = 2;
uart_intr.UART_TX_FifoEmptyIntrThresh = 20;
UART_IntrConfig(UART0, &uart_intr);
UART_SetPrintPort(UART0);
UART_intr_handler_register(uart0_rx_intr_handler, NULL);
ETS_UART_INTR_ENABLE();
/*
UART_SetWordLength(UART0,UART_WordLength_8b);
UART_SetStopBits(UART0,USART_StopBits_1);
UART_SetParity(UART0,USART_Parity_None);
UART_SetBaudrate(UART0,74880);
UART_SetFlowCtrl(UART0,USART_HardwareFlowControl_None,0);
*/
}