Merge branch 'master' into lwip220d1

This commit is contained in:
Our Air Quality 2019-04-12 12:34:20 +10:00
commit 3f72d59b75
55 changed files with 1787 additions and 737 deletions

View file

@ -19,7 +19,7 @@
typedef void (*handle_http_token)(char *);
struct http_token_table {
char * token;
const char * token;
handle_http_token http_tock_cb;
};

View file

@ -15,9 +15,9 @@ typedef enum {
} HTTP_Client_State;
typedef struct {
char * server;
char * port;
char * path;
const char * server;
const char * port;
const char * path;
char * buffer;
uint16_t buffer_size;
http_final_cb buffer_full_cb;

View file

@ -38,10 +38,10 @@ typedef enum {
* Struct that contains all info for start ota.
*/
typedef struct {
char *server; /**< Server domain */
char *port; /**< Server port */
char *binary_path; /**< Server Path dowload new update binary */
char *sha256_path; /**< Server Path of SHA256 sum for check binary, could be NULL, check will be skipped */
const char *server; /**< Server domain */
const char *port; /**< Server port */
const char *binary_path; /**< Server Path dowload new update binary */
const char *sha256_path; /**< Server Path of SHA256 sum for check binary, could be NULL, check will be skipped */
} ota_info;
/**

View file

@ -0,0 +1,10 @@
# Component makefile for extras/mactimer
# Expected anyone using mactimer includes it as 'mactimer/mactimer.h'
INC_DIRS += $(mactimer_ROOT)..
# args for passing into compile rule generation
mactimer_INC_DIR =
mactimer_SRC_DIR = $(mactimer_ROOT)
$(eval $(call component_compile_rules,mactimer))

205
extras/mactimer/mactimer.c Normal file
View file

@ -0,0 +1,205 @@
/*
* MAC NMI interrupt based timer support.
*
* Copyright (C) 2018 to 2019 OurAirQuality.org
*
* Licensed under the Apache License, Version 2.0, January 2004 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <FreeRTOS.h>
#include "esp/dport_regs.h"
#include "mactimer/mactimer.h"
/* The MAC timer handler offers a higher priority timer interrupt, but comes
* with some significant practical limitations.
*/
static mactimer_t* timer_list = 0;
void mactimer_setfn(mactimer_t *timer, mactimer_func_t *func, void *parg)
{
timer->callback = func;
timer->timer_arg = parg;
timer->trigger_usec = 0;
timer->next = NULL;
}
/* Return the Mac timer count, a 64 bit value.
* This can be called without the NMI interrupt disabled. */
uint64_t IRAM mactime_get_count(void) {
uint32_t high1 = *(uint32_t volatile *)0x3FF21008;
uint32_t low = *(uint32_t volatile *)0x3FF21004;
uint32_t high2 = *(uint32_t volatile *)0x3FF21008;
if (high1 != high2) {
/* The high word just clocked over, so resample the low value to
* match. It will not change for some time now so the new low word
* matches high2. */
low = *(uint32_t volatile *)0x3FF21004;
}
return ((uint64_t)high2 << 32UL) | (uint32_t)low;
}
/* Set the Mac timer to trigger at the given absolute count. This is expected
* to be called with the NMI disabled, such as from a handler. */
static inline void IRAM mactime_set_trigger(uint64_t count) {
*(uint32_t volatile *)0x3FF2109C = (uint32_t)count;
*(uint32_t volatile *)0x3FF210A0 = (uint32_t)(count >> 32UL);
*(uint32_t volatile *)0x3FF21098 |= 0x80000000;
}
/* Insert the timer into the queue to trigger at the given absolute
* count. This does not actually set the timer trigger, and the caller is
* expected to do so. This is typically called from a handler to set the next
* trigger time, and the MAC timer handler sets the next trigger count if
* necessary before returning. */
void IRAM mactime_add_pending(mactimer_t *timer, uint64_t count)
{
mactimer_t *prev = NULL;
mactimer_t *curr = timer_list;
while (curr) {
if (((int64_t)count - (int64_t)curr->trigger_usec) < 1) {
break;
}
prev = curr;
curr = curr->next;
}
timer->next = curr;
timer->trigger_usec = count;
if (prev != NULL) {
prev->next = timer;
} else {
timer_list = timer;
}
}
/* This is called outside the NMI context, with the NMI enabled, and it
* disables the NMI to synchronize access to the data structures. If a MAC
* timer handler wishes to set another timeout, such as for a periodic timer,
* then it need only call mactime_add_pending() before returning.
*/
void mactimer_arm(mactimer_t *timer, uint64_t count)
{
/* Guard against being called withing the NMI handler. */
if (sdk_NMIIrqIsOn == 0) {
/* Disable the maskable interrupts. */
vPortEnterCritical();
/* Disable the NMI. */
do {
DPORT.DPORT0 &= 0xFFFFFFE0;
} while (DPORT.DPORT0 & 1);
}
mactime_add_pending(timer, mactime_get_count() + count);
mactime_set_trigger(timer_list->trigger_usec);
if (sdk_NMIIrqIsOn == 0) {
/* Reenable the NMI. */
DPORT.DPORT0 = (DPORT.DPORT0 & 0xFFFFFFE0) | 1;
/* Enable the maskable interrupts. */
vPortExitCritical();
}
}
/* This is called outside the NMI context, with the NMI enabled, and it
* disables the NMI to synchronize access to the data structures.
*/
void mactimer_disarm(mactimer_t *timer)
{
/* Guard against being called withing the NMI handler. */
if (sdk_NMIIrqIsOn == 0) {
/* Disable the maskable interrupts. */
vPortEnterCritical();
/* Disable the NMI. */
do {
DPORT.DPORT0 &= 0xFFFFFFE0;
} while (DPORT.DPORT0 & 1);
}
/* Remove timer from the timer_list. */
mactimer_t *timers = timer_list;
if (timers == timer) {
timer_list = timers->next;
} else {
while (timers) {
mactimer_t *next = timers->next;
if (next == timer) {
timers->next = next->next;
break;
}
timers = next;
}
}
if (sdk_NMIIrqIsOn == 0) {
/* Reenable the NMI. */
DPORT.DPORT0 = (DPORT.DPORT0 & 0xFFFFFFE0) | 1;
/* Enable the maskable interrupts. */
vPortExitCritical();
}
}
/*
* NMI handler. The callbacks are called in this NMI context. If there are
* pending timers remaining when done then a new timeout is set.
*
* This is a fragile context that can be called even when processor interrupts
* are masked, so it can not touch data synchronized by disabling maskable
* interrupts. So don't expect to be able call into the FreeRTOS functions or
* the C library etc.
*
* It can be called with a flash operation in progress, so that the flash is
* not readable, so handlers can not depend on code or data stored in
* flash. Keep handlers in IRAM, and watch our for constant data that might be
* linked into flash.
*
* It might delay handling of MAC interrupts which could compromise the Wifi
* handling, so keep any handlers as quick as possible.
*/
static IRAM void mactimer_handler()
{
while (timer_list) {
if (((int64_t)timer_list->trigger_usec - (int64_t)mactime_get_count()) > 0) {
/* Nothing remaining to handle now. */
break;
}
mactimer_t *timer = timer_list;
timer_list = timer->next;
timer->next = NULL;
timer->callback(timer->timer_arg);
}
if (timer_list) {
/* Reset the trigger. */
mactime_set_trigger(timer_list->trigger_usec);
}
}
extern void IRAM sdk_wDev_MacTimSetFunc(void * arg0);
void mactimer_init()
{
timer_list = NULL;
sdk_wDev_MacTimSetFunc(mactimer_handler);
}

View file

@ -0,0 +1,36 @@
/*
* MAC NMI interrupt based timer support.
*
* Copyright (C) 2018 to 2019 OurAirQuality.org
*
* Licensed under the Apache License, Version 2.0, January 2004 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
typedef void mactimer_func_t(void *);
typedef struct mactimer_st {
struct mactimer_st *next;
mactimer_func_t *callback;
uint64_t trigger_usec;
void *timer_arg;
} mactimer_t;
void mactimer_setfn(mactimer_t *timer, mactimer_func_t *func, void *parg);
uint64_t mactime_get_count(void);
void mactime_add_pending(mactimer_t *timer, uint64_t count);
void mactimer_arm(mactimer_t *timer, uint64_t count);
void mactimer_disarm(mactimer_t *timer);
void mactimer_init(void);

View file

@ -216,7 +216,7 @@ onewire_addr_t onewire_search_next(onewire_search_t *search, int pin) {
uint8_t id_bit_number;
uint8_t last_zero, search_result;
int rom_byte_number;
uint8_t id_bit, cmp_id_bit;
int8_t id_bit, cmp_id_bit;
onewire_addr_t addr;
unsigned char rom_byte_mask;
bool search_direction;

View file

@ -239,7 +239,7 @@ typedef struct __attribute__((packed)) {
bool rboot_verify_image(uint32_t initial_offset, uint32_t *image_length, const char **error_message)
{
uint32_t offset = initial_offset;
char *error = NULL;
const char *error = NULL;
RBOOT_DEBUG("rboot_verify_image: verifying image at 0x%08x\n", initial_offset);
if(offset % 4) {
error = "Unaligned flash offset";

View file

@ -690,7 +690,7 @@ sntp_request(void *arg)
void
sntp_init(void)
{
char *def_addr[] = {SNTP_SERVER_ADDRESS};
const char *def_addr[] = {SNTP_SERVER_ADDRESS};
sntp_num_servers = 0;
sntp_set_servers(def_addr, sizeof(def_addr) / sizeof(char*));
@ -715,7 +715,7 @@ sntp_init(void)
/**
* Set the NTP servers
*/
int sntp_set_servers(char *server_url[], int num_servers)
int sntp_set_servers(const char *server_url[], int num_servers)
{
int i;

View file

@ -52,7 +52,7 @@ void sntp_set_timezone(const struct timezone *tz);
* Returns 0 if OK, less than 0 if error.
* NOTE: This function must NOT be called before sntp_initialize().
*/
int sntp_set_servers(char *server_url[], int num_servers);
int sntp_set_servers(const char *server_url[], int num_servers);
/*
* Sets the update delay in ms. If requested value is less than 15s,

View file

@ -1007,7 +1007,7 @@ int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font
return d->width;
}
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, char *str,
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, const char *str,
ssd1306_color_t foreground, ssd1306_color_t background)
{
uint8_t t = x;

View file

@ -493,7 +493,7 @@ int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font
* @param background Background color
* @return Width of the string or negative value if error occured
*/
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, char *str, ssd1306_color_t foreground, ssd1306_color_t background);
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, const char *str, ssd1306_color_t foreground, ssd1306_color_t background);
/**
* Stop scrolling (the ram data needs to be rewritten)

View file

@ -362,7 +362,7 @@ bool tsl2561_read_lux(tsl2561_t *device, uint32_t *lux)
break;
}
uint32_t temp;
int32_t temp;
temp = ((channel0 * b) - (channel1 * m));
// Do not allow negative lux value

View file

@ -0,0 +1,10 @@
# Component makefile for extras/tsoftuart
# Expected anyone using tsoftuart includes it as 'tsoftuart/tsoftuart.h'
INC_DIRS += $(tsoftuart_ROOT)..
# args for passing into compile rule generation
tsoftuart_INC_DIR =
tsoftuart_SRC_DIR = $(tsoftuart_ROOT)
$(eval $(call component_compile_rules,tsoftuart))

View file

@ -0,0 +1,195 @@
/*
* Software timer based UART driver.
*
* Copyright (C) 2018 to 2019 OurAirQuality.org
*
* Licensed under the Apache License, Version 2.0, January 2004 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
#include <stdint.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <esp/uart.h>
#include <stdio.h>
#include <espressif/esp_system.h>
#include "FreeRTOS.h"
#include "task.h"
#include "tsoftuart/tsoftuart.h"
/*
* The design builds a sequence of UART output transitions - the delay between
* each toggling of the output. This sequence is then followed by a timer and
* the timer handler toggles the state and resets the timer for the next
* transition until done. This design avoids the code having to spin to
* implement delays, and avoid having to disable interrupts for more reliable
* timing.
*
* The MAC timer interrupt is used here as it has a high priority which helps
* keep accurate output transition times. The MAC timer interrupt is a NMI and
* the handler needs to take care not to interact widely. The handler only
* accesses the timer queue, which has already been initialized.
*
* This software UART is not completely reliable, but might suit debug output
* or communication that has an error detection layer, and it is more reliable
* at lower baud rates. While it can run up to 115200 baud it is not very
* reliable at these higher rates. It is not uncommon for the MAC timer
* handler to be delayed 20us, so at UART baud rates above 19200 errors are
* expected. This driver attempts to measure the timing errors and this can be
* used to help detect when timing errors have occurred.
*/
static void IRAM output_handler(void *arg)
{
tsoftuart_t *uart = arg;
uint32_t tail = uart->output_queue_tail;
do {
uint32_t state = uart->output_queue_state ^ 1;
uint64_t current = mactime_get_count();
gpio_write(uart->tx_pin, state);
uart->output_queue_state = state;
if (tail == 0) {
// First transition.
uart->output_start_time = current;
uart->output_expected_time = current;
}
/* The difference can be negative because the delay is skipped
* if very short, see below. */
int32_t err = current - uart->output_expected_time;
if (err > uart->output_queue_error_high) {
uart->output_queue_error_high = err;
}
if (err < uart->output_queue_error_low) {
uart->output_queue_error_low = err;
}
if (tail >= uart->output_queue_head) {
// Done.
uart->output_queue_tail = tail;
uart->output_done = 1;
return;
}
/* Offset from the start. */
uint32_t next = uart->output_queue[tail++];
uint64_t target = uart->output_start_time + next;
uart->output_expected_time = target;
/* Target an earlier time, that would not give an error if
* actually met, to give more room for the response delay. */
target -= 4;
int64_t diff = target - current;
if (diff >= 0) {
uart->output_queue_tail = tail;
mactime_add_pending(&uart->output_mactimer, target);
break;
}
} while(1);
}
void tsoftuart_putc(tsoftuart_t *uart, uint8_t ch)
{
uart->output_queue_state = 1;
gpio_write(uart->tx_pin, uart->output_queue_state);
uart->output_queue_head = 0;
uart->output_queue_tail = 0;
uart->output_queue_error_high = 0;
uart->output_queue_error_low = 0;
uart->output_done = 0;
uint32_t state = 0;
uint32_t count = 1;
size_t head = 0;
uint32_t cumulative = 0;
uint32_t td = uart->td;
for (size_t i = 0; i < 8; i++) {
if ((ch & 1) == state) {
/* No change */
count++;
} else {
cumulative += count * td;
uart->output_queue[head++] = (cumulative + 128) >> 8;
state ^= 1;
count = 1;
}
ch >>= 1;
}
if (state == 0) {
cumulative += count * td;
uart->output_queue[head++] = (cumulative + 128) >> 8;
state ^= 1;
count = 1;
}
uart->output_queue_head = head;
/* Trigger the first transition in the future. */
mactimer_arm(&uart->output_mactimer, 20);
/* Wait until the transmittions is expected to have completed. */
uint32_t delay = (td * 11 + 128) >> 8;
vTaskDelay(((delay / 1000) + portTICK_PERIOD_MS) / portTICK_PERIOD_MS);
/* Double check that it is done. There is a possibility that the timer has
* failed to trigger, and this needed to be detected and the timer removed
* from the pending list before retrying. */
size_t i;
for (i = 0; uart->output_done == 0 && i < 10; i++) {
vTaskDelay(1);
}
if (uart->output_done == 0) {
/* Remove the timer. */
mactimer_disarm(&uart->output_mactimer);
/* Set the output high */
gpio_write(uart->tx_pin, 1);
}
}
ssize_t tsoftuart_write(tsoftuart_t *uart, const void *ptr, size_t len)
{
for(int i = 0; i < len; i++) {
tsoftuart_putc(uart, ((char *)ptr)[i]);
}
return len;
}
tsoftuart_t *tsoftuart_init(uint8_t tx_pin, uint32_t baud_rate)
{
tsoftuart_t *uart = malloc(sizeof(tsoftuart_t));
if (uart) {
uart->tx_pin = tx_pin;
uart->td = 256000000 / baud_rate;
gpio_enable(tx_pin, GPIO_OUTPUT);
gpio_set_pullup(tx_pin, true, false);
gpio_write(tx_pin, 1);
mactimer_init();
mactimer_setfn(&uart->output_mactimer, output_handler, uart);
}
return uart;
}

View file

@ -0,0 +1,47 @@
/*
* Software timer based UART driver.
*
* Copyright (C) 2018 to 2019 OurAirQuality.org
*
* Licensed under the Apache License, Version 2.0, January 2004 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
* http://www.apache.org/licenses/
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
#ifndef _TSOFTUART_H
#define _TSOFTUART_H
#include "mactimer/mactimer.h"
typedef struct tsoftuart {
uint32_t tx_pin;
/* Bit time period in usec * 256 */
uint32_t td;
mactimer_t output_mactimer;
uint32_t output_queue[16];
volatile uint64_t output_start_time;
volatile size_t output_queue_head;
volatile size_t output_queue_tail;
size_t output_queue_state;
uint64_t output_expected_time;
int32_t output_queue_error_high;
int32_t output_queue_error_low;
uint32_t output_done;
} tsoftuart_t;
void tsoftuart_putc(tsoftuart_t *uart, uint8_t ch);
ssize_t tsoftuart_write(tsoftuart_t *uart, const void *ptr, size_t len);
tsoftuart_t *tsoftuart_init(uint8_t tx_pin, uint32_t baud_rate);
#endif /* _TSOFTUART_H */