Added the (possibly modified) Espressif SDK to the project to avoid problems with building. This may not be OK license wise, but who cares
This commit is contained in:
+44
@@ -0,0 +1,44 @@
|
||||
|
||||
#############################################################
|
||||
# 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
|
||||
INCLUDES += -I ./
|
||||
PDIR := ../$(PDIR)
|
||||
sinclude $(PDIR)Makefile
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "driver/gpio16.h"
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
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 ICACHE_FLASH_ATTR
|
||||
gpio16_output_set(uint8 value)
|
||||
{
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT,
|
||||
(READ_PERI_REG(RTC_GPIO_OUT) & (uint32)0xfffffffe) | (uint32)(value & 1));
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
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 ICACHE_FLASH_ATTR
|
||||
gpio16_input_get(void)
|
||||
{
|
||||
return (uint8)(READ_PERI_REG(RTC_GPIO_IN_DATA) & 1);
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013-2014 Espressif Systems (Wuxi)
|
||||
*
|
||||
* FileName: hw_timer.c
|
||||
*
|
||||
* Description: hw_timer driver
|
||||
*
|
||||
* Modification history:
|
||||
* 2014/5/1, v1.0 create this file.
|
||||
*******************************************************************************/
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.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
|
||||
|
||||
//TIMER PREDIVED MODE
|
||||
typedef enum {
|
||||
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;
|
||||
|
||||
typedef enum {
|
||||
FRC1_SOURCE = 0,
|
||||
NMI_SOURCE = 1,
|
||||
} FRC1_TIMER_SOURCE_TYPE;
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : hw_timer_arm
|
||||
* Description : set a trigger timer delay for this timer.
|
||||
* Parameters : uint32 val :
|
||||
in autoload mode
|
||||
50 ~ 0x7fffff; for FRC1 source.
|
||||
100 ~ 0x7fffff; for NMI source.
|
||||
in non autoload mode:
|
||||
10 ~ 0x7fffff;
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void hw_timer_arm(u32 val)
|
||||
{
|
||||
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, US_TO_RTC_TIMER_TICKS(val));
|
||||
}
|
||||
|
||||
static void (* user_hw_timer_cb)(void) = NULL;
|
||||
/******************************************************************************
|
||||
* FunctionName : hw_timer_set_func
|
||||
* Description : set the func, when trigger timer is up.
|
||||
* Parameters : void (* user_hw_timer_cb_set)(void):
|
||||
timer callback function,
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void hw_timer_set_func(void (* user_hw_timer_cb_set)(void))
|
||||
{
|
||||
user_hw_timer_cb = user_hw_timer_cb_set;
|
||||
}
|
||||
|
||||
static void hw_timer_isr_cb(void)
|
||||
{
|
||||
if (user_hw_timer_cb != NULL) {
|
||||
(*(user_hw_timer_cb))();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : hw_timer_init
|
||||
* Description : initilize the hardware isr timer
|
||||
* Parameters :
|
||||
FRC1_TIMER_SOURCE_TYPE source_type:
|
||||
FRC1_SOURCE, timer use frc1 isr as isr source.
|
||||
NMI_SOURCE, timer use nmi isr as isr source.
|
||||
u8 req:
|
||||
0, not autoload,
|
||||
1, autoload mode,
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR hw_timer_init(FRC1_TIMER_SOURCE_TYPE source_type, u8 req)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
if (source_type == NMI_SOURCE) {
|
||||
ETS_FRC_TIMER1_NMI_INTR_ATTACH(hw_timer_isr_cb);
|
||||
} else {
|
||||
ETS_FRC_TIMER1_INTR_ATTACH(hw_timer_isr_cb, NULL);
|
||||
}
|
||||
|
||||
TM1_EDGE_INT_ENABLE();
|
||||
ETS_FRC1_INTR_ENABLE();
|
||||
}
|
||||
|
||||
//-------------------------------Test Code Below--------------------------------------
|
||||
#if 0
|
||||
void hw_test_timer_cb(void)
|
||||
{
|
||||
static uint16 j = 0;
|
||||
j++;
|
||||
|
||||
if ((WDEV_NOW() - tick_now2) >= 1000000) {
|
||||
static u32 idx = 1;
|
||||
tick_now2 = WDEV_NOW();
|
||||
os_printf("b%u:%d\n", idx++, j);
|
||||
j = 0;
|
||||
}
|
||||
|
||||
//hw_timer_arm(50);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR user_init(void)
|
||||
{
|
||||
hw_timer_init(FRC1_SOURCE, 1);
|
||||
hw_timer_set_func(hw_test_timer_cb);
|
||||
hw_timer_arm(100);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
NOTE:
|
||||
1 if use nmi source, for autoload timer , the timer setting val can't be less than 100.
|
||||
2 if use nmi source, this timer has highest priority, can interrupt other isr.
|
||||
3 if use frc1 source, this timer can't interrupt other isr.
|
||||
|
||||
*/
|
||||
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
/******************************************************************************
|
||||
* 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 "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#include "driver/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;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* 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;
|
||||
sda_out = GPIO_INPUT_GET(GPIO_ID_PIN(I2C_MASTER_SDA_GPIO));
|
||||
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);
|
||||
}
|
||||
}
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/******************************************************************************
|
||||
* Copyright 2013-2014 Espressif Systems (Wuxi)
|
||||
*
|
||||
* FileName: key.c
|
||||
*
|
||||
* Description: key driver, now can use different gpio and install different function
|
||||
*
|
||||
* Modification history:
|
||||
* 2014/5/1, v1.0 create this file.
|
||||
*******************************************************************************/
|
||||
#include "ets_sys.h"
|
||||
#include "os_type.h"
|
||||
#include "osapi.h"
|
||||
#include "mem.h"
|
||||
#include "gpio.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
#include "driver/key.h"
|
||||
|
||||
LOCAL void key_intr_handler(struct keys_param *keys);
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : key_init_single
|
||||
* Description : init single key's gpio and register function
|
||||
* Parameters : uint8 gpio_id - which gpio to use
|
||||
* uint32 gpio_name - gpio mux name
|
||||
* uint32 gpio_func - gpio function
|
||||
* key_function long_press - long press function, needed to install
|
||||
* key_function short_press - short press function, needed to install
|
||||
* Returns : single_key_param - single key parameter, needed by key init
|
||||
*******************************************************************************/
|
||||
struct single_key_param *ICACHE_FLASH_ATTR
|
||||
key_init_single(uint8 gpio_id, uint32 gpio_name, uint8 gpio_func, key_function long_press, key_function short_press)
|
||||
{
|
||||
struct single_key_param *single_key = (struct single_key_param *)os_zalloc(sizeof(struct single_key_param));
|
||||
|
||||
single_key->gpio_id = gpio_id;
|
||||
single_key->gpio_name = gpio_name;
|
||||
single_key->gpio_func = gpio_func;
|
||||
single_key->long_press = long_press;
|
||||
single_key->short_press = short_press;
|
||||
|
||||
return single_key;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : key_init
|
||||
* Description : init keys
|
||||
* Parameters : key_param *keys - keys parameter, which inited by key_init_single
|
||||
* Returns : none
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
key_init(struct keys_param *keys)
|
||||
{
|
||||
uint8 i;
|
||||
|
||||
ETS_GPIO_INTR_ATTACH(key_intr_handler, keys);
|
||||
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
|
||||
for (i = 0; i < keys->key_num; i++) {
|
||||
keys->single_key[i]->key_level = 1;
|
||||
|
||||
PIN_FUNC_SELECT(keys->single_key[i]->gpio_name, keys->single_key[i]->gpio_func);
|
||||
|
||||
gpio_output_set(0, 0, 0, GPIO_ID_PIN(keys->single_key[i]->gpio_id));
|
||||
|
||||
gpio_register_set(GPIO_PIN_ADDR(keys->single_key[i]->gpio_id), GPIO_PIN_INT_TYPE_SET(GPIO_PIN_INTR_DISABLE)
|
||||
| GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_DISABLE)
|
||||
| GPIO_PIN_SOURCE_SET(GPIO_AS_PIN_SOURCE));
|
||||
|
||||
//clear gpio14 status
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(keys->single_key[i]->gpio_id));
|
||||
|
||||
//enable interrupt
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_NEGEDGE);
|
||||
}
|
||||
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : key_5s_cb
|
||||
* Description : long press 5s timer callback
|
||||
* Parameters : single_key_param *single_key - single key parameter
|
||||
* Returns : none
|
||||
*******************************************************************************/
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
key_5s_cb(struct single_key_param *single_key)
|
||||
{
|
||||
os_timer_disarm(&single_key->key_5s);
|
||||
|
||||
// low, then restart
|
||||
if (0 == GPIO_INPUT_GET(GPIO_ID_PIN(single_key->gpio_id))) {
|
||||
if (single_key->long_press) {
|
||||
single_key->long_press();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : key_50ms_cb
|
||||
* Description : 50ms timer callback to check it's a real key push
|
||||
* Parameters : single_key_param *single_key - single key parameter
|
||||
* Returns : none
|
||||
*******************************************************************************/
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
key_50ms_cb(struct single_key_param *single_key)
|
||||
{
|
||||
os_timer_disarm(&single_key->key_50ms);
|
||||
|
||||
// high, then key is up
|
||||
if (1 == GPIO_INPUT_GET(GPIO_ID_PIN(single_key->gpio_id))) {
|
||||
os_timer_disarm(&single_key->key_5s);
|
||||
single_key->key_level = 1;
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(single_key->gpio_id), GPIO_PIN_INTR_NEGEDGE);
|
||||
|
||||
if (single_key->short_press) {
|
||||
single_key->short_press();
|
||||
}
|
||||
} else {
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(single_key->gpio_id), GPIO_PIN_INTR_POSEDGE);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : key_intr_handler
|
||||
* Description : key interrupt handler
|
||||
* Parameters : key_param *keys - keys parameter, which inited by key_init_single
|
||||
* Returns : none
|
||||
*******************************************************************************/
|
||||
LOCAL void
|
||||
key_intr_handler(struct keys_param *keys)
|
||||
{
|
||||
uint8 i;
|
||||
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
|
||||
|
||||
for (i = 0; i < keys->key_num; i++) {
|
||||
if (gpio_status & BIT(keys->single_key[i]->gpio_id)) {
|
||||
//disable interrupt
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_DISABLE);
|
||||
|
||||
//clear interrupt status
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(keys->single_key[i]->gpio_id));
|
||||
|
||||
if (keys->single_key[i]->key_level == 1) {
|
||||
// 5s, restart & enter softap mode
|
||||
os_timer_disarm(&keys->single_key[i]->key_5s);
|
||||
os_timer_setfn(&keys->single_key[i]->key_5s, (os_timer_func_t *)key_5s_cb, keys->single_key[i]);
|
||||
os_timer_arm(&keys->single_key[i]->key_5s, 5000, 0);
|
||||
keys->single_key[i]->key_level = 0;
|
||||
gpio_pin_intr_state_set(GPIO_ID_PIN(keys->single_key[i]->gpio_id), GPIO_PIN_INTR_POSEDGE);
|
||||
} else {
|
||||
// 50ms, check if this is a real key up
|
||||
os_timer_disarm(&keys->single_key[i]->key_50ms);
|
||||
os_timer_setfn(&keys->single_key[i]->key_50ms, (os_timer_func_t *)key_50ms_cb, keys->single_key[i]);
|
||||
os_timer_arm(&keys->single_key[i]->key_50ms, 50, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+433
@@ -0,0 +1,433 @@
|
||||
#include "driver/slc_register.h"
|
||||
#include "driver/sdio_slv.h"
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "os_type.h"
|
||||
//#include "gpio.h"
|
||||
#include "user_interface.h"
|
||||
#include "mem.h"
|
||||
|
||||
#define SDIO_TOKEN_SIZE 0//4
|
||||
#define RX_BUFFER_SIZE 512
|
||||
#define RX_BUFFER_NUM 4
|
||||
|
||||
#define TX_BUFFER_SIZE 512
|
||||
#define SLC_INTEREST_EVENT (SLC_TX_EOF_INT_ENA | SLC_RX_EOF_INT_ENA | SLC_RX_UDF_INT_ENA | SLC_TX_DSCR_ERR_INT_ENA)
|
||||
#define TRIG_TOHOST_INT() SET_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0);\
|
||||
//CLEAR_PERI_REG_MASK(SLC_INTVEC_TOHOST , BIT0)
|
||||
struct sdio_queue
|
||||
{
|
||||
uint32 blocksize:12;
|
||||
uint32 datalen:12;
|
||||
uint32 unused:5;
|
||||
uint32 sub_sof:1;
|
||||
uint32 eof:1;
|
||||
uint32 owner:1;
|
||||
|
||||
uint32 buf_ptr;
|
||||
uint32 next_link_ptr;
|
||||
};
|
||||
|
||||
struct sdio_slave_status_element
|
||||
{
|
||||
uint32 wr_busy:1;
|
||||
uint32 rd_empty :1;
|
||||
uint32 comm_cnt :3;
|
||||
uint32 intr_no :3;
|
||||
uint32 rx_length:16;
|
||||
uint32 res:8;
|
||||
};
|
||||
|
||||
union sdio_slave_status
|
||||
{
|
||||
struct sdio_slave_status_element elm_value;
|
||||
uint32 word_value;
|
||||
};
|
||||
|
||||
//uint8 rx_buffer[RX_BUFFER_NUM][RX_BUFFER_SIZE],tx_buffer[1024];
|
||||
uint8 tx_buffer[TX_BUFFER_SIZE];
|
||||
|
||||
uint32 data_len = 0;
|
||||
|
||||
struct sdio_list {
|
||||
uint8 buffer[RX_BUFFER_SIZE + SDIO_TOKEN_SIZE];
|
||||
uint8* tail;
|
||||
struct sdio_list* next;
|
||||
};
|
||||
|
||||
static sdio_recv_data_callback_t sdio_recv_data_callback_ptr = NULL;
|
||||
struct sdio_list* pHead_ToSend;
|
||||
struct sdio_list* pTail_ToSend;
|
||||
struct sdio_list* pHead_Sended;
|
||||
struct sdio_list* pTail_Sended;
|
||||
|
||||
|
||||
|
||||
os_event_t * sdioQueue;
|
||||
struct sdio_queue rx_que,tx_que;
|
||||
|
||||
static bool has_read = 0;
|
||||
|
||||
static void sdio_slave_isr(void *para);
|
||||
static void tx_buff_handle_done(void);
|
||||
static void rx_buff_read_done(void);
|
||||
static void tx_buff_write_done(void);
|
||||
|
||||
static void sdio_try_to_load(void);
|
||||
static void sdio_read_done_process(void);
|
||||
|
||||
void sdio_slave_init(void)
|
||||
{
|
||||
uint32 regval = 0;
|
||||
union sdio_slave_status sdio_sta;
|
||||
ETS_SDIO_INTR_DISABLE();
|
||||
////reset orginal link
|
||||
SET_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST|SLC_TXLINK_RST);
|
||||
CLEAR_PERI_REG_MASK(SLC_CONF0, SLC_RXLINK_RST|SLC_TXLINK_RST);
|
||||
|
||||
os_printf("RX&TX link reset!\n");
|
||||
|
||||
//set sdio mode
|
||||
SET_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_RX_EOF_MODE | SLC_RX_FILL_MODE);
|
||||
//clear to host interrupt io signal for preventing from random initial signal.
|
||||
WRITE_PERI_REG(SLC_HOST_INTR_CLR, 0xffffffff);
|
||||
//enable 2 events to trigger the to host intr io
|
||||
SET_PERI_REG_MASK(SLC_HOST_INTR_ENA , SLC_HOST_TOHOST_BIT0_INT_ENA);
|
||||
////initialize rx queue information
|
||||
|
||||
has_read = TRUE;
|
||||
pHead_ToSend = NULL;
|
||||
|
||||
int loop = RX_BUFFER_NUM;
|
||||
struct sdio_list* p = NULL;
|
||||
while(loop--) {
|
||||
if(pHead_Sended == NULL) {
|
||||
pHead_Sended = (struct sdio_list*)os_malloc(sizeof(struct sdio_list));
|
||||
p = pHead_Sended;
|
||||
} else {
|
||||
p->next = (struct sdio_list*)os_malloc(sizeof(struct sdio_list));
|
||||
p = p->next;
|
||||
}
|
||||
//os_printf("p:0x%08x\r\n",p);
|
||||
p->tail = p->buffer + SDIO_TOKEN_SIZE;
|
||||
p->next = NULL;
|
||||
}
|
||||
pTail_Sended = p;
|
||||
|
||||
rx_que.blocksize = RX_BUFFER_SIZE;
|
||||
rx_que.datalen=0;
|
||||
rx_que.eof=1;
|
||||
rx_que.owner=1;
|
||||
rx_que.sub_sof=0;
|
||||
rx_que.unused=0;
|
||||
rx_que.buf_ptr=(uint32)pHead_Sended->buffer;
|
||||
rx_que.next_link_ptr=0;
|
||||
|
||||
|
||||
////initialize tx queue information
|
||||
tx_que.blocksize=TX_BUFFER_SIZE;
|
||||
tx_que.datalen=0;
|
||||
tx_que.eof=0;
|
||||
tx_que.owner=1;
|
||||
tx_que.sub_sof=0;
|
||||
tx_que.unused=0;
|
||||
tx_que.buf_ptr=(uint32)tx_buffer;
|
||||
tx_que.next_link_ptr=0;
|
||||
|
||||
///////link tx&rx queue information address to sdio hardware
|
||||
CLEAR_PERI_REG_MASK(SLC_RX_LINK,SLC_RXLINK_DESCADDR_MASK);
|
||||
regval= ((uint32)&rx_que);
|
||||
SET_PERI_REG_MASK(SLC_RX_LINK, regval&SLC_RXLINK_DESCADDR_MASK);
|
||||
CLEAR_PERI_REG_MASK(SLC_TX_LINK,SLC_TXLINK_DESCADDR_MASK);
|
||||
regval= ((uint32)&tx_que);
|
||||
SET_PERI_REG_MASK(SLC_TX_LINK, regval&SLC_TXLINK_DESCADDR_MASK);
|
||||
|
||||
#if (SDIO_TOKEN_SIZE == 0)
|
||||
SET_PERI_REG_MASK(SLC_RX_DSCR_CONF, SLC_TOKEN_NO_REPLACE);
|
||||
#endif
|
||||
|
||||
/////config sdio_status reg
|
||||
sdio_sta.elm_value.comm_cnt=7;
|
||||
sdio_sta.elm_value.intr_no=INIT_STAGE;
|
||||
sdio_sta.elm_value.wr_busy=0;
|
||||
sdio_sta.elm_value.rd_empty=1;
|
||||
sdio_sta.elm_value.rx_length=0;
|
||||
sdio_sta.elm_value.res=0;
|
||||
SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START);
|
||||
WRITE_PERI_REG(SLC_HOST_CONF_W2, sdio_sta.word_value);
|
||||
|
||||
|
||||
/////attach isr func to sdio interrupt
|
||||
ETS_SDIO_INTR_ATTACH(sdio_slave_isr, NULL);
|
||||
/////enable sdio operation intr
|
||||
WRITE_PERI_REG(SLC_INT_ENA, SLC_INTEREST_EVENT);
|
||||
/////clear sdio initial random active intr signal
|
||||
WRITE_PERI_REG(SLC_INT_CLR, 0xffffffff);
|
||||
/////enable sdio intr in cpu
|
||||
ETS_SDIO_INTR_ENABLE();
|
||||
}
|
||||
|
||||
static void sdio_slave_isr(void *para)
|
||||
{
|
||||
uint32 slc_intr_status,postval;
|
||||
static uint8 state =0;
|
||||
uint16 rx_len,i;
|
||||
uint32* pword;
|
||||
union sdio_slave_status sdio_sta;
|
||||
|
||||
slc_intr_status = READ_PERI_REG(SLC_INT_STATUS);
|
||||
|
||||
if (slc_intr_status == 0)
|
||||
{
|
||||
/* No interested interrupts pending */
|
||||
return;
|
||||
}
|
||||
//clear all intrs
|
||||
WRITE_PERI_REG(SLC_INT_CLR, slc_intr_status);
|
||||
//os_printf("slc_intr_status:0x%08x\r\n",slc_intr_status);
|
||||
//process every intr
|
||||
|
||||
//TO HOST DONE
|
||||
if (slc_intr_status & SLC_RX_EOF_INT_ENA)
|
||||
{
|
||||
//following code must be called after a data pack has been read
|
||||
rx_buff_read_done();
|
||||
//TRIG_TOHOST_INT();
|
||||
//system_os_post(2, 1, 0);
|
||||
sdio_read_done_process();
|
||||
}
|
||||
|
||||
//FROM HOST DONE
|
||||
if (slc_intr_status & SLC_TX_EOF_INT_ENA)
|
||||
{
|
||||
//call the following function after host cpu data transmission finished
|
||||
tx_buff_write_done();
|
||||
|
||||
//system_os_post(USER_TASK_PRIO_1,SDIO_DATA_ERROR,0);
|
||||
//os_printf("%d,%s\r\n",tx_que.datalen,tx_que.buf_ptr);
|
||||
//at_fake_uart_rx((uint8*)tx_que.buf_ptr,tx_que.datalen);
|
||||
if(sdio_recv_data_callback_ptr) {
|
||||
sdio_recv_data_callback_ptr((uint8*)tx_que.buf_ptr,tx_que.datalen);
|
||||
}
|
||||
tx_buff_handle_done();
|
||||
TRIG_TOHOST_INT();
|
||||
//system_os_post(2, 3, 0);
|
||||
}
|
||||
|
||||
//TO HOST underflow
|
||||
if(slc_intr_status & SLC_RX_UDF_INT_ENA)
|
||||
{
|
||||
}
|
||||
|
||||
//FROM HOST overflow
|
||||
if(slc_intr_status & SLC_TX_DSCR_ERR_INT_ENA)
|
||||
{
|
||||
}
|
||||
|
||||
slc_intr_status = READ_PERI_REG(SLC_INT_STATUS);
|
||||
if(slc_intr_status)
|
||||
{
|
||||
WRITE_PERI_REG(SLC_INT_CLR, slc_intr_status);
|
||||
os_printf("slc_intr_status:0x%08x\r\n",slc_intr_status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void rx_buff_read_done(void)
|
||||
{
|
||||
union sdio_slave_status sdio_sta;
|
||||
/////modify sdio status reg
|
||||
sdio_sta.word_value=READ_PERI_REG(SLC_HOST_CONF_W2);
|
||||
sdio_sta.elm_value.comm_cnt++;
|
||||
sdio_sta.elm_value.rd_empty=1;
|
||||
sdio_sta.elm_value.rx_length=0;
|
||||
sdio_sta.elm_value.intr_no &= (~RX_AVAILIBLE);
|
||||
WRITE_PERI_REG(SLC_HOST_CONF_W2, sdio_sta.word_value); //update sdio status register
|
||||
//os_printf("rx_buff_read_done\r\n");
|
||||
}
|
||||
|
||||
static void tx_buff_write_done(void)
|
||||
{
|
||||
union sdio_slave_status sdio_sta;
|
||||
/////modify sdio status reg
|
||||
sdio_sta.word_value=READ_PERI_REG(SLC_HOST_CONF_W2);
|
||||
sdio_sta.elm_value.comm_cnt++;
|
||||
sdio_sta.elm_value.wr_busy=1;
|
||||
sdio_sta.elm_value.intr_no &= (~TX_AVAILIBLE);
|
||||
WRITE_PERI_REG(SLC_HOST_CONF_W2, sdio_sta.word_value); //update sdio status register
|
||||
}
|
||||
|
||||
static void tx_buff_handle_done(void)
|
||||
{
|
||||
union sdio_slave_status sdio_sta;
|
||||
|
||||
/////config tx queue information
|
||||
tx_que.blocksize=TX_BUFFER_SIZE;
|
||||
tx_que.datalen=0;
|
||||
tx_que.eof=0;
|
||||
tx_que.owner=1;
|
||||
|
||||
/////modify sdio status reg
|
||||
sdio_sta.word_value=READ_PERI_REG(SLC_HOST_CONF_W2);
|
||||
sdio_sta.elm_value.wr_busy=0;
|
||||
sdio_sta.elm_value.intr_no |= TX_AVAILIBLE;
|
||||
|
||||
SET_PERI_REG_MASK(SLC_TX_LINK, SLC_TXLINK_START); //tx buffer is ready for being written
|
||||
WRITE_PERI_REG(SLC_HOST_CONF_W2, sdio_sta.word_value); //update sdio status register
|
||||
//*******************************************************************//
|
||||
|
||||
}
|
||||
static int32 rx_buff_load_done(uint16 rx_len)
|
||||
{
|
||||
union sdio_slave_status sdio_sta;
|
||||
|
||||
if(rx_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(rx_len > rx_que.blocksize)
|
||||
{
|
||||
rx_len = rx_que.blocksize;
|
||||
}
|
||||
|
||||
//os_memcpy(rx_que.buf_ptr,data,rx_len);
|
||||
/////config rx queue information
|
||||
rx_que.blocksize=RX_BUFFER_SIZE;
|
||||
rx_que.datalen=rx_len + SDIO_TOKEN_SIZE;
|
||||
rx_que.eof=1;
|
||||
rx_que.owner=1;
|
||||
|
||||
//ETS_SDIO_INTR_DISABLE();
|
||||
//available_buffer_amount--;
|
||||
|
||||
/////modify sdio status reg
|
||||
sdio_sta.word_value=READ_PERI_REG(SLC_HOST_CONF_W2);
|
||||
sdio_sta.elm_value.rd_empty=0;
|
||||
sdio_sta.elm_value.intr_no |= RX_AVAILIBLE;
|
||||
sdio_sta.elm_value.rx_length=rx_len;
|
||||
|
||||
SET_PERI_REG_MASK(SLC_RX_LINK, SLC_RXLINK_START); //rx buffer is ready for being read
|
||||
WRITE_PERI_REG(SLC_HOST_CONF_W2, sdio_sta.word_value); //update sdio status register
|
||||
//ETS_SDIO_INTR_ENABLE();
|
||||
//os_printf("rx_buff_load_done(%d,0x%08x):%s\r\n",rx_len,rx_que.buf_ptr,rx_que.buf_ptr);
|
||||
//os_printf("rx_buff_load_done:%d\r\n",rx_len);
|
||||
return rx_len;
|
||||
}
|
||||
|
||||
int32 ICACHE_FLASH_ATTR sdio_load_data(const uint8* data,uint32 len)
|
||||
{
|
||||
int32 data_len = 0;
|
||||
|
||||
if (pHead_Sended == NULL) {
|
||||
os_printf("no buf\r\n");
|
||||
return 0;
|
||||
}
|
||||
int32 left_len = 0;
|
||||
|
||||
while(len)
|
||||
{
|
||||
left_len = RX_BUFFER_SIZE + SDIO_TOKEN_SIZE - (uint32)(pHead_Sended->tail - pHead_Sended->buffer);
|
||||
if(len < left_len)
|
||||
{
|
||||
os_memcpy(pHead_Sended->tail,data,len);
|
||||
pHead_Sended->tail += len;
|
||||
len = 0;
|
||||
data_len += len;
|
||||
//os_printf(">555:0x%08x,0x%08x\r\n",pHead_Sended->buffer,pHead_Sended->tail);
|
||||
}
|
||||
else
|
||||
{
|
||||
os_memcpy(pHead_Sended->tail,data,left_len);
|
||||
pHead_Sended->tail += left_len;
|
||||
len -= left_len;
|
||||
data += left_len;
|
||||
data_len += left_len;
|
||||
if(pHead_ToSend == NULL) {
|
||||
pTail_ToSend = pHead_Sended;
|
||||
pHead_ToSend = pTail_ToSend;
|
||||
} else {
|
||||
pTail_ToSend->next = pHead_Sended;
|
||||
pTail_ToSend = pTail_ToSend->next;
|
||||
}
|
||||
pHead_Sended = pHead_Sended->next;
|
||||
|
||||
pTail_ToSend->next = NULL;
|
||||
if(pHead_Sended == NULL)
|
||||
{
|
||||
os_printf("buf full\r\n");
|
||||
break;
|
||||
}
|
||||
//os_printf(">666\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
//os_printf(">>pHead_ToSend:0x%08x\r\n",pHead_ToSend);
|
||||
|
||||
if(pHead_ToSend == NULL) {
|
||||
pTail_ToSend = pHead_Sended;
|
||||
pHead_ToSend = pTail_ToSend;
|
||||
|
||||
pHead_Sended = pHead_Sended->next;
|
||||
pTail_ToSend->next = NULL;
|
||||
//system_os_post(2, 2, 0);
|
||||
sdio_try_to_load();
|
||||
}
|
||||
return data_len;
|
||||
}
|
||||
|
||||
static void sdio_try_to_load(void)
|
||||
{
|
||||
if((has_read == TRUE) && (pHead_ToSend != NULL))
|
||||
{
|
||||
rx_que.buf_ptr = (uint32)pHead_ToSend->buffer;
|
||||
rx_buff_load_done(pHead_ToSend->tail- pHead_ToSend->buffer - SDIO_TOKEN_SIZE);
|
||||
//pHead_ToSend = pHead_ToSend->next;
|
||||
has_read = FALSE;
|
||||
//os_printf("SLC_INT_STATUS:0x%08x\r\n",READ_PERI_REG(SLC_INT_STATUS));
|
||||
TRIG_TOHOST_INT();
|
||||
}
|
||||
}
|
||||
|
||||
static void sdio_read_done_process(void)
|
||||
{
|
||||
has_read = TRUE;
|
||||
|
||||
pHead_ToSend->tail = pHead_ToSend->buffer + SDIO_TOKEN_SIZE;
|
||||
if(pHead_Sended) {
|
||||
pTail_Sended->next = pHead_ToSend;
|
||||
pTail_Sended = pTail_Sended->next;
|
||||
}else {
|
||||
pTail_Sended = pHead_ToSend;
|
||||
pHead_Sended = pTail_Sended;
|
||||
}
|
||||
pHead_ToSend = pHead_ToSend->next;
|
||||
pTail_Sended->next = NULL;
|
||||
//os_printf(">>pHead_ToSend:0x%08x,pHead_Sended:0x%08x,0x%08x,0x%08x\r\n",pHead_ToSend,pHead_Sended,pHead_Sended->buffer,pHead_Sended->tail);
|
||||
if(pHead_ToSend) {
|
||||
rx_que.buf_ptr = (uint32)pHead_ToSend->buffer;
|
||||
rx_buff_load_done(pHead_ToSend->tail - pHead_ToSend->buffer - SDIO_TOKEN_SIZE);
|
||||
has_read = FALSE;
|
||||
//os_printf("intr trig\r\n");
|
||||
//TRIG_TOHOST_INT();
|
||||
} else if ((pHead_Sended != NULL) && (pHead_Sended->buffer != (pHead_Sended->tail- SDIO_TOKEN_SIZE))) {
|
||||
pHead_ToSend = pHead_Sended;
|
||||
pTail_ToSend = pHead_ToSend;
|
||||
pHead_Sended = pHead_Sended->next;
|
||||
pTail_ToSend->next = NULL;
|
||||
|
||||
rx_que.buf_ptr = (uint32)pHead_ToSend->buffer;
|
||||
rx_buff_load_done(pHead_ToSend->tail- pHead_ToSend->buffer - SDIO_TOKEN_SIZE);
|
||||
has_read = FALSE;
|
||||
//os_printf("intr trig\r\n");
|
||||
//TRIG_TOHOST_INT();
|
||||
}
|
||||
|
||||
TRIG_TOHOST_INT();
|
||||
}
|
||||
|
||||
bool sdio_register_recv_cb(sdio_recv_data_callback_t cb)
|
||||
{
|
||||
sdio_recv_data_callback_ptr = cb;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+464
@@ -0,0 +1,464 @@
|
||||
|
||||
#include "driver/spi.h"
|
||||
#include "driver/spi_overlap.h"
|
||||
|
||||
#define CACHE_FLASH_CTRL_REG 0x3ff0000C
|
||||
#define CACHE_FLUSH_START_BIT BIT0
|
||||
#define CACHE_EMPTY_FLAG_BIT BIT1
|
||||
/******************************************************************************
|
||||
* FunctionName : cache_flush
|
||||
* Description : clear all the cpu cache data for stability test.
|
||||
*******************************************************************************/
|
||||
void cache_flush(void)
|
||||
{
|
||||
while(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT) {
|
||||
CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT);
|
||||
SET_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT);
|
||||
}
|
||||
while(!(READ_PERI_REG(CACHE_FLASH_CTRL_REG)&CACHE_EMPTY_FLAG_BIT));
|
||||
|
||||
CLEAR_PERI_REG_MASK(CACHE_FLASH_CTRL_REG, CACHE_FLUSH_START_BIT);
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_master_init
|
||||
* Description : SPI master initial function for common byte units transmission
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_master_init(uint8 spi_no)
|
||||
{
|
||||
uint32 regvalue;
|
||||
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_USR_COMMAND);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);
|
||||
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no),
|
||||
((3&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
|
||||
((1&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
|
||||
((3&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_lcd_9bit_write
|
||||
* Description : SPI 9bits transmission function for driving LCD TM035PDZV36
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
* uint8 high_bit - first high bit of the data, 0 is for "0",the other value 1-255 is for "1"
|
||||
* uint8 low_8bit- the rest 8bits of the data.
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit)
|
||||
{
|
||||
uint32 regvalue;
|
||||
uint8 bytetemp;
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
if(high_bit) bytetemp=(low_8bit>>1)|0x80;
|
||||
else bytetemp=(low_8bit>>1)&0x7f;
|
||||
|
||||
regvalue= ((8&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)bytetemp); //configure transmission variable,9bit transmission length and first 8 command bit
|
||||
if(low_8bit&0x01) regvalue|=BIT15; //write the 9th bit
|
||||
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR); //waiting for spi module available
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no), regvalue); //write command and command length into spi reg
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR); //transmission start
|
||||
// while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_mast_byte_write
|
||||
* Description : SPI master 1 byte transmission function
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
* uint8 data- transmitted data
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_mast_byte_write(uint8 spi_no,uint8 data)
|
||||
{
|
||||
uint32 regvalue;
|
||||
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_MISO);
|
||||
|
||||
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
|
||||
// bit15-0 is cmd value.
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no),
|
||||
((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|((uint32)data));
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_byte_write_espslave
|
||||
* Description : SPI master 1 byte transmission function for esp8266 slave,
|
||||
* transmit 1byte data to esp8266 slave buffer needs 16bit transmission ,
|
||||
* first byte is command 0x04 to write slave buffer, second byte is data
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
* uint8 data- transmitted data
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_byte_write_espslave(uint8 spi_no,uint8 data)
|
||||
{
|
||||
uint32 regvalue;
|
||||
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO|SPI_USR_ADDR|SPI_USR_DUMMY);
|
||||
|
||||
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
|
||||
// bit15-0 is cmd value.
|
||||
//0x70000000 is for 8bits cmd, 0x04 is eps8266 slave write cmd value
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no),
|
||||
((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|4);
|
||||
WRITE_PERI_REG(SPI_W0(spi_no), (uint32)(data));
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_byte_read_espslave
|
||||
* Description : SPI master 1 byte read function for esp8266 slave,
|
||||
* read 1byte data from esp8266 slave buffer needs 16bit transmission ,
|
||||
* first byte is command 0x06 to read slave buffer, second byte is recieved data
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
* uint8* data- recieved data address
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_byte_read_espslave(uint8 spi_no,uint8 *data)
|
||||
{
|
||||
uint32 regvalue;
|
||||
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
|
||||
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MISO);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_USR_MOSI|SPI_USR_ADDR|SPI_USR_DUMMY);
|
||||
//SPI_FLASH_USER2 bit28-31 is cmd length,cmd bit length is value(0-15)+1,
|
||||
// bit15-0 is cmd value.
|
||||
//0x70000000 is for 8bits cmd, 0x06 is eps8266 slave read cmd value
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no),
|
||||
((7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S)|6);
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no), SPI_USR);
|
||||
|
||||
while(READ_PERI_REG(SPI_CMD(spi_no))&SPI_USR);
|
||||
*data=(uint8)(READ_PERI_REG(SPI_W0(spi_no))&0xff);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_slave_init
|
||||
* Description : SPI slave mode initial funtion, including mode setting,
|
||||
* IO setting, transmission interrupt opening, interrupt function registration
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
* uint8 data_len - read&write data pack length,using byte as unit,the range is 1-32
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_slave_init(uint8 spi_no,uint8 data_len)
|
||||
{
|
||||
uint32 regvalue;
|
||||
uint32 data_bit_len;
|
||||
if(spi_no>1)
|
||||
return; //handle invalid input number
|
||||
if(data_len<=1) data_bit_len=7;
|
||||
else if(data_len>=32) data_bit_len=0xff;
|
||||
else data_bit_len=(data_len<<3)-1;
|
||||
|
||||
//clear bit9,bit8 of reg PERIPHS_IO_MUX
|
||||
//bit9 should be cleared when HSPI clock doesn't equal CPU clock
|
||||
//bit8 should be cleared when SPI clock doesn't equal CPU clock
|
||||
////WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105); //clear bit9//TEST
|
||||
if(spi_no==SPI){
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
|
||||
}else if(spi_no==HSPI){
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
|
||||
}
|
||||
|
||||
//regvalue=READ_PERI_REG(SPI_FLASH_SLAVE(spi_no));
|
||||
//slave mode,slave use buffers which are register "SPI_FLASH_C0~C15", enable trans done isr
|
||||
//set bit 30 bit 29 bit9,bit9 is trans done isr mask
|
||||
SET_PERI_REG_MASK( SPI_SLAVE(spi_no),
|
||||
SPI_SLAVE_MODE|SPI_SLV_WR_RD_BUF_EN|
|
||||
SPI_SLV_WR_BUF_DONE_EN|SPI_SLV_RD_BUF_DONE_EN|
|
||||
SPI_SLV_WR_STA_DONE_EN|SPI_SLV_RD_STA_DONE_EN|
|
||||
SPI_TRANS_DONE_EN);
|
||||
//disable general trans intr
|
||||
//CLEAR_PERI_REG_MASK(SPI_SLAVE(spi_no),SPI_TRANS_DONE_EN);
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE);//disable flash operation mode
|
||||
SET_PERI_REG_MASK(SPI_USER(spi_no),SPI_USR_MISO_HIGHPART);//SLAVE SEND DATA BUFFER IN C8-C15
|
||||
|
||||
|
||||
//////**************RUN WHEN SLAVE RECIEVE*******************///////
|
||||
//tow lines below is to configure spi timing.
|
||||
SET_PERI_REG_MASK(SPI_CTRL2(spi_no),(0x2&SPI_MOSI_DELAY_NUM)<<SPI_MOSI_DELAY_NUM_S) ;//delay num
|
||||
os_printf("SPI_CTRL2 is %08x\n",READ_PERI_REG(SPI_CTRL2(spi_no)));
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no), 0);
|
||||
|
||||
|
||||
|
||||
/////***************************************************//////
|
||||
|
||||
//set 8 bit slave command length, because slave must have at least one bit addr,
|
||||
//8 bit slave+8bit addr, so master device first 2 bytes can be regarded as a command
|
||||
//and the following bytes are datas,
|
||||
//32 bytes input wil be stored in SPI_FLASH_C0-C7
|
||||
//32 bytes output data should be set to SPI_FLASH_C8-C15
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no), (0x7&SPI_USR_COMMAND_BITLEN)<<SPI_USR_COMMAND_BITLEN_S); //0x70000000
|
||||
|
||||
//set 8 bit slave recieve buffer length, the buffer is SPI_FLASH_C0-C7
|
||||
//set 8 bit slave status register, which is the low 8 bit of register "SPI_FLASH_STATUS"
|
||||
SET_PERI_REG_MASK(SPI_SLAVE1(spi_no), ((data_bit_len&SPI_SLV_BUF_BITLEN)<< SPI_SLV_BUF_BITLEN_S)|
|
||||
((0x7&SPI_SLV_STATUS_BITLEN)<<SPI_SLV_STATUS_BITLEN_S)|
|
||||
((0x7&SPI_SLV_WR_ADDR_BITLEN)<<SPI_SLV_WR_ADDR_BITLEN_S)|
|
||||
((0x7&SPI_SLV_RD_ADDR_BITLEN)<<SPI_SLV_RD_ADDR_BITLEN_S));
|
||||
|
||||
SET_PERI_REG_MASK(SPI_PIN(spi_no),BIT19);//BIT19
|
||||
|
||||
//maybe enable slave transmission liston
|
||||
SET_PERI_REG_MASK(SPI_CMD(spi_no),SPI_USR);
|
||||
//register level2 isr function, which contains spi, hspi and i2s events
|
||||
ETS_SPI_INTR_ATTACH(spi_slave_isr_handler,NULL);
|
||||
//enable level2 isr, which contains spi, hspi and i2s events
|
||||
ETS_SPI_INTR_ENABLE();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* =============================================================================================
|
||||
* code below is for spi slave r/w testcase with 2 r/w state lines connected to the spi master mcu
|
||||
* replace with your own process functions
|
||||
* find "add system_os_post here" in spi_slave_isr_handler.
|
||||
* =============================================================================================
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef SPI_SLAVE_DEBUG
|
||||
/******************************************************************************
|
||||
* FunctionName : hspi_master_readwrite_repeat
|
||||
* Description : SPI master test function for reading and writing esp8266 slave buffer,
|
||||
the function uses HSPI module
|
||||
*******************************************************************************/
|
||||
os_timer_t timer2;
|
||||
|
||||
void hspi_master_readwrite_repeat(void)
|
||||
{
|
||||
static uint8 data=0;
|
||||
uint8 temp;
|
||||
|
||||
os_timer_disarm(&timer2);
|
||||
spi_byte_read_espslave(HSPI,&temp);
|
||||
|
||||
temp++;
|
||||
spi_byte_write_espslave(HSPI,temp);
|
||||
os_timer_setfn(&timer2, (os_timer_func_t *)hspi_master_readwrite_repeat, NULL);
|
||||
os_timer_arm(&timer2, 500, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_slave_isr_handler
|
||||
* Description : SPI interrupt function, SPI HSPI and I2S interrupt can trig this function
|
||||
some basic operation like clear isr flag has been done,
|
||||
and it is availible for adding user coder in the funtion
|
||||
* Parameters : void *para- function parameter address, which has been registered in function spi_slave_init
|
||||
*******************************************************************************/
|
||||
#include "gpio.h"
|
||||
#include "user_interface.h"
|
||||
#include "mem.h"
|
||||
static uint8 spi_data[32] = {0};
|
||||
static uint8 idx = 0;
|
||||
static uint8 spi_flg = 0;
|
||||
#define SPI_MISO
|
||||
#define SPI_QUEUE_LEN 8
|
||||
os_event_t * spiQueue;
|
||||
#define MOSI 0
|
||||
#define MISO 1
|
||||
#define STATUS_R_IN_WR 2
|
||||
#define STATUS_W 3
|
||||
#define TR_DONE_ALONE 4
|
||||
#define WR_RD 5
|
||||
#define DATA_ERROR 6
|
||||
#define STATUS_R_IN_RD 7
|
||||
//init the two intr line of slave
|
||||
//gpio0: wr_ready ,and
|
||||
//gpio2: rd_ready , controlled by slave
|
||||
void ICACHE_FLASH_ATTR
|
||||
gpio_init()
|
||||
{
|
||||
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
|
||||
//PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4);
|
||||
GPIO_OUTPUT_SET(0, 1);
|
||||
GPIO_OUTPUT_SET(2, 0);
|
||||
//GPIO_OUTPUT_SET(4, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void spi_slave_isr_handler(void *para)
|
||||
{
|
||||
uint32 regvalue,calvalue;
|
||||
static uint8 state =0;
|
||||
uint32 recv_data,send_data;
|
||||
|
||||
if(READ_PERI_REG(0x3ff00020)&BIT4){
|
||||
//following 3 lines is to clear isr signal
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE(SPI), 0x3ff);
|
||||
}else if(READ_PERI_REG(0x3ff00020)&BIT7){ //bit7 is for hspi isr,
|
||||
regvalue=READ_PERI_REG(SPI_SLAVE(HSPI));
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
|
||||
SPI_TRANS_DONE_EN|
|
||||
SPI_SLV_WR_STA_DONE_EN|
|
||||
SPI_SLV_RD_STA_DONE_EN|
|
||||
SPI_SLV_WR_BUF_DONE_EN|
|
||||
SPI_SLV_RD_BUF_DONE_EN);
|
||||
SET_PERI_REG_MASK(SPI_SLAVE(HSPI), SPI_SYNC_RESET);
|
||||
CLEAR_PERI_REG_MASK(SPI_SLAVE(HSPI),
|
||||
SPI_TRANS_DONE|
|
||||
SPI_SLV_WR_STA_DONE|
|
||||
SPI_SLV_RD_STA_DONE|
|
||||
SPI_SLV_WR_BUF_DONE|
|
||||
SPI_SLV_RD_BUF_DONE);
|
||||
SET_PERI_REG_MASK(SPI_SLAVE(HSPI),
|
||||
SPI_TRANS_DONE_EN|
|
||||
SPI_SLV_WR_STA_DONE_EN|
|
||||
SPI_SLV_RD_STA_DONE_EN|
|
||||
SPI_SLV_WR_BUF_DONE_EN|
|
||||
SPI_SLV_RD_BUF_DONE_EN);
|
||||
|
||||
if(regvalue&SPI_SLV_WR_BUF_DONE){
|
||||
GPIO_OUTPUT_SET(0, 0);
|
||||
idx=0;
|
||||
while(idx<8){
|
||||
recv_data=READ_PERI_REG(SPI_W0(HSPI)+(idx<<2));
|
||||
spi_data[idx<<2] = recv_data&0xff;
|
||||
spi_data[(idx<<2)+1] = (recv_data>>8)&0xff;
|
||||
spi_data[(idx<<2)+2] = (recv_data>>16)&0xff;
|
||||
spi_data[(idx<<2)+3] = (recv_data>>24)&0xff;
|
||||
idx++;
|
||||
}
|
||||
//add system_os_post here
|
||||
GPIO_OUTPUT_SET(0, 1);
|
||||
}
|
||||
if(regvalue&SPI_SLV_RD_BUF_DONE){
|
||||
//it is necessary to call GPIO_OUTPUT_SET(2, 1), when new data is preped in SPI_W8-15 and needs to be sended.
|
||||
GPIO_OUTPUT_SET(2, 0);
|
||||
//add system_os_post here
|
||||
//system_os_post(USER_TASK_PRIO_1,WR_RD,regvalue);
|
||||
|
||||
}
|
||||
|
||||
}else if(READ_PERI_REG(0x3ff00020)&BIT9){ //bit7 is for i2s isr,
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef SPI_SLAVE_DEBUG
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
set_miso_data()
|
||||
{
|
||||
if(GPIO_INPUT_GET(2)==0){
|
||||
WRITE_PERI_REG(SPI_W8(HSPI),0x05040302);
|
||||
WRITE_PERI_REG(SPI_W9(HSPI),0x09080706);
|
||||
WRITE_PERI_REG(SPI_W10(HSPI),0x0d0c0b0a);
|
||||
WRITE_PERI_REG(SPI_W11(HSPI),0x11100f0e);
|
||||
|
||||
WRITE_PERI_REG(SPI_W12(HSPI),0x15141312);
|
||||
WRITE_PERI_REG(SPI_W13(HSPI),0x19181716);
|
||||
WRITE_PERI_REG(SPI_W14(HSPI),0x1d1c1b1a);
|
||||
WRITE_PERI_REG(SPI_W15(HSPI),0x21201f1e);
|
||||
GPIO_OUTPUT_SET(2, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
disp_spi_data()
|
||||
{
|
||||
uint8 i = 0;
|
||||
for(i=0;i<32;i++){
|
||||
os_printf("data %d : 0x%02x\n\r",i,spi_data[i]);
|
||||
}
|
||||
//os_printf("d31:0x%02x\n\r",spi_data[31]);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_task(os_event_t *e)
|
||||
{
|
||||
uint8 data;
|
||||
switch(e->sig){
|
||||
case MOSI:
|
||||
disp_spi_data();
|
||||
break;
|
||||
case STATUS_R_IN_WR :
|
||||
os_printf("SR ERR in WRPR,Reg:%08x \n",e->par);
|
||||
break;
|
||||
case STATUS_W:
|
||||
os_printf("SW ERR,Reg:%08x\n",e->par);
|
||||
break;
|
||||
case TR_DONE_ALONE:
|
||||
os_printf("TD ALO ERR,Reg:%08x\n",e->par);
|
||||
break;
|
||||
case WR_RD:
|
||||
os_printf("WR&RD ERR,Reg:%08x\n",e->par);
|
||||
break;
|
||||
case DATA_ERROR:
|
||||
os_printf("Data ERR,Reg:%08x\n",e->par);
|
||||
break;
|
||||
case STATUS_R_IN_RD :
|
||||
os_printf("SR ERR in RDPR,Reg:%08x\n",e->par);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_task_init(void)
|
||||
{
|
||||
spiQueue = (os_event_t*)os_malloc(sizeof(os_event_t)*SPI_QUEUE_LEN);
|
||||
system_os_task(spi_task,USER_TASK_PRIO_1,spiQueue,SPI_QUEUE_LEN);
|
||||
}
|
||||
|
||||
os_timer_t spi_timer_test;
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_test_init()
|
||||
{
|
||||
os_printf("spi init\n\r");
|
||||
spi_slave_init(HSPI);
|
||||
os_printf("gpio init\n\r");
|
||||
gpio_init();
|
||||
os_printf("spi task init \n\r");
|
||||
spi_task_init();
|
||||
#ifdef SPI_MISO
|
||||
os_printf("spi miso init\n\r");
|
||||
set_miso_data();
|
||||
#endif
|
||||
|
||||
//os_timer_disarm(&spi_timer_test);
|
||||
//os_timer_setfn(&spi_timer_test, (os_timer_func_t *)set_miso_data, NULL);//wjl
|
||||
//os_timer_arm(&spi_timer_test,50,1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
+398
@@ -0,0 +1,398 @@
|
||||
#include "driver/spi_overlap.h"
|
||||
#include "driver/spi.h"
|
||||
#include "gpio.h"
|
||||
|
||||
#define SPI_FLASH_READ_MODE_MASK 0x196000
|
||||
#define WAIT_HSPI_IDLE() while(READ_PERI_REG(SPI_EXT2(HSPI))||(READ_PERI_REG(SPI_CMD(HSPI))&0xfffc0000));
|
||||
#define CONF_HSPI_CLK_DIV(div) WRITE_PERI_REG(SPI_CLOCK(HSPI), (((div<<1)+1)<<12)+(div<<6)+(div<<1)+1)
|
||||
#define HSPI_FALLING_EDGE_SAMPLE() SET_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE)
|
||||
#define HSPI_RISING_EDGE_SAMPLE() CLEAR_PERI_REG_MASK(SPI_USER(HSPI), SPI_CK_OUT_EDGE)
|
||||
#define ACTIVE_HSPI_CS0 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS0_DIS);\
|
||||
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS1_DIS |SPI_CS2_DIS)
|
||||
#define ACTIVE_HSPI_CS1 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS1_DIS);\
|
||||
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS0_DIS |SPI_CS2_DIS)
|
||||
#define ACTIVE_HSPI_CS2 CLEAR_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS2_DIS);\
|
||||
SET_PERI_REG_MASK(SPI_PIN(HSPI), SPI_CS0_DIS |SPI_CS1_DIS)
|
||||
#define ENABLE_HSPI_DEV_CS() PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2)
|
||||
#define DISABLE_HSPI_DEV_CS() GPIO_OUTPUT_SET(15, 1);\
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15)
|
||||
struct hspi_device_register hspi_dev_reg;
|
||||
/******************************************************************************
|
||||
* FunctionName : hspi_overlap_init
|
||||
* Description : enable hspi and spi module overlap mode
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
hspi_overlap_init(void)
|
||||
{
|
||||
//hspi overlap to spi, two spi masters on cspi
|
||||
SET_PERI_REG_MASK(HOST_INF_SEL, reg_cspi_overlap);
|
||||
|
||||
//set higher priority for spi than hspi
|
||||
SET_PERI_REG_MASK(SPI_EXT3(SPI),0x1);
|
||||
SET_PERI_REG_MASK(SPI_EXT3(HSPI),0x3);
|
||||
SET_PERI_REG_MASK(SPI_USER(HSPI), BIT(5));
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : hspi_overlap_deinit
|
||||
* Description : recover hspi and spi module from overlap mode
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
hspi_overlap_deinit(void)
|
||||
{
|
||||
//hspi overlap to spi, two spi masters on cspi
|
||||
CLEAR_PERI_REG_MASK(HOST_INF_SEL, reg_cspi_overlap);
|
||||
|
||||
//set higher priority for spi than hspi
|
||||
CLEAR_PERI_REG_MASK(SPI_EXT3(SPI),0x1);
|
||||
CLEAR_PERI_REG_MASK(SPI_EXT3(HSPI),0x3);
|
||||
CLEAR_PERI_REG_MASK(SPI_USER(HSPI), BIT(5));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_reg_backup
|
||||
* Description : backup SPI normal operation register value and disable CPU cache to modify some flash registers.
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_reg_backup(uint8 spi_no,uint32* backup_mem)
|
||||
{
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
backup_mem[PERIPHS_IO_MUX_BACKUP] =READ_PERI_REG(PERIPHS_IO_MUX);
|
||||
backup_mem[SPI_USER_BACKUP] =READ_PERI_REG(SPI_USER(spi_no));
|
||||
backup_mem[SPI_CTRL_BACKUP] =READ_PERI_REG(SPI_CTRL(spi_no));
|
||||
backup_mem[SPI_CLOCK_BACKUP] =READ_PERI_REG(SPI_CLOCK(spi_no));
|
||||
backup_mem[SPI_USER1_BACKUP] =READ_PERI_REG(SPI_USER1(spi_no));
|
||||
backup_mem[SPI_USER2_BACKUP] =READ_PERI_REG(SPI_USER2(spi_no));
|
||||
backup_mem[SPI_CMD_BACKUP] =READ_PERI_REG(SPI_CMD(spi_no));
|
||||
backup_mem[SPI_PIN_BACKUP] =READ_PERI_REG(SPI_PIN(spi_no));
|
||||
backup_mem[SPI_SLAVE_BACKUP] =READ_PERI_REG(SPI_SLAVE(spi_no));
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_reg_recover
|
||||
* Description : recover SPI normal operation register value and enable CPU cache.
|
||||
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
spi_reg_recover(uint8 spi_no,uint32* backup_mem)
|
||||
{
|
||||
if(spi_no>1) return; //handle invalid input number
|
||||
|
||||
// WRITE_PERI_REG(PERIPHS_IO_MUX, backup_mem[PERIPHS_IO_MUX_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_USER(spi_no), backup_mem[SPI_USER_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_CTRL(spi_no), backup_mem[SPI_CTRL_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_CLOCK(spi_no), backup_mem[SPI_CLOCK_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_USER1(spi_no), backup_mem[SPI_USER1_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_USER2(spi_no), backup_mem[SPI_USER2_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_CMD(spi_no), backup_mem[SPI_CMD_BACKUP]);
|
||||
WRITE_PERI_REG(SPI_PIN(spi_no), backup_mem[SPI_PIN_BACKUP]);
|
||||
// WRITE_PERI_REG(SPI_SLAVE(spi_no), backup_mem[SPI_SLAVE_BACKUP]);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
hspi_master_dev_init(uint8 dev_no,uint8 clk_polar,uint8 clk_div)
|
||||
{
|
||||
uint32 regtemp;
|
||||
if((dev_no>3)||(clk_polar>1)||(clk_div>0x1f))
|
||||
{
|
||||
os_printf("hspi_master_dev_init parameter is out of range!\n\r");
|
||||
return;
|
||||
}
|
||||
|
||||
WAIT_HSPI_IDLE();
|
||||
if(!hspi_dev_reg.hspi_reg_backup_flag){
|
||||
if(READ_PERI_REG(PERIPHS_IO_MUX)&BIT8){
|
||||
hspi_dev_reg.spi_io_80m=1;
|
||||
SET_PERI_REG_MASK(SPI_CLOCK(HSPI),SPI_CLK_EQU_SYSCLK);
|
||||
}else{
|
||||
hspi_dev_reg.spi_io_80m=0;
|
||||
CLEAR_PERI_REG_MASK(SPI_CLOCK(HSPI),SPI_CLK_EQU_SYSCLK);
|
||||
}
|
||||
|
||||
regtemp=READ_PERI_REG(SPI_CTRL(SPI))&SPI_FLASH_READ_MODE_MASK;
|
||||
CLEAR_PERI_REG_MASK(SPI_CTRL(HSPI), SPI_FLASH_READ_MODE_MASK);
|
||||
SET_PERI_REG_MASK(SPI_CTRL(HSPI), regtemp);
|
||||
spi_reg_backup(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
|
||||
|
||||
spi_master_init(HSPI);
|
||||
spi_reg_backup(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
|
||||
|
||||
hspi_dev_reg.hspi_reg_backup_flag=1;
|
||||
|
||||
// spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
|
||||
hspi_dev_reg.selected_dev_num=HSPI_IDLE;
|
||||
}
|
||||
|
||||
hspi_dev_reg.hspi_dev_conf[dev_no].active=1;
|
||||
hspi_dev_reg.hspi_dev_conf[dev_no].clk_div=clk_div;
|
||||
hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar=clk_polar;
|
||||
|
||||
switch(dev_no){
|
||||
case HSPI_CS_DEV :
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);
|
||||
CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX, BIT9);
|
||||
break;
|
||||
|
||||
case SPI_CS1_DEV :
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_SPI_CS1);
|
||||
if(hspi_dev_reg.spi_io_80m){
|
||||
os_printf("SPI CS1 device must work at 80Mhz");
|
||||
}
|
||||
break;
|
||||
|
||||
case SPI_CS2_DEV :
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_SPI_CS2);
|
||||
if(hspi_dev_reg.spi_io_80m){
|
||||
os_printf("SPI CS2 device must work at 80Mhz");
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
hspi_dev_sel(uint8 dev_no)
|
||||
{
|
||||
uint32 regval;
|
||||
|
||||
if(dev_no>3){
|
||||
os_printf("hspi_dev_sel parameter is out of range!\n\r");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!hspi_dev_reg.hspi_dev_conf[dev_no].active){
|
||||
os_printf("device%d has not been initialized!\n\r",dev_no);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(hspi_dev_reg.selected_dev_num){
|
||||
case HSPI_CS_DEV:
|
||||
if((dev_no==SPI_CS1_DEV)||(dev_no==SPI_CS2_DEV)){
|
||||
WAIT_HSPI_IDLE();
|
||||
DISABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_init();
|
||||
|
||||
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
|
||||
else {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
if(dev_no==SPI_CS1_DEV) {ACTIVE_HSPI_CS1;}
|
||||
else {ACTIVE_HSPI_CS2;}
|
||||
}
|
||||
else if(dev_no==SPI_CS0_FLASH){
|
||||
WAIT_HSPI_IDLE();
|
||||
DISABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_init();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
|
||||
|
||||
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
|
||||
|
||||
HSPI_RISING_EDGE_SAMPLE();
|
||||
ACTIVE_HSPI_CS0 ;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPI_CS1_DEV:
|
||||
if(dev_no==SPI_CS2_DEV){
|
||||
WAIT_HSPI_IDLE();
|
||||
if(!hspi_dev_reg.spi_io_80m) {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
ACTIVE_HSPI_CS2;
|
||||
}
|
||||
else if(dev_no==SPI_CS0_FLASH){
|
||||
WAIT_HSPI_IDLE();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
|
||||
HSPI_RISING_EDGE_SAMPLE();
|
||||
ACTIVE_HSPI_CS0;
|
||||
}
|
||||
else if(dev_no==HSPI_CS_DEV){
|
||||
WAIT_HSPI_IDLE();
|
||||
ENABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_deinit();
|
||||
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
ACTIVE_HSPI_CS0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPI_CS2_DEV:
|
||||
if(dev_no==SPI_CS1_DEV){
|
||||
WAIT_HSPI_IDLE();
|
||||
if(!hspi_dev_reg.spi_io_80m) {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
ACTIVE_HSPI_CS1;
|
||||
}
|
||||
else if(dev_no==SPI_CS0_FLASH){
|
||||
WAIT_HSPI_IDLE();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
|
||||
HSPI_RISING_EDGE_SAMPLE();
|
||||
ACTIVE_HSPI_CS0;
|
||||
}
|
||||
else if(dev_no==HSPI_CS_DEV){
|
||||
WAIT_HSPI_IDLE();
|
||||
ENABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_deinit();
|
||||
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
ACTIVE_HSPI_CS0;
|
||||
}
|
||||
break;
|
||||
|
||||
case SPI_CS0_FLASH:
|
||||
if((dev_no==SPI_CS1_DEV)||(dev_no==SPI_CS2_DEV)){
|
||||
WAIT_HSPI_IDLE();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
|
||||
|
||||
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
|
||||
else {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
if(dev_no==SPI_CS1_DEV) {ACTIVE_HSPI_CS1;}
|
||||
else {ACTIVE_HSPI_CS2;}
|
||||
}
|
||||
else if(dev_no==HSPI_CS_DEV){
|
||||
WAIT_HSPI_IDLE();
|
||||
ENABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_deinit();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
|
||||
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
ACTIVE_HSPI_CS0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if((dev_no==SPI_CS1_DEV)||(dev_no==SPI_CS2_DEV)){
|
||||
WAIT_HSPI_IDLE();
|
||||
DISABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_init();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
|
||||
|
||||
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
|
||||
else {CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);}
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
if(dev_no==SPI_CS1_DEV) {ACTIVE_HSPI_CS1;}
|
||||
else {ACTIVE_HSPI_CS2;}
|
||||
}
|
||||
else if(dev_no==SPI_CS0_FLASH){
|
||||
WAIT_HSPI_IDLE();
|
||||
DISABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_init();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_flash_reg_backup);
|
||||
|
||||
if(hspi_dev_reg.spi_io_80m) {SET_PERI_REG_MASK(SPI_CLOCK(HSPI), SPI_CLK_EQU_SYSCLK);}
|
||||
|
||||
HSPI_RISING_EDGE_SAMPLE();
|
||||
ACTIVE_HSPI_CS0 ;
|
||||
}
|
||||
else if(dev_no==HSPI_CS_DEV){
|
||||
WAIT_HSPI_IDLE();
|
||||
ENABLE_HSPI_DEV_CS();
|
||||
hspi_overlap_deinit();
|
||||
spi_reg_recover(HSPI, hspi_dev_reg.hspi_dev_reg_backup);
|
||||
CONF_HSPI_CLK_DIV(hspi_dev_reg.hspi_dev_conf[dev_no].clk_div);
|
||||
|
||||
if(hspi_dev_reg.hspi_dev_conf[dev_no].clk_polar) {HSPI_FALLING_EDGE_SAMPLE();}
|
||||
else {HSPI_RISING_EDGE_SAMPLE();}
|
||||
|
||||
ACTIVE_HSPI_CS0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
hspi_dev_reg.selected_dev_num=dev_no;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : spi_read_data
|
||||
* Description : use hspi to read flash data for stability test
|
||||
* Parameters : SpiFlashChip * spi-- flash parameter structure pointer
|
||||
* uint32 flash_addr--flash start address
|
||||
* uint32 * addr_dest--start address for preped destination memory space
|
||||
* uint32 byte_length--length of the data which needs to be read from flash
|
||||
*******************************************************************************/
|
||||
SpiFlashOpResult ICACHE_FLASH_ATTR
|
||||
hspi_overlap_read_flash_data(SpiFlashChip * spi, uint32 flash_addr, uint32 * addr_dest, uint32 byte_length)
|
||||
{
|
||||
uint32 temp_addr,reg_tmp;
|
||||
sint32 temp_length;
|
||||
uint8 i;
|
||||
uint8 remain_word_num;
|
||||
|
||||
hspi_dev_sel(SPI_CS0_FLASH);
|
||||
|
||||
//address range check
|
||||
if ((flash_addr+byte_length) > (spi->chip_size))
|
||||
{
|
||||
return SPI_FLASH_RESULT_ERR;
|
||||
}
|
||||
|
||||
temp_addr = flash_addr;
|
||||
temp_length = byte_length;
|
||||
|
||||
while(temp_length > 0)
|
||||
{
|
||||
if(temp_length >= SPI_BUFF_BYTE_NUM)
|
||||
{
|
||||
// reg_tmp=((temp_addr&0xff)<<16)|(temp_addr&0xff00)|((temp_addr&0xff0000)>>16)|(SPI_BUFF_BYTE_NUM << SPI_FLASH_BYTES_LEN);
|
||||
reg_tmp= temp_addr |(SPI_BUFF_BYTE_NUM<< SPI_FLASH_BYTES_LEN) ;
|
||||
WRITE_PERI_REG(SPI_ADDR(HSPI), reg_tmp);
|
||||
WRITE_PERI_REG(SPI_CMD(HSPI), SPI_FLASH_READ);
|
||||
while(READ_PERI_REG(SPI_CMD(HSPI)) != 0);
|
||||
|
||||
for(i=0; i<(SPI_BUFF_BYTE_NUM>>2);i++)
|
||||
{
|
||||
*addr_dest++ = READ_PERI_REG(SPI_W0(HSPI)+i*4);
|
||||
}
|
||||
temp_length = temp_length - SPI_BUFF_BYTE_NUM;
|
||||
temp_addr = temp_addr + SPI_BUFF_BYTE_NUM;
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITE_PERI_REG(SPI_ADDR(HSPI), temp_addr |(temp_length << SPI_FLASH_BYTES_LEN ));
|
||||
WRITE_PERI_REG(SPI_CMD(HSPI), SPI_FLASH_READ);
|
||||
while(READ_PERI_REG(SPI_CMD(HSPI)) != 0);
|
||||
|
||||
remain_word_num = (0== (temp_length&0x3))? (temp_length>>2) : (temp_length>>2)+1;
|
||||
for (i=0; i<remain_word_num; i++)
|
||||
{
|
||||
*addr_dest++ = READ_PERI_REG(SPI_W0(HSPI)+i*4);
|
||||
}
|
||||
temp_length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return SPI_FLASH_RESULT_OK;
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
hspi_overlap_flash_init(void)
|
||||
{
|
||||
hspi_master_dev_init(SPI_CS0_FLASH,0,0);
|
||||
|
||||
spi_flash_set_read_func(hspi_overlap_read_flash_data);
|
||||
}
|
||||
+788
@@ -0,0 +1,788 @@
|
||||
/*
|
||||
* File : uart.c
|
||||
* Copyright (C) 2013 - 2016, Espressif Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of version 3 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
#include "driver/uart.h"
|
||||
#include "osapi.h"
|
||||
#include "driver/uart_register.h"
|
||||
#include "mem.h"
|
||||
#include "os_type.h"
|
||||
|
||||
// UartDev is defined and initialized in rom code.
|
||||
extern UartDevice UartDev;
|
||||
|
||||
LOCAL struct UartBuffer* pTxBuffer = NULL;
|
||||
LOCAL struct UartBuffer* pRxBuffer = NULL;
|
||||
|
||||
/*uart demo with a system task, to output what uart receives*/
|
||||
/*this is a example to process uart data from task,please change the priority to fit your application task if exists*/
|
||||
/*it might conflict with your task, if so,please arrange the priority of different task, or combine it to a different event in the same task. */
|
||||
#define uart_recvTaskPrio 0
|
||||
#define uart_recvTaskQueueLen 10
|
||||
os_event_t uart_recvTaskQueue[uart_recvTaskQueueLen];
|
||||
|
||||
#define DBG
|
||||
#define DBG1 uart1_sendStr_no_wait
|
||||
#define DBG2 os_printf
|
||||
|
||||
|
||||
LOCAL void uart0_rx_intr_handler(void *para);
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart_config
|
||||
* Description : Internal used function
|
||||
* UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled
|
||||
* UART1 just used for debug output
|
||||
* Parameters : uart_no, use UART0 or UART1 defined ahead
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
uart_config(uint8 uart_no)
|
||||
{
|
||||
if (uart_no == UART1){
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
|
||||
}else{
|
||||
/* rcv_buff size if 0x100 */
|
||||
ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
|
||||
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
|
||||
#if UART_HW_RTS
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //HW FLOW CONTROL RTS PIN
|
||||
#endif
|
||||
#if UART_HW_CTS
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //HW FLOW CONTROL CTS PIN
|
||||
#endif
|
||||
}
|
||||
uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));//SET BAUDRATE
|
||||
|
||||
WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) //SET BIT AND PARITY MODE
|
||||
| ((UartDev.parity & UART_PARITY_M) <<UART_PARITY_S )
|
||||
| ((UartDev.stop_bits & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S)
|
||||
| ((UartDev.data_bits & UART_BIT_NUM) << 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); //RESET FIFO
|
||||
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),
|
||||
((100 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
|
||||
#if UART_HW_RTS
|
||||
((110 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) |
|
||||
UART_RX_FLOW_EN | //enbale rx flow control
|
||||
#endif
|
||||
(0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S |
|
||||
UART_RX_TOUT_EN|
|
||||
((0x10 & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S));//wjl
|
||||
#if UART_HW_CTS
|
||||
SET_PERI_REG_MASK( UART_CONF0(uart_no),UART_TX_FLOW_EN); //add this sentense to add a tx flow control via MTCK( CTS )
|
||||
#endif
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_TOUT_INT_ENA |UART_FRM_ERR_INT_ENA);
|
||||
}else{
|
||||
WRITE_PERI_REG(UART_CONF1(uart_no),((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));//TrigLvl default val == 1
|
||||
}
|
||||
//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|UART_RXFIFO_OVF_INT_ENA);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart1_tx_one_char
|
||||
* Description : Internal used function
|
||||
* Use uart1 interface to transfer one char
|
||||
* Parameters : uint8 TxChar - character to tx
|
||||
* Returns : OK
|
||||
*******************************************************************************/
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart1_write_char
|
||||
* Description : Internal used function
|
||||
* Do some special deal while tx char is '\r' or '\n'
|
||||
* Parameters : char c - character to tx
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//os_printf output to fifo or to the tx buffer
|
||||
LOCAL void ICACHE_FLASH_ATTR
|
||||
uart0_write_char_no_wait(char c)
|
||||
{
|
||||
#if UART_BUFF_EN //send to uart0 fifo but do not wait
|
||||
uint8 chr;
|
||||
if (c == '\n'){
|
||||
chr = '\r';
|
||||
tx_buff_enq(&chr, 1);
|
||||
chr = '\n';
|
||||
tx_buff_enq(&chr, 1);
|
||||
}else if (c == '\r'){
|
||||
|
||||
}else{
|
||||
tx_buff_enq(&c,1);
|
||||
}
|
||||
#else //send to uart tx buffer
|
||||
if (c == '\n'){
|
||||
uart_tx_one_char_no_wait(UART0, '\r');
|
||||
uart_tx_one_char_no_wait(UART0, '\n');
|
||||
}else if (c == '\r'){
|
||||
|
||||
}
|
||||
else{
|
||||
uart_tx_one_char_no_wait(UART0, c);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart0_tx_buffer
|
||||
* Description : use uart0 to transfer buffer
|
||||
* Parameters : uint8 *buf - point to send buffer
|
||||
* uint16 len - buffer len
|
||||
* Returns :
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart0_tx_buffer(uint8 *buf, uint16 len)
|
||||
{
|
||||
uint16 i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
uart_tx_one_char(UART0, buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart0_sendStr
|
||||
* Description : use uart0 to transfer buffer
|
||||
* Parameters : uint8 *buf - point to send buffer
|
||||
* uint16 len - buffer len
|
||||
* Returns :
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart0_sendStr(const char *str)
|
||||
{
|
||||
while(*str){
|
||||
uart_tx_one_char(UART0, *str++);
|
||||
}
|
||||
}
|
||||
void at_port_print(const char *str) __attribute__((alias("uart0_sendStr")));
|
||||
/******************************************************************************
|
||||
* FunctionName : uart0_rx_intr_handler
|
||||
* Description : Internal used function
|
||||
* UART0 interrupt handler, add self handle code inside
|
||||
* Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
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 temp,cnt;
|
||||
//RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;
|
||||
|
||||
/*ATTENTION:*/
|
||||
/*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/
|
||||
/*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */
|
||||
/*IF NOT , POST AN EVENT AND PROCESS IN SYSTEM TASK */
|
||||
if(UART_FRM_ERR_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_FRM_ERR_INT_ST)){
|
||||
DBG1("FRM_ERR\r\n");
|
||||
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
|
||||
}else if(UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_FULL_INT_ST)){
|
||||
DBG("f");
|
||||
uart_rx_intr_disable(UART0);
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
|
||||
system_os_post(uart_recvTaskPrio, 0, 0);
|
||||
}else if(UART_RXFIFO_TOUT_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_TOUT_INT_ST)){
|
||||
DBG("t");
|
||||
uart_rx_intr_disable(UART0);
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_TOUT_INT_CLR);
|
||||
system_os_post(uart_recvTaskPrio, 0, 0);
|
||||
}else if(UART_TXFIFO_EMPTY_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_TXFIFO_EMPTY_INT_ST)){
|
||||
DBG("e");
|
||||
/* to output uart data from uart buffer directly in empty interrupt handler*/
|
||||
/*instead of processing in system event, in order not to wait for current task/function to quit */
|
||||
/*ATTENTION:*/
|
||||
/*IN NON-OS VERSION SDK, DO NOT USE "ICACHE_FLASH_ATTR" FUNCTIONS IN THE WHOLE HANDLER PROCESS*/
|
||||
/*ALL THE FUNCTIONS CALLED IN INTERRUPT HANDLER MUST BE DECLARED IN RAM */
|
||||
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
||||
#if UART_BUFF_EN
|
||||
tx_start_uart_buffer(UART0);
|
||||
#endif
|
||||
//system_os_post(uart_recvTaskPrio, 1, 0);
|
||||
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_TXFIFO_EMPTY_INT_CLR);
|
||||
|
||||
}else if(UART_RXFIFO_OVF_INT_ST == (READ_PERI_REG(UART_INT_ST(uart_no)) & UART_RXFIFO_OVF_INT_ST)){
|
||||
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_RXFIFO_OVF_INT_CLR);
|
||||
DBG1("RX OVF!!\r\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart_init
|
||||
* Description : user interface for init uart
|
||||
* Parameters : UartBautRate uart0_br - uart0 bautrate
|
||||
* UartBautRate uart1_br - uart1 bautrate
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
#if UART_SELFTEST&UART_BUFF_EN
|
||||
os_timer_t buff_timer_t;
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart_test_rx()
|
||||
{
|
||||
uint8 uart_buf[128]={0};
|
||||
uint16 len = 0;
|
||||
len = rx_buff_deq(uart_buf, 128 );
|
||||
tx_buff_enq(uart_buf,len);
|
||||
}
|
||||
#endif
|
||||
|
||||
LOCAL void ICACHE_FLASH_ATTR ///////
|
||||
uart_recvTask(os_event_t *events)
|
||||
{
|
||||
if(events->sig == 0){
|
||||
#if UART_BUFF_EN
|
||||
Uart_rx_buff_enq();
|
||||
#else
|
||||
uint8 fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
|
||||
uint8 d_tmp = 0;
|
||||
uint8 idx=0;
|
||||
for(idx=0;idx<fifo_len;idx++) {
|
||||
d_tmp = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
|
||||
uart_tx_one_char(UART0, d_tmp);
|
||||
}
|
||||
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR|UART_RXFIFO_TOUT_INT_CLR);
|
||||
uart_rx_intr_enable(UART0);
|
||||
#endif
|
||||
}else if(events->sig == 1){
|
||||
#if UART_BUFF_EN
|
||||
//already move uart buffer output to uart empty interrupt
|
||||
//tx_start_uart_buffer(UART0);
|
||||
#else
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart_init(UartBautRate uart0_br, UartBautRate uart1_br)
|
||||
{
|
||||
/*this is a example to process uart data from task,please change the priority to fit your application task if exists*/
|
||||
system_os_task(uart_recvTask, uart_recvTaskPrio, uart_recvTaskQueue, uart_recvTaskQueueLen); //demo with a task to process the uart data
|
||||
|
||||
UartDev.baut_rate = uart0_br;
|
||||
uart_config(UART0);
|
||||
UartDev.baut_rate = uart1_br;
|
||||
uart_config(UART1);
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
#if UART_BUFF_EN
|
||||
pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE);
|
||||
pRxBuffer = Uart_Buf_Init(UART_RX_BUFFER_SIZE);
|
||||
#endif
|
||||
|
||||
|
||||
/*option 1: use default print, output from uart0 , will wait some time if fifo is full */
|
||||
//do nothing...
|
||||
|
||||
/*option 2: output from uart1,uart1 output will not wait , just for output debug info */
|
||||
/*os_printf output uart data via uart1(GPIO2)*/
|
||||
//os_install_putc1((void *)uart1_write_char); //use this one to output debug information via uart1 //
|
||||
|
||||
/*option 3: output from uart0 will skip current byte if fifo is full now... */
|
||||
/*see uart0_write_char_no_wait:you can output via a buffer or output directly */
|
||||
/*os_printf output uart data via uart0 or uart buffer*/
|
||||
//os_install_putc1((void *)uart0_write_char_no_wait); //use this to print via uart0
|
||||
|
||||
#if UART_SELFTEST&UART_BUFF_EN
|
||||
os_timer_disarm(&buff_timer_t);
|
||||
os_timer_setfn(&buff_timer_t, uart_test_rx , NULL); //a demo to process the data in uart rx buffer
|
||||
os_timer_arm(&buff_timer_t,10,1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart_reattach()
|
||||
{
|
||||
uart_init(BIT_RATE_115200, BIT_RATE_115200);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart_tx_one_char_no_wait
|
||||
* Description : uart tx a single char without waiting for fifo
|
||||
* Parameters : uint8 uart - uart port
|
||||
* uint8 TxChar - char to tx
|
||||
* Returns : STATUS
|
||||
*******************************************************************************/
|
||||
STATUS uart_tx_one_char_no_wait(uint8 uart, uint8 TxChar)
|
||||
{
|
||||
uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(uart))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT);
|
||||
if (fifo_cnt < 126) {
|
||||
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
STATUS uart0_tx_one_char_no_wait(uint8 TxChar)
|
||||
{
|
||||
uint8 fifo_cnt = (( READ_PERI_REG(UART_STATUS(UART0))>>UART_TXFIFO_CNT_S)& UART_TXFIFO_CNT);
|
||||
if (fifo_cnt < 126) {
|
||||
WRITE_PERI_REG(UART_FIFO(UART0) , TxChar);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart1_sendStr_no_wait
|
||||
* Description : uart tx a string without waiting for every char, used for print debug info which can be lost
|
||||
* Parameters : const char *str - string to be sent
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void uart1_sendStr_no_wait(const char *str)
|
||||
{
|
||||
while(*str){
|
||||
uart_tx_one_char_no_wait(UART1, *str++);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if UART_BUFF_EN
|
||||
/******************************************************************************
|
||||
* FunctionName : Uart_Buf_Init
|
||||
* Description : tx buffer enqueue: fill a first linked buffer
|
||||
* Parameters : char *pdata - data point to be enqueue
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
struct UartBuffer* ICACHE_FLASH_ATTR
|
||||
Uart_Buf_Init(uint32 buf_size)
|
||||
{
|
||||
uint32 heap_size = system_get_free_heap_size();
|
||||
if(heap_size <=buf_size){
|
||||
DBG1("no buf for uart\n\r");
|
||||
return NULL;
|
||||
}else{
|
||||
DBG("test heap size: %d\n\r",heap_size);
|
||||
struct UartBuffer* pBuff = (struct UartBuffer* )os_malloc(sizeof(struct UartBuffer));
|
||||
pBuff->UartBuffSize = buf_size;
|
||||
pBuff->pUartBuff = (uint8*)os_malloc(pBuff->UartBuffSize);
|
||||
pBuff->pInPos = pBuff->pUartBuff;
|
||||
pBuff->pOutPos = pBuff->pUartBuff;
|
||||
pBuff->Space = pBuff->UartBuffSize;
|
||||
pBuff->BuffState = OK;
|
||||
pBuff->nextBuff = NULL;
|
||||
pBuff->TcpControl = RUN;
|
||||
return pBuff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//copy uart buffer
|
||||
LOCAL void Uart_Buf_Cpy(struct UartBuffer* pCur, char* pdata , uint16 data_len)
|
||||
{
|
||||
if(data_len == 0) return ;
|
||||
|
||||
uint16 tail_len = pCur->pUartBuff + pCur->UartBuffSize - pCur->pInPos ;
|
||||
if(tail_len >= data_len){ //do not need to loop back the queue
|
||||
os_memcpy(pCur->pInPos , pdata , data_len );
|
||||
pCur->pInPos += ( data_len );
|
||||
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize );
|
||||
pCur->Space -=data_len;
|
||||
}else{
|
||||
os_memcpy(pCur->pInPos, pdata, tail_len);
|
||||
pCur->pInPos += ( tail_len );
|
||||
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize );
|
||||
pCur->Space -=tail_len;
|
||||
os_memcpy(pCur->pInPos, pdata+tail_len , data_len-tail_len);
|
||||
pCur->pInPos += ( data_len-tail_len );
|
||||
pCur->pInPos = (pCur->pUartBuff + (pCur->pInPos - pCur->pUartBuff) % pCur->UartBuffSize );
|
||||
pCur->Space -=( data_len-tail_len);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : uart_buf_free
|
||||
* Description : deinit of the tx buffer
|
||||
* Parameters : struct UartBuffer* pTxBuff - tx buffer struct pointer
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart_buf_free(struct UartBuffer* pBuff)
|
||||
{
|
||||
os_free(pBuff->pUartBuff);
|
||||
os_free(pBuff);
|
||||
}
|
||||
|
||||
|
||||
//rx buffer dequeue
|
||||
uint16 ICACHE_FLASH_ATTR
|
||||
rx_buff_deq(char* pdata, uint16 data_len )
|
||||
{
|
||||
uint16 buf_len = (pRxBuffer->UartBuffSize- pRxBuffer->Space);
|
||||
uint16 tail_len = pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize - pRxBuffer->pOutPos ;
|
||||
uint16 len_tmp = 0;
|
||||
len_tmp = ((data_len > buf_len)?buf_len:data_len);
|
||||
if(pRxBuffer->pOutPos <= pRxBuffer->pInPos){
|
||||
os_memcpy(pdata, pRxBuffer->pOutPos,len_tmp);
|
||||
pRxBuffer->pOutPos+= len_tmp;
|
||||
pRxBuffer->Space += len_tmp;
|
||||
}else{
|
||||
if(len_tmp>tail_len){
|
||||
os_memcpy(pdata, pRxBuffer->pOutPos, tail_len);
|
||||
pRxBuffer->pOutPos += tail_len;
|
||||
pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize );
|
||||
pRxBuffer->Space += tail_len;
|
||||
|
||||
os_memcpy(pdata+tail_len , pRxBuffer->pOutPos, len_tmp-tail_len);
|
||||
pRxBuffer->pOutPos+= ( len_tmp-tail_len );
|
||||
pRxBuffer->pOutPos= (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize );
|
||||
pRxBuffer->Space +=( len_tmp-tail_len);
|
||||
}else{
|
||||
//os_printf("case 3 in rx deq\n\r");
|
||||
os_memcpy(pdata, pRxBuffer->pOutPos, len_tmp);
|
||||
pRxBuffer->pOutPos += len_tmp;
|
||||
pRxBuffer->pOutPos = (pRxBuffer->pUartBuff + (pRxBuffer->pOutPos- pRxBuffer->pUartBuff) % pRxBuffer->UartBuffSize );
|
||||
pRxBuffer->Space += len_tmp;
|
||||
}
|
||||
}
|
||||
if(pRxBuffer->Space >= UART_FIFO_LEN){
|
||||
uart_rx_intr_enable(UART0);
|
||||
}
|
||||
return len_tmp;
|
||||
}
|
||||
|
||||
|
||||
//move data from uart fifo to rx buffer
|
||||
void Uart_rx_buff_enq()
|
||||
{
|
||||
uint8 fifo_len,buf_idx;
|
||||
uint8 fifo_data;
|
||||
#if 1
|
||||
fifo_len = (READ_PERI_REG(UART_STATUS(UART0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
|
||||
if(fifo_len >= pRxBuffer->Space){
|
||||
os_printf("buf full!!!\n\r");
|
||||
}else{
|
||||
buf_idx=0;
|
||||
while(buf_idx < fifo_len){
|
||||
buf_idx++;
|
||||
fifo_data = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
|
||||
*(pRxBuffer->pInPos++) = fifo_data;
|
||||
if(pRxBuffer->pInPos == (pRxBuffer->pUartBuff + pRxBuffer->UartBuffSize)){
|
||||
pRxBuffer->pInPos = pRxBuffer->pUartBuff;
|
||||
}
|
||||
}
|
||||
pRxBuffer->Space -= fifo_len ;
|
||||
if(pRxBuffer->Space >= UART_FIFO_LEN){
|
||||
//os_printf("after rx enq buf enough\n\r");
|
||||
uart_rx_intr_enable(UART0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//fill the uart tx buffer
|
||||
void ICACHE_FLASH_ATTR
|
||||
tx_buff_enq(char* pdata, uint16 data_len )
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
||||
|
||||
if(pTxBuffer == NULL){
|
||||
DBG1("\n\rnull, create buffer struct\n\r");
|
||||
pTxBuffer = Uart_Buf_Init(UART_TX_BUFFER_SIZE);
|
||||
if(pTxBuffer!= NULL){
|
||||
Uart_Buf_Cpy(pTxBuffer , pdata, data_len );
|
||||
}else{
|
||||
DBG1("uart tx MALLOC no buf \n\r");
|
||||
}
|
||||
}else{
|
||||
if(data_len <= pTxBuffer->Space){
|
||||
Uart_Buf_Cpy(pTxBuffer , pdata, data_len);
|
||||
}else{
|
||||
DBG1("UART TX BUF FULL!!!!\n\r");
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
if(pTxBuffer->Space <= URAT_TX_LOWER_SIZE){
|
||||
set_tcp_block();
|
||||
}
|
||||
#endif
|
||||
SET_PERI_REG_MASK(UART_CONF1(UART0), (UART_TX_EMPTY_THRESH_VAL & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S);
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//--------------------------------
|
||||
LOCAL void tx_fifo_insert(struct UartBuffer* pTxBuff, uint8 data_len, uint8 uart_no)
|
||||
{
|
||||
uint8 i;
|
||||
for(i = 0; i<data_len;i++){
|
||||
WRITE_PERI_REG(UART_FIFO(uart_no) , *(pTxBuff->pOutPos++));
|
||||
if(pTxBuff->pOutPos == (pTxBuff->pUartBuff + pTxBuff->UartBuffSize)){
|
||||
pTxBuff->pOutPos = pTxBuff->pUartBuff;
|
||||
}
|
||||
}
|
||||
pTxBuff->pOutPos = (pTxBuff->pUartBuff + (pTxBuff->pOutPos - pTxBuff->pUartBuff) % pTxBuff->UartBuffSize );
|
||||
pTxBuff->Space += data_len;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* FunctionName : tx_start_uart_buffer
|
||||
* Description : get data from the tx buffer and fill the uart tx fifo, co-work with the uart fifo empty interrupt
|
||||
* Parameters : uint8 uart_no - uart port num
|
||||
* Returns : NONE
|
||||
*******************************************************************************/
|
||||
void tx_start_uart_buffer(uint8 uart_no)
|
||||
{
|
||||
uint8 tx_fifo_len = (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT;
|
||||
uint8 fifo_remain = UART_FIFO_LEN - tx_fifo_len ;
|
||||
uint8 len_tmp;
|
||||
uint16 tail_ptx_len,head_ptx_len,data_len;
|
||||
//struct UartBuffer* pTxBuff = *get_buff_prt();
|
||||
|
||||
if(pTxBuffer){
|
||||
data_len = (pTxBuffer->UartBuffSize - pTxBuffer->Space);
|
||||
if(data_len > fifo_remain){
|
||||
len_tmp = fifo_remain;
|
||||
tx_fifo_insert( pTxBuffer,len_tmp,uart_no);
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(UART0), UART_TXFIFO_EMPTY_INT_ENA);
|
||||
}else{
|
||||
len_tmp = data_len;
|
||||
tx_fifo_insert( pTxBuffer,len_tmp,uart_no);
|
||||
}
|
||||
}else{
|
||||
DBG1("pTxBuff null \n\r");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void uart_rx_intr_disable(uint8 uart_no)
|
||||
{
|
||||
#if 1
|
||||
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
|
||||
#else
|
||||
ETS_UART_INTR_DISABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
void uart_rx_intr_enable(uint8 uart_no)
|
||||
{
|
||||
#if 1
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA|UART_RXFIFO_TOUT_INT_ENA);
|
||||
#else
|
||||
ETS_UART_INTR_ENABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//========================================================
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetWordLength(uint8 uart_no, UartBitsNum4Char len)
|
||||
{
|
||||
SET_PERI_REG_BITS(UART_CONF0(uart_no),UART_BIT_NUM,len,UART_BIT_NUM_S);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetStopBits(uint8 uart_no, UartStopBitsNum bit_num)
|
||||
{
|
||||
SET_PERI_REG_BITS(UART_CONF0(uart_no),UART_STOP_BIT_NUM,bit_num,UART_STOP_BIT_NUM_S);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetLineInverse(uint8 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 ICACHE_FLASH_ATTR
|
||||
UART_SetParity(uint8 uart_no, UartParityMode Parity_mode)
|
||||
{
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY |UART_PARITY_EN);
|
||||
if(Parity_mode==NONE_BITS){
|
||||
}else{
|
||||
SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode|UART_PARITY_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetBaudrate(uint8 uart_no,uint32 baud_rate)
|
||||
{
|
||||
uart_div_modify(uart_no, UART_CLK_FREQ /baud_rate);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetFlowCtrl(uint8 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 ICACHE_FLASH_ATTR
|
||||
UART_WaitTxFifoEmpty(uint8 uart_no , uint32 time_out_us) //do not use if tx flow control enabled
|
||||
{
|
||||
uint32 t_s = system_get_time();
|
||||
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)){
|
||||
|
||||
if(( system_get_time() - t_s )> time_out_us){
|
||||
break;
|
||||
}
|
||||
WRITE_PERI_REG(0X60000914, 0X73);//WTD
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ICACHE_FLASH_ATTR
|
||||
UART_CheckOutputFinished(uint8 uart_no, uint32 time_out_us)
|
||||
{
|
||||
uint32 t_start = system_get_time();
|
||||
uint8 tx_fifo_len;
|
||||
uint32 tx_buff_len;
|
||||
while(1){
|
||||
tx_fifo_len =( (READ_PERI_REG(UART_STATUS(uart_no))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT);
|
||||
if(pTxBuffer){
|
||||
tx_buff_len = ((pTxBuffer->UartBuffSize)-(pTxBuffer->Space));
|
||||
}else{
|
||||
tx_buff_len = 0;
|
||||
}
|
||||
|
||||
if( tx_fifo_len==0 && tx_buff_len==0){
|
||||
return TRUE;
|
||||
}
|
||||
if( system_get_time() - t_start > time_out_us){
|
||||
return FALSE;
|
||||
}
|
||||
WRITE_PERI_REG(0X60000914, 0X73);//WTD
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_ResetFifo(uint8 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 ICACHE_FLASH_ATTR
|
||||
UART_ClearIntrStatus(uint8 uart_no,uint32 clr_mask)
|
||||
{
|
||||
WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetIntrEna(uint8 uart_no,uint32 ena_mask)
|
||||
{
|
||||
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
|
||||
}
|
||||
|
||||
|
||||
void ICACHE_FLASH_ATTR
|
||||
UART_SetPrintPort(uint8 uart_no)
|
||||
{
|
||||
if(uart_no==1){
|
||||
os_install_putc1(uart1_write_char);
|
||||
}else{
|
||||
/*option 1: do not wait if uart fifo is full,drop current character*/
|
||||
os_install_putc1(uart0_write_char_no_wait);
|
||||
/*option 2: wait for a while if uart fifo is full*/
|
||||
os_install_putc1(uart0_write_char);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================
|
||||
|
||||
|
||||
/*test code*/
|
||||
void ICACHE_FLASH_ATTR
|
||||
uart_init_2(UartBautRate uart0_br, UartBautRate uart1_br)
|
||||
{
|
||||
// rom use 74880 baut_rate, here reinitialize
|
||||
UartDev.baut_rate = uart0_br;
|
||||
UartDev.exist_parity = STICK_PARITY_EN;
|
||||
UartDev.parity = EVEN_BITS;
|
||||
UartDev.stop_bits = ONE_STOP_BIT;
|
||||
UartDev.data_bits = EIGHT_BITS;
|
||||
|
||||
uart_config(UART0);
|
||||
UartDev.baut_rate = uart1_br;
|
||||
uart_config(UART1);
|
||||
ETS_UART_INTR_ENABLE();
|
||||
|
||||
// install uart1 putc callback
|
||||
os_install_putc1((void *)uart1_write_char);//print output at UART1
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user