1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-26 15:03:53 +01:00

Merge pull request #11108 from gschorcht/cpu/esp8266/esp-idf/pr

cpu/esp8266: complete reimplementation based on ESP8266 RTOS SDK
This commit is contained in:
Kevin "Tristate Tom" Weiss 2019-11-18 09:34:49 +01:00 committed by GitHub
commit be39169bd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
242 changed files with 31657 additions and 11420 deletions

View File

@ -173,7 +173,7 @@ static const gpio_t pwm1_channels[] = PWM1_GPIOS;
*/
/**
* @brief Static array with configuration for declared I2C devices
* @brief Static array with configuration for declared SPI devices
*/
static const spi_conf_t spi_config[] = {
#ifdef SPI0_CTRL
@ -220,7 +220,7 @@ static const spi_conf_t spi_config[] = {
#endif
/**
* @brief Static array with configuration for declared I2C devices
* @brief Static array with configuration for declared UART devices
*/
static const uart_conf_t uart_config[] = {
{
@ -249,13 +249,7 @@ static const uart_conf_t uart_config[] = {
*
* @note UART_NUMOF definition must not be changed.
*/
#if defined(UART1_TXD) && defined(UART1_RXD) && defined(UART2_TXD) && defined(UART2_RXD)
#define UART_NUMOF 3
#elif (defined(UART1_TXD) && defined(UART1_RXD)) || (defined(UART2_TXD) && defined(UART2_RXD))
#define UART_NUMOF 2
#else
#define UART_NUMOF 1
#endif
#define UART_NUMOF ARRAY_SIZE(uart_config)
/** @} */
#ifdef __cplusplus

View File

@ -10,3 +10,4 @@ FEATURES_PROVIDED += periph_i2c
FEATURES_PROVIDED += periph_pwm
FEATURES_PROVIDED += periph_spi
FEATURES_PROVIDED += periph_uart
FEATURES_PROVIDED += periph_uart_modecfg

View File

@ -4,5 +4,5 @@ PORT_DARWIN ?= $(firstword $(sort $(wildcard /dev/tty.SLAB_USBtoUART*)))
include $(RIOTMAKE)/tools/serial.inc.mk
# reset tool configuration
RESET ?= esptool.py
RESET_FLAGS ?= --port $(PROG_DEV) --before default_reset run
RESET ?= $(RIOTTOOLS)/esptool/espreset.py
RESET_FLAGS ?= --port $(PROG_DEV)

View File

@ -16,9 +16,12 @@
* @author Gunar Schorcht <gunar@schorcht.net>
*/
#include "board_common.h"
#include "board.h"
#include "esp_common.h"
#include "log.h"
#include "periph/gpio.h"
#include "esp_libc.h"
#include "rom/ets_sys.h"
#ifdef __cplusplus
extern "C" {
@ -40,35 +43,69 @@ void board_init(void)
#endif
}
extern void adc_print_config(void);
extern void dac_print_config(void);
extern void pwm_print_config(void);
extern void i2c_print_config(void);
extern void spi_print_config(void);
extern void uart_print_config(void);
extern void timer_print_config(void);
extern void can_print_config(void);
void board_print_config (void)
{
LOG_INFO("\nBoard configuration:\n");
ets_printf("\nBoard configuration:\n");
#if MODULE_PERIPH_ADC
adc_print_config();
#endif
#if MODULE_PERIPH_DAC
dac_print_config();
#endif
#if MODULE_PERIPH_PWM
pwm_print_config();
#endif
#if MODULE_PERIPH_I2C
i2c_print_config();
#endif
#if MODULE_PERIPH_SPI
spi_print_config();
#endif
#if MODULE_PERIPH_UART
uart_print_config();
#endif
#if MODULE_PERIPH_TIMER
timer_print_config();
#endif
#ifdef MODULE_ESP_CAN
can_print_config();
#endif
LOG_INFO("\tLED: pins=[ ");
ets_printf("\tLED\t\tpins=[ ");
#ifdef LED0_PIN
LOG_INFO("%d ", LED0_PIN);
ets_printf("%d ", LED0_PIN);
#endif
#ifdef LED1_PIN
LOG_INFO("%d ", LED1_PIN);
ets_printf("%d ", LED1_PIN);
#endif
#ifdef LED2_PIN
LOG_INFO("%d ", LED2_PIN);
ets_printf("%d ", LED2_PIN);
#endif
LOG_INFO("]\n");
ets_printf("]\n");
LOG_INFO("\n\n");
ets_printf("\tBUTTON\t\tpins=[ ");
#ifdef BUTTON0_PIN
ets_printf("%d ", BUTTON0_PIN);
#endif
#ifdef BUTTON2_PIN
ets_printf("%d ", BUTTON1_PIN);
#endif
#ifdef BUTTON3_PIN
ets_printf("%d ", BUTTON2_PIN);
#endif
ets_printf("]\n");
ets_printf("\n");
}
#ifdef __cplusplus

View File

@ -17,6 +17,9 @@
* @{
*/
/* not required when compiling ESP vendor code parts */
#ifndef ESP_PLATFORM
#include <stdint.h>
#include "cpu.h"
@ -124,7 +127,7 @@ extern mtd_dev_t *mtd0;
* initializations are done during the CPU initialization that is called from
* boot loader.
*/
extern void board_init(void);
void board_init (void);
/**
* @brief Print the board configuration in a human readable format
@ -140,4 +143,5 @@ void board_print_config (void);
/** @} */
#endif /* ESP_PLATFORM */
#endif /* BOARD_COMMON_H */

View File

@ -53,13 +53,13 @@ extern "C" {
#define ENC28J60_PARAM_SPI SPI_DEV(0) /**< SPI_DEV(0) is used (fixed) */
#ifndef ENC28J60_PARAM_CS
#define ENC28J60_PARAM_CS GPIO4 /**< ENC28J60 CS signal (can be overriden) */
#define ENC28J60_PARAM_CS GPIO4 /**< ENC28J60 CS signal (can be overridden) */
#endif
#ifndef ENC28J60_PARAM_INT
#define ENC28J60_PARAM_INT GPIO9 /**< ENC28J60 INT signal (can be overriden) */
#define ENC28J60_PARAM_INT GPIO9 /**< ENC28J60 INT signal (can be overridden) */
#endif
#ifndef ENC28J60_PARAM_RESET
#define ENC28J60_PARAM_RESET GPIO10 /**< ENC28J60 RESET signal (can be overriden) */
#define ENC28J60_PARAM_RESET GPIO10 /**< ENC28J60 RESET signal (can be overridden) */
#endif
/** @} */
#endif /* defined(MODULE_ENC28J60) || defined(DOXYGEN) */
@ -82,16 +82,16 @@ extern "C" {
#define MRF24J40_PARAM_SPI SPI_DEV(0) /**< SPI_DEV(0) is used (fixed) */
#ifndef MRF24J40_PARAM_SPI_CLK
#define MRF24J40_PARAM_SPI_CLK SPI_CLK_1MHZ /**< SPI bus speed used (can be overriden) */
#define MRF24J40_PARAM_SPI_CLK SPI_CLK_1MHZ /**< SPI bus speed used (can be overridden) */
#endif
#ifndef MRF24J40_PARAM_CS
#define MRF24J40_PARAM_CS GPIO16 /**< MRF24J40 CS signal (can be overriden) */
#define MRF24J40_PARAM_CS GPIO16 /**< MRF24J40 CS signal (can be overridden) */
#endif
#ifndef MRF24J40_PARAM_INT
#define MRF24J40_PARAM_INT GPIO0 /**< MRF24J40 INT signal (can be overriden) */
#define MRF24J40_PARAM_INT GPIO0 /**< MRF24J40 INT signal (can be overridden) */
#endif
#ifndef MRF24J40_PARAM_RESET
#define MRF24J40_PARAM_RESET GPIO2 /**< MRF24J40 RESET signal (can be overriden) */
#define MRF24J40_PARAM_RESET GPIO2 /**< MRF24J40 RESET signal (can be overridden) */
#endif
/** @} */
#endif /* defined(MODULE_MRF24J40) || defined(DOXYGEN) */
@ -109,14 +109,14 @@ extern "C" {
* If not defined, the default CS signal of SPI_DEV(0) is used.
* @{
*/
#define SDCARD_SPI_PARAM_SPI SPI_DEV(0) /**< SPI_DEV(0) is used (fixed) */
#define SDCARD_SPI_PARAM_CLK SPI0_SCK_GPIO /**< SPI_DEV(0) SCK is used (fixed) */
#define SDCARD_SPI_PARAM_MOSI SPI0_MOSI_GPIO /**< SPI_DEV(0) MOSI is used (fixed) */
#define SDCARD_SPI_PARAM_MISO SPI0_MISO_GPIO /**< SPI_DEV(0) MISO is used (fixed) */
#define SDCARD_SPI_PARAM_POWER GPIO_UNDEF /**< power control is not used (fixed) */
#define SDCARD_SPI_PARAM_SPI SPI_DEV(0) /**< SPI_DEV(0) is used (fixed) */
#define SDCARD_SPI_PARAM_CLK SPI0_SCK /**< SPI_DEV(0) SCK is used (fixed) */
#define SDCARD_SPI_PARAM_MOSI SPI0_MOSI /**< SPI_DEV(0) MOSI is used (fixed) */
#define SDCARD_SPI_PARAM_MISO SPI0_MISO /**< SPI_DEV(0) MISO is used (fixed) */
#define SDCARD_SPI_PARAM_POWER GPIO_UNDEF /**< power control is not used (fixed) */
#ifndef SDCARD_SPI_PARAM_CS
#define SDCARD_SPI_PARAM_CS SPI0_CS0_GPIO /**< SD-Card CS signal (can be overridden) */
#define SDCARD_SPI_PARAM_CS SPI0_CS0 /**< SD-Card CS signal (can be overridden) */
#endif
/** @} */
#endif /* defined(MODULE_SDCARD_SPI) || defined(DOXYGEN) */

View File

@ -19,8 +19,8 @@
#define PERIPH_CONF_COMMON_H
/* include board.h and periph_cpu.h to make them visible in any case */
#include "board.h"
#include "periph_cpu.h"
#include "kernel_defines.h"
#ifdef __cplusplus
extern "C" {
@ -36,18 +36,67 @@ extern "C" {
* ESP8266 provides one ADC pin that is broken out on all boards.
* @{
*/
#define ADC_NUMOF 1 /**< number of ADC channels */
#define ADC_NUMOF (1) /**< number of ADC channels */
/** @} */
/**
* @name DAC configuration
*
* ESP8266 provides no DAC.
* @{
*/
#define DAC_NUMOF (0) /**< number of DAC channels */
/** @} */
/**
* @name I2C configuration
* @{
*/
/**
* @brief Static array with configuration for declared I2C devices
*/
static const i2c_conf_t i2c_config[] = {
#if defined(I2C0_SCL) && defined(I2C0_SDA) && defined(I2C0_SPEED)
{
.speed = I2C0_SPEED,
.scl = I2C0_SCL,
.sda = I2C0_SDA,
},
#endif
#if defined(I2C1_SCL) && defined(I2C1_SDA) && defined(I2C1_SPEED)
{
.speed = I2C1_SPEED,
.scl = I2C1_SCL,
.sda = I2C1_SDA,
},
#endif
};
/**
* @brief Number of I2C interfaces
*
* The number of I2C interfaces is determined automatically from board-specific
* peripheral definitions.
*
* @note I2C_NUMOF definition must not be changed.
*/
#define I2C_NUMOF ARRAY_SIZE(i2c_config)
/** @} */
/**
* @name PWM configuration
*
* The hardware implementation of ESP8266 PWM supports only frequencies as power of
* two. Therefore a software implementation of one PWM device PWM_DEV(0) with up to
* 8 PWM channels (PWM_CHANNEL_NUM_MAX) is used.
* The hardware implementation of ESP8266 PWM supports only frequencies as
* power of two. Therefore a software implementation of one PWM device
* PWM_DEV(0) with up to 8 PWM channels (#PWM_CHANNEL_NUM_MAX) is used. The
* GPIOs that can be used as PWM channels are defined by #PWM0_GPIOS in board
* definition.
*
* @note The minumum PWM period that can be realized is 10 us or 100.000 PWM
* @note The minimum PWM period that can be realized is 10 us or 100.000 PWM
* clock cycles per second. Therefore, the product of frequency and resolution
* should not be greater than 100.000. Otherwise the frequency is scaled down
* automatically.
@ -55,71 +104,85 @@ extern "C" {
* @{
*/
#if defined(PWM0_GPIOS) || defined(DOXYGEN)
/**
* @brief Static array of GPIOs that can be used as channels of PWM_DEV(0)
*/
static const gpio_t pwm0_channels[] = PWM0_GPIOS;
/**
* @brief Number of PWM devices
*
* The number of PWM devices is determined from the #PWM0_GPIOS definition.
*
* @note #PWM_NUMOF definition must not be changed.
*/
#define PWM_NUMOF (1) /**< Number of PWM devices */
/**
* @brief Maximum number of channels per PWM device.
*/
#define PWM_CHANNEL_NUM_MAX (8)
/**
* @brief Definition of GPIOs that can be used as PWM channels
* of device PWM_DEV(0).
*
* The following definition is just an example configuration. Declare up to
* \ref PWM_CHANNEL_NUM_MAX GPIOs as PWM channels. GPIOs with a duty cycle
* value of 0 can be used as normal GPIOs for other purposes. GPIOs in the
* list that are used for other purposes, e.g., I2C or SPI, are then not
* available as PWM channels.
*/
#ifndef PWM0_CHANNEL_GPIOS
#define PWM0_CHANNEL_GPIOS { GPIO2, GPIO4, GPIO5 }
#endif
/** Alternative device definition */
#define PWM0_DEV PWM_DEV(0)
#endif /* defined(PWM0_GPIOS) || defined(DOXYGEN) */
/** @} */
/**
* @name SPI configuration
* @name SPI configuration
*
* ESP8266 provides two hardware SPI interfaces:
* ESP8266 has two SPI controllers:
*
* _FSPI_ for flash memory and usually simply referred to as _SPI_<br>
* _HSPI_ for peripherals
* - _CSPI_ for caching and accessing the flash memory<br>
* - _HSPI_ for peripherals
*
* Even though _FSPI_ (or simply _SPI_) is a normal SPI interface, it is not
* possible to use it for peripherals. _HSPI_ is therefore the only usable
* SPI interface available for peripherals as RIOT's SPI_DEV(0).
* Thus, _HSPI_ is the only SPI interface that is available for peripherals.
* It is exposed as RIOT's SPI_DEV(0). Furthermore, the pin configuration of
* the _HSPI_ interface is fixed as shown in following table.
*
* The pin configuration of the _HSPI_ interface SPI_DEV(0) is fixed. The
* only pin definition that can be overridden by an application-specific
* board configuration is the CS signal defined by SPI0_CS0_GPIO.
* Signal | Pin
* -----------|-------
* #SPI0_MISO | GPIO12
* #SPI0_MOSI | GPIO13
* #SPI0_SCK | GPIO14
* #SPI0_CS0 | GPIOn with n = 0, 2, 4, 5, 15, 16 (additionally 9, 10 in DOUT flash mode)
*
* The only pin definition that can be overridden by an application-specific
* board configuration is the CS signal defined by #SPI0_CS0.
*
* Signal | Pin
* ----------------|-------
* SPI_DEV(0).MISO | GPIO12
* SPI_DEV(0).MOSI | GPIO13
* SPI_DEV(0).SCK | GPIO14
* SPI_DEV(0).CS | GPIOn with n = 0, 2, 4, 5, 15, 16 (additionally 9, 10 in DOUT flash mode)
* @{
*/
#if defined(MODULE_PERIPH_SPI) || defined(DOXYGEN)
#define SPI_NUMOF 1 /**< Number of SPI interfaces */
#define SPI_DEV(x) ((unsigned int)(x+1)) /**< SPI_DEV to SPI hardware mapping */
#define SPI0_DEV SPI_DEV(0) /**< HSPI / SPI_DEV(0) device */
#define SPI0_CTRL HSPI /**< HSPI / SPI_DEV(0) controller */
#define SPI0_MISO GPIO12 /**< HSPI / SPI_DEV(0) MISO pin */
#define SPI0_MOSI GPIO13 /**< HSPI / SPI_DEV(0) MOSI pin */
#define SPI0_SCK GPIO14 /**< HSPI / SPI_DEV(0) SCK pin */
#define SPI0_DEV SPI_DEV(0) /**< HSPI / SPI_DEV(0) device */
#define SPI0_MISO_GPIO GPIO12 /**< HSPI / SPI_DEV(0) MISO pin */
#define SPI0_MOSI_GPIO GPIO13 /**< HSPI / SPI_DEV(0) MOSI pin */
#define SPI0_SCK_GPIO GPIO14 /**< HSPI / SPI_DEV(0) SCK pin */
#ifndef SPI0_CS0_GPIO
#define SPI0_CS0_GPIO GPIO15 /**< HSPI / SPI_DEV(0) CS default pin, only used when cs
parameter in spi_acquire is GPIO_UNDEF */
#ifndef SPI0_CS0
#define SPI0_CS0 GPIO15 /**< HSPI / SPI_DEV(0) CS default pin, only used when cs
parameter in spi_acquire is #GPIO_UNDEF */
#endif
#endif /* defined(MODULE_PERIPH_SPI) || defined(DOXYGEN) */
/**
* @brief Static array with configuration for declared SPI devices
*/
static const spi_conf_t spi_config[] = {
#ifdef SPI0_CTRL
{
.ctrl = SPI0_CTRL,
.sck = SPI0_SCK,
.mosi = SPI0_MOSI,
.miso = SPI0_MISO,
.cs = SPI0_CS0,
},
#endif
};
/**
* @brief Number of SPI interfaces
*
* The number of SPI interfaces is determined from board-specific peripheral
* definitions of SPIn_*.
*
* @note SPI_NUMOF definition must not be changed.
*/
#define SPI_NUMOF ARRAY_SIZE(spi_config)
/** @} */
/**
@ -153,9 +216,29 @@ extern "C" {
*
* @{
*/
#define UART_NUMOF 1 /**< Number of UART devices */
#define UART0_TXD GPIO1 /**< TxD pin of UART_DEV(0) */
#define UART0_RXD GPIO3 /**< RxD pin of UART_DEV(0) */
/**
* @brief Static array with configuration for declared UART devices
*/
static const uart_conf_t uart_config[] = {
{
.txd = UART0_TXD,
.rxd = UART0_RXD,
},
};
/**
* @brief Number of UART interfaces
*
* The number of UART interfaces is determined from board-specific peripheral
* definitions of UARTn_*.
*
* @note UART_NUMOF definition must not be changed.
*/
#define UART_NUMOF (sizeof(uart_config)/sizeof(uart_config[0]))
/** @} */
#ifdef __cplusplus

View File

@ -82,7 +82,7 @@ D1 mini Pro | ESP8266EX | 16 MByte | ceramic | |
Following image shows the pinout of all WEMOS LOLIN D1 mini boards. It is compatible with the WEMOS LOLIN D32 Pro ESP32 board.
@image html "https://gitlab.com/gschorcht/RIOT.wiki-Images/raw/master/esp8266/Wemos_D1_mini_pinout.png?inline=false" "WEMOS LOLIN D1 min pinout"<br>
@image html "https://gitlab.com/gschorcht/RIOT.wiki-Images/raw/master/esp8266/Wemos_D1_mini_pinout.png?inline=false" "WEMOS LOLIN D1 mini pinout"<br>
## <a name="nodemcu_devkit_esp8266"> NodeMCU DEVKIT </a>

View File

@ -6,10 +6,6 @@
* directory for more details.
*/
/**
* @ingroup boards_esp8266_esp-12x
*/
/**
* @ingroup boards_esp8266_esp-12x
* @brief Board specific definitions for ESP-12x based boards.

View File

@ -27,9 +27,6 @@ extern "C" {
* @name I2C configuration
* @{
*/
#ifndef I2C_NUMOF
#define I2C_NUMOF (1) /**< Number of I2C interfaces */
#endif
#ifndef I2C0_SPEED
#define I2C0_SPEED I2C_SPEED_FAST /**< I2C bus speed of I2C_DEV(0) */
#endif
@ -41,6 +38,25 @@ extern "C" {
#endif
/** @} */
/**
* @name PWM channel configuration
*
* @{
*/
/**
* @brief Declaration of the channels for device PWM_DEV(0),
* at maximum 8 channels.
*
* @note As long as PWM_DEV(0) is not initialized with \ref pwm_init, the GPIOs
* declared as PWM channels can be used for other purposes.
*/
#ifndef PWM0_GPIOS
#define PWM0_GPIOS { GPIO0, GPIO2, GPIO16 }
#endif
/** @} */
#ifdef __cplusplus
} /* end extern "C" */
#endif

View File

@ -6,10 +6,6 @@
* directory for more details.
*/
/**
* @ingroup boards_esp8266_olimex-mod
*/
/**
* @ingroup boards_esp8266_olimex-mod
* @brief Board specific definitions for

View File

@ -28,9 +28,6 @@
* @name I2C configuration
* @{
*/
#ifndef I2C_NUMOF
#define I2C_NUMOF (1) /**< Number of I2C interfaces */
#endif
#ifndef I2C0_SPEED
#define I2C0_SPEED I2C_SPEED_FAST /**< I2C bus speed of I2C_DEV(0) */
#endif
@ -42,6 +39,23 @@
#endif
/** @} */
/**
* @name PWM channel configuration
*
* @{
*/
/**
* @brief Declaration of the channels for device PWM_DEV(0),
* at maximum 8 channels.
*
* @note As long as PWM_DEV(0) is not initialized with \ref pwm_init, the GPIOs
* declared as PWM channels can be used for other purposes.
*/
#ifndef PWM0_GPIOS
#define PWM0_GPIOS { GPIO0, GPIO5, GPIO16 }
#endif
#ifdef __cplusplus
} /* end extern "C" */
#endif

View File

@ -6,10 +6,6 @@
* directory for more details.
*/
/**
* @ingroup boards_esp8266_sparkfun-thing
*/
/**
* @ingroup boards_esp8266_sparkfun-thing
* @brief Board specific definitions for

View File

@ -28,9 +28,6 @@
* @name I2C configuration
* @{
*/
#ifndef I2C_NUMOF
#define I2C_NUMOF (1) /**< Number of I2C interfaces */
#endif
#ifndef I2C0_SPEED
#define I2C0_SPEED I2C_SPEED_FAST /**< I2C bus speed of I2C_DEV(0) */
#endif
@ -42,6 +39,25 @@
#endif
/** @} */
/**
* @name PWM channel configuration
*
* @{
*/
/**
* @brief Declaration of the channels for device PWM_DEV(0),
* at maximum 8 channels.
*
* @note As long as PWM_DEV(0) is not initialized with \ref pwm_init, the GPIOs
* declared as PWM channels can be used for other purposes.
*/
#ifndef PWM0_GPIOS
#define PWM0_GPIOS { GPIO0, GPIO4, GPIO5 }
#endif
/** @} */
#ifdef __cplusplus
} /* end extern "C" */
#endif

View File

@ -205,3 +205,10 @@ void IRAM NORETURN panic_arch(void)
UNREACHABLE();
}
void _panic_handler(uint32_t addr)
{
ets_printf("#! _xt_panic called from 0x%08x: powering off\n", addr);
pm_off();
while (1) { };
}

View File

@ -170,7 +170,7 @@ typedef enum {
*
* ESP32 integrates two 12-bit ADCs (ADC1 and ADC2) capable of measuring up to
* 18 analog signals in total. Most of these ADC channels are either connected
* to a number of intergrated sensors like a Hall sensors, touch sensors and a
* to a number of integrated sensors like a Hall sensors, touch sensors and a
* temperature sensor or can be connected with certain GPIOs. Integrated
* sensors are disabled in RIOT's implementation and are not accessible. Thus,
* up to 18 GPIOs, the RTC GPIOs, can be used as ADC inputs:
@ -209,7 +209,7 @@ typedef enum {
* determines the mapping between the RIOT's ADC lines and the GPIOs.
*
* @note ADC_GPIOS must be defined even if there are no GPIOs that could be
* used as ADC channels on the board. In this case, an empy list hast to be
* used as ADC channels on the board. In this case, an empty list hast to be
* defined which just contains the curly braces.
*
* ADC_NUMOF is determined automatically from the ADC_GPIOS definition.
@ -240,7 +240,7 @@ typedef enum {
#endif /* ndef DOXYGEN */
/**
* @brief Number of ADC cahnnels that could be used at maximum
* @brief Number of ADC channels that could be used at maximum
*
* @note GPIO37 and GPIO38 are usually not broken out on ESP32 modules and are
* therefore not usable. The maximum number of ADC channels (ADC_NUMOF_MAX)
@ -263,7 +263,7 @@ typedef enum {
* determines the mapping between the RIOT's DAC lines and the GPIOs.
*
* @note DAC_GPIOS must be defined even if there are no GPIOs that could be
* used as DAC channels on the board. In this case, an empy list hast to be
* used as DAC channels on the board. In this case, an empty list hast to be
* defined which just contains the curly braces.
*
* DAC_NUMOF is determined automatically from the DAC_GPIOS definition.
@ -275,7 +275,7 @@ typedef enum {
*/
/**
* @brief Number of DAC cahnnels that could be used at maximum.
* @brief Number of DAC channels that could be used at maximum.
*/
#define DAC_NUMOF_MAX 2
@ -287,7 +287,7 @@ typedef enum {
* ESP32 has two built-in I2C interfaces.
*
* The board-specific configuration of the I2C interface I2C_DEV(n) requires
* the defintion of
* the definition of
*
* I2Cn_SPEED, the bus speed,
* I2Cn_SCL, the GPIO used as SCL signal, and
@ -332,6 +332,11 @@ typedef struct {
gpio_t sda; /**< GPIO used as SDA pin */
} i2c_conf_t;
/**
* @brief Maximum number of I2C interfaces that can be used by board definitions
*/
#define I2C_NUMOF_MAX (2)
#define PERIPH_I2C_NEED_READ_REG /**< i2c_read_reg required */
#define PERIPH_I2C_NEED_READ_REGS /**< i2c_read_regs required */
#define PERIPH_I2C_NEED_WRITE_REG /**< i2c_write_reg required */
@ -340,7 +345,6 @@ typedef struct {
/**
* @name PWM configuration
* @{
*
* PWM implementation uses ESP32's high-speed MCPWM modules. ESP32 has 2 such
* modules, each with up to 6 channels (PWM_CHANNEL_NUM_DEV_MAX). Thus, the
@ -362,6 +366,8 @@ typedef struct {
* @note As long as the GPIOs listed in PWM0_GPIOS and PMW1_GPIOS are not
* initialized as PWM channels with the *pwm_init* function, they can be used
* other purposes.
*
* @{
*/
/**
@ -395,7 +401,7 @@ typedef struct {
* device driver doesn't support it.
*
* The board-specific configuration of the SPI interface SPI_DEV(n) requires
* the defintion of
* the definition of
*
* - SPIn_CTRL, the SPI controller which is used for the interface (VSPI or HSPI),
* - SPIn_SCK, the GPIO used as clock signal
@ -409,6 +415,8 @@ typedef struct {
*
* SPI_NUMOF is determined automatically from the board-specific peripheral
* definitions of SPIn_*.
*
* @{
*/
/**
@ -430,6 +438,11 @@ typedef struct {
gpio_t cs; /**< GPIO used as CS0 pin */
} spi_conf_t;
/**
* @brief Maximum number of SPI interfaces that can be used by board definitions
*/
#define SPI_NUMOF_MAX 2
#define PERIPH_SPI_NEEDS_TRANSFER_BYTE /**< requires function spi_transfer_byte */
#define PERIPH_SPI_NEEDS_TRANSFER_REG /**< requires function spi_transfer_reg */
#define PERIPH_SPI_NEEDS_TRANSFER_REGS /**< requires function spi_transfer_regs */

View File

@ -3,6 +3,7 @@ MODULE = cpu
# Add a list of subdirectories, that should also be built:
DIRS += $(RIOTCPU)/esp_common
DIRS += freertos
DIRS += periph
DIRS += sdk
DIRS += vendor
@ -11,4 +12,6 @@ ifneq (, $(filter esp_wifi, $(USEMODULE)))
DIRS += esp-wifi
endif
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/esp8266/include/internal
include $(RIOTBASE)/Makefile.base

View File

@ -1,17 +1,5 @@
# additional modules dependencies
ifneq (, $(filter esp_sdk, $(USEMODULE)))
USEMODULE += core_thread_flags
INCLUDES += -I$(ESP8266_SDK_DIR)/third_party/include
LINKFLAGS += -Wl,-wrap=malloc
LINKFLAGS += -Wl,-wrap=free
LINKFLAGS += -Wl,-wrap=calloc
LINKFLAGS += -Wl,-wrap=realloc
LINKFLAGS += -Wl,-wrap=_malloc_r
LINKFLAGS += -Wl,-wrap=_free_r
LINKFLAGS += -Wl,-wrap=_realloc_r
endif
ifneq (, $(filter esp_spiffs, $(USEMODULE)))
export SPIFFS_STD_OPTION = -std=c99
USEMODULE += spiffs
@ -19,12 +7,9 @@ ifneq (, $(filter esp_spiffs, $(USEMODULE)))
endif
ifneq (, $(filter esp_wifi, $(USEMODULE)))
CFLAGS += -DLWIP_OPEN_SRC
LINKFLAGS += -Wl,-wrap=ethernet_input
USEMODULE += netdev_eth
endif
ifneq (,$(filter ndn-riot,$(USEPKG)))
USEMODULE += crypto
USEMODULE += cipher_modes
ifneq (,$(filter log_color,$(USEMODULE)))
USEMODULE += esp_log_colored
endif

View File

@ -2,6 +2,7 @@
FEATURES_PROVIDED += arch_32bit
FEATURES_PROVIDED += arch_esp8266
FEATURES_PROVIDED += cpp
FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_hwrng
FEATURES_PROVIDED += periph_pm

View File

@ -1,23 +1,13 @@
# check some environment variables first
ifndef ESP8266_NEWLIB_DIR
$(info ESP8266_NEWLIB_DIR should be defined as /path/to/newlib directory)
$(info ESP8266_NEWLIB_DIR is set by default to /opt/esp/newlib-xtensa)
export ESP8266_NEWLIB_DIR=/opt/esp/newlib-xtensa
endif
ifndef ESP8266_SDK_DIR
$(info ESP8266_SDK_DIR should be defined as /path/to/sdk directory)
$(info ESP8266_SDK_DIR is set by default to /opt/esp/esp-open-sdk/sdk)
export ESP8266_SDK_DIR=/opt/esp/esp-open-sdk/sdk
ifndef ESP8266_RTOS_SDK_DIR
$(info ESP8266_RTOS_SDK_DIR should be defined as /path/to/sdk directory)
$(info ESP8266_RTOS_SDK_DIR is set by default to /opt/esp/ESP8266-RTOS-SDK)
export ESP8266_RTOS_SDK_DIR=/opt/esp/ESP8266-RTOS-SDK
endif
# Options to control the compilation
ifeq ($(USE_SDK), 1)
USEMODULE += esp_sdk
endif
ifeq ($(ENABLE_GDB), 1)
USEMODULE += esp_gdb
endif
@ -29,85 +19,117 @@ endif
# SPECIAL module dependencies
# cannot be done in Makefile.dep since Makefile.dep is included too late
ifneq (, $(filter esp_sw_timer, $(USEMODULE)))
USEMODULE += esp_sdk
endif
ifneq (, $(filter esp_wifi, $(USEMODULE)))
ifneq (, $(filter esp_now esp_wifi, $(USEMODULE)))
$(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1))))
USEMODULE += esp_sdk
USEMODULE += netopt
endif
ifneq (, $(filter esp_now, $(USEMODULE)))
$(eval GNRC_NETIF_NUMOF=$(shell echo $$(($(GNRC_NETIF_NUMOF)+1))))
USEMODULE += esp_sdk
CFLAGS += -DSCHED_PRIO_LEVELS=32
USEMODULE += esp_wifi_any
USEMODULE += netopt
USEMODULE += xtimer
endif
ifneq (, $(filter esp_gdbstub, $(USEMODULE)))
USEMODULE += esp_gdb
endif
ifneq (, $(filter spiffs, $(USEMODULE)))
export RIOT_TEST_TIMEOUT = 300
endif
ifneq (, $(filter littlefs, $(USEMODULE)))
export RIOT_TEST_TIMEOUT = 300
endif
# regular Makefile
export TARGET_ARCH ?= xtensa-lx106-elf
export TARGET_ARCH ?= xtensa-esp8266-elf
# ESP8266 pseudomodules
PSEUDOMODULES += esp_gdb
PSEUDOMODULES += esp_sdk
PSEUDOMODULES += esp_log_colored
PSEUDOMODULES += esp_log_tagged
PSEUDOMODULES += esp_qemu
PSEUDOMODULES += esp_sw_timer
PSEUDOMODULES += esp_spiffs
PSEUDOMODULES += esp_wifi_any
USEMODULE += esp
USEMODULE += esp_freertos
USEMODULE += esp_idf
USEMODULE += esp_idf_esp8266
USEMODULE += esp_idf_nvs_flash
USEMODULE += esp_idf_spi_flash
USEMODULE += esp_idf_util
USEMODULE += esp_idf_wpa_supplicant_crypto
USEMODULE += esp_sdk
USEMODULE += log
USEMODULE += mtd
USEMODULE += newlib
USEMODULE += newlib_nano
USEMODULE += newlib_syscalls_default
USEMODULE += periph
USEMODULE += periph_common
USEMODULE += periph_hrng
USEMODULE += periph_flash
USEMODULE += periph_uart
USEMODULE += ps
USEMODULE += random
USEMODULE += sdk
USEMODULE += stdio_uart
USEMODULE += xtensa
ifneq (, $(filter pthread, $(USEMODULE)))
# has to be included before $(ESP8266_NEWLIB_DIR)
INCLUDES += -I$(RIOTBASE)/sys/posix/pthread/include
endif
INCLUDES += -I$(ESP8266_NEWLIB_DIR)/$(TARGET_ARCH)/include
INCLUDES += -I$(RIOTBOARD)/common/$(CPU)/include
INCLUDES += -I$(RIOTCPU)/esp_common/vendor/
INCLUDES += -I$(RIOTCPU)/$(CPU)
INCLUDES += -I$(RIOTCPU)/$(CPU)/include
INCLUDES += -I$(RIOTCPU)/$(CPU)/include/freertos
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/espressif
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/bootloader_support/include
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/esp8266/include
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/esp8266/include/esp8266
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/heap/include
INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/log/include
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/bootloader_support/include/
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/esp8266/include
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/esp8266/include/esp8266
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/heap/include
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/heap/port/esp8266/include
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/nvs_flash/include
INCLUDES += -I$(ESP8266_RTOS_SDK_DIR)/components/spi_flash/include
CFLAGS += -DESP_OPEN_SDK -DSCHED_PRIO_LEVELS=32 -DCONTEXT_SWITCH_BY_INT
CFLAGS += -D__ESP_FILE__=__FILE__
CFLAGS += -Wno-unused-parameter -Wformat=0
CFLAGS += -mlongcalls -mtext-section-literals
CFLAGS += -ffunction-sections -fdata-sections -fzero-initialized-in-bss
CFLAGS += -mlongcalls -mtext-section-literals -fstrict-volatile-bitfields
CFLAGS += -fdata-sections -ffunction-sections -fzero-initialized-in-bss
OPTIONAL_CFLAGS_BLACKLIST += -fdiagnostics-color
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-truncation
OPTIONAL_CFLAGS_BLACKLIST += -gz
ASFLAGS += --longcalls --text-section-literals
ifneq (, $(filter esp_sdk, $(USEMODULE)))
INCLUDES += -I$(ESP8266_SDK_DIR)/include
CFLAGS += -DUSE_US_TIMER
endif
# thin archives trigger a reboot loop - see #12258, #12035, #12346
ARFLAGS = rcs
ifneq (, $(filter esp_gdbstub, $(USEMODULE)))
GDBSTUB_DIR ?= $(RIOTCPU)/$(CPU)/vendor/esp-gdbstub
CFLAGS += -DGDBSTUB_FREERTOS=0
CFLAGS += -DGDBSTUB_BREAK_ON_INIT=1
INCLUDES += -I$(GDBSTUB_DIR)
endif
ifneq (, $(filter esp_gdb, $(USEMODULE)))
CFLAGS += -Og -ggdb -g3
CFLAGS_OPT ?= -Og -ggdb -g3
else
CFLAGS += -Os
# TODO should be -Os
# With -Os char arrays have not to be 32-bit word aligned. This leads to
# an alignment exception when the address of an char array is assigned to
# an uint32_t pointer and the pointer is used for the access.
CFLAGS_OPT ?= -O2
endif
CFLAGS += $(CFLAGS_OPT)
ifeq ($(QEMU), 1)
CFLAGS += -DQEMU
USEMODULE += esp_qemu
endif
ifeq ($(FLASH_MODE), qio)
@ -118,51 +140,80 @@ ifeq ($(FLASH_MODE), qout)
CFLAGS += -DFLASH_MODE_QOUT
endif
LINKFLAGS += -L$(ESP8266_NEWLIB_DIR)/$(TARGET_ARCH)/lib
LINKFLAGS += -L$(ESP8266_SDK_DIR)/lib
LINKFLAGS += -L$(ESP8266_RTOS_SDK_DIR)/components/esp8266/lib
LINKFLAGS += $(CFLAGS_OPT)
ifneq (, $(filter esp_sdk, $(USEMODULE)))
LINKFLAGS += -Wl,--start-group $(BINDIR)/sdk.a
ifneq (, $(filter esp_now, $(USEMODULE)))
LINKFLAGS += -lespnow
endif
LINKFLAGS += -lmain -lnet80211 -lcrypto -lwpa2 -lwpa -llwip -lpp -lphy -lc -lhal
LINKFLAGS += -Wl,--end-group
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.riot-os.sdk.app.ld
else
LINKFLAGS += -Wl,--start-group -lphy -lhal -lc -Wl,--end-group
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.riot-os.no_sdk.app.ld
BASELIBS += -lc -lgcc -lwpa -lcore -lnet80211 -lphy -lpp -lhal -lstdc++
ifneq (, $(filter esp_now, $(USEMODULE)))
BASELIBS += -lespnow
endif
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/eagle.rom.addr.v6.ld
LINKFLAGS += -nostdlib -lgcc -u ets_run -Wl,-gc-sections # -Wl,--print-gc-sections
LINKFLAGS += -u _malloc_r
LINKFLAGS += -nostdlib -Wl,-gc-sections -Wl,-static # -Wl,--print-gc-sections
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.rom.ld
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.riot-os.ld
LINKFLAGS += -T$(RIOTCPU)/$(CPU)/ld/esp8266.peripherals.ld
LINKFLAGS += -Wl,-wrap=pp_attach
LINKFLAGS += -Wl,-wrap=pm_attach
ifneq (, $(filter esp_idf_heap, $(USEMODULE)))
LINKFLAGS += -Wl,-wrap=_malloc_r
LINKFLAGS += -Wl,-wrap=_calloc_r
LINKFLAGS += -Wl,-wrap=_free_r
LINKFLAGS += -Wl,-wrap=_realloc_r
endif
# The ELFFILE is the base one used for flashing
FLASHFILE ?= $(ELFFILE)
# configure preflasher to convert .elf to .bin before flashing
FLASH_SIZE = -fs 8m
PREFLASHER ?= esptool.py
PREFFLAGS ?= elf2image $(FLASH_SIZE) $(FLASHFILE)
FLASH_MODE = dout # FIX configuration, DO NOT CHANGE
FLASH_FREQ = 26m # FIX configuration, DO NOT CHANGE
FLASH_SIZE ?= 1MB
FLASHDEPS += preflash
# flasher configuration
ifeq ($(QEMU), 1)
FLASHER = cat
FFLAGS += $(FLASHFILE)-0x00000.bin /dev/zero | head -c $$((0x10000)) | cat -
FFLAGS += $(FLASHFILE)-0x10000.bin /dev/zero | head -c $$((0xfc000)) | cat -
FFLAGS += $(RIOTCPU)/$(CPU)/bin/esp_init_data_default.bin > $(FLASHFILE).bin
PREFLASHER ?= $(RIOTTOOLS)/esptool/esptool.py
PREFFLAGS = --chip esp8266 elf2image
PREFFLAGS += --flash_mode $(FLASH_MODE) --flash_size $(FLASH_SIZE)
PREFFLAGS += --flash_freq $(FLASH_FREQ) --version 3
PREFFLAGS += -o $(FLASHFILE).bin $(FLASHFILE);
PREFFLAGS += echo "" > $(BINDIR)/partitions.csv;
PREFFLAGS += echo "nvs, data, nvs, 0x9000, 0x6000" >> $(BINDIR)/partitions.csv;
PREFFLAGS += echo "phy_init, data, phy, 0xf000, 0x1000" >> $(BINDIR)/partitions.csv;
PREFFLAGS += echo -n "factory, app, factory, 0x10000, " >> $(BINDIR)/partitions.csv;
PREFFLAGS += ls -l $(FLASHFILE).bin | awk '{ print $$5 }' >> $(BINDIR)/partitions.csv;
PREFFLAGS += python $(RIOTCPU)/$(CPU)/vendor/esp-idf/partition_table/gen_esp32part.py
PREFFLAGS += --verify $(BINDIR)/partitions.csv $(BINDIR)/partitions.bin
ifneq (, $(filter esp_log_colored, $(USEMODULE)))
BOOTLOADER ?= bootloader_dout_115200_color.bin
else
FLASH_MODE ?= dout
export PROGRAMMER_SPEED ?= 460800
FLASHER = esptool.py
FFLAGS += -p $(PROG_DEV) -b $(PROGRAMMER_SPEED) write_flash
FFLAGS += -fm $(FLASH_MODE)
FFLAGS += 0 $(FLASHFILE)-0x00000.bin
FFLAGS += 0x10000 $(FLASHFILE)-0x10000.bin; esptool.py -p $(PROG_DEV) run
BOOTLOADER ?= bootloader_dout_115200_no_color.bin
endif
OPTIONAL_CFLAGS_BLACKLIST += -fdiagnostics-color
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-overflow
OPTIONAL_CFLAGS_BLACKLIST += -Wformat-truncation
OPTIONAL_CFLAGS_BLACKLIST += -gz
ifneq (, $(filter esp_qemu, $(USEMODULE)))
FLASHER = dd
FFLAGS += if=/dev/zero bs=1M count=1 | tr "\\000" "\\377" > tmp.bin &&
FFLAGS += cat $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER) tmp.bin |
FFLAGS += head -c $$((0x8000)) |
FFLAGS += cat - $(BINDIR)/partitions.bin tmp.bin |
FFLAGS += head -c $$((0x10000)) |
FFLAGS += cat - $(FLASHFILE).bin tmp.bin |
FFLAGS += head -c $$((0xfc000)) |
FFLAGS += cat - $(RIOTCPU)/$(CPU)/bin/esp_init_data_default.bin tmp.bin |
FFLAGS += head -c $$((0x100000)) > $(BINDIR)/esp8266flash.bin && rm tmp.bin
else
export PROGRAMMER_SPEED ?= 460800
FLASHER = $(RIOTBASE)/dist/tools/esptool/esptool.py
FFLAGS += --chip esp8266 --port $(PROG_DEV) --baud $(PROGRAMMER_SPEED)
FFLAGS += --before default_reset write_flash -z
FFLAGS += --flash_size detect
FFLAGS += --flash_mode $(FLASH_MODE) --flash_freq $(FLASH_FREQ)
FFLAGS += 0x0000 $(RIOTCPU)/$(CPU)/bin/$(BOOTLOADER)
FFLAGS += 0x8000 $(BINDIR)/partitions.bin
FFLAGS += 0x10000 $(FLASHFILE).bin
endif

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,7 @@
MODULE=esp_wifi
# we have to do it in that way to avoid that pkg/lwip is found first
CFLAGS += -I$(ESP8266_RTOS_SDK_DIR)/components/lwip/lwip/src/include
CFLAGS += -I$(ESP8266_RTOS_SDK_DIR)/components/lwip/port/esp8266/include/
include $(RIOTBASE)/Makefile.base

View File

@ -34,7 +34,7 @@ make -C examples/gnrc_networking BOARD=...
```
@note The Wifi network interface (module `esp_wifi`) and the
\ref esp32_esp_now_network_interface "ESP-NOW network interface" (module `esp_now`)
\ref esp8266_esp_now_network_interface "ESP-NOW network interface" (module `esp_now`)
can be used simultaneously, for example, to realize a border router for
a mesh network which uses ESP-NOW.
*/

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@
* @{
*
* @file
* @brief Network device driver for the ESP8266 WiFi interface
* @brief Network device driver for the ESP32 WiFi interface
*
* @author Gunar Schorcht <gunar@schorcht.net>
*/
@ -20,35 +20,46 @@
#define ESP_WIFI_NETDEV_H
#include "net/netdev.h"
#include "ringbuffer.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief State of the WiFi interface
* @brief Buffer size used for RX buffering
*/
typedef enum {
ESP_WIFI_NOT_WORKING, /**< interface is not working correctly */
ESP_WIFI_DISCONNECTED, /**< interface is not associated to the AP */
ESP_WIFI_CONNECTING, /**< interface is trying an association to the AP */
ESP_WIFI_CONNECTED /**< interface is not associated to the AP */
} esp_wifi_state_t;
#ifndef ESP_WIFI_BUFSIZE
#define ESP_WIFI_BUFSIZE (ETHERNET_MAX_LEN << 1)
#endif
/**
* @brief Device descriptor for ESP infrastructure mode WIFI device
* @brief Reference to the netdev device driver struct
*/
extern const netdev_driver_t esp_wifi_driver;
/**
* @brief Device descriptor for ESP WiFi devices
*/
typedef struct
{
netdev_t netdev; /**< netdev parent struct */
netdev_t netdev; /**< netdev parent struct */
uint8_t mac[ETHERNET_ADDR_LEN]; /**< MAC address of the device */
uint8_t rx_mem[ESP_WIFI_BUFSIZE]; /**< memory holding incoming packages */
ringbuffer_t rx_buf; /**< ringbuffer for incoming packages */
uint8_t rx_buf[ETHERNET_MAX_LEN]; /**< receive buffer */
uint16_t rx_len; /**< number of bytes received from lwIP */
uint16_t tx_len; /**< number of bytes in transmit buffer */
uint8_t tx_buf[ETHERNET_MAX_LEN]; /**< transmit buffer */
esp_wifi_state_t state; /**< indicates the interface state */
uint32_t event; /**< received event */
uint8_t event_recv; /**< number of frame received events */
uint8_t event_conn; /**< number of pending connect events */
uint8_t event_disc; /**< number of pending disc events */
bool connected; /**< indicates whether connected to AP */
gnrc_netif_t* netif; /**< reference to the corresponding netif */
mutex_t dev_lock; /**< device is already in use */
} esp_wifi_netdev_t;

View File

@ -12,7 +12,7 @@
* @{
*
* @file
* @brief Parameters for the ESP8266 WiFi netdev interface
* @brief Parameters for the ESP32 WiFi netdev interface
*
* @author Gunar Schorcht <gunar@schorcht.net>
*/
@ -20,10 +20,10 @@
#ifndef ESP_WIFI_PARAMS_H
#define ESP_WIFI_PARAMS_H
#if MODULE_ESP_WIFI || DOXYGEN
#if defined(MODULE_ESP_WIFI) || defined(DOXYGEN)
/**
* @name Set default configuration parameters for the ESP WIFI netdev driver
* @name Set default configuration parameters for the ESP WiFi netdev driver
* @{
*/
@ -31,30 +31,32 @@
* @brief The size of the stack used for the ESP WIFI netdev driver thread.
*/
#ifndef ESP_WIFI_STACKSIZE
#define ESP_WIFI_STACKSIZE (1536)
#define ESP_WIFI_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#endif
/**
* @brief The priority of the ESP WiFi netdev driver thread. Should not be changed.
*/
#ifndef ESP_WIFI_PRIO
#define ESP_WIFI_PRIO (GNRC_NETIF_PRIO)
#define ESP_WIFI_PRIO (GNRC_NETIF_PRIO)
#endif
/**
* @brief SSID of the AP to be used.
*/
#ifndef ESP_WIFI_SSID
#define ESP_WIFI_SSID "RIOT_AP"
#define ESP_WIFI_SSID "RIOT_AP"
#endif
/**
* @brief Passphrase used for the AP (max. 64 chars).
* @brief Passphrase used for the AP as clear text (max. 64 chars).
*/
#ifndef ESP_WIFI_PASS
#define ESP_WIFI_PASS "ThisistheRIOTporttoESP"
#define ESP_WIFI_PASS "ThisistheRIOTporttoESP"
#endif
/**@}*/
#ifdef __cplusplus
extern "C" {
#endif

103
cpu/esp8266/esp_events.c Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief ESP system event handler
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
* @}
*/
#if defined(MODULE_ESP_WIFI_ANY) || defined(MODULE_ESP_ETH)
#define ENABLE_DEBUG 0
#include "debug.h"
#include <string.h>
#include "esp_common.h"
#include "log.h"
#include "esp_attr.h"
#include "esp_event_loop.h"
#include "irq_arch.h"
#define MAX_HANDLER_NUM 5
static system_event_cb_t _handler[MAX_HANDLER_NUM] = {};
static void* _handler_arg[MAX_HANDLER_NUM] = {};
esp_err_t esp_system_event_add_handler (system_event_cb_t handler, void *arg)
{
int i;
/* determine next free handler entry */
for (i = 0; i < MAX_HANDLER_NUM; i++) {
if (_handler[i] == NULL) {
break;
}
}
/* return if there is no free entry */
if (i == MAX_HANDLER_NUM) {
return ESP_FAIL;
}
/* set the handler and argument entry */
_handler[i] = handler;
_handler_arg[i] = arg;
return ESP_OK;
}
esp_err_t esp_system_event_del_handler (system_event_cb_t handler)
{
int i;
/* determine the handler entry */
for (i = 0; i < MAX_HANDLER_NUM; i++) {
if (_handler[i] == handler) {
break;
}
}
/* return if entry was not found */
if (i == MAX_HANDLER_NUM) {
return ESP_FAIL;
}
/* clean handler and arg entry */
_handler[i] = NULL;
_handler_arg[i] = NULL;
return ESP_OK;
}
static esp_err_t esp_system_event_handler(void *ctx, system_event_t *event)
{
for (int i = 0; i < MAX_HANDLER_NUM; i++) {
if (_handler[i] != NULL) {
_handler[i](_handler_arg[i], event);
}
}
return ESP_OK;
}
#endif
void esp_event_handler_init(void)
{
#if defined(MODULE_ESP_WIFI_ANY) || defined(MODULE_ESP_ETH)
esp_event_loop_init(esp_system_event_handler, NULL);
#endif
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -17,87 +17,144 @@
* @}
*/
#define ENABLE_DEBUG 0
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"
#include "log.h"
#include "periph/pm.h"
#include "ps.h"
#include "esp_common.h"
#include "esp/common_macros.h"
#include "esp/xtensa_ops.h"
#include "sdk/ets.h"
#include "tools.h"
#include "xtensa/corebits.h"
#include "xtensa/xtensa_api.h"
extern void heap_stats(void);
static const char* exception_names [] =
{
"IllegalInstructionCause", /* 0 */
"SyscallCause", /* 1 */
"InstructionFetchErrorCause", /* 2 */
"LoadStoreErrorCause", /* 3 */
"Level1InterruptCause", /* 4 */
"AllocaCause", /* 5 */
"IntegerDivideByZeroCause", /* 6 */
"", /* 7 - reserved */
"PrivilegedCause", /* 8 */
"LoadStoreAlignmentCause", /* 9 */
"", /* 10 - reserved */
"", /* 11 - reserved */
"InstrPIFDataErrorCause", /* 12 */
"LoadStorePIFDataErrorCause", /* 13 */
"InstrPIFAddrErrorCause", /* 14 */
"LoadStorePIFAddrErrorCause", /* 15 */
"InstTLBMissCause", /* 16 */
"InstTLBMultiHitCause", /* 17 */
"InstFetchPrivilegeCause", /* 18 */
"", /* 19 - reserved */
"InstFetchProhibitedCause", /* 20 */
"", /* 21 - reserved */
"", /* 22 - reserved */
"", /* 23 - reserved */
"LoadStoreTLBMissCause", /* 24 */
"LoadStoreTLBMultiHitCause", /* 25 */
"LoadStorePrivilegeCause", /* 26 */
"", /* 27 - reserved */
"LoadProhibitedCause", /* 28 */
"StoreProhibitedCause", /* 29 */
"", /* 30 - reserved */
"", /* 31 - reserved */
"Coprocessor0Disabled", /* 32 */
"Coprocessor1Disabled", /* 33 */
"Coprocessor2Disabled", /* 34 */
"Coprocessor3Disabled", /* 35 */
"Coprocessor4Disabled", /* 36 */
"Coprocessor5Disabled", /* 37 */
"Coprocessor6Disabled", /* 38 */
"Coprocessor7Disabled", /* 39 */
"IllegalInstructionCause", /* 0 */
"SyscallCause", /* 1 */
"InstructionFetchErrorCause", /* 2 */
"LoadStoreErrorCause", /* 3 */
"Level1InterruptCause", /* 4 */
"AllocaCause", /* 5 */
"IntegerDivideByZeroCause", /* 6 */
"", /* 7 - reserved */
"PrivilegedCause", /* 8 */
"LoadStoreAlignmentCause", /* 9 */
"", /* 10 - reserved */
"", /* 11 - reserved */
"InstrPIFDataErrorCause", /* 12 */
"LoadStorePIFDataErrorCause", /* 13 */
"InstrPIFAddrErrorCause", /* 14 */
"LoadStorePIFAddrErrorCause", /* 15 */
"InstTLBMissCause", /* 16 */
"InstTLBMultiHitCause", /* 17 */
"InstFetchPrivilegeCause", /* 18 */
"", /* 19 - reserved */
"InstFetchProhibitedCause", /* 20 */
"", /* 21 - reserved */
"", /* 22 - reserved */
"", /* 23 - reserved */
"LoadStoreTLBMissCause", /* 24 */
"LoadStoreTLBMultiHitCause", /* 25 */
"LoadStorePrivilegeCause", /* 26 */
"", /* 27 - reserved */
"LoadProhibitedCause", /* 28 */
"StoreProhibitedCause", /* 29 */
"", /* 30 - reserved */
"", /* 31 - reserved */
"Coprocessor0Disabled", /* 32 */
"Coprocessor1Disabled", /* 33 */
"Coprocessor2Disabled", /* 34 */
"Coprocessor3Disabled", /* 35 */
"Coprocessor4Disabled", /* 36 */
"Coprocessor5Disabled", /* 37 */
"Coprocessor6Disabled", /* 38 */
"Coprocessor7Disabled", /* 39 */
};
void IRAM NORETURN exception_handler (XtExcFrame *frame)
{
uint32_t excsave1;
uint32_t epc1;
uint32_t epc2;
uint32_t epc3;
RSR(excsave1, excsave1);
RSR(epc1, epc1);
RSR(epc2, epc2);
RSR(epc3, epc3);
ets_printf("EXCEPTION!! exccause=%d (%s) @%08lx excvaddr=%08lx\n",
#ifdef MCU_ESP32
uint32_t epc4;
RSR(epc4, epc4);
#endif
ets_printf("EXCEPTION!! exccause=%d (%s) @%08x excvaddr=%08x\n",
frame->exccause, exception_names[frame->exccause],
excsave1, frame->excvaddr);
#if defined(DEVELHELP)
#if defined(MODULE_PS)
ps();
#endif
print_meminfo();
#endif
/* flushing the buffer */
ets_printf(" \n");
ets_printf(" \n");
ets_printf(" \n");
#if defined(DEVELHELP)
#if defined(MODULE_PS)
ets_printf("processes:\n");
ps();
ets_printf("\n");
#endif /* MODULE_PS */
heap_stats();
ets_printf("\nregister set\n");
ets_printf("pc : %08x\t", frame->pc);
ets_printf("ps : %08x\t", frame->ps);
ets_printf("exccause: %08x\t", frame->exccause);
ets_printf("excvaddr: %08x\n", frame->excvaddr);
ets_printf("epc1 : %08x\t", epc1);
ets_printf("epc2 : %08x\t", epc2);
ets_printf("epc3 : %08x\t", epc3);
#ifdef MCU_ESP32
ets_printf("epc4 : %08x\n", epc4);
#else /* MCU_ESP32 */
ets_printf("epc3 : %08x\n", epc3);
#endif /* MCU_ESP32 */
ets_printf("a0 : %08x\t", frame->a0);
ets_printf("a1 : %08x\t", frame->a1);
ets_printf("a2 : %08x\t", frame->a2);
ets_printf("a3 : %08x\n", frame->a3);
ets_printf("a4 : %08x\t", frame->a4);
ets_printf("a5 : %08x\t", frame->a5);
ets_printf("a6 : %08x\t", frame->a6);
ets_printf("a7 : %08x\n", frame->a7);
ets_printf("a8 : %08x\t", frame->a8);
ets_printf("a9 : %08x\t", frame->a9);
ets_printf("a10 : %08x\t", frame->a10);
ets_printf("a11 : %08x\n", frame->a11);
ets_printf("a12 : %08x\t", frame->a12);
ets_printf("a13 : %08x\t", frame->a13);
ets_printf("a14 : %08x\t", frame->a14);
ets_printf("a15 : %08x\n", frame->a15);
#if XCHAL_HAVE_LOOPS
ets_printf("lbeg : %08x\t", frame->lbeg);
ets_printf("lend : %08x\t", frame->lend);
ets_printf("lcount : %08x\n", frame->lcount);
#endif /* XCHAL_HAVE_LOOPS */
#endif /* DEVELHELP */
/* restart */
/* TODO: Improvement
Normally, we should try to restart the system. However, this
will not work after some exceptions, e.g., the LoadStoreErrorCause.
One option is to break the execution and wait for the WDT reset. Maybe
there is better way. If debugger is active, 'break 0,0' stops the
execution in debugger. */
/* __asm__ volatile ("break 0,0"); */
/* hard reset */
__asm__ volatile (" call0 0x40000080 ");
@ -118,9 +175,7 @@ void init_exceptions (void)
void IRAM NORETURN panic_arch(void)
{
#if defined(DEVELHELP)
print_meminfo();
ets_printf(" \n");
ets_printf(" \n");
heap_stats();
#endif
/* hard reset */
@ -128,3 +183,10 @@ void IRAM NORETURN panic_arch(void)
UNREACHABLE();
}
void _panic_handler(uint32_t addr)
{
ets_printf("#! _xt_panic called from 0x%08x: powering off\n", addr);
pm_off();
while (1) { };
}

View File

@ -1,3 +1,3 @@
MODULE=esp
MODULE=esp_freertos
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,58 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef DOXYGEN
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <string.h>
#include "rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
EventGroupHandle_t xEventGroupCreate (void)
{
printf("%s is not supported\n", __func__);
return NULL;
}
void vEventGroupDelete (EventGroupHandle_t xEventGroup)
{
printf("%s is not supported\n", __func__);
}
EventBits_t xEventGroupSetBits (EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet)
{
printf("%s is not supported\n", __func__);
return 0;
}
EventBits_t xEventGroupClearBits (EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear )
{
printf("%s is not supported\n", __func__);
return 0;
}
EventBits_t xEventGroupWaitBits (const EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait)
{
printf("%s is not supported\n", __func__);
return 0;
}
#endif /* DOXYGEN */

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef DOXYGEN
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <string.h>
#include "esp_common.h"
#include "log.h"
#ifdef MCU_ESP8266
#include "esp_attr.h"
#include "irq.h"
#include "rom/ets_sys.h"
#endif
#include "freertos/FreeRTOS.h"
uint32_t xPortGetTickRateHz(void) {
return MSEC_PER_SEC / portTICK_PERIOD_MS;
}
BaseType_t xPortInIsrContext(void)
{
/* is working on single core in that way */
return irq_is_in();
}
#ifdef MCU_ESP8266
unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */
extern void vTaskEnterCritical( portMUX_TYPE *mux );
extern void vTaskExitCritical( portMUX_TYPE *mux );
void vPortEnterCritical(void)
{
vTaskEnterCritical(0);
}
extern void vPortExitCritical(void)
{
vTaskExitCritical(0);
}
/* source: /path/to/esp8266-rtos-sdk/components/freertos/port/esp8266/port.c */
void IRAM_ATTR vPortETSIntrLock(void)
{
ETS_INTR_LOCK();
}
/* source: /path/to/esp8266-rtos-sdk/components/freertos/port/esp8266/port.c */
void IRAM_ATTR vPortETSIntrUnlock(void)
{
ETS_INTR_UNLOCK();
}
/* source: /path/to/esp8266-rtos-sdk/components/freertos/port/esp8266/port.c */
void ResetCcountVal(unsigned int cnt_val)
{
asm volatile("wsr a2, ccount");
}
#endif /* MCU_ESP8266 */
#endif /* DOXYGEN */

View File

@ -0,0 +1,394 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef DOXYGEN
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <string.h>
#include "esp_common.h"
#include "esp_attr.h"
#include "irq_arch.h"
#include "log.h"
#include "mutex.h"
#include "rmutex.h"
#include "syscalls.h"
#include "thread.h"
#include "rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
/*
* In FreeRTOS different types of semaphores, mutexes and queues are all
* mapped to a single generic queue type. With all these different types,
* single functions for send, receive, give and take are then used. To be
* able to dsitinguish between these different types in RIOT, we need typed
* objects.
*/
typedef struct {
uint8_t type; /* type of the queue, MUST be the first element */
list_node_t sending; /* threads that are waiting to send */
list_node_t receiving; /* threads that are waiting to receive */
uint8_t* queue; /* the queue of waiting items */
uint32_t item_size; /* size of each item in the queue */
uint32_t item_num; /* num of items that can be stored in queue */
uint32_t item_front; /* first item in queue */
uint32_t item_tail; /* last item in queue */
uint32_t item_level; /* num of items stored in queue */
} _queue_t;
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType )
{
DEBUG("%s pid=%d len=%u size=%u type=%u ", __func__,
thread_getpid(), uxQueueLength, uxItemSize, ucQueueType);
uint32_t queue_size = uxQueueLength * uxItemSize;
_queue_t* queue = malloc(sizeof(_queue_t) + queue_size);
if (!queue) {
return NULL;
}
queue->type = ucQueueType;
queue->receiving.next = NULL;
queue->sending.next = NULL;
queue->queue = (queue_size) ? (uint8_t*)queue + sizeof(_queue_t) : NULL;
queue->item_num = uxQueueLength;
queue->item_size = uxItemSize;
queue->item_front = 0;
queue->item_tail = 0;
queue->item_level = 0;
DEBUG("queue=%p\n", queue);
return queue;
}
#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 )
QueueHandle_t xQueueCreateCountingSemaphore (const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount)
{
_queue_t* queue;
assert(uxMaxCount != 0);
assert(uxInitialCount <= uxMaxCount);
queue = xQueueGenericCreate(uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH,
queueQUEUE_TYPE_COUNTING_SEMAPHORE);
DEBUG("%s pid=%d queue=%p\n", __func__, thread_getpid(), queue);
if (queue != NULL) {
queue->item_level = uxInitialCount;
queue->item_tail = (queue->item_front + queue->item_level) % queue->item_num;
}
return queue;
}
void vQueueDelete( QueueHandle_t xQueue )
{
DEBUG("%s pid=%d queue=%p\n", __func__, thread_getpid(), xQueue);
assert(xQueue != NULL);
free(xQueue);
}
BaseType_t IRAM_ATTR _queue_generic_send(QueueHandle_t xQueue,
const void * const pvItemToQueue,
const BaseType_t xCopyPosition,
TickType_t xTicksToWait,
BaseType_t * const pxHigherPriorityTaskWoken)
{
DEBUG("%s pid=%d prio=%d queue=%p pos=%d wait=%u woken=%p isr=%d\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority,
xQueue, xCopyPosition, xTicksToWait, pxHigherPriorityTaskWoken,
irq_is_in());
assert(xQueue != NULL);
_queue_t* queue = (_queue_t*)xQueue;
while (1) {
vTaskEnterCritical(0);
/* is there still space in the queue */
if (queue->item_level < queue->item_num || xCopyPosition == queueOVERWRITE) {
uint32_t write_pos;
/* determine the write position in the queue and update positions */
if (xCopyPosition == queueSEND_TO_BACK) {
write_pos = queue->item_tail;
queue->item_tail = (queue->item_tail + 1) % queue->item_num;
queue->item_level++;
}
else if (xCopyPosition == queueSEND_TO_FRONT) {
queue->item_front = (queue->item_front - 1) % queue->item_num;
queue->item_level++;
write_pos = queue->item_front;
}
else { /* queueOVERWRITE */
write_pos = queue->item_front;
if (queue->item_level == 0) {
queue->item_level++;
}
}
/* if the item has no 0 size, copy it to the according place in queue */
if (queue->item_size && queue->queue && pvItemToQueue) {
memcpy(queue->queue + write_pos * queue->item_size,
pvItemToQueue, queue->item_size);
}
/* indicates a required context switch */
bool ctx_switch = false;
/* unlock waiting receiving thread */
if (queue->receiving.next != NULL) {
list_node_t *next = list_remove_head(&queue->receiving);
thread_t *proc = container_of((clist_node_t*)next, thread_t, rq_entry);
sched_set_status(proc, STATUS_PENDING);
ctx_switch = proc->priority < sched_threads[thread_getpid()]->priority;
DEBUG("%s pid=%d queue=%p unlock waiting pid=%d switch=%d\n",
__func__, thread_getpid(), xQueue, proc->pid, ctx_switch);
}
if (ctx_switch && pxHigherPriorityTaskWoken) {
*pxHigherPriorityTaskWoken = pdTRUE;
vTaskExitCritical(0);
}
else if (ctx_switch) {
vTaskExitCritical(0);
/* sets only the sched_context_switch_request in ISRs */
thread_yield_higher();
}
else {
vTaskExitCritical(0);
}
DEBUG("%s pid=%d queue=%p return pdPASS\n", __func__,
thread_getpid(), xQueue);
/* in all cases vTaskExitCritical has been called already */
return pdPASS;
}
else if (xTicksToWait == 0 || irq_is_in()) {
/* if there was no space and timeout = 0, return with error */
DEBUG("%s pid=%d queue=%p return errQUEUE_FULL\n", __func__,
thread_getpid(), xQueue);
vTaskExitCritical(0);
return errQUEUE_FULL;
}
else {
/* suspend the calling thread to wait for space in the queue */
thread_t *me = (thread_t*)sched_active_thread;
sched_set_status(me, STATUS_SEND_BLOCKED);
/* waiting list is sorted by priority */
thread_add_to_list(&queue->sending, me);
DEBUG("%s pid=%d queue=%p suspended calling thread\n", __func__,
thread_getpid(), xQueue);
vTaskExitCritical(0);
thread_yield_higher();
/* TODO timeout handling with xTicksToWait */
DEBUG("%s pid=%d queue=%p continue calling thread\n", __func__,
thread_getpid(), xQueue);
}
/* in all cases vTaskExitCritical has been called already */
}
return errQUEUE_FULL;
}
BaseType_t IRAM_ATTR _queue_generic_recv (QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait,
const BaseType_t xJustPeeking,
BaseType_t * const pxHigherPriorityTaskWoken)
{
DEBUG("%s pid=%d prio=%d queue=%p wait=%u peek=%u woken=%p isr=%d\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority,
xQueue, xTicksToWait, xJustPeeking, pxHigherPriorityTaskWoken,
irq_is_in());
assert(xQueue != NULL);
_queue_t* queue = (_queue_t*)xQueue;
while (1) {
vTaskEnterCritical(0);
/* if there is at least one item in the queue */
if (queue->item_level > 0) {
/* if the item has no 0 size, copy it from queue to buffer */
if (queue->item_size && queue->item_num && queue->queue && pvBuffer) {
memcpy(pvBuffer,
queue->queue + queue->item_front * queue->item_size,
queue->item_size);
}
/* when only peeking leave the element in queue */
if (xJustPeeking == pdTRUE) {
DEBUG("%s pid=%d queue=%p return pdPASS\n", __func__,
thread_getpid(), xQueue);
vTaskExitCritical(0);
return pdPASS;
}
/* remove element from queue */
queue->item_front = (queue->item_front + 1) % queue->item_num;
queue->item_level--;
/* return if there is no waiting sending thread */
if (queue->sending.next == NULL) {
DEBUG("%s pid=%d queue=%p return pdPASS\n", __func__,
thread_getpid(), xQueue);
vTaskExitCritical(0);
return pdPASS;
}
/* otherwise unlock the waiting sending thread */
list_node_t *next = list_remove_head(&queue->sending);
thread_t *proc = container_of((clist_node_t*)next, thread_t, rq_entry);
sched_set_status(proc, STATUS_PENDING);
/* test whether context switch is required */
bool ctx_switch = proc->priority < sched_threads[thread_getpid()]->priority;
DEBUG("%s pid=%d queue=%p unlock waiting pid=%d switch=%d\n",
__func__, thread_getpid(), xQueue, proc->pid, ctx_switch);
if (ctx_switch && pxHigherPriorityTaskWoken) {
*pxHigherPriorityTaskWoken = pdTRUE;
vTaskExitCritical(0);
}
else if (ctx_switch) {
vTaskExitCritical(0);
/* sets only the sched_context_switch_request in ISRs */
sched_switch(proc->priority);
}
else {
vTaskExitCritical(0);
}
DEBUG("%s pid=%d queue=%p return pdPASS\n", __func__,
thread_getpid(), xQueue);
/* in all cases vTaskExitCritical has been called already */
return pdPASS;
}
else if (xTicksToWait == 0 || irq_is_in()) {
/* if there was no item in the queue and timeout is 0, return with error */
DEBUG("%s pid=%d queue=%p return errQUEUE_EMPTY\n", __func__,
thread_getpid(), xQueue);
vTaskExitCritical(0);
return errQUEUE_EMPTY;
}
else {
/* suspend the calling thread to wait for an item in the queue */
thread_t *me = (thread_t*)sched_active_thread;
sched_set_status(me, STATUS_RECEIVE_BLOCKED);
/* waiting list is sorted by priority */
thread_add_to_list(&queue->receiving, me);
DEBUG("%s pid=%d queue=%p suspended calling thread\n", __func__,
thread_getpid(), xQueue);
vTaskExitCritical(0);
thread_yield_higher();
/* TODO timeout handling with xTicksToWait */
DEBUG("%s pid=%d queue=%p continue calling thread\n", __func__,
thread_getpid(), xQueue);
}
/* in all cases vTaskExitCritical has been called already */
}
}
BaseType_t IRAM_ATTR xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
{
DEBUG("%s pid=%d prio=%d queue=%p wait=%u pos=%d\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority,
xQueue, xTicksToWait, xCopyPosition);
return _queue_generic_send(xQueue, pvItemToQueue, xCopyPosition,
xTicksToWait, NULL);
}
BaseType_t IRAM_ATTR xQueueGenericSendFromISR( QueueHandle_t xQueue,
const void * const pvItemToQueue,
BaseType_t * const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition )
{
DEBUG("%s pid=%d prio=%d queue=%p pos=%d woken=%p\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority,
xQueue, xCopyPosition, pxHigherPriorityTaskWoken);
return _queue_generic_send(xQueue, pvItemToQueue, xCopyPosition,
0, pxHigherPriorityTaskWoken);
}
BaseType_t IRAM_ATTR xQueueGenericReceive (QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait,
const BaseType_t xJustPeeking)
{
DEBUG("%s pid=%d prio=%d queue=%p wait=%u peek=%d\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority,
xQueue, xTicksToWait, xJustPeeking);
return _queue_generic_recv(xQueue, pvBuffer, xTicksToWait,
xJustPeeking, NULL);
}
BaseType_t IRAM_ATTR xQueueReceiveFromISR (QueueHandle_t xQueue,
void * const pvBuffer,
BaseType_t * const pxHigherPriorityTaskWoken)
{
DEBUG("%s pid=%d prio=%d queue=%p woken=%p\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority,
xQueue, pxHigherPriorityTaskWoken);
return _queue_generic_recv(xQueue, pvBuffer, 0,
0, pxHigherPriorityTaskWoken);
}
UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue )
{
assert(xQueue != NULL);
_queue_t* queue = (_queue_t*)xQueue;
return queue->item_level;
}
BaseType_t xQueueGiveFromISR (QueueHandle_t xQueue,
BaseType_t * const pxHigherPriorityTaskWoken)
{
/* this function only satisfies the linker and should not be called */
assert(0);
DEBUG("%s\n", __func__);
return pdFALSE;
}
#endif /* DOXYGEN */

View File

@ -0,0 +1,176 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef DOXYGEN
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <string.h>
#include "esp_common.h"
#include "irq_arch.h"
#include "log.h"
#include "mutex.h"
#include "rmutex.h"
#include "freertos/FreeRTOS.h"
/*
* In FreeRTOS different types of semaphores, mutexes and queues are all
* mapped to a single generic queue type. With all these different types,
* single functions for send, receive, give and take are then used. To be
* able to dsitinguish between these different types in RIOT, we need typed
* objects.
*/
typedef struct {
uint8_t type; /* type of the mutex, MUST be the first element */
mutex_t mutex; /* the mutex */
} _mutex_t;
typedef struct {
uint8_t type; /* type of the mutex, MUST be the first element */
rmutex_t rmutex; /* the mutex */
} _rmutex_t;
SemaphoreHandle_t xSemaphoreCreateMutex(void)
{
_mutex_t* _tmp = (_mutex_t*)malloc (sizeof(_mutex_t));
_tmp->type = queueQUEUE_TYPE_MUTEX;
mutex_init(&_tmp->mutex);
DEBUG("%s mutex=%p\n", __func__, _tmp);
return _tmp;
}
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore )
{
DEBUG("%s mutex=%p\n", __func__, xSemaphore);
assert(xSemaphore != NULL);
free(xSemaphore);
}
BaseType_t xSemaphoreGive (SemaphoreHandle_t xSemaphore)
{
DEBUG("%s mutex=%p\n", __func__, xSemaphore);
assert(xSemaphore != NULL);
uint8_t type = ((_mutex_t*)xSemaphore)->type;
mutex_t* mutex= &((_mutex_t*)xSemaphore)->mutex;
switch (type) {
case queueQUEUE_TYPE_MUTEX:
mutex_unlock(mutex);
break;
case queueQUEUE_TYPE_RECURSIVE_MUTEX:
return xSemaphoreGiveRecursive (xSemaphore);
default:
return xQueueGenericSend(xSemaphore, NULL, 0, queueSEND_TO_BACK);
}
return pdTRUE;
}
BaseType_t xSemaphoreTake (SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait)
{
DEBUG("%s mutex=%p wait=%u\n", __func__, xSemaphore, xTicksToWait);
assert(xSemaphore != NULL);
uint8_t type = ((_mutex_t*)xSemaphore)->type;
mutex_t* mutex= &((_mutex_t*)xSemaphore)->mutex;
switch (type) {
case queueQUEUE_TYPE_MUTEX:
{
if (xTicksToWait == 0) {
return (mutex_trylock(mutex) == 1) ? pdPASS : pdFAIL;
}
else {
mutex_lock(mutex);
/* TODO timeout handling */
return pdTRUE;
}
break;
}
case queueQUEUE_TYPE_RECURSIVE_MUTEX:
return xSemaphoreTakeRecursive (xSemaphore, xTicksToWait);
default:
return xQueueGenericReceive(xSemaphore, NULL, xTicksToWait, pdFALSE);
}
}
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void)
{
_rmutex_t* _tmp = (_rmutex_t*)malloc (sizeof(_rmutex_t));
_tmp->type = queueQUEUE_TYPE_RECURSIVE_MUTEX;
rmutex_init(&_tmp->rmutex);
DEBUG("%s rmutex=%p\n", __func__, _tmp);
return _tmp;
}
BaseType_t xSemaphoreGiveRecursive (SemaphoreHandle_t xSemaphore)
{
DEBUG("%s rmutex=%p\n", __func__, xSemaphore);
assert(xSemaphore != NULL);
assert(((_rmutex_t*)xSemaphore)->type == queueQUEUE_TYPE_RECURSIVE_MUTEX);
rmutex_unlock(&((_rmutex_t*)xSemaphore)->rmutex);
return pdTRUE;
}
BaseType_t xSemaphoreTakeRecursive (SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait)
{
DEBUG("%s rmutex=%p wait=%u\n", __func__, xSemaphore, xTicksToWait);
assert(xSemaphore != NULL);
assert(((_rmutex_t*)xSemaphore)->type == queueQUEUE_TYPE_RECURSIVE_MUTEX);
BaseType_t ret = pdTRUE;
rmutex_t* rmutex = &((_rmutex_t*)xSemaphore)->rmutex;
if (xTicksToWait == 0) {
ret = (rmutex_trylock(rmutex) == 1) ? pdPASS : pdFAIL;
}
else {
rmutex_lock(&((_rmutex_t*)xSemaphore)->rmutex);
/* TODO timeout handling */
}
return ret;
}
void vPortCPUAcquireMutex(portMUX_TYPE *mux)
{
DEBUG("%s pid=%d prio=%d mux=%p\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority, mux);
critical_enter();
mutex_lock(mux); /* lock the mutex with interrupts disabled */
critical_exit();
}
void vPortCPUReleaseMutex(portMUX_TYPE *mux)
{
DEBUG("%s pid=%d prio=%d mux=%p\n", __func__,
thread_getpid(), sched_threads[thread_getpid()]->priority, mux);
critical_enter();
mutex_unlock(mux); /* unlock the mutex with interrupts disabled */
critical_exit();
}
#endif /* DOXYGEN */

226
cpu/esp8266/freertos/task.c Normal file
View File

@ -0,0 +1,226 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef DOXYGEN
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <string.h>
#include "esp_common.h"
#include "esp_attr.h"
#include "log.h"
#include "syscalls.h"
#include "thread.h"
#include "xtimer.h"
#ifdef MCU_ESP32
#include "soc/soc.h"
#endif
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define MHZ 1000000
#ifdef MCU_ESP8266
#include "rom/ets_sys.h"
#define PRO_CPU_NUM (0)
#endif
/**
* @brief Architecture specific data of thread control blocks
*/
typedef struct {
uint32_t saved_int_state;
uint32_t critical_nesting;
} thread_arch_ext_t;
volatile thread_arch_ext_t threads_arch_exts[KERNEL_PID_LAST + 1] = {};
BaseType_t xTaskCreatePinnedToCore (TaskFunction_t pvTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask,
const BaseType_t xCoreID)
{
/* FreeRTOS priority values have to be inverted */
uxPriority = SCHED_PRIO_LEVELS - uxPriority - 1;
DEBUG("%s name=%s size=%d prio=%d pvCreatedTask=%p ",
__func__, pcName, usStackDepth, uxPriority, pvCreatedTask);
char* stack = malloc(usStackDepth + sizeof(thread_t));
if (!stack) {
LOG_TAG_ERROR("freertos", "not enough memory to create task %s with "
"stack size of %d bytes\n", pcName, usStackDepth);
abort();
return pdFALSE;
}
kernel_pid_t pid = thread_create(stack,
usStackDepth + sizeof(thread_t),
uxPriority,
THREAD_CREATE_WOUT_YIELD |
THREAD_CREATE_STACKTEST,
(thread_task_func_t)pvTaskCode,
pvParameters, pcName);
DEBUG("pid=%d\n", pid);
if (pvCreatedTask) {
*pvCreatedTask = (TaskHandle_t)(0L + pid);
}
return (pid < 0) ? pdFALSE : pdTRUE;
}
BaseType_t xTaskCreate (TaskFunction_t pvTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask)
{
return xTaskCreatePinnedToCore (pvTaskCode,
pcName,
usStackDepth,
pvParameters,
uxPriority,
pvCreatedTask,
PRO_CPU_NUM);
}
void vTaskDelete (TaskHandle_t xTaskToDelete)
{
DEBUG("%s pid=%d task=%p\n", __func__, thread_getpid(), xTaskToDelete);
assert(xTaskToDelete != NULL);
uint32_t pid = (uint32_t)xTaskToDelete;
/* remove old task from scheduling */
thread_t* thread = (thread_t*)sched_threads[pid];
sched_set_status(thread, STATUS_STOPPED);
sched_threads[pid] = NULL;
sched_num_threads--;
sched_active_thread = NULL;
/* determine the new running task */
sched_run();
}
TaskHandle_t xTaskGetCurrentTaskHandle(void)
{
DEBUG("%s pid=%d\n", __func__, thread_getpid());
uint32_t pid = thread_getpid();
return (TaskHandle_t)pid;
}
void vTaskDelay( const TickType_t xTicksToDelay )
{
DEBUG("%s xTicksToDelay=%d\n", __func__, xTicksToDelay);
#if defined(MCU_ESP8266) && defined(MODULE_ESP_WIFI_ANY)
uint64_t us = xTicksToDelay * MHZ / xPortGetTickRateHz();
xtimer_usleep(us);
#endif
}
TickType_t xTaskGetTickCount (void)
{
return system_get_time() / USEC_PER_MSEC / portTICK_PERIOD_MS;
}
void vTaskEnterCritical( portMUX_TYPE *mux )
{
#ifdef MCU_ESP8266
/* we have to return on NMI */
if (NMIIrqIsOn) {
return;
}
#endif /* MCU_ESP8266 */
/* disable interrupts */
uint32_t state = irq_disable();
/* determine calling thread pid (can't fail) */
kernel_pid_t my_pid = thread_getpid();
DEBUG("%s pid=%d prio=%d mux=%p\n", __func__,
my_pid, sched_threads[my_pid]->priority, mux);
/* acquire the mutex with interrupts disabled */
if (mux) {
mutex_lock(mux); /* TODO should be only a spin lock */
}
/* increment nesting counter and save old interrupt level */
threads_arch_exts[my_pid].critical_nesting++;
if (threads_arch_exts[my_pid].critical_nesting == 1) {
threads_arch_exts[my_pid].saved_int_state = state;
}
}
void vTaskExitCritical( portMUX_TYPE *mux )
{
#ifdef MCU_ESP8266
/* we have to return on NMI */
if (NMIIrqIsOn) {
return;
}
#endif /* MCU_ESP8266 */
/* determine calling thread pid (can't fail) */
kernel_pid_t my_pid = thread_getpid();
DEBUG("%s pid=%d prio=%d mux=%p\n", __func__,
my_pid, sched_threads[my_pid]->priority, mux);
/* release the mutex with interrupts disabled */
if (mux) {
mutex_unlock(mux); /* TODO should be only a spin lock */
}
/* decrement nesting counter and restore old interrupt level */
if (threads_arch_exts[my_pid].critical_nesting) {
threads_arch_exts[my_pid].critical_nesting--;
if (threads_arch_exts[my_pid].critical_nesting == 0) {
irq_restore(threads_arch_exts[my_pid].saved_int_state);
}
}
}
void vTaskStepTick(const TickType_t xTicksToJump)
{
DEBUG("%s xTicksToJump=%d\n", __func__, xTicksToJump);
/*
* TODO:
* At the moment, only the calling task is set to sleep state. Usually, the
* complete system should sleep but not only the task.
*/
vTaskDelay(xTicksToJump);
}
TickType_t prvGetExpectedIdleTime(void)
{
DEBUG("%s\n", __func__);
/*
* TODO:
* Since we are not able to estimate the time the system will be idle,
* we simply return 0.
*/
return 0;
}
#endif /* DOXYGEN */

View File

@ -0,0 +1,129 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef DOXYGEN
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <string.h>
#include "esp_common.h"
#include "esp_attr.h"
#include "log.h"
#include "xtimer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
typedef struct {
xtimer_t xtimer; /* xtimer object */
const char* name; /* FreeRTOS timer name */
uint32_t period; /* in us */
bool autoreload; /* FreeRTOS timer reload indicator */
const void* timerid; /* FreeRTOS timer id */
TimerCallbackFunction_t cb; /* FreeRTOS callback function */
} freertos_xtimer_t;
static void IRAM_ATTR _xtimer_callback (void *arg)
{
assert(arg != NULL);
freertos_xtimer_t* timer = (freertos_xtimer_t*)arg;
if (timer->autoreload) {
xtimer_set(&timer->xtimer, timer->period);
}
if (timer->cb) {
timer->cb(arg);
}
}
TimerHandle_t xTimerCreate (const char * const pcTimerName,
const TickType_t xTimerPeriod,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction)
{
freertos_xtimer_t* timer = malloc(sizeof(freertos_xtimer_t));
if (timer == NULL) {
return NULL;
}
/* FreeRTOS timer parameter */
timer->name = pcTimerName;
timer->period = xTimerPeriod * portTICK_PERIOD_MS * USEC_PER_MSEC;
timer->autoreload = uxAutoReload;
timer->timerid = pvTimerID;
timer->cb = pxCallbackFunction;
/* xtimer parameter */
timer->xtimer.callback = _xtimer_callback;
timer->xtimer.arg = timer;
DEBUG("%s %p %s %d %u\n", __func__, timer, pcTimerName, xTimerPeriod, uxAutoReload);
return timer;
}
BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xBlockTime)
{
DEBUG("%s %p %d\n", __func__, xTimer, xBlockTime);
assert(xTimer != NULL);
freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer;
xtimer_remove(&timer->xtimer);
free(timer);
return pdTRUE;
}
BaseType_t xTimerStart (TimerHandle_t xTimer, TickType_t xBlockTime)
{
DEBUG("%s %p %d\n", __func__, xTimer, xBlockTime);
assert(xTimer != NULL);
freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer;
xtimer_set(&timer->xtimer, timer->period);
return pdTRUE;
}
BaseType_t xTimerStop (TimerHandle_t xTimer, TickType_t xBlockTime)
{
DEBUG("%s %p %d\n", __func__, xTimer, xBlockTime);
assert(xTimer != NULL);
freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer;
xtimer_remove(&timer->xtimer);
return pdTRUE;
}
BaseType_t xTimerReset (TimerHandle_t xTimer, TickType_t xBlockTime)
{
DEBUG("%s %p %d\n", __func__, xTimer, xBlockTime);
assert(xTimer != NULL);
freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer;
xtimer_set(&timer->xtimer, xBlockTime * portTICK_PERIOD_MS * USEC_PER_MSEC);
return pdTRUE;
}
void *pvTimerGetTimerID(const TimerHandle_t xTimer)
{
assert(xTimer != NULL);
freertos_xtimer_t* timer = (freertos_xtimer_t*)xTimer;
return (void*)timer->timerid;
}
#endif /* DOXYGEN */

View File

@ -1,98 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief Common helper macros
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
*/
#ifndef COMMON_H
#define COMMON_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
/** string representation of x */
#ifndef XTSTR
#define _XTSTR(x) # x
#define XTSTR(x) _XTSTR(x)
#endif
#endif
#if !defined(ICACHE_FLASH) || defined (DOXYGEN)
#ifndef ICACHE_RAM_ATTR
/** Places the code with this attribute in the IRAM. */
#define ICACHE_RAM_ATTR __attribute__((section(".iram.text")))
#endif
#else
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR
#endif
#endif
/** Print out a message that function is not yet implementd */
#define NOT_YET_IMPLEMENTED() LOG_INFO("%s not yet implemented\n", __func__)
/** Print out a message that function is not supported */
#define NOT_SUPPORTED() LOG_INFO("%s not supported\n", __func__)
#if defined(ENABLE_DEBUG) || defined(DOXYGEN)
/**
* @brief Parameter check with return a value.
*
* If ENABLE_DEBUG is true, the macro checks a condition and returns with a value
* if the condition is not fulfilled.
* @param cond the condition
* @param err the return value in the case the condition is not fulfilled.
*/
#define CHECK_PARAM_RET(cond,err) if (!(cond)) \
{ \
DEBUG("%s\n", "parameter condition (" #cond ") not fulfilled"); \
return err; \
}
/**
* @brief Parameter check without return value.
*
* If ENABLE_DEBUG is true, the macro checks a condition and returns without a
* value if the condition is not fulfilled.
* @param cond the condition
*/
#define CHECK_PARAM(cond) if (!(cond)) \
{ \
DEBUG("%s\n", "parameter condition (" #cond ") not fulfilled"); \
return; \
}
#else
#define CHECK_PARAM_RET(cond,err) if (!(cond)) return err;
#define CHECK_PARAM(cond) if (!(cond)) return;
#endif
#define LOG_TAG_ERROR(tag, fmt, ...) LOG_ERROR("[%s] " fmt, tag, ##__VA_ARGS__)
#define LOG_TAG_WARNING(tag, fmt, ...) LOG_WARNING("[%s] " fmt, tag, ##__VA_ARGS__)
#define LOG_TAG_INFO(tag, fmt, ...) LOG_INFO("[%s] " fmt, tag, ##__VA_ARGS__)
#define LOG_TAG_DEBUG(tag, fmt, ...) LOG_DEBUG("[%s] " fmt, tag, ##__VA_ARGS__)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* COMMON_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -29,7 +29,16 @@ extern "C" {
#endif
/**
* @name Stack size configuration
* @brief Defines the CPU frequency in MHz
*
* Possible values are 80 and 160 MHz.
*/
#ifndef ESP8266_CPU_FREQUENCY
#define ESP8266_CPU_FREQUENCY (80)
#endif
/**
* @name Stack size configurations
* @{
*/
#ifndef THREAD_EXTRA_STACKSIZE_PRINTF
@ -49,16 +58,12 @@ extern "C" {
#define GNRC_IPV6_STACK_SIZE (1536)
#endif
#ifndef GNRC_PKTDUMP_STACKSIZE
#define GNRC_PKTDUMP_STACKSIZE (THREAD_STACKSIZE_DEFAULT)
#define GNRC_PKTDUMP_STACKSIZE (THREAD_STACKSIZE_DEFAULT << 1)
#endif
#ifndef ESP_NOW_STACKSIZE
#define ESP_NOW_STACKSIZE (2560)
#endif
#ifndef ETS_THREAD_STACKSIZE
#define ETS_THREAD_STACKSIZE (1536)
#endif
/** @} */
/**
@ -66,16 +71,6 @@ extern "C" {
*/
#define PRINTF_BUFSIZ 256
/* Following include is neccessary to overwrite newlib's PRI*8 and PRI*32. */
/* PLEASE NOTE: ets_vprintf does not understand %i %li, or %hi */
#ifndef DOXYGEN
#include <inttypes.h>
#undef __INT8
#define __INT8
#undef __INT32
#define __INT32
#endif
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,130 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief Common helper macros
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
*/
#ifndef ESP_COMMON_H
#define ESP_COMMON_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
#include "log.h"
#include "esp_common_log.h"
#define asm __asm__
/** string representation of x */
#ifndef XTSTR
#define _XTSTR(x) # x
#define XTSTR(x) _XTSTR(x)
#endif /* XSTR */
#if !defined(ICACHE_FLASH)
#ifndef ICACHE_RAM_ATTR
/** Places the code with this attribute in the IRAM. */
#define ICACHE_RAM_ATTR __attribute__((section(".iram0.text")))
#endif
#else /* ICACHE_FLASH */
#ifndef ICACHE_RAM_ATTR
#define ICACHE_RAM_ATTR
#endif
#endif /* ICACHE_FLASH */
/** Print out a message that function is not yet implementd */
#define NOT_YET_IMPLEMENTED() LOG_INFO("%s not yet implemented\n", __func__)
/** Print out a message that function is not supported */
#define NOT_SUPPORTED() LOG_INFO("%s not supported\n", __func__)
#if ENABLE_DEBUG
/**
* @brief Parameter check with return a value.
*
* If ENABLE_DEBUG is true, the macro checks a condition and returns with a value
* if the condition is not fulfilled.
* @param cond the condition
* @param err the return value in the case the condition is not fulfilled.
*/
#define CHECK_PARAM_RET(cond,err) if (!(cond)) \
{ \
DEBUG("%s parameter condition (" #cond ") " \
"not fulfilled\n", __func__); \
return err; \
}
/**
* @brief Parameter check without return value.
*
* If ENABLE_DEBUG is true, the macro checks a condition and returns without a
* value if the condition is not fulfilled.
* @param cond the condition
*/
#define CHECK_PARAM(cond) if (!(cond)) \
{ \
DEBUG("%s parameter condition (" #cond ") " \
"not fulfilled\n", __func__); \
return; \
}
#else /* ENABLE_DEBUG */
#define CHECK_PARAM_RET(cond,err) if (!(cond)) return err;
#define CHECK_PARAM(cond) if (!(cond)) return;
#endif /* ENABLE_DEBUG */
/** gives the minimum of a and b */
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/** gives the maximum of a and b */
#ifndef MAX
#define MAX(a,b) ((a) > (b) ? (a) : (b))
#endif
/**
* @brief function name mappings for source code compatibility with ESP8266 port
* @{
*/
#ifdef MCU_ESP32
#define system_get_cpu_freq ets_get_cpu_frequency
#define system_update_cpu_freq ets_update_cpu_frequency
#endif /* MCU_ESP32 */
/** @} */
/** @} */
/** microseconds per millisecond */
#ifndef USEC_PER_MSEC
#define USEC_PER_MSEC 1000UL
#endif
#ifndef MSEC_PER_SEC
#define MSEC_PER_SEC 1000UL
#endif
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* ESP_COMMON_H */

View File

@ -0,0 +1,150 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief Common log macros
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
*/
#ifndef ESP_COMMON_LOG_H
#define ESP_COMMON_LOG_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
#include "log.h"
extern uint32_t system_get_time_ms (void);
extern int ets_printf(const char *fmt, ...);
#if MODULE_ESP_LOG_COLORED
#define LOG_RESET_COLOR "\033[0m"
#define LOG_COLOR_E "\033[1;31m"
#define LOG_COLOR_W "\033[1;33m"
#define LOG_COLOR_I "\033[1m"
#define LOG_COLOR_D "\033[0;32m"
#define LOG_COLOR_V
#else /* MODULE_ESP_LOG_COLORED */
#define LOG_RESET_COLOR
#define LOG_COLOR_E
#define LOG_COLOR_W
#define LOG_COLOR_I
#define LOG_COLOR_D
#define LOG_COLOR_V
#endif /* MODULE_ESP_LOG_COLORED */
#if MODULE_ESP_LOG_TAGGED
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter #letter " (%d) [%s] " format LOG_RESET_COLOR
#define LOG_TAG(level, letter, tag, format, ...) \
do { \
if ((unsigned)level <= (unsigned)LOG_LEVEL) { \
printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \
fflush(stdout); \
} \
} while(0)
#define LOG_TAG_EARLY(level, letter, tag, format, ...) \
do { \
if (LOG_LEVEL >= level) { \
ets_printf(LOG_FORMAT(letter, format), system_get_time_ms(), tag, ##__VA_ARGS__); \
} \
} while(0)
#else /* MODULE_ESP_LOG_TAGGED */
#define LOG_FORMAT(letter, format) LOG_COLOR_ ## letter format LOG_RESET_COLOR
#define LOG_TAG(level, letter, tag, format, ...) \
do { \
(void)tag; \
if ((unsigned)level <= (unsigned)LOG_LEVEL) { \
printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \
fflush(stdout); \
} \
} while (0U)
#define LOG_TAG_EARLY(level, letter, tag, format, ...) \
do { \
(void)tag; \
if ((unsigned)level <= (unsigned)LOG_LEVEL) { \
ets_printf(LOG_FORMAT(letter, format), ##__VA_ARGS__); \
} \
} while (0U)
#endif /* MODULE_ESP_LOG_TAGGED */
/**
* Override LOG_* definitions with a tagged version. By default the function
* name is used as tag.
*/
#ifndef MODULE_LOG_PRINTFNOFORMAT
#undef LOG_ERROR
#undef LOG_INFO
#undef LOG_WARNING
#undef LOG_DEBUG
#define LOG_ERROR(format, ...) LOG_TAG(LOG_ERROR , E, __func__, format, ##__VA_ARGS__)
#define LOG_WARNING(format, ...) LOG_TAG(LOG_WARNING, W, __func__, format, ##__VA_ARGS__)
#define LOG_INFO(format, ...) LOG_TAG(LOG_INFO , I, __func__, format, ##__VA_ARGS__)
#define LOG_DEBUG(format, ...) LOG_TAG(LOG_DEBUG , D, __func__, format, ##__VA_ARGS__)
#endif
/** Tagged LOG_* definitions */
#define LOG_TAG_ERROR(tag, format, ...) LOG_TAG(LOG_ERROR , E, tag, format, ##__VA_ARGS__)
#define LOG_TAG_WARNING(tag, format, ...) LOG_TAG(LOG_WARNING, W, tag, format, ##__VA_ARGS__)
#define LOG_TAG_INFO(tag, format, ...) LOG_TAG(LOG_INFO , I, tag, format, ##__VA_ARGS__)
#define LOG_TAG_DEBUG(tag, format, ...) LOG_TAG(LOG_DEBUG , D, tag, format, ##__VA_ARGS__)
/** definitions for source code compatibility with ESP-IDF */
#define ESP_EARLY_LOGE(tag, format, ...) LOG_TAG_EARLY(LOG_ERROR , E, tag, format "\n", ##__VA_ARGS__)
#define ESP_EARLY_LOGW(tag, format, ...) LOG_TAG_EARLY(LOG_WARNING, W, tag, format "\n", ##__VA_ARGS__)
#define ESP_EARLY_LOGI(tag, format, ...) LOG_TAG_EARLY(LOG_INFO , I, tag, format "\n", ##__VA_ARGS__)
#define ESP_LOGE(tag, format, ...) LOG_TAG(LOG_ERROR , E, tag, format "\n", ##__VA_ARGS__)
#define ESP_LOGW(tag, format, ...) LOG_TAG(LOG_WARNING, W, tag, format "\n", ##__VA_ARGS__)
#define ESP_LOGI(tag, format, ...) LOG_TAG(LOG_INFO , I, tag, format "\n", ##__VA_ARGS__)
#if ENABLE_DEBUG
#define ESP_EARLY_LOGD(tag, format, ...) LOG_TAG_EARLY(LOG_DEBUG, D, tag, format "\n", ##__VA_ARGS__)
#define ESP_EARLY_LOGV(tag, format, ...) LOG_TAG_EARLY(LOG_ALL , V, tag, format "\n", ##__VA_ARGS__)
#define ESP_LOGD(tag, format, ...) LOG_TAG(LOG_DEBUG, D, tag, format "\n", ##__VA_ARGS__)
#define ESP_LOGV(tag, format, ...) LOG_TAG(LOG_ALL , V, tag, format "\n", ##__VA_ARGS__)
#else /* ENABLE_DEBUG */
#define ESP_EARLY_LOGD( tag, format, ... ) (void)tag
#define ESP_EARLY_LOGV( tag, format, ... ) (void)tag
#define ESP_LOGD( tag, format, ... ) (void)tag
#define ESP_LOGV( tag, format, ... ) (void)tag
#endif /* ENABLE_DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* ESP_COMMON_LOG_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -24,7 +24,7 @@
extern "C" {
#endif
/** Initalize exception handler */
/** Initialize exception handler */
extern void init_exceptions(void);
#ifdef __cplusplus

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_FREERTOS_H
#define FREERTOS_FREERTOS_H
#ifndef DOXYGEN
#include "freertos/portmacro.h"
#ifdef __cplusplus
extern "C" {
#endif
#define configMAX_PRIORITIES SCHED_PRIO_LEVELS
#ifndef configASSERT
#define configASSERT assert
#endif
#define portTICK_PERIOD_MS 10
#define portTickType TickType_t
#define portTICK_RATE_MS portTICK_PERIOD_MS
#define BaseType_t portBASE_TYPE
#define UBaseType_t unsigned portBASE_TYPE
typedef uint32_t TickType_t;
uint32_t xPortGetTickRateHz(void);
BaseType_t xPortInIsrContext(void);
/*
* PLEASE NOTE: Following definitions were copied directly from the FreeRTOS
* distribution and are under the following copyright:
*
* FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
* All rights reserved
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
* Full license text is available on the following
* link: http://www.freertos.org/a00114.html
*/
#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )
#define pdPASS ( pdTRUE )
#define pdFAIL ( pdFALSE )
#ifdef __cplusplus
}
#endif
#include "freertos/semphr.h"
#include "freertos/queue.h"
#endif /* DOXYGEN */
#endif /* FREERTOS_FREERTOS_H */

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_EVENT_GROUPS_H
#define FREERTOS_EVENT_GROUPS_H
#ifndef DOXYGEN
#include "freertos/FreeRTOS.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void * EventGroupHandle_t;
typedef TickType_t EventBits_t;
EventGroupHandle_t xEventGroupCreate (void);
void vEventGroupDelete (EventGroupHandle_t xEventGroup);
EventBits_t xEventGroupSetBits (EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet);
EventBits_t xEventGroupClearBits (EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToClear );
EventBits_t xEventGroupWaitBits (const EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait);
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* FREERTOS_EVENT_GROUPS_H */

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_PORTMACRO_H
#define FREERTOS_PORTMACRO_H
#ifndef DOXYGEN
#include "stdint.h"
#include "mutex.h"
#include "irq.h"
#ifdef __cplusplus
extern "C" {
#endif
#define portBASE_TYPE int
#define portUBASE_TYPE unsigned portBASE_TYPE
#define portMAX_DELAY 0xFFFFFFFF
#define portMUX_TYPE mutex_t
#define portMUX_INITIALIZER_UNLOCKED MUTEX_INIT
#define portYIELD_FROM_ISR thread_yield_higher
#ifdef MCU_ESP32
#define portNUM_PROCESSORS 2
#define xPortGetCoreID() PRO_CPU_NUM
#define portENTER_CRITICAL(pm) mutex_lock(pm)
#define portEXIT_CRITICAL(pm) mutex_unlock(pm)
#define portENTER_CRITICAL_NESTED irq_disable
#define portEXIT_CRITICAL_NESTED irq_restore
#define portENTER_CRITICAL_ISR vTaskEnterCritical
#define portEXIT_CRITICAL_ISR vTaskExitCritical
#else /* MCU_ESP32 */
#define portNUM_PROCESSORS 1
#define xPortGetCoreID() PRO_CPU_NUM
#define portENTER_CRITICAL vTaskEnterCritical
#define portEXIT_CRITICAL vTaskExitCritical
#endif /* MCU_ESP32 */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* FREERTOS_PORTMACRO_H */

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_QUEUE_H
#define FREERTOS_QUEUE_H
#ifndef DOXYGEN
#include "freertos/FreeRTOS.h"
#ifdef __cplusplus
extern "C" {
#endif
#define xQueueHandle QueueHandle_t
typedef void* QueueHandle_t;
QueueHandle_t xQueueGenericCreate (const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType);
QueueHandle_t xQueueCreateCountingSemaphore (const UBaseType_t uxMaxCount,
const UBaseType_t uxInitialCount);
void vQueueDelete (QueueHandle_t xQueue);
BaseType_t xQueueGenericReset (QueueHandle_t xQueue, BaseType_t xNewQueue);
BaseType_t xQueueGenericReceive (QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait,
const BaseType_t xJustPeeking);
BaseType_t xQueueGenericSend (QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition);
BaseType_t xQueueReceiveFromISR (QueueHandle_t xQueue, void * const pvBuffer,
BaseType_t * const pxHigherPriorityTaskWoken);
BaseType_t xQueueGenericSendFromISR (QueueHandle_t xQueue,
const void * const pvItemToQueue,
BaseType_t * const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition );
BaseType_t xQueueGiveFromISR (QueueHandle_t xQueue,
BaseType_t * const pxHigherPriorityTaskWoken);
UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );
/*
* PLEASE NOTE: Following definitions were copied directly from the FreeRTOS
* distribution and are under the following copyright:
*
* FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
* All rights reserved
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
* Full license text is available on the following
* link: http://www.freertos.org/a00114.html
*/
#define queueSEND_TO_BACK ( ( BaseType_t ) 0 )
#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 )
#define queueOVERWRITE ( ( BaseType_t ) 2 )
#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U )
#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U )
#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U )
#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U )
#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U )
#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U )
#define errQUEUE_EMPTY ( ( BaseType_t ) 0 )
#define errQUEUE_FULL ( ( BaseType_t ) 0 )
#define errQUEUE_BLOCKED ( -4 )
#define errQUEUE_YIELD ( -5 )
#define xQueueCreate( uxQueueLength, uxItemSize ) \
xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) )
#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) \
xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), \
pdFALSE )
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), \
queueSEND_TO_BACK )
#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), \
queueSEND_TO_BACK )
#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \
xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), \
( pxHigherPriorityTaskWoken ), \
queueSEND_TO_BACK )
#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE )
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* FREERTOS_QUEUE_H */

View File

@ -0,0 +1,81 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_SEMPHR_H
#define FREERTOS_SEMPHR_H
#ifndef DOXYGEN
#include "freertos/FreeRTOS.h"
#include <stdlib.h>
#include "mutex.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void* SemaphoreHandle_t;
SemaphoreHandle_t xSemaphoreCreateMutex(void);
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void);
void vSemaphoreDelete (SemaphoreHandle_t xSemaphore);
BaseType_t xSemaphoreGive (SemaphoreHandle_t xSemaphore);
BaseType_t xSemaphoreTake (SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait);
BaseType_t xSemaphoreGiveRecursive (SemaphoreHandle_t xSemaphore);
BaseType_t xSemaphoreTakeRecursive (SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait);
#define vPortCPUInitializeMutex(m) mutex_init(m)
void vPortCPUAcquireMutex (portMUX_TYPE *mux);
void vPortCPUReleaseMutex (portMUX_TYPE *mux);
/*
* PLEASE NOTE: Following definitions were copied directly from the FreeRTOS
* distribution and are under the following copyright:
*
* FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
* All rights reserved
*
* FreeRTOS is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License (version 2) as published by the
* Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
*
* Full license text is available on the following
* link: http://www.freertos.org/a00114.html
*/
#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U )
#define xSemaphoreCreateBinary() \
xQueueGenericCreate( ( UBaseType_t ) 1, \
semSEMAPHORE_QUEUE_ITEM_LENGTH, \
queueQUEUE_TYPE_BINARY_SEMAPHORE )
#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) \
xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \
xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), \
NULL, ( pxHigherPriorityTaskWoken ) )
#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) \
xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), \
( pxHigherPriorityTaskWoken ) )
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* FREERTOS_SEMPHR_H */

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_TASK_H
#define FREERTOS_TASK_H
#ifndef DOXYGEN
#include "thread.h"
#ifdef __cplusplus
extern "C" {
#endif
#define xTaskHandle TaskHandle_t
#define tskNO_AFFINITY INT_MAX
#define taskDISABLE_INTERRUPTS portDISABLE_INTERRUPTS
#define taskENABLE_INTERRUPTS portENABLE_INTERRUPTS
#define taskENTER_CRITICAL portENTER_CRITICAL
#define taskEXIT_CRITICAL portEXIT_CRITICAL
typedef void (*TaskFunction_t)(void *);
typedef void* TaskHandle_t;
BaseType_t xTaskCreate(TaskFunction_t pvTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask);
BaseType_t xTaskCreatePinnedToCore(TaskFunction_t pvTaskCode,
const char * const pcName,
const uint32_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pvCreatedTask,
const BaseType_t xCoreID);
void vTaskDelete(TaskHandle_t xTaskToDelete);
void vTaskDelay(const TickType_t xTicksToDelay);
TaskHandle_t xTaskGetCurrentTaskHandle(void);
void vTaskEnterCritical(portMUX_TYPE *mux);
void vTaskExitCritical(portMUX_TYPE *mux);
TickType_t xTaskGetTickCount (void);
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* FREERTOS_TASK_H */

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_TIMERS_H
#define FREERTOS_TIMERS_H
#ifndef DOXYGEN
#include "freertos/FreeRTOS.h"
#include "xtimer.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void* TimerHandle_t;
#define TimerCallbackFunction_t xtimer_callback_t
#define tmrTIMER_CALLBACK TimerCallbackFunction_t
TimerHandle_t xTimerCreate (const char * const pcTimerName,
const TickType_t xTimerPeriod,
const UBaseType_t uxAutoReload,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction);
BaseType_t xTimerDelete(TimerHandle_t xTimer, TickType_t xBlockTime);
BaseType_t xTimerStart (TimerHandle_t xTimer, TickType_t xBlockTime);
BaseType_t xTimerStop (TimerHandle_t xTimer, TickType_t xBlockTime);
BaseType_t xTimerReset (TimerHandle_t xTimer, TickType_t xTicksToWait);
void *pvTimerGetTimerID(const TimerHandle_t xTimer);
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* FREERTOS_TIMERS_H */

View File

@ -0,0 +1,24 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* FreeRTOS to RIOT-OS adaption module for source code compatibility
*/
#ifndef FREERTOS_XTENSA_API_H
#define FREERTOS_XTENSA_API_H
#include "xtensa/xtensa_api.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
#endif /* FREERTOS_XTENSA_API_H */

View File

@ -0,0 +1,142 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief Architecture specific GPIO functions for ESP8266
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef GPIO_ARCH_H
#define GPIO_ARCH_H
#ifdef MCU_ESP32
#include "periph/gpio.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"
#endif /* MCU_ESP32 */
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
/** Definitions for source code compatibility with ESP-IDF */
#define GPIO_MODE_INPUT GPIO_IN
#define GPIO_MODE_OUTPUT GPIO_OUT
#define GPIO_MODE_INPUT_OUTPUT GPIO_IN_OUT
/** Definition of possible GPIO usage types (for internal use only) */
typedef enum
{
_GPIO = 0, /**< pin used as standard GPIO */
#ifdef MCU_ESP32
_ADC, /**< pin used as ADC input */
_CAN, /**< pin used as CAN signal */
_DAC, /**< pin used as DAC output */
_EMAC, /**< pin used as EMAC signal */
#endif /* MCU_ESP32 */
_I2C, /**< pin used as I2C signal */
_PWM, /**< pin used as PWM output */
_SPI, /**< pin used as SPI interface */
_SPIF, /**< pin used as SPI flash interface */
_UART, /**< pin used as UART interface */
_NOT_EXIST /**< pin cannot be used at all */
} gpio_pin_usage_t;
#ifdef MCU_ESP32
/** Table of GPIO to IOMUX register mappings */
extern const uint32_t _gpio_to_iomux_reg[];
#define GPIO_PIN_MUX_REG _gpio_to_iomux_reg
#else /* MCU_ESP32 */
/** Map of GPIO pin numbers to IOMUX pin numbers */
extern const uint8_t _gpio_to_iomux[];
/** Map of IOMUX pin numbers to GPIO pin numbers */
extern const uint8_t _iomux_to_gpio[];
#endif /* MCU_ESP32 */
/**
* @brief Set the usage type of the pin
* @param pin GPIO pin
* @param usage GPIO pin usage type
* @return 0 on success
* -1 on error
*/
int gpio_set_pin_usage(gpio_t pin, gpio_pin_usage_t usage);
/**
* @brief Get the usage type of the pin
* @param pin GPIO pin
* @return GPIO pin usage type on success
* _NOT_EXIST on error
*/
gpio_pin_usage_t gpio_get_pin_usage(gpio_t pin);
/**
* @brief Get the usage type of the pin as string
* @param pin GPIO pin
* @return GPIO pin usage type string on success
* _NOT_EXIST on error
*/
const char* gpio_get_pin_usage_str(gpio_t pin);
#ifdef MCU_ESP32
/**
* @brief Disable the pullup of the pin
*/
void gpio_pullup_dis (gpio_t pin);
/**
* @brief Returns the RTCIO pin number or -1 if the pin is not an RTCIO pin
*/
int8_t gpio_is_rtcio (gpio_t pin);
/**
* @brief Configure sleep mode for an GPIO pin if the pin is an RTCIO pin
* @param pin GPIO pin
* @param mode active in sleep mode if true
* @param input as input if true, as output otherwise
* @return 0 on success
* @return -1 on invalid pin
*/
int gpio_config_sleep_mode (gpio_t pin, bool sleep_mode, bool input);
/**
* @brief GPIO set direction init the pin calling gpio_init
* @param pin GPIO pin
* @param mode active in sleep mode if true
* @return 0 on success
* -1 on invalid argument
*/
int gpio_set_direction(gpio_t pin, gpio_mode_t mode);
/**
* @brief extern declaration of ROM functions to avoid compilation problems
*/
void gpio_matrix_in (uint32_t gpio, uint32_t signal_idx, bool inv);
void gpio_matrix_out(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv);
#endif /* MCU_ESP32 */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* GPIO_ARCH_H */

View File

@ -1,54 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief Low-level GPIO driver implementation for ESP8266
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef GPIO_COMMON_H
#define GPIO_COMMON_H
#ifdef __cplusplus
extern "C" {
#endif
/** Map of GPIO pin numbers to IOMUX pin numbers */
extern const uint8_t _gpio_to_iomux[];
/** Map of IOMUX pin numbers to GPIO pin numbers */
extern const uint8_t _iomux_to_gpio[];
/**
* @brief Definition of possible GPIO usage types
*/
typedef enum
{
_GPIO = 0, /**< pin used as standard GPIO */
_I2C, /**< pin used as I2C signal */
_PWM, /**< pin used as PWM output */
_SPI, /**< pin used as SPI interface */
_SPIF, /**< pin used as SPI flash interface */
_UART, /**< pin used as UART interface */
} _gpio_pin_usage_t;
/**
* Holds the usage type of each GPIO pin
*/
extern _gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF];
#ifdef __cplusplus
}
#endif
#endif /* GPIO_COMMON_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -39,9 +39,8 @@ extern uint32_t irq_interrupt_nesting;
/**
* @name Macros to enter and exit an ISR
*
* In non-SDK interrupt handling all stuff is done in `_frxt_int_enter`
* and `_frxt_int_exit`. These macros do therefore nothing and are kept only
* for source code compatibility.
* Since all the stuff is done in `_frxt_int_enter` and `_frxt_int_exit`, these
* macros are doing nothing and are kept only for source code compatibility.
*
* @{
*/
@ -56,10 +55,28 @@ extern uint32_t irq_interrupt_nesting;
*
* @{
*/
#define critical_enter() int _irq_state = irq_disable ()
#define critical_enter() int _irq_state = irq_disable()
#define critical_exit() irq_restore(_irq_state)
/** @} */
/**
* @name Macros to enter and exit a critical region with state variable
* @{
*/
#define critical_enter_var(m) m = irq_disable()
#define critical_exit_var(m) irq_restore(m)
/** @} */
/**
* @name Software interrupt types
*
* These definitions are used to distinguish different types of software
* interrupts in software interrupt handler.
*/
#define ETS_SOFT_INT_NONE 0
#define ETS_SOFT_INT_YIELD 1
#define ETS_SOFT_INT_HDL_MAC 2
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief Log module to realize consistent log messages
*
* @author Gunar Schorcht <gunar@schorcht.net>
*/
#ifndef LOG_MODULE_H
#define LOG_MODULE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include "esp_common_log.h"
#ifdef MODULE_LOG_PRINTFNOFORMAT
static inline void log_write(unsigned level, const char *format, ...) {
(void)level;
puts(format);
}
#else /* MODULE_LOG_PRINTFNOFORMAT */
#define log_write(level, ...) \
do { \
if (level == LOG_ERROR) { \
LOG_TAG(LOG_ERROR, E, __func__, ##__VA_ARGS__); \
} \
else if (level == LOG_WARNING) { \
LOG_TAG(LOG_WARNING, W, __func__, ##__VA_ARGS__); \
} \
else if (level == LOG_INFO) { \
LOG_TAG(LOG_INFO, D, __func__, ##__VA_ARGS__); \
} \
else if (level == LOG_DEBUG) { \
LOG_TAG(LOG_DEBUG, E, __func__, ##__VA_ARGS__); \
} \
} while (0)
#endif /* MODULE_LOG_PRINTFNOFORMAT */
#ifdef __cplusplus
}
#endif
/**@}*/
#endif /* LOG_MODULE_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -33,31 +33,55 @@ extern "C" {
#define CPUID_LEN (4U)
/**
* @name GPIO configuration of ESP8266
* @name GPIO configuration
* @{
*/
/**
* @brief Available ports on the ESP8266
* @brief Override the default gpio_t type definition
*
* This is required here to have gpio_t defined in this file.
* @{
*/
#define PORT_GPIO 0 /**< port GPIO */
#define HAVE_GPIO_T
typedef unsigned int gpio_t;
/** @} */
/**
* @brief Definition of a fitting UNDEF value
*/
#define GPIO_UNDEF (GPIO_ID_NONE)
#define GPIO_UNDEF ((gpio_t)(UINT_MAX))
/**
* @brief Define CPU specific GPIO pin generator macro
* @brief Define a CPU specific GPIO pin generator macro
*/
#define GPIO_PIN(x, y) ((x << 4) | y)
#define GPIO_PIN(x, y) ((x & 0) | y)
/**
* @brief Available GPIO ports on ESP8266
*/
#define PORT_GPIO (0)
/**
* @brief Define CPU specific number of GPIO pins
*/
#define GPIO_PIN_NUMOF GPIO_PIN_COUNT+1
#define GPIO_PIN_NUMOF (17)
/**
* @brief Override flank selection values
* @{
*/
#define HAVE_GPIO_FLANK_T
typedef enum {
GPIO_NONE = 0,
GPIO_RISING = 1, /**< emit interrupt on rising flank */
GPIO_FALLING = 2, /**< emit interrupt on falling flank */
GPIO_BOTH = 3, /**< emit interrupt on both flanks */
GPIO_LOW = 4, /**< emit interrupt on low level */
GPIO_HIGH = 5 /**< emit interrupt on low level */
} gpio_flank_t;
/** @} */
/** @} */
/**
* @name Predefined GPIO names
@ -82,51 +106,64 @@ extern "C" {
#define GPIO16 (GPIO_PIN(PORT_GPIO,16))
/** @} */
#ifndef DOXYGEN
#define GPIO0_MASK (BIT(0))
#define GPIO1_MASK (BIT(1))
#define GPIO2_MASK (BIT(2))
#define GPIO3_MASK (BIT(3))
#define GPIO4_MASK (BIT(4))
#define GPIO5_MASK (BIT(5))
#define GPIO6_MASK (BIT(6))
#define GPIO7_MASK (BIT(7))
#define GPIO8_MASK (BIT(8))
#define GPIO9_MASK (BIT(9))
#define GPIO10_MASK (BIT(10))
#define GPIO11_MASK (BIT(11))
#define GPIO12_MASK (BIT(12))
#define GPIO13_MASK (BIT(13))
#define GPIO14_MASK (BIT(14))
#define GPIO15_MASK (BIT(15))
#define GPIO16_MASK (BIT(16))
/**
* @brief Override flank selection values
* @{
*/
#define HAVE_GPIO_FLANK_T
typedef enum {
GPIO_NONE = 0,
GPIO_RISING = 1, /**< emit interrupt on rising flank */
GPIO_FALLING = 2, /**< emit interrupt on falling flank */
GPIO_BOTH = 3, /**< emit interrupt on both flanks */
GPIO_LOW = 4, /**< emit interrupt on low level */
GPIO_HIGH = 5 /**< emit interrupt on low level */
} gpio_flank_t;
/** @} */
#endif /* DOXYGEN */
/** @} */
/**
* @name I2C configuration
*
* ESP8266 provides up to two bit-banging I2C interfaces.
*
* The board-specific configuration of the I2C interface I2C_DEV(n) requires
* the definition of
*
* I2Cn_SPEED, the bus speed,
* I2Cn_SCL, the GPIO used as SCL signal, and
* I2Cn_SDA, the GPIO used as SDA signal,
*
* where n can be 0 or 1. If they are not defined, the I2C interface
* I2C_DEV(n) is not used.
*
* @note The configuration of the I2C interfaces I2C_DEV(n) must be in
* continuous ascending order of n.
*
* I2C_NUMOF is determined automatically from board-specific peripheral
* definitions of I2Cn_SPEED, I2Cn_SCK, and I2Cn_SDA.
*
* @{
*/
#define PERIPH_I2C_NEED_READ_REG
#define PERIPH_I2C_NEED_READ_REGS
#define PERIPH_I2C_NEED_WRITE_REG
#define PERIPH_I2C_NEED_WRITE_REGS
/**
* @brief Override I2C clock speed values
*
* This is required here to have i2c_speed_t defined in this file.
* @{
*/
#define HAVE_I2C_SPEED_T
typedef enum {
I2C_SPEED_LOW = 0, /**< 10 kbit/s */
I2C_SPEED_NORMAL, /**< 100 kbit/s */
I2C_SPEED_FAST, /**< 400 kbit/s */
I2C_SPEED_FAST_PLUS, /**< 1 Mbit/s */
I2C_SPEED_HIGH, /**< not supported */
} i2c_speed_t;
/** @} */
/**
* @brief I2C configuration structure type
*/
typedef struct {
i2c_speed_t speed; /**< I2C bus speed */
gpio_t scl; /**< GPIO used as SCL pin */
gpio_t sda; /**< GPIO used as SDA pin */
} i2c_conf_t;
/**
* @brief Maximum number of I2C interfaces that can be used by board definitions
*/
#define I2C_NUMOF_MAX (2)
#define PERIPH_I2C_NEED_READ_REG /**< i2c_read_reg required */
#define PERIPH_I2C_NEED_READ_REGS /**< i2c_read_regs required */
#define PERIPH_I2C_NEED_WRITE_REG /**< i2c_write_reg required */
#define PERIPH_I2C_NEED_WRITE_REGS /**< i2c_write_regs required */
/** @} */
/**
@ -139,24 +176,114 @@ typedef enum {
/** @} */
/**
* @name SPI configuration
* @name PWM configuration
*
* The hardware implementation of ESP8266 PWM supports only frequencies as
* power of two. Therefore a software implementation of one PWM device
* PWM_DEV(0) with up to 8 PWM channels (#PWM_CHANNEL_NUM_MAX) is used. The
* GPIOs that can be used as PWM channels are defined by #PWM0_GPIOS in board
* definition.
*
* @note The minimum PWM period that can be realized is 10 us or 100.000 PWM
* clock cycles per second. Therefore, the product of frequency and resolution
* should not be greater than 100.000. Otherwise the frequency is scaled down
* automatically.
*
* @{
*/
#if defined(MODULE_PERIPH_SPI)
#define PERIPH_SPI_NEEDS_TRANSFER_BYTE
#define PERIPH_SPI_NEEDS_TRANSFER_REG
#define PERIPH_SPI_NEEDS_TRANSFER_REGS
/**
* @brief Maximum number of PWM devices.
*/
#define PWM_NUMOF_MAX (1)
#endif /* MODULE_PERIPH_SPI */
/**
* @brief Maximum number of channels per PWM device.
*/
#define PWM_CHANNEL_NUM_MAX (8)
/** @} */
/**
* @name SPI configuration
*
* ESP8266 has two SPI controllers:
*
* - _CSPI_ for caching and accessing the flash memory<br>
* - _HSPI_ for peripherals
*
* Thus, _HSPI_ is the only SPI interface that is available for peripherals.
* It is exposed as RIOT's SPI_DEV(0). The pin configuration of the _HSPI_
* interface is fixed as shown in following table.
*
* Signal | Pin
* -- --------|-------
* #SPI0_MISO | GPIO12
* #SPI0_MOSI | GPIO13
* #SPI0_SCK | GPIO14
* #SPI0_CS0 | GPIOn with n = 0, 2, 4, 5, 15, 16 (additionally 9, 10 in DOUT flash mode)
*
* The only pin definition that can be overridden by an application-specific
* board configuration is the CS signal defined by #SPI0_CS0.
*
* @{
*/
/**
* @brief SPI controllers that can be used for peripheral interfaces
*/
typedef enum {
HSPI = 1, /**< HSPI interface controller */
} spi_ctrl_t;
/**
* @brief SPI configuration structure type
*/
typedef struct {
spi_ctrl_t ctrl; /**< SPI controller used for the interface */
gpio_t sck; /**< GPIO used as SCK pin */
gpio_t mosi; /**< GPIO used as MOSI pin */
gpio_t miso; /**< GPIO used as MISO pin */
gpio_t cs; /**< GPIO used as CS0 pin */
} spi_conf_t;
/**
* @brief Maximum number of SPI interfaces
*/
#define SPI_NUMOF_MAX (1)
#define PERIPH_SPI_NEEDS_TRANSFER_BYTE /**< requires function spi_transfer_byte */
#define PERIPH_SPI_NEEDS_TRANSFER_REG /**< requires function spi_transfer_reg */
#define PERIPH_SPI_NEEDS_TRANSFER_REGS /**< requires function spi_transfer_regs */
/** @} */
/**
* @brief Prevent shared timer functions from being used
*/
#define PERIPH_TIMER_PROVIDES_SET
/**
* @name UART configuration
*
* All ESP8266 boards have exactly one UART device with fixed pin mapping.
*
* @{
*/
/**
* @brief UART configuration structure type
*/
typedef struct {
gpio_t txd; /**< GPIO used as TxD pin */
gpio_t rxd; /**< GPIO used as RxD pin */
} uart_conf_t;
/**
* @brief Maximum number of UART interfaces
*/
#define UART_NUMOF_MAX (1)
/** @} */
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief SDK configuration compatible to the ESP-IDF
*
* This file defines configuration parameters that are only required for source
* code compatibility with the SDK. These configuration parameters are not used
* directly to configure the compilation of RIOT-OS. However, some of them can
* be overrien overridden by application-specific board configuration.
*
* @author Gunar Schorcht <gunar@schorcht.net>
*/
#ifndef SDK_CONF_H
#define SDK_CONF_H
#ifndef DOXYGEN
#include "board.h"
#include "esp_image_format.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief SDK version number
*
* Determined with `git describe --tags` in `$ESP8266_SDK_DIR`
*/
#define IDF_VER "v3.1-4-g08c234e"
/**
* @name Default console configuration
*
* STDIO_UART_BAUDRATE is used as CONFIG_CONSOLE_UART_BAUDRATE and
* can be overridden by an application specific configuration.
*
* @{
*/
#define CONFIG_CONSOLE_UART_NUM (0)
#ifndef CONFIG_CONSOLE_UART_BAUDRATE
#define CONFIG_CONSOLE_UART_BAUDRATE (STDIO_UART_BAUDRATE)
#endif
/** @} */
#define CONFIG_APP1_SIZE (0xf0000)
#define CONFIG_APP1_OFFSET (0x10000)
#define CONFIG_SOC_IRAM_SIZE (0xc000)
#define CONFIG_TASK_WDT_PANIC
#define CONFIG_TASK_WDT_TIMEOUT_S (15)
#define CONFIG_WIFI_PPT_TASKSTACK_SIZE (3584)
#define CONFIG_MAIN_TASK_STACK_SIZE (2048)
#define CONFIG_EVENT_LOOP_STACK_SIZE (2048)
#define CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE
#define CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION (0)
#define CONFIG_SPI_FLASH_FREQ (ESP_IMAGE_SPI_SPEED_40M) /* 40 MHz */
#define CONFIG_SPI_FLASH_MODE (ESP_IMAGE_SPI_MODE_DIO) /* DIO mode */
#define CONFIG_SPI_FLASH_SIZE (0x100000)
#define CONFIG_SCAN_AP_MAX (32)
#define CONFIG_USING_NEW_ETS_VPRINTF
#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* SDK_CONF_H */

748
cpu/esp8266/include/stdio.h Normal file
View File

@ -0,0 +1,748 @@
/**
* This file is a modification of the original file to overwrite the *putchar*
* and *getchar* macros in the case the *uart_stdio* module is used. If the
* *uart_stdio* module is used, *putchar* and *getchar* are redirections to
* according *uart_stdio_* functions.
*/
/*
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#)stdio.h 5.3 (Berkeley) 3/15/86
*/
/*
* NB: to fit things in six character monocase externals, the
* stdio code uses the prefix `__s' for stdio objects, typically
* followed by a three-character attempt at a mnemonic.
*/
#ifndef STDIO_H
#define STDIO_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
#include "_ansi.h"
#define _FSTDIO /* ``function stdio'' */
#define __need_size_t
#define __need_NULL
#include <sys/cdefs.h>
#include <stddef.h>
#define __need___va_list
#include <stdarg.h>
/*
* <sys/reent.h> defines __FILE, _fpos_t.
* They must be defined there because struct _reent needs them (and we don't
* want reent.h to include this file.
*/
#include <sys/reent.h>
#include <sys/types.h>
_BEGIN_STD_C
typedef __FILE FILE;
#ifdef __CYGWIN__
typedef _fpos64_t fpos_t;
#else
typedef _fpos_t fpos_t;
#ifdef __LARGE64_FILES
typedef _fpos64_t fpos64_t;
#endif
#endif /* !__CYGWIN__ */
#include <sys/stdio.h>
#define __SLBF 0x0001 /* line buffered */
#define __SNBF 0x0002 /* unbuffered */
#define __SRD 0x0004 /* OK to read */
#define __SWR 0x0008 /* OK to write */
/* RD and WR are never simultaneously asserted */
#define __SRW 0x0010 /* open for reading & writing */
#define __SEOF 0x0020 /* found EOF */
#define __SERR 0x0040 /* found error */
#define __SMBF 0x0080 /* _buf is from malloc */
#define __SAPP 0x0100 /* fdopen()ed in append mode - so must write to end */
#define __SSTR 0x0200 /* this is an sprintf/snprintf string */
#define __SOPT 0x0400 /* do fseek() optimisation */
#define __SNPT 0x0800 /* do not do fseek() optimisation */
#define __SOFF 0x1000 /* set iff _offset is in fact correct */
#define __SORD 0x2000 /* true => stream orientation (byte/wide) decided */
#if defined(__CYGWIN__)
#define __SCLE 0x4000 /* convert line endings CR/LF <-> NL */
#endif
#define __SL64 0x8000 /* is 64-bit offset large file */
/* _flags2 flags */
#define __SNLK 0x0001 /* stdio functions do not lock streams themselves */
#define __SWID 0x2000 /* true => stream orientation wide, false => byte, only valid if __SORD in _flags is true */
/*
* The following three definitions are for ANSI C, which took them
* from System V, which stupidly took internal interface macros and
* made them official arguments to setvbuf(), without renaming them.
* Hence, these ugly _IOxxx names are *supposed* to appear in user code.
*
* Although these happen to match their counterparts above, the
* implementation does not rely on that (so these could be renumbered).
*/
#define _IOFBF 0 /* setvbuf should set fully buffered */
#define _IOLBF 1 /* setvbuf should set line buffered */
#define _IONBF 2 /* setvbuf should set unbuffered */
#define EOF (-1)
#ifdef __BUFSIZ__
#define BUFSIZ __BUFSIZ__
#else
#define BUFSIZ 1024
#endif
#ifdef __FOPEN_MAX__
#define FOPEN_MAX __FOPEN_MAX__
#else
#define FOPEN_MAX 20
#endif
#ifdef __FILENAME_MAX__
#define FILENAME_MAX __FILENAME_MAX__
#else
#define FILENAME_MAX 1024
#endif
#ifdef __L_tmpnam__
#define L_tmpnam __L_tmpnam__
#else
#define L_tmpnam FILENAME_MAX
#endif
#ifndef __STRICT_ANSI__
#define P_tmpdir "/tmp"
#endif
#ifndef SEEK_SET
#define SEEK_SET 0 /* set file offset to offset */
#endif
#ifndef SEEK_CUR
#define SEEK_CUR 1 /* set file offset to current plus offset */
#endif
#ifndef SEEK_END
#define SEEK_END 2 /* set file offset to EOF plus offset */
#endif
#define TMP_MAX 26
#define stdin (_REENT->_stdin)
#define stdout (_REENT->_stdout)
#define stderr (_REENT->_stderr)
#define _stdin_r(x) ((x)->_stdin)
#define _stdout_r(x) ((x)->_stdout)
#define _stderr_r(x) ((x)->_stderr)
/*
* Functions defined in ANSI C standard.
*/
#ifndef __VALIST
#ifdef __GNUC__
#define __VALIST __gnuc_va_list
#else
#define __VALIST char*
#endif
#endif
FILE * _EXFUN(tmpfile, (void));
char * _EXFUN(tmpnam, (char *));
#if __BSD_VISIBLE || __XSI_VISIBLE || __POSIX_VISIBLE >= 200112
char * _EXFUN(tempnam, (const char *, const char *));
#endif
int _EXFUN(fclose, (FILE *));
int _EXFUN(fflush, (FILE *));
FILE * _EXFUN(freopen, (const char *__restrict, const char *__restrict, FILE *__restrict));
void _EXFUN(setbuf, (FILE *__restrict, char *__restrict));
int _EXFUN(setvbuf, (FILE *__restrict, char *__restrict, int, size_t));
int _EXFUN(fprintf, (FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
int _EXFUN(fscanf, (FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3))));
int _EXFUN(printf, (const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 1, 2))));
int _EXFUN(scanf, (const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 1, 2))));
int _EXFUN(sscanf, (const char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3))));
int _EXFUN(vfprintf, (FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vprintf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 1, 0))));
int _EXFUN(vsprintf, (char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(fgetc, (FILE *));
char * _EXFUN(fgets, (char *__restrict, int, FILE *__restrict));
int _EXFUN(fputc, (int, FILE *));
int _EXFUN(fputs, (const char *__restrict, FILE *__restrict));
int _EXFUN(getc, (FILE *));
int _EXFUN(getchar, (void));
char * _EXFUN(gets, (char *));
int _EXFUN(putc, (int, FILE *));
int _EXFUN(putchar, (int));
int _EXFUN(puts, (const char *));
int _EXFUN(ungetc, (int, FILE *));
size_t _EXFUN(fread, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict));
size_t _EXFUN(fwrite, (const _PTR __restrict , size_t _size, size_t _n, FILE *));
#ifdef _COMPILING_NEWLIB
int _EXFUN(fgetpos, (FILE *, _fpos_t *));
#else
int _EXFUN(fgetpos, (FILE *__restrict, fpos_t *__restrict));
#endif
int _EXFUN(fseek, (FILE *, long, int));
#ifdef _COMPILING_NEWLIB
int _EXFUN(fsetpos, (FILE *, const _fpos_t *));
#else
int _EXFUN(fsetpos, (FILE *, const fpos_t *));
#endif
long _EXFUN(ftell, ( FILE *));
void _EXFUN(rewind, (FILE *));
void _EXFUN(clearerr, (FILE *));
int _EXFUN(feof, (FILE *));
int _EXFUN(ferror, (FILE *));
void _EXFUN(perror, (const char *));
#ifndef _REENT_ONLY
FILE * _EXFUN(fopen, (const char *__restrict _name, const char *__restrict _type));
int _EXFUN(sprintf, (char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
int _EXFUN(remove, (const char *));
int _EXFUN(rename, (const char *, const char *));
#ifdef _COMPILING_NEWLIB
int _EXFUN(_rename, (const char *, const char *));
#endif
#endif
#if !defined(__STRICT_ANSI__) || defined(__USE_XOPEN2K)
#ifdef _COMPILING_NEWLIB
int _EXFUN(fseeko, (FILE *, _off_t, int));
_off_t _EXFUN(ftello, ( FILE *));
#else
int _EXFUN(fseeko, (FILE *, off_t, int));
off_t _EXFUN(ftello, ( FILE *));
#endif
#endif
#if __GNU_VISIBLE
int _EXFUN(fcloseall, (_VOID));
#endif
#if !defined(__STRICT_ANSI__) || (__STDC_VERSION__ >= 199901L) || (__cplusplus >= 201103L)
#ifndef _REENT_ONLY
int _EXFUN(asiprintf, (char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
char * _EXFUN(asniprintf, (char *, size_t *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
char * _EXFUN(asnprintf, (char *__restrict, size_t *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(asprintf, (char **__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
#ifndef diprintf
int _EXFUN(diprintf, (int, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
#endif
int _EXFUN(fiprintf, (FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
int _EXFUN(fiscanf, (FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3))));
int _EXFUN(iprintf, (const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 1, 2))));
int _EXFUN(iscanf, (const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 1, 2))));
int _EXFUN(siprintf, (char *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
int _EXFUN(siscanf, (const char *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3))));
int _EXFUN(snprintf, (char *__restrict, size_t, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(sniprintf, (char *, size_t, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(vasiprintf, (char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
char * _EXFUN(vasniprintf, (char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
char * _EXFUN(vasnprintf, (char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(vasprintf, (char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vdiprintf, (int, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vfiprintf, (FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vfiscanf, (FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(vfscanf, (FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(viprintf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 1, 0))));
int _EXFUN(viscanf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 1, 0))));
int _EXFUN(vscanf, (const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 1, 0))));
int _EXFUN(vsiprintf, (char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(vsiscanf, (const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(vsniprintf, (char *, size_t, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(vsnprintf, (char *__restrict, size_t, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(vsscanf, (const char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
#endif /* !_REENT_ONLY */
#endif /* !__STRICT_ANSI__ */
/*
* Routines in POSIX 1003.1:2001.
*/
#ifndef __STRICT_ANSI__
#ifndef _REENT_ONLY
FILE * _EXFUN(fdopen, (int, const char *));
#endif
int _EXFUN(fileno, (FILE *));
int _EXFUN(getw, (FILE *));
int _EXFUN(pclose, (FILE *));
FILE * _EXFUN(popen, (const char *, const char *));
int _EXFUN(putw, (int, FILE *));
void _EXFUN(setbuffer, (FILE *, char *, int));
int _EXFUN(setlinebuf, (FILE *));
int _EXFUN(getc_unlocked, (FILE *));
int _EXFUN(getchar_unlocked, (void));
void _EXFUN(flockfile, (FILE *));
int _EXFUN(ftrylockfile, (FILE *));
void _EXFUN(funlockfile, (FILE *));
int _EXFUN(putc_unlocked, (int, FILE *));
int _EXFUN(putchar_unlocked, (int));
#endif /* ! __STRICT_ANSI__ */
/*
* Routines in POSIX 1003.1:200x.
*/
#ifndef __STRICT_ANSI__
# ifndef _REENT_ONLY
# ifndef dprintf
int _EXFUN(dprintf, (int, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
# endif
FILE * _EXFUN(fmemopen, (void *__restrict, size_t, const char *__restrict));
/* getdelim - see __getdelim for now */
/* getline - see __getline for now */
FILE * _EXFUN(open_memstream, (char **, size_t *));
#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809
int _EXFUN(renameat, (int, const char *, int, const char *));
#endif
int _EXFUN(vdprintf, (int, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
# endif
#endif
/*
* Recursive versions of the above.
*/
int _EXFUN(_asiprintf_r, (struct _reent *, char **, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
char * _EXFUN(_asniprintf_r, (struct _reent *, char *, size_t *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5))));
char * _EXFUN(_asnprintf_r, (struct _reent *, char *__restrict, size_t *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5))));
int _EXFUN(_asprintf_r, (struct _reent *, char **__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_diprintf_r, (struct _reent *, int, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_dprintf_r, (struct _reent *, int, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_fclose_r, (struct _reent *, FILE *));
int _EXFUN(_fcloseall_r, (struct _reent *));
FILE * _EXFUN(_fdopen_r, (struct _reent *, int, const char *));
int _EXFUN(_fflush_r, (struct _reent *, FILE *));
int _EXFUN(_fgetc_r, (struct _reent *, FILE *));
int _EXFUN(_fgetc_unlocked_r, (struct _reent *, FILE *));
char * _EXFUN(_fgets_r, (struct _reent *, char *__restrict, int, FILE *__restrict));
char * _EXFUN(_fgets_unlocked_r, (struct _reent *, char *__restrict, int, FILE *__restrict));
#ifdef _COMPILING_NEWLIB
int _EXFUN(_fgetpos_r, (struct _reent *, FILE *__restrict, _fpos_t *__restrict));
int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const _fpos_t *));
#else
int _EXFUN(_fgetpos_r, (struct _reent *, FILE *, fpos_t *));
int _EXFUN(_fsetpos_r, (struct _reent *, FILE *, const fpos_t *));
#endif
int _EXFUN(_fiprintf_r, (struct _reent *, FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_fiscanf_r, (struct _reent *, FILE *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4))));
FILE * _EXFUN(_fmemopen_r, (struct _reent *, void *__restrict, size_t, const char *__restrict));
FILE * _EXFUN(_fopen_r, (struct _reent *, const char *__restrict, const char *__restrict));
FILE * _EXFUN(_freopen_r, (struct _reent *, const char *__restrict, const char *__restrict, FILE *__restrict));
int _EXFUN(_fprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_fpurge_r, (struct _reent *, FILE *));
int _EXFUN(_fputc_r, (struct _reent *, int, FILE *));
int _EXFUN(_fputc_unlocked_r, (struct _reent *, int, FILE *));
int _EXFUN(_fputs_r, (struct _reent *, const char *__restrict, FILE *__restrict));
int _EXFUN(_fputs_unlocked_r, (struct _reent *, const char *__restrict, FILE *__restrict));
size_t _EXFUN(_fread_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict));
size_t _EXFUN(_fread_unlocked_r, (struct _reent *, _PTR __restrict, size_t _size, size_t _n, FILE *__restrict));
int _EXFUN(_fscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4))));
int _EXFUN(_fseek_r, (struct _reent *, FILE *, long, int));
int _EXFUN(_fseeko_r,(struct _reent *, FILE *, _off_t, int));
long _EXFUN(_ftell_r, (struct _reent *, FILE *));
_off_t _EXFUN(_ftello_r,(struct _reent *, FILE *));
void _EXFUN(_rewind_r, (struct _reent *, FILE *));
size_t _EXFUN(_fwrite_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict));
size_t _EXFUN(_fwrite_unlocked_r, (struct _reent *, const _PTR __restrict, size_t _size, size_t _n, FILE *__restrict));
int _EXFUN(_getc_r, (struct _reent *, FILE *));
int _EXFUN(_getc_unlocked_r, (struct _reent *, FILE *));
int _EXFUN(_getchar_r, (struct _reent *));
int _EXFUN(_getchar_unlocked_r, (struct _reent *));
char * _EXFUN(_gets_r, (struct _reent *, char *));
int _EXFUN(_iprintf_r, (struct _reent *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
int _EXFUN(_iscanf_r, (struct _reent *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3))));
FILE * _EXFUN(_open_memstream_r, (struct _reent *, char **, size_t *));
void _EXFUN(_perror_r, (struct _reent *, const char *));
int _EXFUN(_printf_r, (struct _reent *, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 2, 3))));
int _EXFUN(_putc_r, (struct _reent *, int, FILE *));
int _EXFUN(_putc_unlocked_r, (struct _reent *, int, FILE *));
int _EXFUN(_putchar_unlocked_r, (struct _reent *, int));
int _EXFUN(_putchar_r, (struct _reent *, int));
int _EXFUN(_puts_r, (struct _reent *, const char *));
int _EXFUN(_remove_r, (struct _reent *, const char *));
int _EXFUN(_rename_r, (struct _reent *,
const char *_old, const char *_new));
int _EXFUN(_scanf_r, (struct _reent *, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 2, 3))));
int _EXFUN(_siprintf_r, (struct _reent *, char *, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_siscanf_r, (struct _reent *, const char *, const char *, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4))));
int _EXFUN(_sniprintf_r, (struct _reent *, char *, size_t, const char *, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5))));
int _EXFUN(_snprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 4, 5))));
int _EXFUN(_sprintf_r, (struct _reent *, char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__printf__, 3, 4))));
int _EXFUN(_sscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, ...)
_ATTRIBUTE ((__format__ (__scanf__, 3, 4))));
char * _EXFUN(_tempnam_r, (struct _reent *, const char *, const char *));
FILE * _EXFUN(_tmpfile_r, (struct _reent *));
char * _EXFUN(_tmpnam_r, (struct _reent *, char *));
int _EXFUN(_ungetc_r, (struct _reent *, int, FILE *));
int _EXFUN(_vasiprintf_r, (struct _reent *, char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
char * _EXFUN(_vasniprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0))));
char * _EXFUN(_vasnprintf_r, (struct _reent*, char *, size_t *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0))));
int _EXFUN(_vasprintf_r, (struct _reent *, char **, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vdiprintf_r, (struct _reent *, int, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vdprintf_r, (struct _reent *, int, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vfiprintf_r, (struct _reent *, FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vfiscanf_r, (struct _reent *, FILE *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
int _EXFUN(_vfprintf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vfscanf_r, (struct _reent *, FILE *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
int _EXFUN(_viprintf_r, (struct _reent *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(_viscanf_r, (struct _reent *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(_vprintf_r, (struct _reent *, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 2, 0))));
int _EXFUN(_vscanf_r, (struct _reent *, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 2, 0))));
int _EXFUN(_vsiprintf_r, (struct _reent *, char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vsiscanf_r, (struct _reent *, const char *, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
int _EXFUN(_vsniprintf_r, (struct _reent *, char *, size_t, const char *, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0))));
int _EXFUN(_vsnprintf_r, (struct _reent *, char *__restrict, size_t, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 4, 0))));
int _EXFUN(_vsprintf_r, (struct _reent *, char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__printf__, 3, 0))));
int _EXFUN(_vsscanf_r, (struct _reent *, const char *__restrict, const char *__restrict, __VALIST)
_ATTRIBUTE ((__format__ (__scanf__, 3, 0))));
/* Other extensions. */
int _EXFUN(fpurge, (FILE *));
ssize_t _EXFUN(__getdelim, (char **, size_t *, int, FILE *));
ssize_t _EXFUN(__getline, (char **, size_t *, FILE *));
#if __BSD_VISIBLE
void _EXFUN(clearerr_unlocked, (FILE *));
int _EXFUN(feof_unlocked, (FILE *));
int _EXFUN(ferror_unlocked, (FILE *));
int _EXFUN(fileno_unlocked, (FILE *));
int _EXFUN(fflush_unlocked, (FILE *));
int _EXFUN(fgetc_unlocked, (FILE *));
int _EXFUN(fputc_unlocked, (int, FILE *));
size_t _EXFUN(fread_unlocked, (_PTR __restrict, size_t _size, size_t _n, FILE *__restrict));
size_t _EXFUN(fwrite_unlocked, (const _PTR __restrict , size_t _size, size_t _n, FILE *));
#endif
#if __GNU_VISIBLE
char * _EXFUN(fgets_unlocked, (char *__restrict, int, FILE *__restrict));
int _EXFUN(fputs_unlocked, (const char *__restrict, FILE *__restrict));
#endif
#ifdef __LARGE64_FILES
#if !defined(__CYGWIN__) || defined(_COMPILING_NEWLIB)
FILE * _EXFUN(fdopen64, (int, const char *));
FILE * _EXFUN(fopen64, (const char *, const char *));
FILE * _EXFUN(freopen64, (_CONST char *, _CONST char *, FILE *));
_off64_t _EXFUN(ftello64, (FILE *));
_off64_t _EXFUN(fseeko64, (FILE *, _off64_t, int));
int _EXFUN(fgetpos64, (FILE *, _fpos64_t *));
int _EXFUN(fsetpos64, (FILE *, const _fpos64_t *));
FILE * _EXFUN(tmpfile64, (void));
FILE * _EXFUN(_fdopen64_r, (struct _reent *, int, const char *));
FILE * _EXFUN(_fopen64_r, (struct _reent *,const char *, const char *));
FILE * _EXFUN(_freopen64_r, (struct _reent *, _CONST char *, _CONST char *, FILE *));
_off64_t _EXFUN(_ftello64_r, (struct _reent *, FILE *));
_off64_t _EXFUN(_fseeko64_r, (struct _reent *, FILE *, _off64_t, int));
int _EXFUN(_fgetpos64_r, (struct _reent *, FILE *, _fpos64_t *));
int _EXFUN(_fsetpos64_r, (struct _reent *, FILE *, const _fpos64_t *));
FILE * _EXFUN(_tmpfile64_r, (struct _reent *));
#endif /* !__CYGWIN__ */
#endif /* __LARGE64_FILES */
/*
* Routines internal to the implementation.
*/
int _EXFUN(__srget_r, (struct _reent *, FILE *));
int _EXFUN(__swbuf_r, (struct _reent *, int, FILE *));
/*
* Stdio function-access interface.
*/
#ifndef __STRICT_ANSI__
# ifdef __LARGE64_FILES
FILE *_EXFUN(funopen,(const _PTR __cookie,
int (*__readfn)(_PTR __c, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(_PTR __c, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
_fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence),
int (*__closefn)(_PTR __c)));
FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie,
int (*__readfn)(_PTR __c, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(_PTR __c, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
_fpos64_t (*__seekfn)(_PTR __c, _fpos64_t __off, int __whence),
int (*__closefn)(_PTR __c)));
# else
FILE *_EXFUN(funopen,(const _PTR __cookie,
int (*__readfn)(_PTR __cookie, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(_PTR __cookie, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence),
int (*__closefn)(_PTR __cookie)));
FILE *_EXFUN(_funopen_r,(struct _reent *, const _PTR __cookie,
int (*__readfn)(_PTR __cookie, char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
int (*__writefn)(_PTR __cookie, const char *__buf,
_READ_WRITE_BUFSIZE_TYPE __n),
fpos_t (*__seekfn)(_PTR __cookie, fpos_t __off, int __whence),
int (*__closefn)(_PTR __cookie)));
# endif /* !__LARGE64_FILES */
# define fropen(__cookie, __fn) funopen(__cookie, __fn, (int (*)())0, \
(fpos_t (*)())0, (int (*)())0)
# define fwopen(__cookie, __fn) funopen(__cookie, (int (*)())0, __fn, \
(fpos_t (*)())0, (int (*)())0)
typedef ssize_t cookie_read_function_t(void *__cookie, char *__buf, size_t __n);
typedef ssize_t cookie_write_function_t(void *__cookie, const char *__buf,
size_t __n);
# ifdef __LARGE64_FILES
typedef int cookie_seek_function_t(void *__cookie, _off64_t *__off,
int __whence);
# else
typedef int cookie_seek_function_t(void *__cookie, off_t *__off, int __whence);
# endif /* !__LARGE64_FILES */
typedef int cookie_close_function_t(void *__cookie);
typedef struct
{
/* These four struct member names are dictated by Linux; hopefully,
they don't conflict with any macros. */
cookie_read_function_t *read;
cookie_write_function_t *write;
cookie_seek_function_t *seek;
cookie_close_function_t *close;
} cookie_io_functions_t;
FILE *_EXFUN(fopencookie,(void *__cookie,
const char *__mode, cookie_io_functions_t __functions));
FILE *_EXFUN(_fopencookie_r,(struct _reent *, void *__cookie,
const char *__mode, cookie_io_functions_t __functions));
#endif /* ! __STRICT_ANSI__ */
#ifndef __CUSTOM_FILE_IO__
/*
* The __sfoo macros are here so that we can
* define function versions in the C library.
*/
#define __sgetc_raw_r(__ptr, __f) (--(__f)->_r < 0 ? __srget_r(__ptr, __f) : (int)(*(__f)->_p++))
#ifdef __SCLE
/* For a platform with CR/LF, additional logic is required by
__sgetc_r which would otherwise simply be a macro; therefore we
use an inlined function. The function is only meant to be inlined
in place as used and the function body should never be emitted.
There are two possible means to this end when compiling with GCC,
one when compiling with a standard C99 compiler, and for other
compilers we're just stuck. At the moment, this issue only
affects the Cygwin target, so we'll most likely be using GCC. */
_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p);
_ELIDABLE_INLINE int __sgetc_r(struct _reent *__ptr, FILE *__p)
{
int __c = __sgetc_raw_r(__ptr, __p);
if ((__p->_flags & __SCLE) && (__c == '\r'))
{
int __c2 = __sgetc_raw_r(__ptr, __p);
if (__c2 == '\n')
__c = __c2;
else
ungetc(__c2, __p);
}
return __c;
}
#else
#define __sgetc_r(__ptr, __p) __sgetc_raw_r(__ptr, __p)
#endif
#ifdef _never /* __GNUC__ */
/* If this inline is actually used, then systems using coff debugging
info get hopelessly confused. 21sept93 rich@cygnus.com. */
_ELIDABLE_INLINE int __sputc_r(struct _reent *_ptr, int _c, FILE *_p) {
if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
return (*_p->_p++ = _c);
else
return (__swbuf_r(_ptr, _c, _p));
}
#else
/*
* This has been tuned to generate reasonable code on the vax using pcc
*/
#define __sputc_raw_r(__ptr, __c, __p) \
(--(__p)->_w < 0 ? \
(__p)->_w >= (__p)->_lbfsize ? \
(*(__p)->_p = (__c)), *(__p)->_p != '\n' ? \
(int)*(__p)->_p++ : \
__swbuf_r(__ptr, '\n', __p) : \
__swbuf_r(__ptr, (int)(__c), __p) : \
(*(__p)->_p = (__c), (int)*(__p)->_p++))
#ifdef __SCLE
#define __sputc_r(__ptr, __c, __p) \
((((__p)->_flags & __SCLE) && ((__c) == '\n')) \
? __sputc_raw_r(__ptr, '\r', (__p)) : 0 , \
__sputc_raw_r((__ptr), (__c), (__p)))
#else
#define __sputc_r(__ptr, __c, __p) __sputc_raw_r(__ptr, __c, __p)
#endif
#endif
#define __sfeof(p) ((int)(((p)->_flags & __SEOF) != 0))
#define __sferror(p) ((int)(((p)->_flags & __SERR) != 0))
#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
#define __sfileno(p) ((p)->_file)
#ifndef _REENT_SMALL
#define feof(p) __sfeof(p)
#define ferror(p) __sferror(p)
#define clearerr(p) __sclearerr(p)
#if __BSD_VISIBLE
#define feof_unlocked(p) __sfeof(p)
#define ferror_unlocked(p) __sferror(p)
#define clearerr_unlocked(p) __sclearerr(p)
#endif /* __BSD_VISIBLE */
#endif /* _REENT_SMALL */
#if 0 /*ndef __STRICT_ANSI__ - FIXME: must initialize stdio first, use fn */
#define fileno(p) __sfileno(p)
#endif
#ifndef __CYGWIN__
#ifndef lint
#define getc(fp) __sgetc_r(_REENT, fp)
#define putc(x, fp) __sputc_r(_REENT, x, fp)
#endif /* lint */
#endif /* __CYGWIN__ */
#ifndef __STRICT_ANSI__
/* fast always-buffered version, true iff error */
#define fast_putc(x,p) (--(p)->_w < 0 ? \
__swbuf_r(_REENT, (int)(x), p) == EOF : (*(p)->_p = (x), (p)->_p++, 0))
#define L_cuserid 9 /* posix says it goes in stdio.h :( */
#ifdef __CYGWIN__
#define L_ctermid 16
#endif
#endif
#endif /* !__CUSTOM_FILE_IO__ */
#define getchar() getc(stdin)
#define putchar(x) putc(x, stdout)
#ifndef __STRICT_ANSI__
#define getchar_unlocked() getc_unlocked(stdin)
#define putchar_unlocked(x) putc_unlocked(x, stdout)
#endif
_END_STD_C
#undef putchar
#undef getchar
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* STDIO_H */

View File

@ -1,228 +0,0 @@
/*
* Copyright (c) 2004, 2005 by
* Ralf Corsepius, Ulm/Germany. All rights reserved.
*
* Permission to use, copy, modify, and distribute this software
* is freely granted, provided that this notice is preserved.
*/
/**
* @brief Modified _intsup.h for compilation with RIOT OS
* Source: /path/to/newlib-xtensa/xtensa-lx106-elf/include/sys
* Changes: __INT32 (see below)
*/
#ifndef SYS__INTSUP_H
#define SYS__INTSUP_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
/* additional header guard to avoid conflicts if original file is included later */
#ifndef _SYS__INTSUP_H
#define _SYS__INTSUP_H
#include <sys/features.h>
#if __GNUC_PREREQ (3, 2)
/* gcc > 3.2 implicitly defines the values we are interested */
#define __STDINT_EXP(x) __##x##__
#else
#define __STDINT_EXP(x) x
#include <limits.h>
#endif
/* Determine how intptr_t and intN_t fastN_t and leastN_t are defined by gcc
for this target. This is used to determine the correct printf() constant in
inttypes.h and other constants in stdint.h.
So we end up with
?(signed|unsigned) char == 0
?(signed|unsigned) short == 1
?(signed|unsigned) int == 2
?(signed|unsigned) short int == 3
?(signed|unsigned) long == 4
?(signed|unsigned) long int == 6
?(signed|unsigned) long long == 8
?(signed|unsigned) long long int == 10
*/
#pragma push_macro("signed")
#pragma push_macro("unsigned")
#pragma push_macro("char")
#pragma push_macro("short")
#pragma push_macro("__int20")
#pragma push_macro("int")
#pragma push_macro("long")
#undef signed
#undef unsigned
#undef char
#undef short
#undef int
#undef __int20
#undef long
#define signed +0
#define unsigned +0
#define char +0
#define short +1
#define __int20 +2
#define int +2
#define long +4
#if (__INTPTR_TYPE__ == 8 || __INTPTR_TYPE__ == 10)
#define _INTPTR_EQ_LONGLONG
#elif (__INTPTR_TYPE__ == 4 || __INTPTR_TYPE__ == 6)
#define _INTPTR_EQ_LONG
/* Note - the tests for _INTPTR_EQ_INT and _INTPTR_EQ_SHORT are currently
redundant as the values are not used. But one day they may be needed
and so the tests remain. */
#elif __INTPTR_TYPE__ == 2
#define _INTPTR_EQ_INT
#elif (__INTPTR_TYPE__ == 1 || __INTPTR_TYPE__ == 3)
#define _INTPTR_EQ_SHORT
#else
#error "Unable to determine type definition of intptr_t"
#endif
#if (__INT32_TYPE__ == 4 || __INT32_TYPE__ == 6)
#define _INT32_EQ_LONG
#elif __INT32_TYPE__ == 2
/* Nothing to define because int32_t is safe to print as an int. */
#else
#error "Unable to determine type definition of int32_t"
#endif
#if (__INT8_TYPE__ == 0)
#define __INT8 /* "hh" */ /* ets_printf doesn't support "h" */
#elif (__INT8_TYPE__ == 1 || __INT8_TYPE__ == 3)
#define __INT8 /* "h" */ /* ets_printf doesn't support "h" */
#elif (__INT8_TYPE__ == 2)
#define __INT8
#elif (__INT8_TYPE__ == 4 || __INT8_TYPE__ == 6)
#define __INT8 "l"
#elif (__INT8_TYPE__ == 8 || __INT8_TYPE__ == 10)
#define __INT8 "ll"
#endif
#if (__INT16_TYPE__ == 1 || __INT16_TYPE__ == 3)
#define __INT16 /* "h" */ /* ets_printf doesn't support "h" */
#elif (__INT16_TYPE__ == 2)
#define __INT16
#elif (__INT16_TYPE__ == 4 || __INT16_TYPE__ == 6)
#define __INT16 "l"
#elif (__INT16_TYPE__ == 8 || __INT16_TYPE__ == 10)
#define __INT16 "ll"
#endif
#if (__INT32_TYPE__ == 2)
#define __INT32
#elif (__INT32_TYPE__ == 4 || __INT32_TYPE__ == 6)
/**
* Definition of __INT32 had to be changed since to avoid format warnings/
* errors since xtensa-lx106-elf-gcc defines *__INT32_TYPE__* as *long int*
* while newlib defines *int32_t* as *signed int*. PRI*32 there throw format
* warnings/errors.
*/
#if 0
#define __INT32 "l"
#else
#define __INT32
#endif
#elif (__INT32_TYPE__ == 8 || __INT32_TYPE__ == 10)
#define __INT32 "ll"
#endif
#if (__INT64_TYPE__ == 2)
#define __INT64
#elif (__INT64_TYPE__ == 4 || __INT64_TYPE__ == 6)
#define __INT64 "l"
#elif (__INT64_TYPE__ == 8 || __INT64_TYPE__ == 10)
#define __INT64 "ll"
#endif
#if (__INT_FAST8_TYPE__ == 0)
#define __FAST8 /* "hh" */ /* ets_printf doesn't support "h" */
#elif (__INT_FAST8_TYPE__ == 1 || __INT_FAST8_TYPE__ == 3)
#define __FAST8 /* "h" */ /* ets_printf doesn't support "h" */
#elif (__INT_FAST8_TYPE__ == 2)
#define __FAST8
#elif (__INT_FAST8_TYPE__ == 4 || __INT_FAST8_TYPE__ == 6)
#define __FAST8 "l"
#elif (__INT_FAST8_TYPE__ == 8 || __INT_FAST8_TYPE__ == 10)
#define __FAST8 "ll"
#endif
#if (__INT_FAST16_TYPE__ == 1 || __INT_FAST16_TYPE__ == 3)
#define __FAST16 /* "h" */ /* ets_printf doesn't support "h" */
#elif (__INT_FAST16_TYPE__ == 2)
#define __FAST16
#elif (__INT_FAST16_TYPE__ == 4 || __INT_FAST16_TYPE__ == 6)
#define __FAST16 "l"
#elif (__INT_FAST16_TYPE__ == 8 || __INT_FAST16_TYPE__ == 10)
#define __FAST16 "ll"
#endif
#if (__INT_FAST32_TYPE__ == 2)
#define __FAST32
#elif (__INT_FAST32_TYPE__ == 4 || __INT_FAST32_TYPE__ == 6)
#define __FAST32 "l"
#elif (__INT_FAST32_TYPE__ == 8 || __INT_FAST32_TYPE__ == 10)
#define __FAST32 "ll"
#endif
#if (__INT_FAST64_TYPE__ == 2)
#define __FAST64
#elif (__INT_FAST64_TYPE__ == 4 || __INT_FAST64_TYPE__ == 6)
#define __FAST64 "l"
#elif (__INT_FAST64_TYPE__ == 8 || __INT_FAST64_TYPE__ == 10)
#define __FAST64 "ll"
#endif
#if (__INT_LEAST8_TYPE__ == 0)
#define __LEAST8 /* "hh" */ /* ets_printf doesn't support "h" */
#elif (__INT_LEAST8_TYPE__ == 1 || __INT_LEAST8_TYPE__ == 3)
#define __LEAST8 /* "h" */ /* ets_printf doesn't support "h" */
#elif (__INT_LEAST8_TYPE__ == 2)
#define __LEAST8
#elif (__INT_LEAST8_TYPE__ == 4 || __INT_LEAST8_TYPE__ == 6)
#define __LEAST8 "l"
#elif (__INT_LEAST8_TYPE__ == 8 || __INT_LEAST8_TYPE__ == 10)
#define __LEAST8 "ll"
#endif
#if (__INT_LEAST16_TYPE__ == 1 || __INT_LEAST16_TYPE__ == 3)
#define __LEAST16 /* "h" */ /* ets_printf doesn't support "h" */
#elif (__INT_LEAST16_TYPE__ == 2)
#define __LEAST16
#elif (__INT_LEAST16_TYPE__ == 4 || __INT_LEAST16_TYPE__ == 6)
#define __LEAST16 "l"
#elif (__INT_LEAST16_TYPE__ == 8 || __INT_LEAST16_TYPE__ == 10)
#define __LEAST16 "ll"
#endif
#if (__INT_LEAST32_TYPE__ == 2)
#define __LEAST32
#elif (__INT_LEAST32_TYPE__ == 4 || __INT_LEAST32_TYPE__ == 6)
#define __LEAST32 "l"
#elif (__INT_LEAST32_TYPE__ == 8 || __INT_LEAST32_TYPE__ == 10)
#define __LEAST32 "ll"
#endif
#if (__INT_LEAST64_TYPE__ == 2)
#define __LEAST64
#elif (__INT_LEAST64_TYPE__ == 4 || __INT_LEAST64_TYPE__ == 6)
#define __LEAST64 "l"
#elif (__INT_LEAST64_TYPE__ == 8 || __INT_LEAST64_TYPE__ == 10)
#define __LEAST64 "ll"
#endif
#undef signed
#undef unsigned
#undef char
#undef short
#undef int
#undef long
#pragma pop_macro("signed")
#pragma pop_macro("unsigned")
#pragma pop_macro("char")
#pragma pop_macro("short")
#pragma pop_macro("__int20")
#pragma pop_macro("int")
#pragma pop_macro("long")
#endif /* _SYS__INTSUP_H */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* SYS__INTSUP_H */

View File

@ -0,0 +1,337 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief This file is a modification of original sys/types.h
*
* @author Gunar Schorcht <gunar@schorcht.net>
*
* This file is just a wrapper around sys/types.h to fix missing types
* fsblkcnt_t and fsfilcnt_t needed in statvfs.h and to avoid type conflicts
* with pthread types from pthread module.
*/
/* unified sys/types.h:
start with sef's sysvi386 version.
merge go32 version -- a few ifdefs.
h8300hms, h8300xray, and sysvnecv70 disagree on the following types:
typedef int gid_t;
typedef int uid_t;
typedef int dev_t;
typedef int ino_t;
typedef int mode_t;
typedef int caddr_t;
however, these aren't "reasonable" values, the sysvi386 ones make far
more sense, and should work sufficiently well (in particular, h8300
doesn't have a stat, and the necv70 doesn't matter.) -- eichin
*/
#ifndef SYS_TYPES_H
#define SYS_TYPES_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
#ifndef _FSBLKCNT_T_DECLARED
#include <stdint.h>
typedef uint32_t fsblkcnt_t;
typedef uint32_t fsfilcnt_t;
#define _FSBLKCNT_T_DECLARED
#endif
#ifndef _SYS_TYPES_H
#include <_ansi.h>
#ifndef __INTTYPES_DEFINED__
#define __INTTYPES_DEFINED__
#include <machine/_types.h>
#if defined(__rtems__) || defined(__XMK__)
/*
* The following section is RTEMS specific and is needed to more
* closely match the types defined in the BSD sys/types.h.
* This is needed to let the RTEMS/BSD TCP/IP stack compile.
*/
/* deprecated */
#if ___int8_t_defined
typedef __uint8_t u_int8_t;
#endif
#if ___int16_t_defined
typedef __uint16_t u_int16_t;
#endif
#if ___int32_t_defined
typedef __uint32_t u_int32_t;
#endif
#if ___int64_t_defined
typedef __uint64_t u_int64_t;
/* deprecated */
typedef __uint64_t u_quad_t;
typedef __int64_t quad_t;
typedef quad_t * qaddr_t;
#endif
#endif
#endif /* ! __INTTYPES_DEFINED */
#ifndef __need_inttypes
#define _SYS_TYPES_H
#include <sys/_types.h>
#ifdef __i386__
#if defined (GO32) || defined (__MSDOS__)
#define __MS_types__
#endif
#endif
# include <stddef.h>
# include <machine/types.h>
/* To ensure the stat struct's layout doesn't change when sizeof(int), etc.
changes, we assume sizeof short and long never change and have all types
used to define struct stat use them and not int where possible.
Where not possible, _ST_INTxx are used. It would be preferable to not have
such assumptions, but until the extra fluff is necessary, it's avoided.
No 64 bit targets use stat yet. What to do about them is postponed
until necessary. */
#ifdef __GNUC__
#define _ST_INT32 __attribute__ ((__mode__ (__SI__)))
#else
#define _ST_INT32
#endif
# ifndef _POSIX_SOURCE
# define physadr physadr_t
# define quad quad_t
#ifndef _BSDTYPES_DEFINED
/* also defined in mingw/gmon.h and in w32api/winsock[2].h */
#ifndef __u_char_defined
typedef unsigned char u_char;
#define __u_char_defined
#endif
#ifndef __u_short_defined
typedef unsigned short u_short;
#define __u_short_defined
#endif
#ifndef __u_int_defined
typedef unsigned int u_int;
#define __u_int_defined
#endif
#ifndef __u_long_defined
typedef unsigned long u_long;
#define __u_long_defined
#endif
#define _BSDTYPES_DEFINED
#endif
typedef unsigned short ushort; /* System V compatibility */
typedef unsigned int uint; /* System V compatibility */
typedef unsigned long ulong; /* System V compatibility */
# endif /*!_POSIX_SOURCE */
#ifndef __clock_t_defined
typedef _CLOCK_T_ clock_t;
#define __clock_t_defined
#endif
#ifndef __time_t_defined
typedef _TIME_T_ time_t;
#define __time_t_defined
#endif
#ifndef __timespec_defined
#define __timespec_defined
/* Time Value Specification Structures, P1003.1b-1993, p. 261 */
struct timespec {
time_t tv_sec; /* Seconds */
long tv_nsec; /* Nanoseconds */
};
#endif
struct itimerspec {
struct timespec it_interval; /* Timer period */
struct timespec it_value; /* Timer expiration */
};
#ifndef __daddr_t_defined
typedef long daddr_t;
#define __daddr_t_defined
#endif
#ifndef __caddr_t_defined
typedef char * caddr_t;
#define __caddr_t_defined
#endif
#ifndef __CYGWIN__
#if defined(__MS_types__) || defined(__rtems__) || \
defined(__sparc__) || defined(__SPU__)
typedef unsigned long ino_t;
#else
typedef unsigned short ino_t;
#endif
#endif /*__CYGWIN__*/
#ifdef __MS_types__
typedef unsigned long vm_offset_t;
typedef unsigned long vm_size_t;
#define __BIT_TYPES_DEFINED__
typedef signed char int8_t;
typedef unsigned char u_int8_t;
typedef short int16_t;
typedef unsigned short u_int16_t;
typedef int int32_t;
typedef unsigned int u_int32_t;
typedef long long int64_t;
typedef unsigned long long u_int64_t;
typedef int32_t register_t;
#endif /* __MS_types__ */
/*
* All these should be machine specific - right now they are all broken.
* However, for all of Cygnus' embedded targets, we want them to all be
* the same. Otherwise things like sizeof (struct stat) might depend on
* how the file was compiled (e.g. -mint16 vs -mint32, etc.).
*/
#ifndef __CYGWIN__ /* which defines these types in it's own types.h. */
typedef _off_t off_t;
typedef __dev_t dev_t;
typedef __uid_t uid_t;
typedef __gid_t gid_t;
#endif
#if defined(__XMK__)
typedef signed char pid_t;
#else
typedef int pid_t;
#endif
#if defined(__rtems__)
typedef _mode_t mode_t;
#endif
#ifndef __CYGWIN__
typedef long key_t;
#endif
typedef _ssize_t ssize_t;
#if !defined(__CYGWIN__) && !defined(__rtems__)
#ifdef __MS_types__
typedef char * addr_t;
typedef int mode_t;
#else
#if defined (__sparc__) && !defined (__sparc_v9__)
#ifdef __svr4__
typedef unsigned long mode_t;
#else
typedef unsigned short mode_t;
#endif
#else
typedef unsigned int mode_t _ST_INT32;
#endif
#endif /* ! __MS_types__ */
#endif /*__CYGWIN__*/
typedef unsigned short nlink_t;
/* We don't define fd_set and friends if we are compiling POSIX
source, or if we have included (or may include as indicated
by __USE_W32_SOCKETS) the W32api winsock[2].h header which
defines Windows versions of them. Note that a program which
includes the W32api winsock[2].h header must know what it is doing;
it must not call the cygwin32 select function.
*/
# if !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS))
# define _SYS_TYPES_FD_SET
# define NBBY 8 /* number of bits in a byte */
/*
* Select uses bit masks of file descriptors in longs.
* These macros manipulate such bit fields (the filesystem macros use chars).
* FD_SETSIZE may be defined by the user, but the default here
* should be >= NOFILE (param.h).
*/
# ifndef FD_SETSIZE
# define FD_SETSIZE 64
# endif
typedef long fd_mask;
# define NFDBITS (sizeof (fd_mask) * NBBY) /* bits per mask */
# ifndef howmany
# define howmany(x,y) (((x)+((y)-1))/(y))
# endif
/* We use a macro for fd_set so that including Sockets.h afterwards
can work. */
typedef struct _types_fd_set {
fd_mask fds_bits[howmany(FD_SETSIZE, NFDBITS)];
} _types_fd_set;
#define fd_set _types_fd_set
# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1L << ((n) % NFDBITS)))
# define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1L << ((n) % NFDBITS)))
# define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1L << ((n) % NFDBITS)))
# define FD_ZERO(p) (__extension__ (void)({ \
size_t __i; \
char *__tmp = (char *)p; \
for (__i = 0; __i < sizeof (*(p)); ++__i) \
*__tmp++ = 0; \
}))
# endif /* !(defined (_POSIX_SOURCE) || defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) */
#undef __MS_types__
#undef _ST_INT32
#ifndef __clockid_t_defined
typedef _CLOCKID_T_ clockid_t;
#define __clockid_t_defined
#endif
#ifndef __timer_t_defined
typedef _TIMER_T_ timer_t;
#define __timer_t_defined
#endif
typedef unsigned long useconds_t;
typedef long suseconds_t;
#endif /* !__need_inttypes */
#undef __need_inttypes
#endif /* _SYS_TYPES_H */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* SYS_TYPES_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -23,6 +23,7 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
@ -35,12 +36,24 @@ extern void syscalls_init (void);
/** System standard printf function */
extern int printf(const char* format, ...);
/** Determine free heap size */
unsigned int get_free_heap_size (void);
/** System standard puts function */
extern int puts(const char * str);
/** Determine free heap size */
extern unsigned int get_free_heap_size (void);
/** Time since boot in us (32bit version) */
uint32_t system_get_time (void);
/** Time since boot in ms (32bit version) */
uint32_t system_get_time_ms (void);
/** memset version that the compiler should not be allowed to optimize this */
void *system_secure_memset(void *s, int c, size_t n);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level

View File

@ -1,36 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @brief Default configurations required by the SDK
* @author Gunar Schorcht <gunar@schorcht.net>
* @file
* @{
*/
#ifndef USER_CONFIG_H
#define USER_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Default CPU frequency in MHz.
* Possible values are 80 and 160.
*/
#ifndef ESP8266_CPU_FREQUENCY
#define ESP8266_CPU_FREQUENCY 80
#endif
#ifdef __cplusplus
}
#endif
#endif /* USER_CONFIG_H */
/** @} */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -18,7 +18,7 @@
* @}
*/
#define ENABLE_DEBUG 0
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <stdint.h>
@ -27,10 +27,9 @@
#include "irq.h"
#include "cpu.h"
#include "common.h"
#include "esp_common.h"
#include "esp/common_macros.h"
#include "esp/xtensa_ops.h"
#include "sdk/ets.h"
#include "xtensa/xtensa_context.h"
/**
@ -46,9 +45,9 @@ unsigned int IRAM irq_disable(void)
uint32_t _saved_interrupt_level;
/* read and set interrupt level (RSIL) */
__asm__ volatile ("rsil %0, " XTSTR(XCHAL_NUM_INTLEVELS+1) : "=a" (_saved_interrupt_level));
__asm__ volatile ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) : "=a" (_saved_interrupt_level));
DEBUG ("%s %02x(%02x)\n", __func__,
(_saved_interrupt_level & 0xfffffff0) | (XCHAL_NUM_INTLEVELS+1),
(_saved_interrupt_level & 0xfffffff0) | (XCHAL_EXCM_LEVEL),
_saved_interrupt_level);
return _saved_interrupt_level;
}
@ -62,7 +61,7 @@ unsigned int IRAM irq_enable(void)
/* read and set interrupt level (RSIL) */
__asm__ volatile ("rsil %0, 0" : "=a" (_saved_interrupt_level));
DEBUG ("%s %02x(%02x)\n", __func__,
DEBUG ("%s %02x (%02x)\n", __func__,
_saved_interrupt_level & 0xfffffff0, _saved_interrupt_level);
return _saved_interrupt_level;
}

View File

@ -1,350 +0,0 @@
PROVIDE ( Cache_Read_Disable = 0x400047f0 );
PROVIDE ( Cache_Read_Enable = 0x40004678 );
PROVIDE ( FilePacketSendReqMsgProc = 0x400035a0 );
PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000368c );
PROVIDE ( FlashDwnLdStartMsgProc = 0x40003538 );
PROVIDE ( FlashDwnLdStopReqMsgProc = 0x40003658 );
PROVIDE ( GetUartDevice = 0x40003f4c );
PROVIDE ( MD5Final = 0x40009900 );
PROVIDE ( MD5Init = 0x40009818 );
PROVIDE ( MD5Update = 0x40009834 );
PROVIDE ( MemDwnLdStartMsgProc = 0x400036c4 );
PROVIDE ( MemDwnLdStopReqMsgProc = 0x4000377c );
PROVIDE ( MemPacketSendReqMsgProc = 0x400036f0 );
PROVIDE ( RcvMsg = 0x40003eac );
PROVIDE ( SHA1Final = 0x4000b648 );
PROVIDE ( SHA1Init = 0x4000b584 );
PROVIDE ( SHA1Transform = 0x4000a364 );
PROVIDE ( SHA1Update = 0x4000b5a8 );
PROVIDE ( SPI_read_status = 0x400043c8 );
PROVIDE ( SPI_write_status = 0x40004400 );
PROVIDE ( SPI_write_enable = 0x4000443c );
PROVIDE ( Wait_SPI_Idle = 0x4000448c );
PROVIDE ( Enable_QMode = 0x400044c0 );
PROVIDE ( SPIEraseArea = 0x40004b44 );
PROVIDE ( SPIEraseBlock = 0x400049b4 );
PROVIDE ( SPIEraseChip = 0x40004984 );
PROVIDE ( SPIEraseSector = 0x40004a00 );
PROVIDE ( SPILock = 0x400048a8 );
PROVIDE ( SPIParamCfg = 0x40004c2c );
PROVIDE ( SPIRead = 0x40004b1c );
PROVIDE ( SPIReadModeCnfig = 0x400048ec );
PROVIDE ( SPIUnlock = 0x40004878 );
PROVIDE ( SPIWrite = 0x40004a4c );
PROVIDE ( SelectSpiFunction = 0x40003f58 );
PROVIDE ( SendMsg = 0x40003cf4 );
PROVIDE ( UartConnCheck = 0x40003230 );
PROVIDE ( UartConnectProc = 0x400037a0 );
PROVIDE ( UartDwnLdProc = 0x40003368 );
PROVIDE ( UartGetCmdLn = 0x40003ef4 );
PROVIDE ( UartRegReadProc = 0x4000381c );
PROVIDE ( UartRegWriteProc = 0x400037ac );
PROVIDE ( UartRxString = 0x40003c30 );
PROVIDE ( Uart_Init = 0x40003a14 );
PROVIDE ( _DebugExceptionVector = 0x40000010 );
PROVIDE ( _DoubleExceptionVector = 0x40000070 );
PROVIDE ( _KernelExceptionVector = 0x40000030 );
PROVIDE ( _NMIExceptionVector = 0x40000020 );
PROVIDE ( _ResetHandler = 0x400000a4 );
PROVIDE ( _ResetVector = 0x40000080 );
PROVIDE ( _UserExceptionVector = 0x40000050 );
PROVIDE ( __adddf3 = 0x4000c538 );
PROVIDE ( __addsf3 = 0x4000c180 );
PROVIDE ( __divdf3 = 0x4000cb94 );
PROVIDE ( __divdi3 = 0x4000ce60 );
PROVIDE ( __divsi3 = 0x4000dc88 );
PROVIDE ( __extendsfdf2 = 0x4000cdfc );
PROVIDE ( __fixdfsi = 0x4000ccb8 );
PROVIDE ( __fixunsdfsi = 0x4000cd00 );
PROVIDE ( __fixunssfsi = 0x4000c4c4 );
PROVIDE ( __floatsidf = 0x4000e2f0 );
PROVIDE ( __floatsisf = 0x4000e2ac );
PROVIDE ( __floatunsidf = 0x4000e2e8 );
PROVIDE ( __floatunsisf = 0x4000e2a4 );
PROVIDE ( __muldf3 = 0x4000c8f0 );
PROVIDE ( __muldi3 = 0x40000650 );
PROVIDE ( __mulsf3 = 0x4000c3dc );
PROVIDE ( __subdf3 = 0x4000c688 );
PROVIDE ( __subsf3 = 0x4000c268 );
PROVIDE ( __truncdfsf2 = 0x4000cd5c );
PROVIDE ( __udivdi3 = 0x4000d310 );
PROVIDE ( __udivsi3 = 0x4000e21c );
PROVIDE ( __umoddi3 = 0x4000d770 );
PROVIDE ( __umodsi3 = 0x4000e268 );
PROVIDE ( __umulsidi3 = 0x4000dcf0 );
PROVIDE ( _rom_store = 0x4000e388 );
PROVIDE ( _rom_store_table = 0x4000e328 );
PROVIDE ( _start = 0x4000042c );
PROVIDE ( _xtos_alloca_handler = 0x4000dbe0 );
PROVIDE ( _xtos_c_wrapper_handler = 0x40000598 );
PROVIDE ( _xtos_cause3_handler = 0x40000590 );
PROVIDE ( _xtos_ints_off = 0x4000bda4 );
PROVIDE ( _xtos_ints_on = 0x4000bd84 );
PROVIDE ( _xtos_l1int_handler = 0x4000048c );
PROVIDE ( _xtos_p_none = 0x4000dbf8 );
PROVIDE ( _xtos_restore_intlevel = 0x4000056c );
PROVIDE ( _xtos_return_from_exc = 0x4000dc54 );
PROVIDE ( _xtos_set_exception_handler = 0x40000454 );
PROVIDE ( _xtos_set_interrupt_handler = 0x4000bd70 );
PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bd28 );
PROVIDE ( _xtos_set_intlevel = 0x4000dbfc );
PROVIDE ( _xtos_set_min_intlevel = 0x4000dc18 );
PROVIDE ( _xtos_set_vpri = 0x40000574 );
PROVIDE ( _xtos_syscall_handler = 0x4000dbe4 );
PROVIDE ( _xtos_unhandled_exception = 0x4000dc44 );
PROVIDE ( _xtos_unhandled_interrupt = 0x4000dc3c );
PROVIDE ( aes_decrypt = 0x400092d4 );
PROVIDE ( aes_decrypt_deinit = 0x400092e4 );
PROVIDE ( aes_decrypt_init = 0x40008ea4 );
PROVIDE ( aes_unwrap = 0x40009410 );
PROVIDE ( base64_decode = 0x40009648 );
PROVIDE ( base64_encode = 0x400094fc );
PROVIDE ( bzero = 0x4000de84 );
PROVIDE ( cmd_parse = 0x40000814 );
PROVIDE ( conv_str_decimal = 0x40000b24 );
PROVIDE ( conv_str_hex = 0x40000cb8 );
PROVIDE ( convert_para_str = 0x40000a60 );
PROVIDE ( dtm_get_intr_mask = 0x400026d0 );
PROVIDE ( dtm_params_init = 0x4000269c );
PROVIDE ( dtm_set_intr_mask = 0x400026c8 );
PROVIDE ( dtm_set_params = 0x400026dc );
PROVIDE ( eprintf = 0x40001d14 );
PROVIDE ( eprintf_init_buf = 0x40001cb8 );
PROVIDE ( eprintf_to_host = 0x40001d48 );
PROVIDE ( est_get_printf_buf_remain_len = 0x40002494 );
PROVIDE ( est_reset_printf_buf_len = 0x4000249c );
PROVIDE ( ets_bzero = 0x40002ae8 );
PROVIDE ( ets_char2xdigit = 0x40002b74 );
PROVIDE ( ets_delay_us = 0x40002ecc );
PROVIDE ( ets_enter_sleep = 0x400027b8 );
PROVIDE ( ets_external_printf = 0x40002578 );
PROVIDE ( ets_get_cpu_frequency = 0x40002f0c );
PROVIDE ( ets_getc = 0x40002bcc );
PROVIDE ( ets_install_external_printf = 0x40002450 );
PROVIDE ( ets_install_putc1 = 0x4000242c );
PROVIDE ( ets_install_putc2 = 0x4000248c );
PROVIDE ( ets_install_uart_printf = 0x40002438 );
PROVIDE ( ets_intr_lock = 0x40000f74 );
PROVIDE ( ets_intr_unlock = 0x40000f80 );
PROVIDE ( ets_isr_attach = 0x40000f88 );
PROVIDE ( ets_isr_mask = 0x40000f98 );
PROVIDE ( ets_isr_unmask = 0x40000fa8 );
PROVIDE ( ets_memcmp = 0x400018d4 );
PROVIDE ( ets_memcpy = 0x400018b4 );
PROVIDE ( ets_memmove = 0x400018c4 );
PROVIDE ( ets_memset = 0x400018a4 );
PROVIDE ( ets_post = 0x40000e24 );
PROVIDE ( ets_printf = 0x400024cc );
PROVIDE ( ets_putc = 0x40002be8 );
PROVIDE ( ets_rtc_int_register = 0x40002a40 );
PROVIDE ( ets_run = 0x40000e04 );
PROVIDE ( ets_set_idle_cb = 0x40000dc0 );
PROVIDE ( ets_set_user_start = 0x40000fbc );
PROVIDE ( ets_str2macaddr = 0x40002af8 );
PROVIDE ( ets_strcmp = 0x40002aa8 );
PROVIDE ( ets_strcpy = 0x40002a88 );
PROVIDE ( ets_strlen = 0x40002ac8 );
PROVIDE ( ets_strncmp = 0x40002ab8 );
PROVIDE ( ets_strncpy = 0x40002a98 );
PROVIDE ( ets_strstr = 0x40002ad8 );
PROVIDE ( ets_task = 0x40000dd0 );
PROVIDE ( ets_timer_arm = 0x40002cc4 );
PROVIDE ( ets_timer_disarm = 0x40002d40 );
PROVIDE ( ets_timer_done = 0x40002d80 );
PROVIDE ( ets_timer_handler_isr = 0x40002da8 );
PROVIDE ( ets_timer_init = 0x40002e68 );
PROVIDE ( ets_timer_setfn = 0x40002c48 );
PROVIDE ( ets_uart_printf = 0x40002544 );
PROVIDE ( ets_update_cpu_frequency = 0x40002f04 );
PROVIDE ( ets_vprintf = 0x40001f00 );
PROVIDE ( ets_wdt_disable = 0x400030f0 );
PROVIDE ( ets_wdt_enable = 0x40002fa0 );
PROVIDE ( ets_wdt_get_mode = 0x40002f34 );
PROVIDE ( ets_wdt_init = 0x40003170 );
PROVIDE ( ets_wdt_restore = 0x40003158 );
PROVIDE ( ets_write_char = 0x40001da0 );
PROVIDE ( get_first_seg = 0x4000091c );
PROVIDE ( gpio_init = 0x40004c50 );
PROVIDE ( gpio_input_get = 0x40004cf0 );
PROVIDE ( gpio_intr_ack = 0x40004dcc );
PROVIDE ( gpio_intr_handler_register = 0x40004e28 );
PROVIDE ( gpio_intr_pending = 0x40004d88 );
PROVIDE ( gpio_intr_test = 0x40004efc );
PROVIDE ( gpio_output_set = 0x40004cd0 );
PROVIDE ( gpio_pin_intr_state_set = 0x40004d90 );
PROVIDE ( gpio_pin_wakeup_disable = 0x40004ed4 );
PROVIDE ( gpio_pin_wakeup_enable = 0x40004e90 );
PROVIDE ( gpio_register_get = 0x40004d5c );
PROVIDE ( gpio_register_set = 0x40004d04 );
PROVIDE ( hmac_md5 = 0x4000a2cc );
PROVIDE ( hmac_md5_vector = 0x4000a160 );
PROVIDE ( hmac_sha1 = 0x4000ba28 );
PROVIDE ( hmac_sha1_vector = 0x4000b8b4 );
PROVIDE ( lldesc_build_chain = 0x40004f40 );
PROVIDE ( lldesc_num2link = 0x40005050 );
PROVIDE ( lldesc_set_owner = 0x4000507c );
PROVIDE ( main = 0x40000fec );
PROVIDE ( md5_vector = 0x400097ac );
PROVIDE ( mem_calloc = 0x40001c2c );
PROVIDE ( mem_free = 0x400019e0 );
PROVIDE ( mem_init = 0x40001998 );
PROVIDE ( mem_malloc = 0x40001b40 );
PROVIDE ( mem_realloc = 0x40001c6c );
PROVIDE ( mem_trim = 0x40001a14 );
PROVIDE ( mem_zalloc = 0x40001c58 );
PROVIDE ( memcmp = 0x4000dea8 );
PROVIDE ( memcpy = 0x4000df48 );
PROVIDE ( memmove = 0x4000e04c );
PROVIDE ( memset = 0x4000e190 );
PROVIDE ( multofup = 0x400031c0 );
PROVIDE ( pbkdf2_sha1 = 0x4000b840 );
PROVIDE ( phy_get_romfuncs = 0x40006b08 );
PROVIDE ( rand = 0x40000600 );
PROVIDE ( rc4_skip = 0x4000dd68 );
PROVIDE ( recv_packet = 0x40003d08 );
PROVIDE ( remove_head_space = 0x40000a04 );
PROVIDE ( rijndaelKeySetupDec = 0x40008dd0 );
PROVIDE ( rijndaelKeySetupEnc = 0x40009300 );
PROVIDE ( rom_abs_temp = 0x400060c0 );
PROVIDE ( rom_ana_inf_gating_en = 0x40006b10 );
PROVIDE ( rom_cal_tos_v50 = 0x40007a28 );
PROVIDE ( rom_chip_50_set_channel = 0x40006f84 );
PROVIDE ( rom_chip_v5_disable_cca = 0x400060d0 );
PROVIDE ( rom_chip_v5_enable_cca = 0x400060ec );
PROVIDE ( rom_chip_v5_rx_init = 0x4000711c );
PROVIDE ( rom_chip_v5_sense_backoff = 0x4000610c );
PROVIDE ( rom_chip_v5_tx_init = 0x4000718c );
PROVIDE ( rom_dc_iq_est = 0x4000615c );
PROVIDE ( rom_en_pwdet = 0x400061b8 );
PROVIDE ( rom_get_bb_atten = 0x40006238 );
PROVIDE ( rom_get_corr_power = 0x40006260 );
PROVIDE ( rom_get_fm_sar_dout = 0x400062dc );
PROVIDE ( rom_get_noisefloor = 0x40006394 );
PROVIDE ( rom_get_power_db = 0x400063b0 );
PROVIDE ( rom_i2c_readReg = 0x40007268 );
PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c );
PROVIDE ( rom_i2c_writeReg = 0x400072d8 );
PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c );
PROVIDE ( rom_iq_est_disable = 0x40006400 );
PROVIDE ( rom_iq_est_enable = 0x40006430 );
PROVIDE ( rom_linear_to_db = 0x40006484 );
PROVIDE ( rom_mhz2ieee = 0x400065a4 );
PROVIDE ( rom_pbus_dco___SA2 = 0x40007bf0 );
PROVIDE ( rom_pbus_debugmode = 0x4000737c );
PROVIDE ( rom_pbus_enter_debugmode = 0x40007410 );
PROVIDE ( rom_pbus_exit_debugmode = 0x40007448 );
PROVIDE ( rom_pbus_force_test = 0x4000747c );
PROVIDE ( rom_pbus_rd = 0x400074d8 );
PROVIDE ( rom_pbus_set_rxgain = 0x4000754c );
PROVIDE ( rom_pbus_set_txgain = 0x40007610 );
PROVIDE ( rom_pbus_workmode = 0x40007648 );
PROVIDE ( rom_pbus_xpd_rx_off = 0x40007688 );
PROVIDE ( rom_pbus_xpd_rx_on = 0x400076cc );
PROVIDE ( rom_pbus_xpd_tx_off = 0x400076fc );
PROVIDE ( rom_pbus_xpd_tx_on = 0x40007740 );
PROVIDE ( rom_pbus_xpd_tx_on__low_gain = 0x400077a0 );
PROVIDE ( rom_phy_reset_req = 0x40007804 );
PROVIDE ( rom_restart_cal = 0x4000781c );
PROVIDE ( rom_rfcal_pwrctrl = 0x40007eb4 );
PROVIDE ( rom_rfcal_rxiq = 0x4000804c );
PROVIDE ( rom_rfcal_rxiq_set_reg = 0x40008264 );
PROVIDE ( rom_rfcal_txcap = 0x40008388 );
PROVIDE ( rom_rfcal_txiq = 0x40008610 );
PROVIDE ( rom_rfcal_txiq_cover = 0x400088b8 );
PROVIDE ( rom_rfcal_txiq_set_reg = 0x40008a70 );
PROVIDE ( rom_rfpll_reset = 0x40007868 );
PROVIDE ( rom_rfpll_set_freq = 0x40007968 );
PROVIDE ( rom_rxiq_cover_mg_mp = 0x40008b6c );
PROVIDE ( rom_rxiq_get_mis = 0x40006628 );
PROVIDE ( rom_sar_init = 0x40006738 );
PROVIDE ( rom_set_ana_inf_tx_scale = 0x4000678c );
PROVIDE ( rom_set_channel_freq = 0x40006c50 );
PROVIDE ( rom_set_loopback_gain = 0x400067c8 );
PROVIDE ( rom_set_noise_floor = 0x40006830 );
PROVIDE ( rom_set_rxclk_en = 0x40006550 );
PROVIDE ( rom_set_txbb_atten = 0x40008c6c );
PROVIDE ( rom_set_txclk_en = 0x4000650c );
PROVIDE ( rom_set_txiq_cal = 0x40008d34 );
PROVIDE ( rom_start_noisefloor = 0x40006874 );
PROVIDE ( rom_start_tx_tone = 0x400068b4 );
PROVIDE ( rom_stop_tx_tone = 0x4000698c );
PROVIDE ( rom_tx_mac_disable = 0x40006a98 );
PROVIDE ( rom_tx_mac_enable = 0x40006ad4 );
PROVIDE ( rom_txtone_linear_pwr = 0x40006a1c );
PROVIDE ( rom_write_rfpll_sdm = 0x400078dc );
PROVIDE ( roundup2 = 0x400031b4 );
PROVIDE ( rtc_enter_sleep = 0x40002870 );
PROVIDE ( rtc_get_reset_reason = 0x400025e0 );
PROVIDE ( rtc_intr_handler = 0x400029ec );
PROVIDE ( rtc_set_sleep_mode = 0x40002668 );
PROVIDE ( save_rxbcn_mactime = 0x400027a4 );
PROVIDE ( save_tsf_us = 0x400027ac );
PROVIDE ( send_packet = 0x40003c80 );
PROVIDE ( sha1_prf = 0x4000ba48 );
PROVIDE ( sha1_vector = 0x4000a2ec );
PROVIDE ( sip_alloc_to_host_evt = 0x40005180 );
PROVIDE ( sip_get_ptr = 0x400058a8 );
PROVIDE ( sip_get_state = 0x40005668 );
PROVIDE ( sip_init_attach = 0x4000567c );
PROVIDE ( sip_install_rx_ctrl_cb = 0x4000544c );
PROVIDE ( sip_install_rx_data_cb = 0x4000545c );
PROVIDE ( sip_post = 0x400050fc );
PROVIDE ( sip_post_init = 0x400056c4 );
PROVIDE ( sip_reclaim_from_host_cmd = 0x4000534c );
PROVIDE ( sip_reclaim_tx_data_pkt = 0x400052c0 );
PROVIDE ( sip_send = 0x40005808 );
PROVIDE ( sip_to_host_chain_append = 0x40005864 );
PROVIDE ( sip_to_host_evt_send_done = 0x40005234 );
PROVIDE ( slc_add_credits = 0x400060ac );
PROVIDE ( slc_enable = 0x40005d90 );
PROVIDE ( slc_from_host_chain_fetch = 0x40005f24 );
PROVIDE ( slc_from_host_chain_recycle = 0x40005e94 );
PROVIDE ( slc_init_attach = 0x40005c50 );
PROVIDE ( slc_init_credit = 0x4000608c );
PROVIDE ( slc_pause_from_host = 0x40006014 );
PROVIDE ( slc_reattach = 0x40005c1c );
PROVIDE ( slc_resume_from_host = 0x4000603c );
PROVIDE ( slc_select_tohost_gpio = 0x40005dc0 );
PROVIDE ( slc_select_tohost_gpio_mode = 0x40005db8 );
PROVIDE ( slc_send_to_host_chain = 0x40005de4 );
PROVIDE ( slc_set_host_io_max_window = 0x40006068 );
PROVIDE ( slc_to_host_chain_recycle = 0x40005f10 );
PROVIDE ( software_reset = 0x4000264c );
PROVIDE ( spi_flash_attach = 0x40004644 );
PROVIDE ( srand = 0x400005f0 );
PROVIDE ( strcmp = 0x4000bdc8 );
PROVIDE ( strcpy = 0x4000bec8 );
PROVIDE ( strlen = 0x4000bf4c );
PROVIDE ( strncmp = 0x4000bfa8 );
PROVIDE ( strncpy = 0x4000c0a0 );
PROVIDE ( strstr = 0x4000e1e0 );
PROVIDE ( timer_insert = 0x40002c64 );
PROVIDE ( uartAttach = 0x4000383c );
PROVIDE ( uart_baudrate_detect = 0x40003924 );
PROVIDE ( uart_buff_switch = 0x400038a4 );
PROVIDE ( uart_div_modify = 0x400039d8 );
PROVIDE ( uart_rx_intr_handler = 0x40003bbc );
PROVIDE ( uart_rx_one_char = 0x40003b8c );
PROVIDE ( uart_rx_one_char_block = 0x40003b64 );
PROVIDE ( uart_rx_readbuff = 0x40003ec8 );
PROVIDE ( uart_tx_one_char = 0x40003b30 );
PROVIDE ( wepkey_128 = 0x4000bc40 );
PROVIDE ( wepkey_64 = 0x4000bb3c );
PROVIDE ( xthal_bcopy = 0x40000688 );
PROVIDE ( xthal_copy123 = 0x4000074c );
PROVIDE ( xthal_get_ccompare = 0x4000dd4c );
PROVIDE ( xthal_get_ccount = 0x4000dd38 );
PROVIDE ( xthal_get_interrupt = 0x4000dd58 );
PROVIDE ( xthal_get_intread = 0x4000dd58 );
PROVIDE ( xthal_memcpy = 0x400006c4 );
PROVIDE ( xthal_set_ccompare = 0x4000dd40 );
PROVIDE ( xthal_set_intclear = 0x4000dd60 );
PROVIDE ( xthal_spill_registers_into_stack_nw = 0x4000e320 );
PROVIDE ( xthal_window_spill = 0x4000e324 );
PROVIDE ( xthal_window_spill_nw = 0x4000e320 );
PROVIDE ( Te0 = 0x3fffccf0 );
PROVIDE ( Td0 = 0x3fffd100 );
PROVIDE ( Td4s = 0x3fffd500);
PROVIDE ( rcons = 0x3fffd0f0);
PROVIDE ( UartDev = 0x3fffde10 );

View File

@ -0,0 +1,14 @@
PROVIDE ( GPIO = 0x60000300);
PROVIDE ( uart0 = 0x60000000 );
PROVIDE ( uart1 = 0x60000f00 );
PROVIDE ( frc1 = 0x60000600 );
PROVIDE ( rtc_sys_info = 0x60001100 );
PROVIDE ( SLC = 0x60000B00 );
PROVIDE ( I2S = 0x60000e00 );
PROVIDE ( SPI1 = 0x60000100 );
PROVIDE ( SPI0 = 0x60000200 );

View File

@ -1,17 +1,15 @@
/**
* This linker script is a modified version of eagle.app.v6.ld that
* was generated from xt-genldscripts.tpp for LSP and shipped with
* ESP8266_NONOS_SDK
*/
/* Linker Script for ld -N */
* This linker script is a combined and modified version of esp8266.ld and
* esp8266.common.ld from ESP8266-RTOS-SDK.
*/
MEMORY
{
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40210000, len = 0x5C000
dram0_0_seg : org = 0x3FFE8000, len = 0x18000
iram1_0_seg : org = 0x40100000, len = 0xC000
irom0_0_seg : org = 0x40200010 + 0x10000, len = 0x80000 - 0x10 - 0x10000
rtc_seg : org = 0x60001200, len = 0x200
}
PHDRS
@ -25,7 +23,7 @@ PHDRS
/* Default entry point: */
ENTRY(_call_user_start)
ENTRY(call_user_start)
EXTERN(_DebugExceptionVector)
EXTERN(_DoubleExceptionVector)
EXTERN(_KernelExceptionVector)
@ -50,17 +48,6 @@ _memmap_cacheattr_wt_allvalid = 0x22222112;
_memmap_cacheattr_bp_allvalid = 0x22222222;
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
/* ROM variables */
/* source: disassembly of boot rom at https://github.com/trebisky/esp8266 */
PROVIDE( ets_task_min_prio = 0x3fffc6fc );
PROVIDE( ets_idle_cb = 0x3fffdab0 );
PROVIDE( ets_idle_arg = 0x3fffdab4 );
PROVIDE( ets_task_exec_mask = 0x3fffdab8 );
PROVIDE( ets_task_tab = 0x3fffdac0 );
PROVIDE( flashchip = 0x3fffc714 );
PROVIDE( sdk_flashchip = 0x3fffc718 );
PROVIDE( ets_phy_mactime = 0x3ff20a00 );
SECTIONS
{
@ -88,6 +75,15 @@ SECTIONS
_dport0_data_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
/* RTC memory holds user's data/rodata */
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
*(.rtc.data)
*(.rtc.rodata)
_rtc_data_end = ABSOLUTE(.);
} > rtc_seg
.data : ALIGN(4)
{
_data_start = ABSOLUTE(.);
@ -108,26 +104,30 @@ SECTIONS
.rodata : ALIGN(4)
{
_rodata_start = ABSOLUTE(.);
*(.sdk.version)
/* TODO put only necessary .rodata to dram
/* TODO put only necessary .rodata to dram */
/* *(.rodata .rodata.*) */
*libc.a:*.o(.rodata.* .rodata)
*core.a:*(.rodata.* .rodata)
*cpu.a:*(.rodata .rodata.*)
*/
*(.rodata .rodata.*)
*libpp.a:(.rodata.* .rodata)
*liblog.a:(.rodata.* .rodata)
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
@ -140,7 +140,7 @@ SECTIONS
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
. = ALIGN(4); /* this table MUST be 4-byte aligned */
. = ALIGN(4); /* this table MUST be 4-byte aligned */
_bss_table_start = ABSOLUTE(.);
LONG(_bss_start)
LONG(_bss_end)
@ -165,7 +165,6 @@ SECTIONS
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
_sheap = ABSOLUTE(.);
@ -173,40 +172,39 @@ SECTIONS
} >dram0_0_seg :dram0_0_bss_phdr
/* ETS system memory starts at 0x3FFFC000 which is the top of the heap for the app */
. = 0x3FFFC000;
. = 0x3FFFFFF0;
_heap_top = ABSOLUTE(.);
_eheap = ABSOLUTE(.);
.text : ALIGN(4)
.text : ALIGN(4) /* IRAM */
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.UserEnter.text)
LONG(_text_start)
. = ALIGN(16);
*(.DebugExceptionVector.text)
*(.DebugExceptionVector.text) /* 0x40100010 */
. = ALIGN(16);
*(.NMIExceptionVector.text)
*(.NMIExceptionVector.text) /* 0x40100020 */
. = ALIGN(16);
*(.KernelExceptionVector.text)
*(.KernelExceptionVector.text) /* 0x40100030 */
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
*(.UserExceptionVector.text)
*(.UserExceptionVector.text) /* 0x40100050 */
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
*(.DoubleExceptionVector.text)
*(.DoubleExceptionVector.text) /* 0x40100070 */
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN (16);
*(.UserExceptionTrampoline.text)
*(.UserExceptionTrampoline.text) /* 0x40100090 */
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
@ -214,30 +212,48 @@ SECTIONS
/* normal code should be in irom0 */
/*
*(.literal .text .literal.* .text.* .stub)
*(.gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.literal .text)
*core.a:*(.literal .text .literal.* .text.*)
*/
*gdbstub.a:*(.literal .text .literal.* .text.*)
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
/* RIOT-OS compiled source files that use the .iram1.* section names for IRAM
functions, etc. */
*(.iram1.*)
*(.iram1 .iram1.*)
/* SDK libraries expect their .text sections to link to iram, not irom */
*libcrypto.a:*(.literal .text)
*libmain.a:*(.literal .text .literal.* .text.*)
*libnet80211.a:*(.literal .text)
*libpp.a:*(.literal .text .literal.* .text.*)
*libphy.a:*(.literal .text .literal.* .text.*)
*libwpa.a:*(.literal .text)
*libwpa2.a:*(.literal .text)
*liblwip.a:*(.literal .text)
/* SDK libraries that expect their .text or .data sections to link to iram */
/* TODO *libcore.a:(.bss .data .bss.* .data.* COMMON) */
*esp_idf_spi_flash.a:spi_flash_raw.o(.literal .text .literal.* .text.*)
*esp_idf_esp8266.a:ets_printf.o(.literal .text .literal.* .text.*)
/*
*cpu.a:*.o(.literal .text .literal.* .text.*)
*/
*core.a:sched.o(.literal .text .literal.* .text.*)
*esp_wifi.a:*(.literal .text .literal.* .text.*)
*freertos.a:*(.literal .text .literal.* .text.*)
*periph.a:*(.literal .text .literal.* .text.*)
*xtimer.a:*(.literal .text .literal.* .text.*)
*libhal.a:clock.o(.literal .text .literal.* .text.*)
*libhal.a:int_asm--set_intclear.o(.literal .text .literal.* .text.*)
*libpp.a:esf_buf.o(.literal .text .literal.* .text.*)
*libpp.a:lmac.o(.literal .text .literal.* .text.*)
*libpp.a:pp.o(.literal .text .literal.* .text.*)
*libpp.a:rate_control.o(.literal .text .literal.* .text.*)
*libpp.a:trc.o(.literal .text .literal.* .text.*)
*libpp.a:wdev.o(.literal .text .literal.* .text.*)
*libphy.a:phy.o(.literal .text .literal.* .text.*)
*libphy.a:phy_chip_v6_cal.o(.literal .text .literal.* .text.*)
*libphy.a:phy_sleep.o(.literal .text .literal.* .text.*)
/* Xtensa basic functionality written in assembler should be placed in iram */
*xtensa.a:*(.literal .text .literal.* .text.*)
/* libgcc integer functions also need to be in .text, as some are called before
flash is mapped (also performance)
*/
/* libgcc functions required for debugging have to be in IRAM */
*libgcc.a:unwind-dw2.o(.literal .text .literal.* .text.*)
/* libgcc integer functions also need to be in .text */
/* some are called before flash is mapped and also for performance) */
*libgcc.a:*i3.o(.literal .text .literal.* .text.*)
*libgcc.a:*mulsf3.o(.literal .text .literal.* .text.*)
@ -245,6 +261,7 @@ SECTIONS
*libgcc.a:*fixsfsi.o(.literal .text .literal.* .text.*)
/* libc also in IRAM */
/*
*libc.a:*malloc.o(.literal .text .literal.* .text.*)
*libc.a:*mallocr.o(.literal .text .literal.* .text.*)
*libc.a:*freer.o(.literal .text .literal.* .text.*)
@ -260,6 +277,7 @@ SECTIONS
*libc.a:*printf.o(.literal .text .literal.* .text.*)
*libc.a:*findfp.o(.literal .text .literal.* .text.*)
*libc.a:*fputwc.o(.literal .text .literal.* .text.*)
*/
enc28j60.a:*(.literal .text .literal.* .text.*)
@ -274,15 +292,18 @@ SECTIONS
{
_irom0_text_start = ABSOLUTE(.);
*libmbedtls.a:(.literal .text .literal.* .text.*)
/* RIOT-OS compiled code goes into IROM by default
(except for libgcc which is matched above.) */
*(.literal .text .literal.* .text.* .rodata .rodata.*)
/* RIOT-OS compiled code and RO data go into IROM by default */
*(.literal .text .literal.* .text.*)
*(.rodata .rodata.*)
/* Anything explicitly marked as "irom" or "irom0" should go here */
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
. = ALIGN(16);
__start_ksymatabesp_socket = .;
*(ksymatabesp_socket)
__stop_ksymatabesp_socket = .;
_irom0_text_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr

View File

@ -1,322 +0,0 @@
/**
* This linker script is a modified version of eagle.app.v6.ld that
* was generated from xt-genldscripts.tpp for LSP and shipped with
* ESP8266_NONOS_SDK
*/
/* Linker Script for ld -N */
MEMORY
{
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40210000, len = 0x5C000
}
PHDRS
{
dport0_0_phdr PT_LOAD;
dram0_0_phdr PT_LOAD;
dram0_0_bss_phdr PT_LOAD;
iram1_0_phdr PT_LOAD;
irom0_0_phdr PT_LOAD;
}
/* Default entry point: */
ENTRY(call_user_start)
EXTERN(_DebugExceptionVector)
EXTERN(_DoubleExceptionVector)
EXTERN(_KernelExceptionVector)
EXTERN(_NMIExceptionVector)
EXTERN(_UserExceptionVector)
PROVIDE(_memmap_vecbase_reset = 0x40000000);
/* Various memory-map dependent cache attribute settings: */
_memmap_cacheattr_wb_base = 0x00000110;
_memmap_cacheattr_wt_base = 0x00000110;
_memmap_cacheattr_bp_base = 0x00000220;
_memmap_cacheattr_unused_mask = 0xFFFFF00F;
_memmap_cacheattr_wb_trapnull = 0x2222211F;
_memmap_cacheattr_wba_trapnull = 0x2222211F;
_memmap_cacheattr_wbna_trapnull = 0x2222211F;
_memmap_cacheattr_wt_trapnull = 0x2222211F;
_memmap_cacheattr_bp_trapnull = 0x2222222F;
_memmap_cacheattr_wb_strict = 0xFFFFF11F;
_memmap_cacheattr_wt_strict = 0xFFFFF11F;
_memmap_cacheattr_bp_strict = 0xFFFFF22F;
_memmap_cacheattr_wb_allvalid = 0x22222112;
_memmap_cacheattr_wt_allvalid = 0x22222112;
_memmap_cacheattr_bp_allvalid = 0x22222222;
PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
/* System task handling variables */
/* source: disassembly of boot rom at https://github.com/trebisky/esp8266 */
PROVIDE( ets_task_min_prio = 0x3fffc6fc );
PROVIDE( ets_idle_cb = 0x3fffdab0 );
PROVIDE( ets_idle_arg = 0x3fffdab4 );
PROVIDE( ets_task_exec_mask = 0x3fffdab8 );
PROVIDE( ets_task_tab = 0x3fffdac0 );
PROVIDE( flashchip = 0x3fffc714 );
PROVIDE( sdk_flashchip = 0x3fffc718 );
PROVIDE( _xt_interrupt_table = 0x3fffc200 );
SECTIONS
{
.dport0.rodata : ALIGN(4)
{
_dport0_rodata_start = ABSOLUTE(.);
*(.dport0.rodata)
*(.dport.rodata)
_dport0_rodata_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.dport0.literal : ALIGN(4)
{
_dport0_literal_start = ABSOLUTE(.);
*(.dport0.literal)
*(.dport.literal)
_dport0_literal_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.dport0.data : ALIGN(4)
{
_dport0_data_start = ABSOLUTE(.);
*(.dport0.data)
*(.dport.data)
_dport0_data_end = ABSOLUTE(.);
} >dport0_0_seg :dport0_0_phdr
.data : ALIGN(4)
{
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_phdr
/*
* .rodata sections that are placed in RAM
*
* Usually, all .rodata sections are placed in RAM by the Espressif SDK
* since IROM (flash) access requires 32-bit word aligned reads.
*
* However, thanks to the LoadStoreError handler from esp-open-rtos which is
* also used in RIOT-OS, it is possible to place .rodata sections in IROM
* (flash) to save RAM resources.
*
* Only .rodata data sections of compilation units that may be executed
* while SPI flash is not mapped have to be stored in RAM. These are IRAM
* functions that are called from interrupt context or SPI flash management
* functions. Such compilation units have to be listed here.
*
* Furthermore, compilation units with constant data that are performance-
* critical should be listed here as well.
*/
.rodata : ALIGN(4)
{
_rodata_start = ABSOLUTE(.);
*(.sdk.version)
*core.a:*(.rodata.* .rodata)
*cpu.a:*(.rodata .rodata.*)
*esp.a:*(.rodata .rodata.*)
*esp_now.a:*(.rodata .rodata.*)
*esp_wifi.a:*(.rodata .rodata.*)
*periph.a:*(.rodata.* .rodata)
*sdk.a:*(.rodata .rodata.*)
*xtensa.a:*(.rodata .rodata.*)
*libc.a:*.o(.rodata.* .rodata)
*libpp.a:wdev.o(.rodata.* .rodata)
*libmain.a:spi_flash.o(.rodata.* .rodata)
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame)
/* C++ constructor and destructor tables, properly ordered: */
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
. = ALIGN(4); /* this table MUST be 4-byte aligned */
_bss_table_start = ABSOLUTE(.);
LONG(_bss_start)
LONG(_bss_end)
_bss_table_end = ABSOLUTE(.);
_rodata_end = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_phdr
.bss ALIGN(8) (NOLOAD) : ALIGN(4)
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
_sheap = ABSOLUTE(.);
_heap_start = ABSOLUTE(.);
} >dram0_0_seg :dram0_0_bss_phdr
/* ETS system memory starts at 0x3FFFC000 which is the top of the heap for the app */
. = 0x3FFFC000;
_heap_top = ABSOLUTE(.);
_eheap = ABSOLUTE(.);
.text : ALIGN(4)
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.UserEnter.text)
. = ALIGN(16);
*(.DebugExceptionVector.text)
. = ALIGN(16);
*(.NMIExceptionVector.text)
. = ALIGN(16);
*(.KernelExceptionVector.text)
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
*(.UserExceptionVector.text)
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN(16);
*(.DoubleExceptionVector.text)
LONG(0)
LONG(0)
LONG(0)
LONG(0)
. = ALIGN (16);
*(.UserExceptionTrampoline.text)
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
/* normal code should be in irom0 */
/*
*(.literal .text .literal.* .text.* .stub)
*(.gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*/
/* RIOT-OS compiled source files that use the .iram1.* section names for IRAM
functions, etc. */
*(.iram1.*)
/* SDK libraries expect their .text sections to link to iram, not irom */
*libcrypto.a:*(.literal .text)
*libmain.a:*(.literal .text .literal.* .text.*)
*libnet80211.a:*(.literal .text)
*libpp.a:*(.literal .text .literal.* .text.*)
*libphy.a:*(.literal .text .literal.* .text.*)
*libwpa.a:*(.literal .text)
*libwpa2.a:*(.literal .text)
*liblwip.a:*(.literal .text)
/* Xtensa basic functionality written in assembler should be placed in iram */
*xtensa.a:*(.literal .text .literal.* .text.*)
/* libgcc integer functions also need to be in .text, as some are called before
flash is mapped (also performance) */
*libgcc.a:*i3.o(.literal .text .literal.* .text.*)
*libgcc.a:*mulsf3.o(.literal .text .literal.* .text.*)
*libgcc.a:*divsf3.o(.literal .text .literal.* .text.*)
*libgcc.a:*fixsfsi.o(.literal .text .literal.* .text.*)
/* libc also in IRAM */
*libc.a:*malloc.o(.literal .text .literal.* .text.*)
*libc.a:*mallocr.o(.literal .text .literal.* .text.*)
*libc.a:*freer.o(.literal .text .literal.* .text.*)
*libc.a:*memchr.o(.literal .text .literal.* .text.*)
*libc.a:*memcpy.o(.literal .text .literal.* .text.*)
*libc.a:*memset.o(.literal .text .literal.* .text.*)
*libc.a:*memcmp.o(.literal .text .literal.* .text.*)
*libc.a:*memmove.o(.literal .text .literal.* .text.*)
*libc.a:*rand.o(.literal .text .literal.* .text.*)
*libc.a:*bzero.o(.literal .text .literal.* .text.*)
*libc.a:*lock.o(.literal .text .literal.* .text.*)
*libc.a:*findfp.o(.literal .text .literal.* .text.*)
*libc.a:*fputwc.o(.literal .text .literal.* .text.*)
enc28j60.a:*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_etext = .;
} >iram1_0_seg :iram1_0_phdr
.irom0.text : ALIGN(4)
{
_irom0_text_start = ABSOLUTE(.);
*libmbedtls.a:(.literal .text .literal.* .text.*)
/* RIOT-OS compiled code goes into IROM by default
(except for functions with section names defined in .text above.) */
*(.literal .text .literal.* .text.* .rodata .rodata.*)
/* Anything explicitly marked as "irom" or "irom0" should go here */
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
_irom0_text_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr
.lit4 : ALIGN(4)
{
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
} >iram1_0_seg :iram1_0_phdr
}

View File

@ -0,0 +1,60 @@
SPI_sector_erase = 0x400040c0;
SPI_page_program = 0x40004174;
SPI_read_data = 0x400042ac;
SPI_read_status = 0x400043c8;
SPI_write_status = 0x40004400;
SPI_write_enable = 0x4000443c;
Wait_SPI_Idle = 0x4000448c;
Enable_QMode = 0x400044c0;
Disable_QMode = 0x40004508;
Cache_Read_Enable = 0x40004678;
Cache_Read_Disable = 0x400047f0;
lldesc_build_chain = 0x40004f40;
lldesc_num2link = 0x40005050;
lldesc_set_owner = 0x4000507c;
__adddf3 = 0x4000c538;
__addsf3 = 0x4000c180;
__divdf3 = 0x4000cb94;
__divdi3 = 0x4000ce60;
__divsi3 = 0x4000dc88;
__extendsfdf2 = 0x4000cdfc;
__fixdfsi = 0x4000ccb8;
__fixunsdfsi = 0x4000cd00;
__fixunssfsi = 0x4000c4c4;
__floatsidf = 0x4000e2f0;
__floatsisf = 0x4000e2ac;
__floatunsidf = 0x4000e2e8;
__floatunsisf = 0x4000e2a4;
__muldf3 = 0x4000c8f0;
__muldi3 = 0x40000650;
__mulsf3 = 0x4000c3dc;
__subdf3 = 0x4000c688;
__subsf3 = 0x4000c268;
__truncdfsf2 = 0x4000cd5c;
__udivdi3 = 0x4000d310;
__udivsi3 = 0x4000e21c;
__umoddi3 = 0x4000d770;
__umodsi3 = 0x4000e268;
__umulsidi3 = 0x4000dcf0;
bzero = 0x4000de84;
memcmp = 0x4000dea8;
memcpy = 0x4000df48;
memmove = 0x4000e04c;
memset = 0x4000e190;
strcmp = 0x4000bdc8;
strcpy = 0x4000bec8;
strlen = 0x4000bf4c;
strncmp = 0x4000bfa8;
strncpy = 0x4000c0a0;
strstr = 0x4000e1e0;
gpio_input_get = 0x40004cf0;
gpio_pin_wakeup_disable = 0x40004ed4;
gpio_pin_wakeup_enable = 0x40004e90;
ets_io_vprintf = 0x40001f00;

View File

@ -1,3 +1,3 @@
MODULE = periph
include $(RIOTBASE)/Makefile.base
include $(RIOTMAKE)/periph.mk

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
@ -28,10 +28,10 @@
#include "periph_conf.h"
#include "board.h"
#include "common.h"
#include "esp_common.h"
#include "sdk/sdk.h"
#if defined(ADC_NUMOF) && ADC_NUMOF > 0
extern uint16_t test_tout(void);
int adc_init(adc_t line)
{
@ -47,11 +47,10 @@ int adc_sample(adc_t line, adc_res_t res)
CHECK_PARAM_RET (line < ADC_NUMOF, -1)
CHECK_PARAM_RET (res == ADC_RES_10BIT, -1)
#ifdef MODULE_ESP_SDK
return system_adc_read ();
#else
return test_tout(false);
#endif
return test_tout();
}
#endif
void adc_print_config(void)
{
printf("\tADC\t\tpins=[ A0 ]\n");
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -18,25 +18,42 @@
* @}
*/
#define ENABLE_DEBUG (0)
#include "debug.h"
#if MODULE_MTD
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "board.h"
#include "common.h"
#include "esp_common.h"
#include "irq_arch.h"
#include "log.h"
#include "mtd.h"
#include "c_types.h"
#include "esp/spiflash.h"
#include "spi_flash.h"
#include "sdk/rom.h"
#include "esp_flash_data_types.h"
#include "esp_partition.h"
#define SDK_FLASH_FUNCTIONS
#ifdef MCU_ESP32
#include "rom/cache.h"
#include "rom/spi_flash.h"
#include "esp_spi_flash.h"
#else /* MCU_ESP32 */
#include "rom_functions.h"
#include "spi_flash.h"
#endif /* MCU_ESP32 */
#define ENABLE_DEBUG (0)
#include "debug.h"
#define ESP_PART_TABLE_ADDR 0x8000 /* TODO configurable as used in Makefile.include */
#define ESP_PART_TABLE_SIZE 0xC00
#define ESP_PART_ENTRY_SIZE 0x20
#define ESP_PART_ENTRY_MAGIC ESP_PARTITION_MAGIC
/* the external pointer to the system MTD device */
mtd_dev_t* mtd0 = 0;
@ -44,6 +61,18 @@ mtd_dev_t* mtd0 = 0;
mtd_dev_t _flash_dev;
mtd_desc_t _flash_driver;
#ifdef MCU_ESP8266
/* for source code compatibility with ESP32 SDK */
#define esp_rom_spiflash_chip_t esp_spi_flash_chip_t
#define g_rom_flashchip flashchip
/* defined in vendor/esp-idf/spi_flash.c */
extern esp_spi_flash_chip_t flashchip;
extern uint32_t spi_flash_get_id(void);
#endif /* MCU_ESP8266 */
/* forward declaration of mtd functions */
static int _flash_init (mtd_dev_t *dev);
static int _flash_read (mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size);
@ -55,60 +84,420 @@ static uint32_t _flash_beg; /* first byte addr of the flash drive in SPI flash
static uint32_t _flash_end; /* first byte addr after the flash drive in SPI flash */
static uint32_t _flash_size; /* resulting size of the flash drive in SPI flash */
#define SPIFFS_FLASH_BEGIN 0x80000 /* TODO determine real possible value */
static esp_rom_spiflash_chip_t* _flashchip = NULL;
void flash_drive_init (void)
/* flash_id determines the flash size in kByte */
static const uint32_t flash_sizes[] = {
256, /* last byte of id is 0x12 */
512, /* last byte of id is 0x13 */
1 * 1024, /* last byte of id is 0x14 */
2 * 1024, /* last byte of id is 0x15 */
4 * 1024, /* last byte of id is 0x16 */
8 * 1024, /* last byte of id is 0x17 */
16 * 1024 /* last byte of id is 0x18 */
};
void spi_flash_drive_init (void)
{
DEBUG("%s\n", __func__);
_flashchip = &g_rom_flashchip;
assert(_flashchip);
#ifdef MCU_ESP8266
_flashchip->deviceId = spi_flash_get_id();
uint8_t devid_lb = _flashchip->deviceId >> 16 & 0xff;
if (devid_lb >= 0x12 && devid_lb <= 0x18) {
_flashchip->chip_size = flash_sizes[devid_lb - 0x12] << 10;
}
else {
LOG_TAG_WARNING("spi_flash", "could not determine flash size, "
"4 MBytes are used as default size\n");
_flashchip->chip_size = 4 << 20;
}
#endif /* MCU_ESP8266 */
_flash_driver.init = &_flash_init;
_flash_driver.read = &_flash_read;
_flash_driver.write = &_flash_write;
_flash_driver.erase = &_flash_erase;
_flash_driver.power = &_flash_power;
_flash_beg = SPIFFS_FLASH_BEGIN;
_flash_end = flashchip->chip_size - 5 * flashchip->sector_size;
/* first, set the beginning of flash to 0x0 to read partition table */
_flash_beg = 0x0;
_flash_end = _flashchip->chip_size - 5 * _flashchip->sector_size;
_flash_size = _flash_end - _flash_beg;
/* read in partition table an determine the top of all partitions */
uint32_t part_addr = ESP_PART_TABLE_ADDR;
uint8_t part_buf[ESP_PART_ENTRY_SIZE];
bool part_read = true;
uint32_t part_top = 0;
esp_partition_info_t* part = (esp_partition_info_t*)part_buf;
while (part_read && part_addr < ESP_PART_TABLE_ADDR + ESP_PART_TABLE_SIZE) {
spi_flash_read (part_addr, (void*)part_buf, ESP_PART_ENTRY_SIZE);
if (part->magic == ESP_PART_ENTRY_MAGIC) {
DEBUG("%s partition @%08x size=%08x label=%s\n", __func__,
part->pos.offset, part->pos.size, part->label);
if (part->pos.offset + part->pos.size > part_top) {
part_top = part->pos.offset + part->pos.size;
}
part_addr += ESP_PART_ENTRY_SIZE;
}
else {
part_read = false;
}
}
#ifdef MCU_ESP32
/* map the partition top address to next higher multiple of 0x100000 (1 MB) */
part_top = (part_top + 0x100000) & ~0xfffff;
#else /* MCU_ESP32 */
/* map the partition top address to next higher multiple of 0x80000 (512 kB) */
part_top = (part_top + 0x80000) & ~0x7ffff;
#endif /* MCU_ESP32 */
/*
* if flash drive start address is not configured, use the determined
* one otherwise check the configured one and use it
*/
#if SPI_FLASH_DRIVE_START
if (part_top > SPI_FLASH_DRIVE_START) {
LOG_TAG_ERROR("spi_flash", "configured MTD start address in SPI Flash is to less\n");
}
else if (SPI_FLASH_DRIVE_START % _flashchip->sector_size) {
LOG_TAG_ERROR("spi_flash", "configured start address has to be a "
"multiple of %d byte\n", _flashchip->sector_size);
part_top = ((SPI_FLASH_DRIVE_START +
_flashchip->sector_size)) & ~(_flashchip->sector_size-1);
}
else {
part_top = SPI_FLASH_DRIVE_START;
}
#endif
/* second, change flash parameters according to partition table */
_flash_beg = part_top;
_flash_end = _flashchip->chip_size - 5 * _flashchip->sector_size;
_flash_size = _flash_end - _flash_beg; /* MUST be at least 3 sectors (0x3000) */
LOG_TAG_INFO("spi_flash", "MTD in SPI flash starts at address 0x%08x "
"with a size of %d kbytes\n", _flash_beg, _flash_size >> 10);
_flash_dev.driver = &_flash_driver;
_flash_dev.sector_count = _flash_size / flashchip->sector_size;
_flash_dev.sector_count = _flash_size / _flashchip->sector_size;
mtd0 = &_flash_dev;
_flash_dev.pages_per_sector = flashchip->sector_size / flashchip->page_size;
_flash_dev.page_size = flashchip->page_size;
_flash_dev.pages_per_sector = _flashchip->sector_size / _flashchip->page_size;
_flash_dev.page_size = _flashchip->page_size;
DEBUG("%s flashchip chip_size=%d block_size=%d sector_size=%d page_size=%d\n", __func__,
flashchip->chip_size, flashchip->block_size,
flashchip->sector_size, flashchip->page_size);
_flashchip->chip_size, _flashchip->block_size,
_flashchip->sector_size, _flashchip->page_size);
DEBUG("%s flash_dev sector_count=%d pages_per_sector=%d page_size=%d\n", __func__,
_flash_dev.sector_count, _flash_dev.pages_per_sector, _flash_dev.page_size);
DEBUG("\n");
}
#ifdef MCU_ESP32
#define RETURN_WITH_ESP_ERR_CODE(err) do { \
switch (err) { \
case ESP_ROM_SPIFLASH_RESULT_OK : return ESP_OK; \
case ESP_ROM_SPIFLASH_RESULT_ERR : return ESP_ERR_FLASH_OP_FAIL; \
case ESP_ROM_SPIFLASH_RESULT_TIMEOUT: return ESP_ERR_FLASH_OP_TIMEOUT; \
} \
return ESP_FAIL; \
} while(0)
uint8_t _flash_buf[ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM];
esp_err_t IRAM_ATTR spi_flash_read(size_t addr, void *buff, size_t size)
{
DEBUG("%s addr=%08x size=%u buf=%p\n", __func__, addr, size, buff);
CHECK_PARAM_RET (buff != NULL, -ENOTSUP);
/* size must be within the flash address space */
CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW);
int result = ESP_ROM_SPIFLASH_RESULT_OK;
uint32_t len = size;
/* if addr is not 4 byte aligned, we need to read the first full word */
if (addr & 0x3) {
uint32_t word_addr = addr & ~0x3;
uint32_t pos_in_word = addr & 0x3;
uint32_t len_in_word = 4 - pos_in_word;
len_in_word = (len_in_word < len) ? len_in_word : len;
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result = esp_rom_spiflash_read (word_addr, (uint32_t*)_flash_buf, 4);
memcpy(buff, _flash_buf + pos_in_word, len_in_word);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_in_word;
addr += len_in_word;
len -= len_in_word;
}
/* read all full words, maximum ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM
in one read operation */
while (len > 4 && result == ESP_ROM_SPIFLASH_RESULT_OK) {
uint32_t len_full_words = len & ~0x3;
if (len_full_words > ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM) {
len_full_words = ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM;
}
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, len_full_words);
memcpy(buff, _flash_buf, len_full_words);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_full_words;
addr += len_full_words;
len -= len_full_words;
}
/* if there is some remaining, we need to prepare last word */
if (len && result == ESP_ROM_SPIFLASH_RESULT_OK) {
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, 4);
memcpy(buff, _flash_buf, len);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
}
/* return with the ESP-IDF error code that is mapped from ROM error code */
RETURN_WITH_ESP_ERR_CODE(result);
}
esp_err_t IRAM_ATTR spi_flash_write(size_t addr, const void *buff, size_t size)
{
DEBUG("%s addr=%08x size=%u buf=%p\n", __func__, addr, size, buff);
CHECK_PARAM_RET (buff != NULL, -ENOTSUP);
/* size must be within the flash address space */
CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW);
/* prepare for write access */
int result = esp_rom_spiflash_unlock();
uint32_t len = size;
/* if addr is not 4 byte aligned, we need to prepare first full word */
if (addr & 0x3 && result == ESP_ROM_SPIFLASH_RESULT_OK) {
uint32_t word_addr = addr & ~0x3;
uint32_t pos_in_word = addr & 0x3;
uint32_t len_in_word = 4 - pos_in_word;
len_in_word = (len_in_word < len) ? len_in_word : len;
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (word_addr, (uint32_t*)_flash_buf, 4);
memcpy(_flash_buf + pos_in_word, buff, len_in_word);
result |= esp_rom_spiflash_write (word_addr, (uint32_t*)_flash_buf, 4);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_in_word;
addr += len_in_word;
len -= len_in_word;
}
/* write all full words, maximum ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM
in one write operation */
while (len > 4 && result == ESP_ROM_SPIFLASH_RESULT_OK) {
uint32_t len_full_words = len & ~0x3;
if (len_full_words > ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM) {
len_full_words = ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM;
}
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
memcpy(_flash_buf, buff, len_full_words);
result |= esp_rom_spiflash_write (addr, (uint32_t*)_flash_buf, len_full_words);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
buff = (uint8_t*)buff + len_full_words;
addr += len_full_words;
len -= len_full_words;
}
/* if there is some remaining, we need to prepare last word */
if (len && result == ESP_ROM_SPIFLASH_RESULT_OK) {
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
result |= esp_rom_spiflash_read (addr, (uint32_t*)_flash_buf, 4);
memcpy(_flash_buf, buff, len);
result |= esp_rom_spiflash_write (addr, (uint32_t*)_flash_buf, 4);
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
}
/* reset write access */
esp_rom_spiflash_lock();
/* return with the ESP-IDF error code that is mapped from ROM error code */
RETURN_WITH_ESP_ERR_CODE(result);
}
esp_err_t IRAM_ATTR spi_flash_erase_sector(size_t sector)
{
return spi_flash_erase_range(sector * _flashchip->sector_size, 1);
}
esp_err_t IRAM_ATTR spi_flash_erase_range(size_t addr, size_t size)
{
/* size must be within the flash address space */
CHECK_PARAM_RET (addr + size <= _flash_end, -EOVERFLOW);
/* size must be a multiple of sector_size && at least one sector */
CHECK_PARAM_RET (size >= _flashchip->sector_size, -ENOTSUP);
CHECK_PARAM_RET (size % _flashchip->sector_size == 0, -ENOTSUP)
/* prepare for write access */
uint32_t result = esp_rom_spiflash_unlock();
/* erase as many sectors as necessary */
uint32_t sec = addr / _flashchip->sector_size;
uint32_t cnt = size / _flashchip->sector_size;
uint32_t sec_per_block = _flashchip->block_size / _flashchip->sector_size;
while (cnt && result == ESP_ROM_SPIFLASH_RESULT_OK) {
/* disable interrupts and the cache */
critical_enter();
Cache_Read_Disable(PRO_CPU_NUM);
/* erase block-wise (64 kByte) if cnt is at least sec_per_block */
if (cnt >= sec_per_block) {
result = esp_rom_spiflash_erase_block (sec / sec_per_block);
sec += sec_per_block;
cnt -= sec_per_block;
}
else {
result = esp_rom_spiflash_erase_sector (sec++);
cnt--;
}
/* enable interrupts and the cache */
Cache_Read_Enable(PRO_CPU_NUM);
critical_exit();
}
/* reset write access */
esp_rom_spiflash_lock();
/* return with the ESP-IDF error code that is mapped from ROM error code */
RETURN_WITH_ESP_ERR_CODE(result);
}
#endif /* MCU_ESP32 */
const esp_partition_t* esp_partition_find_first(esp_partition_type_t type,
esp_partition_subtype_t subtype,
const char* label)
{
uint32_t info_addr = ESP_PART_TABLE_ADDR;
uint8_t info_buf[ESP_PART_ENTRY_SIZE];
bool info_read = true;
esp_partition_info_t* info = (esp_partition_info_t*)info_buf;
esp_partition_t* part;
while (info_read && info_addr < ESP_PART_TABLE_ADDR + ESP_PART_TABLE_SIZE) {
spi_flash_read (info_addr, (void*)info_buf, ESP_PART_ENTRY_SIZE);
if (info->magic == ESP_PART_ENTRY_MAGIC) {
DEBUG("%s partition @%08x size=%08x label=%s\n", __func__,
info->pos.offset, info->pos.size, info->label);
if ((info->type == type) &&
(info->subtype == subtype || subtype == ESP_PARTITION_SUBTYPE_ANY) &&
(label == NULL || strcmp((const char*)info->label, label) == 0)) {
part = malloc(sizeof(esp_partition_t));
part->type = info->type;
part->subtype = info->subtype;
part->address = info->pos.offset;
part->size = info->pos.size;
part->encrypted = info->flags & PART_FLAG_ENCRYPTED;
strncpy(part->label, (const char*)info->label, sizeof(info->label));
part->label[sizeof(part->label) - 1] = 0x0;
return part;
}
info_addr += ESP_PART_ENTRY_SIZE;
}
else {
info_read = false;
}
}
return NULL;
}
esp_err_t esp_partition_erase_range(const esp_partition_t* part,
size_t addr, size_t size)
{
CHECK_PARAM_RET(part != NULL, ESP_ERR_INVALID_ARG);
/* start addr and size must be inside the partition */
CHECK_PARAM_RET(addr <= part->size, ESP_ERR_INVALID_ARG);
CHECK_PARAM_RET(addr + size <= part->size, ESP_ERR_INVALID_SIZE);
/* start addr and size must be a multiple of sector size */
CHECK_PARAM_RET(addr % SPI_FLASH_SEC_SIZE == 0, ESP_ERR_INVALID_ARG);
CHECK_PARAM_RET(size % SPI_FLASH_SEC_SIZE == 0, ESP_ERR_INVALID_SIZE);
return spi_flash_erase_range(part->address + addr, size);
}
static int _flash_init (mtd_dev_t *dev)
{
DEBUG("%s dev=%p driver=%p\n", __func__, dev, &_flash_driver);
CHECK_PARAM_RET (dev == &_flash_dev, -ENODEV);
#ifdef SPI_FLASH_CHIP_SIZE
if (SPI_FLASH_CHIP_SIZE <= SPIFFS_FLASH_BEGIN) {
#else
if (flashchip->chip_size <= SPIFFS_FLASH_BEGIN) {
#endif
if (_flashchip->chip_size <= _flash_beg) {
LOG_ERROR("Flash size is equal or less than %d Byte, "
"SPIFFS cannot be used\n", SPIFFS_FLASH_BEGIN);
"SPIFFS cannot be used\n", _flash_beg);
return -ENODEV;
}
return 0;
}
#define SPI_FLASH_BUF_SIZE 64
uint8_t _flash_buf[SPI_FLASH_BUF_SIZE];
static int _flash_read (mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t size)
{
DEBUG("%s dev=%p addr=%08x size=%u buf=%p\n", __func__, dev, addr, size, buff);
@ -119,58 +508,7 @@ static int _flash_read (mtd_dev_t *dev, void *buff, uint32_t addr, uint32_t siz
/* size must be within the flash address space */
CHECK_PARAM_RET (_flash_beg + addr + size <= _flash_end, -EOVERFLOW);
#ifndef SDK_FLASH_FUNCTIONS
bool result = spiflash_read (_flash_beg + addr, buff, size);
return result ? (int)size : -EIO;
#else
critical_enter();
/* it would be great if would work in that way, but would be too easy :-( */
/* memcpy(buff, (void*)(_flash_beg + addr + 0x40200000), size); */
int result = SPI_FLASH_RESULT_OK;
uint32_t len = size;
/* if addr is not 4 byte aligned, we need to read the first full word */
if (addr & 0x3) {
uint32_t word_addr = addr & ~0x3;
uint32_t pos_in_word = addr & 0x3;
uint32_t len_in_word = 4 - pos_in_word;
len_in_word = (len_in_word < len) ? len_in_word : len;
result = spi_flash_read (_flash_beg + word_addr, (uint32_t*)_flash_buf, 4);
memcpy(buff, _flash_buf + pos_in_word, len_in_word);
buff = (uint8_t*)buff + len_in_word;
addr += len_in_word;
len -= len_in_word;
}
/* read all full words, maximum SPI_FLASH_BUF_SIZE in one write operation */
while (result == SPI_FLASH_RESULT_OK && len > 4) {
uint32_t len_full_words = len & ~0x3;
if (len_full_words > SPI_FLASH_BUF_SIZE) {
len_full_words = SPI_FLASH_BUF_SIZE;
}
result |= spi_flash_read (_flash_beg + addr, (uint32_t*)_flash_buf, len_full_words);
memcpy(buff, _flash_buf, len_full_words);
buff = (uint8_t*)buff + len_full_words;
addr += len_full_words;
len -= len_full_words;
}
/* if there is some remaining, we need to prepare last word */
if (result == SPI_FLASH_RESULT_OK && len) {
result |= spi_flash_read (_flash_beg + addr, (uint32_t*)_flash_buf, 4);
memcpy(buff, _flash_buf, len);
}
critical_exit();
return (result == SPI_FLASH_RESULT_OK) ? (int)size : -EIO;
#endif
return (spi_flash_read(_flash_beg + addr, buff, size) == ESP_OK) ? (int)size : -EIO;
}
static int _flash_write (mtd_dev_t *dev, const void *buff, uint32_t addr, uint32_t size)
@ -183,60 +521,11 @@ static int _flash_write (mtd_dev_t *dev, const void *buff, uint32_t addr, uint32
/* size must be within the flash address space */
CHECK_PARAM_RET (_flash_beg + addr + size <= _flash_end, -EOVERFLOW);
#ifndef SDK_FLASH_FUNCTIONS
/* addr + size must be within a page */
CHECK_PARAM_RET (size <= _flashchip->page_size, -EOVERFLOW);
CHECK_PARAM_RET ((addr % _flashchip->page_size) + size <= _flashchip->page_size, -EOVERFLOW);
bool result = spiflash_write (_flash_beg + addr, (uint8_t*)buff, size);
return result ? (int)size : -EIO;
#else
critical_enter();
int result = SPI_FLASH_RESULT_OK;
uint32_t len = size;
/* if addr is not 4 byte aligned, we need to prepare first full word */
if (addr & 0x3) {
uint32_t word_addr = addr & ~0x3;
uint32_t pos_in_word = addr & 0x3;
uint32_t len_in_word = 4 - pos_in_word;
len_in_word = (len_in_word < len) ? len_in_word : len;
result = spi_flash_read (_flash_beg + word_addr, (uint32_t*)_flash_buf, 4);
memcpy(_flash_buf + pos_in_word, buff, len_in_word);
result |= spi_flash_write (_flash_beg + word_addr, (uint32_t*)_flash_buf, 4);
buff = (uint8_t*)buff + len_in_word;
addr += len_in_word;
len -= len_in_word;
}
/* write all full words, maximum SPI_FLASH_BUF_SIZE in one write operation */
while (result == SPI_FLASH_RESULT_OK && len > 4) {
uint32_t len_full_words = len & ~0x3;
if (len_full_words > SPI_FLASH_BUF_SIZE) {
len_full_words = SPI_FLASH_BUF_SIZE;
}
memcpy(_flash_buf, buff, len_full_words);
result |= spi_flash_write (_flash_beg + addr, (uint32_t*)_flash_buf, len_full_words);
buff = (uint8_t*)buff + len_full_words;
addr += len_full_words;
len -= len_full_words;
}
/* if there is some remaining, we need to prepare last word */
if (result == SPI_FLASH_RESULT_OK && len) {
result |= spi_flash_read (_flash_beg + addr, (uint32_t*)_flash_buf, 4);
memcpy(_flash_buf, buff, len);
result |= spi_flash_write (_flash_beg + addr, (uint32_t*)_flash_buf, 4);
}
critical_exit();
return (result == SPI_FLASH_RESULT_OK) ? (int)size : -EIO;
#endif
return (spi_flash_write(_flash_beg + addr, buff, size) == ESP_OK) ? (int)size : -EIO;
}
static int _flash_erase (mtd_dev_t *dev, uint32_t addr, uint32_t size)
@ -249,34 +538,10 @@ static int _flash_erase (mtd_dev_t *dev, uint32_t addr, uint32_t size)
CHECK_PARAM_RET (_flash_beg + addr + size <= _flash_end, -EOVERFLOW);
/* size must be a multiple of sector_size && at least one sector */
CHECK_PARAM_RET (size >= flashchip->sector_size, -ENOTSUP);
CHECK_PARAM_RET (size % flashchip->sector_size == 0, -ENOTSUP)
CHECK_PARAM_RET (size >= _flashchip->sector_size, -EOVERFLOW);
CHECK_PARAM_RET (size % _flashchip->sector_size == 0, -EOVERFLOW)
#ifndef SDK_FLASH_FUNCTIONS
bool result = false;
uint32_t count = size / flashchip->sector_size;
while (count--) {
uint32_t sec = _flash_beg + addr + count * flashchip->sector_size;
if (!(result = spiflash_erase_sector (sec))) {
break;
}
}
return result ? 0 : -EIO;
#else
critical_enter();
uint32_t result = SPI_FLASH_RESULT_OK;
uint32_t count = size / flashchip->sector_size;
while (count--) {
uint32_t sec = (_flash_beg + addr) / flashchip->sector_size + count;
if ((result = spi_flash_erase_sector (sec)) != SPI_FLASH_RESULT_OK) {
break;
}
}
critical_exit();
return result;
#endif
return (spi_flash_erase_range(_flash_beg + addr, size) == ESP_OK) ? 0 : -EIO;
}
static int _flash_power (mtd_dev_t *dev, enum mtd_power_state power)
@ -285,3 +550,5 @@ static int _flash_power (mtd_dev_t *dev, enum mtd_power_state power)
return -ENOTSUP;
}
#endif /* MODULE_MTD */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -26,17 +26,17 @@
#include "log.h"
#include "periph/gpio.h" /* RIOT gpio.h */
#include "c_types.h"
#include "eagle_soc.h"
#include "ets_sys.h"
#include "esp8266/eagle_soc.h"
#include "esp8266/gpio_register.h"
#include "rom/ets_sys.h"
#include "sdk/ets.h"
#include "esp/gpio_regs.h"
#include "esp/iomux_regs.h"
#include "esp/rtc_regs.h"
#include "common.h"
#include "gpio_common.h"
#include "esp_common.h"
#include "gpio_arch.h"
#include "irq_arch.h"
#include "syscalls.h"
@ -48,7 +48,7 @@
const uint8_t _gpio_to_iomux[] = { 12, 5, 13, 4, 14, 15, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3 };
const uint8_t _iomux_to_gpio[] = { 12, 13, 14, 15, 3, 1, 6, 7, 8, 9, 10, 11, 0, 2, 4, 5 };
_gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF] =
gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF] =
{
_GPIO, /* gpio0 */
@ -75,6 +75,12 @@ _gpio_pin_usage_t _gpio_pin_usage [GPIO_PIN_NUMOF] =
_GPIO /* gpio16 */
};
/* String representation of usage types */
const char* _gpio_pin_usage_str[] =
{
"GPIO", "I2C", "PWM", "SPI", "SPI Flash", "UART", "N/A"
};
int gpio_init(gpio_t pin, gpio_mode_t mode)
{
DEBUG("%s: %d %d\n", __func__, pin, mode);
@ -285,3 +291,20 @@ void gpio_toggle (gpio_t pin)
GPIO.OUT ^= BIT(pin);
}
int gpio_set_pin_usage(gpio_t pin, gpio_pin_usage_t usage)
{
CHECK_PARAM_RET(pin < GPIO_PIN_NUMOF, -1);
_gpio_pin_usage [pin] = usage;
return 0;
}
gpio_pin_usage_t gpio_get_pin_usage (gpio_t pin)
{
return (pin < GPIO_PIN_NUMOF) ? _gpio_pin_usage[pin] : _NOT_EXIST;
}
const char* gpio_get_pin_usage_str(gpio_t pin)
{
return _gpio_pin_usage_str[_gpio_pin_usage[((pin < GPIO_PIN_NUMOF) ? pin : _NOT_EXIST)]];
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -22,8 +22,13 @@
#include "cpu.h"
#include "periph_conf.h"
#include "periph/hwrng.h"
#include "rom/ets_sys.h"
#include "esp/wdev_regs.h"
#ifdef MCU_ESP32
static const uint32_t* RNG_DATA_REG = (uint32_t*)0x3ff75144;
#else
static const uint32_t* RNG_DATA_REG = (uint32_t*)0x3ff20e44;
#endif
void hwrng_init(void)
{
@ -37,7 +42,7 @@ void hwrng_read(void *buf, unsigned int num)
while (count < num) {
/* read next 4 bytes of random data */
uint32_t tmp = WDEV.HWRNG;
uint32_t tmp = *RNG_DATA_REG;
/* copy data into result vector */
for (int i = 0; i < 4 && count < num; i++) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -7,8 +7,8 @@
*/
/**
* @ingroup cpu_esp8266
* @ingroup drivers_periph_i2c
* @ingroup cpu_esp8266
* @ingroup drivers_periph_i2c
* @{
*
* @file
@ -22,18 +22,16 @@
/*
PLEASE NOTE:
Some parts of the implementation bases on the bit-banging implementation as
described in [wikipedia](https://en.wikipedia.org/wiki/I%C2%B2C) as well as
its implementation in [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git).
These parts are under the copyright of their respective owners.
The implementation bases on the bit-banging I2C master implementation as
described in [wikipedia](https://en.wikipedia.org/wiki/I%C2%B2C#Example_of_bit-banging_the_I%C2%B2C_master_protocol).
*/
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <assert.h>
#include <stdbool.h>
#include <errno.h>
#include <stdbool.h>
#include "cpu.h"
#include "log.h"
@ -42,20 +40,36 @@
#include "periph/gpio.h"
#include "periph/i2c.h"
#include "common.h"
#include "esp_common.h"
#include "gpio_arch.h"
#include "rom/ets_sys.h"
#ifdef MCU_ESP32
#include "soc/gpio_reg.h"
#include "soc/gpio_struct.h"
/* max clock stretching counter */
#define I2C_CLOCK_STRETCH 200
/* gpio access macros */
#define GPIO_SET(l,h,b) if (b < 32) GPIO.l = BIT(b); else GPIO.h.val = BIT(32-b)
#define GPIO_GET(l,h,b) ((b < 32) ? GPIO.l & BIT(b) : GPIO.h.val & BIT(32-b))
#else /* MCU_ESP32 */
#include "esp/gpio_regs.h"
#include "sdk/ets.h"
#if defined(I2C_NUMOF) && I2C_NUMOF > 0
/* max clock stretching counter (ca. 10 ms) */
#define I2C_CLOCK_STRETCH 40000
/* has to be declared as extern since it is not possible to include */
/* user_interface.h due to conflicts with gpio_init */
/* following functions have to be declared as extern since it is not possible */
/* to include user_interface.h due to conflicts with gpio_init */
extern uint8_t system_get_cpu_freq(void);
extern bool system_update_cpu_freq(uint8_t freq);
/* max clock stretching counter (ca. 10 ms) */
#define I2C_CLOCK_STRETCH 40000
#endif /* MCU_ESP32 */
typedef struct
{
@ -71,50 +85,42 @@ typedef struct
uint32_t sda_bit; /* gpio bit mask for faster access */
uint32_t delay;
mutex_t lock;
} _i2c_bus_t;
static _i2c_bus_t _i2c_bus[] =
{
#if defined(I2C0_SDA) && defined(I2C0_SCL)
{
.speed = I2C0_SPEED,
.sda = I2C0_SDA,
.scl = I2C0_SCL
},
#endif
#if defined(I2C1_SDA) && defined(I2C1_SCL)
{
.speed = I2C1_SPEED,
.sda = I2C1_SDA,
.scl = I2C1_SCL
},
#endif
#if defined(I2C2_SDA) && defined(I2C2_SCL)
{
.speed = I2C2_SPEED,
.sda = I2C2_SDA,
.scl = I2C2_SCL
},
#endif
};
static _i2c_bus_t _i2c_bus[I2C_NUMOF] = {};
/* to ensure that I2C is always optimized with -O2 to use the defined delays */
#pragma GCC optimize ("O2")
#ifdef MCU_ESP32
static const uint32_t _i2c_delays[][3] =
{
/* values specify one half-period and are only valid for -O2 option */
/* value = [period - 0.25 us (240 MHz) / 0.5us(160MHz) / 1.0us(80MHz)] */
/* * cycles per second / 2 */
/* 1 us = 16 cycles (80 MHz) / 32 cycles (160 MHz) / 48 cycles (240) */
/* values for 80, 160, 240 MHz */
[I2C_SPEED_LOW] = {790, 1590, 2390}, /* 10 kbps (period 100 us) */
[I2C_SPEED_NORMAL] = { 70, 150, 230}, /* 100 kbps (period 10 us) */
[I2C_SPEED_FAST] = { 11, 31, 51}, /* 400 kbps (period 2.5 us) */
[I2C_SPEED_FAST_PLUS] = { 0, 7, 15}, /* 1 Mbps (period 1 us) */
[I2C_SPEED_HIGH] = { 0, 0, 0} /* 3.4 Mbps (period 0.3 us) not working */
};
#else /* MCU_ESP32 */
static const uint32_t _i2c_delays[][2] =
{
/* values specify one half-period and are only valid for -O2 option */
/* values specify one half-period and are only valid for -O2 option */
/* value = [period - 0.5us(160MHz) or 1.0us(80MHz)] * cycles per second / 2 */
/* cycles per us = ca. 20 (80 MHz) / ca. 40 (160 MHz) */
[I2C_SPEED_LOW] = {1990, 989}, /* 10 kbps (period 100 us) */
[I2C_SPEED_NORMAL] = { 190, 89}, /* 100 kbps (period 10 us) */
[I2C_SPEED_FAST] = { 40, 16}, /* 400 kbps (period 2.5 us) */
[I2C_SPEED_FAST_PLUS] = { 13, 0}, /* 1 Mbps (period 1 us) */
/* 1 us = 20 cycles (80 MHz) / 40 cycles (160 MHz) */
[I2C_SPEED_LOW] = {989, 1990}, /* 10 kbps (period 100 us) */
[I2C_SPEED_NORMAL] = { 89, 190}, /* 100 kbps (period 10 us) */
[I2C_SPEED_FAST] = { 16, 40}, /* 400 kbps (period 2.5 us) */
[I2C_SPEED_FAST_PLUS] = { 0, 13}, /* 1 Mbps (period 1 us) */
[I2C_SPEED_HIGH] = { 0, 0} /* 3.4 Mbps (period 0.3 us) is not working */
};
static mutex_t i2c_bus_lock[I2C_NUMOF] = { MUTEX_INIT };
#endif /* MCU_ESP32 */
/* forward declaration of internal functions */
@ -136,51 +142,86 @@ static void _i2c_abort (_i2c_bus_t* bus, const char* func);
static void _i2c_clear (_i2c_bus_t* bus);
/* implementation of i2c interface */
void i2c_init(i2c_t dev)
{
if (I2C_NUMOF != ARRAY_SIZE(_i2c_bus)) {
LOG_INFO("I2C_NUMOF does not match number of I2C_SDA_x/I2C_SCL_x definitions\n");
LOG_INFO("Please check your board configuration in 'board.h'\n");
assert(I2C_NUMOF < ARRAY_SIZE(_i2c_bus));
assert(dev < I2C_NUMOF_MAX);
assert(dev < I2C_NUMOF);
if (i2c_config[dev].speed == I2C_SPEED_HIGH) {
LOG_TAG_INFO("i2c", "I2C_SPEED_HIGH is not supported\n");
return;
}
CHECK_PARAM (dev < I2C_NUMOF)
mutex_init(&_i2c_bus[dev].lock);
if (_i2c_bus[dev].speed == I2C_SPEED_HIGH) {
LOG_INFO("I2C_SPEED_HIGH is not supported\n");
return;
}
i2c_acquire (dev);
_i2c_bus[dev].scl = i2c_config[dev].scl;
_i2c_bus[dev].sda = i2c_config[dev].sda;
_i2c_bus[dev].speed = i2c_config[dev].speed;
_i2c_bus[dev].dev = dev;
_i2c_bus[dev].delay =_i2c_delays[_i2c_bus[dev].speed][ets_get_cpu_frequency() == 80 ? 1 : 0];
_i2c_bus[dev].scl_bit = BIT(_i2c_bus[dev].scl); /* store bit mask for faster access */
_i2c_bus[dev].sda_bit = BIT(_i2c_bus[dev].sda); /* store bit mask for faster access */
_i2c_bus[dev].started = false; /* for handling of repeated start condition */
DEBUG ("%s: scl=%d sda=%d speed=%d\n", __func__,
_i2c_bus[dev].scl, _i2c_bus[dev].sda, _i2c_bus[dev].speed);
switch (ets_get_cpu_frequency()) {
case 80: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][0]; break;
case 160: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][1]; break;
#ifdef MCU_ESP32
case 240: _i2c_bus[dev].delay = _i2c_delays[_i2c_bus[dev].speed][2]; break;
#endif
default : LOG_TAG_INFO("i2c", "I2C software implementation is not "
"supported for this CPU frequency: %d MHz\n",
ets_get_cpu_frequency());
return;
}
DEBUG("%s: scl=%d sda=%d speed=%d\n", __func__,
_i2c_bus[dev].scl, _i2c_bus[dev].sda, _i2c_bus[dev].speed);
/* reset the GPIO usage if the pins were used for I2C before */
if (gpio_get_pin_usage(_i2c_bus[dev].scl) == _I2C) {
gpio_set_pin_usage(_i2c_bus[dev].scl, _GPIO);
}
if (gpio_get_pin_usage(_i2c_bus[dev].sda) == _I2C) {
gpio_set_pin_usage(_i2c_bus[dev].sda, _GPIO);
}
/* Configure and initialize SDA and SCL pin. */
#ifdef MCU_ESP32
/*
* Configure and initialize SDA and SCL pin.
* Note: Due to critical timing required by the I2C software
* implementation, the ESP8266 GPIOs can not be used directly in GPIO_OD_PU
* mode. Instead, the GPIOs are configured in GPIO_IN_PU mode with
* open-drain output driver. Signal levels are then realized as following:
* ESP32 pins are used in input/output mode with open-drain output driver.
* Signal levels are then realized as following:
*
* - HIGH: Output value 1 lets the pin floating and is pulled-up to high.
* - LOW : Output value 0 actively drives the pin to low.
*/
if (gpio_init(_i2c_bus[dev].scl, GPIO_IN_OD_PU) ||
gpio_init(_i2c_bus[dev].sda, GPIO_IN_OD_PU)) {
return;
}
#else /* MCU_ESP32 */
/*
* Due to critical timing required by the I2C software implementation,
* the ESP8266 GPIOs can not be used directly in GPIO_OD_PU mode.
* Instead, the GPIOs are configured in GPIO_IN_PU mode with open-drain
* output driver. Signal levels are then realized as following:
*
* - HIGH: The GPIO is used in the configured GPIO_IN_PU mode. In this
* mode, the output driver is in open-drain mode and pulled-up.
* - LOW : The GPIO is temporarily switched to GPIO_OD_PU mode. In this
* mode, the output value 0, which is written during
* initialization, actively drives the output to low.
* initialization, actively drives the pin to low.
*/
gpio_init (_i2c_bus[dev].scl, GPIO_IN_PU);
gpio_init (_i2c_bus[dev].sda, GPIO_IN_PU);
gpio_clear (_i2c_bus[dev].scl);
gpio_clear (_i2c_bus[dev].sda);
if (gpio_init(_i2c_bus[dev].scl, GPIO_IN_PU) ||
gpio_init(_i2c_bus[dev].sda, GPIO_IN_PU)) {
return;
}
#endif /* MCU_ESP32 */
/* store the usage type in GPIO table */
gpio_set_pin_usage(_i2c_bus[dev].scl, _I2C);
gpio_set_pin_usage(_i2c_bus[dev].sda, _I2C);
/* set SDA and SCL to be floating and pulled-up to high */
_i2c_sda_high (&_i2c_bus[dev]);
@ -189,16 +230,14 @@ void i2c_init(i2c_t dev)
/* clear the bus if necessary (SDA is driven permanently low) */
_i2c_clear (&_i2c_bus[dev]);
i2c_release (dev);
return;
}
int i2c_acquire(i2c_t dev)
{
CHECK_PARAM_RET (dev < I2C_NUMOF, -1)
assert(dev < I2C_NUMOF);
mutex_lock(&i2c_bus_lock[dev]);
mutex_lock(&_i2c_bus[dev].lock);
return 0;
}
@ -206,7 +245,7 @@ void i2c_release(i2c_t dev)
{
assert(dev < I2C_NUMOF);
mutex_unlock(&i2c_bus_lock[dev]);
mutex_unlock(&_i2c_bus[dev].lock);
}
int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len, uint8_t flags)
@ -214,7 +253,8 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len,
DEBUG ("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n",
__func__, dev, addr, data, len, flags);
CHECK_PARAM_RET (dev < I2C_NUMOF, -EINVAL);
assert(dev < I2C_NUMOF);
CHECK_PARAM_RET (len > 0, -EINVAL);
CHECK_PARAM_RET (data != NULL, -EINVAL);
@ -235,7 +275,7 @@ int /* IRAM */ i2c_read_bytes(i2c_t dev, uint16_t addr, void *data, size_t len,
/* prepare 10 bit address bytes */
uint8_t addr1 = 0xf0 | (addr & 0x0300) >> 7 | I2C_READ;
uint8_t addr2 = addr & 0xff;
/* send address bytes wit read flag */
/* send address bytes with read flag */
if ((res = _i2c_write_byte (bus, addr1)) != 0 ||
(res = _i2c_write_byte (bus, addr2)) != 0) {
/* abort transfer */
@ -275,7 +315,8 @@ int /* IRAM */ i2c_write_bytes(i2c_t dev, uint16_t addr, const void *data, size_
DEBUG ("%s: dev=%u addr=%02x data=%p len=%d flags=%01x\n",
__func__, dev, addr, data, len, flags);
CHECK_PARAM_RET (dev < I2C_NUMOF, -EINVAL);
assert(dev < I2C_NUMOF);
CHECK_PARAM_RET (len > 0, -EINVAL);
CHECK_PARAM_RET (data != NULL, -EINVAL);
@ -348,74 +389,99 @@ void i2c_poweroff(i2c_t dev)
static inline void _i2c_delay (_i2c_bus_t* bus)
{
/* produces a delay */
/* ca. 20 cycles = 1 us (80 MHz) or ca. 40 cycles = 1 us (160 MHz) */
uint32_t cycles = bus->delay;
if (cycles) {
__asm__ volatile ("1: _addi.n %0, %0, -1 \n"
" bnez %0, 1b \n" : "=r" (cycles) : "0" (cycles));
__asm__ volatile ("1: _addi.n %0, %0, -1 \n"
" bnez %0, 1b \n" : "=r" (cycles) : "0" (cycles));
}
}
/*
* Note: Due to critical timing required by the I2C software implementation,
* the ESP8266 GPIOs can not be used directly in GPIO_OD_PU mode. Instead,
* the GPIOs are configured in GPIO_IN_PU mode with open-drain output driver.
* Signal levels are then realized as following:
* Please note: SDA and SDL pins are used in GPIO_OD_PU mode
* (open-drain with pull-ups).
*
* - HIGH: The GPIO is used in the configured GPIO_IN_PU mode. In this mode,
* the output driver is in open-drain mode and pulled-up.
* - LOW : The GPIO is temporarily switched to GPIO_OD_PU mode. In this mode,
* the output value 0, which is written during initialization,
* actively drives the output to low.
* Setting a pin which is in open-drain mode leaves the pin floating and
* the signal is pulled up to high. The signal can then be actively driven
* to low by a slave. A read operation returns the current signal at the pin.
*
* Clearing a pin which is in open-drain mode actively drives the signal to
* low.
*/
static inline bool _i2c_scl_read(_i2c_bus_t* bus)
{
/* read SCL status */
/* read SCL status (pin is in open-drain mode and set) */
#ifdef MCU_ESP32
return GPIO_GET(in, in1, bus->scl);
#else /* MCU_ESP32 */
return GPIO.IN & bus->scl_bit;
#endif /* MCU_ESP32 */
}
static inline bool _i2c_sda_read(_i2c_bus_t* bus)
{
/* read SDA status */
/* read SDA status (pin is in open-drain mode and set) */
#ifdef MCU_ESP32
return GPIO_GET(in, in1, bus->sda);
#else /* MCU_ESP32 */
return GPIO.IN & bus->sda_bit;
}
static inline void _i2c_scl_low(_i2c_bus_t* bus)
{
/*
* set SCL signal low (switch temporarily to GPIO_OD_PU where the
* written output value 0 drives the pin actively to low)
*/
GPIO.ENABLE_OUT_SET = bus->scl_bit;
#endif /* MCU_ESP32 */
}
static inline void _i2c_scl_high(_i2c_bus_t* bus)
{
#ifdef MCU_ESP32
/* set SCL signal high (pin is in open-drain mode and pulled-up) */
GPIO_SET(out_w1ts, out1_w1ts, bus->scl);
#else /* MCU_ESP32 */
/*
* set SCL signal high (switch back to GPIO_IN_PU mode, that is the pin is
* in open-drain mode and pulled-up to high)
*/
GPIO.ENABLE_OUT_CLEAR = bus->scl_bit;
#endif /* MCU_ESP32 */
}
static inline void _i2c_sda_low(_i2c_bus_t* bus)
static inline void _i2c_scl_low(_i2c_bus_t* bus)
{
#ifdef MCU_ESP32
/* set SCL signal low (actively driven to low) */
GPIO_SET(out_w1tc, out1_w1tc, bus->scl);
#else /* MCU_ESP32 */
/*
* set SDA signal low (switch temporarily to GPIO_OD_PU where the
* set SCL signal low (switch temporarily to GPIO_OD_PU where the
* written output value 0 drives the pin actively to low)
*/
GPIO.ENABLE_OUT_SET = bus->sda_bit;
GPIO.ENABLE_OUT_SET = bus->scl_bit;
#endif /* MCU_ESP32 */
}
static inline void _i2c_sda_high(_i2c_bus_t* bus)
{
#ifdef MCU_ESP32
/* set SDA signal high (pin is in open-drain mode and pulled-up) */
GPIO_SET(out_w1ts, out1_w1ts, bus->sda);
#else /* MCU_ESP32 */
/*
* set SDA signal high (switch back to GPIO_IN_PU mode, that is the pin is
* in open-drain mode and pulled-up to high)
*/
GPIO.ENABLE_OUT_CLEAR = bus->sda_bit;
#endif /* MCU_ESP32 */
}
static inline void _i2c_sda_low(_i2c_bus_t* bus)
{
#ifdef MCU_ESP32
/* set SDA signal low (actively driven to low) */
GPIO_SET(out_w1tc, out1_w1tc, bus->sda);
#else /* MCU_ESP32 */
/*
* set SDA signal low (switch temporarily to GPIO_OD_PU where the
* written output value 0 drives the pin actively to low)
*/
GPIO.ENABLE_OUT_SET = bus->sda_bit;
#endif /* MCU_ESP32 */
}
static void _i2c_clear(_i2c_bus_t* bus)
@ -500,7 +566,7 @@ static /* IRAM */ int _i2c_start_cond(_i2c_bus_t* bus)
/* SDA = passive HIGH (floating and pulled-up) */
_i2c_sda_high (bus);
/* t_VD;DAT not neccessary */
/* t_VD;DAT not necessary */
/* _i2c_delay (bus); */
/* SCL = passive HIGH (floating and pulled-up) */
@ -724,7 +790,7 @@ static /* IRAM */ int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack)
if (res != 0) {
return res;
}
*byte = (*byte << 1) | bit;
*byte = (*byte << 1) | (bit ? 1 : 0);
}
/* write acknowledgement flag */
@ -735,17 +801,8 @@ static /* IRAM */ int _i2c_read_byte(_i2c_bus_t* bus, uint8_t *byte, bool ack)
void i2c_print_config(void)
{
for (unsigned bus = 0; bus < I2C_NUMOF; bus++) {
LOG_INFO("\tI2C_DEV(%d): scl=%d sda=%d\n",
bus, _i2c_bus[bus].scl, _i2c_bus[bus].sda);
for (unsigned dev = 0; dev < I2C_NUMOF; dev++) {
printf("\tI2C_DEV(%u)\tscl=%d sda=%d\n",
dev, i2c_config[dev].scl, i2c_config[dev].sda);
}
}
#else /* if defined(I2C_NUMOF) && I2C_NUMOF */
void i2c_print_config(void)
{
LOG_INFO("\tI2C: no devices\n");
}
#endif /* if defined(I2C_NUMOF) && I2C_NUMOF */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -18,31 +18,28 @@
* @}
*/
#define ENABLE_DEBUG 0
#define ENABLE_DEBUG (0)
#include "debug.h"
#include <stdbool.h>
#include "irq.h"
#include "esp/xtensa_ops.h"
#include "sdk/ets_task.h"
#include "sdk/sdk.h"
#include "syscalls.h"
void pm_set_lowest(void)
{
DEBUG ("%s\n", __func__);
DEBUG ("%s enter to sleep @%u\n", __func__, system_get_time());
#if !defined(QEMU)
DEBUG ("%s enter to sleep @%u\n", __func__, phy_get_mactime());
/* reset system watchdog timer */
system_wdt_feed();
#ifndef MODULE_ESP_QEMU
/* passive wait for interrupt to leave lowest power mode */
__asm__ volatile ("waiti 0");
DEBUG ("%s exit from sleep @%u\n", __func__, phy_get_mactime());
#endif
DEBUG ("%s exit from sleep @%u\n", __func__, system_get_time());
/* reset system watchdog timer */
system_wdt_feed();
}
void pm_off(void)

View File

@ -18,7 +18,7 @@
* @}
*/
#define ENABLE_DEBUG 0
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "cpu.h"
@ -27,21 +27,19 @@
#include "periph/pwm.h"
#include "periph/gpio.h"
#include "common.h"
#include "esp_common.h"
#include "esp/iomux_regs.h"
#include "esp/timer_regs.h"
#include "gpio_common.h"
#include "sdk/ets.h"
#if defined(PWM_NUMOF) && PWM_NUMOF > 0
#include "gpio_arch.h"
#include "sdk/sdk.h"
#include "xtensa/xtensa_api.h"
#define TIMER_FRC1_CLKDIV_16 BIT(2)
#define TIMER_FRC1_CLKDIV_256 BIT(3)
#define ETS_FRC1_INT_ENABLE ETS_FRC1_INTR_ENABLE
#define ETS_FRC1_INT_DISABLE ETS_FRC1_INTR_DISABLE
#define ETS_FRC1_INT_ATTACH ETS_FRC_TIMER1_INTR_ATTACH
#define ETS_FRC1_NMI_ATTACH ETS_FRC_TIMER1_NMI_INTR_ATTACH
#define ETS_FRC1_INT_ENABLE() xt_ints_on(BIT(ETS_FRC_TIMER1_INUM))
#define ETS_FRC1_INT_DISABLE() xt_ints_off(BIT(ETS_FRC_TIMER1_INUM))
#define ETS_FRC1_INT_ATTACH(f, a) xt_set_interrupt_handler(ETS_FRC_TIMER1_INUM, f, a)
typedef struct
{
@ -65,8 +63,6 @@ typedef struct
static _pwm_dev_t _pwm_dev;
static const uint32_t _pwm_channel_gpios[] = PWM0_CHANNEL_GPIOS;
static void _pwm_timer_handler (void* arg)
{
irq_isr_enter ();
@ -119,14 +115,15 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
{
DEBUG ("%s pwm=%u mode=%u freq=%u, res=%u\n", __func__, pwm, mode, freq, res);
uint8_t _pwm_channel_gpio_num = sizeof(_pwm_channel_gpios) >> 2;
uint8_t _pwm_channel_gpio_num = sizeof(pwm0_channels) >> 2;
CHECK_PARAM_RET (pwm < PWM_NUMOF, 0);
CHECK_PARAM_RET (freq > 0, 0);
CHECK_PARAM_RET (_pwm_channel_gpio_num <= PWM_CHANNEL_NUM_MAX, 0);
assert(pwm < PWM_NUMOF_MAX);
assert(pwm < PWM_NUMOF);
assert(freq > 0);
assert(_pwm_channel_gpio_num <= PWM_CHANNEL_NUM_MAX);
/* maximum number of cycles per second (freq*res) should not be greater than */
/* 100.000 (period of 10 us), reduce freq if neccessary and keep resolution */
/* 100.000 (period of 10 us), reduce freq if necessary and keep resolution */
if (res * freq > PWM_MAX_CPS) {
freq = PWM_MAX_CPS / res;
}
@ -138,21 +135,21 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
_pwm_dev.mode = mode;
for (int i = 0; i < _pwm_channel_gpio_num; i++) {
if (_gpio_pin_usage[_pwm_channel_gpios[i]] != _GPIO) {
if (gpio_get_pin_usage(pwm0_channels[i]) != _GPIO) {
LOG_ERROR("GPIO%d is used for something else and cannot be used as PWM output\n", i);
return 0;
}
if (gpio_init(_pwm_channel_gpios[i], GPIO_OUT) < 0) {
if (gpio_init(pwm0_channels[i], GPIO_OUT) < 0) {
return 0;
}
gpio_clear (_pwm_channel_gpios[i]);
gpio_clear (pwm0_channels[i]);
_pwm_dev.chn[_pwm_dev.chn_num].duty = 0;
_pwm_dev.chn[_pwm_dev.chn_num].next_on = 0;
_pwm_dev.chn[_pwm_dev.chn_num].next_off = 0;
_pwm_dev.chn[_pwm_dev.chn_num].gpio = _pwm_channel_gpios[i];
_pwm_dev.chn[_pwm_dev.chn_num].gpio = pwm0_channels[i];
_pwm_dev.chn_num++;
}
@ -169,7 +166,7 @@ uint32_t pwm_init(pwm_t pwm, pwm_mode_t mode, uint32_t freq, uint16_t res)
uint8_t pwm_channels(pwm_t pwm)
{
CHECK_PARAM_RET (pwm < PWM_NUMOF, 0);
assert(pwm < PWM_NUMOF);
return _pwm_dev.chn_num;
}
@ -178,9 +175,9 @@ void pwm_set(pwm_t pwm, uint8_t channel, uint16_t value)
{
DEBUG("%s pwm=%u channel=%u value=%u\n", __func__, pwm, channel, value);
CHECK_PARAM (pwm < PWM_NUMOF);
CHECK_PARAM (channel < _pwm_dev.chn_num);
CHECK_PARAM (value <= _pwm_dev.res);
assert(pwm < PWM_NUMOF);
assert(channel < _pwm_dev.chn_num);
assert(value <= _pwm_dev.res);
uint32_t state = irq_disable();
uint32_t phase = _pwm_dev.cycles - _pwm_dev.cycles % _pwm_dev.res;
@ -226,25 +223,16 @@ void pwm_poweron(pwm_t pwm)
void pwm_poweroff(pwm_t pwm)
{
CHECK_PARAM (pwm < PWM_NUMOF);
assert(pwm < PWM_NUMOF);
_pwm_stop ();
}
void pwm_print_config(void)
{
LOG_INFO("\tPWM_DEV(0): channels=[ ");
for (unsigned i = 0; i < sizeof(_pwm_channel_gpios) >> 2; i++) {
LOG_INFO("%d ", _pwm_channel_gpios[i]);
printf("\tPWM_DEV(0)\tchannels=[ ");
for (unsigned i = 0; i < sizeof(pwm0_channels) >> 2; i++) {
printf("%d ", pwm0_channels[i]);
}
LOG_INFO("]\n");
printf("]\n");
}
#else /* defined(PWM_NUMOF) && PWM_NUMOF > 0 */
void pwm_print_config(void)
{
LOG_INFO("\tPWM: no devices\n");
}
#endif /* defined(PWM_NUMOF) && PWM_NUMOF > 0 */

View File

@ -26,9 +26,9 @@
#include "log.h"
#include "periph/rtc.h"
#include "common.h"
#include "esp_common.h"
#include "sdk/ets.h"
#include "sdk/sdk.h"
void rtc_init(void)
{

View File

@ -21,32 +21,77 @@
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "common.h"
#include "esp_common.h"
#include "log.h"
#if defined(MODULE_PERIPH_SPI)
#include <string.h>
#include "cpu.h"
#include "mutex.h"
#include "periph/spi.h"
#include "esp_attr.h"
#include "gpio_arch.h"
#ifdef MCU_ESP32
#include "driver/periph_ctrl.h"
#include "rom/ets_sys.h"
#include "soc/gpio_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_struct.h"
#include "soc/io_mux_reg.h"
#include "soc/spi_reg.h"
#include "soc/spi_struct.h"
#else /* MCU_ESP32 */
#include "esp/iomux_regs.h"
#include "esp/spi_regs.h"
#include "esp8266/spi_register.h"
#include "esp8266/spi_struct.h"
#include "gpio_common.h"
#define SPI_DOUTDIN (BIT(0))
#define SPI_BUS_NUM 2
#define SPI_BLOCK_SIZE 64 /* number of bytes per SPI transfer */
#endif /* MCU_ESP32 */
static mutex_t _spi_lock[SPI_BUS_NUM] = { MUTEX_INIT };
#define SPI_BLOCK_SIZE 64 /* number of bytes per SPI transfer */
/* indicate whether SPI interface were already initilized */
static bool _spi_initialized[SPI_BUS_NUM] = { false };
/* pins of FSI are fixed */
#define FSPI_SCK GPIO6
#define FSPI_MISO GPIO7
#define FSPI_MOSI GPIO8
/* indicate whether pins of the SPI interface were already initilized */
static bool _spi_pins_initialized[SPI_BUS_NUM] = { false };
/** structure which describes all properties of one SPI bus */
struct _spi_bus_t {
spi_dev_t* regs; /* pointer to register data struct of the SPI device */
mutex_t lock; /* mutex for each possible SPI interface */
bool initialized; /* interface already initialized */
bool pins_initialized; /* pins interface initialized */
#ifdef MCU_ESP32
uint8_t mod; /* peripheral hardware module of the SPI interface */
uint8_t int_src; /* peripheral interrupt source used by the SPI device */
uint8_t signal_sck; /* SCK signal from the controller */
uint8_t signal_mosi; /* MOSI signal from the controller */
uint8_t signal_miso; /* MISO signal to the controller */
#endif /* MCU_ESP32 */
};
static struct _spi_bus_t _spi[] = {
#ifdef SPI0_CTRL
{
.initialized = false,
.pins_initialized = false,
.lock = MUTEX_INIT
},
#endif
#ifdef SPI1_CTRL
{
.initialized = false,
.pins_initialized = false,
.lock = MUTEX_INIT
},
#endif
};
/*
* GPIOs that were once initialized as SPI interface pins can not be used
@ -57,23 +102,48 @@ static bool _spi_pins_initialized[SPI_BUS_NUM] = { false };
* the *spi_init_cs* function or the *spi_acquire* function when the interface
* is used for the first time.
*/
void IRAM spi_init (spi_t bus)
void IRAM_ATTR spi_init (spi_t bus)
{
assert(bus < SPI_NUMOF_MAX);
assert(bus < SPI_NUMOF);
switch (spi_config[bus].ctrl) {
#ifdef MCU_ESP32
case HSPI: _spi[bus].regs = &SPI2;
_spi[bus].mod = PERIPH_HSPI_MODULE;
_spi[bus].int_src = ETS_SPI2_INTR_SOURCE;
_spi[bus].signal_sck = HSPICLK_OUT_IDX;
_spi[bus].signal_mosi = HSPID_OUT_IDX;
_spi[bus].signal_miso = HSPIQ_IN_IDX;
break;
case VSPI: _spi[bus].regs = &SPI3;
_spi[bus].mod = PERIPH_VSPI_MODULE;
_spi[bus].int_src = ETS_SPI3_INTR_SOURCE;
_spi[bus].signal_sck = VSPICLK_OUT_IDX;
_spi[bus].signal_mosi = VSPID_OUT_IDX;
_spi[bus].signal_miso = VSPIQ_IN_IDX;
break;
#else /* MCU_ESP32 */
case HSPI: _spi[bus].regs = &SPI1;
break;
#endif /* MCU_ESP32 */
default: LOG_TAG_ERROR("spi", "invalid SPI interface controller "
"used for SPI_DEV(%d)\n", bus);
break;
}
return;
}
void _spi_init_internal(spi_t bus)
/* Internal initialization function when the interface is used the first time */
static void IRAM_ATTR _spi_init_internal(spi_t bus)
{
/* only one physical SPI(1) bus (HSPI) can be used for peripherals */
/* RIOT's SPI_DEV(0) is mapped to SPI(1) bus (HSPI) */
/* TODO SPI overlap mode SPI and HSPI */
CHECK_PARAM (bus == SPI_DEV(0));
assert(bus < SPI_NUMOF);
/* avoid multiple initializations */
if (_spi_initialized[bus]) {
if (_spi[bus].initialized) {
return;
}
_spi_initialized[bus] = true;
_spi[bus].initialized = true;
DEBUG("%s bus=%u\n", __func__, bus);
@ -82,139 +152,176 @@ void _spi_init_internal(spi_t bus)
/* check whether pins could be initialized, otherwise return, CS is not
initialized in spi_init_pins */
if (_gpio_pin_usage[SPI0_SCK_GPIO] != _SPI &&
_gpio_pin_usage[SPI0_MOSI_GPIO] != _SPI &&
_gpio_pin_usage[SPI0_MISO_GPIO] != _SPI) {
if (gpio_get_pin_usage(spi_config[bus].sck) != _SPI &&
gpio_get_pin_usage(spi_config[bus].miso) != _SPI &&
gpio_get_pin_usage(spi_config[bus].mosi) != _SPI &&
gpio_get_pin_usage(spi_config[bus].cs) != _SPI) {
return;
}
/* set bus into a defined state */
SPI(bus).USER0 = SPI_USER0_MOSI | SPI_USER0_CLOCK_IN_EDGE | SPI_USER0_DUPLEX;
SPI(bus).USER0 |= SPI_USER0_CS_SETUP | SPI_USER0_CS_HOLD;
#ifdef MCU_ESP32
/* enable (power on) the according SPI module */
periph_module_enable(_spi[bus].mod);
#endif /* MCU_ESP32 */
/* bring the bus into a defined state */
_spi[bus].regs->user.val = SPI_USR_MOSI | SPI_CK_I_EDGE | SPI_DOUTDIN |
SPI_CS_SETUP | SPI_CS_HOLD;
/* set byte order to little endian for read and write operations */
SPI(bus).USER0 &= ~(SPI_USER0_WR_BYTE_ORDER | SPI_USER0_RD_BYTE_ORDER);
_spi[bus].regs->user.wr_byte_order = 0;
_spi[bus].regs->user.rd_byte_order = 0;
/* set bit order to most significant first for read and write operations */
SPI(bus).CTRL0 = 0; /* ~(SPI_CTRL0_WR_BIT_ORDER | SPI_CTRL0_RD_BIT_ORDER); */
_spi[bus].regs->ctrl.wr_bit_order = 0;
_spi[bus].regs->ctrl.rd_bit_order = 0;
DEBUG("%s SPI(bus).USER0=%08x SPI(bus).CTRL0=%08x\n",
__func__, SPI(bus).USER0, SPI(bus).CTRL0);
/* reset all DIO or QIO flags */
_spi[bus].regs->ctrl.fread_qio = 0;
_spi[bus].regs->ctrl.fread_dio = 0;
_spi[bus].regs->ctrl.fread_quad = 0;
_spi[bus].regs->ctrl.fread_dual = 0;
/* disable fast read mode and write protection */
_spi[bus].regs->ctrl.fastrd_mode = 0;
#ifdef MCU_ESP32
_spi[bus].regs->ctrl.wp = 0;
#endif /* MCU_ESP32 */
/* acquire and release to set default parameters */
spi_acquire(bus, GPIO_UNDEF, SPI_MODE_0, SPI_CLK_1MHZ);
spi_release(bus);
}
void spi_init_pins(spi_t bus)
{
/* see spi_init */
CHECK_PARAM (bus == SPI_DEV(0));
assert(bus < SPI_NUMOF);
/* call initialization of the SPI interface if it is not initialized yet */
if (!_spi_initialized[bus]) {
if (!_spi[bus].initialized) {
_spi_init_internal(bus);
}
/* avoid multiple pin initializations */
if (_spi_pins_initialized[bus]) {
if (_spi[bus].pins_initialized) {
return;
}
_spi_pins_initialized[bus] = true;
_spi[bus].pins_initialized = true;
DEBUG("%s bus=%u\n", __func__, bus);
uint32_t iomux_func = (bus == 0) ? IOMUX_FUNC(1) : IOMUX_FUNC(2);
if (gpio_init (spi_config[bus].sck, GPIO_OUT) ||
gpio_init (spi_config[bus].mosi, GPIO_OUT) ||
gpio_init (spi_config[bus].miso, GPIO_IN)) {
LOG_TAG_ERROR("spi",
"SPI_DEV(%d) pins could not be initialized\n", bus);
return;
}
if (spi_init_cs(bus, spi_config[bus].cs) != SPI_OK) {
LOG_TAG_ERROR("spi",
"SPI_DEV(%d) CS signal could not be initialized\n",
bus);
return;
}
/* store the usage type in GPIO table */
gpio_set_pin_usage(spi_config[bus].sck, _SPI);
gpio_set_pin_usage(spi_config[bus].mosi, _SPI);
gpio_set_pin_usage(spi_config[bus].miso, _SPI);
#ifdef MCU_ESP32
/* connect SCK and MOSI pins to the output signal through the GPIO matrix */
GPIO.func_out_sel_cfg[spi_config[bus].sck].func_sel = _spi[bus].signal_sck;
GPIO.func_out_sel_cfg[spi_config[bus].mosi].func_sel = _spi[bus].signal_mosi;
/* connect MISO input signal to the MISO pin through the GPIO matrix */
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].sig_in_sel = 1;
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].sig_in_inv = 0;
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].func_sel = spi_config[bus].miso;
#else /* MCU_ESP32 */
/*
* CS is handled as normal GPIO ouptut. Due to the small number of GPIOs
* CS is handled as normal GPIO output. Due to the small number of GPIOs
* we have, we do not initialize the default CS pin here. Either the app
* uses spi_init_cs to initialize the CS pin explicitly, or we initialize
* the default CS when spi_aquire is used first time.
*/
IOMUX.PIN[_gpio_to_iomux[SPI0_MISO_GPIO]] &= ~IOMUX_PIN_FUNC_MASK;
IOMUX.PIN[_gpio_to_iomux[SPI0_MOSI_GPIO]] &= ~IOMUX_PIN_FUNC_MASK;
IOMUX.PIN[_gpio_to_iomux[SPI0_SCK_GPIO]] &= ~IOMUX_PIN_FUNC_MASK;
uint32_t iomux_func = IOMUX_FUNC(2);
IOMUX.PIN[_gpio_to_iomux[SPI0_MISO_GPIO]] |= iomux_func;
IOMUX.PIN[_gpio_to_iomux[SPI0_MOSI_GPIO]] |= iomux_func;
IOMUX.PIN[_gpio_to_iomux[SPI0_SCK_GPIO]] |= iomux_func;
IOMUX.PIN[_gpio_to_iomux[spi_config[bus].miso]] &= ~IOMUX_PIN_FUNC_MASK;
IOMUX.PIN[_gpio_to_iomux[spi_config[bus].mosi]] &= ~IOMUX_PIN_FUNC_MASK;
IOMUX.PIN[_gpio_to_iomux[spi_config[bus].sck]] &= ~IOMUX_PIN_FUNC_MASK;
_gpio_pin_usage [SPI0_MISO_GPIO] = _SPI; /* pin cannot be used for anything else */
_gpio_pin_usage [SPI0_MOSI_GPIO] = _SPI; /* pin cannot be used for anything else */
_gpio_pin_usage [SPI0_SCK_GPIO] = _SPI; /* pin cannot be used for anything else */
IOMUX.PIN[_gpio_to_iomux[spi_config[bus].miso]] |= iomux_func;
IOMUX.PIN[_gpio_to_iomux[spi_config[bus].mosi]] |= iomux_func;
IOMUX.PIN[_gpio_to_iomux[spi_config[bus].sck]] |= iomux_func;
#endif /* MCU_ESP32 */
}
int spi_init_cs(spi_t bus, spi_cs_t cs)
{
DEBUG("%s bus=%u cs=%u\n", __func__, bus, cs);
/* see spi_init */
CHECK_PARAM_RET (bus == SPI_DEV(0), SPI_NODEV);
assert(bus < SPI_NUMOF);
/* call initialization of the SPI interface if it is not initialized yet */
if (!_spi_initialized[bus]) {
if (!_spi[bus].initialized) {
_spi_init_internal(bus);
}
/* return if pin is already initialized as SPI CS signal */
if (_gpio_pin_usage [cs] == _SPI) {
if (gpio_get_pin_usage(cs) == _SPI) {
return SPI_OK;
}
if (_gpio_pin_usage [cs] != _GPIO) {
/* check whether CS pin is used otherwise */
if (gpio_get_pin_usage(cs) != _GPIO) {
return SPI_NOCS;
}
/* initialize the pin */
gpio_init(cs, GPIO_OUT);
gpio_set (cs);
gpio_set(cs);
_gpio_pin_usage [cs] = _SPI; /* pin cannot be used for anything else */
/* pin cannot be used for anything else */
gpio_set_pin_usage(cs, _SPI);
return SPI_OK;
}
int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
int IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
{
DEBUG("%s bus=%u cs=%u mode=%u clk=%u\n", __func__, bus, cs, mode, clk);
/* see spi_init */
CHECK_PARAM_RET (bus == SPI_DEV(0), SPI_NODEV);
assert(bus < SPI_NUMOF);
/* call initialization of the SPI interface if it is not initialized yet */
if (!_spi_initialized[bus]) {
if (!_spi[bus].initialized) {
_spi_init_internal(bus);
}
/* if parameter cs is GPIO_UNDEF, the default CS pin is used */
cs = (cs == GPIO_UNDEF) ? SPI0_CS0_GPIO : cs;
cs = (cs == GPIO_UNDEF) ? spi_config[bus].cs : cs;
/* if the CS pin used is not yet initialized, we do it now */
if (_gpio_pin_usage[cs] != _SPI && spi_init_cs(bus, cs) != SPI_OK) {
LOG_ERROR("SPI_DEV(%d) CS signal could not be initialized\n", bus);
if (gpio_get_pin_usage(cs) != _SPI && spi_init_cs(bus, cs) != SPI_OK) {
LOG_TAG_ERROR("spi",
"SPI_DEV(%d) CS signal could not be initialized\n",
bus);
return SPI_NOCS;
}
/* lock the bus */
mutex_lock(&_spi_lock[bus]);
mutex_lock(&_spi[bus].lock);
/* set SPI mode */
bool cpha = (mode == SPI_MODE_1 || mode == SPI_MODE_3);
bool cpol = (mode == SPI_MODE_2 || mode == SPI_MODE_3);
if (cpol) {
cpha = !cpha; /* CPHA must be inverted when CPOL = 1 */
}
if (cpha) {
SPI(bus).USER0 |= SPI_USER0_CLOCK_OUT_EDGE;
}
else {
SPI(bus).USER0 &= ~SPI_USER0_CLOCK_OUT_EDGE;
}
if (cpol) {
SPI(bus).PIN |= SPI_PIN_IDLE_EDGE;
}
else {
SPI(bus).PIN &= ~SPI_PIN_IDLE_EDGE;
}
/*
* set SPI mode
* see ESP32 Technical Reference, Table 25 and Section 7.4.2
*/
_spi[bus].regs->pin.ck_idle_edge = (mode == SPI_MODE_2 || mode == SPI_MODE_3);
_spi[bus].regs->user.ck_out_edge = (mode == SPI_MODE_1 || mode == SPI_MODE_2);
_spi[bus].regs->ctrl2.miso_delay_mode = (mode == SPI_MODE_0 || mode == SPI_MODE_3) ? 2 : 1;
_spi[bus].regs->ctrl2.miso_delay_num = 0;
_spi[bus].regs->ctrl2.mosi_delay_mode = 0;
_spi[bus].regs->ctrl2.mosi_delay_num = 0;
/* set SPI clock
* see ESP8266 Technical Reference Appendix 2 - SPI registers
@ -248,31 +355,53 @@ int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk)
spi_clkdiv_pre--;
spi_clkcnt_N--;
DEBUG("%s spi_clkdiv_prev=%u spi_clkcnt_N=%u\n", __func__, spi_clkdiv_pre, spi_clkcnt_N);
DEBUG("%s spi_clkdiv_prev=%u spi_clkcnt_N=%u\n",
__func__, spi_clkdiv_pre, spi_clkcnt_N);
/* SPI clock is derived from system bus frequency and should not be affected by */
/* CPU clock */
#ifdef MCU_ESP8266
IOMUX.CONF &= ~IOMUX_CONF_SPI1_CLOCK_EQU_SYS_CLOCK;
#endif
IOMUX.CONF &= ~(bus == 0 ? IOMUX_CONF_SPI0_CLOCK_EQU_SYS_CLOCK
: IOMUX_CONF_SPI1_CLOCK_EQU_SYS_CLOCK);
SPI(bus).CLOCK = VAL2FIELD_M (SPI_CLOCK_DIV_PRE, spi_clkdiv_pre) |
VAL2FIELD_M (SPI_CLOCK_COUNT_NUM, spi_clkcnt_N) |
VAL2FIELD_M (SPI_CLOCK_COUNT_HIGH, (spi_clkcnt_N+1)/2-1) |
VAL2FIELD_M (SPI_CLOCK_COUNT_LOW, spi_clkcnt_N);
/* SPI clock is derived from APB clock by dividers */
_spi[bus].regs->clock.clk_equ_sysclk = 0;
DEBUG("%s IOMUX.CONF=%08x SPI(bus).CLOCK=%08x\n",
__func__, IOMUX.CONF, SPI(bus).CLOCK);
/* set SPI clock dividers */
_spi[bus].regs->clock.clkdiv_pre = spi_clkdiv_pre;
_spi[bus].regs->clock.clkcnt_n = spi_clkcnt_N;
_spi[bus].regs->clock.clkcnt_h = (spi_clkcnt_N+1)/2-1;
_spi[bus].regs->clock.clkcnt_l = spi_clkcnt_N;
DEBUG("%s bus %d: SPI_CLOCK_REG=%08x\n",
__func__, bus, _spi[bus].regs->clock.val);
return SPI_OK;
}
void spi_release(spi_t bus)
void IRAM_ATTR spi_release(spi_t bus)
{
/* see spi_init */
CHECK_PARAM (bus == SPI_DEV(0));
DEBUG("%s bus=%u\n", __func__, bus);
assert(bus < SPI_NUMOF);
/* release the bus */
mutex_unlock(&_spi_lock[bus]);
mutex_unlock(&_spi[bus].lock);
}
#ifdef MCU_ESP32
static const char* _spi_names[] = { "CSPI", "FSPI", "HSPI", "VSPI" };
#else /* MCU_ESP32 */
static const char* _spi_names[] = { "FSPI", "HSPI" };
#endif /* MCU_ESP32 */
void spi_print_config(void)
{
for (unsigned bus = 0; bus < SPI_NUMOF; bus++) {
printf("\tSPI_DEV(%u)\t%s ", bus, _spi_names[spi_config[bus].ctrl]);
printf("sck=%d " , spi_config[bus].sck);
printf("miso=%d ", spi_config[bus].miso);
printf("mosi=%d ", spi_config[bus].mosi);
printf("cs=%d\n" , spi_config[bus].cs);
}
}
/*
@ -284,29 +413,37 @@ void spi_release(spi_t bus)
* https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE
*/
inline static void _set_size(uint8_t bus, uint8_t bytes)
inline static void IRAM_ATTR _set_size(uint8_t bus, uint8_t bytes)
{
uint32_t bits = ((uint32_t)bytes << 3) - 1;
SPI(bus).USER1 = SET_FIELD(SPI(bus).USER1, SPI_USER1_MISO_BITLEN, bits);
SPI(bus).USER1 = SET_FIELD(SPI(bus).USER1, SPI_USER1_MOSI_BITLEN, bits);
#ifdef MCU_ESP32
_spi[bus].regs->mosi_dlen.val = bits;
_spi[bus].regs->miso_dlen.val = bits;
#else /* MCU_ESP32 */
_spi[bus].regs->user1.usr_mosi_bitlen = bits;
_spi[bus].regs->user1.usr_miso_bitlen = bits;
#endif /* MCU_ESP32 */
}
inline static void _wait(uint8_t bus)
inline static void IRAM_ATTR _wait(uint8_t bus)
{
while (SPI(bus).CMD & SPI_CMD_USR) {}
/* SPI_CMD_REG.SPI_USR is cleared when operation has been finished */
while (_spi[bus].regs->cmd.usr) {}
}
inline static void _start(uint8_t bus)
inline static void IRAM_ATTR _start(uint8_t bus)
{
SPI(bus).CMD |= SPI_CMD_USR;
/* set SPI_CMD_REG.SPI_USR to start an operation */
_spi[bus].regs->cmd.usr = 1;
}
inline static void _store_data(uint8_t bus, const void *data, size_t len)
inline static void IRAM_ATTR _store_data(uint8_t bus, const void *data, size_t len)
{
uint8_t words = len / 4;
uint8_t tail = len % 4;
memcpy((void *)SPI(bus).W, data, len - tail);
memcpy((void *)_spi[bus].regs->data_buf, data, len - tail);
if (!tail) {
return;
@ -317,12 +454,12 @@ inline static void _store_data(uint8_t bus, const void *data, size_t len)
for (uint8_t i = 0; i < tail; i++) {
last = last | (offs[i] << (i * 8));
}
SPI(bus).W[words] = last;
_spi[bus].regs->data_buf[words] = last;
}
static const uint8_t spi_empty_out[SPI_BLOCK_SIZE] = { 0 };
static void _spi_buf_transfer(uint8_t bus, const void *out, void *in, size_t len)
static void IRAM_ATTR _spi_buf_transfer(uint8_t bus, const void *out, void *in, size_t len)
{
DEBUG("%s bus=%u out=%p in=%p len=%u\n", __func__, bus, out, in, len);
@ -333,15 +470,14 @@ static void _spi_buf_transfer(uint8_t bus, const void *out, void *in, size_t len
_start(bus);
_wait(bus);
if (in) {
memcpy(in, (void *)SPI(bus).W, len);
memcpy(in, (void *)_spi[bus].regs->data_buf, len);
}
}
void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
const void *out, void *in, size_t len)
void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
const void *out, void *in, size_t len)
{
/* see spi_init */
CHECK_PARAM (bus == SPI_DEV(0));
assert(bus < SPI_NUMOF);
DEBUG("%s bus=%u cs=%u cont=%d out=%p in=%p len=%u\n",
__func__, bus, cs, cont, out, in, len);
@ -360,9 +496,7 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
}
#endif
if (cs != SPI_CS_UNDEF) {
gpio_clear (cs);
}
gpio_clear(cs != SPI_CS_UNDEF ? cs : spi_config[bus].cs);
size_t blocks = len / SPI_BLOCK_SIZE;
uint8_t tail = len % SPI_BLOCK_SIZE;
@ -382,8 +516,8 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
in ? (uint8_t *)in + blocks * SPI_BLOCK_SIZE : NULL, tail);
}
if (!cont && (cs != SPI_CS_UNDEF)) {
gpio_set (cs);
if (!cont) {
gpio_set(cs != SPI_CS_UNDEF ? cs : spi_config[bus].cs);
}
#if ENABLE_DEBUG
@ -396,21 +530,3 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
}
#endif
}
void spi_print_config(void)
{
LOG_INFO("\tSPI_DEV(0): ");
LOG_INFO("sck=%d " , SPI0_SCK_GPIO);
LOG_INFO("miso=%d ", SPI0_MISO_GPIO);
LOG_INFO("mosi=%d ", SPI0_MOSI_GPIO);
LOG_INFO("cs=%d\n" , SPI0_CS0_GPIO);
}
#else /* MODULE_PERIPH_SPI */
void spi_print_config(void)
{
LOG_INFO("\tSPI: no devices\n");
}
#endif /* MODULE_PERIPH_SPI */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -27,9 +27,10 @@
#include "xtimer.h"
#include "periph/timer.h"
#include "common.h"
#include "irq_arch.h"
#include "esp/common_macros.h"
#include "esp_common.h"
#include "irq_arch.h"
#include "rom/ets_sys.h"
#include "sdk/sdk.h"
#include "xtensa/hal.h"
@ -295,18 +296,14 @@ static void IRAM __timer_channel_stop (struct hw_timer_t* timer, struct hw_chann
void timer_print_config(void)
{
for (int i = 0; i < HW_TIMER_NUMOF; i++) {
LOG_INFO("\tTIMER_DEV(%d): %d channel(s)\n", i,
ARRAY_SIZE(timers[i].channels));
for (unsigned i = 0; i < HW_TIMER_NUMOF; i++) {
printf("\tTIMER_DEV(%u)\t%d channel(s)\n", i,
ARRAY_SIZE(timers[i].channels));
}
}
#else /* MODULE_ESP_SW_TIMER */
#ifndef MODULE_ESP_SDK
#error Software timers are not available in Non-SDK version, use USE_SDK=1 to enable SDK-version.
#else
/* software timer based on os_timer_arm functions */
#define OS_TIMER_NUMOF 1
@ -319,6 +316,8 @@ void timer_print_config(void)
#define OS_TIMER_DELTA_RSHIFT 16
#define OS_TIMER_CORRECTION 4
extern void os_timer_arm_us(os_timer_t *ptimer, uint32_t time, bool repeat_flag);
/* Since hardware timer FRC1 is needed to implement PWM, we have to map our */
/* timer using the exsting ETS timer with 1 us clock rate */
@ -560,12 +559,10 @@ static void IRAM __timer_channel_stop (struct phy_timer_t* timer, struct phy_cha
void timer_print_config(void)
{
for (int i = 0; i < OS_TIMER_NUMOF; i++) {
LOG_INFO("\tTIMER_DEV(%d): %d channel(s)\n", i,
ARRAY_SIZE(timers[i].channels));
for (unsigned i = 0; i < OS_TIMER_NUMOF; i++) {
printf("\tTIMER_DEV(%u)\t%d channel(s)\n", i,
ARRAY_SIZE(timers[i].channels));
}
}
#endif /* NON_SDK */
#endif /* MODULE_ESP_SW_TIMER */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -19,147 +19,461 @@
* @}
*/
#define ENABLE_DEBUG 0
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "common.h"
#include "esp_common.h"
#include "cpu.h"
#include "irq_arch.h"
#include "log.h"
#include "sched.h"
#include "thread.h"
#include "periph/gpio.h"
#include "periph/uart.h"
#include "eagle_soc.h"
#include "stdio_uart.h"
#include "esp/common_macros.h"
#include "rom/ets_sys.h"
#include "xtensa/xtensa_api.h"
#ifdef MCU_ESP32
#include "gpio_arch.h"
#include "driver/periph_ctrl.h"
#include "soc/gpio_reg.h"
#include "soc/gpio_sig_map.h"
#include "soc/gpio_struct.h"
#include "soc/rtc.h"
#include "soc/uart_reg.h"
#include "soc/uart_struct.h"
#undef UART_CLK_FREQ
#define UART_CLK_FREQ rtc_clk_apb_freq_get() /* APB_CLK is used */
#else /* MCU_ESP32 */
#include "esp8266/uart_struct.h"
#ifdef MODULE_ESP_QEMU
#include "esp/uart_regs.h"
#include "sdk/sdk.h"
#endif /* MODULE_ESP_QEMU */
/**
* @brief Allocate memory to store the callback functions.
*/
static uart_isr_ctx_t isr_ctx[UART_NUMOF];
#define UART0 uart0
#define UART1 uart1
#define CPU_INUM_UART ETS_UART_INUM
static uint8_t IRAM __uart_rx_one_char (uart_t uart);
static void __uart_tx_one_char(uart_t uart, uint8_t data);
static void __uart_intr_enable (uart_t uart);
static void IRAM __uart_intr_handler (void *para);
#endif /* MCU_ESP32 */
struct uart_hw_t {
uart_dev_t* regs; /* pointer to register data struct of the UART device */
uint8_t pin_txd; /* TxD pin used */
uint8_t pin_rxd; /* RxD pin used */
bool used; /* indicates whether UART is used */
uint32_t baudrate; /* used baudrate */
uart_data_bits_t data; /* used data bits */
uart_stop_bits_t stop; /* used stop bits */
uart_parity_t parity; /* used parity bits */
uart_isr_ctx_t isr_ctx; /* callback functions */
#ifdef MCU_ESP32
uint8_t mod; /* peripheral hardware module of the UART interface */
uint8_t signal_txd; /* TxD signal from the controller */
uint8_t signal_rxd; /* RxD signal to the controller */
uint8_t int_src; /* peripheral interrupt source used by the UART device */
#endif
};
/* hardware resources */
static struct uart_hw_t _uarts[] = {
{
.regs = &UART0,
.used = false,
.baudrate = STDIO_UART_BAUDRATE,
.data = UART_DATA_BITS_8,
.stop = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
#ifdef MCU_ESP32
.mod = PERIPH_UART0_MODULE,
.signal_txd = U0TXD_OUT_IDX,
.signal_rxd = U0RXD_IN_IDX,
.int_src = ETS_UART0_INTR_SOURCE
},
{
.regs = &UART1,
.used = false,
.baudrate = STDIO_UART_BAUDRATE,
.data = UART_DATA_BITS_8,
.stop = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.mod = PERIPH_UART1_MODULE,
.signal_txd = U1TXD_OUT_IDX,
.signal_rxd = U1RXD_IN_IDX,
.int_src = ETS_UART1_INTR_SOURCE
},
{
.regs = &UART2,
.used = false,
.baudrate = STDIO_UART_BAUDRATE,
.data = UART_DATA_BITS_8,
.stop = UART_STOP_BITS_1,
.parity = UART_PARITY_NONE,
.mod = PERIPH_UART2_MODULE,
.signal_txd = U2TXD_OUT_IDX,
.signal_rxd = U2RXD_IN_IDX,
.int_src = ETS_UART2_INTR_SOURCE
#endif /* MCU_ESP32 */
},
};
/* declaration of external functions */
extern void uart_div_modify(uint8_t uart_no, uint32_t div);
/* forward declaration of internal functions */
static int _uart_set_baudrate(uart_t uart, uint32_t baudrate);
static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits,
uart_parity_t parity, uart_stop_bits_t stop_bits);
static uint8_t IRAM _uart_rx_one_char(uart_t uart);
static void _uart_tx_one_char(uart_t uart, uint8_t data);
static void _uart_intr_enable(uart_t uart);
static void _uart_config (uart_t uart);
static void IRAM _uart_intr_handler(void *para);
int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
{
CHECK_PARAM_RET (uart < UART_NUMOF, -1);
DEBUG("%s uart=%d, rate=%d, rx_cb=%p, arg=%p\n", __func__, uart, baudrate, rx_cb, arg);
/* setup the baudrate */
uart_div_modify(uart, UART_CLK_FREQ / baudrate);
assert(uart < UART_NUMOF_MAX);
assert(uart < UART_NUMOF);
_uarts[uart].pin_txd = uart_config[uart].txd;
_uarts[uart].pin_rxd = uart_config[uart].rxd;
#ifdef MCU_ESP32
/* UART1 and UART2 have configurable pins */
if ((uart == UART_DEV(1) || uart == UART_DEV(2))) {
/* reset the pins when they were already used as UART pins */
if (gpio_get_pin_usage(_uarts[uart].pin_txd) == _UART) {
gpio_set_pin_usage(_uarts[uart].pin_txd, _GPIO);
}
if (gpio_get_pin_usage(_uarts[uart].pin_rxd) == _UART) {
gpio_set_pin_usage(_uarts[uart].pin_rxd, _GPIO);
}
/* try to initialize the pins as GPIOs first */
if (gpio_init(_uarts[uart].pin_txd, GPIO_OUT) ||
gpio_init(_uarts[uart].pin_rxd, GPIO_IN)) {
return -1;
}
/* store the usage type in GPIO table */
gpio_set_pin_usage(_uarts[uart].pin_txd, _UART);
gpio_set_pin_usage(_uarts[uart].pin_rxd, _UART);
/* connect TxD pin to the TxD output signal through the GPIO matrix */
GPIO.func_out_sel_cfg[_uarts[uart].pin_txd].func_sel = _uarts[uart].signal_txd;
/* connect RxD input signal to the RxD pin through the GPIO matrix */
GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].sig_in_sel = 1;
GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].sig_in_inv = 0;
GPIO.func_in_sel_cfg[_uarts[uart].signal_rxd].func_sel = _uarts[uart].pin_rxd;
}
#endif
_uarts[uart].baudrate = baudrate;
/* register interrupt context */
isr_ctx[uart].rx_cb = rx_cb;
isr_ctx[uart].arg = arg;
_uarts[uart].isr_ctx.rx_cb = rx_cb;
_uarts[uart].isr_ctx.arg = arg;
if (rx_cb) {
ets_isr_attach (ETS_UART_INUM, __uart_intr_handler, 0);
/* since reading is done byte for byte we set the RX FIFO FULL */
/* interrupt level to 1 byte */
UART(uart).CONF1 = SET_FIELD(UART(uart).CONF1, UART_CONF1_RXFIFO_FULL_THRESHOLD, 1);
/* enable the RX FIFO FULL interrupt */
__uart_intr_enable (uart);
}
/* enable and configure the according UART module */
uart_poweron(uart);
return UART_OK;
}
#if MODULE_PERIPH_UART_MODECFG
int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity,
uart_stop_bits_t stop_bits)
{
return _uart_set_mode(uart, data_bits, parity, stop_bits);
}
#endif
void uart_write(uart_t uart, const uint8_t *data, size_t len)
{
CHECK_PARAM (uart < UART_NUMOF);
CHECK_PARAM(uart < UART_NUMOF);
for (size_t i = 0; i < len; i++) {
__uart_tx_one_char(uart, data[i]);
_uart_tx_one_char(uart, data[i]);
}
}
void uart_poweron (uart_t uart)
{
/* UART can't be powered on/off, just return */
CHECK_PARAM(uart < UART_NUMOF);
#ifdef MCU_ESP32
periph_module_enable(_uarts[uart].mod);
#endif
_uart_config(uart);
}
void uart_poweroff (uart_t uart)
{
/* UART can't be powered on/off, just return */
CHECK_PARAM(uart < UART_NUMOF);
#ifdef MCU_ESP32
periph_module_disable(_uarts[uart].mod);
#endif
}
void IRAM __uart_intr_handler (void *arg)
/* systemwide UART initializations */
void uart_system_init (void)
{
for (unsigned uart = 0; uart < UART_NUMOF; uart++) {
/* reset all UART interrupt status registers */
_uarts[uart].regs->int_clr.val = ~0;
}
}
void uart_print_config(void)
{
for (unsigned uart = 0; uart < UART_NUMOF; uart++) {
printf("\tUART_DEV(%u)\ttxd=%d rxd=%d\n", uart,
uart_config[uart].txd, uart_config[uart].rxd);
}
}
static void IRAM _uart_intr_handler(void *arg)
{
/* to satisfy the compiler */
(void)arg;
irq_isr_enter ();
irq_isr_enter();
DEBUG("%s \n", __func__);
/* UART0, UART1, UART2 peripheral interrupt sources are routed to the same
interrupt, so we have to use the status to distinguish interruptees */
for (unsigned uart = 0; uart < UART_NUMOF; uart++) {
if (_uarts[uart].used) {
DEBUG("%s uart=%d int_st=%08x\n", __func__,
uart, _uarts[uart].regs->int_st.val);
/*
* UART0 and UART1 interrupts are combined togther. So we have to
* iterate over all UART devices and test the INT_STATUS register for
* interrupts
*/
for (int i = 0; i < UART_NUMOF; i++) {
uart_t uart = UART_DEV(0); /* UartDev.buff_uart_no; */
if (UART(uart).INT_STATUS & UART_INT_STATUS_RXFIFO_FULL) {
/* clear interrupt flag */
uint8_t data = __uart_rx_one_char (uart);
if (_uarts[uart].used && _uarts[uart].regs->int_st.rxfifo_full) {
/* read one byte of data */
uint8_t data = _uart_rx_one_char (uart);
/* if registered, call the RX callback function */
if (_uarts[uart].isr_ctx.rx_cb) {
_uarts[uart].isr_ctx.rx_cb(_uarts[uart].isr_ctx.arg, data);
}
/* clear interrupt flag */
_uarts[uart].regs->int_clr.rxfifo_full = 1;
}
/* call registered RX callback function */
isr_ctx[uart].rx_cb(isr_ctx[uart].arg, data);
/* clear interrupt flag */
UART(uart).INT_CLEAR |= UART_INT_CLEAR_RXFIFO_FULL;
}
else {
/* TODO handle other type of interrupts, for the moment just clear them */
UART(uart).INT_CLEAR = 0x1f;
/* TODO handle other types of interrupts, for the moment just clear them */
_uarts[uart].regs->int_clr.val = ~0x0;
}
}
irq_isr_exit ();
irq_isr_exit();
}
/* RX/TX FIFO capacity is 128 byte */
#define UART_FIFO_MAX 1
#define UART_FIFO_MAX 128
/* receive one data byte with wait */
static uint8_t IRAM __uart_rx_one_char (uart_t uart)
static uint8_t IRAM _uart_rx_one_char (uart_t uart)
{
/* uint8_t fifo_len = FIELD2VAL(UART_STATUS_RXFIFO_COUNT, UART(uart).STATUS); */
#if defined(MODULE_ESP_QEMU) && defined(MCU_ESP8266)
/* wait until at least von byte is in RX FIFO */
while (!FIELD2VAL(UART_STATUS_RXFIFO_COUNT, UART(uart).STATUS)) {}
/* read the lowest byte from RX FIFO register */
return UART(uart).FIFO & 0xff; /* only bit 0 ... 7 */
#else
/* wait until at least von byte is in RX FIFO */
while (!_uarts[uart].regs->status.rxfifo_cnt) {}
/* read the lowest byte from RX FIFO register */
return _uarts[uart].regs->fifo.rw_byte;
#endif
}
/* send one data byte with wait */
static void __uart_tx_one_char(uart_t uart, uint8_t data)
static void _uart_tx_one_char(uart_t uart, uint8_t data)
{
/* wait until at least one byte is avaiable in the TX FIFO */
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(uart).STATUS) >= UART_FIFO_MAX) {}
/* wait until at least one byte is available in the TX FIFO */
while (_uarts[uart].regs->status.txfifo_cnt >= UART_FIFO_MAX) {}
/* send the byte by placing it in the TX FIFO */
/* send the byte by placing it in the TX FIFO using MPU */
#ifdef MCU_ESP32
WRITE_PERI_REG(UART_FIFO_AHB_REG(uart), data);
#else /* MCU_ESP32 */
#ifdef MODULE_ESP_QEMU
UART(uart).FIFO = data;
#else /* MODULE_ESP_QEMU */
_uarts[uart].regs->fifo.rw_byte = data;
#endif /* MODULE_ESP_QEMU */
#endif /* MCU_ESP32 */
}
static void __uart_intr_enable(uart_t uart)
static void _uart_intr_enable(uart_t uart)
{
UART(uart).INT_ENABLE |= UART_INT_ENABLE_RXFIFO_FULL;
ETS_INTR_ENABLE(ETS_UART_INUM);
_uarts[uart].regs->int_ena.rxfifo_full = 1;
_uarts[uart].regs->int_clr.rxfifo_full = 1;
_uarts[uart].used = true;
DEBUG("%s %08x\n", __func__, UART(uart).INT_ENABLE);
DEBUG("%s %08x\n", __func__, _uarts[uart].regs->int_ena.val);
}
void uart_print_config(void)
static void _uart_config(uart_t uart)
{
LOG_INFO("\tUART_DEV(0): txd=%d rxd=%d\n", UART0_TXD, UART0_RXD);
assert(uart < UART_NUMOF);
while (_uarts[uart].regs->status.txfifo_cnt != 0) { }
#if 0
/* setup the baudrate */
if (uart == UART_DEV(0) || uart == UART_DEV(1)) {
/* for UART0 and UART1, we can us the ROM function */
uart_div_modify(uart, (UART_CLK_FREQ << 4) / _uarts[uart].baudrate);
}
else
#endif
if (_uart_set_baudrate(uart, _uarts[uart].baudrate) != UART_OK) {
return;
}
/* set number of data bits, stop bits and parity mode */
if (_uart_set_mode(uart, _uarts[uart].data, _uarts[uart].stop,
_uarts[uart].parity) != UART_OK) {
return;
}
/* reset the FIFOs */
_uarts[uart].regs->conf0.rxfifo_rst = 1;
_uarts[uart].regs->conf0.rxfifo_rst = 0;
_uarts[uart].regs->conf0.txfifo_rst = 1;
_uarts[uart].regs->conf0.txfifo_rst = 0;
if (_uarts[uart].isr_ctx.rx_cb) {
/* since reading can only be done byte by byte, we set
UART_RXFIFO_FULL_THRHD interrupt level to 1 byte */
_uarts[uart].regs->conf1.rxfifo_full_thrhd = 1;
/* enable the RX FIFO FULL interrupt */
_uart_intr_enable(uart);
#ifdef MCU_ESP32
/* route all UART interrupt sources to same the CPU interrupt */
intr_matrix_set(PRO_CPU_NUM, _uarts[uart].int_src, CPU_INUM_UART);
#endif /* MCU_ESP32 */
/* we have to enable therefore the CPU interrupt here */
xt_set_interrupt_handler(CPU_INUM_UART, _uart_intr_handler, NULL);
xt_ints_on(BIT(CPU_INUM_UART));
}
}
static int _uart_set_baudrate(uart_t uart, uint32_t baudrate)
{
DEBUG("%s uart=%d, rate=%d\n", __func__, uart, baudrate);
CHECK_PARAM_RET (uart < UART_NUMOF, -1);
/* wait until TX FIFO is empty */
while (_uarts[uart].regs->status.txfifo_cnt != 0) { }
critical_enter();
_uarts[uart].baudrate = baudrate;
#ifdef MCU_ESP32
/* use APB_CLK */
_uarts[uart].regs->conf0.tick_ref_always_on = 1;
/* compute and set the integral and the decimal part */
uint32_t clk_div = (UART_CLK_FREQ << 4) / _uarts[uart].baudrate;
_uarts[uart].regs->clk_div.div_int = clk_div >> 4;
_uarts[uart].regs->clk_div.div_frag = clk_div & 0xf;
#else
/* compute and set clock divider */
uint32_t clk_div = UART_CLK_FREQ / _uarts[uart].baudrate;
_uarts[uart].regs->clk_div.val = clk_div & 0xFFFFF;
#endif
critical_exit();
return UART_OK;
}
static int _uart_set_mode(uart_t uart, uart_data_bits_t data_bits,
uart_parity_t parity, uart_stop_bits_t stop_bits)
{
DEBUG("%s uart=%d, data_bits=%d parity=%d stop_bits=%d\n", __func__,
uart, data_bits, parity, stop_bits);
CHECK_PARAM_RET (uart < UART_NUMOF, UART_NODEV);
critical_enter();
/* set number of data bits */
switch (data_bits) {
case UART_DATA_BITS_5: _uarts[uart].regs->conf0.bit_num = 0; break;
case UART_DATA_BITS_6: _uarts[uart].regs->conf0.bit_num = 1; break;
case UART_DATA_BITS_7: _uarts[uart].regs->conf0.bit_num = 2; break;
case UART_DATA_BITS_8: _uarts[uart].regs->conf0.bit_num = 3; break;
default: LOG_TAG_ERROR("uart", "invalid number of data bits\n");
critical_exit();
return UART_NOMODE;
}
/* store changed number of data bits in configuration */
_uarts[uart].data = data_bits;
/* set number of stop bits */
#ifdef MCU_ESP32
/* workaround for hardware bug when stop bits are set to 2-bit mode. */
switch (stop_bits) {
case UART_STOP_BITS_1: _uarts[uart].regs->conf0.stop_bit_num = 1;
_uarts[uart].regs->rs485_conf.dl1_en = 0;
break;
case UART_STOP_BITS_2: _uarts[uart].regs->conf0.stop_bit_num = 1;
_uarts[uart].regs->rs485_conf.dl1_en = 1;
break;
default: LOG_TAG_ERROR("uart", "invalid number of stop bits\n");
critical_exit();
return UART_NOMODE;
}
#else
switch (stop_bits) {
case UART_STOP_BITS_1: _uarts[uart].regs->conf0.stop_bit_num = 1; break;
case UART_STOP_BITS_2: _uarts[uart].regs->conf0.stop_bit_num = 3; break;
default: LOG_TAG_ERROR("uart", "invalid number of stop bits\n");
critical_exit();
return UART_NOMODE;
}
#endif
/* store changed number of stop bits in configuration */
_uarts[uart].stop = stop_bits;
/* set parity mode */
switch (parity) {
case UART_PARITY_NONE: _uarts[uart].regs->conf0.parity_en = 0;
break;
case UART_PARITY_EVEN: _uarts[uart].regs->conf0.parity = 0;
_uarts[uart].regs->conf0.parity_en = 1;
break;
case UART_PARITY_ODD: _uarts[uart].regs->conf0.parity = 1;
_uarts[uart].regs->conf0.parity_en = 1;
break;
default: LOG_TAG_ERROR("uart", "invalid or unsupported parity mode\n");
critical_exit();
return UART_NOMODE;
}
/* store changed parity in configuration */
_uarts[uart].parity = parity;
critical_exit();
return UART_OK;
}

View File

@ -1,3 +1,3 @@
MODULE=sdk
MODULE=esp_sdk
include $(RIOTBASE)/Makefile.base

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -16,8 +16,35 @@
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef MODULE_ESP_SDK
#include "sdk/ets.h"
#include <string.h>
#endif /* MODULE_ESP_SDK */
#include "eagle_soc.h"
#include "sdk/sdk.h"
uint8_t ets_get_cpu_frequency(void)
{
return system_get_cpu_freq();
}
void *ets_memcpy(void *dst, const void *src, size_t size)
{
return memcpy(dst, src, size);
}
void ets_wdt_disable(void)
{
SET_PERI_REG_BITS(EDGE_INT_ENABLE_REG, BIT0, 0, BIT0);
SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_EN_MASK, 0, WDT_CTL_EN_LSB);
}
void ets_wdt_enable (void)
{
SET_PERI_REG_BITS(EDGE_INT_ENABLE_REG, BIT0, 1, BIT0);
SET_PERI_REG_BITS(PERIPHS_WDT_BASEADDR + WDT_CTL_ADDRESS, WDT_CTL_EN_MASK, 1, WDT_CTL_EN_LSB);
}
void ets_install_putc1(void (*p)(char c))
{
os_install_putc1(p);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -21,27 +21,25 @@
#ifndef DOXYGEN
#include <stdint.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include "c_types.h"
#include "ets_sys.h"
#include "rom/ets_sys.h"
#ifdef __cplusplus
extern "C" {
#endif
/* interrupts that are not defined in espressif/ets_sys.h */
/* interrupts that are not defined in rom/ets_sys.h */
#define ETS_WDEV_INUM 0 /* WDEV process FIQ interrupt */
#define ETS_RTC_INUM 3 /* RTC interrupt */
#define ETS_CCOM_INUM 6 /* CCOMPARE0 match interrupt */
#define ETS_SOFT_INUM 7 /* software interrupt */
#define ETS_WDT_INUM 8 /* SDK watchdog timer */
#define ETS_FRC2_INUM 10 /* SDK FRC2 timer interrupt */
/*
* The following functions are mappings or dummies for source code
* compatibility of SDK and NON-SDK version
* compatibility of NONOS-SDK and RTOS-SDK version
*/
#include "xtensa/xtensa_api.h"
@ -50,30 +48,20 @@ extern "C" {
#define ets_isr_unmask(x) xt_ints_on(x)
#define ets_isr_attach(i,f,a) xt_set_interrupt_handler(i,f,a)
#define ETS_INTR_ENABLE(inum) ets_isr_unmask((1<<inum))
#define ETS_INTR_DISABLE(inum) ets_isr_mask((1<<inum))
#define _xtos_set_exception_handler(n,f) xt_set_exception_handler(n,f)
#ifndef MODULE_ESP_SDK
extern void ets_delay_us(uint16_t us);
extern void ets_timer_arm_new(ETSTimer *ptimer, uint32_t ms_us, int repeat_flag, int is_ms);
extern void ets_timer_disarm(ETSTimer *ptimer);
extern void ets_timer_setfn(ETSTimer *ptimer, ETSTimerFunc *pfunction, void *arg);
#endif
extern void ets_timer_arm(ETSTimer *ptimer, uint32_t ms, bool repeat_flag);
extern void ets_timer_handler_isr(void);
extern void ets_install_uart_printf(void);
extern void ets_install_putc1(void (*p)(char c));
extern int ets_uart_printf(const char *format, ...);
extern int ets_putc(int);
extern int ets_printf(const char * format, ...);
extern int ets_vprintf(void *function, const char *format, va_list arg);
extern uint8_t ets_get_cpu_frequency(void);
extern void ets_update_cpu_frequency(uint8_t);
extern void ets_update_cpu_frequency(uint8_t);
extern void *ets_memcpy(void *to, const void *from, size_t size);
extern int ets_vprintf(const char *fmt, va_list ap);
extern int ets_printf(const char *fmt, ...);
extern int ets_putc(int c);
extern void ets_install_putc1(void (*p)(char c));
extern void *ets_memcpy(void *dst, const void *src, size_t size);
extern void ets_wdt_disable(void);
extern void ets_wdt_enable (void);

View File

@ -1,198 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*
* PLEASE NOTE: This file is only used in SDK version
*/
/*
* Internally, the SDK uses its own priority-based multitasking system,
* the *ETS*, to handle hardware components such as the WiFi interface, or to
* implement event-driven functions such as software timers. ETS periodically
* executes all ETS tasks with pending events in an infinite loop with the ROM
* function *ets_run*.
*
* ETS doesn't process interrupts directly in interrupt service routines.
* Instead, they use the *ets_post* ROM function to send an event to one of the
* ETS tasks, which then processes the interrupts asynchronously. Context
* switches are not possible in interrupt service routines.
*
* To use SDK functions and keep the system alive, ETS tasks with pending
* events have to be handled. For that purpose
*
* - the *ets_task_func* RIOT thread with highest possible priority is used
* - the ROM functions *ets_run* and *ets_post* are overwritten.
*
* The *ets_task_func* RIOT thread is waiting for a thread flag, which is set
* by the *ets_post function* at the end of an ETS interrupt service routine.
* The flag indicates that there are ETS tasks with pending events that need
* to be executed. The *ets_task_func* RIOT thread then calls the *ets_run*
* function, which performs all ETS tasks with pending events exactly once.
*
* Thus, when a hardware component used by the SDK triggers an interrupt, e.g.
* the WiFi interface, the interrupt sevice routine posts an event to the ETS
* task by calling the *ets_post* function. The overwritten version of this
* function sets the thread flag of the *ets_task_func* thread. The thread
* then calls function *ets_run* to process pending events.
*/
#ifdef MODULE_ESP_SDK
#define ENABLE_DEBUG 0
#include <stdio.h>
#include "irq_arch.h"
#include "mutex.h"
#include "thread.h"
#include "esp/common_macros.h"
#include "sdk/ets_task.h"
#include "sdk/sdk.h"
static uint8_t min_prio = 0;
/* helper function for *ets_run* */
uint8_t ets_highest_1_bit (uint32_t mask)
{
__asm__ volatile ("nsau %0, %1;" :"=r"(mask) : "r"(mask));
return 32 - mask;
}
/*
* Perform the execution of all pending ETS tasks. This is necessary to
* keep the underlying ETS system used by the SDK alive. It is called from
* the RIOT thread *ets_task_func*.
*/
void IRAM ets_tasks_run (void)
{
#if ENABLE_DEBUG
uint32_t _entry = phy_get_mactime();
uint32_t _exit;
ets_printf("ets_tasks_run @%lu\n", _entry);
#endif
/* reset hardware watchdog here */
system_soft_wdt_feed();
while (1) {
uint8_t hbit;
int state = irq_disable();
hbit = ets_highest_1_bit (ets_task_exec_mask);
if (min_prio < hbit) {
ets_task_tcb_t* task = &ets_task_tab[hbit-1];
ETSEvent * event = &task->queue[task->qposr++];
if (task->qposr == task->qlength) {
task->qposr = 0;
}
if (--task->qpending == 0) {
ets_task_exec_mask &= ~task->maskbit;
}
ets_task_min_prio = hbit;
irq_restore(state);
task->task(event);
ets_task_min_prio = min_prio;
}
else {
irq_restore(state);
break;
}
}
#if ENABLE_DEBUG
_exit = phy_get_mactime();
ets_printf("ets_tasks_run @%lu for %lu us\n", _entry, _exit - _entry);
#endif
/* reset hardware watchdog here again */
system_soft_wdt_feed();
}
#define THREAD_FLAG_ETS_THREAD (1 << 0)
static volatile thread_t* ets_thread = NULL;
/*
* Thread *ets_task_func* is waiting for the thread flag THREAD_FLAG_ETS_THREAD
* indicating that ETS tasks have pending events and need to be executed. When
* the thread flag is set, it calls the *ets_run* function, which performs
* all ETS tasks with pending events exactly once. The thread flag is set by
* the *ets_post* function, which is called at the end of an ETS interrupt
* service routine.
*/
void *ets_task_func(void *arg)
{
(void) arg;
ets_thread = sched_active_thread;
while (1) {
thread_flags_wait_one(THREAD_FLAG_ETS_THREAD);
ets_tasks_run();
}
return NULL;
}
/* helper macro for *ets_post */
#define irom_cache_enabled() (*((uint32_t*)0x60000208) & (1 << 17))
/* ETS timer task priority */
#define TIMER_TASK_PRIORITY 31
/* reference to the *ets_post* ROM function */
typedef uint32_t (*ets_post_function_t)(uint32_t prio, ETSSignal sig, ETSParam par);
static ets_post_function_t ets_post_rom = (ets_post_function_t)0x40000e24;
/*
* Overwritten version of ROM function *ets_post*.
*
* ETS doesn't process interrupts directly in interrupt service routines.
* Instead, they use the *ets_post* ROM function to send an event to one of the
* ETS tasks, which then processes the interrupts asynchronously. Context
* switches are not possible in interrupt service routines.
*
* Please note: *ets_post* is executed in interrupt context
*/
uint32_t IRAM ets_post (uint32_t prio, ETSSignal sig, ETSParam par)
{
/* This function is executed in interrupt context */
uint32_t ret;
critical_enter();
/* test whether we are in hardware timer interrupt handling routine */
if (prio == TIMER_TASK_PRIORITY) {
/* first call ETS system post function */
ret = ets_post_rom (prio, sig, par);
/* handle only pending timer events */
if (irom_cache_enabled()) {
ets_timer_handler_isr();
}
}
else {
/* simply call ROM ets_post function */
ret = ets_post_rom (prio, sig, par);
}
/* since only timer events are handled we have to reset watch dog timer */
if (irom_cache_enabled()) {
system_soft_wdt_feed();
}
if (ets_thread && irom_cache_enabled()) {
thread_flags_set((thread_t*)ets_thread, THREAD_FLAG_ETS_THREAD);
}
critical_exit();
return ret;
}
void ets_tasks_init(void)
{
/* there is nothing to be done here at the moment */
}
#endif /* MODULE_ESP_SDK */

View File

@ -1,61 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#ifndef ETS_TASK_H
#define ETS_TASK_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
#ifdef MODULE_ESP_SDK
#include "ets_sys.h"
extern uint8_t ets_task_min_prio;
/* Task control block definition as used for ETS task functions */
typedef struct {
ETSTask task; /* +0 task function */
ETSEvent* queue; /* +4 event queue (ring buffer) */
uint8_t qlength; /* +8 event queue length */
uint8_t qposw; /* +9 event queue position for write */
uint8_t qposr; /* +10 event queue position for read */
uint8_t qpending; /* +11 pending events */
uint32_t maskbit; /* +12 task mask bit */
} ets_task_tcb_t;
/* ROM variables, defined in esp8266.riot-os.app.ld */
/* source: disassembly of boot rom at https://github.com/trebisky/esp8266 */
extern uint8_t ets_task_min_prio; /* 0x3fffc6fc */
extern void* ets_idle_cb; /* 0x3fffdab0 */
extern void* ets_idle_arg; /* 0x3fffdab4 */
extern uint32_t ets_task_exec_mask; /* 0x3fffdab8 */
extern ets_task_tcb_t ets_task_tab[32]; /* 0x3fffdac0 */
extern uint32_t ets_post (uint32_t prio, ETSSignal sig, ETSParam par);
void ets_tasks_run (void);
void ets_tasks_init (void);
#else /* MODULE_ESP_SDK */
#define ets_tasks_run()
#define ets_tasks_init()
#endif /* MODULE_ESP_SDK */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* ETS_TASK_H */

View File

@ -1,220 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266
* @{
*
* @file
* @brief lwIP functions required as symbols by the SDK
*
* This file defines a number of lwIP functions that are required as symbols by
* Espressif's SDK libraries. Since RIOT doesn't need lwIP, these functions are
* only dummies without real functionality. Using these functions instead of
* the lwIP functions as provided with the SDK saves arround 4 kBytes of RAM.
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifdef MODULE_ESP_SDK
#include "lwip/err.h"
#include "lwip/ip_addr.h"
#include "lwip/netif.h"
#include "lwip/pbuf.h"
#include "lwip/tcp_impl.h"
#include "netif/etharp.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#include "log.h"
#ifndef ERR_OK
#define ERR_OK 0
#endif
const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
err_t ethernet_input(struct pbuf *pb, struct netif* netif)
{
DEBUG("%s\n", __func__);
(void)pb;
(void)netif;
return ERR_OK;
}
err_t etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr)
{
DEBUG("%s\n", __func__);
(void)netif;
(void)q;
(void)ipaddr;
return ERR_OK;
}
err_t etharp_request(struct netif *netif, ip_addr_t *ipaddr)
{
DEBUG("%s\n", __func__);
(void)netif;
(void)ipaddr;
return ERR_OK;
}
void etharp_tmr(void)
{
DEBUG("%s\n", __func__);
}
void etharp_cleanup_netif(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
}
void dhcp_cleanup(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
}
err_t dhcp_start(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
return ERR_OK;
}
err_t dhcp_renew(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
return ERR_OK;
}
err_t dhcp_release(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
return ERR_OK;
}
void dhcp_stop(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
}
void dhcp_network_changed(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
}
void dhcp_coarse_tmr(void)
{
DEBUG("%s\n", __func__);
}
void dhcp_fine_tmr(void)
{
DEBUG("%s\n", __func__);
}
void dhcps_start(struct ip_info *info)
{
DEBUG("%s\n", __func__);
(void)info;
}
void dhcps_stop(void)
{
DEBUG("%s\n", __func__);
}
void dhcps_coarse_tmr(void)
{
DEBUG("%s\n", __func__);
}
union tcp_listen_pcbs_t tcp_listen_pcbs;
struct tcp_pcb *tcp_active_pcbs;
struct tcp_pcb *tcp_tw_pcbs;
void tcp_seg_free(struct tcp_seg *seg)
{
DEBUG("%s\n", __func__);
(void)seg;
}
void tcp_abort (struct tcp_pcb *pcb)
{
DEBUG("%s\n", __func__);
(void)pcb;
}
void tcp_tmr(void)
{
DEBUG("%s\n", __func__);
}
void igmp_init(void)
{
DEBUG("%s\n", __func__);
}
err_t igmp_start(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
return ERR_OK;
}
err_t igmp_stop(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
return ERR_OK;
}
void igmp_report_groups(struct netif *netif)
{
DEBUG("%s\n", __func__);
(void)netif;
}
void igmp_tmr(void)
{
DEBUG("%s\n", __func__);
}
void dns_init(void)
{
DEBUG("%s\n", __func__);
}
void dns_tmr(void)
{
DEBUG("%s\n", __func__);
}
uint32_t espconn_init(uint32 arg)
{
DEBUG("%s\n", __func__);
(void)arg;
return 1;
}
extern struct netif * eagle_lwip_getif(uint8_t index);
void esp_lwip_init(void)
{
netif_set_default((struct netif *)eagle_lwip_getif(0));
}
#endif /* MODULE_ESP_SDK */

View File

@ -1,202 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 SDK libmain function
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef MODULE_ESP_SDK
#include <stdio.h>
#include "c_types.h"
#include "common.h"
#include "cpu_conf.h"
#include "irq.h"
#include "irq_arch.h"
#include "log.h"
#include "esp/rtcmem_regs.h"
#include "spi_flash.h"
#include "sdk/ets.h"
#include "sdk/main.h"
#include "sdk/rom.h"
static char _printf_buf[PRINTF_BUFSIZ];
int IRAM os_printf_plus (const char* format, ...)
{
va_list arglist;
va_start(arglist, format);
int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, format, arglist);
if (ret > 0) {
ets_printf (_printf_buf);
}
va_end(arglist);
return ret;
}
SpiFlashOpResult IRAM spi_flash_read (uint32_t faddr, uint32_t *dst, size_t size)
{
/*
* For simplicity, we use the ROM function. Since we need to disable the
* IROM cache function for that purpose, we have to be IRAM.
* Please note, faddr, src and size have to be aligned to 4 byte.
*/
SpiFlashOpResult ret;
CHECK_PARAM_RET (dst != NULL, SPI_FLASH_RESULT_ERR);
CHECK_PARAM_RET (faddr + size <= flashchip->chip_size, SPI_FLASH_RESULT_ERR);
critical_enter ();
Cache_Read_Disable ();
ret = SPIRead (faddr, dst, size);
Cache_Read_Enable(0, 0, 1);
critical_exit ();
return ret;
}
SpiFlashOpResult IRAM spi_flash_write (uint32_t faddr, uint32_t *src, size_t size)
{
/*
* For simplicity, we use the ROM function. Since we need to disable the
* IROM cache function for that purpose, we have to be in IRAM.
* Please note, faddr, src and size have to be aligned to 4 byte
*/
SpiFlashOpResult ret;
CHECK_PARAM_RET (src != NULL, SPI_FLASH_RESULT_ERR);
CHECK_PARAM_RET (faddr + size <= flashchip->chip_size, SPI_FLASH_RESULT_ERR);
critical_enter ();
Cache_Read_Disable ();
ret = SPIWrite (faddr, src, size);
Cache_Read_Enable(0, 0, 1);
critical_exit ();
return ret;
}
SpiFlashOpResult IRAM spi_flash_erase_sector(uint16_t sec)
{
CHECK_PARAM_RET (sec < flashchip->chip_size / flashchip->sector_size, SPI_FLASH_RESULT_ERR);
critical_enter ();
Cache_Read_Disable();
SpiFlashOpResult ret = SPIEraseSector (sec);
Cache_Read_Enable(0, 0, 1);
critical_exit ();
return ret;
}
void system_deep_sleep(uint32_t time_in_us)
{
/* TODO implement */
(void)time_in_us;
NOT_YET_IMPLEMENTED();
}
void system_restart(void)
{
/* TODO it's just a hard reset at the moment */
__asm__ volatile (" call0 0x40000080 ");
}
extern bool system_update_cpu_freq(uint8 freq)
{
if (freq == 160) {
DPORT.CPU_CLOCK |= DPORT_CPU_CLOCK_X2;
ets_update_cpu_frequency(160);
}
else {
DPORT.CPU_CLOCK &= ~DPORT_CPU_CLOCK_X2;
ets_update_cpu_frequency(80);
}
return true;
}
/**
* Following code is completly or at least partially from
* https://github.com/pvvx/esp8266web
* (c) PV` 2015
*
* @{
*/
uint8_t ICACHE_FLASH_ATTR system_get_checksum(uint8_t *ptr, uint32_t len)
{
uint8_t checksum = 0xEF;
while (len--) {
checksum ^= *ptr++;
}
return checksum;
}
#define RTCMEM_SIZE 0x300 /* user RTC RAM 768 bytes, 192 dword registers */
static bool IRAM _system_rtc_mem_access (uint32_t src, void *dst, uint32_t size, bool write)
{
/* src hast to be smaller than 192 */
CHECK_PARAM_RET (src <= (RTCMEM_SIZE >> 2), false);
/* src times 4 plus size must less than RTCMEM_SIZE */
CHECK_PARAM_RET (((src << 2) + size) < RTCMEM_SIZE, false);
/* des_addr has to be a multiple of 4 */
CHECK_PARAM_RET (((uint32_t)dst & 0x3) == 0, false);
/* align size to next higher multiple of 4 */
if (size & 0x3) {
size = (size + 4) & ~0x3;
}
for (uint32_t i = 0; i < (size >> 2); i++) {
if (write) {
RTCMEM_SYSTEM[src + i] = ((uint32_t*)dst)[i];
}
else {
((uint32_t*)dst)[i] = RTCMEM_SYSTEM[src + i];
}
}
return true;
}
bool IRAM system_rtc_mem_read (uint32_t src_addr, void *des_addr, uint32_t save_size)
{
return _system_rtc_mem_access (src_addr, des_addr, save_size, false);
}
bool IRAM system_rtc_mem_write (uint32_t src_addr, void *des_addr, uint32_t save_size)
{
return _system_rtc_mem_access (src_addr, des_addr, save_size, true);
}
/** @} */
#endif /* MODULE_ESP_SDK */

View File

@ -1,65 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 SDK libmain function prototypes
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef MAIN_H
#define MAIN_H
#ifndef DOXYGEN
#include <stdint.h>
#include <stdarg.h>
#include "c_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MODULE_ESP_SDK
#include "esp/dport_regs.h"
/*
* The following functions are mappings or dummies for source code
* compatibility of SDK and NON-SDK version
*/
#define system_get_time phy_get_mactime
#define system_get_chip_id() (((DPORT.OTP_MAC1 & 0xffff) << 8) + ((DPORT.OTP_MAC0 >> 24) & 0xff))
#define system_get_cpu_freq ets_get_cpu_frequency
extern int os_printf_plus (const char* format, ...);
extern void system_deep_sleep (uint32_t time_in_us);
extern uint8_t system_get_checksum(uint8_t *ptr, uint32_t len);
extern void system_restart (void);
extern bool system_update_cpu_freq(uint8 freq);
extern bool system_rtc_mem_read(uint32_t src_addr, void *des_addr, uint32_t save_size);
extern bool system_rtc_mem_write(uint32_t src_addr, void *des_addr, uint32_t save_size);
#endif /* MODULE_ESP_SDK */
extern void NmiTimSetFunc(void (*func)(void));
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* MAIN_H */

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 SDK libphy functions
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef MODULE_ESP_SDK
#include "sdk/phy.h"
#endif /* MODULE_ESP_SDK */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -25,29 +25,10 @@
#include <stdint.h>
#include <stdarg.h>
#include "c_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MODULE_ESP_SDK
/*
* The following functions are mappings or dummies for source code
* compatibility of SDK and NON-SDK version
*/
#include "esp/dport_regs.h"
extern void phy_afterwake_set_rfoption(int op);
extern int phy_check_data_table(void * gdctbl, int x, int flg);
extern int register_chipv6_phy(uint8_t * esp_init_data);
extern void sleep_reset_analog_rtcreg_8266(void);
extern uint32_t test_tout(bool);
extern void write_data_to_rtc(uint8_t *);
#endif /* MODULE_ESP_SDK */
extern uint32_t phy_get_mactime(void);
#ifdef __cplusplus

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 other ROM functions
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef MODULE_ESP_SDK
#include "sdk/pp.h"
#endif /* MODULE_ESP_SDK */

View File

@ -1,46 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 SDK libpp function prototypes
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef PP_H
#define PP_H
#ifndef DOXYGEN
#ifdef __cplusplus
extern "C" {
#endif
#include "c_types.h"
#ifndef MODULE_ESP_SDK
/*
* The following functions are mappings or dummies for source code
* compatibility of SDK and NON-SDK version
*/
#define system_soft_wdt_feed()
#endif /* MODULE_ESP_SDK */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* PP_H */

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 other ROM functions
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef MODULE_ESP_SDK
#include "sdk/rom.h"
#endif /* MODULE_ESP_SDK */

View File

@ -1,95 +0,0 @@
/*
* Copyright (C) 2018 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 other ROM function prototypes
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef ROM_H
#define ROM_H
#ifndef DOXYGEN
#include <stdint.h>
#include <stdarg.h>
#include "c_types.h"
#include "spi_flash.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MODULE_ESP_SDK
/*
* The following functions are mappings or dummies for source code
* compatibility of SDK and NON-SDK version
*/
extern uint8_t rom_i2c_readReg(uint32_t block, uint32_t host_id, uint32_t reg_add);
extern uint8_t rom_i2c_readReg_Mask(uint32_t block, uint32_t host_id,
uint32_t reg_add,uint32_t Msb, uint32_t Lsb);
extern void rom_i2c_writeReg (uint32_t block, uint32_t host_id,
uint32_t reg_add, uint32_t data);
extern void rom_i2c_writeReg_Mask(uint32_t block, uint32_t host_id,
uint32_t reg_add, uint32_t Msb, uint32_t Lsb,
uint32_t indata);
extern uint32_t rtc_get_reset_reason(void);
#endif /* MODULE_ESP_SDK */
/* pointer to flash chip data structure */
extern SpiFlashChip* flashchip;
extern SpiFlashOpResult spi_flash_attach(void);
void Cache_Read_Disable(void);
void Cache_Read_Enable (uint32_t odd_even, uint32_t mb_count, uint32_t no_idea);
SpiFlashOpResult Wait_SPI_Idle(SpiFlashChip *chip);
SpiFlashOpResult SPI_write_enable(SpiFlashChip *chip);
SpiFlashOpResult SPIEraseArea (uint32_t off, size_t len);
SpiFlashOpResult SPIEraseBlock (uint32_t num);
SpiFlashOpResult SPIEraseSector(uint32_t num);
SpiFlashOpResult SPIEraseChip (void);
SpiFlashOpResult SPILock (void);
SpiFlashOpResult SPIUnlock(void);
SpiFlashOpResult SPIRead (uint32_t off, uint32_t *dst, size_t size);
SpiFlashOpResult SPIWrite (uint32_t off, const uint32_t *src, size_t size);
int SPIReadModeCnfig (uint32_t);
/* set elements of flashchip, see struct SpiFlashChip; */
SpiFlashOpResult SPIParamCfg (uint32_t deviceId,
uint32_t chip_size,
uint32_t block_size,
uint32_t sector_size,
uint32_t page_size,
uint32_t status_mask);
extern void uartAttach (void);
extern void uart_div_modify(uint8 uart_no, uint32_t DivLatchValue);
extern void Uart_Init (uint8 uart_no);
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* ROM_H */

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Gunar Schorcht
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
@ -20,25 +20,16 @@
#ifndef SDK_H
#define SDK_H
#include "c_types.h"
#include "ets_sys.h"
#include <stdint.h>
#include "sdk/ets.h"
#include "sdk/main.h"
#include "sdk/phy.h"
#include "sdk/pp.h"
#include "sdk/rom.h"
#include "sdk/user.h"
#include "sdk/system.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef MODULE_ESP_SDK
#include "espressif/osapi.h"
#include "espressif/user_interface.h"
#endif /* MODULE_ESP_SDK */
#ifdef __cplusplus
}
#endif

56
cpu/esp8266/sdk/system.c Normal file
View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 user defined SDK functions
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#include "sdk/sdk.h"
#include "esp/dport_regs.h"
#include "esp_sleep.h"
#include "esp_system.h"
uint32_t system_get_chip_id(void)
{
/* Chip ID as determined by NONOS SDK */
return (((DPORT.OTP_MAC1 << 8) & 0xffffff00) + ((DPORT.OTP_MAC0 >> 24) & 0xff));
}
const char* system_get_sdk_version(void)
{
return esp_get_idf_version();
}
void system_deep_sleep(uint32_t time_in_us)
{
/* TODO test */
esp_deep_sleep(time_in_us);
}
void system_restart(void)
{
esp_restart();
}
void system_update_cpu_freq(uint8_t freq)
{
if (freq == 160) {
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_160M);
}
else {
rtc_clk_cpu_freq_set(RTC_CPU_FREQ_80M);
}
}

60
cpu/esp8266/sdk/system.h Normal file
View File

@ -0,0 +1,60 @@
/*
* Copyright (C) 2019 Gunar Schorcht
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_esp8266_sdk
* @{
*
* @file
* @brief ESP8266 user defined SDK function prototypes
*
* @author Gunar Schorcht <gunar@schorcht.net>
* @}
*/
#ifndef SYSTEM_H
#define SYSTEM_H
#ifndef DOXYGEN
#include <stdint.h>
#include <stdarg.h>
#include "esp_task_wdt.h"
#include "sdk/ets.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Functions for NONOS SDK compatibility
*
* @{
*/
extern uint8_t system_get_cpu_freq(void);
extern void system_update_cpu_freq(uint8_t);
extern uint32_t system_get_chip_id(void);
extern const char* system_get_sdk_version(void);
extern void system_deep_sleep(uint32_t time_in_us);
extern void system_restart(void);
#define system_wdt_init esp_task_wdt_init
#define system_wdt_feed esp_task_wdt_reset
#define system_wdt_start pp_soft_wdt_stop
#define system_wdt_stop pp_soft_wdt_restart
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* DOXYGEN */
#endif /* SYSTEM_H */

Some files were not shown because too many files have changed in this diff Show More