Merge branch 'master' into feature/c++
This commit is contained in:
commit
e43d2dd3de
27 changed files with 1352 additions and 591 deletions
62
.travis.yml
Normal file
62
.travis.yml
Normal file
|
@ -0,0 +1,62 @@
|
|||
language: c
|
||||
sudo: false
|
||||
env:
|
||||
# Target commit for https://github.com/pfalcon/esp-open-sdk/
|
||||
OPENSDK_COMMIT=b44afa47
|
||||
CROSS_ROOT="${HOME}/toolchain-${OPENSDK_COMMIT}"
|
||||
CROSS_BINDIR="${CROSS_ROOT}/bin"
|
||||
ESPTOOL2_COMMIT=92530bb8
|
||||
ESPTOOL2_BINDIR="${HOME}/esptool2-${ESPTOOL2_COMMIT}"
|
||||
PATH=${PATH}:${CROSS_BINDIR}:${ESPTOOL2_BINDIR}
|
||||
cache:
|
||||
directories:
|
||||
- ${CROSS_ROOT}
|
||||
- ${HOME}/.ccache
|
||||
- ${ESPTOOL2_BINDIR}
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- make
|
||||
- unrar
|
||||
- autoconf
|
||||
- automake
|
||||
- libtool
|
||||
- gcc
|
||||
- g++
|
||||
- gperf
|
||||
- flex
|
||||
- bison
|
||||
- texinfo
|
||||
- gawk
|
||||
- libncurses5-dev
|
||||
- libexpat1-dev
|
||||
- python
|
||||
- python-serial
|
||||
- sed
|
||||
- git
|
||||
|
||||
before_install:
|
||||
# Install a toolchain using esp-open-sdk (parts we need for this are the GNU toolchain and libhal)
|
||||
#
|
||||
# Adds hack of "{$HAS_TC} || -Buildstep-" to avoid rebuilding toolchain if it's already
|
||||
# installed from the cache. If this gets any more complex it should be spun out to a standalone shell script.
|
||||
- export HAS_TC="test -d ${CROSS_BINDIR}"
|
||||
- unset CC # Travis sets this due to "language: c", but it confuses autotools configure when cross-building
|
||||
- ${HAS_TC} || git clone --recursive https://github.com/pfalcon/esp-open-sdk.git
|
||||
- ${HAS_TC} || cd esp-open-sdk
|
||||
- ${HAS_TC} || git reset --hard ${OPENSDK_COMMIT}
|
||||
- ${HAS_TC} || git submodule update
|
||||
- ${HAS_TC} || sed -i "s/2.69/2.68/" lx106-hal/configure.ac # this is a nasty hack as Ubuntu Precise only has autoconf 2.68 not 2.69...
|
||||
- ${HAS_TC} || sed -r -i 's%TOOLCHAIN ?=.*%TOOLCHAIN=${CROSS_ROOT}%' Makefile
|
||||
- ${HAS_TC} || make STANDALONE=n
|
||||
- export HAS_ET2="test -f ${ESPTOOL2_BINDIR}/esptool2"
|
||||
- ${HAS_ET2} || git clone https://github.com/raburton/esp8266 ${HOME}/raburton
|
||||
- ${HAS_ET2} || make -C ${HOME}/raburton/esptool2
|
||||
- ${HAS_ET2} || mkdir -p ${ESPTOOL2_BINDIR}
|
||||
- ${HAS_ET2} || cp -a ${HOME}/raburton/esptool2/esptool2 ${ESPTOOL2_BINDIR}/
|
||||
|
||||
script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
# Remove ssid_config requirement for examples
|
||||
- sed -i "s%#warning%//#warning%" include/ssid_config.h
|
||||
- make -C examples/ build-examples CROSS="ccache xtensa-lx106-elf-"
|
|
@ -4,15 +4,17 @@ A community developed open source [FreeRTOS](http://www.freertos.org/)-based fra
|
|||
|
||||
Originally based on, but substantially different from, the [Espressif IOT RTOS SDK](https://github.com/espressif/esp_iot_rtos_sdk).
|
||||
|
||||
[![Build Status](https://travis-ci.org/SuperHouse/esp-open-rtos.svg?branch=master)](https://travis-ci.org/SuperHouse/esp-open-rtos)
|
||||
|
||||
## Quick Start
|
||||
|
||||
* Install [esp-open-sdk](https://github.com/pfalcon/esp-open-sdk/), build it with `make STANDALONE=n`, then edit your PATH and add the generated toolchain `bin` directory. (Despite the similar name esp-open-sdk has different maintainers - but we think it's fantastic!)
|
||||
|
||||
(Other toolchains will also work, as long as a gcc cross-compiler is available on the PATH. The proprietary Tensilica "xcc" compiler will probably not work.)
|
||||
(Other toolchains may also work, as long as a gcc cross-compiler is available on the PATH and libhal (and libhal headers) are compiled and available to gcc. The proprietary Tensilica "xcc" compiler will probably not work.)
|
||||
|
||||
* Install [esptool.py](https://github.com/themadinventor/esptool) and make it available on your PATH.
|
||||
* Install [esptool.py](https://github.com/themadinventor/esptool) and make it available on your PATH. If you used esp-open-sdk then this is done already.
|
||||
|
||||
* The build process uses `GNU Make`, and the utilities `sed` and `grep`. Linux & OS X should have these already. Windows users can get these tools a variety of ways - [MingGW](http://www.mingw.org/wiki/mingw) is one option.
|
||||
* The esp-open-rtos build process uses `GNU Make`, and the utilities `sed` and `grep`. If you built esp-open-sdk then you probably have these already.
|
||||
|
||||
* Use git to clone the esp-open-rtos project (note the `--recursive`):
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
OR
|
||||
|
||||
- Implement a single function named gpio_interrupt_handler(). This
|
||||
will need to manually check GPIO_STATUS_REG and clear any status
|
||||
will need to manually check GPIO.STATUS and clear any status
|
||||
bits after handling interrupts. This gives you full control, but
|
||||
you can't combine it with the first approach.
|
||||
|
||||
|
@ -67,14 +67,14 @@ const gpio_interrupt_handler_t gpio_interrupt_handlers[16] = {
|
|||
|
||||
void __attribute__((weak)) IRAM gpio_interrupt_handler(void)
|
||||
{
|
||||
uint32_t status_reg = GPIO_STATUS_REG;
|
||||
GPIO_STATUS_CLEAR = status_reg;
|
||||
uint32_t status_reg = GPIO.STATUS;
|
||||
GPIO.STATUS_CLEAR = status_reg;
|
||||
uint8_t gpio_idx;
|
||||
while((gpio_idx = __builtin_ffs(status_reg)))
|
||||
{
|
||||
gpio_idx--;
|
||||
status_reg &= ~BIT(gpio_idx);
|
||||
if(GPIO_CTRL_REG(gpio_idx) & GPIO_INT_MASK)
|
||||
if(FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_idx]))
|
||||
gpio_interrupt_handlers[gpio_idx]();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@
|
|||
* the arguments aren't known at compile time (values are evaluated at
|
||||
* compile time otherwise.)
|
||||
*/
|
||||
uint32_t _timer_freq_to_count_runtime(const timer_frc_t frc, const uint32_t freq, const timer_div_t div)
|
||||
uint32_t _timer_freq_to_count_runtime(const timer_frc_t frc, const uint32_t freq, const timer_clkdiv_t div)
|
||||
{
|
||||
return _timer_freq_to_count_impl(frc, freq, div);
|
||||
}
|
||||
|
||||
uint32_t _timer_time_to_count_runtime(const timer_frc_t frc, uint32_t us, const timer_div_t div)
|
||||
uint32_t _timer_time_to_count_runtime(const timer_frc_t frc, uint32_t us, const timer_clkdiv_t div)
|
||||
{
|
||||
return _timer_time_to_count_runtime(frc, us, div);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,16 @@
|
|||
#define BIT(X) (1<<(X))
|
||||
#endif
|
||||
|
||||
/* These macros convert values to/from bitfields specified by *_M and *_S (mask
|
||||
* and shift) constants. Used primarily with ESP8266 register access.
|
||||
*/
|
||||
|
||||
#define VAL2FIELD(fieldname, value) (((value) & fieldname##_M) << fieldname##_S)
|
||||
#define FIELD2VAL(fieldname, regbits) (((regbits) >> fieldname##_S) & fieldname##_M)
|
||||
|
||||
#define FIELD_MASK(fieldname) (fieldname##_M << fieldname##_S)
|
||||
#define SET_FIELD(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD(fieldname, value))
|
||||
|
||||
/* Use this macro to store constant values in IROM flash instead
|
||||
of having them loaded into rodata (which resides in DRAM)
|
||||
|
||||
|
|
125
core/include/esp/dport_regs.h
Normal file
125
core/include/esp/dport_regs.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* esp/dport_regs.h
|
||||
*
|
||||
* ESP8266 DPORT0 register definitions
|
||||
*
|
||||
* Not compatible with ESP SDK register access code.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_DPORT_REGS_H
|
||||
#define _ESP_DPORT_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
#define DPORT_BASE 0x3ff00000
|
||||
#define DPORT (*(struct DPORT_REGS *)(DPORT_BASE))
|
||||
|
||||
/* DPORT registers
|
||||
|
||||
Control various aspects of core/peripheral interaction... Not well
|
||||
documented or understood.
|
||||
*/
|
||||
|
||||
struct DPORT_REGS {
|
||||
uint32_t volatile DPORT0; // 0x00 FIXME: need a better name for this
|
||||
uint32_t volatile INT_ENABLE; // 0x04
|
||||
uint32_t volatile _unknown08; // 0x08
|
||||
uint32_t volatile SPI_READY; // 0x0c
|
||||
uint32_t volatile _unknown10; // 0x10
|
||||
uint32_t volatile CPU_CLOCK; // 0x14
|
||||
uint32_t volatile CLOCKGATE_WATCHDOG; // 0x18
|
||||
uint32_t volatile _unknown1c; // 0x1c
|
||||
uint32_t volatile SPI_INT_STATUS; // 0x20
|
||||
uint32_t volatile SPI_CACHE_RAM; // 0x24
|
||||
uint32_t volatile PERI_IO; // 0x28
|
||||
uint32_t volatile SLC_TX_DESC_DEBUG; // 0x2c
|
||||
uint32_t volatile _unknown30; // 0x30
|
||||
uint32_t volatile _unknown34; // 0x34
|
||||
uint32_t volatile _unknown38; // 0x38
|
||||
uint32_t volatile _unknown3c; // 0x3c
|
||||
uint32_t volatile _unknown40; // 0x40
|
||||
uint32_t volatile _unknown44; // 0x44
|
||||
uint32_t volatile _unknown48; // 0x48
|
||||
uint32_t volatile _unknown4c; // 0x4c
|
||||
uint32_t volatile OTP_MAC0; // 0x50
|
||||
uint32_t volatile OTP_MAC1; // 0x54
|
||||
uint32_t volatile OTP_CHIPID; // 0x58
|
||||
uint32_t volatile OTP_MAC2; // 0x5c
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct DPORT_REGS) == 0x60, "DPORT_REGS is the wrong size");
|
||||
|
||||
/* Details for DPORT0 register */
|
||||
|
||||
/* Currently very little known about this register. The following is based on analysis of the startup code in the Espressif SDK: */
|
||||
|
||||
#define DPORT_DPORT0_FIELD0_M 0x0000007f
|
||||
#define DPORT_DPORT0_FIELD0_S 0
|
||||
|
||||
/* Details for INT_ENABLE register */
|
||||
|
||||
/* Set flags to enable CPU interrupts from some peripherals. Read/write.
|
||||
|
||||
bit 0 - INT_ENABLE_WDT (unclear exactly how this works. Set by RTOS SDK startup code)
|
||||
bit 1 - INT_ENABLE_TIMER0 allows TIMER 0 (FRC1) to trigger interrupt INUM_TIMER_FRC1.
|
||||
bit 2 - INT_ENABLE_TIMER1 allows TIMER 1 (FRC2) to trigger interrupt INUM_TIMER_FRC2.
|
||||
|
||||
Espressif calls this register "EDGE_INT_ENABLE_REG". The "edge" in
|
||||
question is (I think) the interrupt line from the peripheral, as
|
||||
the interrupt status bit is set. There may be a similar register
|
||||
for enabling "level" interrupts instead of edge triggering
|
||||
- this is unknown.
|
||||
*/
|
||||
|
||||
#define DPORT_INT_ENABLE_WDT BIT(0)
|
||||
#define DPORT_INT_ENABLE_TIMER0 BIT(1)
|
||||
#define DPORT_INT_ENABLE_TIMER1 BIT(2)
|
||||
|
||||
/* Aliases for the Espressif way of referring to TIMER0 (FRC1) and TIMER1
|
||||
* (FRC2).. */
|
||||
#define DPORT_INT_ENABLE_FRC1 DPORT_INT_ENABLE_TIMER0
|
||||
#define DPORT_INT_ENABLE_FRC2 DPORT_INT_ENABLE_TIMER1
|
||||
|
||||
/* Details for SPI_READY register */
|
||||
|
||||
#define DPORT_SPI_READY_IDLE BIT(9)
|
||||
|
||||
/* Details for CPU_CLOCK register */
|
||||
|
||||
#define DPORT_CPU_CLOCK_X2 BIT(0)
|
||||
|
||||
/* Details for CLOCKGATE_WATCHDOG register */
|
||||
|
||||
/* Comment found in pvvx/mp3_decode headers: "use clockgate_watchdog(flg) { if(flg) 0x3FF00018 &= 0x77; else 0x3FF00018 |= 8; }". Not sure what this means or does. */
|
||||
|
||||
#define DPORT_CLOCKGATE_WATCHDOG_DISABLE BIT(3)
|
||||
|
||||
/* Details for SPI_INT_STATUS register */
|
||||
|
||||
#define DPORT_SPI_INT_STATUS_SPI0 BIT(4)
|
||||
#define DPORT_SPI_INT_STATUS_SPI1 BIT(7)
|
||||
#define DPORT_SPI_INT_STATUS_I2S BIT(9)
|
||||
|
||||
/* Details for SPI_CACHE_RAM register */
|
||||
|
||||
#define DPORT_SPI_CACHE_RAM_BANK1 BIT(3)
|
||||
#define DPORT_SPI_CACHE_RAM_BANK0 BIT(4)
|
||||
|
||||
/* Details for PERI_IO register */
|
||||
|
||||
#define DPORT_PERI_IO_SWAP_UARTS BIT(0)
|
||||
#define DPORT_PERI_IO_SWAP_SPIS BIT(1)
|
||||
#define DPORT_PERI_IO_SWAP_UART0_PINS BIT(2)
|
||||
#define DPORT_PERI_IO_SWAP_UART1_PINS BIT(3)
|
||||
#define DPORT_PERI_IO_SPI1_PRIORITY BIT(5)
|
||||
#define DPORT_PERI_IO_SPI1_SHARED BIT(6)
|
||||
#define DPORT_PERI_IO_SPI0_SHARED BIT(7)
|
||||
|
||||
/* Details for SLC_TX_DESC_DEBUG register */
|
||||
|
||||
#define SLC_TX_DESC_DEBUG_VALUE_M 0x0000ffff
|
||||
#define SLC_TX_DESC_DEBUG_VALUE_S 0
|
||||
|
||||
#define SLC_TX_DESC_DEBUG_VALUE_MAGIC 0xcccc
|
||||
|
||||
#endif /* _ESP_DPORT_REGS_H */
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef _ESP_GPIO_H
|
||||
#define _ESP_GPIO_H
|
||||
#include <stdbool.h>
|
||||
#include "esp/registers.h"
|
||||
#include "esp/gpio_regs.h"
|
||||
#include "esp/iomux.h"
|
||||
#include "esp/cpu.h"
|
||||
#include "xtensa_interrupts.h"
|
||||
|
@ -32,37 +32,38 @@ INLINED void gpio_enable(const uint8_t gpio_num, const gpio_direction_t directio
|
|||
switch(direction) {
|
||||
case GPIO_INPUT:
|
||||
iomux_flags = 0;
|
||||
ctrl_val = GPIO_SOURCE_GPIO;
|
||||
ctrl_val = 0;
|
||||
break;
|
||||
case GPIO_OUTPUT:
|
||||
iomux_flags = IOMUX_OE;
|
||||
ctrl_val = GPIO_DRIVE_PUSH_PULL|GPIO_SOURCE_GPIO;
|
||||
iomux_flags = IOMUX_PIN_OUTPUT_ENABLE;
|
||||
ctrl_val = GPIO_CONF_PUSH_PULL;
|
||||
break;
|
||||
case GPIO_OUT_OPEN_DRAIN:
|
||||
iomux_flags = IOMUX_OE;
|
||||
ctrl_val = GPIO_DRIVE_OPEN_DRAIN|GPIO_SOURCE_GPIO;
|
||||
iomux_flags = IOMUX_PIN_OUTPUT_ENABLE;
|
||||
ctrl_val = 0;
|
||||
break;
|
||||
case GPIO_INPUT_PULLUP:
|
||||
iomux_flags = IOMUX_PU;
|
||||
ctrl_val = GPIO_SOURCE_GPIO;
|
||||
iomux_flags = IOMUX_PIN_PULLUP;
|
||||
ctrl_val = 0;
|
||||
break;
|
||||
}
|
||||
iomux_set_gpio_function(gpio_num, iomux_flags);
|
||||
GPIO_CTRL_REG(gpio_num) = (GPIO_CTRL_REG(gpio_num)&GPIO_INT_MASK) | ctrl_val;
|
||||
if(direction == GPIO_OUTPUT)
|
||||
GPIO_DIR_SET = BIT(gpio_num);
|
||||
GPIO.CONF[gpio_num] = (GPIO.CONF[gpio_num] & FIELD_MASK(GPIO_CONF_INTTYPE)) | ctrl_val;
|
||||
if (iomux_flags & IOMUX_PIN_OUTPUT_ENABLE)
|
||||
GPIO.ENABLE_OUT_SET = BIT(gpio_num);
|
||||
else
|
||||
GPIO_DIR_CLEAR = BIT(gpio_num);
|
||||
GPIO.ENABLE_OUT_CLEAR = BIT(gpio_num);
|
||||
}
|
||||
|
||||
/* Disable GPIO on the specified pin, and set it Hi-Z.
|
||||
*
|
||||
* If later muxing this pin to a different function, make sure to set
|
||||
* IOMUX_OE if necessary to enable the output buffer.
|
||||
* IOMUX_PIN_OUTPUT_ENABLE if necessary to enable the output buffer.
|
||||
*/
|
||||
INLINED void gpio_disable(const uint8_t gpio_num)
|
||||
{
|
||||
GPIO_DIR_CLEAR = BIT(gpio_num);
|
||||
*gpio_iomux_reg(gpio_num) &= ~IOMUX_OE;
|
||||
GPIO.ENABLE_OUT_CLEAR = BIT(gpio_num);
|
||||
*gpio_iomux_reg(gpio_num) &= ~IOMUX_PIN_OUTPUT_ENABLE;
|
||||
}
|
||||
|
||||
/* Set output of a pin high or low.
|
||||
|
@ -72,9 +73,9 @@ INLINED void gpio_disable(const uint8_t gpio_num)
|
|||
INLINED void gpio_write(const uint8_t gpio_num, const bool set)
|
||||
{
|
||||
if(set)
|
||||
GPIO_OUT_SET = BIT(gpio_num);
|
||||
GPIO.OUT_SET = BIT(gpio_num);
|
||||
else
|
||||
GPIO_OUT_CLEAR = BIT(gpio_num);
|
||||
GPIO.OUT_CLEAR = BIT(gpio_num);
|
||||
}
|
||||
|
||||
/* Toggle output of a pin
|
||||
|
@ -89,10 +90,10 @@ INLINED void gpio_toggle(const uint8_t gpio_num)
|
|||
get an invalid value. Prevents one task from clobbering another
|
||||
task's pins, without needing to disable/enable interrupts.
|
||||
*/
|
||||
if(GPIO_OUT_REG & BIT(gpio_num))
|
||||
GPIO_OUT_CLEAR = BIT(gpio_num);
|
||||
if(GPIO.OUT & BIT(gpio_num))
|
||||
GPIO.OUT_CLEAR = BIT(gpio_num);
|
||||
else
|
||||
GPIO_OUT_SET = BIT(gpio_num);
|
||||
GPIO.OUT_SET = BIT(gpio_num);
|
||||
}
|
||||
|
||||
/* Read input value of a GPIO pin.
|
||||
|
@ -102,38 +103,28 @@ INLINED void gpio_toggle(const uint8_t gpio_num)
|
|||
*/
|
||||
INLINED bool gpio_read(const uint8_t gpio_num)
|
||||
{
|
||||
return GPIO_IN_REG & BIT(gpio_num);
|
||||
return GPIO.IN & BIT(gpio_num);
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
INT_NONE = 0,
|
||||
INT_RISING = GPIO_INT_RISING,
|
||||
INT_FALLING = GPIO_INT_FALLING,
|
||||
INT_CHANGE = GPIO_INT_CHANGE,
|
||||
INT_LOW = GPIO_INT_LOW,
|
||||
INT_HIGH = GPIO_INT_HIGH,
|
||||
} gpio_interrupt_t;
|
||||
|
||||
extern void gpio_interrupt_handler(void);
|
||||
|
||||
/* Set the interrupt type for a given pin
|
||||
*
|
||||
* If int_type is not INT_NONE, the gpio_interrupt_handler will be attached and unmasked.
|
||||
* If int_type is not GPIO_INTTYPE_NONE, the gpio_interrupt_handler will be attached and unmasked.
|
||||
*/
|
||||
INLINED void gpio_set_interrupt(const uint8_t gpio_num, const gpio_interrupt_t int_type)
|
||||
INLINED void gpio_set_interrupt(const uint8_t gpio_num, const gpio_inttype_t int_type)
|
||||
{
|
||||
GPIO_CTRL_REG(gpio_num) = (GPIO_CTRL_REG(gpio_num)&~GPIO_INT_MASK)
|
||||
| (int_type & GPIO_INT_MASK);
|
||||
if(int_type != INT_NONE) {
|
||||
GPIO.CONF[gpio_num] = SET_FIELD(GPIO.CONF[gpio_num], GPIO_CONF_INTTYPE, int_type);
|
||||
if(int_type != GPIO_INTTYPE_NONE) {
|
||||
_xt_isr_attach(INUM_GPIO, gpio_interrupt_handler);
|
||||
_xt_isr_unmask(1<<INUM_GPIO);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the interrupt type set for a pin */
|
||||
INLINED gpio_interrupt_t gpio_get_interrupt(const uint8_t gpio_num)
|
||||
INLINED gpio_inttype_t gpio_get_interrupt(const uint8_t gpio_num)
|
||||
{
|
||||
return (gpio_interrupt_t)(GPIO_CTRL_REG(gpio_num) & GPIO_INT_MASK);
|
||||
return FIELD2VAL(GPIO_CONF_INTTYPE, GPIO.CONF[gpio_num]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
130
core/include/esp/gpio_regs.h
Normal file
130
core/include/esp/gpio_regs.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/* esp/gpio_regs.h
|
||||
*
|
||||
* ESP8266 GPIO register definitions
|
||||
*
|
||||
* Not compatible with ESP SDK register access code.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_GPIO_REGS_H
|
||||
#define _ESP_GPIO_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
#define GPIO_BASE 0x60000300
|
||||
#define GPIO (*(struct GPIO_REGS *)(GPIO_BASE))
|
||||
|
||||
/** GPIO output registers GPIO.OUT, GPIO.OUT_SET, GPIO.OUT_CLEAR:
|
||||
*
|
||||
* _SET and _CLEAR write-only registers set and clear bits in the main register,
|
||||
* respectively.
|
||||
*
|
||||
* i.e.
|
||||
* GPIO.OUT_SET = BIT(3);
|
||||
* and
|
||||
* GPIO.OUT |= BIT(3);
|
||||
*
|
||||
* ... are equivalent, but the former uses fewer CPU cycles.
|
||||
*
|
||||
* ENABLE_OUT / ENABLE_OUT_SET / ENABLE_OUT_CLEAR:
|
||||
*
|
||||
* Determine whether the corresponding GPIO has its output enabled or not.
|
||||
* When clear, GPIO can function as an input. When set, GPIO will drive its
|
||||
* output (and IN register will simply reflect the output state).
|
||||
*
|
||||
* (_SET/_CLEAR function similarly to OUT registers)
|
||||
*
|
||||
* STATUS / STATUS_SET / STATUS_CLEAR:
|
||||
*
|
||||
* Indicates which GPIOs have triggered an interrupt. Interrupt status should
|
||||
* be reset by writing to STATUS or STATUS_CLEAR.
|
||||
*
|
||||
* (_SET/_CLEAR function similarly to OUT registers)
|
||||
*/
|
||||
|
||||
struct GPIO_REGS {
|
||||
uint32_t volatile OUT; // 0x00
|
||||
uint32_t volatile OUT_SET; // 0x04
|
||||
uint32_t volatile OUT_CLEAR; // 0x08
|
||||
uint32_t volatile ENABLE_OUT; // 0x0c
|
||||
uint32_t volatile ENABLE_OUT_SET; // 0x10
|
||||
uint32_t volatile ENABLE_OUT_CLEAR; // 0x14
|
||||
uint32_t volatile IN; // 0x18
|
||||
uint32_t volatile STATUS; // 0x1c
|
||||
uint32_t volatile STATUS_SET; // 0x20
|
||||
uint32_t volatile STATUS_CLEAR; // 0x24
|
||||
uint32_t volatile CONF[16]; // 0x28 - 0x64
|
||||
uint32_t volatile PWM; // 0x68
|
||||
uint32_t volatile RTC_CALIB; // 0x6c
|
||||
uint32_t volatile RTC_CALIB_RESULT; // 0x70
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
|
||||
|
||||
/* Details for CONF[i] registers */
|
||||
|
||||
/* GPIO.CONF[i] control the pin behavior for the corresponding GPIO in/output.
|
||||
*
|
||||
* GPIO_CONF_CONFIG (multi-value)
|
||||
* FIXME: Unclear what these do. Need to find a better name.
|
||||
*
|
||||
* GPIO_CONF_WAKEUP_ENABLE (boolean)
|
||||
* Can an interrupt contion on this pin wake the processor from a sleep
|
||||
* state?
|
||||
*
|
||||
* GPIO_CONF_INTTYPE (multi-value)
|
||||
* Under what conditions this GPIO input should generate an interrupt.
|
||||
* (see gpio_inttype_t enum below for values)
|
||||
*
|
||||
* GPIO_CONF_PUSH_PULL (boolean)
|
||||
* When set, a high output state will pull the pin up to +Vcc (3.3V). When
|
||||
* cleared, output functions in "open drain" mode (low state will pull down
|
||||
* to ground, but high state allows output to "float").
|
||||
*
|
||||
* GPIO_CONF_SOURCE_PWM (boolean)
|
||||
* When set, GPIO pin output will be connected to the sigma-delta PWM
|
||||
* generator (controlled by the GPIO.PWM register). When cleared, pin
|
||||
* output will function as a normal GPIO output (controlled by the
|
||||
* GPIO.OUT* registers).
|
||||
*/
|
||||
|
||||
#define GPIO_CONF_CONFIG_M 0x00000003
|
||||
#define GPIO_CONF_CONFIG_S 11
|
||||
#define GPIO_CONF_WAKEUP_ENABLE BIT(10)
|
||||
#define GPIO_CONF_INTTYPE_M 0x00000007
|
||||
#define GPIO_CONF_INTTYPE_S 7
|
||||
#define GPIO_CONF_PUSH_PULL BIT(2)
|
||||
#define GPIO_CONF_SOURCE_PWM BIT(0)
|
||||
|
||||
/* Valid values for the GPIO_CONF_INTTYPE field */
|
||||
typedef enum {
|
||||
GPIO_INTTYPE_NONE = 0,
|
||||
GPIO_INTTYPE_EDGE_POS = 1,
|
||||
GPIO_INTTYPE_EDGE_NEG = 2,
|
||||
GPIO_INTTYPE_EDGE_ANY = 3,
|
||||
GPIO_INTTYPE_LEVEL_LOW = 4,
|
||||
GPIO_INTTYPE_LEVEL_HIGH = 5,
|
||||
} gpio_inttype_t;
|
||||
|
||||
/* Details for PWM register */
|
||||
|
||||
#define GPIO_PWM_ENABLE BIT(16)
|
||||
#define GPIO_PWM_PRESCALER_M 0x000000ff
|
||||
#define GPIO_PWM_PRESCALER_S 8
|
||||
#define GPIO_PWM_TARGET_M 0x000000ff
|
||||
#define GPIO_PWM_TARGET_S 0
|
||||
|
||||
/* Details for RTC_CALIB register */
|
||||
|
||||
#define GPIO_RTC_CALIB_START BIT(31)
|
||||
#define GPIO_RTC_CALIB_PERIOD_M 0x000003ff
|
||||
#define GPIO_RTC_CALIB_PERIOD_S 0
|
||||
|
||||
/* Details for RTC_CALIB_RESULT register */
|
||||
|
||||
#define GPIO_RTC_CALIB_RESULT_READY BIT(31)
|
||||
#define GPIO_RTC_CALIB_RESULT_READY_REAL BIT(30)
|
||||
#define GPIO_RTC_CALIB_RESULT_VALUE_M 0x000fffff
|
||||
#define GPIO_RTC_CALIB_RESULT_VALUE_S 0
|
||||
|
||||
#endif /* _ESP_GPIO_REGS_H */
|
|
@ -8,8 +8,8 @@
|
|||
*/
|
||||
#ifndef _ESP_IOMUX_H
|
||||
#define _ESP_IOMUX_H
|
||||
#include <stdint.h>
|
||||
#include "esp/registers.h"
|
||||
#include "esp/types.h"
|
||||
#include "esp/iomux_regs.h"
|
||||
|
||||
/**
|
||||
* Convert a GPIO pin number to an iomux register index.
|
||||
|
@ -32,11 +32,11 @@ inline static uint8_t iomux_to_gpio(const uint8_t iomux_num);
|
|||
/**
|
||||
* Directly get the IOMUX register for a particular gpio number
|
||||
*
|
||||
* ie *gpio_iomux_reg(3) is equivalent to IOMUX_GP03
|
||||
* ie *gpio_iomux_reg(3) is equivalent to IOMUX_GPIO3
|
||||
*/
|
||||
inline static esp_reg_t gpio_iomux_reg(const uint8_t gpio_number)
|
||||
{
|
||||
return &IOMUX_REG(gpio_to_iomux(gpio_number));
|
||||
return &(IOMUX.PIN[gpio_to_iomux(gpio_number)]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -45,153 +45,21 @@ inline static esp_reg_t gpio_iomux_reg(const uint8_t gpio_number)
|
|||
* This allows you to set pins to GPIO without knowing in advance the
|
||||
* exact register masks to use.
|
||||
*
|
||||
* flags can be any of IOMUX_OE, IOMUX_PU, IOMUX_PD, etc. Any other flags will be cleared.
|
||||
* flags can be any of IOMUX_PIN_OUTPUT_ENABLE, IOMUX_PIN_PULLUP, IOMUX_PIN_PULLDOWN, etc. Any other flags will be cleared.
|
||||
*
|
||||
* Equivalent to a direct register operation if gpio_number is known at compile time.
|
||||
* ie the following are equivalent:
|
||||
*
|
||||
* iomux_set_gpio_function(12, IOMUX_OE);
|
||||
* IOMUX_GP12 = (IOMUX_GP12 & ~IOMUX_FUNC_MASK) | IOMUX_GP12_GPIO | IOMUX_OE;
|
||||
* iomux_set_gpio_function(12, IOMUX_PIN_OUTPUT_ENABLE);
|
||||
* IOMUX_GPIO12 = IOMUX_GPIO12_FUNC_GPIO | IOMUX_PIN_OUTPUT_ENABLE;
|
||||
*/
|
||||
inline static void iomux_set_gpio_function(const uint8_t gpio_number, const uint8_t flags)
|
||||
inline static void iomux_set_gpio_function(const uint8_t gpio_number, const uint32_t flags)
|
||||
{
|
||||
const uint8_t reg_idx = gpio_to_iomux(gpio_number);
|
||||
const esp_reg_t reg = &IOMUX_REG(reg_idx);
|
||||
const uint32_t func = (reg_idx > 11 ? IOMUX_FUNC_A : IOMUX_FUNC_D) | flags;
|
||||
const uint32_t val = *reg & ~(IOMUX_FUNC_MASK | IOMUX_FLAG_MASK);
|
||||
*reg = val | func;
|
||||
const uint32_t func = (reg_idx > 11 ? IOMUX_FUNC(0) : IOMUX_FUNC(3)) | flags;
|
||||
IOMUX.PIN[reg_idx] = func | flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an IOMUX register directly
|
||||
*
|
||||
* Shortcut for
|
||||
* IOMUX_GPxx = (IOMUX_GPxx & ~IOMUX_FUNC_MASK) | IOMUX_GPxx_func
|
||||
*
|
||||
* instead call
|
||||
* IOMUX_SET_FN(GPxx, func);
|
||||
* can also do
|
||||
* IOMUX_SET_FN(GP12, GPIO)|IOMUX_OE;
|
||||
* ... to set the OE flag if it was previously cleared.
|
||||
*
|
||||
* but a better option is:
|
||||
* IOMUX_SET(GP12, GPIO, IOMUX_OE);
|
||||
* ...which clears any other flags at the same time.
|
||||
*/
|
||||
#define IOMUX_SET_FN(GP,FN) IOMUX_##GP = ((IOMUX_##GP & ~IOMUX_FUNC_MASK) | IOMUX_##GP##_##FN)
|
||||
#define IOMUX_SET(GP,FN,FLAGS) IOMUX_##GP = ((IOMUX_##GP & ~(IOMUX_FUNC_MASK|IOMUX_FLAG_MASK)) | IOMUX_##GP##_##FN|FLAGS)
|
||||
|
||||
/* IOMUX register index 0, GPIO 12 */
|
||||
#define IOMUX_GP12 IOMUX_REG(0)
|
||||
#define IOMUX_GP12_MTDI IOMUX_FUNC_A
|
||||
#define IOMUX_GP12_I2S_DIN IOMUX_FUNC_B
|
||||
#define IOMUX_GP12_HSPI_MISO IOMUX_FUNC_C
|
||||
#define IOMUX_GP12_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP12_UART0_DTR IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 1, GPIO 13 */
|
||||
#define IOMUX_GP13 IOMUX_REG(1)
|
||||
#define IOMUX_GP13_MTCK IOMUX_FUNC_A
|
||||
#define IOMUX_GP13_I2SI_BCK IOMUX_FUNC_B
|
||||
#define IOMUX_GP13_HSPI_MOSI IOMUX_FUNC_C
|
||||
#define IOMUX_GP13_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP13_UART0_CTS IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 2, GPIO 14 */
|
||||
#define IOMUX_GP14 IOMUX_REG(2)
|
||||
#define IOMUX_GP14_MTMS IOMUX_FUNC_A
|
||||
#define IOMUX_GP14_I2SI_WS IOMUX_FUNC_B
|
||||
#define IOMUX_GP14_HSPI_CLK IOMUX_FUNC_C
|
||||
#define IOMUX_GP14_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP14_UART0_DSR IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 3, GPIO 15 */
|
||||
#define IOMUX_GP15 IOMUX_REG(3)
|
||||
#define IOMUX_GP15_MTDO IOMUX_FUNC_A
|
||||
#define IOMUX_GP15_I2SO_BCK IOMUX_FUNC_B
|
||||
#define IOMUX_GP15_HSPI_CS0 IOMUX_FUNC_C
|
||||
#define IOMUX_GP15_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP15_UART0_RTS IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 4, GPIO 3 */
|
||||
#define IOMUX_GP03 IOMUX_REG(4)
|
||||
#define IOMUX_GP03_UART0_RX IOMUX_FUNC_A
|
||||
#define IOMUX_GP03_I2SO_DATA IOMUX_FUNC_B
|
||||
#define IOMUX_GP03_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP03_CLK_XTAL_BK IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 5, GPIO 1 */
|
||||
#define IOMUX_GP01 IOMUX_REG(5)
|
||||
#define IOMUX_GP01_UART0_TX IOMUX_FUNC_A
|
||||
#define IOMUX_GP01_SPICS1 IOMUX_FUNC_B
|
||||
#define IOMUX_GP01_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP01_CLK_RTC_BK IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 6, GPIO 6 */
|
||||
#define IOMUX_GP06 IOMUX_REG(6)
|
||||
#define IOMUX_GP06_SD_CLK IOMUX_FUNC_A
|
||||
#define IOMUX_GP06_SP_ICLK IOMUX_FUNC_B
|
||||
#define IOMUX_GP06_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP06_UART1_CTS IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 7, GPIO 7 */
|
||||
#define IOMUX_GP07 IOMUX_REG(7)
|
||||
#define IOMUX_GP07_SD_DATA0 IOMUX_FUNC_A
|
||||
#define IOMUX_GP07_SPIQ_MISO IOMUX_FUNC_B
|
||||
#define IOMUX_GP07_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP07_UART1_TX IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 8, GPIO 8 */
|
||||
#define IOMUX_GP08 IOMUX_REG(8)
|
||||
#define IOMUX_GP08_SD_DATA1 IOMUX_FUNC_A
|
||||
#define IOMUX_GP08_SPID_MOSI IOMUX_FUNC_B
|
||||
#define IOMUX_GP08_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP08_UART1_RX IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 9, GPIO 9 */
|
||||
#define IOMUX_GP09 IOMUX_REG(9)
|
||||
#define IOMUX_GP09_SD_DATA2 IOMUX_FUNC_A
|
||||
#define IOMUX_GP09_SPI_HD IOMUX_FUNC_B
|
||||
#define IOMUX_GP09_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP09_UFNC_HSPIHD IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 10, GPIO 10 */
|
||||
#define IOMUX_GP10 IOMUX_REG(10)
|
||||
#define IOMUX_GP10_SD_DATA3 IOMUX_FUNC_A
|
||||
#define IOMUX_GP10_SPI_WP IOMUX_FUNC_B
|
||||
#define IOMUX_GP10_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP10_HSPIWP IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 11, GPIO 11 */
|
||||
#define IOMUX_GP11 IOMUX_REG(11)
|
||||
#define IOMUX_GP11_SD_CMD IOMUX_FUNC_A
|
||||
#define IOMUX_GP11_SPI_CS0 IOMUX_FUNC_B
|
||||
#define IOMUX_GP11_GPIO IOMUX_FUNC_D
|
||||
#define IOMUX_GP11_UART1_RTS IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 12, GPIO 0 */
|
||||
#define IOMUX_GP00 IOMUX_REG(12)
|
||||
#define IOMUX_GP00_GPIO IOMUX_FUNC_A
|
||||
#define IOMUX_GP00_SPI_CS2 IOMUX_FUNC_B
|
||||
#define IOMUX_GP00_CLK_OUT IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 13, GPIO 2 */
|
||||
#define IOMUX_GP02 IOMUX_REG(13)
|
||||
#define IOMUX_GP02_GPIO IOMUX_FUNC_A
|
||||
#define IOMUX_GP02_I2SO_WS IOMUX_FUNC_B
|
||||
#define IOMUX_GP02_UART1_TX IOMUX_FUNC_C
|
||||
#define IOMUX_GP02_UART0_TX IOMUX_FUNC_E
|
||||
|
||||
/* IOMUX register index 14, GPIO 4 */
|
||||
#define IOMUX_GP04 IOMUX_REG(14)
|
||||
#define IOMUX_GP04_GPIO4 IOMUX_FUNC_A
|
||||
#define IOMUX_GP04_CLK_XTAL IOMUX_FUNC_B
|
||||
|
||||
/* IOMUX register index 15, GPIO 5 */
|
||||
#define IOMUX_GP05 IOMUX_REG(15)
|
||||
#define IOMUX_GP05_GPIO5 IOMUX_FUNC_A
|
||||
#define IOMUX_GP05_CLK_RTC IOMUX_FUNC_B
|
||||
|
||||
/* esp_iomux_private contains implementation parts of the inline functions
|
||||
declared above */
|
||||
#include "esp/iomux_private.h"
|
||||
|
|
151
core/include/esp/iomux_regs.h
Normal file
151
core/include/esp/iomux_regs.h
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* esp/iomux_regs.h
|
||||
*
|
||||
* ESP8266 IOMUX register definitions
|
||||
*
|
||||
* Not compatible with ESP SDK register access code.
|
||||
*
|
||||
* Note that IOMUX register order is _not_ the same as GPIO order. See
|
||||
* esp/iomux.h for programmer-friendly IOMUX configuration options.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_IOMUX_REGS_H
|
||||
#define _ESP_IOMUX_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
#define IOMUX_BASE 0x60000800
|
||||
#define IOMUX (*(struct IOMUX_REGS *)(IOMUX_BASE))
|
||||
|
||||
struct IOMUX_REGS {
|
||||
uint32_t volatile CONF; // 0x00
|
||||
uint32_t volatile PIN[16]; // 0x04 - 0x40
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct IOMUX_REGS) == 0x44, "IOMUX_REGS is the wrong size");
|
||||
|
||||
/* Details for CONF register */
|
||||
|
||||
#define IOMUX_CONF_SPI0_CLOCK_EQU_SYS_CLOCK BIT(8)
|
||||
#define IOMUX_CONF_SPI1_CLOCK_EQU_SYS_CLOCK BIT(9)
|
||||
|
||||
/* Details for PIN registers */
|
||||
|
||||
#define IOMUX_PIN_OUTPUT_ENABLE BIT(0)
|
||||
#define IOMUX_PIN_OUTPUT_ENABLE_SLEEP BIT(1)
|
||||
#define IOMUX_PIN_PULLDOWN_SLEEP BIT(2)
|
||||
#define IOMUX_PIN_PULLUP_SLEEP BIT(3)
|
||||
#define IOMUX_PIN_FUNC_LOW_M 0x00000003
|
||||
#define IOMUX_PIN_FUNC_LOW_S 4
|
||||
#define IOMUX_PIN_PULLDOWN BIT(6)
|
||||
#define IOMUX_PIN_PULLUP BIT(7)
|
||||
#define IOMUX_PIN_FUNC_HIGH_M 0x00000004
|
||||
#define IOMUX_PIN_FUNC_HIGH_S 8
|
||||
|
||||
#define IOMUX_PIN_FUNC_MASK 0x00001030
|
||||
|
||||
/* WARNING: Macro evaluates argument twice */
|
||||
#define IOMUX_FUNC(val) (VAL2FIELD(IOMUX_PIN_FUNC_LOW, val) | VAL2FIELD(IOMUX_PIN_FUNC_HIGH, val))
|
||||
|
||||
/* WARNING: Macro evaluates argument twice */
|
||||
#define IOMUX_FUNC_VALUE(regbits) (FIELD2VAL(IOMUX_PIN_FUNC_LOW, regbits) | FIELD2VAL(IOMUX_PIN_FUNC_HIGH, regbits))
|
||||
|
||||
#define IOMUX_SET_FUNC(regbits, funcval) (((regbits) & ~IOMUX_PIN_FUNC_MASK) | (funcval))
|
||||
|
||||
#define IOMUX_GPIO0 IOMUX.PIN[12]
|
||||
#define IOMUX_GPIO1 IOMUX.PIN[5]
|
||||
#define IOMUX_GPIO2 IOMUX.PIN[13]
|
||||
#define IOMUX_GPIO3 IOMUX.PIN[4]
|
||||
#define IOMUX_GPIO4 IOMUX.PIN[14]
|
||||
#define IOMUX_GPIO5 IOMUX.PIN[15]
|
||||
#define IOMUX_GPIO6 IOMUX.PIN[6]
|
||||
#define IOMUX_GPIO7 IOMUX.PIN[7]
|
||||
#define IOMUX_GPIO8 IOMUX.PIN[8]
|
||||
#define IOMUX_GPIO9 IOMUX.PIN[9]
|
||||
#define IOMUX_GPIO10 IOMUX.PIN[10]
|
||||
#define IOMUX_GPIO11 IOMUX.PIN[11]
|
||||
#define IOMUX_GPIO12 IOMUX.PIN[0]
|
||||
#define IOMUX_GPIO13 IOMUX.PIN[1]
|
||||
#define IOMUX_GPIO14 IOMUX.PIN[2]
|
||||
#define IOMUX_GPIO15 IOMUX.PIN[3]
|
||||
|
||||
#define IOMUX_GPIO0_FUNC_GPIO IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO0_FUNC_SPI0_CS2 IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO0_FUNC_CLOCK_OUT IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO1_FUNC_UART0_TXD IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO1_FUNC_SPI0_CS1 IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO1_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO1_FUNC_CLOCK_RTC_BLINK IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO2_FUNC_GPIO IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO2_FUNC_I2SO_WS IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO2_FUNC_UART1_TXD_BLINK IOMUX_FUNC(2)
|
||||
#define IOMUX_GPIO2_FUNC_UART0_TXD_BLINK IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO3_FUNC_UART0_RXD IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO3_FUNC_I2SO_DATA IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO3_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO3_FUNC_CLOCK_XTAL_BLINK IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO4_FUNC_GPIO IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO4_FUNC_CLOCK_XTAL IOMUX_FUNC(1)
|
||||
|
||||
#define IOMUX_GPIO5_FUNC_GPIO IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO5_FUNC_CLOCK_RTC IOMUX_FUNC(1)
|
||||
|
||||
#define IOMUX_GPIO6_FUNC_SD_CLK IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO6_FUNC_SPI0_CLK IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO6_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO6_FUNC_UART1_CTS IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO7_FUNC_SD_DATA0 IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO7_FUNC_SPI0_Q_MISO IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO7_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO7_FUNC_UART1_TXD IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO8_FUNC_SD_DATA1 IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO8_FUNC_SPI0_D_MOSI IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO8_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO8_FUNC_UART1_RXD IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO9_FUNC_SD_DATA2 IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO9_FUNC_SPI0_HD IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO9_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO9_FUNC_SPI1_HD IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO10_FUNC_SD_DATA3 IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO10_FUNC_SPI0_WP IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO10_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO10_FUNC_SPI1_WP IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO11_FUNC_SD_CMD IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO11_FUNC_SPI0_CS0 IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO11_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO11_FUNC_UART1_RTS IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO12_FUNC_MTDI IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO12_FUNC_I2SI_DATA IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO12_FUNC_SPI1_Q_MISO IOMUX_FUNC(2)
|
||||
#define IOMUX_GPIO12_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO12_FUNC_UART0_DTR IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO13_FUNC_MTCK IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO13_FUNC_I2SI_BCK IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO13_FUNC_SPI1_D_MOSI IOMUX_FUNC(2)
|
||||
#define IOMUX_GPIO13_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO13_FUNC_UART0_CTS IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO14_FUNC_MTMS IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO14_FUNC_I2SI_WS IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO14_FUNC_SPI1_CLK IOMUX_FUNC(2)
|
||||
#define IOMUX_GPIO14_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO14_FUNC_UART0_DSR IOMUX_FUNC(4)
|
||||
|
||||
#define IOMUX_GPIO15_FUNC_MTDO IOMUX_FUNC(0)
|
||||
#define IOMUX_GPIO15_FUNC_I2SO_BCK IOMUX_FUNC(1)
|
||||
#define IOMUX_GPIO15_FUNC_SPI1_CS0 IOMUX_FUNC(2)
|
||||
#define IOMUX_GPIO15_FUNC_GPIO IOMUX_FUNC(3)
|
||||
#define IOMUX_GPIO15_FUNC_UART0_RTS IOMUX_FUNC(4)
|
||||
|
||||
#endif /* _ESP_IOMUX_REGS_H */
|
|
@ -14,295 +14,43 @@
|
|||
#ifndef _ESP_REGISTERS
|
||||
#define _ESP_REGISTERS
|
||||
#include "common_macros.h"
|
||||
#include "esp/types.h"
|
||||
|
||||
typedef volatile uint32_t *esp_reg_t;
|
||||
|
||||
/* Internal macro, only defined in header body */
|
||||
#define _REG(BASE, OFFSET) (*(esp_reg_t)((BASE)+(OFFSET)))
|
||||
#include "esp/uart_regs.h"
|
||||
#include "esp/spi_regs.h"
|
||||
#include "esp/iomux_regs.h"
|
||||
#include "esp/gpio_regs.h"
|
||||
#include "esp/timer_regs.h"
|
||||
#include "esp/wdt_regs.h"
|
||||
#include "esp/rtcmem_regs.h"
|
||||
#include "esp/dport_regs.h"
|
||||
|
||||
/* Register base addresses
|
||||
|
||||
You shouldn't need to use these directly.
|
||||
The base addresses below are ones which haven't been migrated to
|
||||
the new register header style yet. For any commented out lines, see
|
||||
the matching xxx_regs.h header file referenced above.
|
||||
|
||||
If you want to access registers that aren't mapped to the new
|
||||
register header system yet, you can either use the deprecated
|
||||
Espressif SDK headers (in include/espressif), or you can create a
|
||||
new register header file and contribute it to the project (hooray!)
|
||||
*/
|
||||
#define MMIO_BASE 0x60000000
|
||||
#define DPORT_BASE 0x3ff00000
|
||||
//#define DPORT_BASE 0x3ff00000
|
||||
|
||||
#define UART0_BASE (MMIO_BASE + 0)
|
||||
#define SPI1_BASE (MMIO_BASE + 0x0100)
|
||||
#define SPI_BASE (MMIO_BASE + 0x0200)
|
||||
#define GPIO0_BASE (MMIO_BASE + 0x0300)
|
||||
#define TIMER_BASE (MMIO_BASE + 0x0600)
|
||||
//#define UART0_BASE (MMIO_BASE + 0)
|
||||
//#define SPI1_BASE (MMIO_BASE + 0x0100)
|
||||
//#define SPI_BASE (MMIO_BASE + 0x0200)
|
||||
//#define GPIO0_BASE (MMIO_BASE + 0x0300)
|
||||
//#define TIMER_BASE (MMIO_BASE + 0x0600)
|
||||
#define RTC_BASE (MMIO_BASE + 0x0700)
|
||||
#define IOMUX_BASE (MMIO_BASE + 0x0800)
|
||||
#define WDT_BASE (MMIO_BASE + 0x0900)
|
||||
//#define IOMUX_BASE (MMIO_BASE + 0x0800)
|
||||
//#define WDT_BASE (MMIO_BASE + 0x0900)
|
||||
#define I2C_BASE (MMIO_BASE + 0x0d00)
|
||||
#define UART1_BASE (MMIO_BASE + 0x0F00)
|
||||
#define RTCB_BASE (MMIO_BASE + 0x1000)
|
||||
#define RTCS_BASE (MMIO_BASE + 0x1100)
|
||||
#define RTCU_BASE (MMIO_BASE + 0x1200)
|
||||
|
||||
/*
|
||||
* iomux registers, apply to pin functions.
|
||||
*
|
||||
* Note that IOMUX register order is _not_ the same as GPIO order. See
|
||||
* esp_iomux.h for programmer-friendly IOMUX configuration options
|
||||
*/
|
||||
#define IOMUX_REG(X) _REG(IOMUX_BASE,0x04+4*X)
|
||||
|
||||
#define IOMUX_OE BIT(0) /* iomux Output enable bit */
|
||||
#define IOMUX_OE_SLEEP BIT(1) /* iomux Output during sleep bit */
|
||||
|
||||
#define IOMUX_PD BIT(6) /* iomux soft pulldown bit */
|
||||
#define IOMUX_PD_SLEEP BIT(2) /* iomux soft pulldown during sleep bit */
|
||||
#define IOMUX_PU BIT(7) /* iomux soft pullup bit */
|
||||
#define IOMUX_PU_SLEEP BIT(3) /* iomux soft pullup during sleep bit */
|
||||
|
||||
#define IOMUX_FLAG_WAKE_MASK (IOMUX_OE|IOMUX_PD|IOMUX_PU)
|
||||
#define IOMUX_FLAG_SLEEP_MASK (IOMUX_OE_SLEEP|IOMUX_PD_SLEEP|IOMUX_PU_SLEEP)
|
||||
#define IOMUX_FLAG_MASK (IOMUX_FLAG_WAKE_MASK|IOMUX_FLAG_SLEEP_MASK)
|
||||
|
||||
#define IOMUX_FUNC_MASK (BIT(4)|BIT(5)|BIT(12))
|
||||
|
||||
/* All pins have FUNC_A on reset (unconfirmed) */
|
||||
#define IOMUX_FUNC_A (0)
|
||||
#define IOMUX_FUNC_B BIT(4)
|
||||
#define IOMUX_FUNC_C BIT(5)
|
||||
#define IOMUX_FUNC_D BIT(4)|BIT(5)
|
||||
#define IOMUX_FUNC_E BIT(12)
|
||||
|
||||
|
||||
/*
|
||||
* Based on descriptions by mamalala at https://github.com/esp8266/esp8266-wiki/wiki/gpio-registers
|
||||
*/
|
||||
|
||||
/** GPIO OUTPUT registers GPIO_OUT_REG, GPIO_OUT_SET, GPIO_OUT_CLEAR
|
||||
*
|
||||
* Registers for pin outputs.
|
||||
*
|
||||
* _SET and _CLEAR write-only registers set and clear bits in _REG,
|
||||
* respectively.
|
||||
*
|
||||
* ie
|
||||
* GPIO_OUT_REG |= BIT(3);
|
||||
* and
|
||||
* GPIO_OUT_SET = BIT(3);
|
||||
*
|
||||
* ... are equivalent, but latter uses less CPU cycles.
|
||||
*/
|
||||
#define GPIO_OUT_REG _REG(GPIO0_BASE, 0x00)
|
||||
#define GPIO_OUT_SET _REG(GPIO0_BASE, 0x04)
|
||||
#define GPIO_OUT_CLEAR _REG(GPIO0_BASE, 0x08)
|
||||
|
||||
/* GPIO DIR registers GPIO_DIR_REG, GPIO_DIR_SET, GPIO_DIR_CLEAR
|
||||
*
|
||||
* Set bit in DIR register for output pins. Writing to _SET and _CLEAR
|
||||
* registers set and clear bits in _REG, respectively.
|
||||
*/
|
||||
#define GPIO_DIR_REG _REG(GPIO0_BASE, 0x0C)
|
||||
#define GPIO_DIR_SET _REG(GPIO0_BASE, 0x10)
|
||||
#define GPIO_DIR_CLEAR _REG(GPIO0_BASE, 0x14)
|
||||
|
||||
|
||||
/* GPIO IN register GPIO_IN_REG
|
||||
*
|
||||
* Reads current input values.
|
||||
*/
|
||||
#define GPIO_IN_REG _REG(GPIO0_BASE, 0x18)
|
||||
|
||||
/* GPIO interrupt 'status' flag
|
||||
|
||||
Bit set if interrupt has fired (see below for interrupt config
|
||||
registers.
|
||||
|
||||
Lower 16 bits only are used.
|
||||
*/
|
||||
#define GPIO_STATUS_REG _REG(GPIO0_BASE,0x1c)
|
||||
#define GPIO_STATUS_SET _REG(GPIO0_BASE,0x20)
|
||||
#define GPIO_STATUS_CLEAR _REG(GPIO0_BASE,0x24)
|
||||
|
||||
#define GPIO_STATUS_MASK 0x0000FFFFL
|
||||
|
||||
/* GPIO pin control registers for GPIOs 0-15
|
||||
*
|
||||
*/
|
||||
#define GPIO_CTRL_REG(GPNUM) _REG(GPIO0_BASE, 0x28+(GPNUM*4))
|
||||
|
||||
#define GPIO_SOURCE_GPIO 0
|
||||
#define GPIO_SOURCE_DAC BIT(0) /* "Sigma-Delta" */
|
||||
#define GPIO_SOURCE_MASK BIT(0
|
||||
|
||||
#define GPIO_DRIVE_PUSH_PULL 0
|
||||
#define GPIO_DRIVE_OPEN_DRAIN BIT(2)
|
||||
#define GPIO_DRIVE_MASK BIT(2)
|
||||
|
||||
#define GPIO_INT_NONE 0
|
||||
#define GPIO_INT_RISING BIT(7)
|
||||
#define GPIO_INT_FALLING BIT(8)
|
||||
#define GPIO_INT_CHANGE (BIT(7)|BIT(8))
|
||||
#define GPIO_INT_LOW BIT(9)
|
||||
#define GPIO_INT_HIGH (BIT(7)|BIT(9))
|
||||
#define GPIO_INT_MASK (BIT(7)|BIT(8)|BIT(9))
|
||||
|
||||
/* TIMER registers
|
||||
*
|
||||
* ESP8266 has two hardware(?) timer counters, FRC1 and FRC2.
|
||||
*
|
||||
* FRC1 is a 24-bit countdown timer, triggers interrupt when reaches zero.
|
||||
* FRC2 is a 32-bit countup timer, can set a variable match value to trigger an interrupt.
|
||||
*
|
||||
* FreeRTOS tick timer appears to come from XTensa core tick timer0,
|
||||
* not either of these. FRC2 is used in the FreeRTOS SDK however. It
|
||||
* is set to free-run, interrupting periodically via updates to the
|
||||
* MATCH register. sdk_ets_timer_init configures FRC2 and assigns FRC2
|
||||
* interrupt handler at sdk_vApplicationTickHook+0x68
|
||||
*/
|
||||
|
||||
/* Load value for FRC1, read/write.
|
||||
|
||||
When TIMER_CTRL_RELOAD is cleared in TIMER_FRC1_CTRL_REG, FRC1 will
|
||||
reload to TIMER_FRC1_MAX_LOAD once overflowed (unless the load
|
||||
value is rewritten in the interrupt handler.)
|
||||
|
||||
When TIMER_CTRL_RELOAD is set in TIMER_FRC1_CTRL_REG, FRC1 will reload
|
||||
from the load register value once overflowed.
|
||||
*/
|
||||
#define TIMER_FRC1_LOAD_REG _REG(TIMER_BASE, 0x00)
|
||||
|
||||
#define TIMER_FRC1_MAX_LOAD 0x7fffff
|
||||
|
||||
/* Current count value for FRC1, read only? */
|
||||
#define TIMER_FRC1_COUNT_REG _REG(TIMER_BASE, 0x04)
|
||||
|
||||
/* Control register for FRC1, read/write.
|
||||
|
||||
See the bit definitions TIMER_CTRL_xxx lower down.
|
||||
*/
|
||||
#define TIMER_FRC1_CTRL_REG _REG(TIMER_BASE, 0x08)
|
||||
|
||||
/* Reading this register always returns the value in
|
||||
* TIMER_FRC1_LOAD_REG.
|
||||
*
|
||||
* Writing zero to this register clears the FRC1
|
||||
* interrupt status.
|
||||
*/
|
||||
#define TIMER_FRC1_CLEAR_INT_REG _REG(TIMER_BASE, 0x0c)
|
||||
|
||||
/* FRC2 load register.
|
||||
*
|
||||
* If TIMER_CTRL_RELOAD is cleared in TIMER_FRC2_CTRL_REG, writing to
|
||||
* this register will update the FRC2 COUNT value.
|
||||
*
|
||||
* If TIMER_CTRL_RELOAD is set in TIMER_FRC2_CTRL_REG, the behaviour
|
||||
* appears to be the same except that writing 0 to the load register
|
||||
* both sets the COUNT register to 0 and disables the timer, even if
|
||||
* the TIMER_CTRL_RUN bit is set.
|
||||
*
|
||||
* Offsets 0x34, 0x38, 0x3c all seem to read back the LOAD_REG value
|
||||
* also (but have no known function.)
|
||||
*/
|
||||
#define TIMER_FRC2_LOAD_REG _REG(TIMER_BASE, 0x20)
|
||||
|
||||
/* FRC2 current count value. Read only? */
|
||||
#define TIMER_FRC2_COUNT_REG _REG(TIMER_BASE, 0x24)
|
||||
|
||||
/* Control register for FRC2. Read/write.
|
||||
|
||||
See the bit definitions TIMER_CTRL_xxx lower down.
|
||||
*/
|
||||
#define TIMER_FRC2_CTRL_REG _REG(TIMER_BASE, 0x28)
|
||||
|
||||
/* Reading this value returns the current value of
|
||||
* TIMER_FRC2_LOAD_REG.
|
||||
*
|
||||
* Writing zero to this value clears the FRC2 interrupt status.
|
||||
*/
|
||||
#define TIMER_FRC2_CLEAR_INT_REG _REG(TIMER_BASE, 0x2c)
|
||||
|
||||
/* Interrupt match value for FRC2. When COUNT == MATCH,
|
||||
the interrupt fires.
|
||||
*/
|
||||
#define TIMER_FRC2_MATCH_REG _REG(TIMER_BASE, 0x30)
|
||||
|
||||
/* Timer control bits to set clock divisor values.
|
||||
|
||||
Divider from master 80MHz APB_CLK (unconfirmed, see esp/clocks.h).
|
||||
*/
|
||||
#define TIMER_CTRL_DIV_1 0
|
||||
#define TIMER_CTRL_DIV_16 BIT(2)
|
||||
#define TIMER_CTRL_DIV_256 BIT(3)
|
||||
#define TIMER_CTRL_DIV_MASK (BIT(2)|BIT(3))
|
||||
|
||||
/* Set timer control bits to trigger interrupt on "edge" or "level"
|
||||
*
|
||||
* Observed behaviour is like this:
|
||||
*
|
||||
* * When TIMER_CTRL_INT_LEVEL is set, the interrupt status bit
|
||||
* TIMER_CTRL_INT_STATUS remains set when the timer interrupt
|
||||
* triggers, unless manually cleared by writing 0 to
|
||||
* TIMER_FRCx_CLEAR_INT. While the interrupt status bit stays set
|
||||
* the timer will continue to run normally, but the interrupt
|
||||
* (INUM_TIMER_FRC1 or INUM_TIMER_FRC2) won't trigger again.
|
||||
*
|
||||
* * When TIMER_CTRL_INT_EDGE (default) is set, there's no need to
|
||||
* manually write to TIMER_FRCx_CLEAR_INT. The interrupt status bit
|
||||
* TIMER_CTRL_INT_STATUS automatically clears after the interrupt
|
||||
* triggers, and the interrupt handler will run again
|
||||
* automatically.
|
||||
*
|
||||
*/
|
||||
#define TIMER_CTRL_INT_EDGE 0
|
||||
#define TIMER_CTRL_INT_LEVEL BIT(0)
|
||||
#define TIMER_CTRL_INT_MASK BIT(0)
|
||||
|
||||
/* Timer auto-reload bit
|
||||
|
||||
This bit interacts with TIMER_FRC1_LOAD_REG & TIMER_FRC2_LOAD_REG
|
||||
differently, see those registers for details.
|
||||
*/
|
||||
#define TIMER_CTRL_RELOAD BIT(6)
|
||||
|
||||
/* Timer run bit */
|
||||
#define TIMER_CTRL_RUN BIT(7)
|
||||
|
||||
/* Read-only timer interrupt status.
|
||||
|
||||
This bit gets set on FRC1 when interrupt fires, and cleared on a
|
||||
write to TIMER_FRC1_CLEAR_INT (cleared automatically if
|
||||
TIMER_CTRL_INT_LEVEL is not set).
|
||||
*/
|
||||
#define TIMER_CTRL_INT_STATUS BIT(8)
|
||||
|
||||
/* WDT register(s)
|
||||
|
||||
Not fully understood yet. Writing 0 here disables wdt.
|
||||
|
||||
See ROM functions esp_wdt_xxx
|
||||
*/
|
||||
#define WDT_CTRL _REG(WDT_BASE, 0x00)
|
||||
|
||||
/* DPORT registers
|
||||
|
||||
Control various aspects of core/peripheral interaction... Not well
|
||||
documented or understood.
|
||||
*/
|
||||
|
||||
/* Set flags to enable CPU interrupts from some peripherals. Read/write.
|
||||
|
||||
bit 0 - Is set by RTOS SDK startup code but function is unknown.
|
||||
bit 1 - INT_ENABLE_FRC1 allows TIMER FRC1 to trigger interrupt INUM_TIMER_FRC1.
|
||||
bit 2 - INT_ENABLE_FRC2 allows TIMER FRC2 to trigger interrupt INUM_TIMER_FRC2.
|
||||
|
||||
Espressif calls this register "EDGE_INT_ENABLE_REG". The "edge" in
|
||||
question is (I think) the interrupt line from the peripheral, as
|
||||
the interrupt status bit is set. There may be a similar register
|
||||
for enabling "level" interrupts instead of edge triggering
|
||||
- this is unknown.
|
||||
*/
|
||||
#define DP_INT_ENABLE_REG _REG(DPORT_BASE, 0x04)
|
||||
|
||||
/* Set to enable interrupts from TIMER FRC1 */
|
||||
#define INT_ENABLE_FRC1 BIT(1)
|
||||
/* Set to enable interrupts interrupts from TIMER FRC2 */
|
||||
#define INT_ENABLE_FRC2 BIT(2)
|
||||
//#define UART1_BASE (MMIO_BASE + 0x0F00)
|
||||
//#define RTCB_BASE (MMIO_BASE + 0x1000)
|
||||
//#define RTCS_BASE (MMIO_BASE + 0x1100)
|
||||
//#define RTCU_BASE (MMIO_BASE + 0x1200)
|
||||
|
||||
#endif
|
||||
|
|
44
core/include/esp/rtcmem_regs.h
Normal file
44
core/include/esp/rtcmem_regs.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* esp/rtcmem_regs.h
|
||||
*
|
||||
* ESP8266 RTC semi-persistent memory register definitions
|
||||
*
|
||||
* Not compatible with ESP SDK register access code.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_RTCMEM_REGS_H
|
||||
#define _ESP_RTCMEM_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
/* The RTC memory is a range of 256 words (1 KB) of general-purpose memory
|
||||
* within the Real Time Clock peripheral. Because it's part of the RTC, it
|
||||
* continues to be powered (and retains its contents) even when the ESP8266 is
|
||||
* in its deepest sleep mode (and other RAM is lost). It can therefore be
|
||||
* useful for keeping data which must be persisted through sleep or a reset.
|
||||
*
|
||||
* Note, however, that it is not "battery backed", or flash memory, and thus
|
||||
* will not keep its contents if power is removed entirely.
|
||||
*/
|
||||
|
||||
// We could just define these as 'volatile uint32_t *', but doing things this
|
||||
// way means that the RTCMEM* defines will include array size information, so
|
||||
// the C compiler can do bounds-checking for static arguments.
|
||||
|
||||
typedef volatile uint32_t rtcmem_array64_t[64];
|
||||
typedef volatile uint32_t rtcmem_array128_t[128];
|
||||
typedef volatile uint32_t rtcmem_array256_t[256];
|
||||
|
||||
#define RTCMEM_BASE 0x60001000
|
||||
|
||||
/* RTCMEM is an array covering the entire semi-persistent memory range */
|
||||
#define RTCMEM (*(rtcmem_array256_t *)(RTCMEM_BASE))
|
||||
|
||||
/* RTCMEM_BACKUP / RTCMEM_SYSTEM / RTCMEM_USER are the same range, divided up
|
||||
* into chunks by application/use, as defined by Espressif */
|
||||
|
||||
#define RTCMEM_BACKUP (*(rtcmem_array64_t *)(RTCMEM_BASE))
|
||||
#define RTCMEM_SYSTEM (*(rtcmem_array64_t *)(RTCMEM_BASE + 0x100))
|
||||
#define RTCMEM_USER (*(rtcmem_array128_t *)(RTCMEM_BASE + 0x200))
|
||||
|
||||
#endif /* _ESP_RTCMEM_REGS_H */
|
244
core/include/esp/spi_regs.h
Normal file
244
core/include/esp/spi_regs.h
Normal file
|
@ -0,0 +1,244 @@
|
|||
/** esp/spi.h
|
||||
*
|
||||
* Configuration of SPI registers.
|
||||
*
|
||||
* Part of esp-open-rtos
|
||||
* Copyright (C) 2015 Superhouse Automation Pty Ltd
|
||||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
#ifndef _SPI_REGS_H
|
||||
#define _SPI_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
/* Register definitions for the SPI peripherals on the ESP8266.
|
||||
*
|
||||
* There are twp SPI devices built into the ESP8266:
|
||||
* SPI(0) is at 0x60000200
|
||||
* SPI(1) is at 0x60000100
|
||||
* (note that the device number order is reversed in memory)
|
||||
*
|
||||
* Each device is allocated a block of 64 32-bit registers (256 bytes of
|
||||
* address space) to communicate with application code.
|
||||
*/
|
||||
|
||||
#define SPI_BASE 0x60000200
|
||||
#define SPI(i) (*(struct SPI_REGS *)(0x60000200 - (i)*0x100))
|
||||
|
||||
#define SPI0_BASE SPI_BASE
|
||||
#define SPI1_BASE (SPI_BASE - 0x100)
|
||||
|
||||
struct SPI_REGS {
|
||||
uint32_t volatile CMD; // 0x00
|
||||
uint32_t volatile ADDR; // 0x04
|
||||
uint32_t volatile CTRL0; // 0x08
|
||||
uint32_t volatile CTRL1; // 0x0c
|
||||
uint32_t volatile RSTATUS; // 0x10
|
||||
uint32_t volatile CTRL2; // 0x14
|
||||
uint32_t volatile CLOCK; // 0x18
|
||||
uint32_t volatile USER0; // 0x1c
|
||||
uint32_t volatile USER1; // 0x20
|
||||
uint32_t volatile USER2; // 0x24
|
||||
uint32_t volatile WSTATUS; // 0x28
|
||||
uint32_t volatile PIN; // 0x2c
|
||||
uint32_t volatile SLAVE0; // 0x30
|
||||
uint32_t volatile SLAVE1; // 0x34
|
||||
uint32_t volatile SLAVE2; // 0x38
|
||||
uint32_t volatile SLAVE3; // 0x3c
|
||||
uint32_t volatile W0; // 0x40
|
||||
uint32_t volatile W1; // 0x44
|
||||
uint32_t volatile W2; // 0x48
|
||||
uint32_t volatile W3; // 0x4c
|
||||
uint32_t volatile W4; // 0x50
|
||||
uint32_t volatile W5; // 0x54
|
||||
uint32_t volatile W6; // 0x58
|
||||
uint32_t volatile W7; // 0x5c
|
||||
uint32_t volatile W8; // 0x60
|
||||
uint32_t volatile W9; // 0x64
|
||||
uint32_t volatile W10; // 0x68
|
||||
uint32_t volatile W11; // 0x6c
|
||||
uint32_t volatile W12; // 0x70
|
||||
uint32_t volatile W13; // 0x74
|
||||
uint32_t volatile W14; // 0x78
|
||||
uint32_t volatile W15; // 0x7c
|
||||
uint32_t volatile _unused[28]; // 0x80 - 0xec
|
||||
uint32_t volatile EXT0; // 0xf0
|
||||
uint32_t volatile EXT1; // 0xf4
|
||||
uint32_t volatile EXT2; // 0xf8
|
||||
uint32_t volatile EXT3; // 0xfc
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct SPI_REGS) == 0x100, "SPI_REGS is the wrong size");
|
||||
|
||||
/* Details for CMD register */
|
||||
|
||||
#define SPI_CMD_USR BIT(18)
|
||||
|
||||
/* Details for CTRL0 register */
|
||||
|
||||
#define SPI_CTRL0_WR_BIT_ORDER BIT(26)
|
||||
#define SPI_CTRL0_RD_BIT_ORDER BIT(25)
|
||||
#define SPI_CTRL0_QIO_MODE BIT(24)
|
||||
#define SPI_CTRL0_DIO_MODE BIT(23)
|
||||
#define SPI_CTRL0_QOUT_MODE BIT(20)
|
||||
#define SPI_CTRL0_DOUT_MODE BIT(14)
|
||||
#define SPI_CTRL0_FASTRD_MODE BIT(13)
|
||||
#define SPI_CTRL0_CLOCK_EQU_SYS_CLOCK BIT(12)
|
||||
#define SPI_CTRL0_CLOCK_NUM_M 0x0000000F
|
||||
#define SPI_CTRL0_CLOCK_NUM_S 8
|
||||
#define SPI_CTRL0_CLOCK_HIGH_M 0x0000000F
|
||||
#define SPI_CTRL0_CLOCK_HIGH_S 4
|
||||
#define SPI_CTRL0_CLOCK_LOW_M 0x0000000F
|
||||
#define SPI_CTRL0_CLOCK_LOW_S 0
|
||||
|
||||
/* Mask for the CLOCK_NUM/CLOCK_HIGH/CLOCK_LOW combined, in case one wants
|
||||
* to set them all as a single value.
|
||||
*/
|
||||
#define SPI_CTRL0_CLOCK_M 0x00000FFF
|
||||
#define SPI_CTRL0_CLOCK_S 0
|
||||
|
||||
/* Details for CTRL2 register */
|
||||
|
||||
#define SPI_CTRL2_CS_DELAY_NUM_M 0x0000000F
|
||||
#define SPI_CTRL2_CS_DELAY_NUM_S 28
|
||||
#define SPI_CTRL2_CS_DELAY_MODE_M 0x00000003
|
||||
#define SPI_CTRL2_CS_DELAY_MODE_S 26
|
||||
#define SPI_CTRL2_MOSI_DELAY_NUM_M 0x00000007
|
||||
#define SPI_CTRL2_MOSI_DELAY_NUM_S 23
|
||||
#define SPI_CTRL2_MOSI_DELAY_MODE_M 0x00000003
|
||||
#define SPI_CTRL2_MOSI_DELAY_MODE_S 21
|
||||
#define SPI_CTRL2_MISO_DELAY_NUM_M 0x00000007
|
||||
#define SPI_CTRL2_MISO_DELAY_NUM_S 18
|
||||
#define SPI_CTRL2_MISO_DELAY_MODE_M 0x00000003
|
||||
#define SPI_CTRL2_MISO_DELAY_MODE_S 16
|
||||
|
||||
/* Details for CLOCK register */
|
||||
|
||||
#define SPI_CLOCK_EQU_SYS_CLOCK BIT(31)
|
||||
#define SPI_CLOCK_DIV_PRE_M 0x00001FFF
|
||||
#define SPI_CLOCK_DIV_PRE_S 18
|
||||
#define SPI_CLOCK_COUNT_NUM_M 0x0000003F
|
||||
#define SPI_CLOCK_COUNT_NUM_S 12
|
||||
#define SPI_CLOCK_COUNT_HIGH_M 0x0000003F
|
||||
#define SPI_CLOCK_COUNT_HIGH_S 6
|
||||
#define SPI_CLOCK_COUNT_LOW_M 0x0000003F
|
||||
#define SPI_CLOCK_COUNT_LOW_S 0
|
||||
|
||||
/* Mask for the COUNT_NUM/COUNT_HIGH/COUNT_LOW combined, in case one wants
|
||||
* to set them all as a single value.
|
||||
*/
|
||||
#define SPI_CTRL0_COUNT_M 0x0003FFFF
|
||||
#define SPI_CTRL0_COUNT_S 0
|
||||
|
||||
/* Details for USER0 register */
|
||||
|
||||
#define SPI_USER0_COMMAND BIT(31)
|
||||
#define SPI_USER0_ADDR BIT(30)
|
||||
#define SPI_USER0_DUMMY BIT(29)
|
||||
#define SPI_USER0_MISO BIT(28)
|
||||
#define SPI_USER0_MOSI BIT(27)
|
||||
#define SPI_USER0_MOSI_HIGHPART BIT(25)
|
||||
#define SPI_USER0_MISO_HIGHPART BIT(24)
|
||||
#define SPI_USER0_SIO BIT(16)
|
||||
#define SPI_USER0_FWRITE_QIO BIT(15)
|
||||
#define SPI_USER0_FWRITE_DIO BIT(14)
|
||||
#define SPI_USER0_FWRITE_QUAD BIT(13)
|
||||
#define SPI_USER0_FWRITE_DUAL BIT(12)
|
||||
#define SPI_USER0_WR_BYTE_ORDER BIT(11)
|
||||
#define SPI_USER0_RD_BYTE_ORDER BIT(10)
|
||||
#define SPI_USER0_CLOCK_OUT_EDGE BIT(7)
|
||||
#define SPI_USER0_CLOCK_IN_EDGE BIT(6)
|
||||
#define SPI_USER0_CS_SETUP BIT(5)
|
||||
#define SPI_USER0_CS_HOLD BIT(4)
|
||||
#define SPI_USER0_FLASH_MODE BIT(2)
|
||||
|
||||
/* Details for USER1 register */
|
||||
|
||||
#define SPI_USER1_ADDR_BITLEN_M 0x0000003F
|
||||
#define SPI_USER1_ADDR_BITLEN_S 26
|
||||
#define SPI_USER1_MOSI_BITLEN_M 0x000001FF
|
||||
#define SPI_USER1_MOSI_BITLEN_S 17
|
||||
#define SPI_USER1_MISO_BITLEN_M 0x000001FF
|
||||
#define SPI_USER1_MISO_BITLEN_S 8
|
||||
#define SPI_USER1_DUMMY_CYCLELEN_M 0x000000FF
|
||||
#define SPI_USER1_DUMMY_CYCLELEN_S 0
|
||||
|
||||
/* Details for USER2 register */
|
||||
|
||||
#define SPI_USER2_COMMAND_BITLEN_M 0x0000000F
|
||||
#define SPI_USER2_COMMAND_BITLEN_S 28
|
||||
#define SPI_USER2_COMMAND_VALUE_M 0x0000FFFF
|
||||
#define SPI_USER2_COMMAND_VALUE_S 0
|
||||
|
||||
/* Details for PIN register */
|
||||
|
||||
#define SPI_PIN_CS2_DISABLE BIT(2)
|
||||
#define SPI_PIN_CS1_DISABLE BIT(1)
|
||||
#define SPI_PIN_CS0_DISABLE BIT(0)
|
||||
|
||||
/* Details for SLAVE0 register */
|
||||
|
||||
#define SPI_SLAVE0_SYNC_RESET BIT(31)
|
||||
#define SPI_SLAVE0_MODE BIT(30)
|
||||
#define SPI_SLAVE0_WR_RD_BUF_EN BIT(29)
|
||||
#define SPI_SLAVE0_WR_RD_STA_EN BIT(28)
|
||||
#define SPI_SLAVE0_CMD_DEFINE BIT(27)
|
||||
#define SPI_SLAVE0_TRANS_COUNT_M 0x0000000F
|
||||
#define SPI_SLAVE0_TRANS_COUNT_S 23
|
||||
#define SPI_SLAVE0_TRANS_DONE_EN BIT(9)
|
||||
#define SPI_SLAVE0_WR_STA_DONE_EN BIT(8)
|
||||
#define SPI_SLAVE0_RD_STA_DONE_EN BIT(7)
|
||||
#define SPI_SLAVE0_WR_BUF_DONE_EN BIT(6)
|
||||
#define SPI_SLAVE0_RD_BUF_DONE_EN BIT(5)
|
||||
#define SPI_SLAVE0_INT_EN_M 0x0000001f
|
||||
#define SPI_SLAVE0_INT_EN_S 5
|
||||
#define SPI_SLAVE0_TRANS_DONE BIT(4)
|
||||
#define SPI_SLAVE0_WR_STA_DONE BIT(3)
|
||||
#define SPI_SLAVE0_RD_STA_DONE BIT(2)
|
||||
#define SPI_SLAVE0_WR_BUF_DONE BIT(1)
|
||||
#define SPI_SLAVE0_RD_BUF_DONE BIT(0)
|
||||
|
||||
/* Details for SLAVE1 register */
|
||||
|
||||
#define SPI_SLAVE1_STATUS_BITLEN_M 0x0000001F
|
||||
#define SPI_SLAVE1_STATUS_BITLEN_S 27
|
||||
#define SPI_SLAVE1_BUF_BITLEN_M 0x000001FF
|
||||
#define SPI_SLAVE1_BUF_BITLEN_S 16
|
||||
#define SPI_SLAVE1_RD_ADDR_BITLEN_M 0x0000003F
|
||||
#define SPI_SLAVE1_RD_ADDR_BITLEN_S 10
|
||||
#define SPI_SLAVE1_WR_ADDR_BITLEN_M 0x0000003F
|
||||
#define SPI_SLAVE1_WR_ADDR_BITLEN_S 4
|
||||
#define SPI_SLAVE1_WRSTA_DUMMY_ENABLE BIT(3)
|
||||
#define SPI_SLAVE1_RDSTA_DUMMY_ENABLE BIT(2)
|
||||
#define SPI_SLAVE1_WRBUF_DUMMY_ENABLE BIT(1)
|
||||
#define SPI_SLAVE1_RDBUF_DUMMY_ENABLE BIT(0)
|
||||
|
||||
/* Details for SLAVE2 register */
|
||||
|
||||
#define SPI_SLAVE2_WRBUF_DUMMY_CYCLELEN_M 0x000000FF
|
||||
#define SPI_SLAVE2_WRBUF_DUMMY_CYCLELEN_S 24
|
||||
#define SPI_SLAVE2_RDBUF_DUMMY_CYCLELEN_M 0x000000FF
|
||||
#define SPI_SLAVE2_RDBUF_DUMMY_CYCLELEN_S 16
|
||||
#define SPI_SLAVE2_WRSTR_DUMMY_CYCLELEN_M 0x000000FF
|
||||
#define SPI_SLAVE2_WRSTR_DUMMY_CYCLELEN_S 8
|
||||
#define SPI_SLAVE2_RDSTR_DUMMY_CYCLELEN_M 0x000000FF
|
||||
#define SPI_SLAVE2_RDSTR_DUMMY_CYCLELEN_S 0
|
||||
|
||||
/* Details for SLAVE3 register */
|
||||
|
||||
#define SPI_SLAVE3_WRSTA_CMD_VALUE_M 0x000000FF
|
||||
#define SPI_SLAVE3_WRSTA_CMD_VALUE_S 24
|
||||
#define SPI_SLAVE3_RDSTA_CMD_VALUE_M 0x000000FF
|
||||
#define SPI_SLAVE3_RDSTA_CMD_VALUE_S 16
|
||||
#define SPI_SLAVE3_WRBUF_CMD_VALUE_M 0x000000FF
|
||||
#define SPI_SLAVE3_WRBUF_CMD_VALUE_S 8
|
||||
#define SPI_SLAVE3_RDBUF_CMD_VALUE_M 0x000000FF
|
||||
#define SPI_SLAVE3_RDBUF_CMD_VALUE_S 0
|
||||
|
||||
/* Details for EXT3 register */
|
||||
|
||||
#define SPI_EXT3_INT_HOLD_ENABLE_M 0x00000003
|
||||
#define SPI_EXT3_INT_HOLD_ENABLE_S 0
|
||||
|
||||
#endif /* _SPI_REGS_H */
|
|
@ -11,12 +11,12 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <xtensa_interrupts.h>
|
||||
#include "esp/registers.h"
|
||||
#include "esp/timer_regs.h"
|
||||
#include "esp/cpu.h"
|
||||
|
||||
typedef enum {
|
||||
TIMER_FRC1,
|
||||
TIMER_FRC2,
|
||||
FRC1 = 0,
|
||||
FRC2 = 1,
|
||||
} timer_frc_t;
|
||||
|
||||
/* Return current count value for timer. */
|
||||
|
@ -31,14 +31,8 @@ INLINED void timer_set_load(const timer_frc_t frc, const uint32_t load);
|
|||
/* Returns maximum load value for timer. */
|
||||
INLINED uint32_t timer_max_load(const timer_frc_t frc);
|
||||
|
||||
typedef enum {
|
||||
TIMER_DIV1,
|
||||
TIMER_DIV16,
|
||||
TIMER_DIV256,
|
||||
} timer_div_t;
|
||||
|
||||
/* Set the timer divider value */
|
||||
INLINED void timer_set_divider(const timer_frc_t frc, const timer_div_t div);
|
||||
INLINED void timer_set_divider(const timer_frc_t frc, const timer_clkdiv_t div);
|
||||
|
||||
/* Enable or disable timer interrupts
|
||||
|
||||
|
@ -62,7 +56,7 @@ INLINED bool timer_get_reload(const timer_frc_t frc);
|
|||
/* Return a suitable timer divider for the specified frequency,
|
||||
or -1 if none is found.
|
||||
*/
|
||||
INLINED timer_div_t timer_freq_to_div(uint32_t freq);
|
||||
INLINED timer_clkdiv_t timer_freq_to_div(uint32_t freq);
|
||||
|
||||
/* Return the number of timer counts to achieve the specified
|
||||
* frequency with the specified divisor.
|
||||
|
@ -73,12 +67,12 @@ INLINED timer_div_t timer_freq_to_div(uint32_t freq);
|
|||
*
|
||||
* Compile-time evaluates if all arguments are available at compile time.
|
||||
*/
|
||||
INLINED uint32_t timer_freq_to_count(const timer_frc_t frc, uint32_t freq, const timer_div_t div);
|
||||
INLINED uint32_t timer_freq_to_count(const timer_frc_t frc, uint32_t freq, const timer_clkdiv_t div);
|
||||
|
||||
/* Return a suitable timer divider for the specified duration in
|
||||
microseconds or -1 if none is found.
|
||||
*/
|
||||
INLINED timer_div_t timer_time_to_div(uint32_t us);
|
||||
INLINED timer_clkdiv_t timer_time_to_div(uint32_t us);
|
||||
|
||||
/* Return the number of timer counts for the specified timer duration
|
||||
* in microseconds, when using the specified divisor.
|
||||
|
@ -89,7 +83,7 @@ INLINED timer_div_t timer_time_to_div(uint32_t us);
|
|||
*
|
||||
* Compile-time evaluates if all arguments are available at compile time.
|
||||
*/
|
||||
INLINED uint32_t timer_time_to_count(const timer_frc_t frc, uint32_t us, const timer_div_t div);
|
||||
INLINED uint32_t timer_time_to_count(const timer_frc_t frc, uint32_t us, const timer_clkdiv_t div);
|
||||
|
||||
/* Set a target timer interrupt frequency in Hz.
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "esp/dport_regs.h"
|
||||
|
||||
/* Timer divisor index to max frequency */
|
||||
#define _FREQ_DIV1 (80*1000*1000)
|
||||
|
@ -20,104 +21,90 @@ const static uint32_t IROM _TIMER_FREQS[] = { _FREQ_DIV1, _FREQ_DIV16, _FREQ_DIV
|
|||
/* Timer divisor index to divisor value */
|
||||
const static uint32_t IROM _TIMER_DIV_VAL[] = { 1, 16, 256 };
|
||||
|
||||
/* Timer divisor to mask value */
|
||||
const static uint32_t IROM _TIMER_DIV_REG[] = { TIMER_CTRL_DIV_1, TIMER_CTRL_DIV_16, TIMER_CTRL_DIV_256 };
|
||||
|
||||
INLINED esp_reg_t _timer_ctrl_reg(const timer_frc_t frc)
|
||||
{
|
||||
return (frc == TIMER_FRC1) ? &TIMER_FRC1_CTRL_REG : &TIMER_FRC2_CTRL_REG;
|
||||
}
|
||||
|
||||
INLINED uint32_t timer_get_count(const timer_frc_t frc)
|
||||
{
|
||||
return (frc == TIMER_FRC1) ? TIMER_FRC1_COUNT_REG : TIMER_FRC2_COUNT_REG;
|
||||
return TIMER(frc).COUNT;
|
||||
}
|
||||
|
||||
INLINED uint32_t timer_get_load(const timer_frc_t frc)
|
||||
{
|
||||
return (frc == TIMER_FRC1) ? TIMER_FRC1_LOAD_REG : TIMER_FRC2_LOAD_REG;
|
||||
return TIMER(frc).LOAD;
|
||||
}
|
||||
|
||||
INLINED void timer_set_load(const timer_frc_t frc, const uint32_t load)
|
||||
{
|
||||
if(frc == TIMER_FRC1)
|
||||
TIMER_FRC1_LOAD_REG = load;
|
||||
else
|
||||
TIMER_FRC2_LOAD_REG = load;
|
||||
TIMER(frc).LOAD = load;
|
||||
}
|
||||
|
||||
INLINED uint32_t timer_max_load(const timer_frc_t frc)
|
||||
{
|
||||
return (frc == TIMER_FRC1) ? TIMER_FRC1_MAX_LOAD : UINT32_MAX;
|
||||
return (frc == FRC1) ? TIMER_FRC1_MAX_LOAD : UINT32_MAX;
|
||||
}
|
||||
|
||||
INLINED void timer_set_divider(const timer_frc_t frc, const timer_div_t div)
|
||||
INLINED void timer_set_divider(const timer_frc_t frc, const timer_clkdiv_t div)
|
||||
{
|
||||
if(div < TIMER_DIV1 || div > TIMER_DIV256)
|
||||
if(div < TIMER_CLKDIV_1 || div > TIMER_CLKDIV_256)
|
||||
return;
|
||||
esp_reg_t ctrl = _timer_ctrl_reg(frc);
|
||||
*ctrl = (*ctrl & ~TIMER_CTRL_DIV_MASK) | (_TIMER_DIV_REG[div] & TIMER_CTRL_DIV_MASK);
|
||||
TIMER(frc).CTRL = SET_FIELD(TIMER(frc).CTRL, TIMER_CTRL_CLKDIV, div);
|
||||
}
|
||||
|
||||
INLINED void timer_set_interrupts(const timer_frc_t frc, bool enable)
|
||||
{
|
||||
const uint32_t dp_bit = (frc == TIMER_FRC1) ? INT_ENABLE_FRC1 : INT_ENABLE_FRC2;
|
||||
const uint32_t int_mask = BIT((frc == TIMER_FRC1) ? INUM_TIMER_FRC1 : INUM_TIMER_FRC2);
|
||||
const uint32_t dp_bit = (frc == FRC1) ? DPORT_INT_ENABLE_FRC1 : DPORT_INT_ENABLE_FRC2;
|
||||
const uint32_t int_mask = BIT((frc == FRC1) ? INUM_TIMER_FRC1 : INUM_TIMER_FRC2);
|
||||
if(enable) {
|
||||
DP_INT_ENABLE_REG |= dp_bit;
|
||||
DPORT.INT_ENABLE |= dp_bit;
|
||||
_xt_isr_unmask(int_mask);
|
||||
} else {
|
||||
DP_INT_ENABLE_REG &= ~dp_bit;
|
||||
DPORT.INT_ENABLE &= ~dp_bit;
|
||||
_xt_isr_mask(int_mask);
|
||||
}
|
||||
}
|
||||
|
||||
INLINED void timer_set_run(const timer_frc_t frc, const bool run)
|
||||
{
|
||||
esp_reg_t ctrl = _timer_ctrl_reg(frc);
|
||||
if (run)
|
||||
*ctrl |= TIMER_CTRL_RUN;
|
||||
TIMER(frc).CTRL |= TIMER_CTRL_RUN;
|
||||
else
|
||||
*ctrl &= ~TIMER_CTRL_RUN;
|
||||
TIMER(frc).CTRL &= ~TIMER_CTRL_RUN;
|
||||
}
|
||||
|
||||
INLINED bool timer_get_run(const timer_frc_t frc)
|
||||
{
|
||||
return *_timer_ctrl_reg(frc) & TIMER_CTRL_RUN;
|
||||
return TIMER(frc).CTRL & TIMER_CTRL_RUN;
|
||||
}
|
||||
|
||||
INLINED void timer_set_reload(const timer_frc_t frc, const bool reload)
|
||||
{
|
||||
esp_reg_t ctrl = _timer_ctrl_reg(frc);
|
||||
if (reload)
|
||||
*ctrl |= TIMER_CTRL_RELOAD;
|
||||
TIMER(frc).CTRL |= TIMER_CTRL_RELOAD;
|
||||
else
|
||||
*ctrl &= ~TIMER_CTRL_RELOAD;
|
||||
TIMER(frc).CTRL &= ~TIMER_CTRL_RELOAD;
|
||||
}
|
||||
|
||||
INLINED bool timer_get_reload(const timer_frc_t frc)
|
||||
{
|
||||
return *_timer_ctrl_reg(frc) & TIMER_CTRL_RELOAD;
|
||||
return TIMER(frc).CTRL & TIMER_CTRL_RELOAD;
|
||||
}
|
||||
|
||||
INLINED timer_div_t timer_freq_to_div(uint32_t freq)
|
||||
INLINED timer_clkdiv_t timer_freq_to_div(uint32_t freq)
|
||||
{
|
||||
/*
|
||||
try to maintain resolution without risking overflows.
|
||||
these values are a bit arbitrary at the moment! */
|
||||
if(freq > 100*1000)
|
||||
return TIMER_DIV1;
|
||||
return TIMER_CLKDIV_1;
|
||||
else if(freq > 100)
|
||||
return TIMER_DIV16;
|
||||
return TIMER_CLKDIV_16;
|
||||
else
|
||||
return TIMER_DIV256;
|
||||
return TIMER_CLKDIV_256;
|
||||
}
|
||||
|
||||
/* timer_timer_to_count implementation - inline if all args are constant, call normally otherwise */
|
||||
|
||||
INLINED uint32_t _timer_freq_to_count_impl(const timer_frc_t frc, const uint32_t freq, const timer_div_t div)
|
||||
INLINED uint32_t _timer_freq_to_count_impl(const timer_frc_t frc, const uint32_t freq, const timer_clkdiv_t div)
|
||||
{
|
||||
if(div < TIMER_DIV1 || div > TIMER_DIV256)
|
||||
if(div < TIMER_CLKDIV_1 || div > TIMER_CLKDIV_256)
|
||||
return 0; /* invalid divider */
|
||||
|
||||
if(freq > _TIMER_FREQS[div])
|
||||
|
@ -127,9 +114,9 @@ INLINED uint32_t _timer_freq_to_count_impl(const timer_frc_t frc, const uint32_t
|
|||
return counts;
|
||||
}
|
||||
|
||||
uint32_t _timer_freq_to_count_runtime(const timer_frc_t frc, const uint32_t freq, const timer_div_t div);
|
||||
uint32_t _timer_freq_to_count_runtime(const timer_frc_t frc, const uint32_t freq, const timer_clkdiv_t div);
|
||||
|
||||
INLINED uint32_t timer_freq_to_count(const timer_frc_t frc, const uint32_t freq, const timer_div_t div)
|
||||
INLINED uint32_t timer_freq_to_count(const timer_frc_t frc, const uint32_t freq, const timer_clkdiv_t div)
|
||||
{
|
||||
if(__builtin_constant_p(frc) && __builtin_constant_p(freq) && __builtin_constant_p(div))
|
||||
return _timer_freq_to_count_impl(frc, freq, div);
|
||||
|
@ -137,33 +124,33 @@ INLINED uint32_t timer_freq_to_count(const timer_frc_t frc, const uint32_t freq,
|
|||
return _timer_freq_to_count_runtime(frc, freq, div);
|
||||
}
|
||||
|
||||
INLINED timer_div_t timer_time_to_div(uint32_t us)
|
||||
INLINED timer_clkdiv_t timer_time_to_div(uint32_t us)
|
||||
{
|
||||
/*
|
||||
try to maintain resolution without risking overflows. Similar to
|
||||
timer_freq_to_div, these values are a bit arbitrary at the
|
||||
moment! */
|
||||
if(us < 1000)
|
||||
return TIMER_DIV1;
|
||||
return TIMER_CLKDIV_1;
|
||||
else if(us < 10*1000)
|
||||
return TIMER_DIV16;
|
||||
return TIMER_CLKDIV_16;
|
||||
else
|
||||
return TIMER_DIV256;
|
||||
return TIMER_CLKDIV_256;
|
||||
}
|
||||
|
||||
/* timer_timer_to_count implementation - inline if all args are constant, call normally otherwise */
|
||||
|
||||
INLINED uint32_t _timer_time_to_count_impl(const timer_frc_t frc, uint32_t us, const timer_div_t div)
|
||||
INLINED uint32_t _timer_time_to_count_impl(const timer_frc_t frc, uint32_t us, const timer_clkdiv_t div)
|
||||
{
|
||||
if(div < TIMER_DIV1 || div > TIMER_DIV256)
|
||||
if(div < TIMER_CLKDIV_1 || div > TIMER_CLKDIV_256)
|
||||
return 0; /* invalid divider */
|
||||
|
||||
const uint32_t TIMER_MAX = timer_max_load(frc);
|
||||
|
||||
if(div != TIMER_DIV256) /* timer tick in MHz */
|
||||
if(div != TIMER_CLKDIV_256) /* timer tick in MHz */
|
||||
{
|
||||
/* timer is either 80MHz or 5MHz, so either 80 or 5 MHz counts per us */
|
||||
const uint32_t counts_per_us = ((div == TIMER_DIV1) ? _FREQ_DIV1 : _FREQ_DIV16)/1000/1000;
|
||||
const uint32_t counts_per_us = ((div == TIMER_CLKDIV_1) ? _FREQ_DIV1 : _FREQ_DIV16)/1000/1000;
|
||||
if(us > TIMER_MAX/counts_per_us)
|
||||
return 0; /* Multiplying us by mhz_per_count will overflow TIMER_MAX */
|
||||
return us*counts_per_us;
|
||||
|
@ -186,9 +173,9 @@ INLINED uint32_t _timer_time_to_count_impl(const timer_frc_t frc, uint32_t us, c
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t _timer_time_to_count_runtime(const timer_frc_t frc, uint32_t us, const timer_div_t div);
|
||||
uint32_t _timer_time_to_count_runtime(const timer_frc_t frc, uint32_t us, const timer_clkdiv_t div);
|
||||
|
||||
INLINED uint32_t timer_time_to_count(const timer_frc_t frc, uint32_t us, const timer_div_t div)
|
||||
INLINED uint32_t timer_time_to_count(const timer_frc_t frc, uint32_t us, const timer_clkdiv_t div)
|
||||
{
|
||||
if(__builtin_constant_p(frc) && __builtin_constant_p(us) && __builtin_constant_p(div))
|
||||
return _timer_time_to_count_impl(frc, us, div);
|
||||
|
@ -201,7 +188,7 @@ INLINED uint32_t timer_time_to_count(const timer_frc_t frc, uint32_t us, const t
|
|||
INLINED bool _timer_set_frequency_impl(const timer_frc_t frc, uint32_t freq)
|
||||
{
|
||||
uint32_t counts = 0;
|
||||
timer_div_t div = timer_freq_to_div(freq);
|
||||
timer_clkdiv_t div = timer_freq_to_div(freq);
|
||||
|
||||
counts = timer_freq_to_count(frc, freq, div);
|
||||
if(counts == 0)
|
||||
|
@ -211,7 +198,7 @@ INLINED bool _timer_set_frequency_impl(const timer_frc_t frc, uint32_t freq)
|
|||
}
|
||||
|
||||
timer_set_divider(frc, div);
|
||||
if(frc == TIMER_FRC1)
|
||||
if(frc == FRC1)
|
||||
{
|
||||
timer_set_load(frc, counts);
|
||||
timer_set_reload(frc, true);
|
||||
|
@ -219,7 +206,7 @@ INLINED bool _timer_set_frequency_impl(const timer_frc_t frc, uint32_t freq)
|
|||
else /* FRC2 */
|
||||
{
|
||||
/* assume that if this overflows it'll wrap, so we'll get desired behaviour */
|
||||
TIMER_FRC2_MATCH_REG = counts + TIMER_FRC2_COUNT_REG;
|
||||
TIMER(1).ALARM = counts + TIMER(1).COUNT;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -239,20 +226,20 @@ INLINED bool timer_set_frequency(const timer_frc_t frc, uint32_t freq)
|
|||
INLINED bool _timer_set_timeout_impl(const timer_frc_t frc, uint32_t us)
|
||||
{
|
||||
uint32_t counts = 0;
|
||||
timer_div_t div = timer_time_to_div(us);
|
||||
timer_clkdiv_t div = timer_time_to_div(us);
|
||||
|
||||
counts = timer_time_to_count(frc, us, div);
|
||||
if(counts == 0)
|
||||
return false; /* can't set frequency */
|
||||
|
||||
timer_set_divider(frc, div);
|
||||
if(frc == TIMER_FRC1)
|
||||
if(frc == FRC1)
|
||||
{
|
||||
timer_set_load(frc, counts);
|
||||
}
|
||||
else /* FRC2 */
|
||||
{
|
||||
TIMER_FRC2_MATCH_REG = counts + TIMER_FRC2_COUNT_REG;
|
||||
TIMER(1).ALARM = counts + TIMER(1).COUNT;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
125
core/include/esp/timer_regs.h
Normal file
125
core/include/esp/timer_regs.h
Normal file
|
@ -0,0 +1,125 @@
|
|||
/* esp/timer_regs.h
|
||||
*
|
||||
* ESP8266 Timer register definitions
|
||||
*
|
||||
* Not compatible with ESP SDK register access code.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_TIMER_REGS_H
|
||||
#define _ESP_TIMER_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
#define TIMER_BASE 0x60000600
|
||||
#define TIMER(i) (*(struct TIMER_REGS *)(TIMER_BASE + (i)*0x20))
|
||||
#define TIMER_FRC1 TIMER(0)
|
||||
#define TIMER_FRC2 TIMER(1)
|
||||
|
||||
/* TIMER registers
|
||||
*
|
||||
* ESP8266 has two hardware timer counters, FRC1 and FRC2.
|
||||
*
|
||||
* FRC1 is a 24-bit countdown timer, triggers interrupt when reaches zero.
|
||||
* FRC2 is a 32-bit countup timer, can set a variable match value to trigger an interrupt.
|
||||
*
|
||||
* FreeRTOS tick timer appears to come from XTensa core tick timer0,
|
||||
* not either of these. FRC2 is used in the FreeRTOS SDK however. It
|
||||
* is set to free-run, interrupting periodically via updates to the
|
||||
* ALARM register. sdk_ets_timer_init configures FRC2 and assigns FRC2
|
||||
* interrupt handler at sdk_vApplicationTickHook+0x68
|
||||
*/
|
||||
|
||||
struct TIMER_REGS { // FRC1 FRC2
|
||||
uint32_t volatile LOAD; // 0x00 0x20
|
||||
uint32_t volatile COUNT; // 0x04 0x24
|
||||
uint32_t volatile CTRL; // 0x08 0x28
|
||||
uint32_t volatile STATUS; // 0x0c 0x2c
|
||||
uint32_t volatile ALARM; // 0x30
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct TIMER_REGS) == 0x14, "TIMER_REGS is the wrong size");
|
||||
|
||||
#define TIMER_FRC1_MAX_LOAD 0x7fffff
|
||||
|
||||
/* Details for LOAD registers */
|
||||
|
||||
/* Behavior for FRC1:
|
||||
*
|
||||
* When TIMER_CTRL_RELOAD is cleared in TIMER(0).CTRL, FRC1 will
|
||||
* reload to its max value once underflowed (unless the load
|
||||
* value is rewritten in the interrupt handler.)
|
||||
*
|
||||
* When TIMER_CTRL_RELOAD is set in TIMER(0).CTRL, FRC1 will reload
|
||||
* from the load register value once underflowed.
|
||||
*
|
||||
* Behavior for FRC2:
|
||||
*
|
||||
* If TIMER_CTRL_RELOAD is cleared in TIMER(1).CTRL, writing to
|
||||
* this register will update the FRC2 COUNT value.
|
||||
*
|
||||
* If TIMER_CTRL_RELOAD is set in TIMER(1).CTRL, the behaviour
|
||||
* appears to be the same except that writing 0 to the load register
|
||||
* both sets the COUNT register to 0 and disables the timer, even if
|
||||
* the TIMER_CTRL_RUN bit is set.
|
||||
*
|
||||
* Offsets 0x34, 0x38, 0x3c all seem to read back the LOAD_REG value
|
||||
* also (but have no known function.)
|
||||
*/
|
||||
|
||||
/* Details for CTRL registers */
|
||||
|
||||
/* Observed behaviour is like this:
|
||||
*
|
||||
* * When TIMER_CTRL_INT_HOLD is set, the interrupt status bit
|
||||
* TIMER_CTRL_INT_STATUS remains set when the timer interrupt
|
||||
* triggers, unless manually cleared by writing 0 to
|
||||
* TIMER(x).STATUS. While the interrupt status bit stays set
|
||||
* the timer will continue to run normally, but the interrupt
|
||||
* (INUM_TIMER_FRC1 or INUM_TIMER_FRC2) won't trigger again.
|
||||
*
|
||||
* * When TIMER_CTRL_INT_HOLD is cleared (default), there's no need to
|
||||
* manually write to TIMER(x).STATUS. The interrupt status bit
|
||||
* TIMER_CTRL_INT_STATUS automatically clears after the interrupt
|
||||
* triggers, and the interrupt handler will run again
|
||||
* automatically.
|
||||
*/
|
||||
|
||||
/* The values for TIMER_CTRL_CLKDIV control how many CPU clock cycles amount to
|
||||
* one timer clock cycle. For valid values, see the timer_clkdiv_t enum below.
|
||||
*/
|
||||
|
||||
/* TIMER_CTRL_INT_STATUS gets set when interrupt fires, and cleared on a write
|
||||
* to TIMER(x).STATUS (or cleared automatically if TIMER_CTRL_INT_HOLD is not
|
||||
* set).
|
||||
*/
|
||||
|
||||
#define TIMER_CTRL_INT_HOLD BIT(0)
|
||||
#define TIMER_CTRL_CLKDIV_M 0x00000003
|
||||
#define TIMER_CTRL_CLKDIV_S 2
|
||||
#define TIMER_CTRL_RELOAD BIT(6)
|
||||
#define TIMER_CTRL_RUN BIT(7)
|
||||
#define TIMER_CTRL_INT_STATUS BIT(8)
|
||||
|
||||
typedef enum {
|
||||
TIMER_CLKDIV_1 = 0,
|
||||
TIMER_CLKDIV_16 = 1,
|
||||
TIMER_CLKDIV_256 = 2,
|
||||
} timer_clkdiv_t;
|
||||
|
||||
/* Details for STATUS registers */
|
||||
|
||||
/* Reading this register always returns the value in
|
||||
* TIMER(x).LOAD
|
||||
*
|
||||
* Writing zero to this register clears the FRC1
|
||||
* interrupt status.
|
||||
*/
|
||||
|
||||
/* Details for FRC2.ALARM register */
|
||||
|
||||
/* Interrupt match value for FRC2. When COUNT == ALARM,
|
||||
the interrupt fires.
|
||||
*/
|
||||
|
||||
#endif /* _ESP_TIMER_REGS_H */
|
8
core/include/esp/types.h
Normal file
8
core/include/esp/types.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef _ESP_TYPES_H
|
||||
#define _ESP_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef volatile uint32_t *esp_reg_t;
|
||||
|
||||
#endif /* _ESP_TYPES_H */
|
186
core/include/esp/uart_regs.h
Normal file
186
core/include/esp/uart_regs.h
Normal file
|
@ -0,0 +1,186 @@
|
|||
/** esp/uart.h
|
||||
*
|
||||
* Configuration of UART registers.
|
||||
*
|
||||
* Part of esp-open-rtos
|
||||
* Copyright (C) 2015 Superhouse Automation Pty Ltd
|
||||
* BSD Licensed as described in the file LICENSE
|
||||
*/
|
||||
|
||||
#ifndef _UART_REGS_H
|
||||
#define _UART_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
/* Register definitions for the UART peripherals on the ESP8266.
|
||||
*
|
||||
* There are twp UART devices built into the ESP8266:
|
||||
* UART(0) is at 0x60000000
|
||||
* UART(1) is at 0x60000F00
|
||||
*
|
||||
* Each device is allocated a block of 64 32-bit registers (256 bytes of
|
||||
* address space) to communicate with application code.
|
||||
*/
|
||||
|
||||
#define UART_BASE 0x60000000
|
||||
#define UART(i) (*(struct UART_REGS *)(0x60000200 - (i)*0xf00))
|
||||
|
||||
#define UART0_BASE UART_BASE
|
||||
#define UART1_BASE (UART_BASE + 0xf00)
|
||||
|
||||
struct UART_REGS {
|
||||
uint32_t volatile FIFO; // 0x00
|
||||
uint32_t volatile INT_RAW; // 0x04
|
||||
uint32_t volatile INT_STATUS; // 0x08
|
||||
uint32_t volatile INT_ENABLE; // 0x0c
|
||||
uint32_t volatile INT_CLEAR; // 0x10
|
||||
uint32_t volatile CLOCK_DIVIDER; // 0x14
|
||||
uint32_t volatile AUTOBAUD; // 0x18
|
||||
uint32_t volatile STATUS; // 0x1c
|
||||
uint32_t volatile CONF0; // 0x20
|
||||
uint32_t volatile CONF1; // 0x24
|
||||
uint32_t volatile LOW_PULSE; // 0x28
|
||||
uint32_t volatile HIGH_PULSE; // 0x2c
|
||||
uint32_t volatile PULSE_COUNT; // 0x30
|
||||
uint32_t volatile _unused[17]; // 0x34 - 0x74
|
||||
uint32_t volatile DATE; // 0x78
|
||||
uint32_t volatile ID; // 0x7c
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct UART_REGS) == 0x80, "UART_REGS is the wrong size");
|
||||
|
||||
/* Details for FIFO register */
|
||||
|
||||
#define UART_FIFO_DATA_M 0x000000ff
|
||||
#define UART_FIFO_DATA_S 0
|
||||
|
||||
/* Details for INT_RAW register */
|
||||
|
||||
#define UART_INT_RAW_RXFIFO_TIMEOUT BIT(8)
|
||||
#define UART_INT_RAW_BREAK_DETECTED BIT(7)
|
||||
#define UART_INT_RAW_CTS_CHANGED BIT(6)
|
||||
#define UART_INT_RAW_DSR_CHANGED BIT(5)
|
||||
#define UART_INT_RAW_RXFIFO_OVERFLOW BIT(4)
|
||||
#define UART_INT_RAW_FRAMING_ERR BIT(3)
|
||||
#define UART_INT_RAW_PARITY_ERR BIT(2)
|
||||
#define UART_INT_RAW_TXFIFO_EMPTY BIT(1)
|
||||
#define UART_INT_RAW_RXFIFO_FULL BIT(0)
|
||||
|
||||
/* Details for INT_STATUS register */
|
||||
|
||||
#define UART_INT_STATUS_RXFIFO_TIMEOUT BIT(8)
|
||||
#define UART_INT_STATUS_BREAK_DETECTED BIT(7)
|
||||
#define UART_INT_STATUS_CTS_CHANGED BIT(6)
|
||||
#define UART_INT_STATUS_DSR_CHANGED BIT(5)
|
||||
#define UART_INT_STATUS_RXFIFO_OVERFLOW BIT(4)
|
||||
#define UART_INT_STATUS_FRAMING_ERR BIT(3)
|
||||
#define UART_INT_STATUS_PARITY_ERR BIT(2)
|
||||
#define UART_INT_STATUS_TXFIFO_EMPTY BIT(1)
|
||||
#define UART_INT_STATUS_RXFIFO_FULL BIT(0)
|
||||
|
||||
/* Details for INT_ENABLE register */
|
||||
|
||||
#define UART_INT_ENABLE_RXFIFO_TIMEOUT BIT(8)
|
||||
#define UART_INT_ENABLE_BREAK_DETECTED BIT(7)
|
||||
#define UART_INT_ENABLE_CTS_CHANGED BIT(6)
|
||||
#define UART_INT_ENABLE_DSR_CHANGED BIT(5)
|
||||
#define UART_INT_ENABLE_RXFIFO_OVERFLOW BIT(4)
|
||||
#define UART_INT_ENABLE_FRAMING_ERR BIT(3)
|
||||
#define UART_INT_ENABLE_PARITY_ERR BIT(2)
|
||||
#define UART_INT_ENABLE_TXFIFO_EMPTY BIT(1)
|
||||
#define UART_INT_ENABLE_RXFIFO_FULL BIT(0)
|
||||
|
||||
/* Details for INT_CLEAR register */
|
||||
|
||||
#define UART_INT_CLEAR_RXFIFO_TIMEOUT BIT(8)
|
||||
#define UART_INT_CLEAR_BREAK_DETECTED BIT(7)
|
||||
#define UART_INT_CLEAR_CTS_CHANGED BIT(6)
|
||||
#define UART_INT_CLEAR_DSR_CHANGED BIT(5)
|
||||
#define UART_INT_CLEAR_RXFIFO_OVERFLOW BIT(4)
|
||||
#define UART_INT_CLEAR_FRAMING_ERR BIT(3)
|
||||
#define UART_INT_CLEAR_PARITY_ERR BIT(2)
|
||||
#define UART_INT_CLEAR_TXFIFO_EMPTY BIT(1)
|
||||
#define UART_INT_CLEAR_RXFIFO_FULL BIT(0)
|
||||
|
||||
/* Details for CLOCK_DIVIDER register */
|
||||
|
||||
#define UART_CLOCK_DIVIDER_VALUE_M 0x000fffff
|
||||
#define UART_CLOCK_DIVIDER_VALUE_S 0
|
||||
|
||||
/* Details for AUTOBAUD register */
|
||||
|
||||
#define UART_AUTOBAUD_GLITCH_FILTER_M 0x000000FF
|
||||
#define UART_AUTOBAUD_GLITCH_FILTER_S 8
|
||||
#define UART_AUTOBAUD_ENABLE BIT(0)
|
||||
|
||||
/* Details for STATUS register */
|
||||
|
||||
#define UART_STATUS_TXD BIT(31)
|
||||
#define UART_STATUS_RTS BIT(30)
|
||||
#define UART_STATUS_DTR BIT(29)
|
||||
#define UART_STATUS_TXFIFO_COUNT_M 0x000000ff
|
||||
#define UART_STATUS_TXFIFO_COUNT_S 16
|
||||
#define UART_STATUS_RXD BIT(15)
|
||||
#define UART_STATUS_CTS BIT(14)
|
||||
#define UART_STATUS_DSR BIT(13)
|
||||
#define UART_STATUS_RXFIFO_COUNT_M 0x000000ff
|
||||
#define UART_STATUS_RXFIFO_COUNT_S 0
|
||||
|
||||
/* Details for CONF0 register */
|
||||
|
||||
#define UART_CONF0_DTR_INVERTED BIT(24)
|
||||
#define UART_CONF0_RTS_INVERTED BIT(23)
|
||||
#define UART_CONF0_TXD_INVERTED BIT(22)
|
||||
#define UART_CONF0_DSR_INVERTED BIT(21)
|
||||
#define UART_CONF0_CTS_INVERTED BIT(20)
|
||||
#define UART_CONF0_RXD_INVERTED BIT(19)
|
||||
#define UART_CONF0_TXFIFO_RESET BIT(18)
|
||||
#define UART_CONF0_RXFIFO_RESET BIT(17)
|
||||
#define UART_CONF0_IRDA_ENABLE BIT(16)
|
||||
#define UART_CONF0_TX_FLOW_ENABLE BIT(15)
|
||||
#define UART_CONF0_LOOPBACK BIT(14)
|
||||
#define UART_CONF0_IRDA_RX_INVERTED BIT(13)
|
||||
#define UART_CONF0_IRDA_TX_INVERTED BIT(12)
|
||||
#define UART_CONF0_IRDA_WCTL BIT(11)
|
||||
#define UART_CONF0_IRDA_TX_ENABLE BIT(10)
|
||||
#define UART_CONF0_IRDA_DUPLEX BIT(9)
|
||||
#define UART_CONF0_TXD_BREAK BIT(8)
|
||||
#define UART_CONF0_SW_DTR BIT(7)
|
||||
#define UART_CONF0_SW_RTS BIT(6)
|
||||
#define UART_CONF0_STOP_BITS_M 0x00000003
|
||||
#define UART_CONF0_STOP_BITS_S 4
|
||||
#define UART_CONF0_BYTE_LEN_M 0x00000003
|
||||
#define UART_CONF0_BYTE_LEN_S 2
|
||||
#define UART_CONF0_PARITY_ENABLE BIT(1)
|
||||
#define UART_CONF0_PARITY BIT(0) //FIXME: does this indicate odd or even?
|
||||
|
||||
/* Details for CONF1 register */
|
||||
|
||||
#define UART_CONF1_RX_TIMEOUT_ENABLE BIT(31)
|
||||
#define UART_CONF1_RX_TIMEOUT_THRESHOLD_M 0x0000007f
|
||||
#define UART_CONF1_RX_TIMEOUT_THRESHOLD_S 24
|
||||
#define UART_CONF1_RX_FLOWCTRL_ENABLE BIT(23)
|
||||
#define UART_CONF1_RX_FLOWCTRL_THRESHOLD_M 0x0000007f
|
||||
#define UART_CONF1_RX_FLOWCTRL_THRESHOLD_S 16
|
||||
#define UART_CONF1_TXFIFO_EMPTY_THRESHOLD_M 0x0000007f
|
||||
#define UART_CONF1_TXFIFO_EMPTY_THRESHOLD_S 8
|
||||
#define UART_CONF1_RXFIFO_FULL_THRESHOLD_M 0x0000007f
|
||||
#define UART_CONF1_RXFIFO_FULL_THRESHOLD_S 0
|
||||
|
||||
/* Details for LOW_PULSE register */
|
||||
|
||||
#define UART_LOW_PULSE_MIN_M 0x000fffff
|
||||
#define UART_LOW_PULSE_MIN_S 0
|
||||
|
||||
/* Details for HIGH_PULSE register */
|
||||
|
||||
#define UART_HIGH_PULSE_MIN_M 0x000fffff
|
||||
#define UART_HIGH_PULSE_MIN_S 0
|
||||
|
||||
/* Details for PULSE_COUNT register */
|
||||
|
||||
#define UART_PULSE_COUNT_VALUE_M 0x000003ff
|
||||
#define UART_PULSE_COUNT_VALUE_S 0
|
||||
|
||||
#endif /* _UART_REGS_H */
|
38
core/include/esp/wdt_regs.h
Normal file
38
core/include/esp/wdt_regs.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* esp/wdt_regs.h
|
||||
*
|
||||
* ESP8266 Watchdog Timer register definitions
|
||||
*
|
||||
* Not compatible with ESP SDK register access code.
|
||||
*/
|
||||
|
||||
#ifndef _ESP_WDT_REGS_H
|
||||
#define _ESP_WDT_REGS_H
|
||||
|
||||
#include "esp/types.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
#define WDT_BASE 0x60000900
|
||||
#define WDT (*(struct WDT_REGS *)(WDT_BASE))
|
||||
|
||||
/* WDT register(s)
|
||||
|
||||
Not fully understood yet. Writing 0 to CTRL disables WDT.
|
||||
|
||||
See ROM functions esp_wdt_xxx
|
||||
*/
|
||||
|
||||
struct WDT_REGS {
|
||||
uint32_t volatile CTRL; // 0x00
|
||||
uint32_t volatile REG1; // 0x04
|
||||
uint32_t volatile REG2; // 0x08
|
||||
uint32_t volatile _unused[2]; // 0x0c - 0x10
|
||||
uint32_t volatile FEED; // 0x14
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
_Static_assert(sizeof(struct WDT_REGS) == 0x18, "WDT_REGS is the wrong size");
|
||||
|
||||
/* Writing WDT_FEED_MAGIC to WDT.FEED register "feeds the dog" and holds off
|
||||
* triggering for another cycle (unconfirmed) */
|
||||
#define WDT_FEED_MAGIC 0x73
|
||||
|
||||
#endif /* _ESP_WDT_REGS_H */
|
|
@ -1,28 +1,31 @@
|
|||
EXAMPLES = $(shell find $(dir $(lastword $(MAKEFILE_LIST))) -mindepth 2 -name Makefile | sed s/Makefile//g)
|
||||
# Generate some dummy .dummybuild/.dummyrebuild target files
|
||||
EXAMPLES_BUILD = $(patsubst %,%.dummybuild,$(EXAMPLES))
|
||||
EXAMPLES_REBUILD = $(patsubst %,%.dummyrebuild,$(EXAMPLES))
|
||||
|
||||
warning:
|
||||
@echo "******************************************************"
|
||||
@echo "You may not want this Makefile, even though it's here!"
|
||||
@echo "******************************************************"
|
||||
@echo ""
|
||||
@echo "SUGGESTIONS:"
|
||||
@echo "Running 'make' in one of the subdirectories will build a single example."
|
||||
@echo "Running 'make help' in one of the subdirectories will print some help."
|
||||
@echo "Running 'make' in one of the subdirectories of examples/ will build a single example."
|
||||
@echo "Running 'make help' in one of the subdirectories of examples/ will print some help."
|
||||
@echo ""
|
||||
@echo "OTHERWISE:"
|
||||
@echo "This makefile is for building all of the examples at once, as a developer test."
|
||||
@echo "To use it, run 'make build-examples' or 'make rebuild-examples'"
|
||||
@echo
|
||||
|
||||
build-examples:
|
||||
set -e
|
||||
for example in `find . -mindepth 2 -name Makefile | sed s/Makefile//)`; do
|
||||
$(MAKE) -C $$example
|
||||
done
|
||||
build-examples: $(EXAMPLES_BUILD)
|
||||
|
||||
rebuild-examples:
|
||||
set -e
|
||||
for example in `find . -mindepth 2 -name Makefile | sed s/Makefile//)`; do
|
||||
$(MAKE) -C $$example rebuild
|
||||
done
|
||||
rebuild-examples: $(EXAMPLES_REBUILD)
|
||||
|
||||
%.dummybuild:
|
||||
make -C $(dir $@)
|
||||
|
||||
%.dummyrebuild:
|
||||
make -C $(dir $@) rebuild
|
||||
|
||||
.PHONY: warning rebuild-examples build-examples
|
||||
.NOTPARALLEL:
|
||||
|
|
|
@ -30,8 +30,8 @@ void blinkenTask(void *pvParameters)
|
|||
|
||||
/* This task uses all raw register operations to set the pins.
|
||||
|
||||
It's not fully parameterised, as the IOMUX_SET macro requires the pin number
|
||||
as part of the GPxx value.
|
||||
It's not fully parameterised, as the IOMUX_GPIO# macros involve a non-linear
|
||||
mapping from GPIO to IOMUX ports.
|
||||
|
||||
There is no significant performance benefit to this way over the
|
||||
blinkenTask version, so it's probably better to use the blinkenTask
|
||||
|
@ -41,12 +41,12 @@ void blinkenTask(void *pvParameters)
|
|||
*/
|
||||
void blinkenRegisterTask(void *pvParameters)
|
||||
{
|
||||
GPIO_DIR_SET = BIT(gpio);
|
||||
IOMUX_SET(GP14,GPIO,IOMUX_OE); /* change this line if you change 'gpio' */
|
||||
GPIO.ENABLE_OUT_SET = BIT(gpio);
|
||||
IOMUX_GPIO14 = IOMUX_GPIO14_FUNC_GPIO | IOMUX_PIN_OUTPUT_ENABLE; /* change this line if you change 'gpio' */
|
||||
while(1) {
|
||||
GPIO_OUT_SET = BIT(gpio);
|
||||
GPIO.OUT_SET = BIT(gpio);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
GPIO_OUT_CLEAR = BIT(gpio);
|
||||
GPIO.OUT_CLEAR = BIT(gpio);
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ void frc1_interrupt_handler(void)
|
|||
void frc2_interrupt_handler(void)
|
||||
{
|
||||
/* FRC2 needs the match register updated on each timer interrupt */
|
||||
timer_set_frequency(TIMER_FRC2, freq_frc2);
|
||||
timer_set_frequency(FRC2, freq_frc2);
|
||||
frc2_count++;
|
||||
gpio_toggle(gpio_frc2);
|
||||
}
|
||||
|
@ -41,24 +41,24 @@ void user_init(void)
|
|||
gpio_write(gpio_frc1, 1);
|
||||
|
||||
/* stop both timers and mask their interrupts as a precaution */
|
||||
timer_set_interrupts(TIMER_FRC1, false);
|
||||
timer_set_run(TIMER_FRC1, false);
|
||||
timer_set_interrupts(TIMER_FRC2, false);
|
||||
timer_set_run(TIMER_FRC2, false);
|
||||
timer_set_interrupts(FRC1, false);
|
||||
timer_set_run(FRC1, false);
|
||||
timer_set_interrupts(FRC2, false);
|
||||
timer_set_run(FRC2, false);
|
||||
|
||||
/* set up ISRs */
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_interrupt_handler);
|
||||
_xt_isr_attach(INUM_TIMER_FRC2, frc2_interrupt_handler);
|
||||
|
||||
/* configure timer frequencies */
|
||||
timer_set_frequency(TIMER_FRC1, freq_frc1);
|
||||
timer_set_frequency(TIMER_FRC2, freq_frc2);
|
||||
timer_set_frequency(FRC1, freq_frc1);
|
||||
timer_set_frequency(FRC2, freq_frc2);
|
||||
|
||||
/* unmask interrupts and start timers */
|
||||
timer_set_interrupts(TIMER_FRC1, true);
|
||||
timer_set_run(TIMER_FRC1, true);
|
||||
timer_set_interrupts(TIMER_FRC2, true);
|
||||
timer_set_run(TIMER_FRC2, true);
|
||||
timer_set_interrupts(FRC1, true);
|
||||
timer_set_run(FRC1, true);
|
||||
timer_set_interrupts(FRC2, true);
|
||||
timer_set_run(FRC2, true);
|
||||
|
||||
gpio_write(gpio_frc1, 0);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
/* pin config */
|
||||
const int gpio = 0; /* gpio 0 usually has "PROGRAM" button attached */
|
||||
const int active = 0; /* active == 0 for active low */
|
||||
const gpio_interrupt_t int_type = INT_FALLING;
|
||||
const gpio_inttype_t int_type = GPIO_INTTYPE_EDGE_NEG;
|
||||
#define GPIO_HANDLER gpio00_interrupt_handler
|
||||
|
||||
|
||||
|
|
|
@ -11,14 +11,15 @@
|
|||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "esp8266.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
#define DUMP_SZ 0x10 /* number of regs not size of buffer */
|
||||
|
||||
IRAM void dump_frc1_seq(void)
|
||||
{
|
||||
uint32_t f1_a = TIMER_FRC1_COUNT_REG;
|
||||
uint32_t f1_b = TIMER_FRC1_COUNT_REG;
|
||||
uint32_t f1_c = TIMER_FRC1_COUNT_REG;
|
||||
uint32_t f1_a = TIMER(0).COUNT;
|
||||
uint32_t f1_b = TIMER(0).COUNT;
|
||||
uint32_t f1_c = TIMER(0).COUNT;
|
||||
printf("FRC1 sequence 0x%08lx 0x%08lx 0x%08lx\r\n", f1_a, f1_b, f1_c);
|
||||
printf("FRC1 deltas %ld %ld \r\n", f1_b-f1_a, f1_c-f1_b);
|
||||
}
|
||||
|
@ -33,9 +34,9 @@ IRAM void dump_frc2_seq(void)
|
|||
* /16 = 0 or 1 (usually 1)
|
||||
*
|
||||
*/
|
||||
uint32_t f2_a = TIMER_FRC2_COUNT_REG;
|
||||
uint32_t f2_b = TIMER_FRC2_COUNT_REG;
|
||||
uint32_t f2_c = TIMER_FRC2_COUNT_REG;
|
||||
uint32_t f2_a = TIMER(1).COUNT;
|
||||
uint32_t f2_b = TIMER(1).COUNT;
|
||||
uint32_t f2_c = TIMER(1).COUNT;
|
||||
printf("FRC2 sequence 0x%08lx 0x%08lx 0x%08lx\r\n", f2_a, f2_b, f2_c);
|
||||
printf("FRC2 deltas %ld %ld \r\n", f2_b-f2_a, f2_c-f2_b);
|
||||
}
|
||||
|
@ -99,20 +100,20 @@ void timerRegTask(void *pvParameters)
|
|||
IRAM void frc1_handler(void)
|
||||
{
|
||||
frc1_handler_call_count++;
|
||||
frc1_last_count_val = TIMER_FRC1_COUNT_REG;
|
||||
//TIMER_FRC1_LOAD_REG = 0x300000;
|
||||
//TIMER_FRC1_CLEAR_INT = 0;
|
||||
frc1_last_count_val = TIMER(0).COUNT;
|
||||
//TIMER(0).LOAD = 0x300000;
|
||||
//TIMER(0).STATUS = 0;
|
||||
//TIMER_FRC1_MATCH_REG = frc1_last_count_val + 0x100000;
|
||||
}
|
||||
|
||||
void frc2_handler(void)
|
||||
{
|
||||
frc2_handler_call_count++;
|
||||
frc2_last_count_val = TIMER_FRC2_COUNT_REG;
|
||||
TIMER_FRC2_MATCH_REG = frc2_last_count_val + 0x100000;
|
||||
//TIMER_FRC2_LOAD_REG = 0;
|
||||
//TIMER_FRC2_LOAD_REG = 0x2000000;
|
||||
//TIMER_FRC2_CLEAR_INT_REG = 0;
|
||||
frc2_last_count_val = TIMER(1).COUNT;
|
||||
TIMER(1).ALARM = frc2_last_count_val + 0x100000;
|
||||
//TIMER(1).LOAD = 0;
|
||||
//TIMER(1).LOAD = 0x2000000;
|
||||
//TIMER(1).STATUS = 0;
|
||||
}
|
||||
|
||||
void user_init(void)
|
||||
|
@ -120,19 +121,19 @@ void user_init(void)
|
|||
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
|
||||
xTaskCreate(timerRegTask, (signed char *)"timerRegTask", 1024, NULL, 2, NULL);
|
||||
|
||||
TIMER_FRC1_CTRL_REG = TIMER_CTRL_DIV_256|TIMER_CTRL_INT_EDGE|TIMER_CTRL_RELOAD;
|
||||
TIMER_FRC1_LOAD_REG = 0x200000;
|
||||
TIMER(0).CTRL = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256) | TIMER_CTRL_RELOAD;
|
||||
TIMER(0).LOAD = 0x200000;
|
||||
|
||||
TIMER_FRC2_CTRL_REG = TIMER_CTRL_DIV_256|TIMER_CTRL_INT_EDGE;
|
||||
TIMER(1).LOAD = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256);
|
||||
|
||||
DP_INT_ENABLE_REG |= INT_ENABLE_FRC1|INT_ENABLE_FRC2;
|
||||
DPORT.INT_ENABLE |= DPORT_INT_ENABLE_TIMER0 | DPORT_INT_ENABLE_TIMER1;
|
||||
_xt_isr_attach(INUM_TIMER_FRC1, frc1_handler);
|
||||
_xt_isr_unmask(1<<INUM_TIMER_FRC1);
|
||||
_xt_isr_attach(INUM_TIMER_FRC2, frc2_handler);
|
||||
_xt_isr_unmask(1<<INUM_TIMER_FRC2);
|
||||
|
||||
TIMER_FRC1_CTRL_REG |= TIMER_CTRL_RUN;
|
||||
TIMER_FRC2_CTRL_REG |= TIMER_CTRL_RUN;
|
||||
TIMER(0).CTRL |= TIMER_CTRL_RUN;
|
||||
TIMER(1).CTRL |= TIMER_CTRL_RUN;
|
||||
|
||||
dump_timer_regs("timer regs during user_init");
|
||||
dump_timer_regs("#2 timer regs during user_init");
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
#ifndef __ESP_WIFI_H__
|
||||
#define __ESP_WIFI_H__
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <lwip/ip_addr.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
|
|
@ -39,9 +39,6 @@
|
|||
#define ESP_TIMEWAIT_THRESHOLD 10000
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
|
||||
// Uncomment this line, and set the debug options you want below, for IP stack debug output
|
||||
//#define LWIP_DEBUG
|
||||
|
||||
/*
|
||||
-----------------------------------------------
|
||||
---------- Platform specific locking ----------
|
||||
|
@ -390,6 +387,10 @@
|
|||
---------- Debugging options ----------
|
||||
---------------------------------------
|
||||
*/
|
||||
|
||||
// Uncomment this line, and set the individual debug options you want, for IP stack debug output
|
||||
//#define LWIP_DEBUG
|
||||
|
||||
/**
|
||||
* ETHARP_DEBUG: Enable debugging in etharp.c.
|
||||
*/
|
||||
|
@ -430,11 +431,22 @@
|
|||
*/
|
||||
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* UDP_DEBUG: Enable debugging in udp.c.
|
||||
*/
|
||||
#define UDP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* ICMP_DEBUG: Enable debugging in udp.c.
|
||||
*/
|
||||
#define ICMP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
/**
|
||||
* TCPIP_DEBUG: Enable debugging in tcpip.c.
|
||||
*/
|
||||
#define TCPIP_DEBUG LWIP_DBG_OFF
|
||||
|
||||
|
||||
/**
|
||||
* DHCP_DEBUG: Enable debugging in dhcp.c.
|
||||
*/
|
||||
|
|
28
lwip/include/netbuf_helpers.h
Normal file
28
lwip/include/netbuf_helpers.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/* Some netbuf helpers that should probably be rolled into a patch to lwip soon */
|
||||
#ifndef _NETBUF_HELPERS_H
|
||||
#define _NETBUF_HELPERS_H
|
||||
#include "lwip/netbuf.h"
|
||||
|
||||
/* Read a 16 bit wide unsigned integer, stored host order, from the netbuf */
|
||||
inline static u16_t netbuf_read_u16_h(struct netbuf *netbuf, u16_t offs)
|
||||
{
|
||||
u16_t raw;
|
||||
netbuf_copy_partial(netbuf, &raw, 2, offs);
|
||||
return raw;
|
||||
}
|
||||
|
||||
/* Read a 16 bit wide unsigned integer, stored network order, from the netbuf */
|
||||
inline static u16_t netbuf_read_u16_n(struct netbuf *netbuf, u16_t offs)
|
||||
{
|
||||
return ntohs(netbuf_read_u16_h(netbuf, offs));
|
||||
}
|
||||
|
||||
/* Read an 8 bit unsigned integer from the netbuf */
|
||||
inline static u8_t netbuf_read_u8(struct netbuf *netbuf, u16_t offs)
|
||||
{
|
||||
u8_t result;
|
||||
netbuf_copy_partial(netbuf, &result, 1, offs);
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue