Commit 93a762a7 authored by devsaurus's avatar devsaurus
Browse files

Merge remote-tracking branch 'upstream/dev' into dev

parents e58b7671 98b2bffa
// Headers to the various functions in the rom (as we discover them)
#ifndef _ROM_H_
#define _ROM_H_
// SHA1 is assumed to match the netbsd sha1.h headers
#define SHA1_DIGEST_LENGTH 20
#define SHA1_DIGEST_STRING_LENGTH 41
......@@ -38,6 +41,15 @@ extern unsigned char * base64_decode(const unsigned char *src, size_t len, size_
extern void mem_init(void * start_addr);
// Interrupt Service Routine functions
typedef void (*ets_isr_fn) (void *arg, uint32_t sp);
extern int ets_isr_attach (unsigned int interrupt, ets_isr_fn, void *arg);
extern void ets_isr_mask (unsigned intr);
extern void ets_isr_unmask (unsigned intr);
// Cycle-counter
extern unsigned int xthal_get_ccount (void);
extern int xthal_set_ccompare (unsigned int timer_number, unsigned int compare_value);
// 2, 3 = reset (module dependent?), 4 = wdt
int rtc_get_reset_reason (void);
......@@ -94,3 +106,4 @@ typedef void (*exception_handler_fn) (struct exception_frame *ef, uint32_t cause
*/
exception_handler_fn _xtos_set_exception_handler (uint32_t cause, exception_handler_fn handler);
#endif
#ifndef RTC_ACCESS_H
#define RTC_ACCESS_H
#include <c_types.h>
#define RTC_MMIO_BASE 0x60000700
#define RTC_USER_MEM_BASE 0x60001200
#define RTC_USER_MEM_NUM_DWORDS 128
#define RTC_TARGET_ADDR 0x04
#define RTC_COUNTER_ADDR 0x1c
static inline uint32_t rtc_mem_read(uint32_t addr)
{
return ((uint32_t*)RTC_USER_MEM_BASE)[addr];
}
static inline void rtc_mem_write(uint32_t addr, uint32_t val)
{
((uint32_t*)RTC_USER_MEM_BASE)[addr]=val;
}
static inline uint64_t rtc_make64(uint32_t high, uint32_t low)
{
return (((uint64_t)high)<<32)|low;
}
static inline uint64_t rtc_mem_read64(uint32_t addr)
{
return rtc_make64(rtc_mem_read(addr+1),rtc_mem_read(addr));
}
static inline void rtc_mem_write64(uint32_t addr, uint64_t val)
{
rtc_mem_write(addr+1,val>>32);
rtc_mem_write(addr,val&0xffffffff);
}
static inline void rtc_memw(void)
{
asm volatile ("memw");
}
static inline void rtc_reg_write(uint32_t addr, uint32_t val)
{
rtc_memw();
addr+=RTC_MMIO_BASE;
*((volatile uint32_t*)addr)=val;
rtc_memw();
}
static inline uint32_t rtc_reg_read(uint32_t addr)
{
addr+=RTC_MMIO_BASE;
rtc_memw();
return *((volatile uint32_t*)addr);
}
#endif
/*
* Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the copyright holders nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Bernd Meyer <bmeyer@dius.com.au>
*/
#ifndef _RTCFIFO_H_
#define _RTCFIFO_H_
#include "rtcaccess.h"
#include "rtctime.h"
// 1: measurement alignment, in microseconds
// 2: timestamp for next sample (seconds). For sensors which sense during the sleep phase. Set to
// 0 to indicate no sample waiting. Simply do not use for sensors which deliver values prior to
// deep sleep.
// 3: Number of samples to take before doing a "real" boot. Decremented as samples are obtained
// 4: Reload value for (10). Needs to be applied by the firmware in the real boot (rtc_restart_samples_to_take())
//
// 5: FIFO location. First FIFO address in bits 0:7, first non-FIFO address in bits 8:15.
// Number of tag spaces in bits 16:23
// 6: Number of samples in FIFO.
// 7: FIFO tail (where next sample will be written. Increments by 1 for each sample)
// 8: FIFO head (where next sample will be read. Increments by 1 for each sample)
// 9: FIFO head timestamp. Used and maintained when pulling things off the FIFO. This is the timestamp of the
// most recent sample pulled off; I.e. the head samples timestamp is this plus that sample's delta_t
// 10: FIFO tail timestamp. Used and maintained when adding things to the FIFO. This is the timestamp of the
// most recent sample to have been added. I.e. a new sample's delta-t is calculated relative to this
// (9/10) are meaningless when (3) is zero
//
#define RTC_FIFO_BASE 10
#define RTC_FIFO_MAGIC 0x44695553
// RTCFIFO storage
#define RTC_FIFO_MAGIC_POS (RTC_FIFO_BASE+0)
#define RTC_ALIGNMENT_POS (RTC_FIFO_BASE+1)
#define RTC_TIMESTAMP_POS (RTC_FIFO_BASE+2)
#define RTC_SAMPLESTOTAKE_POS (RTC_FIFO_BASE+3)
#define RTC_SAMPLESPERBOOT_POS (RTC_FIFO_BASE+4)
#define RTC_FIFOLOC_POS (RTC_FIFO_BASE+5)
#define RTC_FIFOCOUNT_POS (RTC_FIFO_BASE+6)
#define RTC_FIFOTAIL_POS (RTC_FIFO_BASE+7)
#define RTC_FIFOHEAD_POS (RTC_FIFO_BASE+8)
#define RTC_FIFOTAIL_T_POS (RTC_FIFO_BASE+9)
#define RTC_FIFOHEAD_T_POS (RTC_FIFO_BASE+10)
// 32-127: FIFO space. Consisting of a number of tag spaces (see 4), followed by data entries.
// Data entries consist of:
// Bits 28:31 -> tag index. 0-15
// Bits 25:27 -> decimals
// Bits 16:24 -> delta-t in seconds from previous entry
// Bits 0:15 -> sample value
#define RTC_DEFAULT_FIFO_START 32
#define RTC_DEFAULT_FIFO_END 128
#define RTC_DEFAULT_TAGCOUNT 5
#define RTC_DEFAULT_FIFO_LOC (RTC_DEFAULT_FIFO_START + (RTC_DEFAULT_FIFO_END<<8) + (RTC_DEFAULT_TAGCOUNT<<16))
#ifndef RTCTIME_SLEEP_ALIGNED
# define RTCTIME_SLEEP_ALIGNED rtc_time_deep_sleep_until_aligned
#endif
typedef struct
{
uint32_t timestamp;
uint32_t value;
uint32_t decimals;
uint32_t tag;
} sample_t;
static inline void rtc_fifo_clear_content(void);
static inline uint32_t rtc_fifo_get_tail(void)
{
return rtc_mem_read(RTC_FIFOTAIL_POS);
}
static inline void rtc_fifo_put_tail(uint32_t val)
{
rtc_mem_write(RTC_FIFOTAIL_POS,val);
}
static inline uint32_t rtc_fifo_get_head(void)
{
return rtc_mem_read(RTC_FIFOHEAD_POS);
}
static inline void rtc_fifo_put_head(uint32_t val)
{
rtc_mem_write(RTC_FIFOHEAD_POS,val);
}
static inline uint32_t rtc_fifo_get_tail_t(void)
{
return rtc_mem_read(RTC_FIFOTAIL_T_POS);
}
static inline void rtc_fifo_put_tail_t(uint32_t val)
{
rtc_mem_write(RTC_FIFOTAIL_T_POS,val);
}
static inline uint32_t rtc_fifo_get_head_t(void)
{
return rtc_mem_read(RTC_FIFOHEAD_T_POS);
}
static inline void rtc_fifo_put_head_t(uint32_t val)
{
rtc_mem_write(RTC_FIFOHEAD_T_POS,val);
}
static inline uint32_t rtc_fifo_get_count(void)
{
return rtc_mem_read(RTC_FIFOCOUNT_POS);
}
static inline void rtc_fifo_put_count(uint32_t val)
{
rtc_mem_write(RTC_FIFOCOUNT_POS,val);
}
static inline uint32_t rtc_fifo_get_tagcount(void)
{
return (rtc_mem_read(RTC_FIFOLOC_POS)>>16)&0xff;
}
static inline uint32_t rtc_fifo_get_tagpos(void)
{
return (rtc_mem_read(RTC_FIFOLOC_POS)>>0)&0xff;
}
static inline uint32_t rtc_fifo_get_last(void)
{
return (rtc_mem_read(RTC_FIFOLOC_POS)>>8)&0xff;
}
static inline uint32_t rtc_fifo_get_first(void)
{
return rtc_fifo_get_tagpos()+rtc_fifo_get_tagcount();
}
static inline void rtc_fifo_put_loc(uint32_t first, uint32_t last, uint32_t tagcount)
{
rtc_mem_write(RTC_FIFOLOC_POS,first+(last<<8)+(tagcount<<16));
}
static inline uint32_t rtc_fifo_normalise_index(uint32_t index)
{
if (index>=rtc_fifo_get_last())
index=rtc_fifo_get_first();
return index;
}
static inline void rtc_fifo_increment_count(void)
{
rtc_fifo_put_count(rtc_fifo_get_count()+1);
}
static inline void rtc_fifo_decrement_count(void)
{
rtc_fifo_put_count(rtc_fifo_get_count()-1);
}
static inline uint32_t rtc_get_samples_to_take(void)
{
return rtc_mem_read(RTC_SAMPLESTOTAKE_POS);
}
static inline void rtc_put_samples_to_take(uint32_t val)
{
rtc_mem_write(RTC_SAMPLESTOTAKE_POS,val);
}
static inline void rtc_decrement_samples_to_take(void)
{
uint32_t stt=rtc_get_samples_to_take();
if (stt)
rtc_put_samples_to_take(stt-1);
}
static inline void rtc_restart_samples_to_take(void)
{
rtc_put_samples_to_take(rtc_mem_read(RTC_SAMPLESPERBOOT_POS));
}
static inline uint32_t rtc_fifo_get_value(uint32_t entry)
{
return entry&0xffff;
}
static inline uint32_t rtc_fifo_get_decimals(uint32_t entry)
{
return (entry>>25)&0x07;
}
static inline uint32_t rtc_fifo_get_deltat(uint32_t entry)
{
return (entry>>16)&0x1ff;
}
static inline uint32_t rtc_fifo_get_tagindex(uint32_t entry)
{
return (entry>>28)&0x0f;
}
static inline uint32_t rtc_fifo_get_tag_from_entry(uint32_t entry)
{
uint32_t index=rtc_fifo_get_tagindex(entry);
uint32_t tags_at=rtc_fifo_get_tagpos();
return rtc_mem_read(tags_at+index);
}
static inline void rtc_fifo_fill_sample(sample_t* dst, uint32_t entry, uint32_t timestamp)
{
dst->timestamp=timestamp;
dst->value=rtc_fifo_get_value(entry);
dst->decimals=rtc_fifo_get_decimals(entry);
dst->tag=rtc_fifo_get_tag_from_entry(entry);
}
// returns 1 if sample popped, 0 if not
static inline int8_t rtc_fifo_pop_sample(sample_t* dst)
{
uint32_t count=rtc_fifo_get_count();
if (count==0)
return 0;
uint32_t head=rtc_fifo_get_head();
uint32_t timestamp=rtc_fifo_get_head_t();
uint32_t entry=rtc_mem_read(head);
timestamp+=rtc_fifo_get_deltat(entry);
rtc_fifo_fill_sample(dst,entry,timestamp);
head=rtc_fifo_normalise_index(head+1);
rtc_fifo_put_head(head);
rtc_fifo_put_head_t(timestamp);
rtc_fifo_decrement_count();
return 1;
}
// returns 1 if sample is available, 0 if not
static inline int8_t rtc_fifo_peek_sample(sample_t* dst, uint32_t from_top)
{
if (rtc_fifo_get_count()<=from_top)
return 0;
uint32_t head=rtc_fifo_get_head();
uint32_t entry=rtc_mem_read(head);
uint32_t timestamp=rtc_fifo_get_head_t();
timestamp+=rtc_fifo_get_deltat(entry);
while (from_top--)
{
head=rtc_fifo_normalise_index(head+1);
entry=rtc_mem_read(head);
timestamp+=rtc_fifo_get_deltat(entry);
}
rtc_fifo_fill_sample(dst,entry,timestamp);
return 1;
}
static inline void rtc_fifo_drop_samples(uint32_t from_top)
{
uint32_t count=rtc_fifo_get_count();
if (count<=from_top)
from_top=count;
uint32_t head=rtc_fifo_get_head();
uint32_t head_t=rtc_fifo_get_head_t();
while (from_top--)
{
uint32_t entry=rtc_mem_read(head);
head_t+=rtc_fifo_get_deltat(entry);
head=rtc_fifo_normalise_index(head+1);
rtc_fifo_decrement_count();
}
rtc_fifo_put_head(head);
rtc_fifo_put_head_t(head_t);
}
static inline int rtc_fifo_find_tag_index(uint32_t tag)
{
uint32_t tags_at=rtc_fifo_get_tagpos();
uint32_t count=rtc_fifo_get_tagcount();
uint32_t i;
for (i=0;i<count;i++)
{
uint32_t stag=rtc_mem_read(tags_at+i);
if (stag==tag)
return i;
if (stag==0)
{
rtc_mem_write(tags_at+i,tag);
return i;
}
}
return -1;
}
static int32_t rtc_fifo_delta_t(uint32_t t, uint32_t ref_t)
{
uint32_t delta=t-ref_t;
if (delta>0x1ff)
return -1;
return delta;
}
static uint32_t rtc_fifo_construct_entry(uint32_t val, uint32_t tagindex, uint32_t decimals, uint32_t deltat)
{
return (val & 0xffff) + ((deltat & 0x1ff) <<16) +
((decimals & 0x7)<<25) + ((tagindex & 0xf)<<28);
}
static inline void rtc_fifo_store_sample(const sample_t* s)
{
uint32_t head=rtc_fifo_get_head();
uint32_t tail=rtc_fifo_get_tail();
uint32_t count=rtc_fifo_get_count();
int32_t tagindex=rtc_fifo_find_tag_index(s->tag);
if (count==0)
{
rtc_fifo_put_head_t(s->timestamp);
rtc_fifo_put_tail_t(s->timestamp);
}
uint32_t tail_t=rtc_fifo_get_tail_t();
int32_t deltat=rtc_fifo_delta_t(s->timestamp,tail_t);
if (tagindex<0 || deltat<0)
{ // We got something that doesn't fit into the scheme. Might be a long delay, might
// be some sort of dynamic change. In order to go on, we need to start over....
// ets_printf("deltat is %d, tagindex is %d\n",deltat,tagindex);
rtc_fifo_clear_content();
rtc_fifo_put_head_t(s->timestamp);
rtc_fifo_put_tail_t(s->timestamp);
head=rtc_fifo_get_head();
tail=rtc_fifo_get_tail();
count=rtc_fifo_get_count();
tagindex=rtc_fifo_find_tag_index(s->tag); // This should work now
if (tagindex<0)
return; // Uh-oh! This should never happen
}
if (head==tail && count>0)
{ // Full! Need to remove a sample
sample_t dummy;
rtc_fifo_pop_sample(&dummy);
}
rtc_mem_write(tail++,rtc_fifo_construct_entry(s->value,tagindex,s->decimals,deltat));
rtc_fifo_put_tail(rtc_fifo_normalise_index(tail));
rtc_fifo_put_tail_t(s->timestamp);
rtc_fifo_increment_count();
}
static uint32_t rtc_fifo_make_tag(const uint8_t* s)
{
uint32_t tag=0;
int i;
for (i=0;i<4;i++)
{
if (!s[i])
break;
tag+=((uint32_t)(s[i]&0xff))<<(i*8);
}
return tag;
}
static void rtc_fifo_tag_to_string(uint32_t tag, uint8_t s[5])
{
int i;
s[4]=0;
for (i=0;i<4;i++)
s[i]=(tag>>(8*i))&0xff;
}
static inline uint32_t rtc_fifo_get_divisor(const sample_t* s)
{
uint8_t decimals=s->decimals;
uint32_t div=1;
while (decimals--)
div*=10;
return div;
}
static inline void rtc_fifo_clear_tags(void)
{
uint32_t tags_at=rtc_fifo_get_tagpos();
uint32_t count=rtc_fifo_get_tagcount();
while (count--)
rtc_mem_write(tags_at++,0);
}
static inline void rtc_fifo_clear_content(void)
{
uint32_t first=rtc_fifo_get_first();
rtc_fifo_put_tail(first);
rtc_fifo_put_head(first);
rtc_fifo_put_count(0);
rtc_fifo_put_tail_t(0);
rtc_fifo_put_head_t(0);
rtc_fifo_clear_tags();
}
static inline void rtc_fifo_init(uint32_t first, uint32_t last, uint32_t tagcount)
{
rtc_fifo_put_loc(first,last,tagcount);
rtc_fifo_clear_content();
}
static inline void rtc_fifo_init_default(uint32_t tagcount)
{
if (tagcount==0)
tagcount=RTC_DEFAULT_TAGCOUNT;
rtc_fifo_init(RTC_DEFAULT_FIFO_START,RTC_DEFAULT_FIFO_END,tagcount);
}
static inline uint8_t rtc_fifo_check_magic(void)
{
if (rtc_mem_read(RTC_FIFO_MAGIC_POS)==RTC_FIFO_MAGIC)
return 1;
return 0;
}
static inline void rtc_fifo_set_magic(void)
{
rtc_mem_write(RTC_FIFO_MAGIC_POS,RTC_FIFO_MAGIC);
}
static inline void rtc_fifo_unset_magic(void)
{
rtc_mem_write(RTC_FIFO_MAGIC_POS,0);
}
static inline void rtc_fifo_deep_sleep_until_sample(uint32_t min_sleep_us)
{
uint32_t align=rtc_mem_read(RTC_ALIGNMENT_POS);
RTCTIME_SLEEP_ALIGNED(align,min_sleep_us);
}
static inline void rtc_fifo_prepare(uint32_t samples_per_boot, uint32_t us_per_sample, uint32_t tagcount)
{
rtc_mem_write(RTC_SAMPLESPERBOOT_POS,samples_per_boot);
rtc_mem_write(RTC_ALIGNMENT_POS,us_per_sample);
rtc_put_samples_to_take(0);
rtc_fifo_init_default(tagcount);
rtc_fifo_set_magic();
}
#endif
/*
* Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the copyright holders nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Johny Mattsson <jmattsson@dius.com.au>
*/
#ifndef _RTCTIME_H_
#define _RTCTIME_H_
/* We don't want to expose the raw rtctime interface as it is heavily
* 'static inline' and used by a few things, so instead we wrap the
* relevant functions and expose these instead, through the rtctime.c module.
*/
#include <c_types.h>
#ifndef _RTCTIME_INTERNAL_H_
struct rtc_timeval
{
uint32_t tv_sec;
uint32_t tv_usec;
};
#endif
void TEXT_SECTION_ATTR rtctime_early_startup (void);
void rtctime_late_startup (void);
void rtctime_gettimeofday (struct rtc_timeval *tv);
void rtctime_settimeofday (const struct rtc_timeval *tv);
bool rtctime_have_time (void);
void rtctime_deep_sleep_us (uint32_t us);
void rtctime_deep_sleep_until_aligned_us (uint32_t align_us, uint32_t min_us);
#endif
This diff is collapsed.
......@@ -35,6 +35,10 @@
#define LUA_USE_MODULES_CRYPTO
#define LUA_USE_MODULES_RC
#define LUA_USE_MODULES_DHT
#define LUA_USE_MODULES_RTCMEM
#define LUA_USE_MODULES_RTCTIME
#define LUA_USE_MODULES_RTCFIFO
#define LUA_USE_MODULES_SNTP
#endif /* LUA_USE_MODULES */
......
......@@ -181,6 +181,38 @@
#define ROM_MODULES_DHT
#endif
#if defined(LUA_USE_MODULES_RTCMEM)
#define MODULES_RTCMEM "rtcmem"
#define ROM_MODULES_RTCMEM \
_ROM(MODULES_RTCMEM, luaopen_rtcmem, rtcmem_map)
#else
#define ROM_MODULES_RTCMEM
#endif
#if defined(LUA_USE_MODULES_RTCTIME)
#define MODULES_RTCTIME "rtctime"
#define ROM_MODULES_RTCTIME \
_ROM(MODULES_RTCTIME, luaopen_rtctime, rtctime_map)
#else
#define ROM_MODULES_RTCTIME
#endif
#if defined(LUA_USE_MODULES_RTCFIFO)
#define MODULES_RTCFIFO "rtcfifo"
#define ROM_MODULES_RTCFIFO \
_ROM(MODULES_RTCFIFO, luaopen_rtcfifo, rtcfifo_map)
#else
#define ROM_MODULES_RTCFIFO
#endif
#if defined(LUA_USE_MODULES_SNTP)
#define MODULES_SNTP "sntp"
#define ROM_MODULES_SNTP \
_ROM(MODULES_SNTP, luaopen_sntp, sntp_map)
#else
#define ROM_MODULES_SNTP
#endif
#define LUA_MODULES_ROM \
ROM_MODULES_GPIO \
ROM_MODULES_PWM \
......@@ -203,6 +235,10 @@
ROM_MODULES_CJSON \
ROM_MODULES_CRYPTO \
ROM_MODULES_RC \
ROM_MODULES_DHT
ROM_MODULES_DHT \
ROM_MODULES_RTCMEM \
ROM_MODULES_RTCTIME \
ROM_MODULES_RTCFIFO \
ROM_MODULES_SNTP \
#endif
// Module for RTC sample FIFO storage
#include "lauxlib.h"
#include "user_modules.h"
#include "rtc/rtctime.h"
#define RTCTIME_SLEEP_ALIGNED rtctime_deep_sleep_until_aligned_us
#include "rtc/rtcfifo.h"
// rtcfifo.prepare ([{sensor_count=n, interval_us=m, storage_begin=x, storage_end=y}])
static int rtcfifo_prepare (lua_State *L)
{
uint32_t sensor_count = RTC_DEFAULT_TAGCOUNT;
uint32_t interval_us = 0;
int first = -1, last = -1;
if (lua_istable (L, 1))
{
#ifdef LUA_USE_MODULES_RTCTIME
lua_getfield (L, 1, "interval_us");
if (lua_isnumber (L, -1))
interval_us = lua_tonumber (L, -1);
lua_pop (L, 1);
#endif
lua_getfield (L, 1, "sensor_count");
if (lua_isnumber (L, -1))
sensor_count = lua_tonumber (L, -1);
lua_pop (L, 1);
lua_getfield (L, 1, "storage_begin");
if (lua_isnumber (L, -1))
first = lua_tonumber (L, -1);
lua_pop (L, 1);
lua_getfield (L, 1, "storage_end");
if (lua_isnumber (L, -1))
last = lua_tonumber (L, -1);
lua_pop (L, 1);
}
else if (!lua_isnone (L, 1))
return luaL_error (L, "expected table as arg #1");
rtc_fifo_prepare (0, interval_us, sensor_count);
if (first != -1 && last != -1)
rtc_fifo_put_loc (first, last, sensor_count);
return 0;
}
// ready = rtcfifo.ready ()
static int rtcfifo_ready (lua_State *L)
{
lua_pushnumber (L, rtc_fifo_check_magic ());
return 1;
}
static void check_fifo_magic (lua_State *L)
{
if (!rtc_fifo_check_magic ())
luaL_error (L, "rtcfifo not prepared!");
}
// rtcfifo.put (timestamp, value, decimals, sensor_name)
static int rtcfifo_put (lua_State *L)
{
check_fifo_magic (L);
sample_t s;
s.timestamp = luaL_checknumber (L, 1);
s.value = luaL_checknumber (L, 2);
s.decimals = luaL_checknumber (L, 3);
size_t len;
const char *str = luaL_checklstring (L, 4, &len);
union {
uint32_t u;
char s[4];
} conv = { 0 };
strncpy (conv.s, str, len > 4 ? 4 : len);
s.tag = conv.u;
rtc_fifo_store_sample (&s);
return 0;
}
static int extract_sample (lua_State *L, const sample_t *s)
{
lua_pushnumber (L, s->timestamp);
lua_pushnumber (L, s->value);
lua_pushnumber (L, s->decimals);
union {
uint32_t u;
char s[4];
} conv = { s->tag };
if (conv.s[3] == 0)
lua_pushstring (L, conv.s);
else
lua_pushlstring (L, conv.s, 4);
return 4;
}
// timestamp, value, decimals, sensor_name = rtcfifo.pop ()
static int rtcfifo_pop (lua_State *L)
{
check_fifo_magic (L);
sample_t s;
if (!rtc_fifo_pop_sample (&s))
return 0;
else
return extract_sample (L, &s);
}
// timestamp, value, decimals, sensor_name = rtcfifo.peek ([offset])
static int rtcfifo_peek (lua_State *L)
{
check_fifo_magic (L);
sample_t s;
uint32_t offs = 0;
if (lua_isnumber (L, 1))
offs = lua_tonumber (L, 1);
if (!rtc_fifo_peek_sample (&s, offs))
return 0;
else
return extract_sample (L, &s);
}
// rtcfifo.drop (num)
static int rtcfifo_drop (lua_State *L)
{
check_fifo_magic (L);
rtc_fifo_drop_samples (luaL_checknumber (L, 1));
return 0;
}
// num = rtcfifo.count ()
static int rtcfifo_count (lua_State *L)
{
check_fifo_magic (L);
lua_pushnumber (L, rtc_fifo_get_count ());
return 1;
}
#ifdef LUA_USE_MODULES_RTCTIME
// rtcfifo.dsleep_until_sample (min_sleep_us)
static int rtcfifo_dsleep_until_sample (lua_State *L)
{
check_fifo_magic (L);
uint32_t min_us = luaL_checknumber (L, 1);
rtc_fifo_deep_sleep_until_sample (min_us); // no return
return 0;
}
#endif
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE rtcfifo_map[] =
{
{ LSTRKEY("prepare"), LFUNCVAL(rtcfifo_prepare) },
{ LSTRKEY("ready"), LFUNCVAL(rtcfifo_ready) },
{ LSTRKEY("put"), LFUNCVAL(rtcfifo_put) },
{ LSTRKEY("pop"), LFUNCVAL(rtcfifo_pop) },
{ LSTRKEY("peek"), LFUNCVAL(rtcfifo_peek) },
{ LSTRKEY("drop"), LFUNCVAL(rtcfifo_drop) },
{ LSTRKEY("count"), LFUNCVAL(rtcfifo_count) },
#ifdef LUA_USE_MODULES_RTCTIME
{ LSTRKEY("dsleep_until_sample"), LFUNCVAL(rtcfifo_dsleep_until_sample) },
#endif
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_rtcfifo (lua_State *L)
{
#if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else
luaL_register (L, AUXLIB_RTCFIFO, rtcfifo_map);
return 1;
#endif
}
// Module for RTC user memory access
#include "lauxlib.h"
#include "rtc/rtcaccess.h"
static int rtcmem_read32 (lua_State *L)
{
int idx = luaL_checknumber (L, 1);
int n = 1;
if (lua_isnumber (L, 2))
n = lua_tonumber (L, 2);
if (!lua_checkstack (L, n))
return 0;
int ret = 0;
while (n > 0 && idx >= 0 && idx < RTC_USER_MEM_NUM_DWORDS)
{
lua_pushinteger (L, rtc_mem_read (idx++));
--n;
++ret;
}
return ret;
}
static int rtcmem_write32 (lua_State *L)
{
int idx = luaL_checknumber (L, 1);
int n = lua_gettop (L) - 1;
luaL_argcheck (
L, idx + n <= RTC_USER_MEM_NUM_DWORDS, 1, "RTC mem would overrun");
int src = 2;
while (n-- > 0)
{
rtc_mem_write (idx++, lua_tonumber (L, src++));
}
return 0;
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE rtcmem_map[] =
{
{ LSTRKEY("read32"), LFUNCVAL(rtcmem_read32) },
{ LSTRKEY("write32"), LFUNCVAL(rtcmem_write32) },
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_rtcmem (lua_State *L)
{
#if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else
luaL_register (L, AUXLIB_RTCMEM, rtcmem_map);
return 1;
#endif
}
// Module for RTC time keeping
#include "lauxlib.h"
#include "rtc/rtctime_internal.h"
#include "rtc/rtctime.h"
// ******* C API functions *************
void rtctime_early_startup (void)
{
Cache_Read_Enable (0, 0, 1);
rtc_time_register_bootup ();
rtc_time_switch_clocks ();
Cache_Read_Disable ();
}
void rtctime_late_startup (void)
{
rtc_time_switch_system ();
}
void rtctime_gettimeofday (struct rtc_timeval *tv)
{
rtc_time_gettimeofday (tv);
}
void rtctime_settimeofday (const struct rtc_timeval *tv)
{
if (!rtc_time_check_magic ())
rtc_time_prepare ();
rtc_time_settimeofday (tv);
}
bool rtctime_have_time (void)
{
return rtc_time_have_time ();
}
void rtctime_deep_sleep_us (uint32_t us)
{
rtc_time_deep_sleep_us (us);
}
void rtctime_deep_sleep_until_aligned_us (uint32_t align_us, uint32_t min_us)
{
rtc_time_deep_sleep_until_aligned (align_us, min_us);
}
// ******* Lua API functions *************
// rtctime.set (sec, usec)
static int rtctime_set (lua_State *L)
{
if (!rtc_time_check_magic ())
rtc_time_prepare ();
uint32_t sec = luaL_checknumber (L, 1);
uint32_t usec = 0;
if (lua_isnumber (L, 2))
usec = lua_tonumber (L, 2);
struct rtc_timeval tv = { sec, usec };
rtctime_settimeofday (&tv);
return 0;
}
// sec, usec = rtctime.get ()
static int rtctime_get (lua_State *L)
{
struct rtc_timeval tv;
rtctime_gettimeofday (&tv);
lua_pushnumber (L, tv.tv_sec);
lua_pushnumber (L, tv.tv_usec);
return 2;
}
static void do_sleep_opt (lua_State *L, int idx)
{
if (lua_isnumber (L, idx))
{
uint32_t opt = lua_tonumber (L, idx);
if (opt < 0 || opt > 4)
luaL_error (L, "unknown sleep option");
deep_sleep_set_option (opt);
}
}
// rtctime.dsleep (usec, option)
static int rtctime_dsleep (lua_State *L)
{
uint32_t us = luaL_checknumber (L, 1);
do_sleep_opt (L, 2);
rtctime_deep_sleep_us (us); // does not return
return 0;
}
// rtctime.dsleep_aligned (aligned_usec, min_usec, option)
static int rtctime_dsleep_aligned (lua_State *L)
{
if (!rtctime_have_time ())
return luaL_error (L, "time not available, unable to align");
uint32_t align_us = luaL_checknumber (L, 1);
uint32_t min_us = luaL_checknumber (L, 2);
do_sleep_opt (L, 3);
rtctime_deep_sleep_until_aligned_us (align_us, min_us); // does not return
return 0;
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE rtctime_map[] =
{
{ LSTRKEY("set"), LFUNCVAL(rtctime_set) },
{ LSTRKEY("get"), LFUNCVAL(rtctime_get) },
{ LSTRKEY("dsleep"), LFUNCVAL(rtctime_dsleep) },
{ LSTRKEY("dsleep_aligned"), LFUNCVAL(rtctime_dsleep_aligned) },
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_rtctime (lua_State *L)
{
#if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else
luaL_register (L, AUXLIB_RTCTIME, rtctime_map);
return 1;
#endif
}
/*
* Copyright 2015 Dius Computing Pty Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* - Neither the name of the copyright holders nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Johny Mattsson <jmattsson@dius.com.au>
*/
// Module for Simple Network Time Protocol (SNTP)
#include "lauxlib.h"
#include "os_type.h"
#include "osapi.h"
#include "lwip/udp.h"
#include "c_stdlib.h"
#include "user_modules.h"
#ifdef LUA_USE_MODULES_RTCTIME
#include "rtc/rtctime.h"
#endif
#define NTP_PORT 123
#define NTP_ANYCAST_ADDR(dst) IP4_ADDR(dst, 224, 0, 1, 1)
#define MAX_ATTEMPTS 5
#if 0
# define sntp_dbg(...) c_printf(__VA_ARGS__)
#else
# define sntp_dbg(...)
#endif
typedef struct
{
uint32_t sec;
uint32_t frac;
} ntp_timestamp_t;
typedef struct
{
uint8_t mode : 3;
uint8_t ver : 3;
uint8_t LI : 2;
uint8_t stratum;
uint8_t poll;
uint8_t precision;
uint32_t root_delay;
uint32_t root_dispersion;
uint32_t refid;
ntp_timestamp_t ref;
ntp_timestamp_t origin;
ntp_timestamp_t recv;
ntp_timestamp_t xmit;
} ntp_frame_t;
typedef struct
{
struct udp_pcb *pcb;
ntp_timestamp_t cookie;
os_timer_t timer;
int sync_cb_ref;
int err_cb_ref;
uint8_t attempts;
} sntp_state_t;
static sntp_state_t *state;
static ip_addr_t server;
static void cleanup (lua_State *L)
{
os_timer_disarm (&state->timer);
udp_remove (state->pcb);
luaL_unref (L, LUA_REGISTRYINDEX, state->sync_cb_ref);
luaL_unref (L, LUA_REGISTRYINDEX, state->err_cb_ref);
os_free (state);
state = 0;
}
static void handle_error (lua_State *L)
{
sntp_dbg("sntp: handle_error\n");
if (state->err_cb_ref != LUA_NOREF)
{
lua_rawgeti (L, LUA_REGISTRYINDEX, state->err_cb_ref);
cleanup (L);
lua_call (L, 0, 0);
}
else
cleanup (L);
}
static void sntp_dosend (lua_State *L)
{
++state->attempts;
sntp_dbg("sntp: attempt %d\n", state->attempts);
struct pbuf *p = pbuf_alloc (PBUF_TRANSPORT, sizeof (ntp_frame_t), PBUF_RAM);
if (!p)
handle_error (L);
ntp_frame_t req;
os_memset (&req, 0, sizeof (req));
req.ver = 4;
req.mode = 3; // client
#ifdef LUA_USE_MODULES_RTCTIME
struct rtc_timeval tv;
rtctime_gettimeofday (&tv);
req.xmit.sec = htonl (tv.tv_sec);
req.xmit.frac = htonl (tv.tv_usec);
#else
req.xmit.frac = htonl (system_get_time ());
#endif
state->cookie = req.xmit;
os_memcpy (p->payload, &req, sizeof (req));
int ret = udp_sendto (state->pcb, p, &server, NTP_PORT);
sntp_dbg("sntp: send: %d\n", ret);
pbuf_free (p);
if (ret != ERR_OK)
handle_error (L);
}
static void on_timeout (void *arg)
{
sntp_dbg("sntp: timer\n");
lua_State *L = arg;
if (state->attempts >= MAX_ATTEMPTS)
handle_error (L);
else
sntp_dosend (L);
}
static void on_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, uint16_t port)
{
(void)port;
sntp_dbg("sntp: on_recv\n");
lua_State *L = arg;
if (!state || state->pcb != pcb)
{
// "impossible", but don't leak if it did happen somehow...
udp_remove (pcb);
pbuf_free (p);
return;
}
if (!p)
return;
if (p->len < sizeof (ntp_frame_t))
{
pbuf_free (p);
return; // not an ntp frame, ignore
}
// make sure we have an aligned copy to work from
ntp_frame_t ntp;
os_memcpy (&ntp, p->payload, sizeof (ntp));
pbuf_free (p);
sntp_dbg("sntp: transmit timestamp: %u, %u\n", ntp.xmit.sec, ntp.xmit.frac);
// sanity checks before we touch our clocks
ip_addr_t anycast;
NTP_ANYCAST_ADDR(&anycast);
if (server.addr != anycast.addr && server.addr != addr->addr)
return; // unknown sender, ignore
if (ntp.origin.sec != state->cookie.sec ||
ntp.origin.frac != state->cookie.frac)
return; // unsolicited message, ignore
if (ntp.LI == 3)
return; // server clock not synchronized (why did it even respond?!)
server.addr = addr->addr;
ntp.origin.sec = ntohl (ntp.origin.sec);
ntp.origin.frac = ntohl (ntp.origin.frac);
ntp.recv.sec = ntohl (ntp.recv.sec);
ntp.recv.frac = ntohl (ntp.recv.frac);
ntp.xmit.sec = ntohl (ntp.xmit.sec);
ntp.xmit.frac = ntohl (ntp.xmit.frac);
const uint32_t UINT32_MAXI = (uint32_t)-1;
const uint64_t MICROSECONDS = 1000000ull;
const uint32_t NTP_TO_UNIX_EPOCH = 2208988800ul;
bool have_cb = (state->sync_cb_ref != LUA_NOREF);
// if we have rtctime, do higher resolution delta calc, else just use
// the transmit timestamp
#ifdef LUA_USE_MODULES_RTCTIME
struct rtc_timeval tv;
rtctime_gettimeofday (&tv);
ntp_timestamp_t dest;
dest.sec = tv.tv_sec;
dest.frac = (MICROSECONDS * tv.tv_usec) / UINT32_MAXI;
// Compensation as per RFC2030
int64_t delta_s = (((int64_t)ntp.recv.sec - ntp.origin.sec) +
((int64_t)ntp.xmit.sec - dest.sec)) / 2;
int64_t delta_f = (((int64_t)ntp.recv.frac - ntp.origin.frac) +
((int64_t)ntp.xmit.frac - dest.frac)) / 2;
dest.sec += delta_s;
if (delta_f + dest.frac < 0)
{
delta_f += UINT32_MAXI;
--dest.sec;
}
else if (delta_f + dest.frac > UINT32_MAXI)
{
delta_f -= UINT32_MAXI;
++dest.sec;
}
dest.frac += delta_f;
tv.tv_sec = dest.sec - NTP_TO_UNIX_EPOCH;
tv.tv_usec = (MICROSECONDS * dest.frac) / UINT32_MAXI;
rtctime_settimeofday (&tv);
if (have_cb)
{
lua_rawgeti (L, LUA_REGISTRYINDEX, state->sync_cb_ref);
lua_pushnumber (L, tv.tv_sec);
lua_pushnumber (L, tv.tv_usec);
}
#else
if (have_cb)
{
lua_rawgeti (L, LUA_REGISTRYINDEX, state->sync_cb_ref);
lua_pushnumber (L, ntp.xmit.sec - NTP_TO_UNIX_EPOCH);
lua_pushnumber (L, (MICROSECONDS * ntp.xmit.frac) / UINT32_MAXI);
}
#endif
cleanup (L);
if (have_cb)
{
lua_pushstring (L, ipaddr_ntoa (&server));
lua_call (L, 3, 0);
}
}
// sntp.sync (server or nil, syncfn or nil, errfn or nil)
static int sntp_sync (lua_State *L)
{
// default to anycast address, then allow last server to stick
if (server.addr == IPADDR_ANY)
NTP_ANYCAST_ADDR(&server);
const char *errmsg = 0;
#define sync_err(x) do { errmsg = x; goto error; } while (0)
if (state)
return luaL_error (L, "sync in progress");
state = (sntp_state_t *)c_malloc (sizeof (sntp_state_t));
if (!state)
sync_err ("out of memory");
memset (state, 0, sizeof (sntp_state_t));
state->sync_cb_ref = LUA_NOREF;
state->err_cb_ref = LUA_NOREF;
state->pcb = udp_new ();
if (!state->pcb)
sync_err ("out of memory");
if (udp_bind (state->pcb, IP_ADDR_ANY, NTP_PORT) != ERR_OK)
sync_err ("ntp port in use");
udp_recv (state->pcb, on_recv, L);
// use last server, unless new one specified
if (!lua_isnoneornil (L, 1))
{
if (!ipaddr_aton (luaL_checkstring (L, 1), &server))
sync_err ("bad IP address");
}
if (!lua_isnoneornil (L, 2))
{
lua_pushvalue (L, 2);
state->sync_cb_ref = luaL_ref (L, LUA_REGISTRYINDEX);
}
else
state->sync_cb_ref = LUA_NOREF;
if (!lua_isnoneornil (L, 3))
{
lua_pushvalue (L, 3);
state->err_cb_ref = luaL_ref (L, LUA_REGISTRYINDEX);
}
else
state->err_cb_ref = LUA_NOREF;
os_timer_disarm (&state->timer);
os_timer_setfn (&state->timer, on_timeout, L);
os_timer_arm (&state->timer, 1000, 1);
state->attempts = 0;
sntp_dosend (L);
return 0;
error:
if (state)
{
if (state->pcb)
udp_remove (state->pcb);
c_free (state);
state = 0;
}
return luaL_error (L, errmsg);
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE sntp_map[] =
{
{ LSTRKEY("sync"), LFUNCVAL(sntp_sync) },
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_sntp (lua_State *L)
{
#if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else
luaL_register (L, AUXLIB_SNTP, sntp_map);
return 1;
#endif
}
......@@ -1105,7 +1105,6 @@ static const LUA_REG_TYPE wifi_station_map[] =
{ LSTRKEY( "connect" ), LFUNCVAL ( wifi_station_connect4lua ) },
{ LSTRKEY( "disconnect" ), LFUNCVAL ( wifi_station_disconnect4lua ) },
{ LSTRKEY( "autoconnect" ), LFUNCVAL ( wifi_station_setauto ) },
{ LSTRKEY( "getconfig" ), LFUNCVAL( wifi_ap_getconfig ) },
{ LSTRKEY( "getip" ), LFUNCVAL ( wifi_station_getip ) },
{ LSTRKEY( "setip" ), LFUNCVAL ( wifi_station_setip ) },
{ LSTRKEY( "getbroadcast" ), LFUNCVAL ( wifi_station_getbroadcast) },
......@@ -1133,6 +1132,7 @@ static const LUA_REG_TYPE wifi_ap_map[] =
{ LSTRKEY( "getmac" ), LFUNCVAL ( wifi_ap_getmac ) },
{ LSTRKEY( "setmac" ), LFUNCVAL ( wifi_ap_setmac ) },
{ LSTRKEY( "getclient" ), LFUNCVAL ( wifi_ap_listclient ) },
{ LSTRKEY( "getconfig" ), LFUNCVAL( wifi_ap_getconfig ) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "dhcp" ), LROVAL( wifi_ap_dhcp_map ) },
......
......@@ -17,11 +17,16 @@
#include "flash_fs.h"
#include "user_interface.h"
#include "user_exceptions.h"
#include "user_modules.h"
#include "ets_sys.h"
#include "driver/uart.h"
#include "mem.h"
#ifdef LUA_USE_MODULES_RTCTIME
#include "rtc/rtctime.h"
#endif
#define SIG_LUA 0
#define TASK_QUEUE_LEN 4
os_event_t *taskQueue;
......@@ -31,12 +36,16 @@ os_event_t *taskQueue;
* by the time it is invoked the irom has not yet been mapped. This naturally
* also goes for anything the trampoline itself calls.
*/
void user_start_trampoline (void) TEXT_SECTION_ATTR;
void user_start_trampoline (void)
void TEXT_SECTION_ATTR user_start_trampoline (void)
{
__real__xtos_set_exception_handler (
EXCCAUSE_LOAD_STORE_ERROR, load_non_32_wide_handler);
#ifdef LUA_USE_MODULES_RTCTIME
// Note: Keep this as close to call_user_start() as possible, since it
// is where the cpu clock actually gets bumped to 80MHz.
rtctime_early_startup ();
#endif
call_user_start ();
}
......@@ -141,6 +150,9 @@ void nodemcu_init(void)
*******************************************************************************/
void user_init(void)
{
#ifdef LUA_USE_MODULES_RTCTIME
rtctime_late_startup ();
#endif
// NODE_DBG("SDK version:%s\n", system_get_sdk_version());
// system_print_meminfo();
// os_printf("Heap size::%d.\n",system_get_free_heap_size());
......
......@@ -85,7 +85,7 @@ typedef enum {
#endif /* ICACHE_FLASH */
#define TEXT_SECTION_ATTR __attribute__((section(".text")))
#define RAM_CONST_ATTR __attribute__((section(".text")))
#define RAM_CONST_ATTR __attribute__((section(".rodata")))
#ifndef __cplusplus
typedef unsigned char bool;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment