Merge pull request #53 from SuperHouse/uart_h

Fix issue #52.  Add esp/uart.h
This commit is contained in:
Alex Stewart 2015-10-10 22:04:53 -07:00
commit 8bcec7eea1
24 changed files with 251 additions and 89 deletions

View file

@ -16,8 +16,8 @@
#include "common_macros.h"
#include "xtensa_ops.h"
#include "esp/rom.h"
#include "esp/uart.h"
#include "esp/iomux_regs.h"
#include "esp/uart_regs.h"
#include "esp/spi_regs.h"
#include "esp/dport_regs.h"
#include "esp/wdev_regs.h"
@ -30,7 +30,6 @@
void user_init(void);
#define UART_DIVISOR 1068 // 74906 bps (yeah, I don't understand it either)
#define BOOT_INFO_SIZE 28
//TODO: phy_info should probably be a struct (no idea about its organization, though)
#define PHY_INFO_SIZE 128
@ -82,8 +81,6 @@ xTaskHandle sdk_xWatchDogTaskHandle;
static void IRAM get_otp_mac_address(uint8_t *buf);
static void IRAM set_spi0_divisor(uint32_t divisor);
static int IRAM default_putc(char c);
static void IRAM default_putc1(char c);
static void zero_bss(void);
static void init_networking(uint8_t *phy_info, uint8_t *mac_addr);
static void init_g_ic(void);
@ -160,27 +157,15 @@ void IRAM sdk_user_fatal_exception_handler(void) {
Cache_Read_Disable();
Cache_Read_Enable(0, 0, 1);
dump_excinfo();
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(0).STATUS)) {}
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(1).STATUS)) {}
uart_flush_txfifo(0);
uart_flush_txfifo(1);
sdk_system_restart_in_nmi();
halt();
}
// .Lfunc003 -- .text+0x1d0
static int IRAM default_putc(char c) {
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(0).STATUS) > 125) {}
UART(0).FIFO = c;
return 0;
}
// .Lfunc004 -- .text+0x1f4
static void IRAM default_putc1(char c) {
if (c == '\n') {
default_putc('\r');
} else if (c == '\r') {
return;
}
default_putc(c);
static void IRAM default_putc(char c) {
uart_putc(0, c);
}
// .text+0x258
@ -247,7 +232,7 @@ void IRAM sdk_user_start(void) {
sdk_SPIRead(ic_flash_addr, buf32, sizeof(struct sdk_g_ic_saved_st));
Cache_Read_Enable(0, 0, 1);
zero_bss();
sdk_os_install_putc1(default_putc1);
sdk_os_install_putc1(default_putc);
if (cksum_magic == 0xffffffff) {
// No checksum required
} else if ((cksum_magic == 0x55aa55aa) &&
@ -293,8 +278,8 @@ static void init_networking(uint8_t *phy_info, uint8_t *mac_addr) {
printf("FATAL: sdk_register_chipv6_phy failed");
halt();
}
sdk_uart_div_modify(0, UART_DIVISOR);
sdk_uart_div_modify(1, UART_DIVISOR);
uart_set_baud(0, 74906);
uart_set_baud(1, 74906);
sdk_phy_disable_agc();
sdk_ieee80211_phy_init(sdk_g_ic.s.phy_mode);
sdk_lmacInit();
@ -378,15 +363,6 @@ static void dump_excinfo(void) {
sdk_system_rtc_mem_write(0, excinfo, 32);
}
// .irom0.text+0x368
int sdk_uart_rx_one_char(char *buf) {
if (FIELD2VAL(UART_STATUS_RXFIFO_COUNT, UART(0).STATUS)) {
*buf = UART(0).FIFO;
return 0;
}
return 1;
}
// .irom0.text+0x398
void sdk_wdt_init(void) {
WDT.CTRL &= ~WDT_CTRL_ENABLE;
@ -455,9 +431,11 @@ static void user_start_phase2(void) {
phy_info = malloc(PHY_INFO_SIZE);
sdk_spi_flash_read(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)phy_info, PHY_INFO_SIZE);
// Disable default buffering on stdout
setbuf(stdout, NULL);
// Wait for UARTs to finish sending anything in their queues.
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(0).STATUS) > 0) {}
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(1).STATUS) > 0) {}
uart_flush_txfifo(0);
uart_flush_txfifo(1);
if (phy_info[0] != 5) {
// Bad version byte. Discard what we read and use default values

127
core/include/esp/uart.h Normal file
View file

@ -0,0 +1,127 @@
/** esp/uart.h
*
* Utility routines for working with UARTs
*
* Part of esp-open-rtos
* Copyright (C) 2015 Superhouse Automation Pty Ltd
* BSD Licensed as described in the file LICENSE
*/
#ifndef _ESP_UART_H
#define _ESP_UART_H
#include "esp/types.h"
#include "esp/uart_regs.h"
#include "esp/clocks.h"
#define UART_FIFO_MAX 127
/* Wait for at least `min_count` bytes of data to be available in the UART's
* receive FIFO
*
* Returns the number of bytes actually available for reading.
*/
static inline int uart_rxfifo_wait(int uart_num, int min_count) {
int count;
do {
count = FIELD2VAL(UART_STATUS_RXFIFO_COUNT, UART(uart_num).STATUS);
} while (count < min_count);
return count;
}
/* Wait for at least `min_count` bytes of space to be available in the UART's
* transmit FIFO
*
* Returns the number of bytes actually available in the write buffer.
*/
static inline int uart_txfifo_wait(int uart_num, int min_count) {
int count;
do {
count = UART_FIFO_MAX - FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(uart_num).STATUS);
} while (count < min_count);
return count;
}
/* Read a character from the UART. Block until a character is available for
* reading.
*
* Returns the character read.
*/
static inline int uart_getc(int uart_num) {
uart_rxfifo_wait(uart_num, 1);
return UART(uart_num).FIFO;
}
/* Read a character from the UART. Does not block.
*
* Returns the read character on success. If the RX FIFO is currently empty
* (nothing to read), returns -1.
*/
static inline int uart_getc_nowait(int uart_num) {
if (FIELD2VAL(UART_STATUS_RXFIFO_COUNT, UART(uart_num).STATUS)) {
return UART(uart_num).FIFO;
}
return -1;
}
/* Write a character to the UART. Blocks if necessary until there is space in
* the TX FIFO.
*/
static inline void uart_putc(int uart_num, char c) {
uart_txfifo_wait(uart_num, 1);
UART(uart_num).FIFO = c;
}
/* Write a character to the UART. Does not block.
*
* Returns 0 on success. If there is no space currently in the TX FIFO,
* returns -1.
*/
static inline int uart_putc_nowait(int uart_num, char c) {
if (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(uart_num).STATUS) < UART_FIFO_MAX) {
UART(uart_num).FIFO = c;
return 0;
}
return -1;
}
/* Clear (discard) all pending write data in the TX FIFO */
static inline void uart_clear_txfifo(int uart_num) {
uint32_t conf = UART(uart_num).CONF0;
UART(uart_num).CONF0 = conf | UART_CONF0_TXFIFO_RESET;
UART(uart_num).CONF0 = conf & ~UART_CONF0_TXFIFO_RESET;
}
/* Clear (discard) all pending read data in the RX FIFO */
static inline void uart_clear_rxfifo(int uart_num) {
uint32_t conf = UART(uart_num).CONF0;
UART(uart_num).CONF0 = conf | UART_CONF0_RXFIFO_RESET;
UART(uart_num).CONF0 = conf & ~UART_CONF0_RXFIFO_RESET;
}
/* Wait until all pending output in the UART's TX FIFO has been sent out the
* serial port. */
static inline void uart_flush_txfifo(int uart_num) {
while (FIELD2VAL(UART_STATUS_TXFIFO_COUNT, UART(uart_num).STATUS) != 0) {}
}
/* Flush all pending input in the UART's RX FIFO
* (this is just another name for uart_clear_rxfifo)
*/
static inline void uart_flush_rxfifo(int uart_num) {
uart_clear_rxfifo(uart_num);
}
/* Set uart baud rate to the desired value */
static inline void uart_set_baud(int uart_num, int bps)
{
uint32_t divider = APB_CLK_FREQ / bps;
UART(uart_num).CLOCK_DIVIDER = divider;
}
/* Returns the current baud rate for the UART */
static inline int uart_get_baud(int uart_num)
{
return APB_CLK_FREQ / FIELD2VAL(UART_CLOCK_DIVIDER_VALUE, UART(uart_num).CLOCK_DIVIDER);
}
#endif /* _ESP_UART_H */

View file

@ -9,6 +9,7 @@
#include <sys/errno.h>
#include <espressif/sdk_private.h>
#include <common_macros.h>
#include <esp/uart.h>
#include <stdlib.h>
IRAM caddr_t _sbrk_r (struct _reent *r, int incr)
@ -32,37 +33,40 @@ IRAM caddr_t _sbrk_r (struct _reent *r, int incr)
return (caddr_t) prev_heap_end;
}
/* syscall implementation for stdio write to UART
at the moment UART functionality is all still in the binary SDK
*/
/* syscall implementation for stdio write to UART */
long _write_r(struct _reent *r, int fd, const char *ptr, int len )
{
if(fd != r->_stdout->_file) {
r->_errno = EBADF;
return -1;
}
for(int i = 0; i < len; i++)
sdk_os_putc(ptr[i]);
for(int i = 0; i < len; i++) {
/* Auto convert CR to CRLF, ignore other LFs (compatible with Espressif SDK behaviour) */
if(ptr[i] == '\r')
continue;
if(ptr[i] == '\n')
uart_putc(0, '\r');
uart_putc(0, ptr[i]);
}
return len;
}
/* syscall implementation for stdio read from UART
at the moment UART functionality is all still in the binary SDK
*/
/* syscall implementation for stdio read from UART */
long _read_r( struct _reent *r, int fd, char *ptr, int len )
{
int ch, i;
if(fd != r->_stdin->_file) {
r->_errno = EBADF;
return -1;
}
for(int i = 0; i < len; i++) {
char ch;
while (sdk_uart_rx_one_char(&ch)) ;
uart_rxfifo_wait(0, 1);
for(i = 0; i < len; i++) {
ch = uart_getc_nowait(0);
if (ch < 0) break;
ptr[i] = ch;
}
return len;
return i;
}
/* Stub syscall implementations follow, to allow compiling newlib functions that

View file

@ -1,5 +1,5 @@
/*
* Wrappers for functions called by binary espressif libraries
* Compatibility routines for the Espressif SDK and its API
*
* Part of esp-open-rtos
* Copyright (C) 2015 Superhouse Automation Pty Ltd
@ -10,6 +10,8 @@
#include <stdio.h>
#include <common_macros.h>
#include <esp/uart.h>
void IRAM *zalloc(size_t nbytes)
{
return calloc(1, nbytes);
@ -18,9 +20,8 @@ void IRAM *zalloc(size_t nbytes)
extern void (*__init_array_start)(void);
extern void (*__init_array_end)(void);
/* Do things which should be done as part of the startup code, but aren't.
Can be replaced with _start() once we have open source startup code.
/* Do things which should be done as part of the SDK startup code, but aren't.
TODO: Move into app_main.c
*/
void sdk_compat_initialise()
{
@ -29,3 +30,15 @@ void sdk_compat_initialise()
for ( p = &__init_array_start; p != &__init_array_end; ++p)
(*p)();
}
/* UART RX function from Espressif SDK internals.
*
* Not part of published API.
*/
int sdk_uart_rx_one_char(char *buf) {
int c = uart_getc_nowait(0);
if(c < 0)
return 1;
*buf = (char)c;
return 0;
}

View file

@ -3,7 +3,7 @@
* This sample code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp8266.h"
@ -53,7 +53,7 @@ void blinkenRegisterTask(void *pvParameters)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
xTaskCreate(blinkenTask, (signed char *)"blinkenTask", 256, NULL, 2, NULL);
//xTaskCreate(blinkenRegisterTask, (signed char *)"blinkenRegisterTask", 256, NULL, 2, NULL);
}

View file

@ -3,7 +3,7 @@
* This sample code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp8266.h"
@ -33,7 +33,7 @@ void frc2_interrupt_handler(void)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
/* configure GPIOs */
gpio_enable(gpio_frc1, GPIO_OUTPUT);

View file

@ -3,7 +3,7 @@
* This sample code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
@ -87,7 +87,7 @@ void bmp180_task(void *pvParameters)
void user_setup(void)
{
// Set UART Parameter
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
// Give the UART some time to settle
sdk_os_delay_us(500);

View file

@ -6,7 +6,7 @@
* This sample code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
@ -75,7 +75,7 @@ void GPIO_HANDLER(void)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
gpio_enable(gpio, GPIO_INPUT);
tsqueue = xQueueCreate(2, sizeof(uint32_t));

View file

@ -31,6 +31,8 @@
#include "espressif/esp_common.h"
#include "esp/uart.h"
/******************************************************************************************************************
* task_1_t
*
@ -94,8 +96,8 @@ esp_open_rtos::thread::queue_t<uint32_t> MyQueue;
*/
extern "C" void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
MyQueue.queue_create(10);
task_1.queue = MyQueue;

View file

@ -7,7 +7,7 @@
* This experimental reverse engineering code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp8266.h"
@ -118,7 +118,7 @@ void frc2_handler(void)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
xTaskCreate(timerRegTask, (signed char *)"timerRegTask", 1024, NULL, 2, NULL);
TIMER(0).CTRL = VAL2FIELD(TIMER_CTRL_CLKDIV, TIMER_CLKDIV_256) | TIMER_CTRL_RELOAD;

View file

@ -3,7 +3,7 @@
#include "esp/rom.h"
#include "esp/timer.h"
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
@ -214,7 +214,7 @@ void sanity_tests(void);
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
gpio_enable(2, GPIO_OUTPUT); /* used for LED debug */
gpio_write(2, 1); /* active low */

View file

@ -5,7 +5,7 @@
* This sample code is in the public domain.,
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include <string.h>
@ -114,7 +114,7 @@ void http_get_task(void *pvParameters)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
struct sdk_station_config config = {

View file

@ -10,7 +10,7 @@
* Additions Copyright (C) 2015 Angus Gratton, Apache 2.0 License.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include <string.h>
@ -80,7 +80,6 @@ static void my_debug(void *ctx, int level,
file = file_sep+1;
printf("%s:%04d: %s", file, line, str);
fflush(stdout);
}
#endif
@ -107,7 +106,6 @@ void http_get_task(void *pvParameters)
mbedtls_x509_crt_init(&cacert);
mbedtls_ctr_drbg_init(&ctr_drbg);
printf("\n . Seeding the random number generator...");
fflush(stdout);
mbedtls_ssl_config_init(&conf);
@ -126,7 +124,6 @@ void http_get_task(void *pvParameters)
* 0. Initialize certificates
*/
printf(" . Loading the CA root certificate ...");
fflush(stdout);
ret = mbedtls_x509_crt_parse(&cacert, (uint8_t*)server_root_cert, strlen(server_root_cert)+1);
if(ret < 0)
@ -148,7 +145,6 @@ void http_get_task(void *pvParameters)
* 2. Setup stuff
*/
printf(" . Setting up the SSL/TLS structure...");
fflush(stdout);
if((ret = mbedtls_ssl_config_defaults(&conf,
MBEDTLS_SSL_IS_CLIENT,
@ -182,7 +178,6 @@ void http_get_task(void *pvParameters)
our network is probably working...
*/
printf("Waiting for server DNS to resolve... ");
fflush(stdout);
err_t dns_err;
ip_addr_t host_ip;
do {
@ -198,7 +193,6 @@ void http_get_task(void *pvParameters)
* 1. Start the connection
*/
printf(" . Connecting to %s:%s...", WEB_SERVER, WEB_PORT);
fflush(stdout);
if((ret = mbedtls_net_connect(&server_fd, WEB_SERVER,
WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
@ -215,7 +209,6 @@ void http_get_task(void *pvParameters)
* 4. Handshake
*/
printf(" . Performing the SSL/TLS handshake...");
fflush(stdout);
while((ret = mbedtls_ssl_handshake(&ssl)) != 0)
{
@ -251,7 +244,6 @@ void http_get_task(void *pvParameters)
* 3. Write the GET request
*/
printf(" > Write to server:");
fflush(stdout);
int len = sprintf((char *) buf, GET_REQUEST);
@ -271,7 +263,6 @@ void http_get_task(void *pvParameters)
* 7. Read the HTTP response
*/
printf(" < Read from server:");
fflush(stdout);
do
{
@ -322,7 +313,6 @@ void http_get_task(void *pvParameters)
printf("\n\nsuccesses = %d failures = %d\n", successes, failures);
for(int countdown = successes ? 10 : 5; countdown >= 0; countdown--) {
printf("%d... ", countdown);
fflush(stdout);
vTaskDelay(1000 / portTICK_RATE_MS);
}
printf("\nStarting again!\n");
@ -331,7 +321,7 @@ void http_get_task(void *pvParameters)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
struct sdk_station_config config = {

View file

@ -7,7 +7,7 @@
* NOT SUITABLE TO PUT ON THE INTERNET OR INTO A PRODUCTION ENVIRONMENT!!!!
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "esp8266.h"
@ -18,7 +18,7 @@
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
rboot_config_t conf = rboot_get_config();
printf("\r\n\r\nOTA Basic demo.\r\nCurrently running on flash slot %d / %d.\r\n\r\n",

View file

@ -0,0 +1,3 @@
# Simple makefile for serial_echo example
PROGRAM=serial_echo
include ../../common.mk

View file

@ -0,0 +1,42 @@
/* Extremely simple example that just reads from stdin and echoes back on stdout
*
* Has an easter egg, which is if you type "QUACK" it'll quack 3 times back at you.
*
* This example code is in the public domain
*/
#include "espressif/esp_common.h"
#include <esp/uart.h>
#include <string.h>
void user_init(void)
{
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
printf("Going into echo mode...\n");
/* By default stdout is line-buffered, so you only see output
after a newline is sent. This is helpful in a multithreaded
environment so output doesn't get chopped up within a line.
Here we want to see the echo immediately, so disable buffering.
*/
setbuf(stdout, NULL);
while(1) {
int c = getchar();
if(c != EOF)
putchar(c);
/* Easter egg: check for a quack! */
static int quack;
if(c == "QUACK"[quack]) {
quack++;
if(quack == strlen("QUACK")) {
printf("\nQUACK\nQUACK\n");
quack = 0;
}
} else {
quack = 0;
}
}
}

View file

@ -1,7 +1,7 @@
/* Very basic example that just demonstrates we can run at all!
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
@ -36,7 +36,7 @@ static xQueueHandle mainqueue;
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
mainqueue = xQueueCreate(10, sizeof(uint32_t));
xTaskCreate(task1, (signed char *)"tsk1", 256, &mainqueue, 2, NULL);

View file

@ -3,11 +3,12 @@
This sample code is in the public domain.
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include <esp/uart.h>
class Counter
{
private:
@ -58,7 +59,7 @@ void task1(void *pvParameters)
extern "C" void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
printf("SDK version:%s\n", sdk_system_get_sdk_version());
xTaskCreate(task1, (signed char *)"tsk1", 256, NULL, 2, NULL);
}

View file

@ -8,7 +8,7 @@
* This sample code is in the public domain.,
*/
#include "espressif/esp_common.h"
#include "espressif/sdk_private.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "mbedtls/md.h"
@ -130,7 +130,7 @@ static void test_md5(void)
void user_init(void)
{
sdk_uart_div_modify(0, UART_CLK_FREQ / 115200);
uart_set_baud(0, 115200);
test_md5();

View file

@ -31,7 +31,7 @@
/* Optional reentrant struct support. Used mostly on platforms with
very restricted storage. */
/* #undef _WANT_REENT_SMALL */
#define _WANT_REENT_SMALL 1
/* Multibyte supported */
/* #undef _MB_CAPABLE */

View file

@ -188,6 +188,8 @@
#ifdef __XTENSA__
#include <xtensa/config/core-isa.h>
#define MALLOC_ALIGNMENT ((XCHAL_DATA_WIDTH) < 16 ? 16 : (XCHAL_DATA_WIDTH))
/* esp8266-specific: shrink the default fd buffer size */
#define __BUFSIZ__ 128
#endif
/* This block should be kept in sync with GCC's limits.h. The point

Binary file not shown.

Binary file not shown.

Binary file not shown.