Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions interrupt_example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
build
firmware
testinterrupt.*
149 changes: 149 additions & 0 deletions interrupt_example/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# tnx to mamalala
# Changelog
# Changed the variables to include the header file directory
# Added global var for the XTENSA tool root
# Added variable for esptool bauds. Some modules don't work with default speed.
#
# This make file still needs some work.
#
# Updated for SDK 0.9.3
#
# Output directors to store intermediate compiled files
# relative to the project directory
BUILD_BASE = build
FW_BASE = firmware

# Base directory for the compiler
XTENSA_TOOLS_ROOT ?= /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf/bin

# base directory of the ESP8266 SDK package, absolute
SDK_BASE ?= /opt/Espressif/ESP8266_SDK

#Esptool.py path and port
ESPTOOL ?= esptool.py
ESPPORT ?= /dev/ttyUSB0
ESPBAUD ?= 115200

# name for the target project
TARGET = app

# which modules (subdirectories) of the project to include in compiling
MODULES = driver user
EXTRA_INCDIR = include /opt/Espressif/include

# libraries used in this project, mainly provided by the SDK
LIBS = c gcc hal pp phy net80211 lwip wpa main

# compiler flags using during compilation of source files
CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH

# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static

# linker script used for the above linkier step
LD_SCRIPT = eagle.app.v6.ld

# various paths from the SDK used in this project
SDK_LIBDIR = lib
SDK_LDDIR = ld
SDK_INCDIR = include include/json

# we create two different files for uploading into the flash
# these are the names and options to generate them
FW_FILE_1 = 0x00000
FW_FILE_1_ARGS = -bo $@ -bs .text -bs .data -bs .rodata -bc -ec
FW_FILE_2 = 0x40000
FW_FILE_2_ARGS = -es .irom0.text $@ -ec

# select which tools to use as compiler, librarian and linker
CC := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc
AR := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-ar
LD := $(XTENSA_TOOLS_ROOT)/xtensa-lx106-elf-gcc



####
#### no user configurable options below here
####
FW_TOOL ?= /usr/bin/esptool
SRC_DIR := $(MODULES)
BUILD_DIR := $(addprefix $(BUILD_BASE)/,$(MODULES))

SDK_LIBDIR := $(addprefix $(SDK_BASE)/,$(SDK_LIBDIR))
SDK_INCDIR := $(addprefix -I$(SDK_BASE)/,$(SDK_INCDIR))

SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.c))
OBJ := $(patsubst %.c,$(BUILD_BASE)/%.o,$(SRC))
LIBS := $(addprefix -l,$(LIBS))
APP_AR := $(addprefix $(BUILD_BASE)/,$(TARGET)_app.a)
TARGET_OUT := $(addprefix $(BUILD_BASE)/,$(TARGET).out)

LD_SCRIPT := $(addprefix -T$(SDK_BASE)/$(SDK_LDDIR)/,$(LD_SCRIPT))

INCDIR := $(addprefix -I,$(SRC_DIR))
EXTRA_INCDIR := $(addprefix -I,$(EXTRA_INCDIR))
MODULE_INCDIR := $(addsuffix /include,$(INCDIR))

FW_FILE_1 := $(addprefix $(FW_BASE)/,$(FW_FILE_1).bin)
FW_FILE_2 := $(addprefix $(FW_BASE)/,$(FW_FILE_2).bin)

V ?= $(VERBOSE)
ifeq ("$(V)","1")
Q :=
vecho := @true
else
Q := @
vecho := @echo
endif

vpath %.c $(SRC_DIR)

define compile-objects
$1/%.o: %.c
$(vecho) "CC $$<"
$(Q) $(CC) $(INCDIR) $(MODULE_INCDIR) $(EXTRA_INCDIR) $(SDK_INCDIR) $(CFLAGS) -c $$< -o $$@
endef

.PHONY: all checkdirs flash clean

all: checkdirs $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)

$(FW_FILE_1): $(TARGET_OUT)
$(vecho) "FW $@"
$(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_1_ARGS)

$(FW_FILE_2): $(TARGET_OUT)
$(vecho) "FW $@"
$(Q) $(FW_TOOL) -eo $(TARGET_OUT) $(FW_FILE_2_ARGS)

$(TARGET_OUT): $(APP_AR)
$(vecho) "LD $@"
$(Q) $(LD) -L$(SDK_LIBDIR) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(LIBS) $(APP_AR) -Wl,--end-group -o $@

$(APP_AR): $(OBJ)
$(vecho) "AR $@"
$(Q) $(AR) cru $@ $^

checkdirs: $(BUILD_DIR) $(FW_BASE)

$(BUILD_DIR):
$(Q) mkdir -p $@

firmware:
$(Q) mkdir -p $@

flash: firmware/0x00000.bin firmware/0x40000.bin
-$(ESPTOOL) --baud $(ESPBAUD) --port $(ESPPORT) write_flash 0x00000 firmware/0x00000.bin 0x40000 firmware/0x40000.bin

clean:
$(Q) rm -f $(APP_AR)
$(Q) rm -f $(TARGET_OUT)
$(Q) rm -rf $(BUILD_DIR)
$(Q) rm -rf $(BUILD_BASE)


$(Q) rm -f $(FW_FILE_1)
$(Q) rm -f $(FW_FILE_2)
$(Q) rm -rf $(FW_BASE)

$(foreach bdir,$(BUILD_DIR),$(eval $(call compile-objects,$(bdir))))
Empty file.
168 changes: 168 additions & 0 deletions interrupt_example/user/user_main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#include "ets_sys.h"
#include "osapi.h"
#include "gpio.h"
#include "os_type.h"
#include "user_interface.h"

#define user_procTaskPrio 0
#define user_procTaskQueueLen 1
os_event_t user_procTaskQueue[user_procTaskQueueLen];
static void loop(os_event_t *events);


// variable modified indirectly by interrupt handler
volatile int whatyouwant;

// gpio interrupt handler. See below
LOCAL void gpio_intr_handler(int * dummy);

//-------------------------------------------------------------------------------------------------
// loop function will be execute by "os" periodically
static void ICACHE_FLASH_ATTR loop(os_event_t *events)
{
static int level;

os_printf("What you want %d \r\n",whatyouwant);
// change GPIO 2 level
level = !level;
GPIO_OUTPUT_SET(GPIO_ID_PIN(2), ((level) ? 1 : 0));
// Delay
os_delay_us(100000);
// turn again
system_os_post(user_procTaskPrio, 0, 0 );
}

//-------------------------------------------------------------------------------------------------
//Init function
void ICACHE_FLASH_ATTR user_init()
{

// Initialize UART0 to use as debug
uart_div_modify(0, UART_CLK_FREQ / 9600);

os_printf(
"GPIO Interrupt ESP8266 test\r\n"
"---------------------------\r\n"
" This program out a square wave on gpio2 and count edges for gpio0\r\n"
" The program report count edges gpio0 periodically.\r\n"
" You Can\r\n"
" 1.- Connect GPIO0 to GPIO2 so you can see increment count edge periodically\r\n"
" 2.- Unconnect GPIO0 from GPIO2 so you can see stop count edge\r\n"
" 3.- Connect GPIO0 to ground to increment count edge\r\n"
);

// Initialize the GPIO subsystem.
gpio_init();

// =================================================
// Initialize GPIO2 and GPIO0 as GPIO
// =================================================
//
//
// PIN_FUNC_SELECT() defined in eagle_soc.h
// PERIPHS_IO_MUX_... for each pin defined in eagle_soc.h
// FUNC_... for each PERIPHS macros defined in eagle_soc.h
//
// From eagle_soc.h:
// GPIO0 only can be GPIO
// GPIO2 can be GPIO, TXD from uart0, or TXD from uart1
//
// #define PERIPHS_IO_MUX_GPIO0_U (PERIPHS_IO_MUX + 0x34)
// #define FUNC_GPIO0 0
// #define PERIPHS_IO_MUX_GPIO2_U (PERIPHS_IO_MUX + 0x38)
// #define FUNC_GPIO2 0
// #define FUNC_U1TXD_BK 2
// #define FUNC_U0TXD_BK 4
//

PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);

// You can select enable/disable internal pullup/pulldown for each pin
//
// PIN_PULLUP_DIS(PIN_NAME)
// PIN_PULLUP_EN(PIN_NAME)
// PIN_PULLDWN_DIS(PIN_NAME)
// PIN_PULLDWN_EN(PIN_NAME)

PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO0_U);
PIN_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO0_U);
PIN_PULLUP_EN(PERIPHS_IO_MUX_GPIO2_U);

//
// void gpio_output_set(uint32 set_mask, uint32 clear_mask, uint32 enable_mask, uint32 disable_mask)
//
// set status and direction pin by mask gpio id pin.

gpio_output_set(0, GPIO_ID_PIN(2), GPIO_ID_PIN(2), GPIO_ID_PIN(0)); // set gpio 2 as output and low. set gpio 0 as input

// =================================================
// Activate gpio interrupt for gpio2
// =================================================

// Disable interrupts by GPIO
ETS_GPIO_INTR_DISABLE();

// Attach interrupt handle to gpio interrupts.
// You can set a void pointer that will be passed to interrupt handler each interrupt

ETS_GPIO_INTR_ATTACH(gpio_intr_handler, &whatyouwant);

// void gpio_register_set(uint32 reg_id, uint32 value);
//
// From include file
// Set the specified GPIO register to the specified value.
// This is a very general and powerful interface that is not
// expected to be used during normal operation. It is intended
// mainly for debug, or for unusual requirements.
//
// All people repeat this mantra but I don't know what it means
//
gpio_register_set(GPIO_PIN_ADDR(0),
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 gpio status. Say ESP8266EX SDK Programming Guide in 5.1.6. GPIO interrupt handler

GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, BIT(0));

// enable interrupt for his GPIO
// GPIO_PIN_INTR_... defined in gpio.h

gpio_pin_intr_state_set(GPIO_ID_PIN(0), GPIO_PIN_INTR_ANYEGDE);

ETS_GPIO_INTR_ENABLE();

//Start os task
system_os_task(loop, user_procTaskPrio,user_procTaskQueue, user_procTaskQueueLen);

system_os_post(user_procTaskPrio, 0, 0 );
}

//-------------------------------------------------------------------------------------------------
// interrupt handler
// this function will be executed on any edge of GPIO0
LOCAL void gpio_intr_handler(int * dummy)
{
// clear gpio status. Say ESP8266EX SDK Programming Guide in 5.1.6. GPIO interrupt handler

uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);

// if the interrupt was by GPIO0
if (gpio_status & BIT(0))
{
// disable interrupt for GPIO0
gpio_pin_intr_state_set(GPIO_ID_PIN(0), GPIO_PIN_INTR_DISABLE);

// Do something, for example, increment whatyouwant indirectly
(*dummy)++;

//clear interrupt status for GPIO0
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & BIT(0));

// Reactivate interrupts for GPIO0
gpio_pin_intr_state_set(GPIO_ID_PIN(0), GPIO_PIN_INTR_ANYEGDE);
}
}