Add core from RtlDuino
This commit is contained in:
122
arduino/realtek-ambz/boards.txt
Normal file
122
arduino/realtek-ambz/boards.txt
Normal file
@@ -0,0 +1,122 @@
|
||||
menu.device_variant=Variant
|
||||
menu.upload_method=Upload method
|
||||
|
||||
|
||||
rtlmodule_rtl8710.name=RTL00 (RTL8710)
|
||||
rtlmodule_rtl8710.vid.0=0x2341
|
||||
rtlmodule_rtl8710.pid.0=0x003d
|
||||
rtlmodule_rtl8710.upload.tool=jlink
|
||||
#rtlmodule_rtl8710.upload.protocol=mbed_dap
|
||||
rtlmodule_rtl8710.upload.protocol=jlink
|
||||
rtlmodule_rtl8710.upload.maximum_size=372736
|
||||
#rtlmodule_rtl8710.upload.use_1200bps_touch=false
|
||||
rtlmodule_rtl8710.upload.wait_for_upload_port=false
|
||||
rtlmodule_rtl8710.upload.native_usb=false
|
||||
rtlmodule_rtl8710.build.mcu=cortex-m3
|
||||
rtlmodule_rtl8710.build.f_cpu=166666666L
|
||||
#rtlmodule_rtl8710.build.usb_product="Module RTL8710"
|
||||
rtlmodule_rtl8710.build.board=rtlmodule
|
||||
rtlmodule_rtl8710.build.core=arduino
|
||||
rtlmodule_rtl8710.build.extra_flags=-mthumb -DBOARD_RTL8710
|
||||
rtlmodule_rtl8710.build.ldscript=linker_scripts/gcc/rtl8710-symbol-v04-img2_arduino_arduino.ld
|
||||
rtlmodule_rtl8710.build.sym_bklist=linker_scripts/gcc/symbol_black_list.txt
|
||||
rtlmodule_rtl8710.build.variant=rtl8710
|
||||
|
||||
rtlmodule_rtl8710.menu.upload_method.jlinkram=JLink RAM
|
||||
rtlmodule_rtl8710.menu.upload_method.jlinkram.upload.protocol=jlink
|
||||
rtlmodule_rtl8710.menu.upload_method.jlinkram.upload.tool=jlink
|
||||
|
||||
rtlmodule_rtl8710.menu.upload_method.jlgdbimg=JLink IMG
|
||||
rtlmodule_rtl8710.menu.upload_method.jlgdbimg.upload.protocol=jlgdbimg
|
||||
rtlmodule_rtl8710.menu.upload_method.jlgdbimg.upload.tool=jlgdbimg
|
||||
|
||||
rtlmodule_rtl8710.menu.upload_method.jlgdbota=JLink OTA
|
||||
rtlmodule_rtl8710.menu.upload_method.jlgdbota.upload.protocol=jlgdbota
|
||||
rtlmodule_rtl8710.menu.upload_method.jlgdbota.upload.tool=jlgdbota
|
||||
|
||||
rtlmodule_rtl8710.menu.upload_method.networkota=Network OTA
|
||||
rtlmodule_rtl8710.menu.upload_method.networkota.upload.protocol=network
|
||||
rtlmodule_rtl8710.menu.upload_method.networkota.upload.tool=network
|
||||
|
||||
rtlmodule_rtl8710.menu.upload_method.dapimg=DAP-Link IMG
|
||||
rtlmodule_rtl8710.menu.upload_method.dapimg.upload.protocol=dapimg
|
||||
rtlmodule_rtl8710.menu.upload_method.dapimg.upload.tool=dapimg
|
||||
|
||||
|
||||
rtlmodule_rtl8711am.name=F11AMIM13 (RTL8711AM)
|
||||
rtlmodule_rtl8711am.vid.0=0x2341
|
||||
rtlmodule_rtl8711am.pid.0=0x003d
|
||||
rtlmodule_rtl8711am.upload.tool=jlink
|
||||
#rtlmodule_rtl8711am.upload.protocol=mbed_dap
|
||||
rtlmodule_rtl8711am.upload.protocol=jlink
|
||||
rtlmodule_rtl8711am.upload.maximum_size=2499639
|
||||
#rtlmodule_rtl8711am.upload.use_1200bps_touch=false
|
||||
rtlmodule_rtl8711am.upload.wait_for_upload_port=false
|
||||
rtlmodule_rtl8711am.upload.native_usb=false
|
||||
rtlmodule_rtl8711am.build.mcu=cortex-m3
|
||||
rtlmodule_rtl8711am.build.f_cpu=166666666L
|
||||
#rtlmodule_rtl8711am.build.usb_product="Module rtl8711am"
|
||||
rtlmodule_rtl8711am.build.board=rtlmodule
|
||||
rtlmodule_rtl8711am.build.core=arduino
|
||||
rtlmodule_rtl8711am.build.extra_flags=-mthumb -DBOARD_RTL8711AM
|
||||
rtlmodule_rtl8711am.build.ldscript=linker_scripts/gcc/rtl8711am-symbol-v04-img2_arduino_arduino.ld
|
||||
rtlmodule_rtl8710.build.sym_bklist=linker_scripts/gcc/symbol_black_list.txt
|
||||
rtlmodule_rtl8711am.build.variant=rtl8711am
|
||||
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlinkram=JLink RAM+SDRAM
|
||||
rtlmodule_rtl8711am.upload_method.jlinkram.upload.protocol=jlinkam
|
||||
rtlmodule_rtl8711am.upload_method.jlinkram.upload.tool=jlinkam
|
||||
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlgdbimg=JLink IMG
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlgdbimg.upload.protocol=jlgdbimg
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlgdbimg.upload.tool=jlgdbimg
|
||||
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlgdbota=JLink OTA
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlgdbota.upload.protocol=jlgdbota
|
||||
rtlmodule_rtl8711am.menu.upload_method.jlgdbota.upload.tool=jlgdbota
|
||||
|
||||
rtlmodule_rtl8711am.menu.upload_method.networkota=Network OTA
|
||||
rtlmodule_rtl8711am.menu.upload_method.networkota.upload.protocol=network
|
||||
rtlmodule_rtl8711am.menu.upload_method.networkota.upload.tool=network
|
||||
|
||||
rtlmodule_rtl8711am.menu.upload_method.dapimg=DAP-Link IMG
|
||||
rtlmodule_rtl8711am.menu.upload_method.dapimg.upload.protocol=dapimg
|
||||
rtlmodule_rtl8711am.menu.upload_method.dapimg.upload.tool=dapimg
|
||||
|
||||
|
||||
rtlmodule_rtl8195.name=RTL8195
|
||||
rtlmodule_rtl8195.vid.0=0x2341
|
||||
rtlmodule_rtl8195.pid.0=0x003d
|
||||
rtlmodule_rtl8195.upload.tool=jlink
|
||||
rtlmodule_rtl8195.upload.protocol=jlink
|
||||
rtlmodule_rtl8195.upload.maximum_size=2499639
|
||||
rtlmodule_rtl8195.upload.wait_for_upload_port=false
|
||||
rtlmodule_rtl8195.upload.native_usb=false
|
||||
rtlmodule_rtl8195.build.mcu=cortex-m3
|
||||
rtlmodule_rtl8195.build.f_cpu=166666666L
|
||||
rtlmodule_rtl8195.build.board=rtlmodule
|
||||
rtlmodule_rtl8195.build.core=arduino
|
||||
rtlmodule_rtl8195.build.extra_flags=-mthumb -DBOARD_RTL8195A
|
||||
rtlmodule_rtl8195.build.ldscript=linker_scripts/gcc/rtl8195-symbol-v04-img3.ld
|
||||
rtlmodule_rtl8195.build.sym_bklist=linker_scripts/gcc/symbol_black_list.txt
|
||||
rtlmodule_rtl8195.build.variant=rtl8195
|
||||
|
||||
rtlmodule_rtl8195.menu.upload_method.jlinkram=JLink RAM+SDRAM
|
||||
rtlmodule_rtl8195.menu.upload_method.jlinkram.upload.protocol=jlinkam
|
||||
rtlmodule_rtl8195.menu.upload_method.jlinkram.upload.tool=jlinkam
|
||||
|
||||
rtlmodule_rtl8195.menu.upload_method.jlgdbimg=JLink IMG
|
||||
rtlmodule_rtl8195.menu.upload_method.jlgdbimg.upload.protocol=jlgdbimg
|
||||
rtlmodule_rtl8195.menu.upload_method.jlgdbimg.upload.tool=jlgdbimg
|
||||
|
||||
rtlmodule_rtl8195.menu.upload_method.jlgdbota=JLink OTA
|
||||
rtlmodule_rtl8195.menu.upload_method.jlgdbota.upload.protocol=jlgdbota
|
||||
rtlmodule_rtl8195.menu.upload_method.jlgdbota.upload.tool=jlgdbota
|
||||
|
||||
rtlmodule_rtl8195.menu.upload_method.networkota=Network OTA
|
||||
rtlmodule_rtl8195.menu.upload_method.networkota.upload.protocol=network
|
||||
rtlmodule_rtl8195.menu.upload_method.networkota.upload.tool=network
|
||||
|
||||
rtlmodule_rtl8195.menu.upload_method.dapimg=DAP-Link IMG
|
||||
rtlmodule_rtl8195.menu.upload_method.dapimg.upload.protocol=dapimg
|
||||
rtlmodule_rtl8195.menu.upload_method.dapimg.upload.tool=dapimg
|
||||
189
arduino/realtek-ambz/cores/arduino/Arduino.h
Normal file
189
arduino/realtek-ambz/cores/arduino/Arduino.h
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
Arduino.h - Main include file for the Arduino SDK
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Arduino_h
|
||||
#define Arduino_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "binary.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "wiring_constants.h"
|
||||
|
||||
extern uint32_t SystemCoreClock;
|
||||
|
||||
#define clockCyclesPerMicrosecond() ( SystemCoreClock / 1000000L )
|
||||
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (SystemCoreClock / 1000L) )
|
||||
#define microsecondsToClockCycles(a) ( (a) * (SystemCoreClock / 1000000L) )
|
||||
|
||||
/*
|
||||
* \brief Set CPU CLK 166MHz
|
||||
* clk : 0 - 166666666 Hz, 1 - 83333333 Hz, 2 - 41666666 Hz, 3 - 20833333 Hz, 4 - 10416666 Hz, 5 - 4000000 Hz
|
||||
* baud: 38400,...
|
||||
*/
|
||||
extern void Init_CPU_CLK_UART(int clkn, int baud);
|
||||
extern void sys_info(void);
|
||||
/* HalGetChipId:
|
||||
* 0xff - RTL8711AM, 0xfe - RTL8195AM, 0xfd - RTL8711AF,
|
||||
* 0xfc - RTL8710AF, 0xfb - RTL8711AN, 0xfa - RTL8710AM */
|
||||
extern unsigned char HalGetChipId(void);
|
||||
extern unsigned int HalGetCpuClk(void);
|
||||
|
||||
extern void wait_us(int us);
|
||||
#define delay_us wait_us
|
||||
|
||||
extern void yield(void);
|
||||
|
||||
extern uint32_t DiagPrintf(const char *fmt, ...);
|
||||
|
||||
extern int rtl_printf(const char *fmt, ...);
|
||||
extern int rtl_sprintf(char* str, const char* fmt, ...);
|
||||
|
||||
#ifndef printf
|
||||
#define printf rtl_printf
|
||||
#endif
|
||||
#ifndef sprintf
|
||||
#define sprintf rtl_sprintf
|
||||
#endif
|
||||
|
||||
/*
|
||||
extern void *pvPortMalloc( size_t xWantedSize );
|
||||
extern void vPortFree( void *pv );
|
||||
extern void *pvPortReAlloc( void *pv, size_t xWantedSize );
|
||||
extern size_t xPortGetFreeHeapSize( void );
|
||||
extern size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||
|
||||
extern void *tcm_heap_malloc(int size);
|
||||
extern void *tcm_heap_calloc(int size);
|
||||
extern void tcm_heap_free(void * mem);
|
||||
extern void tcm_heap_dump(void);
|
||||
extern int tcm_heap_freeSpace(void);
|
||||
|
||||
#ifndef malloc
|
||||
#define malloc pvPortMalloc
|
||||
#endif
|
||||
#ifndef free
|
||||
#define free vPortFree
|
||||
#endif
|
||||
#ifndef realloc
|
||||
#define realloc pvPortReAlloc
|
||||
#endif
|
||||
*/
|
||||
|
||||
/* sketch */
|
||||
extern void setup( void );
|
||||
extern void loop( void );
|
||||
|
||||
#define NOT_INITIAL (1UL<<0)
|
||||
#define PIO_GPIO (1UL<<1)
|
||||
#define PIO_PWM (1UL<<2)
|
||||
#define PIO_I2C (1UL<<3)
|
||||
#define PIO_ADC (1UL<<4)
|
||||
#define PIO_DAC (1UL<<5)
|
||||
#define PIO_GPIO_IRQ (1UL<<6)
|
||||
|
||||
#define PWM_MODE_ENABLED 1
|
||||
#define PWM_MODE_DISABLED 0
|
||||
|
||||
/* Types used for the tables below */
|
||||
typedef struct _PinDescription
|
||||
{
|
||||
|
||||
// HW PinNames
|
||||
uint32_t pinname;
|
||||
|
||||
// Current Pin Type
|
||||
uint32_t ulPinType;
|
||||
|
||||
// Supported Pin Function
|
||||
uint32_t ulPinAttribute;
|
||||
|
||||
// Current Pin Mode
|
||||
uint32_t ulPinMode;
|
||||
|
||||
} PinDescription ;
|
||||
|
||||
/* Pins table to be instanciated into variant.cpp */
|
||||
extern PinDescription g_APinDescription[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
#include "WCharacter.h"
|
||||
#include "WString.h"
|
||||
#include "WMath.h"
|
||||
#include "HardwareSerial.h"
|
||||
#include "wiring_pulse.h"
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
// Include board variant
|
||||
#include "variant.h"
|
||||
|
||||
#include "wiring.h"
|
||||
#include "wiring_digital.h"
|
||||
#include "wiring_analog.h"
|
||||
#include "WInterrupts.h"
|
||||
#include "wiring_os.h"
|
||||
#include "wiring_watchdog.h"
|
||||
#include "wiring_shift.h"
|
||||
|
||||
extern void * malloc(size_t size);
|
||||
extern void * zalloc(size_t size);
|
||||
extern void * calloc(size_t count, size_t size);
|
||||
extern void free(void *pv);
|
||||
extern void * realloc(void *pv, size_t size);
|
||||
extern void hexdump(void * ptr, int cnt);
|
||||
extern void debug_on(void);
|
||||
|
||||
extern unsigned int GetFlashSize(void); // default 1048576 bytes (1 Mbytes)
|
||||
/* FlashID: manufacturer ID : memory type : memory density
|
||||
0xC22015 - MXIC MX25L1606E, F11AMIM13 (RTL8711AM) module,
|
||||
0xC22014 - MXIC MX25L8006E, RTL00 (RTL8710AF) module */
|
||||
extern unsigned int GetFlashId(void);
|
||||
|
||||
// C++ functions
|
||||
#ifdef __cplusplus
|
||||
|
||||
// WMath prototypes
|
||||
extern long random( long ) ;
|
||||
extern long random( long, long ) ;
|
||||
extern void randomSeed( uint32_t dwSeed ) ;
|
||||
extern long map( long, long, long, long, long ) ;
|
||||
|
||||
void tone(uint32_t ulPin, unsigned int frequency, unsigned long duration = 0);
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// custom defined
|
||||
//
|
||||
|
||||
//#include "Thread.h"
|
||||
//#include "DAC1.h"
|
||||
|
||||
|
||||
#endif // Arduino_h
|
||||
45
arduino/realtek-ambz/cores/arduino/Client.h
Normal file
45
arduino/realtek-ambz/cores/arduino/Client.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Client.h - Base class that provides Client
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef client_h
|
||||
#define client_h
|
||||
#include "Print.h"
|
||||
#include "Stream.h"
|
||||
#include "IPAddress.h"
|
||||
|
||||
class Client : public Stream {
|
||||
|
||||
public:
|
||||
virtual int connect(IPAddress ip, uint16_t port) =0;
|
||||
virtual int connect(const char *host, uint16_t port) =0;
|
||||
virtual size_t write(uint8_t) =0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) =0;
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int read(uint8_t *buf, size_t size) = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual uint8_t connected() = 0;
|
||||
virtual operator bool() = 0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||
};
|
||||
|
||||
#endif
|
||||
8
arduino/realtek-ambz/cores/arduino/CountingStream.h
Normal file
8
arduino/realtek-ambz/cores/arduino/CountingStream.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <Print.h>
|
||||
|
||||
class CountingStream : public Print
|
||||
{
|
||||
virtual size_t write(uint8_t) { return 1; };
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) { return size; };
|
||||
};
|
||||
|
||||
198
arduino/realtek-ambz/cores/arduino/FunctionPointer.h
Normal file
198
arduino/realtek-ambz/cores/arduino/FunctionPointer.h
Normal file
@@ -0,0 +1,198 @@
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (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/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_FUNCTIONPOINTER_H
|
||||
#define MBED_FUNCTIONPOINTER_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* If we had variaditic templates, this wouldn't be a problem, but until C++11 is enabled, we are stuck with multiple classes... */
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member function
|
||||
*/
|
||||
template <typename R, typename A1>
|
||||
class FunctionPointerArg1{
|
||||
public:
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointerArg1(R (*function)(A1) = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointerArg1(T *object, R (T::*member)(A1)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The static function to attach (default is none)
|
||||
*/
|
||||
void attach(R (*function)(A1)) {
|
||||
_p.function = function;
|
||||
_membercaller = 0;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(A1)) {
|
||||
_p.object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(A1)>(_member) = member;
|
||||
_membercaller = &FunctionPointerArg1::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(A1 a) {
|
||||
if (_membercaller == 0 && _p.function) {
|
||||
return _p.function(a);
|
||||
} else if (_membercaller && _p.object) {
|
||||
return _membercaller(_p.object, _member, a);
|
||||
}
|
||||
return (R)0;
|
||||
}
|
||||
|
||||
/** Get registered static function
|
||||
*/
|
||||
R(*get_function(A1))() {
|
||||
return _membercaller ? (R(*)(A1))0 : (R(*)(A1))_p.function;
|
||||
}
|
||||
|
||||
R operator ()(A1 a) {
|
||||
return call(a);
|
||||
}
|
||||
operator bool(void) const {
|
||||
return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member, A1 a) {
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(A1) = reinterpret_cast<R (T::**)(A1)>(member);
|
||||
return (o->**m)(a);
|
||||
}
|
||||
|
||||
union {
|
||||
R (*function)(A1); // static function pointer
|
||||
void *object; // object this pointer
|
||||
} _p;
|
||||
uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
|
||||
R (*_membercaller)(void*, uintptr_t*, A1); // registered membercaller function to convert back and call _m.member on _object
|
||||
};
|
||||
|
||||
/** A class for storing and calling a pointer to a static or member function (R ()(void))
|
||||
*/
|
||||
template <typename R>
|
||||
class FunctionPointerArg1<R, void>{
|
||||
public:
|
||||
/** Create a FunctionPointer, attaching a static function
|
||||
*
|
||||
* @param function The static function to attach (default is none)
|
||||
*/
|
||||
FunctionPointerArg1(R (*function)(void) = 0) {
|
||||
attach(function);
|
||||
}
|
||||
|
||||
/** Create a FunctionPointer, attaching a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
FunctionPointerArg1(T *object, R (T::*member)(void)) {
|
||||
attach(object, member);
|
||||
}
|
||||
|
||||
/** Attach a static function
|
||||
*
|
||||
* @param function The void static function to attach (default is none)
|
||||
*/
|
||||
void attach(R (*function)(void)) {
|
||||
_p.function = function;
|
||||
_membercaller = 0;
|
||||
}
|
||||
|
||||
/** Attach a member function
|
||||
*
|
||||
* @param object The object pointer to invoke the member function on (i.e. the this pointer)
|
||||
* @param function The address of the void member function to attach
|
||||
*/
|
||||
template<typename T>
|
||||
void attach(T *object, R (T::*member)(void)) {
|
||||
_p.object = static_cast<void*>(object);
|
||||
*reinterpret_cast<R (T::**)(void)>(_member) = member;
|
||||
_membercaller = &FunctionPointerArg1::membercaller<T>;
|
||||
}
|
||||
|
||||
/** Call the attached static or member function
|
||||
*/
|
||||
R call(){
|
||||
if (_membercaller == 0 && _p.function) {
|
||||
return _p.function();
|
||||
} else if (_membercaller && _p.object) {
|
||||
return _membercaller(_p.object, _member);
|
||||
}
|
||||
return (R)0;
|
||||
}
|
||||
|
||||
/** Get registered static function
|
||||
*/
|
||||
R(*get_function())() {
|
||||
return _membercaller ? (R(*)())0 : (R(*)())_p.function;
|
||||
}
|
||||
|
||||
R operator ()(void) {
|
||||
return call();
|
||||
}
|
||||
operator bool(void) const {
|
||||
return (_membercaller != NULL ? _p.object : (void*)_p.function) != NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
static R membercaller(void *object, uintptr_t *member) {
|
||||
T* o = static_cast<T*>(object);
|
||||
R (T::**m)(void) = reinterpret_cast<R (T::**)(void)>(member);
|
||||
return (o->**m)();
|
||||
}
|
||||
|
||||
union {
|
||||
R (*function)(void); // static function pointer
|
||||
void *object; // object this pointer
|
||||
} _p;
|
||||
uintptr_t _member[4]; // aligned raw member function pointer storage - converted back by registered _membercaller
|
||||
R (*_membercaller)(void*, uintptr_t*); // registered membercaller function to convert back and call _m.member on _object
|
||||
};
|
||||
|
||||
typedef FunctionPointerArg1<void, void> FunctionPointer;
|
||||
typedef FunctionPointerArg1<void, int> event_callback_t;
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
42
arduino/realtek-ambz/cores/arduino/HardwareSerial.h
Normal file
42
arduino/realtek-ambz/cores/arduino/HardwareSerial.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef HardwareSerial_h
|
||||
#define HardwareSerial_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "Stream.h"
|
||||
|
||||
class HardwareSerial : public Stream
|
||||
{
|
||||
public:
|
||||
virtual void begin(unsigned long);
|
||||
virtual void end();
|
||||
virtual int available(void) = 0;
|
||||
virtual int peek(void) = 0;
|
||||
virtual int read(void) = 0;
|
||||
virtual void flush(void) = 0;
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||
virtual operator bool() = 0;
|
||||
};
|
||||
|
||||
extern void serialEventRun(void) __attribute__((weak));
|
||||
|
||||
#endif
|
||||
100
arduino/realtek-ambz/cores/arduino/IPAddress.cpp
Normal file
100
arduino/realtek-ambz/cores/arduino/IPAddress.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
IPAddress.cpp - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <IPAddress.h>
|
||||
#include <Print.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <WString.h>
|
||||
|
||||
//NeoJou
|
||||
extern "C" {
|
||||
#define _LONG_CALL_ __attribute__ ((long_call))
|
||||
extern _LONG_CALL_ uint32_t DiagPrintf(const char *fmt, ...);
|
||||
}
|
||||
|
||||
IPAddress::IPAddress()
|
||||
{
|
||||
_address.dword = 0;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||
{
|
||||
_address.bytes[0] = first_octet;
|
||||
_address.bytes[1] = second_octet;
|
||||
_address.bytes[2] = third_octet;
|
||||
_address.bytes[3] = fourth_octet;
|
||||
|
||||
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
}
|
||||
|
||||
IPAddress::IPAddress(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(uint32_t address)
|
||||
{
|
||||
_address.dword = address;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IPAddress::operator==(const uint8_t* addr) const
|
||||
{
|
||||
return memcmp(addr, _address.bytes, sizeof(_address.bytes)) == 0;
|
||||
}
|
||||
|
||||
char* IPAddress::get_address(void)
|
||||
{
|
||||
String ipAddrStr(_address.bytes[0]);
|
||||
ipAddrStr.concat('.');
|
||||
ipAddrStr.concat(_address.bytes[1]);
|
||||
ipAddrStr.concat('.');
|
||||
ipAddrStr.concat(_address.bytes[2]);
|
||||
ipAddrStr.concat('.');
|
||||
ipAddrStr.concat(_address.bytes[3]);
|
||||
ipAddrStr.toCharArray(_ipAddress, sizeof(_ipAddress));
|
||||
|
||||
return _ipAddress;
|
||||
}
|
||||
|
||||
size_t IPAddress::printTo(Print& p) const
|
||||
{
|
||||
size_t n = 0;
|
||||
for (int i =0; i < 3; i++)
|
||||
{
|
||||
n += p.print(_address.bytes[i], DEC);
|
||||
n += p.print('.');
|
||||
}
|
||||
n += p.print(_address.bytes[3], DEC);
|
||||
return n;
|
||||
}
|
||||
|
||||
79
arduino/realtek-ambz/cores/arduino/IPAddress.h
Normal file
79
arduino/realtek-ambz/cores/arduino/IPAddress.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
IPAddress.h - Base class that provides IPAddress
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef IPAddress_h
|
||||
#define IPAddress_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <Printable.h>
|
||||
|
||||
// A class to make it easier to handle and pass around IP addresses
|
||||
|
||||
class IPAddress : public Printable {
|
||||
private:
|
||||
char _ipAddress[17];
|
||||
union {
|
||||
uint8_t bytes[4]; // IPv4 address
|
||||
uint32_t dword;
|
||||
} _address;
|
||||
|
||||
// Access the raw byte array containing the address. Because this returns a pointer
|
||||
// to the internal structure rather than a copy of the address this function should only
|
||||
// be used when you know that the usage of the returned uint8_t* will be transient and not
|
||||
// stored.
|
||||
uint8_t* raw_address() { return _address.bytes; };
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
IPAddress();
|
||||
IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||
IPAddress(uint32_t address);
|
||||
IPAddress(const uint8_t *address);
|
||||
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const { return _address.dword; };
|
||||
bool operator==(const IPAddress& addr) const { return _address.dword == addr._address.dword; };
|
||||
bool operator==(const uint8_t* addr) const;
|
||||
|
||||
// Overloaded index operator to allow getting and setting individual octets of the address
|
||||
uint8_t operator[](int index) const { return _address.bytes[index]; };
|
||||
uint8_t& operator[](int index) { return _address.bytes[index]; };
|
||||
|
||||
// Overloaded copy operators to allow initialisation of IPAddress objects from other types
|
||||
IPAddress& operator=(const uint8_t *address);
|
||||
IPAddress& operator=(uint32_t address);
|
||||
|
||||
//NeoJou
|
||||
char * get_address(void);
|
||||
|
||||
virtual size_t printTo(Print& p) const;
|
||||
|
||||
friend class EthernetClass;
|
||||
friend class UDP;
|
||||
friend class Client;
|
||||
friend class Server;
|
||||
friend class DhcpClass;
|
||||
friend class DNSClient;
|
||||
};
|
||||
|
||||
const IPAddress INADDR_NONE(0,0,0,0);
|
||||
|
||||
|
||||
#endif
|
||||
156
arduino/realtek-ambz/cores/arduino/LOGUARTClass.cpp
Normal file
156
arduino/realtek-ambz/cores/arduino/LOGUARTClass.cpp
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "LOGUARTClass.h"
|
||||
|
||||
#define LOG_UART_MODIFIABLE_BAUD_RATE 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "log_uart_api.h"
|
||||
#include "hal_irqn.h"
|
||||
|
||||
log_uart_t log_uart_obj;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
RingBuffer rx_buffer0;
|
||||
|
||||
void arduino_loguart_irq_handler(uint32_t id, LOG_UART_INT_ID event)
|
||||
{
|
||||
char c;
|
||||
RingBuffer *pRxBuffer = (RingBuffer *)id;
|
||||
|
||||
if (event == IIR_RX_RDY || IIR_CHAR_TIMEOUT) {
|
||||
c = log_uart_getc(&log_uart_obj);
|
||||
pRxBuffer->store_char(c);
|
||||
}
|
||||
}
|
||||
|
||||
LOGUARTClass::LOGUARTClass(int dwIrq, RingBuffer* pRx_buffer )
|
||||
{
|
||||
_rx_buffer = pRx_buffer;
|
||||
_dwIrq = dwIrq;
|
||||
}
|
||||
|
||||
// Protected Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void LOGUARTClass::IrqHandler( void )
|
||||
{
|
||||
|
||||
uint8_t data = 0;
|
||||
BOOL PullMode = _FALSE;
|
||||
uint32_t IrqEn = DiagGetIsrEnReg();
|
||||
|
||||
DiagSetIsrEnReg(0);
|
||||
|
||||
data = DiagGetChar(PullMode);
|
||||
if ( data > 0 )
|
||||
_rx_buffer->store_char(data);
|
||||
|
||||
DiagSetIsrEnReg(IrqEn);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void LOGUARTClass::begin( const uint32_t dwBaudRate )
|
||||
{
|
||||
#if LOG_UART_MODIFIABLE_BAUD_RATE
|
||||
/* log uart initialize in 38400 baud rate.
|
||||
* If we change baud rate here, Serail Monitor would not detect this change and show nothing on screen.
|
||||
*/
|
||||
log_uart_init(&log_uart_obj, dwBaudRate, 8, ParityNone, 1);
|
||||
#else
|
||||
log_uart_init(&log_uart_obj, 38400, 8, ParityNone, 1);
|
||||
#endif
|
||||
log_uart_irq_set(&log_uart_obj, IIR_RX_RDY, 1);
|
||||
log_uart_irq_handler(&log_uart_obj, arduino_loguart_irq_handler, (uint32_t)_rx_buffer);
|
||||
}
|
||||
|
||||
void LOGUARTClass::end( void )
|
||||
{
|
||||
// clear any received data
|
||||
_rx_buffer->_iHead = _rx_buffer->_iTail ;
|
||||
|
||||
log_uart_free(&log_uart_obj);
|
||||
}
|
||||
|
||||
int LOGUARTClass::available( void )
|
||||
{
|
||||
return (uint32_t)(SERIAL_BUFFER_SIZE + _rx_buffer->_iHead - _rx_buffer->_iTail) % SERIAL_BUFFER_SIZE ;
|
||||
}
|
||||
|
||||
int LOGUARTClass::peek( void )
|
||||
{
|
||||
|
||||
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
|
||||
return -1 ;
|
||||
|
||||
return _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
|
||||
|
||||
}
|
||||
|
||||
int LOGUARTClass::read( void )
|
||||
{
|
||||
// if the head isn't ahead of the tail, we don't have any characters
|
||||
if ( _rx_buffer->_iHead == _rx_buffer->_iTail )
|
||||
return -1 ;
|
||||
|
||||
uint8_t uc = _rx_buffer->_aucBuffer[_rx_buffer->_iTail] ;
|
||||
_rx_buffer->_iTail = (unsigned int)(_rx_buffer->_iTail + 1) % SERIAL_BUFFER_SIZE ;
|
||||
return uc ;
|
||||
|
||||
}
|
||||
|
||||
void LOGUARTClass::flush( void )
|
||||
{
|
||||
// TODO:
|
||||
// while ( serial_writable(&(this->sobj)) != 1 );
|
||||
/*
|
||||
// Wait for transmission to complete
|
||||
while ((_pUart->UART_SR & UART_SR_TXRDY) != UART_SR_TXRDY)
|
||||
;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t LOGUARTClass::write( const uint8_t uc_data )
|
||||
{
|
||||
log_uart_putc(&log_uart_obj, uc_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOGUARTClass Serial(UART_LOG_IRQ, &rx_buffer0);
|
||||
|
||||
bool Serial_available() {
|
||||
return Serial.available() > 0;
|
||||
}
|
||||
58
arduino/realtek-ambz/cores/arduino/LOGUARTClass.h
Normal file
58
arduino/realtek-ambz/cores/arduino/LOGUARTClass.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _LOGUART_CLASS_
|
||||
#define _LOGUART_CLASS_
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
#include "RingBuffer.h"
|
||||
|
||||
class LOGUARTClass : public HardwareSerial
|
||||
{
|
||||
public:
|
||||
LOGUARTClass(int dwIrq, RingBuffer* pRx_buffer );
|
||||
|
||||
void begin(const uint32_t dwBaudRate);
|
||||
void end(void);
|
||||
int available(void);
|
||||
int peek(void);
|
||||
int read(void);
|
||||
void flush(void);
|
||||
size_t write(const uint8_t c);
|
||||
|
||||
|
||||
void IrqHandler(void);
|
||||
|
||||
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||
|
||||
operator bool() { return true; }; // UART always active
|
||||
|
||||
protected:
|
||||
void init(const uint32_t dwBaudRate, const uint32_t config);
|
||||
|
||||
RingBuffer *_rx_buffer;
|
||||
|
||||
int _dwIrq;
|
||||
|
||||
private:
|
||||
friend bool Serial_available();
|
||||
};
|
||||
|
||||
extern LOGUARTClass Serial;
|
||||
|
||||
#endif // _LOGUART_CLASS_
|
||||
66
arduino/realtek-ambz/cores/arduino/PowerManagement.cpp
Normal file
66
arduino/realtek-ambz/cores/arduino/PowerManagement.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "PowerManagement.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
#include "freertos_pmu.h"
|
||||
#include "sys_api.h"
|
||||
|
||||
#include "wiring_digital.h"
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "variant.h"
|
||||
|
||||
#if defined(BOARD_RTL8195A)
|
||||
#define SAVE_LOCK_PIN 18
|
||||
#elif defined(BOARD_RTL8710)
|
||||
#define SAVE_LOCK_PIN 7 // PB_1
|
||||
#else
|
||||
#define SAVE_LOCK_PIN 18
|
||||
#endif
|
||||
|
||||
bool PowerManagementClass::reservePLL = true;
|
||||
|
||||
void PowerManagementClass::setPllReserved(bool reserve) {
|
||||
pmu_set_pll_reserved(reserve);
|
||||
}
|
||||
|
||||
void PowerManagementClass::sleep(uint32_t bitflg) {
|
||||
if (!safeLock()) {
|
||||
pmu_release_wakelock(bitflg);
|
||||
}
|
||||
}
|
||||
|
||||
void PowerManagementClass::sleep(void) {
|
||||
if (!safeLock()) {
|
||||
pmu_release_wakelock(BIT(PMU_OS));
|
||||
}
|
||||
}
|
||||
|
||||
void PowerManagementClass::active(uint32_t bitflg) {
|
||||
pmu_acquire_wakelock(bitflg);
|
||||
}
|
||||
|
||||
void PowerManagementClass::active(void) {
|
||||
pmu_acquire_wakelock(BIT(PMU_OS));
|
||||
}
|
||||
|
||||
void PowerManagementClass::deepsleep(uint32_t duration_ms) {
|
||||
if (!safeLock()) {
|
||||
deepsleep_ex(DSLEEP_WAKEUP_BY_TIMER, duration_ms);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerManagementClass::safeLock() {
|
||||
pinMode(SAVE_LOCK_PIN, INPUT_PULLUP);
|
||||
return (digitalRead(SAVE_LOCK_PIN) == 1) ? false : true;
|
||||
}
|
||||
|
||||
void PowerManagementClass::softReset() {
|
||||
sys_reset();
|
||||
}
|
||||
|
||||
PowerManagementClass PowerManagement;
|
||||
|
||||
76
arduino/realtek-ambz/cores/arduino/PowerManagement.h
Normal file
76
arduino/realtek-ambz/cores/arduino/PowerManagement.h
Normal file
@@ -0,0 +1,76 @@
|
||||
#ifndef _POWER_MANAGEMENT_H_
|
||||
#define _POWER_MANAGEMENT_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/**
|
||||
* @class PowerManagementClass PowerManagement.h
|
||||
* @brief Power management in Ameba
|
||||
*/
|
||||
class PowerManagementClass {
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Allow OS automatically save power while idle
|
||||
*
|
||||
* As OS consider it would idle for more than 2s, it will invoke system suspend.
|
||||
* If wlan is associated with AP, than it will under asslociated idle state.
|
||||
*/
|
||||
static void sleep(void);
|
||||
static void sleep(uint32_t bitflg);
|
||||
|
||||
/**
|
||||
* @brief Disallow OS automatically save power while idle
|
||||
*/
|
||||
static void active(void);
|
||||
static void active(uint32_t bitflg);
|
||||
|
||||
/**
|
||||
* @brief Reserved PLL while sleep
|
||||
*
|
||||
* Reserve PLL would keep FIFO of peripherals (Ex. UART) but cost more power (around 5mA).
|
||||
* If we don't reserve PLL, it saves more power but we might missing data because FIFO is turned of this way.
|
||||
*
|
||||
* @param[in] reserve true for reserved, false for non-reserved
|
||||
*/
|
||||
static void setPllReserved(bool reserve);
|
||||
|
||||
/**
|
||||
* @brief Enter deepsleep immediately
|
||||
*
|
||||
* Invoke deepsleep would make system enter deepsleep state immediately.
|
||||
* It's the state that saves most power.
|
||||
* As it wakeup from deepsleep, the system would behave just like reboot.
|
||||
*
|
||||
* @param[in] duration_ms wakeup after specific time in unit of millisecond
|
||||
*/
|
||||
static void deepsleep(uint32_t duration_ms);
|
||||
|
||||
/**
|
||||
* @brief Check if system is allowed enter any power save state
|
||||
*
|
||||
* The pin 18 (GPIOE_5) is designed as safe lock.
|
||||
* If pin 18 is HIGH, then we prevent Ameba enter any power save state.\n\n
|
||||
* Under any power save state, we are not able to flash image to Ameba.
|
||||
* Thus if user misuse deepsleep and make Ameba enter deepsleep immediately after boot up,
|
||||
* then he would find it's hard to flash image.
|
||||
* In this case, he can pull up pin 18.
|
||||
*
|
||||
* @return true if system not allowed enter any power save state, and false vise versa
|
||||
*/
|
||||
static bool safeLock();
|
||||
|
||||
/**
|
||||
* @brief Reboot system
|
||||
*
|
||||
* Reboot system in soft way. Some registers is not powered off in this case, but mostly we could regard this as reboot.
|
||||
*/
|
||||
static void softReset();
|
||||
|
||||
private:
|
||||
static bool reservePLL;
|
||||
};
|
||||
|
||||
extern PowerManagementClass PowerManagement;
|
||||
|
||||
#endif
|
||||
257
arduino/realtek-ambz/cores/arduino/Print.cpp
Normal file
257
arduino/realtek-ambz/cores/arduino/Print.cpp
Normal file
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
Print.cpp - Base class that provides print() and println()
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 03 August 2015 by Chuck Todd
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
/* default implementation: may be overridden */
|
||||
size_t Print::write(const uint8_t *buffer, size_t size)
|
||||
{
|
||||
size_t n = 0;
|
||||
while (size--) {
|
||||
if (write(*buffer++)) n++;
|
||||
else break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
return print(reinterpret_cast<const char *>(ifsh));
|
||||
}
|
||||
|
||||
size_t Print::print(const String &s)
|
||||
{
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[])
|
||||
{
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(char c)
|
||||
{
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned char b, int base)
|
||||
{
|
||||
return print((unsigned long) b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base)
|
||||
{
|
||||
return print((long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base)
|
||||
{
|
||||
return print((unsigned long) n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base)
|
||||
{
|
||||
if (base == 0) {
|
||||
return write(n);
|
||||
} else if (base == 10) {
|
||||
if (n < 0) {
|
||||
int t = print('-');
|
||||
n = -n;
|
||||
return printNumber(n, 10) + t;
|
||||
}
|
||||
return printNumber(n, 10);
|
||||
} else {
|
||||
return printNumber(n, base);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base)
|
||||
{
|
||||
if (base == 0) return write(n);
|
||||
else return printNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits)
|
||||
{
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
size_t n = print(ifsh);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(const Printable& x)
|
||||
{
|
||||
return x.printTo(*this);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
{
|
||||
return write("\r\n");
|
||||
}
|
||||
|
||||
size_t Print::println(const String &s)
|
||||
{
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[])
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c)
|
||||
{
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned char b, int base)
|
||||
{
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long num, int base)
|
||||
{
|
||||
size_t n = print(num, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(double num, int digits)
|
||||
{
|
||||
size_t n = print(num, digits);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const Printable& x)
|
||||
{
|
||||
size_t n = print(x);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
// Private Methods /////////////////////////////////////////////////////////////
|
||||
|
||||
size_t Print::printNumber(unsigned long n, uint8_t base) {
|
||||
char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
|
||||
char *str = &buf[sizeof(buf) - 1];
|
||||
|
||||
*str = '\0';
|
||||
|
||||
// prevent crash if called with base == 1
|
||||
if (base < 2) base = 10;
|
||||
|
||||
do {
|
||||
unsigned long m = n;
|
||||
n /= base;
|
||||
char c = m - base * n;
|
||||
*--str = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
} while(n);
|
||||
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::printFloat(double number, uint8_t digits)
|
||||
{
|
||||
size_t n = 0;
|
||||
|
||||
if (isnan(number)) return print("nan");
|
||||
if (isinf(number)) return print("inf");
|
||||
if (number > 4294967040.0) return print ("ovf"); // constant determined empirically
|
||||
if (number <-4294967040.0) return print ("ovf"); // constant determined empirically
|
||||
|
||||
// Handle negative numbers
|
||||
if (number < 0.0)
|
||||
{
|
||||
n += print('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for (uint8_t i=0; i<digits; ++i)
|
||||
rounding /= 10.0;
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long)number;
|
||||
double remainder = number - (double)int_part;
|
||||
n += print(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0) {
|
||||
n += print(".");
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0)
|
||||
{
|
||||
remainder *= 10.0;
|
||||
int toPrint = int(remainder);
|
||||
n += print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
84
arduino/realtek-ambz/cores/arduino/Print.h
Normal file
84
arduino/realtek-ambz/cores/arduino/Print.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
Print.h - Base class that provides print() and println()
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Print_h
|
||||
#define Print_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h> // for size_t
|
||||
|
||||
#include "WString.h"
|
||||
#include "Printable.h"
|
||||
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
class Print
|
||||
{
|
||||
private:
|
||||
int write_error;
|
||||
size_t printNumber(unsigned long, uint8_t);
|
||||
size_t printFloat(double, uint8_t);
|
||||
protected:
|
||||
void setWriteError(int err = 1) { write_error = err; }
|
||||
public:
|
||||
Print() : write_error(0) {}
|
||||
|
||||
int getWriteError() { return write_error; }
|
||||
void clearWriteError() { setWriteError(0); }
|
||||
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
size_t write(const char *str) {
|
||||
if (str == NULL) return 0;
|
||||
return write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
virtual size_t write(const uint8_t *buffer, size_t size);
|
||||
size_t write(const char *buffer, size_t size) {
|
||||
return write((const uint8_t *)buffer, size);
|
||||
}
|
||||
|
||||
size_t print(const __FlashStringHelper *);
|
||||
size_t print(const String &);
|
||||
size_t print(const char[]);
|
||||
size_t print(char);
|
||||
size_t print(unsigned char, int = DEC);
|
||||
size_t print(int, int = DEC);
|
||||
size_t print(unsigned int, int = DEC);
|
||||
size_t print(long, int = DEC);
|
||||
size_t print(unsigned long, int = DEC);
|
||||
size_t print(double, int = 2);
|
||||
size_t print(const Printable&);
|
||||
|
||||
size_t println(const __FlashStringHelper *);
|
||||
size_t println(const String &s);
|
||||
size_t println(const char[]);
|
||||
size_t println(char);
|
||||
size_t println(unsigned char, int = DEC);
|
||||
size_t println(int, int = DEC);
|
||||
size_t println(unsigned int, int = DEC);
|
||||
size_t println(long, int = DEC);
|
||||
size_t println(unsigned long, int = DEC);
|
||||
size_t println(double, int = 2);
|
||||
size_t println(const Printable&);
|
||||
size_t println(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
40
arduino/realtek-ambz/cores/arduino/Printable.h
Normal file
40
arduino/realtek-ambz/cores/arduino/Printable.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Printable.h - Interface class that allows printing of complex types
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Printable_h
|
||||
#define Printable_h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
class Print;
|
||||
|
||||
/** The Printable class provides a way for new classes to allow themselves to be printed.
|
||||
By deriving from Printable and implementing the printTo method, it will then be possible
|
||||
for users to print out instances of this class by passing them into the usual
|
||||
Print::print and Print::println methods.
|
||||
*/
|
||||
|
||||
class Printable
|
||||
{
|
||||
public:
|
||||
virtual size_t printTo(Print& p) const = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
34
arduino/realtek-ambz/cores/arduino/Reset.h
Normal file
34
arduino/realtek-ambz/cores/arduino/Reset.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef RESET_H
|
||||
#define RESET_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void initiateReset(int ms);
|
||||
void tickReset();
|
||||
void cancelReset();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
43
arduino/realtek-ambz/cores/arduino/RingBuffer.cpp
Normal file
43
arduino/realtek-ambz/cores/arduino/RingBuffer.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include <string.h>
|
||||
|
||||
RingBuffer::RingBuffer( void )
|
||||
{
|
||||
memset( (void *)_aucBuffer, 0, SERIAL_BUFFER_SIZE ) ;
|
||||
_iHead=0 ;
|
||||
_iTail=0 ;
|
||||
}
|
||||
|
||||
void RingBuffer::store_char( uint8_t c )
|
||||
{
|
||||
int i = (uint32_t)(_iHead + 1) % SERIAL_BUFFER_SIZE ;
|
||||
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
if ( i != _iTail )
|
||||
{
|
||||
_aucBuffer[_iHead] = c ;
|
||||
_iHead = i ;
|
||||
}
|
||||
}
|
||||
|
||||
42
arduino/realtek-ambz/cores/arduino/RingBuffer.h
Normal file
42
arduino/realtek-ambz/cores/arduino/RingBuffer.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _RING_BUFFER_
|
||||
#define _RING_BUFFER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// Define constants and variables for buffering incoming serial data. We're
|
||||
// using a ring buffer (I think), in which head is the index of the location
|
||||
// to which to write the next incoming character and tail is the index of the
|
||||
// location from which to read.
|
||||
#define SERIAL_BUFFER_SIZE 128
|
||||
|
||||
class RingBuffer
|
||||
{
|
||||
public:
|
||||
volatile uint8_t _aucBuffer[SERIAL_BUFFER_SIZE] ;
|
||||
volatile int _iHead ;
|
||||
volatile int _iTail ;
|
||||
|
||||
public:
|
||||
RingBuffer( void ) ;
|
||||
void store_char( uint8_t c ) ;
|
||||
} ;
|
||||
|
||||
#endif /* _RING_BUFFER_ */
|
||||
30
arduino/realtek-ambz/cores/arduino/Server.h
Normal file
30
arduino/realtek-ambz/cores/arduino/Server.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Server.h - Base class that provides Server
|
||||
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef server_h
|
||||
#define server_h
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
class Server : public Print {
|
||||
public:
|
||||
virtual void begin() =0;
|
||||
};
|
||||
|
||||
#endif
|
||||
317
arduino/realtek-ambz/cores/arduino/Stream.cpp
Normal file
317
arduino/realtek-ambz/cores/arduino/Stream.cpp
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
Stream.cpp - adds parsing methods to Stream class
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Created July 2011
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
|
||||
findMulti/findUntil routines written by Jim Leonard/Xuth
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = read();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = peek();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit()
|
||||
{
|
||||
int c;
|
||||
while (1) {
|
||||
c = timedPeek();
|
||||
if (c < 0) return c; // timeout
|
||||
if (c == '-') return c;
|
||||
if (c >= '0' && c <= '9') return c;
|
||||
read(); // discard non-numeric
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(char *target)
|
||||
{
|
||||
return findUntil(target, strlen(target), NULL, 0);
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(char *target, size_t length)
|
||||
{
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(char *target, char *terminator)
|
||||
{
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||
{
|
||||
if (terminator == NULL) {
|
||||
MultiTarget t[1] = {{target, targetLen, 0}};
|
||||
return findMulti(t, 1) == 0 ? true : false;
|
||||
} else {
|
||||
MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}};
|
||||
return findMulti(t, 2) == 0 ? true : false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// function is terminated by the first character that is not a digit.
|
||||
long Stream::parseInt()
|
||||
{
|
||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||
}
|
||||
|
||||
// as above but a given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
long Stream::parseInt(char skipChar)
|
||||
{
|
||||
bool isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if(c == skipChar)
|
||||
; // ignore this charactor
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if(c >= '0' && c <= '9') // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || c == skipChar );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat()
|
||||
{
|
||||
return parseFloat(NO_SKIP_CHAR);
|
||||
}
|
||||
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
float Stream::parseFloat(char skipChar){
|
||||
bool isNegative = false;
|
||||
bool isFraction = false;
|
||||
long value = 0;
|
||||
char c;
|
||||
float fraction = 1.0;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if(c == skipChar)
|
||||
; // ignore
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if (c == '.')
|
||||
isFraction = true;
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
if(isFraction)
|
||||
fraction *= 0.1;
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || c == '.' || c == skipChar );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
if(isFraction)
|
||||
return value * fraction;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
// read characters from stream into buffer
|
||||
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0) break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// as readBytes with terminator character
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||
{
|
||||
if (length < 1) return 0;
|
||||
size_t index = 0;
|
||||
while (index < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0 || c == terminator) break;
|
||||
*buffer++ = (char)c;
|
||||
index++;
|
||||
}
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
String Stream::readString()
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Stream::readStringUntil(char terminator)
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0 && c != terminator)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||
// any zero length target string automatically matches and would make
|
||||
// a mess of the rest of the algorithm.
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
if (t->len <= 0)
|
||||
return t - targets;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
// the simple case is if we match, deal with that first.
|
||||
if (c == t->str[t->index]) {
|
||||
if (++t->index == t->len)
|
||||
return t - targets;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not we need to walk back and see if we could have matched further
|
||||
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||
// but it will match the second position so we can't just reset the current
|
||||
// index to 0 when we find a mismatch.
|
||||
if (t->index == 0)
|
||||
continue;
|
||||
|
||||
int origIndex = t->index;
|
||||
do {
|
||||
--t->index;
|
||||
// first check if current char works against the new current index
|
||||
if (c != t->str[t->index])
|
||||
continue;
|
||||
|
||||
// if it's the only char then we're good, nothing more to check
|
||||
if (t->index == 0) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we need to check the rest of the found string
|
||||
int diff = origIndex - t->index;
|
||||
size_t i;
|
||||
for (i = 0; i < t->index; ++i) {
|
||||
if (t->str[i] != t->str[i + diff])
|
||||
break;
|
||||
}
|
||||
|
||||
// if we successfully got through the previous loop then our current
|
||||
// index is good.
|
||||
if (i == t->index) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we just try the next index
|
||||
} while (t->index);
|
||||
}
|
||||
}
|
||||
// unreachable
|
||||
return -1;
|
||||
}
|
||||
112
arduino/realtek-ambz/cores/arduino/Stream.h
Normal file
112
arduino/realtek-ambz/cores/arduino/Stream.h
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
Stream.h - base class for character-based streams.
|
||||
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#ifndef Stream_h
|
||||
#define Stream_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
// compatability macros for testing
|
||||
/*
|
||||
#define getInt() parseInt()
|
||||
#define getInt(skipChar) parseInt(skipchar)
|
||||
#define getFloat() parseFloat()
|
||||
#define getFloat(skipChar) parseFloat(skipChar)
|
||||
#define getString( pre_string, post_string, buffer, length)
|
||||
readBytesBetween( pre_string, terminator, buffer, length)
|
||||
*/
|
||||
|
||||
class Stream : public Print
|
||||
{
|
||||
protected:
|
||||
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long _startMillis; // used for timeout measurement
|
||||
int timedRead(); // private method to read stream with timeout
|
||||
int timedPeek(); // private method to peek stream with timeout
|
||||
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
|
||||
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
Stream() {_timeout=1000;}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
|
||||
bool find(char *target); // reads data from the stream until the target string is found
|
||||
bool find(uint8_t *target) { return find ((char *)target); }
|
||||
// returns true if target string is found, false if timed out (see setTimeout)
|
||||
|
||||
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||
bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
|
||||
// returns true if target string is found, false if timed out
|
||||
|
||||
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
|
||||
|
||||
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
||||
|
||||
|
||||
long parseInt(); // returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// integer is terminated by the first character that is not a digit.
|
||||
|
||||
float parseFloat(); // float version of parseInt
|
||||
|
||||
virtual size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
||||
virtual size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
|
||||
// terminates if length characters have been read or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
String readString();
|
||||
String readStringUntil(char terminator);
|
||||
|
||||
protected:
|
||||
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
|
||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||
|
||||
struct MultiTarget {
|
||||
const char *str; // string you're searching for
|
||||
size_t len; // length of string you're searching for
|
||||
size_t index; // index used by the search routine.
|
||||
};
|
||||
|
||||
// This allows you to search for an arbitrary number of strings.
|
||||
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||
int findMulti(struct MultiTarget *targets, int tCount);
|
||||
};
|
||||
|
||||
#endif
|
||||
17
arduino/realtek-ambz/cores/arduino/Tone.cpp
Normal file
17
arduino/realtek-ambz/cores/arduino/Tone.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#if 1 // !defined(BOARD_RTL8710)
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
extern void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration);
|
||||
}
|
||||
#endif
|
||||
|
||||
// a wrapper that support default value of duration
|
||||
void tone(uint32_t ulPin, unsigned int frequency, unsigned long duration)
|
||||
{
|
||||
_tone(ulPin, frequency, duration);
|
||||
}
|
||||
|
||||
#endif
|
||||
88
arduino/realtek-ambz/cores/arduino/Udp.h
Normal file
88
arduino/realtek-ambz/cores/arduino/Udp.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Udp.cpp: Library to send/receive UDP packets.
|
||||
*
|
||||
* NOTE: UDP is fast, but has some important limitations (thanks to Warren Gray for mentioning these)
|
||||
* 1) UDP does not guarantee the order in which assembled UDP packets are received. This
|
||||
* might not happen often in practice, but in larger network topologies, a UDP
|
||||
* packet can be received out of sequence.
|
||||
* 2) UDP does not guard against lost packets - so packets *can* disappear without the sender being
|
||||
* aware of it. Again, this may not be a concern in practice on small local networks.
|
||||
* For more information, see http://www.cafeaulait.org/course/week12/35.html
|
||||
*
|
||||
* MIT License:
|
||||
* Copyright (c) 2008 Bjoern Hartmann
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* 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
|
||||
* AUTHORS 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 IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* bjoern@cs.stanford.edu 12/30/2008
|
||||
*/
|
||||
|
||||
#ifndef udp_h
|
||||
#define udp_h
|
||||
|
||||
#include <Stream.h>
|
||||
#include <IPAddress.h>
|
||||
|
||||
class UDP : public Stream {
|
||||
|
||||
public:
|
||||
virtual uint8_t begin(uint16_t) =0; // initialize, start listening on specified port. Returns 1 if successful, 0 if there are no sockets available to use
|
||||
virtual void stop() =0; // Finish with the UDP socket
|
||||
|
||||
// Sending UDP packets
|
||||
|
||||
// Start building up a packet to send to the remote host specific in ip and port
|
||||
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
|
||||
virtual int beginPacket(IPAddress ip, uint16_t port) =0;
|
||||
// Start building up a packet to send to the remote host specific in host and port
|
||||
// Returns 1 if successful, 0 if there was a problem resolving the hostname or port
|
||||
virtual int beginPacket(const char *host, uint16_t port) =0;
|
||||
// Finish off this packet and send it
|
||||
// Returns 1 if the packet was sent successfully, 0 if there was an error
|
||||
virtual int endPacket() =0;
|
||||
// Write a single byte into the packet
|
||||
virtual size_t write(uint8_t) =0;
|
||||
// Write size bytes from buffer into the packet
|
||||
virtual size_t write(const uint8_t *buffer, size_t size) =0;
|
||||
|
||||
// Start processing the next available incoming packet
|
||||
// Returns the size of the packet in bytes, or 0 if no packets are available
|
||||
virtual int parsePacket() =0;
|
||||
// Number of bytes remaining in the current packet
|
||||
virtual int available() =0;
|
||||
// Read a single byte from the current packet
|
||||
virtual int read() =0;
|
||||
// Read up to len bytes from the current packet and place them into buffer
|
||||
// Returns the number of bytes read, or 0 if none are available
|
||||
virtual int read(unsigned char* buffer, size_t len) =0;
|
||||
// Read up to len characters from the current packet and place them into buffer
|
||||
// Returns the number of characters read, or 0 if none are available
|
||||
virtual int read(char* buffer, size_t len) =0;
|
||||
// Return the next byte from the current packet without moving on to the next byte
|
||||
virtual int peek() =0;
|
||||
virtual void flush() =0; // Finish reading the current packet
|
||||
|
||||
// Return the IP address of the host who sent the current incoming packet
|
||||
virtual IPAddress remoteIP() =0;
|
||||
// Return the port of the host who sent the current incoming packet
|
||||
virtual uint16_t remotePort() =0;
|
||||
protected:
|
||||
uint8_t* rawIPAddress(IPAddress& addr) { return addr.raw_address(); };
|
||||
};
|
||||
|
||||
#endif
|
||||
180
arduino/realtek-ambz/cores/arduino/WCharacter.h
Normal file
180
arduino/realtek-ambz/cores/arduino/WCharacter.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
WCharacter.h - Character utility functions for Wiring & Arduino
|
||||
Copyright (c) 2010 Hernando Barragan. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Character_h
|
||||
#define Character_h
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// WCharacter.h prototypes
|
||||
#if defined ( __GNUC__ )
|
||||
inline boolean isAlphaNumeric(int c) __attribute__((always_inline));
|
||||
inline boolean isAlpha(int c) __attribute__((always_inline));
|
||||
inline boolean isAscii(int c) __attribute__((always_inline));
|
||||
inline boolean isWhitespace(int c) __attribute__((always_inline));
|
||||
inline boolean isControl(int c) __attribute__((always_inline));
|
||||
inline boolean isDigit(int c) __attribute__((always_inline));
|
||||
inline boolean isGraph(int c) __attribute__((always_inline));
|
||||
inline boolean isLowerCase(int c) __attribute__((always_inline));
|
||||
inline boolean isPrintable(int c) __attribute__((always_inline));
|
||||
inline boolean isPunct(int c) __attribute__((always_inline));
|
||||
inline boolean isSpace(int c) __attribute__((always_inline));
|
||||
inline boolean isUpperCase(int c) __attribute__((always_inline));
|
||||
inline boolean isHexadecimalDigit(int c) __attribute__((always_inline));
|
||||
inline int toAscii(int c) __attribute__((always_inline));
|
||||
inline int toLowerCase(int c) __attribute__((always_inline));
|
||||
inline int toUpperCase(int c)__attribute__((always_inline));
|
||||
#elif defined ( __ICCARM__ )
|
||||
#endif
|
||||
|
||||
// Checks for an alphanumeric character.
|
||||
// It is equivalent to (isalpha(c) || isdigit(c)).
|
||||
inline boolean isAlphaNumeric(int c)
|
||||
{
|
||||
return ( isalnum(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for an alphabetic character.
|
||||
// It is equivalent to (isupper(c) || islower(c)).
|
||||
inline boolean isAlpha(int c)
|
||||
{
|
||||
return ( isalpha(c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks whether c is a 7-bit unsigned char value
|
||||
// that fits into the ASCII character set.
|
||||
inline boolean isAscii(int c)
|
||||
{
|
||||
/* return ( isascii(c) == 0 ? false : true); */
|
||||
return ( (c & ~0x7f) != 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a blank character, that is, a space or a tab.
|
||||
inline boolean isWhitespace(int c)
|
||||
{
|
||||
return ( isblank (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a control character.
|
||||
inline boolean isControl(int c)
|
||||
{
|
||||
return ( iscntrl (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a digit (0 through 9).
|
||||
inline boolean isDigit(int c)
|
||||
{
|
||||
return ( isdigit (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character except space.
|
||||
inline boolean isGraph(int c)
|
||||
{
|
||||
return ( isgraph (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a lower-case character.
|
||||
inline boolean isLowerCase(int c)
|
||||
{
|
||||
return (islower (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character including space.
|
||||
inline boolean isPrintable(int c)
|
||||
{
|
||||
return ( isprint (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for any printable character which is not a space
|
||||
// or an alphanumeric character.
|
||||
inline boolean isPunct(int c)
|
||||
{
|
||||
return ( ispunct (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for white-space characters. For the avr-libc library,
|
||||
// these are: space, formfeed ('\f'), newline ('\n'), carriage
|
||||
// return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
|
||||
inline boolean isSpace(int c)
|
||||
{
|
||||
return ( isspace (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for an uppercase letter.
|
||||
inline boolean isUpperCase(int c)
|
||||
{
|
||||
return ( isupper (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Checks for a hexadecimal digits, i.e. one of 0 1 2 3 4 5 6 7
|
||||
// 8 9 a b c d e f A B C D E F.
|
||||
inline boolean isHexadecimalDigit(int c)
|
||||
{
|
||||
return ( isxdigit (c) == 0 ? false : true);
|
||||
}
|
||||
|
||||
|
||||
// Converts c to a 7-bit unsigned char value that fits into the
|
||||
// ASCII character set, by clearing the high-order bits.
|
||||
inline int toAscii(int c)
|
||||
{
|
||||
/* return toascii (c); */
|
||||
return (c & 0x7f);
|
||||
}
|
||||
|
||||
|
||||
// Warning:
|
||||
// Many people will be unhappy if you use this function.
|
||||
// This function will convert accented letters into random
|
||||
// characters.
|
||||
|
||||
// Converts the letter c to lower case, if possible.
|
||||
inline int toLowerCase(int c)
|
||||
{
|
||||
return tolower (c);
|
||||
}
|
||||
|
||||
|
||||
// Converts the letter c to upper case, if possible.
|
||||
inline int toUpperCase(int c)
|
||||
{
|
||||
return toupper (c);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
41
arduino/realtek-ambz/cores/arduino/WInterrupts.c
Normal file
41
arduino/realtek-ambz/cores/arduino/WInterrupts.c
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
#include "WInterrupts.h"
|
||||
|
||||
void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode) {
|
||||
if ( g_APinDescription[pin].ulPinType != PIO_GPIO_IRQ ) {
|
||||
pinRemoveMode(pin);
|
||||
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case LOW:
|
||||
pinMode(pin, INPUT_IRQ_LOW);
|
||||
digitalSetIrqHandler(pin, (void *)callback);
|
||||
break;
|
||||
|
||||
case HIGH:
|
||||
pinMode(pin, INPUT_IRQ_HIGH);
|
||||
digitalSetIrqHandler(pin, (void *)callback);
|
||||
break;
|
||||
|
||||
case FALLING:
|
||||
pinMode(pin, INPUT_IRQ_FALL);
|
||||
digitalSetIrqHandler(pin, (void *)callback);
|
||||
break;
|
||||
|
||||
case RISING:
|
||||
pinMode(pin, INPUT_IRQ_RISE);
|
||||
digitalSetIrqHandler(pin, (void *)callback);
|
||||
break;
|
||||
|
||||
case CHANGE:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void detachInterrupt(uint32_t pin) {
|
||||
if ( g_APinDescription[pin].ulPinType == PIO_GPIO_IRQ ) {
|
||||
pinRemoveMode(pin);
|
||||
}
|
||||
}
|
||||
36
arduino/realtek-ambz/cores/arduino/WInterrupts.h
Normal file
36
arduino/realtek-ambz/cores/arduino/WInterrupts.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2011-2012 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_INTERRUPTS_
|
||||
#define _WIRING_INTERRUPTS_
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void attachInterrupt(uint32_t pin, void (*callback)(void), uint32_t mode);
|
||||
|
||||
extern void detachInterrupt(uint32_t pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIRING_INTERRUPTS_ */
|
||||
77
arduino/realtek-ambz/cores/arduino/WMath.cpp
Normal file
77
arduino/realtek-ambz/cores/arduino/WMath.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "WMath.h"
|
||||
|
||||
extern "C" {
|
||||
extern void rtl_srandom( uint32_t seed );
|
||||
extern uint32_t rtl_random( void );
|
||||
}
|
||||
|
||||
#ifndef srand
|
||||
#define srand rtl_srandom
|
||||
#endif
|
||||
#ifndef rand
|
||||
#define rand rtl_random
|
||||
#endif
|
||||
|
||||
extern void randomSeed( uint32_t dwSeed )
|
||||
{
|
||||
if ( dwSeed != 0 )
|
||||
{
|
||||
srand( dwSeed ) ;
|
||||
}
|
||||
}
|
||||
|
||||
extern long random( long howbig )
|
||||
{
|
||||
if ( howbig == 0 )
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
return rand() % howbig;
|
||||
}
|
||||
|
||||
extern long random( long howsmall, long howbig )
|
||||
{
|
||||
if (howsmall >= howbig)
|
||||
{
|
||||
return howsmall;
|
||||
}
|
||||
|
||||
long diff = howbig - howsmall;
|
||||
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
||||
extern long map(long x, long in_min, long in_max, long out_min, long out_max)
|
||||
{
|
||||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||||
}
|
||||
|
||||
extern uint16_t makeWord( uint16_t w )
|
||||
{
|
||||
return w ;
|
||||
}
|
||||
|
||||
extern uint16_t makeWord( uint8_t h, uint8_t l )
|
||||
{
|
||||
return (h << 8) | l ;
|
||||
}
|
||||
33
arduino/realtek-ambz/cores/arduino/WMath.h
Normal file
33
arduino/realtek-ambz/cores/arduino/WMath.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_MATH_
|
||||
#define _WIRING_MATH_
|
||||
|
||||
extern long random( long ) ;
|
||||
extern long random( long, long ) ;
|
||||
extern void randomSeed( uint32_t dwSeed ) ;
|
||||
extern long map( long, long, long, long, long ) ;
|
||||
|
||||
extern uint16_t makeWord( uint16_t w ) ;
|
||||
extern uint16_t makeWord( uint8_t h, uint8_t l ) ;
|
||||
|
||||
#define word(...) makeWord(__VA_ARGS__)
|
||||
|
||||
|
||||
#endif /* _WIRING_MATH_ */
|
||||
748
arduino/realtek-ambz/cores/arduino/WString.cpp
Normal file
748
arduino/realtek-ambz/cores/arduino/WString.cpp
Normal file
@@ -0,0 +1,748 @@
|
||||
/*
|
||||
WString.cpp - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "WString.h"
|
||||
#include "itoa.h"
|
||||
#include "avr/dtostrf.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Constructors */
|
||||
/*********************************************/
|
||||
|
||||
String::String(const char *cstr)
|
||||
{
|
||||
init();
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
String::String(const String &value)
|
||||
{
|
||||
init();
|
||||
*this = value;
|
||||
}
|
||||
|
||||
String::String(const __FlashStringHelper *pstr)
|
||||
{
|
||||
init();
|
||||
*this = pstr;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String::String(String &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
String::String(StringSumHelper &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
String::String(char c)
|
||||
{
|
||||
init();
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned char value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned char)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(int)];
|
||||
itoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned int)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(long)];
|
||||
ltoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned long)];
|
||||
ultoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(float value, unsigned char decimalPlaces)
|
||||
{
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::String(double value, unsigned char decimalPlaces)
|
||||
{
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Memory Management */
|
||||
/*********************************************/
|
||||
|
||||
inline void String::init(void)
|
||||
{
|
||||
buffer = NULL;
|
||||
capacity = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void String::invalidate(void)
|
||||
{
|
||||
if (buffer) free(buffer);
|
||||
buffer = NULL;
|
||||
capacity = len = 0;
|
||||
}
|
||||
|
||||
unsigned char String::reserve(unsigned int size)
|
||||
{
|
||||
if (buffer && capacity >= size) return 1;
|
||||
if (changeBuffer(size)) {
|
||||
if (len == 0) buffer[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
||||
{
|
||||
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
||||
if (newbuffer) {
|
||||
buffer = newbuffer;
|
||||
capacity = maxStrLen;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Copy and Move */
|
||||
/*********************************************/
|
||||
|
||||
String & String::copy(const char *cstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy(buffer, cstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy_P(buffer, (PGM_P)pstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
void String::move(String &rhs)
|
||||
{
|
||||
if (buffer) {
|
||||
if (capacity >= rhs.len) {
|
||||
strcpy(buffer, rhs.buffer);
|
||||
len = rhs.len;
|
||||
rhs.len = 0;
|
||||
return;
|
||||
} else {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
buffer = rhs.buffer;
|
||||
capacity = rhs.capacity;
|
||||
len = rhs.len;
|
||||
rhs.buffer = NULL;
|
||||
rhs.capacity = 0;
|
||||
rhs.len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const String &rhs)
|
||||
{
|
||||
if (this == &rhs) return *this;
|
||||
|
||||
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String & String::operator = (String &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (StringSumHelper &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const char *cstr)
|
||||
{
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (const __FlashStringHelper *pstr)
|
||||
{
|
||||
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* concat */
|
||||
/*********************************************/
|
||||
|
||||
unsigned char String::concat(const String &s)
|
||||
{
|
||||
return concat(s.buffer, s.len);
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr, unsigned int length)
|
||||
{
|
||||
unsigned int newlen = len + length;
|
||||
if (!cstr) return 0;
|
||||
if (length == 0) return 1;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy(buffer + len, cstr);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr)
|
||||
{
|
||||
if (!cstr) return 0;
|
||||
return concat(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
unsigned char String::concat(char c)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
return concat(buf, 1);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned char num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned char)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(int num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(int)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned int num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned int)];
|
||||
utoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(long num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(long)];
|
||||
ltoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned long num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned long)];
|
||||
ultoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(float num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(double num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(const __FlashStringHelper * str)
|
||||
{
|
||||
if (!str) return 0;
|
||||
int length = strlen_P((const char *) str);
|
||||
if (length == 0) return 1;
|
||||
unsigned int newlen = len + length;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy_P(buffer + len, (const char *) str);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Concatenate */
|
||||
/*********************************************/
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(c)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Comparison */
|
||||
/*********************************************/
|
||||
|
||||
int String::compareTo(const String &s) const
|
||||
{
|
||||
if (!buffer || !s.buffer) {
|
||||
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
||||
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||
return 0;
|
||||
}
|
||||
return strcmp(buffer, s.buffer);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const String &s2) const
|
||||
{
|
||||
return (len == s2.len && compareTo(s2) == 0);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const char *cstr) const
|
||||
{
|
||||
if (len == 0) return (cstr == NULL || *cstr == 0);
|
||||
if (cstr == NULL) return buffer[0] == 0;
|
||||
return strcmp(buffer, cstr) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) < 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) > 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<=(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) <= 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>=(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) >= 0;
|
||||
}
|
||||
|
||||
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
||||
{
|
||||
if (this == &s2) return 1;
|
||||
if (len != s2.len) return 0;
|
||||
if (len == 0) return 1;
|
||||
const char *p1 = buffer;
|
||||
const char *p2 = s2.buffer;
|
||||
while (*p1) {
|
||||
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2 ) const
|
||||
{
|
||||
if (len < s2.len) return 0;
|
||||
return startsWith(s2, 0);
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
||||
{
|
||||
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::endsWith( const String &s2 ) const
|
||||
{
|
||||
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Character Access */
|
||||
/*********************************************/
|
||||
|
||||
char String::charAt(unsigned int loc) const
|
||||
{
|
||||
return operator[](loc);
|
||||
}
|
||||
|
||||
void String::setCharAt(unsigned int loc, char c)
|
||||
{
|
||||
if (loc < len) buffer[loc] = c;
|
||||
}
|
||||
|
||||
char & String::operator[](unsigned int index)
|
||||
{
|
||||
static char dummy_writable_char;
|
||||
if (index >= len || !buffer) {
|
||||
dummy_writable_char = 0;
|
||||
return dummy_writable_char;
|
||||
}
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
char String::operator[]( unsigned int index ) const
|
||||
{
|
||||
if (index >= len || !buffer) return 0;
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
||||
{
|
||||
if (!bufsize || !buf) return;
|
||||
if (index >= len) {
|
||||
buf[0] = 0;
|
||||
return;
|
||||
}
|
||||
unsigned int n = bufsize - 1;
|
||||
if (n > len - index) n = len - index;
|
||||
strncpy((char *)buf, buffer + index, n);
|
||||
buf[n] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Search */
|
||||
/*********************************************/
|
||||
|
||||
int String::indexOf(char c) const
|
||||
{
|
||||
return indexOf(c, 0);
|
||||
}
|
||||
|
||||
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char* temp = strchr(buffer + fromIndex, ch);
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2) const
|
||||
{
|
||||
return indexOf(s2, 0);
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
||||
if (found == NULL) return -1;
|
||||
return found - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf( char theChar ) const
|
||||
{
|
||||
return lastIndexOf(theChar, len - 1);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
char tempchar = buffer[fromIndex + 1];
|
||||
buffer[fromIndex + 1] = '\0';
|
||||
char* temp = strrchr( buffer, ch );
|
||||
buffer[fromIndex + 1] = tempchar;
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2) const
|
||||
{
|
||||
return lastIndexOf(s2, len - s2.len);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
||||
if (fromIndex >= len) fromIndex = len - 1;
|
||||
int found = -1;
|
||||
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
||||
p = strstr(p, s2.buffer);
|
||||
if (!p) break;
|
||||
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
String String::substring(unsigned int left, unsigned int right) const
|
||||
{
|
||||
if (left > right) {
|
||||
unsigned int temp = right;
|
||||
right = left;
|
||||
left = temp;
|
||||
}
|
||||
String out;
|
||||
if (left >= len) return out;
|
||||
if (right > len) right = len;
|
||||
char temp = buffer[right]; // save the replaced character
|
||||
buffer[right] = '\0';
|
||||
out = buffer + left; // pointer arithmetic
|
||||
buffer[right] = temp; //restore character
|
||||
return out;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Modification */
|
||||
/*********************************************/
|
||||
|
||||
void String::replace(char find, char replace)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
if (*p == find) *p = replace;
|
||||
}
|
||||
}
|
||||
|
||||
void String::replace(const String& find, const String& replace)
|
||||
{
|
||||
if (len == 0 || find.len == 0) return;
|
||||
int diff = replace.len - find.len;
|
||||
char *readFrom = buffer;
|
||||
char *foundAt;
|
||||
if (diff == 0) {
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
memcpy(foundAt, replace.buffer, replace.len);
|
||||
readFrom = foundAt + replace.len;
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
char *writeTo = buffer;
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
unsigned int n = foundAt - readFrom;
|
||||
memcpy(writeTo, readFrom, n);
|
||||
writeTo += n;
|
||||
memcpy(writeTo, replace.buffer, replace.len);
|
||||
writeTo += replace.len;
|
||||
readFrom = foundAt + find.len;
|
||||
len += diff;
|
||||
}
|
||||
strcpy(writeTo, readFrom);
|
||||
} else {
|
||||
unsigned int size = len; // compute size needed for result
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
readFrom = foundAt + find.len;
|
||||
size += diff;
|
||||
}
|
||||
if (size == len) return;
|
||||
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
|
||||
int index = len - 1;
|
||||
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||
readFrom = buffer + index + find.len;
|
||||
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
||||
len += diff;
|
||||
buffer[len] = 0;
|
||||
memcpy(buffer + index, replace.buffer, replace.len);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index){
|
||||
// Pass the biggest integer as the count. The remove method
|
||||
// below will take care of truncating it at the end of the
|
||||
// string.
|
||||
remove(index, (unsigned int)-1);
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index, unsigned int count){
|
||||
if (index >= len) { return; }
|
||||
if (count <= 0) { return; }
|
||||
if (count > len - index) { count = len - index; }
|
||||
char *writeTo = buffer + index;
|
||||
len = len - count;
|
||||
strncpy(writeTo, buffer + index + count,len - index);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
void String::toLowerCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::toUpperCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::trim(void)
|
||||
{
|
||||
if (!buffer || len == 0) return;
|
||||
char *begin = buffer;
|
||||
while (isspace(*begin)) begin++;
|
||||
char *end = buffer + len - 1;
|
||||
while (isspace(*end) && end >= begin) end--;
|
||||
len = end + 1 - begin;
|
||||
if (begin > buffer) memcpy(buffer, begin, len);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Parsing / Conversion */
|
||||
/*********************************************/
|
||||
|
||||
long String::toInt(void) const
|
||||
{
|
||||
if (buffer) return atol(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float String::toFloat(void) const
|
||||
{
|
||||
if (buffer) return float(atof(buffer));
|
||||
return 0;
|
||||
}
|
||||
224
arduino/realtek-ambz/cores/arduino/WString.h
Normal file
224
arduino/realtek-ambz/cores/arduino/WString.h
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
WString.h - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef String_class_h
|
||||
#define String_class_h
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// When compiling programs with this class, the following gcc parameters
|
||||
// dramatically increase performance and memory (RAM) efficiency, typically
|
||||
// with little or no increase in code size.
|
||||
// -felide-constructors
|
||||
// -std=c++0x
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
|
||||
// An inherited class for holding the result of a concatenation. These
|
||||
// result objects are assumed to be writable by subsequent concatenations.
|
||||
class StringSumHelper;
|
||||
|
||||
// The string class
|
||||
class String
|
||||
{
|
||||
// use a function pointer to allow for "if (s)" without the
|
||||
// complications of an operator bool(). for more information, see:
|
||||
// http://www.artima.com/cppsource/safebool.html
|
||||
typedef void (String::*StringIfHelperType)() const;
|
||||
void StringIfHelper() const {}
|
||||
|
||||
public:
|
||||
// constructors
|
||||
// creates a copy of the initial value.
|
||||
// if the initial value is null or invalid, or if memory allocation
|
||||
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||
// be false).
|
||||
String(const char *cstr = "");
|
||||
String(const String &str);
|
||||
String(const __FlashStringHelper *str);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String(String &&rval);
|
||||
String(StringSumHelper &&rval);
|
||||
#endif
|
||||
explicit String(char c);
|
||||
explicit String(unsigned char, unsigned char base=10);
|
||||
explicit String(int, unsigned char base=10);
|
||||
explicit String(unsigned int, unsigned char base=10);
|
||||
explicit String(long, unsigned char base=10);
|
||||
explicit String(unsigned long, unsigned char base=10);
|
||||
explicit String(float, unsigned char decimalPlaces=2);
|
||||
explicit String(double, unsigned char decimalPlaces=2);
|
||||
~String(void);
|
||||
|
||||
// memory management
|
||||
// return true on success, false on failure (in which case, the string
|
||||
// is left unchanged). reserve(0), if successful, will validate an
|
||||
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||
unsigned char reserve(unsigned int size);
|
||||
inline unsigned int length(void) const {return len;}
|
||||
|
||||
// creates a copy of the assigned value. if the value is null or
|
||||
// invalid, or if the memory allocation fails, the string will be
|
||||
// marked as invalid ("if (s)" will be false).
|
||||
String & operator = (const String &rhs);
|
||||
String & operator = (const char *cstr);
|
||||
String & operator = (const __FlashStringHelper *str);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
String & operator = (String &&rval);
|
||||
String & operator = (StringSumHelper &&rval);
|
||||
#endif
|
||||
|
||||
// concatenate (works w/ built-in types)
|
||||
|
||||
// returns true on success, false on failure (in which case, the string
|
||||
// is left unchanged). if the argument is null or invalid, the
|
||||
// concatenation is considered unsucessful.
|
||||
unsigned char concat(const String &str);
|
||||
unsigned char concat(const char *cstr);
|
||||
unsigned char concat(char c);
|
||||
unsigned char concat(unsigned char c);
|
||||
unsigned char concat(int num);
|
||||
unsigned char concat(unsigned int num);
|
||||
unsigned char concat(long num);
|
||||
unsigned char concat(unsigned long num);
|
||||
unsigned char concat(float num);
|
||||
unsigned char concat(double num);
|
||||
unsigned char concat(const __FlashStringHelper * str);
|
||||
|
||||
// if there's not enough memory for the concatenated value, the string
|
||||
// will be left unchanged (but this isn't signalled in any way)
|
||||
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
||||
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
||||
String & operator += (char c) {concat(c); return (*this);}
|
||||
String & operator += (unsigned char num) {concat(num); return (*this);}
|
||||
String & operator += (int num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned int num) {concat(num); return (*this);}
|
||||
String & operator += (long num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned long num) {concat(num); return (*this);}
|
||||
String & operator += (float num) {concat(num); return (*this);}
|
||||
String & operator += (double num) {concat(num); return (*this);}
|
||||
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
||||
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||
|
||||
// comparison (only works w/ Strings and "strings")
|
||||
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
||||
int compareTo(const String &s) const;
|
||||
unsigned char equals(const String &s) const;
|
||||
unsigned char equals(const char *cstr) const;
|
||||
unsigned char operator == (const String &rhs) const {return equals(rhs);}
|
||||
unsigned char operator == (const char *cstr) const {return equals(cstr);}
|
||||
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
|
||||
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
|
||||
unsigned char operator < (const String &rhs) const;
|
||||
unsigned char operator > (const String &rhs) const;
|
||||
unsigned char operator <= (const String &rhs) const;
|
||||
unsigned char operator >= (const String &rhs) const;
|
||||
unsigned char equalsIgnoreCase(const String &s) const;
|
||||
unsigned char startsWith( const String &prefix) const;
|
||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||
unsigned char endsWith(const String &suffix) const;
|
||||
|
||||
// character acccess
|
||||
char charAt(unsigned int index) const;
|
||||
void setCharAt(unsigned int index, char c);
|
||||
char operator [] (unsigned int index) const;
|
||||
char& operator [] (unsigned int index);
|
||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
||||
{getBytes((unsigned char *)buf, bufsize, index);}
|
||||
const char * c_str() const { return buffer; }
|
||||
|
||||
// search
|
||||
int indexOf( char ch ) const;
|
||||
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||
int indexOf( const String &str ) const;
|
||||
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( char ch ) const;
|
||||
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( const String &str ) const;
|
||||
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
||||
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||
|
||||
// modification
|
||||
void replace(char find, char replace);
|
||||
void replace(const String& find, const String& replace);
|
||||
void remove(unsigned int index);
|
||||
void remove(unsigned int index, unsigned int count);
|
||||
void toLowerCase(void);
|
||||
void toUpperCase(void);
|
||||
void trim(void);
|
||||
|
||||
// parsing/conversion
|
||||
long toInt(void) const;
|
||||
float toFloat(void) const;
|
||||
|
||||
protected:
|
||||
char *buffer; // the actual char array
|
||||
unsigned int capacity; // the array length minus one (for the '\0')
|
||||
unsigned int len; // the String length (not counting the '\0')
|
||||
protected:
|
||||
void init(void);
|
||||
void invalidate(void);
|
||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||
unsigned char concat(const char *cstr, unsigned int length);
|
||||
|
||||
// copy and move
|
||||
String & copy(const char *cstr, unsigned int length);
|
||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||
#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
|
||||
void move(String &rhs);
|
||||
#endif
|
||||
};
|
||||
|
||||
class StringSumHelper : public String
|
||||
{
|
||||
public:
|
||||
StringSumHelper(const String &s) : String(s) {}
|
||||
StringSumHelper(const char *p) : String(p) {}
|
||||
StringSumHelper(char c) : String(c) {}
|
||||
StringSumHelper(unsigned char num) : String(num) {}
|
||||
StringSumHelper(int num) : String(num) {}
|
||||
StringSumHelper(unsigned int num) : String(num) {}
|
||||
StringSumHelper(long num) : String(num) {}
|
||||
StringSumHelper(unsigned long num) : String(num) {}
|
||||
StringSumHelper(float num) : String(num) {}
|
||||
StringSumHelper(double num) : String(num) {}
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // String_class_h
|
||||
100
arduino/realtek-ambz/cores/arduino/WebSocketClient.cpp
Normal file
100
arduino/realtek-ambz/cores/arduino/WebSocketClient.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* WebSocketClient + SSL/TSL
|
||||
* RTL8710AF pvvx 12/12/2016
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "WebSocketClient.h"
|
||||
|
||||
WebSocketClient::WebSocketClient() {
|
||||
}
|
||||
|
||||
WebSocketClient::WebSocketClient(char *url, int port, char *path, char* origin) {
|
||||
client = create_wsclient(url, port, path, origin);
|
||||
}
|
||||
|
||||
WebSocketClient::~WebSocketClient() {
|
||||
close();
|
||||
}
|
||||
|
||||
int WebSocketClient::begin(char *url, int port, char *path, char* origin) {
|
||||
client = create_wsclient(url, port, path, origin);
|
||||
if(client != NULL) return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int WebSocketClient::connect() {
|
||||
if(client != NULL) return ws_connect_url(client);
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void WebSocketClient::send(char* message, int message_len, int use_mask) {
|
||||
if(client != NULL && client->readyState > CLOSED) {
|
||||
ws_send(message, message_len, use_mask, client);
|
||||
ws_poll(0, client);
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketClient::sendBinary(uint8_t* message, int message_len, int use_mask) {
|
||||
if(client != NULL && client->readyState > CLOSED) {
|
||||
ws_sendBinary(message, message_len, use_mask, client);
|
||||
ws_poll(0, client);
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketClient::sendPing() {
|
||||
if(client != NULL && client->readyState > CLOSED) {
|
||||
ws_sendPing(client);
|
||||
ws_poll(0, client);
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketClient::poll(int timeout) {
|
||||
if(client != NULL) ws_poll(timeout, client);
|
||||
}
|
||||
|
||||
readyStateValues WebSocketClient::getReadyState() {
|
||||
if(client != NULL) return ws_getReadyState(client);
|
||||
else return CLOSED;
|
||||
}
|
||||
|
||||
void WebSocketClient::dispatch(void (*callback)(wsclient_context *, int))
|
||||
{
|
||||
if(client != NULL) ws_dispatch(callback);
|
||||
}
|
||||
|
||||
void WebSocketClient::close() {
|
||||
if(client != NULL) {
|
||||
ws_close(client);
|
||||
if(client->ssl) {
|
||||
free(client->ssl);
|
||||
client->ssl = NULL;
|
||||
}
|
||||
client = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void set_ssl_func(wsclient_context *wsclient); // in example_wsclient.c
|
||||
|
||||
void WebSocketClient::ssl_func_on(void)
|
||||
{
|
||||
set_ssl_func(client);
|
||||
/*
|
||||
client->fun_ops.ssl_fun_ops.memory_set_own = memory_set_own;
|
||||
client->fun_ops.ssl_fun_ops.net_connect = net_connect;
|
||||
client->fun_ops.ssl_fun_ops.ssl_init = ssl_init;
|
||||
client->fun_ops.ssl_fun_ops.ssl_set_endpoint = ssl_set_endpoint;
|
||||
client->fun_ops.ssl_fun_ops.ssl_set_authmode = ssl_set_authmode;
|
||||
client->fun_ops.ssl_fun_ops.ssl_set_rng = ssl_set_rng;
|
||||
client->fun_ops.ssl_fun_ops.ssl_set_bio = ssl_set_bio;
|
||||
client->fun_ops.ssl_fun_ops.ssl_handshake = ssl_handshake;
|
||||
client->fun_ops.ssl_fun_ops.net_close = net_close;
|
||||
client->fun_ops.ssl_fun_ops.ssl_free = ssl_free;
|
||||
client->fun_ops.ssl_fun_ops.ssl_read = ssl_read;
|
||||
client->fun_ops.ssl_fun_ops.ssl_write = ssl_write;
|
||||
client->fun_ops.ssl_fun_ops.net_recv = net_recv;
|
||||
client->fun_ops.ssl_fun_ops.net_send = net_send;
|
||||
client->ssl = (void *)zalloc(sizeof(struct _ssl_context)); // 380 bytes
|
||||
*/
|
||||
}
|
||||
117
arduino/realtek-ambz/cores/arduino/WebSocketClient.h
Normal file
117
arduino/realtek-ambz/cores/arduino/WebSocketClient.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* WebSocketClient + SSL/TSL
|
||||
* RTL8710AF pvvx 12/12/2016
|
||||
*
|
||||
*/
|
||||
#ifndef WEBSOCKETCLIENT_H_
|
||||
#define WEBSOCKETCLIENT_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Stream.h>
|
||||
extern "C" {
|
||||
#include "libwsclient.h"
|
||||
#include "wsclient_api.h"
|
||||
}
|
||||
|
||||
class WebSocketClient {
|
||||
public:
|
||||
WebSocketClient();
|
||||
~WebSocketClient();
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : begin
|
||||
** Description : Creating the websocket client context structure
|
||||
** Input : url:websocket server's url
|
||||
** port:websocket server's port, if not given, default 80 for "ws", 443 for "wss"
|
||||
** origin: the address or url of your self
|
||||
** Return : Ok: 1
|
||||
** Failed: 0
|
||||
**************************************************************************************************/
|
||||
WebSocketClient(char *url, int port, char *path = NULL, char* origin = NULL);
|
||||
int begin(char *url, int port, char *path = NULL, char* origin = NULL);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : connect
|
||||
** Description : Connecting to the websocket server
|
||||
** Input : wsclient: the websocket client context created by create_wsclientfunction
|
||||
** Return : Connected: the socket value
|
||||
** Failed: -1
|
||||
**************************************************************************************************/
|
||||
int connect();
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_send
|
||||
** Description : Create the sending string data and copy to tx_buf
|
||||
** Input : message: the string that send to server(cannot exceeding the MAX_DATA_LEN
|
||||
** message_len: the length of the string
|
||||
** use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void send(char* message, int message_len, int use_mask);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : sendBinary
|
||||
** Description : Create the sending binary data and copy to tx_buf
|
||||
** Input : message: the binary that send to server(cannot exceeding the MAX_DATA_LEN
|
||||
** message_len: the length of the binary
|
||||
** use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void sendBinary(uint8_t* message, int message_len, int use_mask);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : sendPing
|
||||
** Description : Sending Ping to websocket server
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void sendPing();
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : poll
|
||||
** Description : Receicing data from server and send the data in tx_buf
|
||||
** Input : timeout(in milliseconds)
|
||||
wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void poll(int timeout);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : dispatch
|
||||
** Description : callback function when getting message from server
|
||||
** Input : function that resolve the message received and the message length
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void dispatch(void (*callback)(wsclient_context *, int));
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : getReadyState
|
||||
** Description : Getting the connection status
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : readyStateValues(4 types: CLOSING, CLOSED, CONNECTING, OPEN )
|
||||
**************************************************************************************************/
|
||||
readyStateValues getReadyState();
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : close
|
||||
** Description : Closing the connection with websocket server
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void close();
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ssl_func_on
|
||||
** Description : Set SSL/TSL function
|
||||
** Input : None
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ssl_func_on(void);
|
||||
|
||||
private:
|
||||
wsclient_context *client;
|
||||
};
|
||||
|
||||
#endif // WEBSOCKETCLIENT_H_
|
||||
222
arduino/realtek-ambz/cores/arduino/ard_socket.c
Normal file
222
arduino/realtek-ambz/cores/arduino/ard_socket.c
Normal file
@@ -0,0 +1,222 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <platform_opts.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netif.h>
|
||||
#include <platform/platform_stdlib.h>
|
||||
#include "ard_socket.h"
|
||||
|
||||
int start_server(uint16_t port, uint8_t protMode)
|
||||
{
|
||||
int _sock;
|
||||
int timeout;
|
||||
|
||||
if(protMode == 0) {
|
||||
timeout = 3000;
|
||||
_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
} else {
|
||||
timeout = 1000;
|
||||
_sock = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
if (_sock < 0) {
|
||||
printf("\r\nERROR opening socket\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in localHost;
|
||||
memset(&localHost, 0, sizeof(localHost));
|
||||
|
||||
localHost.sin_family = AF_INET;
|
||||
localHost.sin_port = htons(port);
|
||||
localHost.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if (lwip_bind(_sock, (struct sockaddr *)&localHost, sizeof(localHost)) < 0) {
|
||||
printf("\r\nERROR on binding\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _sock;
|
||||
}
|
||||
|
||||
int sock_listen(int sock, int max)
|
||||
{
|
||||
if(lwip_listen(sock , max) < 0){
|
||||
printf("\r\nERROR on listening\r\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_available(int sock)
|
||||
{
|
||||
int enable = 1;
|
||||
int timeout;
|
||||
int client_fd;
|
||||
int err;
|
||||
struct sockaddr_in cli_addr;
|
||||
|
||||
socklen_t client = sizeof(cli_addr);
|
||||
|
||||
do {
|
||||
client_fd = lwip_accept(sock, (struct sockaddr *) &cli_addr, &client);
|
||||
if (client_fd < 0) {
|
||||
err = get_sock_errno(sock);
|
||||
if (err != EAGAIN) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (client_fd < 0);
|
||||
|
||||
if(client_fd < 0){
|
||||
printf("\r\nERROR on accept\r\n");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
timeout = 3000;
|
||||
lwip_setsockopt(client_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
timeout = 30000;
|
||||
lwip_setsockopt(client_fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
lwip_setsockopt(client_fd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
|
||||
lwip_setsockopt(client_fd, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
|
||||
printf("\r\nA client connected to this server :\r\n[PORT]: %d\r\n[IP]:%s\r\n\r\n", ntohs(cli_addr.sin_port), inet_ntoa(cli_addr.sin_addr.s_addr));
|
||||
return client_fd;
|
||||
}
|
||||
}
|
||||
|
||||
int get_receive(int sock, uint8_t* data, int length, int flag, uint32_t *peer_addr, uint16_t *peer_port)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sockaddr from;
|
||||
socklen_t fromlen;
|
||||
|
||||
uint8_t backup_recvtimeout = 0;
|
||||
int backup_recv_timeout, recv_timeout, len;
|
||||
|
||||
if (flag & 0x01) {
|
||||
// for MSG_PEEK, we try to peek packets by changing receiving timeout to 10ms
|
||||
ret = lwip_getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &backup_recv_timeout, &len);
|
||||
if (ret >= 0) {
|
||||
recv_timeout = 10;
|
||||
ret = lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout));
|
||||
if (ret >= 0) {
|
||||
backup_recvtimeout = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = lwip_recvfrom(sock, data, length, flag, &from, &fromlen);
|
||||
if ( ret >= 0 ) {
|
||||
if (peer_addr != NULL) {
|
||||
*peer_addr = ((struct sockaddr_in *)&from)->sin_addr.s_addr;
|
||||
}
|
||||
if (peer_port != NULL) {
|
||||
*peer_port = ntohs(((struct sockaddr_in *)&from)->sin_port);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flag & 0x01) && (backup_recvtimeout == 1)) {
|
||||
// restore receiving timeout
|
||||
lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &backup_recv_timeout, sizeof(recv_timeout));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_sock_errno(int sock)
|
||||
{
|
||||
int so_error;
|
||||
socklen_t len = sizeof(so_error);
|
||||
getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);
|
||||
return so_error;
|
||||
}
|
||||
|
||||
int set_sock_recv_timeout(int sock, int timeout)
|
||||
{
|
||||
return lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
}
|
||||
|
||||
void stop_socket(int sock)
|
||||
{
|
||||
lwip_close(sock);
|
||||
}
|
||||
|
||||
int send_data(int sock, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = lwip_write(sock, data, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sendto_data(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port)
|
||||
{
|
||||
int ret;
|
||||
|
||||
struct sockaddr_in peer_addr;
|
||||
memset(&peer_addr, 0, sizeof(peer_addr));
|
||||
peer_addr.sin_family = AF_INET;
|
||||
peer_addr.sin_addr.s_addr = peer_ip;
|
||||
peer_addr.sin_port = htons(peer_port);
|
||||
|
||||
ret = lwip_sendto(sock, data, len, 0, (struct sockaddr*)&peer_addr, sizeof(struct sockaddr_in));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int start_client(uint32_t ipAddress, uint16_t port, uint8_t protMode)
|
||||
{
|
||||
int enable = 1;
|
||||
int timeout;
|
||||
int _sock;
|
||||
|
||||
if(protMode == 0)//tcp
|
||||
_sock = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
else
|
||||
_sock = lwip_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
|
||||
if (_sock < 0) {
|
||||
printf("\r\nERROR opening socket\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in serv_addr;
|
||||
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||
serv_addr.sin_family = AF_INET;
|
||||
serv_addr.sin_addr.s_addr = ipAddress;
|
||||
serv_addr.sin_port = htons(port);
|
||||
|
||||
if (protMode == 0){//TCP MODE
|
||||
if(connect(_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == 0){
|
||||
printf("\r\nConnect to Server successful!\r\n");
|
||||
|
||||
timeout = 3000;
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
||||
timeout = 30000;
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
||||
lwip_setsockopt(_sock, IPPROTO_TCP, TCP_NODELAY, &enable, sizeof(enable));
|
||||
lwip_setsockopt(_sock, SOL_SOCKET, SO_KEEPALIVE, &enable, sizeof(enable));
|
||||
|
||||
return _sock;
|
||||
}
|
||||
else{
|
||||
printf("\r\nConnect to Server failed!\r\n");
|
||||
stop_socket(_sock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf("\r\nUdp client setup Server's information successful!\r\n");
|
||||
}
|
||||
|
||||
return _sock;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
25
arduino/realtek-ambz/cores/arduino/ard_socket.h
Normal file
25
arduino/realtek-ambz/cores/arduino/ard_socket.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef ARD_SOCKET_H
|
||||
#define ARD_SOCKET_H
|
||||
#include "main.h"
|
||||
|
||||
int start_server(uint16_t port, uint8_t protMode);
|
||||
|
||||
int sock_listen(int sock, int max);
|
||||
|
||||
int get_available(int sock);
|
||||
|
||||
int get_receive(int sock, uint8_t* data, int length, int flag, uint32_t *peer_addr, uint16_t *peer_port);
|
||||
|
||||
int get_sock_errno(int sock);
|
||||
|
||||
int set_sock_recv_timeout(int sock, int timeout);
|
||||
|
||||
void stop_socket(int sock);
|
||||
|
||||
int send_data(int sock, const uint8_t *data, uint16_t len);
|
||||
|
||||
int sendto_data(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port);
|
||||
|
||||
int start_client(uint32_t ipAddress, uint16_t port, uint8_t protMode);
|
||||
|
||||
#endif
|
||||
24
arduino/realtek-ambz/cores/arduino/ard_ssl.h
Normal file
24
arduino/realtek-ambz/cores/arduino/ard_ssl.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef ARD_SSL_H
|
||||
#define ARD_SSL_H
|
||||
|
||||
struct ssl_context;
|
||||
|
||||
typedef struct {
|
||||
int socket;
|
||||
int recvTimeout;
|
||||
ssl_context *ssl;
|
||||
} sslclient_context;
|
||||
|
||||
int start_ssl_client(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key);
|
||||
|
||||
void stop_ssl_socket(sslclient_context *ssl_client);
|
||||
|
||||
int send_ssl_data(sslclient_context *ssl_client, const uint8_t *data, uint16_t len);
|
||||
|
||||
int get_ssl_receive(sslclient_context *ssl_client, uint8_t* data, int length, int flag);
|
||||
|
||||
int get_ssl_sock_errno(sslclient_context *ssl_client);
|
||||
|
||||
int get_ssl_bytes_avail(sslclient_context *ssl_client);
|
||||
|
||||
#endif
|
||||
33
arduino/realtek-ambz/cores/arduino/avr/dtostrf.c
Normal file
33
arduino/realtek-ambz/cores/arduino/avr/dtostrf.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
dtostrf - Emulation for dtostrf function from avr-libc
|
||||
Copyright (c) 2013 Arduino. All rights reserved.
|
||||
Written by Cristian Maglie <c.maglie@arduino.cc>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_AMEBA
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
|
||||
char fmt[20];
|
||||
sprintf(fmt, "%%%d.%df", width, prec);
|
||||
sprintf(sout, fmt, val);
|
||||
return sout;
|
||||
}
|
||||
|
||||
29
arduino/realtek-ambz/cores/arduino/avr/dtostrf.h
Normal file
29
arduino/realtek-ambz/cores/arduino/avr/dtostrf.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
dtostrf - Emulation for dtostrf function from avr-libc
|
||||
Copyright (c) 2013 Arduino. All rights reserved.
|
||||
Written by Cristian Maglie <c.maglie@arduino.cc>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dtostrf (double val, signed char width, unsigned char prec, char *sout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
0
arduino/realtek-ambz/cores/arduino/avr/interrupt.h
Normal file
0
arduino/realtek-ambz/cores/arduino/avr/interrupt.h
Normal file
70
arduino/realtek-ambz/cores/arduino/avr/pgmspace.h
Normal file
70
arduino/realtek-ambz/cores/arduino/avr/pgmspace.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
pgmspace.h - Definitions for compatibility with AVR pgmspace macros
|
||||
|
||||
Copyright (c) 2015 Arduino LLC
|
||||
|
||||
Based on work of Paul Stoffregen on Teensy 3 (http://pjrc.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
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
|
||||
AUTHORS 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 IN
|
||||
THE SOFTWARE
|
||||
*/
|
||||
|
||||
#ifndef __PGMSPACE_H_
|
||||
#define __PGMSPACE_H_ 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PSTR(str) (str)
|
||||
|
||||
#define _SFR_BYTE(n) (n)
|
||||
|
||||
typedef void prog_void;
|
||||
typedef char prog_char;
|
||||
typedef unsigned char prog_uchar;
|
||||
typedef int8_t prog_int8_t;
|
||||
typedef uint8_t prog_uint8_t;
|
||||
typedef int16_t prog_int16_t;
|
||||
typedef uint16_t prog_uint16_t;
|
||||
typedef int32_t prog_int32_t;
|
||||
typedef uint32_t prog_uint32_t;
|
||||
|
||||
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||
#define strcpy_P(dest, src) strcpy((dest), (src))
|
||||
#define strcat_P(dest, src) strcat((dest), (src))
|
||||
#define strcmp_P(a, b) strcmp((a), (b))
|
||||
#define strstr_P(a, b) strstr((a), (b))
|
||||
#define strlen_P(a) strlen((a))
|
||||
#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
|
||||
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#define pgm_read_float(addr) (*(const float *)(addr))
|
||||
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_near(addr) pgm_read_float(addr)
|
||||
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_far(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_far(addr) pgm_read_float(addr)
|
||||
|
||||
#endif
|
||||
71
arduino/realtek-ambz/cores/arduino/b64.cpp
Normal file
71
arduino/realtek-ambz/cores/arduino/b64.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
// Simple Base64 code
|
||||
// (c) Copyright 2010 MCQN Ltd.
|
||||
// Released under Apache License, version 2.0
|
||||
|
||||
#include "b64.h"
|
||||
|
||||
/* Simple test program
|
||||
#include <stdio.h>
|
||||
void main()
|
||||
{
|
||||
char* in = "amcewen";
|
||||
char out[22];
|
||||
|
||||
b64_encode(in, 15, out, 22);
|
||||
out[21] = '\0';
|
||||
|
||||
printf(out);
|
||||
}
|
||||
*/
|
||||
|
||||
int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen)
|
||||
{
|
||||
// Work out if we've got enough space to encode the input
|
||||
// Every 6 bits of input becomes a byte of output
|
||||
if (aOutputLen < (aInputLen*8)/6)
|
||||
{
|
||||
// FIXME Should we return an error here, or just the length
|
||||
return (aInputLen*8)/6;
|
||||
}
|
||||
|
||||
// If we get here we've got enough space to do the encoding
|
||||
|
||||
const char* b64_dictionary = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
if (aInputLen == 3)
|
||||
{
|
||||
aOutput[0] = b64_dictionary[aInput[0] >> 2];
|
||||
aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)];
|
||||
aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2|(aInput[2]>>6)];
|
||||
aOutput[3] = b64_dictionary[aInput[2]&0x3F];
|
||||
}
|
||||
else if (aInputLen == 2)
|
||||
{
|
||||
aOutput[0] = b64_dictionary[aInput[0] >> 2];
|
||||
aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4|(aInput[1]>>4)];
|
||||
aOutput[2] = b64_dictionary[(aInput[1]&0x0F)<<2];
|
||||
aOutput[3] = '=';
|
||||
}
|
||||
else if (aInputLen == 1)
|
||||
{
|
||||
aOutput[0] = b64_dictionary[aInput[0] >> 2];
|
||||
aOutput[1] = b64_dictionary[(aInput[0] & 0x3)<<4];
|
||||
aOutput[2] = '=';
|
||||
aOutput[3] = '=';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Break the input into 3-byte chunks and process each of them
|
||||
int i;
|
||||
for (i = 0; i < aInputLen/3; i++)
|
||||
{
|
||||
b64_encode(&aInput[i*3], 3, &aOutput[i*4], 4);
|
||||
}
|
||||
if (aInputLen % 3 > 0)
|
||||
{
|
||||
// It doesn't fit neatly into a 3-byte chunk, so process what's left
|
||||
b64_encode(&aInput[i*3], aInputLen % 3, &aOutput[i*4], aOutputLen - (i*4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
arduino/realtek-ambz/cores/arduino/b64.h
Normal file
7
arduino/realtek-ambz/cores/arduino/b64.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef b64_h
|
||||
#define b64_h
|
||||
|
||||
int b64_encode(const unsigned char* aInput, int aInputLen, unsigned char* aOutput, int aOutputLen);
|
||||
|
||||
#endif
|
||||
|
||||
534
arduino/realtek-ambz/cores/arduino/binary.h
Normal file
534
arduino/realtek-ambz/cores/arduino/binary.h
Normal file
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
binary.h - Definitions for binary constants
|
||||
Copyright (c) 2006 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Binary_h
|
||||
#define Binary_h
|
||||
|
||||
#define B0 0
|
||||
#define B00 0
|
||||
#define B000 0
|
||||
#define B0000 0
|
||||
#define B00000 0
|
||||
#define B000000 0
|
||||
#define B0000000 0
|
||||
#define B00000000 0
|
||||
#define B1 1
|
||||
#define B01 1
|
||||
#define B001 1
|
||||
#define B0001 1
|
||||
#define B00001 1
|
||||
#define B000001 1
|
||||
#define B0000001 1
|
||||
#define B00000001 1
|
||||
#define B10 2
|
||||
#define B010 2
|
||||
#define B0010 2
|
||||
#define B00010 2
|
||||
#define B000010 2
|
||||
#define B0000010 2
|
||||
#define B00000010 2
|
||||
#define B11 3
|
||||
#define B011 3
|
||||
#define B0011 3
|
||||
#define B00011 3
|
||||
#define B000011 3
|
||||
#define B0000011 3
|
||||
#define B00000011 3
|
||||
#define B100 4
|
||||
#define B0100 4
|
||||
#define B00100 4
|
||||
#define B000100 4
|
||||
#define B0000100 4
|
||||
#define B00000100 4
|
||||
#define B101 5
|
||||
#define B0101 5
|
||||
#define B00101 5
|
||||
#define B000101 5
|
||||
#define B0000101 5
|
||||
#define B00000101 5
|
||||
#define B110 6
|
||||
#define B0110 6
|
||||
#define B00110 6
|
||||
#define B000110 6
|
||||
#define B0000110 6
|
||||
#define B00000110 6
|
||||
#define B111 7
|
||||
#define B0111 7
|
||||
#define B00111 7
|
||||
#define B000111 7
|
||||
#define B0000111 7
|
||||
#define B00000111 7
|
||||
#define B1000 8
|
||||
#define B01000 8
|
||||
#define B001000 8
|
||||
#define B0001000 8
|
||||
#define B00001000 8
|
||||
#define B1001 9
|
||||
#define B01001 9
|
||||
#define B001001 9
|
||||
#define B0001001 9
|
||||
#define B00001001 9
|
||||
#define B1010 10
|
||||
#define B01010 10
|
||||
#define B001010 10
|
||||
#define B0001010 10
|
||||
#define B00001010 10
|
||||
#define B1011 11
|
||||
#define B01011 11
|
||||
#define B001011 11
|
||||
#define B0001011 11
|
||||
#define B00001011 11
|
||||
#define B1100 12
|
||||
#define B01100 12
|
||||
#define B001100 12
|
||||
#define B0001100 12
|
||||
#define B00001100 12
|
||||
#define B1101 13
|
||||
#define B01101 13
|
||||
#define B001101 13
|
||||
#define B0001101 13
|
||||
#define B00001101 13
|
||||
#define B1110 14
|
||||
#define B01110 14
|
||||
#define B001110 14
|
||||
#define B0001110 14
|
||||
#define B00001110 14
|
||||
#define B1111 15
|
||||
#define B01111 15
|
||||
#define B001111 15
|
||||
#define B0001111 15
|
||||
#define B00001111 15
|
||||
#define B10000 16
|
||||
#define B010000 16
|
||||
#define B0010000 16
|
||||
#define B00010000 16
|
||||
#define B10001 17
|
||||
#define B010001 17
|
||||
#define B0010001 17
|
||||
#define B00010001 17
|
||||
#define B10010 18
|
||||
#define B010010 18
|
||||
#define B0010010 18
|
||||
#define B00010010 18
|
||||
#define B10011 19
|
||||
#define B010011 19
|
||||
#define B0010011 19
|
||||
#define B00010011 19
|
||||
#define B10100 20
|
||||
#define B010100 20
|
||||
#define B0010100 20
|
||||
#define B00010100 20
|
||||
#define B10101 21
|
||||
#define B010101 21
|
||||
#define B0010101 21
|
||||
#define B00010101 21
|
||||
#define B10110 22
|
||||
#define B010110 22
|
||||
#define B0010110 22
|
||||
#define B00010110 22
|
||||
#define B10111 23
|
||||
#define B010111 23
|
||||
#define B0010111 23
|
||||
#define B00010111 23
|
||||
#define B11000 24
|
||||
#define B011000 24
|
||||
#define B0011000 24
|
||||
#define B00011000 24
|
||||
#define B11001 25
|
||||
#define B011001 25
|
||||
#define B0011001 25
|
||||
#define B00011001 25
|
||||
#define B11010 26
|
||||
#define B011010 26
|
||||
#define B0011010 26
|
||||
#define B00011010 26
|
||||
#define B11011 27
|
||||
#define B011011 27
|
||||
#define B0011011 27
|
||||
#define B00011011 27
|
||||
#define B11100 28
|
||||
#define B011100 28
|
||||
#define B0011100 28
|
||||
#define B00011100 28
|
||||
#define B11101 29
|
||||
#define B011101 29
|
||||
#define B0011101 29
|
||||
#define B00011101 29
|
||||
#define B11110 30
|
||||
#define B011110 30
|
||||
#define B0011110 30
|
||||
#define B00011110 30
|
||||
#define B11111 31
|
||||
#define B011111 31
|
||||
#define B0011111 31
|
||||
#define B00011111 31
|
||||
#define B100000 32
|
||||
#define B0100000 32
|
||||
#define B00100000 32
|
||||
#define B100001 33
|
||||
#define B0100001 33
|
||||
#define B00100001 33
|
||||
#define B100010 34
|
||||
#define B0100010 34
|
||||
#define B00100010 34
|
||||
#define B100011 35
|
||||
#define B0100011 35
|
||||
#define B00100011 35
|
||||
#define B100100 36
|
||||
#define B0100100 36
|
||||
#define B00100100 36
|
||||
#define B100101 37
|
||||
#define B0100101 37
|
||||
#define B00100101 37
|
||||
#define B100110 38
|
||||
#define B0100110 38
|
||||
#define B00100110 38
|
||||
#define B100111 39
|
||||
#define B0100111 39
|
||||
#define B00100111 39
|
||||
#define B101000 40
|
||||
#define B0101000 40
|
||||
#define B00101000 40
|
||||
#define B101001 41
|
||||
#define B0101001 41
|
||||
#define B00101001 41
|
||||
#define B101010 42
|
||||
#define B0101010 42
|
||||
#define B00101010 42
|
||||
#define B101011 43
|
||||
#define B0101011 43
|
||||
#define B00101011 43
|
||||
#define B101100 44
|
||||
#define B0101100 44
|
||||
#define B00101100 44
|
||||
#define B101101 45
|
||||
#define B0101101 45
|
||||
#define B00101101 45
|
||||
#define B101110 46
|
||||
#define B0101110 46
|
||||
#define B00101110 46
|
||||
#define B101111 47
|
||||
#define B0101111 47
|
||||
#define B00101111 47
|
||||
#define B110000 48
|
||||
#define B0110000 48
|
||||
#define B00110000 48
|
||||
#define B110001 49
|
||||
#define B0110001 49
|
||||
#define B00110001 49
|
||||
#define B110010 50
|
||||
#define B0110010 50
|
||||
#define B00110010 50
|
||||
#define B110011 51
|
||||
#define B0110011 51
|
||||
#define B00110011 51
|
||||
#define B110100 52
|
||||
#define B0110100 52
|
||||
#define B00110100 52
|
||||
#define B110101 53
|
||||
#define B0110101 53
|
||||
#define B00110101 53
|
||||
#define B110110 54
|
||||
#define B0110110 54
|
||||
#define B00110110 54
|
||||
#define B110111 55
|
||||
#define B0110111 55
|
||||
#define B00110111 55
|
||||
#define B111000 56
|
||||
#define B0111000 56
|
||||
#define B00111000 56
|
||||
#define B111001 57
|
||||
#define B0111001 57
|
||||
#define B00111001 57
|
||||
#define B111010 58
|
||||
#define B0111010 58
|
||||
#define B00111010 58
|
||||
#define B111011 59
|
||||
#define B0111011 59
|
||||
#define B00111011 59
|
||||
#define B111100 60
|
||||
#define B0111100 60
|
||||
#define B00111100 60
|
||||
#define B111101 61
|
||||
#define B0111101 61
|
||||
#define B00111101 61
|
||||
#define B111110 62
|
||||
#define B0111110 62
|
||||
#define B00111110 62
|
||||
#define B111111 63
|
||||
#define B0111111 63
|
||||
#define B00111111 63
|
||||
#define B1000000 64
|
||||
#define B01000000 64
|
||||
#define B1000001 65
|
||||
#define B01000001 65
|
||||
#define B1000010 66
|
||||
#define B01000010 66
|
||||
#define B1000011 67
|
||||
#define B01000011 67
|
||||
#define B1000100 68
|
||||
#define B01000100 68
|
||||
#define B1000101 69
|
||||
#define B01000101 69
|
||||
#define B1000110 70
|
||||
#define B01000110 70
|
||||
#define B1000111 71
|
||||
#define B01000111 71
|
||||
#define B1001000 72
|
||||
#define B01001000 72
|
||||
#define B1001001 73
|
||||
#define B01001001 73
|
||||
#define B1001010 74
|
||||
#define B01001010 74
|
||||
#define B1001011 75
|
||||
#define B01001011 75
|
||||
#define B1001100 76
|
||||
#define B01001100 76
|
||||
#define B1001101 77
|
||||
#define B01001101 77
|
||||
#define B1001110 78
|
||||
#define B01001110 78
|
||||
#define B1001111 79
|
||||
#define B01001111 79
|
||||
#define B1010000 80
|
||||
#define B01010000 80
|
||||
#define B1010001 81
|
||||
#define B01010001 81
|
||||
#define B1010010 82
|
||||
#define B01010010 82
|
||||
#define B1010011 83
|
||||
#define B01010011 83
|
||||
#define B1010100 84
|
||||
#define B01010100 84
|
||||
#define B1010101 85
|
||||
#define B01010101 85
|
||||
#define B1010110 86
|
||||
#define B01010110 86
|
||||
#define B1010111 87
|
||||
#define B01010111 87
|
||||
#define B1011000 88
|
||||
#define B01011000 88
|
||||
#define B1011001 89
|
||||
#define B01011001 89
|
||||
#define B1011010 90
|
||||
#define B01011010 90
|
||||
#define B1011011 91
|
||||
#define B01011011 91
|
||||
#define B1011100 92
|
||||
#define B01011100 92
|
||||
#define B1011101 93
|
||||
#define B01011101 93
|
||||
#define B1011110 94
|
||||
#define B01011110 94
|
||||
#define B1011111 95
|
||||
#define B01011111 95
|
||||
#define B1100000 96
|
||||
#define B01100000 96
|
||||
#define B1100001 97
|
||||
#define B01100001 97
|
||||
#define B1100010 98
|
||||
#define B01100010 98
|
||||
#define B1100011 99
|
||||
#define B01100011 99
|
||||
#define B1100100 100
|
||||
#define B01100100 100
|
||||
#define B1100101 101
|
||||
#define B01100101 101
|
||||
#define B1100110 102
|
||||
#define B01100110 102
|
||||
#define B1100111 103
|
||||
#define B01100111 103
|
||||
#define B1101000 104
|
||||
#define B01101000 104
|
||||
#define B1101001 105
|
||||
#define B01101001 105
|
||||
#define B1101010 106
|
||||
#define B01101010 106
|
||||
#define B1101011 107
|
||||
#define B01101011 107
|
||||
#define B1101100 108
|
||||
#define B01101100 108
|
||||
#define B1101101 109
|
||||
#define B01101101 109
|
||||
#define B1101110 110
|
||||
#define B01101110 110
|
||||
#define B1101111 111
|
||||
#define B01101111 111
|
||||
#define B1110000 112
|
||||
#define B01110000 112
|
||||
#define B1110001 113
|
||||
#define B01110001 113
|
||||
#define B1110010 114
|
||||
#define B01110010 114
|
||||
#define B1110011 115
|
||||
#define B01110011 115
|
||||
#define B1110100 116
|
||||
#define B01110100 116
|
||||
#define B1110101 117
|
||||
#define B01110101 117
|
||||
#define B1110110 118
|
||||
#define B01110110 118
|
||||
#define B1110111 119
|
||||
#define B01110111 119
|
||||
#define B1111000 120
|
||||
#define B01111000 120
|
||||
#define B1111001 121
|
||||
#define B01111001 121
|
||||
#define B1111010 122
|
||||
#define B01111010 122
|
||||
#define B1111011 123
|
||||
#define B01111011 123
|
||||
#define B1111100 124
|
||||
#define B01111100 124
|
||||
#define B1111101 125
|
||||
#define B01111101 125
|
||||
#define B1111110 126
|
||||
#define B01111110 126
|
||||
#define B1111111 127
|
||||
#define B01111111 127
|
||||
#define B10000000 128
|
||||
#define B10000001 129
|
||||
#define B10000010 130
|
||||
#define B10000011 131
|
||||
#define B10000100 132
|
||||
#define B10000101 133
|
||||
#define B10000110 134
|
||||
#define B10000111 135
|
||||
#define B10001000 136
|
||||
#define B10001001 137
|
||||
#define B10001010 138
|
||||
#define B10001011 139
|
||||
#define B10001100 140
|
||||
#define B10001101 141
|
||||
#define B10001110 142
|
||||
#define B10001111 143
|
||||
#define B10010000 144
|
||||
#define B10010001 145
|
||||
#define B10010010 146
|
||||
#define B10010011 147
|
||||
#define B10010100 148
|
||||
#define B10010101 149
|
||||
#define B10010110 150
|
||||
#define B10010111 151
|
||||
#define B10011000 152
|
||||
#define B10011001 153
|
||||
#define B10011010 154
|
||||
#define B10011011 155
|
||||
#define B10011100 156
|
||||
#define B10011101 157
|
||||
#define B10011110 158
|
||||
#define B10011111 159
|
||||
#define B10100000 160
|
||||
#define B10100001 161
|
||||
#define B10100010 162
|
||||
#define B10100011 163
|
||||
#define B10100100 164
|
||||
#define B10100101 165
|
||||
#define B10100110 166
|
||||
#define B10100111 167
|
||||
#define B10101000 168
|
||||
#define B10101001 169
|
||||
#define B10101010 170
|
||||
#define B10101011 171
|
||||
#define B10101100 172
|
||||
#define B10101101 173
|
||||
#define B10101110 174
|
||||
#define B10101111 175
|
||||
#define B10110000 176
|
||||
#define B10110001 177
|
||||
#define B10110010 178
|
||||
#define B10110011 179
|
||||
#define B10110100 180
|
||||
#define B10110101 181
|
||||
#define B10110110 182
|
||||
#define B10110111 183
|
||||
#define B10111000 184
|
||||
#define B10111001 185
|
||||
#define B10111010 186
|
||||
#define B10111011 187
|
||||
#define B10111100 188
|
||||
#define B10111101 189
|
||||
#define B10111110 190
|
||||
#define B10111111 191
|
||||
#define B11000000 192
|
||||
#define B11000001 193
|
||||
#define B11000010 194
|
||||
#define B11000011 195
|
||||
#define B11000100 196
|
||||
#define B11000101 197
|
||||
#define B11000110 198
|
||||
#define B11000111 199
|
||||
#define B11001000 200
|
||||
#define B11001001 201
|
||||
#define B11001010 202
|
||||
#define B11001011 203
|
||||
#define B11001100 204
|
||||
#define B11001101 205
|
||||
#define B11001110 206
|
||||
#define B11001111 207
|
||||
#define B11010000 208
|
||||
#define B11010001 209
|
||||
#define B11010010 210
|
||||
#define B11010011 211
|
||||
#define B11010100 212
|
||||
#define B11010101 213
|
||||
#define B11010110 214
|
||||
#define B11010111 215
|
||||
#define B11011000 216
|
||||
#define B11011001 217
|
||||
#define B11011010 218
|
||||
#define B11011011 219
|
||||
#define B11011100 220
|
||||
#define B11011101 221
|
||||
#define B11011110 222
|
||||
#define B11011111 223
|
||||
#define B11100000 224
|
||||
#define B11100001 225
|
||||
#define B11100010 226
|
||||
#define B11100011 227
|
||||
#define B11100100 228
|
||||
#define B11100101 229
|
||||
#define B11100110 230
|
||||
#define B11100111 231
|
||||
#define B11101000 232
|
||||
#define B11101001 233
|
||||
#define B11101010 234
|
||||
#define B11101011 235
|
||||
#define B11101100 236
|
||||
#define B11101101 237
|
||||
#define B11101110 238
|
||||
#define B11101111 239
|
||||
#define B11110000 240
|
||||
#define B11110001 241
|
||||
#define B11110010 242
|
||||
#define B11110011 243
|
||||
#define B11110100 244
|
||||
#define B11110101 245
|
||||
#define B11110110 246
|
||||
#define B11110111 247
|
||||
#define B11111000 248
|
||||
#define B11111001 249
|
||||
#define B11111010 250
|
||||
#define B11111011 251
|
||||
#define B11111100 252
|
||||
#define B11111101 253
|
||||
#define B11111110 254
|
||||
#define B11111111 255
|
||||
|
||||
#endif
|
||||
62
arduino/realtek-ambz/cores/arduino/bitband_io.c
Normal file
62
arduino/realtek-ambz/cores/arduino/bitband_io.c
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
#include "bitband_io.h"
|
||||
|
||||
volatile uint8_t * BitBandAddr(void *addr, uint8_t bit) {
|
||||
return (volatile uint8_t *)(BITBAND_ADDR((u32)addr, bit));
|
||||
}
|
||||
|
||||
volatile uint8_t * BitBandPeriAddr(void *addr, uint8_t bit) {
|
||||
return (volatile uint8_t *)(BITBAND_PERI((u32)addr, bit));
|
||||
}
|
||||
|
||||
volatile uint8_t * GetOutPinBitBandAddr(PinName pin) {
|
||||
uint32_t paddr = NULL;
|
||||
uint32_t ippin = HAL_GPIO_GetIPPinName_8195a(pin);
|
||||
if(ippin < 0xff) {
|
||||
// paddr = 0x42000000 + (0x40001000 + 0x0c * (ippin >> 5) - 0x40000000) * 32 + ((ippin & 0x1f) * 4);
|
||||
paddr = BitBandPeriAddr((void *)(GPIO_REG_BASE + GPIO_PORTB_DR * (ippin >> 5)), ippin & 0x1f);
|
||||
}
|
||||
return paddr;
|
||||
}
|
||||
|
||||
volatile uint8_t * GetInPinBitBandAddr(PinName pin) {
|
||||
volatile uint8_t * paddr = NULL;
|
||||
uint32_t ippin = HAL_GPIO_GetIPPinName_8195a(pin);
|
||||
if(ippin < 0xff) {
|
||||
// paddr = 0x42000000 + (0x40001000 + 0x0c * (ippin >> 5) - 0x40000000) * 32 + ((ippin & 0x1f) * 4);
|
||||
paddr = BitBandPeriAddr((void *)(GPIO_REG_BASE + GPIO_EXT_PORTA + (ippin >> 5) * 4), ippin & 0x1f);
|
||||
}
|
||||
return paddr;
|
||||
}
|
||||
|
||||
volatile uint8_t * HardSetPin(PinName pin, HAL_GPIO_PIN_MODE pmode, uint8_t val)
|
||||
{
|
||||
volatile uint8_t *paddr = NULL;
|
||||
uint32_t ippin = HAL_GPIO_GetIPPinName_8195a(pin);
|
||||
if(ippin < 0xff) {
|
||||
if(_pHAL_Gpio_Adapter == NULL) {
|
||||
extern HAL_GPIO_ADAPTER gBoot_Gpio_Adapter;
|
||||
_pHAL_Gpio_Adapter = &gBoot_Gpio_Adapter;
|
||||
}
|
||||
if(_pHAL_Gpio_Adapter->Gpio_Func_En == 0) GPIO_FuncOn_8195a();
|
||||
wait_us(100);
|
||||
// delayMicroseconds(100);
|
||||
// paddr = 0x42000000 + (0x40001000 + 0x0c * (ippin >> 5) - 0x40000000) * 32 + ((ippin & 0x1f) * 4);
|
||||
#if CONFIG_DEBUG_LOG > 3
|
||||
GpioFunctionChk(ippin, ENABLE);
|
||||
#endif
|
||||
GPIO_PullCtrl_8195a(ippin, HAL_GPIO_HIGHZ); // Make the pin pull control default as High-Z
|
||||
paddr = BitBandPeriAddr((void *)(GPIO_REG_BASE + GPIO_PORTB_DR * (ippin >> 5)), ippin & 0x1f);
|
||||
*paddr = val; // data register
|
||||
HAL_GPIO_PIN gpio;
|
||||
gpio.pin_name = ippin;
|
||||
gpio.pin_mode = pmode;
|
||||
HAL_GPIO_Init_8195a(&gpio);
|
||||
*paddr = val; // data register
|
||||
// paddr[(GPIO_PORTB_DDR - GPIO_PORTB_DR) * 32] = pmode == DOUT_PUSH_PULL; // data direction
|
||||
// GPIO_PullCtrl_8195a(ippin, pmode); // set GPIO_PULL_CTRLx
|
||||
// paddr[(GPIO_PORTB_CTRL - GPIO_PORTB_DR) * 32] = 0; // data source control, we should keep it as default: data source from software
|
||||
}
|
||||
return paddr;
|
||||
}
|
||||
|
||||
161
arduino/realtek-ambz/cores/arduino/bitband_io.h
Normal file
161
arduino/realtek-ambz/cores/arduino/bitband_io.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#ifndef _BITBAND_IO_H_
|
||||
#define _BITBAND_IO_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "PinNames.h"
|
||||
#include "hal_platform.h"
|
||||
#include "hal_api.h"
|
||||
#include "hal_gpio.h"
|
||||
#include "rtl8195a_gpio.h"
|
||||
|
||||
#define BITBAND_SRAM_REF 0x10000000
|
||||
#define BITBAND_SRAM_BASE 0x12000000
|
||||
#define BITBAND_SRAM(a,b) (BITBAND_SRAM_BASE + (a-BITBAND_SRAM_REF)*32 + (b*4)) // Convert SRAM address
|
||||
|
||||
/*
|
||||
* in hal_platform.h
|
||||
#define BITBAND_REG_BASE 0x40001000
|
||||
*/
|
||||
|
||||
/*
|
||||
* in rtl8195a_gpio.h
|
||||
*
|
||||
#define BITBAND_PORTA_DR 0x00 // data register
|
||||
#define BITBAND_PORTA_DDR 0x04 // data direction
|
||||
#define BITBAND_PORTA_CTRL 0x08 // data source control, we should keep it as default: data source from software
|
||||
|
||||
#define BITBAND_PORTB_DR 0x0c // data register
|
||||
#define BITBAND_PORTB_DDR 0x10 // data direction
|
||||
#define BITBAND_PORTB_CTRL 0x14 // data source control, we should keep it as default: data source from software
|
||||
|
||||
#define BITBAND_PORTC_DR 0x18 // data register
|
||||
#define BITBAND_PORTC_DDR 0x1c // data direction
|
||||
#define BITBAND_PORTC_CTRL 0x20 // data source control, we should keep it as default: data source from software
|
||||
|
||||
#define BITBAND_EXT_PORTA 0x50 // GPIO IN read or OUT read back
|
||||
#define BITBAND_EXT_PORTB 0x54 // GPIO IN read or OUT read back
|
||||
#define BITBAND_EXT_PORTC 0x58 // GPIO IN read or OUT read back
|
||||
*/
|
||||
|
||||
#define BITBAND_PERI_REF 0x40000000
|
||||
#define BITBAND_PERI_BASE 0x42000000
|
||||
#define BITBAND_PERI(a,b) (BITBAND_PERI_BASE + (a-BITBAND_PERI_REF)*32 + (b*4)) // Convert PERI address
|
||||
#define ucBITBAND_PERI(a,b) *((volatile unsigned char *)BITBAND_PERI(a,b))
|
||||
#define uiBITBAND_PERI(a,b) *((volatile unsigned int *)BITBAND_PERI(a,b))
|
||||
|
||||
#define BITBAND_A0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,0) //Port = 0, bit = 0, A0
|
||||
#define BITBAND_A1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,1) //Port = 0, bit = 1, A1
|
||||
#define BITBAND_A2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,0) //Port = 1, bit = 0, A2
|
||||
#define BITBAND_A3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,1) //Port = 1, bit = 1, A3
|
||||
#define BITBAND_A4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,2) //Port = 1, bit = 2, A4
|
||||
#define BITBAND_A5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,3) //Port = 1, bit = 3, A5
|
||||
#define BITBAND_A6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,4) //Port = 1, bit = 4, A6
|
||||
#define BITBAND_A7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,5) //Port = 1, bit = 5, A7
|
||||
|
||||
#define BITBAND_B0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,6) //Port = 1, bit = 6, B0
|
||||
#define BITBAND_B1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,7) //Port = 1, bit = 7, B1
|
||||
#define BITBAND_B2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,8) //Port = 1, bit = 8, B2
|
||||
#define BITBAND_B3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,2) //Port = 0, bit = 2, B3
|
||||
#define BITBAND_B4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,3) //Port = 0, bit = 3, B4
|
||||
#define BITBAND_B5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,9) //Port = 1, bit = 9, B5
|
||||
#define BITBAND_B6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,4) //Port = 0, bit = 4, B6
|
||||
#define BITBAND_B7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,5) //Port = 0, bit = 5, B7
|
||||
|
||||
#define BITBAND_C0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,10) //Port = 1, bit = 10, C0
|
||||
#define BITBAND_C1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,6) //Port = 0, bit = 6, C1
|
||||
#define BITBAND_C2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,11) //Port = 1, bit = 11, C2
|
||||
#define BITBAND_C3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,7) //Port = 0, bit = 7, C3
|
||||
#define BITBAND_C4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,8) //Port = 0, bit = 8, C4
|
||||
#define BITBAND_C5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,9) //Port = 0, bit = 9, C5
|
||||
#define BITBAND_C6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,10) //Port = 0, bit = 10, C6
|
||||
#define BITBAND_C7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,11) //Port = 0, bit = 11, C7
|
||||
#define BITBAND_C8 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,12) //Port = 0, bit = 12, C8
|
||||
#define BITBAND_C9 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,13) //Port = 0, bit = 13, C9
|
||||
|
||||
#define BITBAND_D0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,12) //Port = 1, bit = 12, D0
|
||||
#define BITBAND_D1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,14) //Port = 0, bit = 14, D1
|
||||
#define BITBAND_D2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,13) //Port = 1, bit = 13, D2
|
||||
#define BITBAND_D3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,15) //Port = 0, bit = 15, D3
|
||||
#define BITBAND_D4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,16) //Port = 0, bit = 16, D4
|
||||
#define BITBAND_D5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,17) //Port = 0, bit = 17, D5
|
||||
#define BITBAND_D6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,18) //Port = 0, bit = 18, D6
|
||||
#define BITBAND_D7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,19) //Port = 0, bit = 19, D7
|
||||
#define BITBAND_D8 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,14) //Port = 1, bit = 14, D8
|
||||
#define BITBAND_D9 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,20) //Port = 0, bit = 20, D9
|
||||
|
||||
#define BITBAND_E0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,15) //Port = 2, bit = 15, E0
|
||||
#define BITBAND_E1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,21) //Port = 0, bit = 21, E1
|
||||
#define BITBAND_E2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,22) //Port = 0, bit = 22, E2
|
||||
#define BITBAND_E3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,23) //Port = 0, bit = 23, E3
|
||||
#define BITBAND_E4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,16) //Port = 1, bit = 16, E4
|
||||
#define BITBAND_E5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,24) //Port = 0, bit = 24, E5
|
||||
#define BITBAND_E6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,25) //Port = 0, bit = 25, E6
|
||||
#define BITBAND_E7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,26) //Port = 0, bit = 26, E7
|
||||
#define BITBAND_E8 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,27) //Port = 0, bit = 27, E8
|
||||
#define BITBAND_E9 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,17) //Port = 1, bit = 17, E9
|
||||
#define BITBAND_E10 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,18) //Port = 1, bit = 17, E10
|
||||
|
||||
#define BITBAND_F0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,19) //Port = 1, bit = 19, F0
|
||||
#define BITBAND_F1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,20) //Port = 1, bit = 20, F1
|
||||
#define BITBAND_F2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,21) //Port = 1, bit = 21, F2
|
||||
#define BITBAND_F3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,22) //Port = 1, bit = 22, F3
|
||||
#define BITBAND_F4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,23) //Port = 1, bit = 23, F4
|
||||
#define BITBAND_F5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,24) //Port = 1, bit = 24, F5
|
||||
|
||||
#define BITBAND_G0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,25) //Port = 1, bit = 25, G0
|
||||
#define BITBAND_G1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,26) //Port = 1, bit = 26, G1
|
||||
#define BITBAND_G2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,27) //Port = 1, bit = 27, G2
|
||||
#define BITBAND_G3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,28) //Port = 0, bit = 28, G3
|
||||
#define BITBAND_G4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,28) //Port = 1, bit = 28, G4
|
||||
#define BITBAND_G5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,29) //Port = 1, bit = 29, G5
|
||||
#define BITBAND_G6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,30) //Port = 1, bit = 30, G6
|
||||
#define BITBAND_G7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTB_DR,31) //Port = 1, bit = 31, G7
|
||||
|
||||
#define BITBAND_H0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,0) //Port = 2, bit = 0, H0
|
||||
#define BITBAND_H1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,29) //Port = 0, bit = 29, H1
|
||||
#define BITBAND_H2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,1) //Port = 2, bit = 1, H2
|
||||
#define BITBAND_H3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,30) //Port = 0, bit = 30, H3
|
||||
#define BITBAND_H4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,2) //Port = 2, bit = 2, H4
|
||||
#define BITBAND_H5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,31) //Port = 0, bit = 31, H5
|
||||
#define BITBAND_H6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,3) //Port = 2, bit = 3, H6
|
||||
#define BITBAND_H7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTA_DR,4) //Port = 2, bit = 4, H7
|
||||
|
||||
#define BITBAND_I0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,5) //Port = 2, bit = 5, I0
|
||||
#define BITBAND_I1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,6) //Port = 2, bit = 6, I1
|
||||
#define BITBAND_I2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,7) //Port = 2, bit = 7, I2
|
||||
#define BITBAND_I3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,8) //Port = 2, bit = 8, I3
|
||||
#define BITBAND_I4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,9) //Port = 2, bit = 9, I4
|
||||
#define BITBAND_I5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,10) //Port = 2, bit = 10, I5
|
||||
#define BITBAND_I6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,11) //Port = 2, bit = 11, I6
|
||||
#define BITBAND_I7 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,12) //Port = 2, bit = 12, I7
|
||||
|
||||
#define BITBAND_J0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,13) //Port = 2, bit = 13, J0
|
||||
#define BITBAND_J1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,14) //Port = 2, bit = 14, J1
|
||||
#define BITBAND_J2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,15) //Port = 2, bit = 15, J2
|
||||
#define BITBAND_J3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,16) //Port = 2, bit = 16, J3
|
||||
#define BITBAND_J4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,17) //Port = 2, bit = 17, J4
|
||||
#define BITBAND_J5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,18) //Port = 2, bit = 18, J5
|
||||
#define BITBAND_J6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,19) //Port = 2, bit = 19, J6
|
||||
|
||||
#define BITBAND_K0 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,20) //Port = 2, bit = 20, K0
|
||||
#define BITBAND_K1 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,21) //Port = 2, bit = 21, K1
|
||||
#define BITBAND_K2 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,22) //Port = 2, bit = 22, K2
|
||||
#define BITBAND_K3 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,23) //Port = 2, bit = 23, K3
|
||||
#define BITBAND_K4 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,24) //Port = 2, bit = 24, K4
|
||||
#define BITBAND_K5 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,25) //Port = 2, bit = 25, K5
|
||||
#define BITBAND_K6 ucBITBAND_PERI(GPIO_REG_BASE+GPIO_PORTC_DR,26) //Port = 2, bit = 26, K6
|
||||
|
||||
volatile uint8_t * BitBandAddr(void *addr, uint8_t bit);
|
||||
volatile uint8_t * BitBandPeriAddr(void *addr, uint8_t bit);
|
||||
volatile uint8_t * GetOutPinBitBandAddr(PinName pin);
|
||||
volatile uint8_t * GetInPinBitBandAddr(PinName pin);
|
||||
volatile uint8_t * HardSetPin(PinName pin, HAL_GPIO_PIN_MODE pmode, uint8_t val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _BITBAND_IO_H_
|
||||
26
arduino/realtek-ambz/cores/arduino/cxxabi-compat.cpp
Normal file
26
arduino/realtek-ambz/cores/arduino/cxxabi-compat.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
extern "C" void __cxa_pure_virtual(void) ;
|
||||
|
||||
/* We compile with nodefaultlibs, so we need to provide an error
|
||||
* handler for an empty pure virtual function */
|
||||
extern "C" void __cxa_pure_virtual(void) {
|
||||
while(1)
|
||||
;
|
||||
}
|
||||
36
arduino/realtek-ambz/cores/arduino/debug.h
Normal file
36
arduino/realtek-ambz/cores/arduino/debug.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef ARD_DEBUG_H
|
||||
#define ARD_DEBUG_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef DEBUG_RTL_CORE
|
||||
#define DEBUGV(...) rtl_printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef DEBUGV
|
||||
#define DEBUGV(...)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
void hexdump(void * addr, int len = 16);
|
||||
#else
|
||||
void hexdump(void * addr, int len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void print_udp_pcb(void);
|
||||
void print_tcp_pcb(void);
|
||||
void DumpForOneBytes(void *addr, int cnt); // cnt max 0x70 !
|
||||
|
||||
void __panic_func(const char* file, int line, const char* func) __attribute__((noreturn));
|
||||
#define panic() __panic_func(__FILE__, __LINE__, __func__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif//ARD_DEBUG_H
|
||||
58
arduino/realtek-ambz/cores/arduino/hooks.c
Normal file
58
arduino/realtek-ambz/cores/arduino/hooks.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Empty yield() hook.
|
||||
*
|
||||
* This function is intended to be used by library writers to build
|
||||
* libraries or sketches that supports cooperative threads.
|
||||
*
|
||||
* Its defined as a weak symbol and it can be redefined to implement a
|
||||
* real cooperative scheduler.
|
||||
*/
|
||||
static void __empty() {
|
||||
// Empty
|
||||
}
|
||||
void yield(void) __attribute__ ((weak, alias("__empty")));
|
||||
|
||||
/**
|
||||
* SysTick hook
|
||||
*
|
||||
* This function is called from SysTick handler, before the default
|
||||
* handler provided by Arduino.
|
||||
*/
|
||||
static int __false() {
|
||||
// Return false
|
||||
return 0;
|
||||
}
|
||||
int sysTickHook(void) __attribute__ ((weak, alias("__false")));
|
||||
|
||||
/**
|
||||
* SVC hook
|
||||
* PendSV hook
|
||||
*
|
||||
* These functions are called from SVC handler, and PensSV handler.
|
||||
* Default action is halting.
|
||||
*/
|
||||
static void __halt() {
|
||||
// Halts
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
void svcHook(void) __attribute__ ((weak, alias("__halt")));
|
||||
void pendSVHook(void) __attribute__ ((weak, alias("__halt")));
|
||||
170
arduino/realtek-ambz/cores/arduino/itoa.c
Normal file
170
arduino/realtek-ambz/cores/arduino/itoa.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "itoa.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
|
||||
#if 0
|
||||
/* reverse: reverse string s in place */
|
||||
static void reverse( char s[] )
|
||||
{
|
||||
int i, j ;
|
||||
char c ;
|
||||
|
||||
for ( i = 0, j = strlen(s)-1 ; i < j ; i++, j-- )
|
||||
{
|
||||
c = s[i] ;
|
||||
s[i] = s[j] ;
|
||||
s[j] = c ;
|
||||
}
|
||||
}
|
||||
|
||||
/* itoa: convert n to characters in s */
|
||||
extern void itoa( int n, char s[] )
|
||||
{
|
||||
int i, sign ;
|
||||
|
||||
if ( (sign = n) < 0 ) /* record sign */
|
||||
{
|
||||
n = -n; /* make n positive */
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{ /* generate digits in reverse order */
|
||||
s[i++] = n % 10 + '0'; /* get next digit */
|
||||
} while ((n /= 10) > 0) ; /* delete it */
|
||||
|
||||
if (sign < 0 )
|
||||
{
|
||||
s[i++] = '-';
|
||||
}
|
||||
|
||||
s[i] = '\0';
|
||||
|
||||
reverse( s ) ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
extern char* itoa( int value, char *string, int radix )
|
||||
{
|
||||
return ltoa( value, string, radix ) ;
|
||||
}
|
||||
|
||||
extern char* ltoa( long value, char *string, int radix )
|
||||
{
|
||||
char tmp[33];
|
||||
char *tp = tmp;
|
||||
long i;
|
||||
unsigned long v;
|
||||
int sign;
|
||||
char *sp;
|
||||
|
||||
if ( string == NULL )
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
if (radix > 36 || radix <= 1)
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
sign = (radix == 10 && value < 0);
|
||||
if (sign)
|
||||
{
|
||||
v = -value;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = (unsigned long)value;
|
||||
}
|
||||
|
||||
while (v || tp == tmp)
|
||||
{
|
||||
i = v % radix;
|
||||
v = v / radix;
|
||||
if (i < 10)
|
||||
*tp++ = i+'0';
|
||||
else
|
||||
*tp++ = i + 'a' - 10;
|
||||
}
|
||||
|
||||
sp = string;
|
||||
|
||||
if (sign)
|
||||
*sp++ = '-';
|
||||
while (tp > tmp)
|
||||
*sp++ = *--tp;
|
||||
*sp = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
extern char* utoa( unsigned long value, char *string, int radix )
|
||||
{
|
||||
return ultoa( value, string, radix ) ;
|
||||
}
|
||||
|
||||
extern char* ultoa( unsigned long value, char *string, int radix )
|
||||
{
|
||||
char tmp[33];
|
||||
char *tp = tmp;
|
||||
long i;
|
||||
unsigned long v = value;
|
||||
char *sp;
|
||||
|
||||
if ( string == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (radix > 36 || radix <= 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (v || tp == tmp)
|
||||
{
|
||||
i = v % radix;
|
||||
v = v / radix;
|
||||
if (i < 10)
|
||||
*tp++ = i+'0';
|
||||
else
|
||||
*tp++ = i + 'a' - 10;
|
||||
}
|
||||
|
||||
sp = string;
|
||||
|
||||
|
||||
while (tp > tmp)
|
||||
*sp++ = *--tp;
|
||||
*sp = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
42
arduino/realtek-ambz/cores/arduino/itoa.h
Normal file
42
arduino/realtek-ambz/cores/arduino/itoa.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ITOA_
|
||||
#define _ITOA_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
|
||||
#if 0
|
||||
|
||||
extern void itoa( int n, char s[] ) ;
|
||||
|
||||
#else
|
||||
|
||||
extern char* itoa( int value, char *string, int radix ) ;
|
||||
extern char* ltoa( long value, char *string, int radix ) ;
|
||||
extern char* utoa( unsigned long value, char *string, int radix ) ;
|
||||
extern char* ultoa( unsigned long value, char *string, int radix ) ;
|
||||
#endif /* 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _ITOA_
|
||||
120
arduino/realtek-ambz/cores/arduino/libwsclient.h
Normal file
120
arduino/realtek-ambz/cores/arduino/libwsclient.h
Normal file
@@ -0,0 +1,120 @@
|
||||
#ifndef EASYWSCLIENT_H
|
||||
#define EASYWSCLIENT_H
|
||||
#include <platform/platform_stdlib.h>
|
||||
|
||||
/****************Define the debug message level*********************/
|
||||
#define DEBUG_WSCLIENT 1
|
||||
|
||||
#define WSCLIENT_LOG(level, fmt, ...) printf("\n\r[WSCLIENT %s] %s: " fmt "\n", level, __FUNCTION__, ##__VA_ARGS__)
|
||||
#if DEBUG_WSCLIENT == 2
|
||||
#define WSCLIENT_DEBUG(fmt, ...) WSCLIENT_LOG("DEBUG", fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define WSCLIENT_DEBUG(fmt, ...)
|
||||
#endif
|
||||
#if DEBUG_WSCLIENT
|
||||
#define WSCLIENT_ERROR(fmt, ...) WSCLIENT_LOG("ERROR", fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define WSCLIENT_ERROR(fmt, ...)
|
||||
#endif
|
||||
/*******************************************************************/
|
||||
|
||||
/****************Define the structures used*************************/
|
||||
typedef enum{
|
||||
CLOSING,
|
||||
CLOSED,
|
||||
CONNECTING,
|
||||
OPEN
|
||||
} readyStateValues;
|
||||
|
||||
struct wsheader_type{
|
||||
unsigned header_size;
|
||||
int fin;
|
||||
int mask;
|
||||
enum opcode_type {
|
||||
CONTINUATION = 0x0,
|
||||
TEXT_FRAME = 0x1,
|
||||
BINARY_FRAME = 0x2,
|
||||
CLOSE = 8,
|
||||
PING = 9,
|
||||
PONG = 0xa,
|
||||
} opcode;
|
||||
int N0;
|
||||
uint64_t N;
|
||||
uint8_t masking_key[4];
|
||||
};
|
||||
|
||||
struct _wsclient_context;
|
||||
struct _ssl_context;
|
||||
|
||||
struct ssl_fun_ops{
|
||||
int (*memory_set_own)( void * (*malloc_func)( size_t ),void (*free_func)( void * ) );
|
||||
int (*net_connect)( int *fd, const char *host, int port );
|
||||
int (*ssl_init)( struct _ssl_context *ssl );
|
||||
void (*ssl_set_endpoint)( struct _ssl_context *ssl, int endpoint );
|
||||
void (*ssl_set_authmode)( struct _ssl_context *ssl, int authmode );
|
||||
void (*ssl_set_rng)( struct _ssl_context *ssl,
|
||||
int (*f_rng)(void *, unsigned char *, size_t),
|
||||
void *p_rng );
|
||||
void (*ssl_set_bio)( struct _ssl_context *ssl,
|
||||
int (*f_recv)(void *, unsigned char *, size_t), void *p_recv,
|
||||
int (*f_send)(void *, const unsigned char *, size_t), void *p_send );
|
||||
int (*ssl_handshake)( struct _ssl_context *ssl );
|
||||
void (*net_close)( int fd );
|
||||
void (*ssl_free)( struct _ssl_context *ssl );
|
||||
int (*ssl_read)( struct _ssl_context *ssl, unsigned char *buf, size_t len );
|
||||
int (*ssl_write)( struct _ssl_context *ssl, const unsigned char *buf, size_t len );
|
||||
const char *(*ssl_get_ciphersuite)( const struct _ssl_context *ssl );
|
||||
int (*net_recv)( void *ctx, unsigned char *buf, size_t len );
|
||||
int (*net_send)( void *ctx, const unsigned char *buf, size_t len );
|
||||
};
|
||||
|
||||
struct ws_fun_ops{
|
||||
int (*hostname_connect)(struct _wsclient_context *wsclient);
|
||||
void (*client_close)(struct _wsclient_context *wsclient);
|
||||
int (*client_send)(struct _wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
int (*client_read)(struct _wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
struct ssl_fun_ops ssl_fun_ops;
|
||||
};
|
||||
|
||||
typedef struct _wsclient_context{
|
||||
char host[128];
|
||||
char path[128];
|
||||
char origin[200];
|
||||
int port;
|
||||
uint8_t use_ssl;
|
||||
int sockfd;
|
||||
readyStateValues readyState;
|
||||
int tx_len;
|
||||
void *ssl;
|
||||
uint8_t *txbuf;
|
||||
uint8_t *rxbuf;
|
||||
uint8_t *receivedData;
|
||||
struct ws_fun_ops fun_ops;
|
||||
}wsclient_context;
|
||||
/*******************************************************************/
|
||||
|
||||
/****************General functions used by wsclient*****************/
|
||||
void ws_get_random_bytes(void *buf, size_t len);
|
||||
void* ws_malloc(unsigned int size);
|
||||
void ws_free(void *buf);
|
||||
int ws_client_handshake(wsclient_context *wsclient);
|
||||
int ws_check_handshake(wsclient_context *wsclient);
|
||||
void ws_sendData(uint8_t type, size_t message_size, uint8_t* message, int useMask, wsclient_context *wsclient);
|
||||
/*******************************************************************/
|
||||
|
||||
/*************Functions used by wsclient without SSL****************/
|
||||
|
||||
int ws_hostname_connect(wsclient_context *wsclient);
|
||||
int ws_client_read(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
int ws_client_send(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
void ws_client_close(wsclient_context *wsclient);
|
||||
/*******************************************************************/
|
||||
|
||||
/***************Functions used by wsclient with SSL*****************/
|
||||
int wss_hostname_connect(wsclient_context *wsclient);
|
||||
int wss_client_read(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
int wss_client_send(wsclient_context *wsclient, unsigned char *data, size_t data_len);
|
||||
void wss_client_close(wsclient_context *wsclient);
|
||||
/*******************************************************************/
|
||||
|
||||
#endif
|
||||
122
arduino/realtek-ambz/cores/arduino/lwip_info.c
Normal file
122
arduino/realtek-ambz/cores/arduino/lwip_info.c
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "lwip_netconf.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/err.h"
|
||||
//#include "lwip/mem.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include "lwip/udp.h"
|
||||
|
||||
/* Get one byte from the 4-byte address */
|
||||
#define ip4_addr1(ipaddr) (((u8_t*)(ipaddr))[0])
|
||||
#define ip4_addr2(ipaddr) (((u8_t*)(ipaddr))[1])
|
||||
#define ip4_addr3(ipaddr) (((u8_t*)(ipaddr))[2])
|
||||
#define ip4_addr4(ipaddr) (((u8_t*)(ipaddr))[3])
|
||||
/* These are cast to u16_t, with the intent that they are often arguments
|
||||
* to printf using the U16_F format from cc.h. */
|
||||
#define ip4_addr1_16(ipaddr) ((u16_t)ip4_addr1(ipaddr))
|
||||
#define ip4_addr2_16(ipaddr) ((u16_t)ip4_addr2(ipaddr))
|
||||
#define ip4_addr3_16(ipaddr) ((u16_t)ip4_addr3(ipaddr))
|
||||
#define ip4_addr4_16(ipaddr) ((u16_t)ip4_addr4(ipaddr))
|
||||
|
||||
#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
|
||||
ip4_addr2_16(ipaddr), \
|
||||
ip4_addr3_16(ipaddr), \
|
||||
ip4_addr4_16(ipaddr)
|
||||
|
||||
#define IPSTR "%d.%d.%d.%d"
|
||||
|
||||
extern const char * const tcp_state_str[];
|
||||
/*
|
||||
static const char * const tcp_state_str[] = {
|
||||
"CLOSED",
|
||||
"LISTEN",
|
||||
"SYN_SENT",
|
||||
"SYN_RCVD",
|
||||
"ESTABLISHED",
|
||||
"FIN_WAIT_1",
|
||||
"FIN_WAIT_2",
|
||||
"CLOSE_WAIT",
|
||||
"CLOSING",
|
||||
"LAST_ACK",
|
||||
"TIME_WAIT"
|
||||
};
|
||||
*/
|
||||
/******************************************************************************
|
||||
* FunctionName : debug
|
||||
* Parameters :
|
||||
* Returns :
|
||||
*******************************************************************************/
|
||||
void print_udp_pcb(void)
|
||||
{
|
||||
struct udp_pcb *pcb;
|
||||
bool prt_none = true;
|
||||
rtl_printf("UDP pcbs:\n");
|
||||
for(pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
rtl_printf("flg:%02x\t" IPSTR ":%d\t" IPSTR ":%d\trecv:%p\n", pcb->flags, IP2STR(&pcb->local_ip), pcb->local_port, IP2STR(&pcb->remote_ip), pcb->remote_port, pcb->recv );
|
||||
prt_none = false;
|
||||
}
|
||||
if(prt_none) rtl_printf("none\n");
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : debug
|
||||
* Parameters :
|
||||
* Returns :
|
||||
*******************************************************************************/
|
||||
void print_tcp_pcb(void)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
rtl_printf("Active PCB states:\n");
|
||||
bool prt_none = true;
|
||||
for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
|
||||
prt_none = false;
|
||||
}
|
||||
if(prt_none) rtl_printf("none\n");
|
||||
rtl_printf("Listen PCB states:\n");
|
||||
prt_none = true;
|
||||
for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
|
||||
prt_none = false;
|
||||
}
|
||||
if(prt_none) rtl_printf("none\n");
|
||||
rtl_printf("TIME-WAIT PCB states:\n");
|
||||
prt_none = true;
|
||||
for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) {
|
||||
rtl_printf("Port %d|%d\tflg:%02x\ttmr:%p\t%s\n", pcb->local_port, pcb->remote_port, pcb->flags, pcb->tmr, tcp_state_str[pcb->state]);
|
||||
prt_none = false;
|
||||
}
|
||||
if(prt_none) rtl_printf("none\n");
|
||||
}
|
||||
/******************************************************************************
|
||||
* FunctionName : debug
|
||||
* Parameters :
|
||||
* Returns :
|
||||
*******************************************************************************/
|
||||
#if 0
|
||||
//------------------------------------------------------------------------------
|
||||
void chow_tcp_connection_info(void)
|
||||
{
|
||||
rtl_printf("TCP Server connections:\n");
|
||||
TCP_SERV_CFG * p;
|
||||
TCP_SERV_CONN * ts_conn;
|
||||
bool prt_none = true;
|
||||
for(p = phcfg; p != NULL; p = p->next) {
|
||||
for(ts_conn = p->conn_links; ts_conn != NULL; ts_conn = ts_conn->next) {
|
||||
rtl_printf("%d "IPSTR ":%d %s\n", p->port, ts_conn->remote_ip.b[0], ts_conn->remote_ip.b[1], ts_conn->remote_ip.b[2], ts_conn->remote_ip.b[3], ts_conn->remote_port, tspsrv_srvconn_state_msg(ts_conn->state) );
|
||||
prt_none = false;
|
||||
}
|
||||
}
|
||||
if(prt_none) rtl_printf("none\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
146
arduino/realtek-ambz/cores/arduino/main.cpp
Normal file
146
arduino/realtek-ambz/cores/arduino/main.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
main.cpp - Main loop for Arduino sketches
|
||||
Copyright (c) 2005-2013 Arduino Team. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#define ARDUINO_MAIN
|
||||
#include "Arduino.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void HalCpuClkConfig(u8 CpuType);
|
||||
extern void SystemCoreClockUpdate(void);
|
||||
extern void En32KCalibration(void);
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "diag.h"
|
||||
#include "rtl8195a.h"
|
||||
extern int tcm_heap_freeSpace(void);
|
||||
extern void console_init(void);
|
||||
|
||||
osThreadId main_tid = 0;
|
||||
|
||||
// Weak empty variant initialization function.
|
||||
// May be redefined by variant files.
|
||||
void initVariant() __attribute__((weak));
|
||||
void initVariant() { }
|
||||
|
||||
/*
|
||||
* \brief User PreInit of Arduino application
|
||||
*/
|
||||
void UserPreInit(void) __attribute__((weak));
|
||||
void UserPreInit(void) { }
|
||||
|
||||
|
||||
/*
|
||||
* \brief Init Random()
|
||||
* \note Use in void __low_level_init(void) { Init_Rand(); } !
|
||||
*/
|
||||
void Init_Rand(void)
|
||||
{
|
||||
extern u32 _rand_z1, _rand_z2, _rand_z3, _rand_z4, _rand_first;
|
||||
u32 *p = (u32 *)0x1FFFFF00;
|
||||
while(p < (u32 *)0x20000000) _rand_z1 ^= *p++;
|
||||
_rand_z1 ^= (*((u32 *)0x40002018) << 24) ^ (*((u32 *)0x40002118) << 16) ^ (*((u32 *)0x40002218) << 8) ^ *((u32 *)0x40002318);
|
||||
_rand_z2 = ((_rand_z1 & 0x007F00FF) << 7) ^ ((_rand_z1 & 0x0F80FF00) >> 8);
|
||||
_rand_z3 = ((_rand_z2 & 0x007F00FF) << 7) ^ ((_rand_z2 & 0x0F80FF00) >> 8);
|
||||
_rand_z4 = ((_rand_z3 & 0x007F00FF) << 7) ^ ((_rand_z3 & 0x0F80FF00) >> 8);
|
||||
_rand_first = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* \brief Set CPU CLK 166MHz
|
||||
* clk : 0 - 166666666 Hz, 1 - 83333333 Hz, 2 - 41666666 Hz, 3 - 20833333 Hz, 4 - 10416666 Hz, 5 - 4000000 Hz
|
||||
* 6 - 200000000 Hz, 7 - 10000000 Hz, 8 - 50000000 Hz, 9 - 25000000 Hz, 10 - 12500000 Hz, 11 - 4000000 Hz
|
||||
* baud: 38400,...
|
||||
*/
|
||||
void Init_CPU_CLK_UART(int clkn, int baud)
|
||||
{
|
||||
// if(HalGetCpuClk() < 166000000)
|
||||
if(clkn > 5) {
|
||||
HalCpuClkConfig(clkn - 6);
|
||||
*((int *)0x40000074) |= (1<<17);
|
||||
}
|
||||
else
|
||||
{
|
||||
HalCpuClkConfig(clkn);
|
||||
*((int *)0x40000074) &= (~(1<<17));
|
||||
}
|
||||
HAL_LOG_UART_ADAPTER pUartAdapter;
|
||||
pUartAdapter.BaudRate = baud;
|
||||
HalLogUartSetBaudRate(&pUartAdapter);
|
||||
SystemCoreClockUpdate();
|
||||
En32KCalibration();
|
||||
}
|
||||
/*
|
||||
* \brief handle sketch
|
||||
*/
|
||||
void main_task( void const *arg )
|
||||
{
|
||||
|
||||
setup();
|
||||
|
||||
/*
|
||||
ConfigDebugErr = -1;
|
||||
ConfigDebugInfo = ~_DBG_SPI_FLASH_;
|
||||
ConfigDebugWarn = -1;
|
||||
CfgSysDebugErr = -1;
|
||||
CfgSysDebugInfo = -1;
|
||||
CfgSysDebugWarn = -1;
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
loop();
|
||||
if (serialEventRun) serialEventRun();
|
||||
osThreadYield();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* \brief Main entry point of Arduino application
|
||||
*/
|
||||
int main( void )
|
||||
{
|
||||
UserPreInit();
|
||||
|
||||
init();
|
||||
|
||||
initVariant();
|
||||
|
||||
#if 0 // pvvx: add start info
|
||||
vPortFree(pvPortMalloc(4)); // Init RAM heap
|
||||
sys_info();
|
||||
#endif
|
||||
|
||||
osThreadDef(main_task, osPriorityRealtime, 1, 4096*4);
|
||||
main_tid = osThreadCreate(osThread (main_task), NULL);
|
||||
|
||||
osKernelStart();
|
||||
|
||||
while(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
29
arduino/realtek-ambz/cores/arduino/netbios.h
Normal file
29
arduino/realtek-ambz/cores/arduino/netbios.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef __NETBIOS_H__
|
||||
#define __NETBIOS_H__
|
||||
|
||||
/** default port number for "NetBIOS Name service */
|
||||
#define NETBIOS_PORT 137
|
||||
|
||||
/** size of a NetBIOS name */
|
||||
#define NETBIOS_NAME_LEN 16
|
||||
|
||||
#ifndef NET_IF_NUM
|
||||
#define NET_IF_NUM 2
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern char netbios_name[NET_IF_NUM][NETBIOS_NAME_LEN + 1]; // default netifs/interfacenum: 0 - SoftAP, 1 - Station, 2 - Ethernet
|
||||
|
||||
// struct udp_pcb * netbios_pcb(void);
|
||||
void netbios_init(void);
|
||||
bool netbios_set_name(unsigned char interfacenum, char * name); // default netifs/interfacenum: 0 - SoftAP, 1 - Station, 2 - Ethernet
|
||||
bool netbios_off(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NETBIOS_H__ */
|
||||
165
arduino/realtek-ambz/cores/arduino/rtl8195a/rtl_libc.h
Normal file
165
arduino/realtek-ambz/cores/arduino/rtl8195a/rtl_libc.h
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* ROM calls
|
||||
*/
|
||||
|
||||
#ifndef _INC_RTL_LIBC_
|
||||
#define _INC_RTL_LIBC_
|
||||
/*
|
||||
#undef malloc
|
||||
#define malloc(size) pvPortMalloc(size)
|
||||
#undef free
|
||||
#define free(pbuf) vPortFree(pbuf)
|
||||
*/
|
||||
|
||||
#define atoi(str) prvAtoi(str)
|
||||
|
||||
#define calloc(nelements, elementSize) calloc_freertos(nelements, elementSize)
|
||||
|
||||
#define snprintf rtl_snprintf
|
||||
#define sprintf rtl_sprintf
|
||||
#define printf rtl_printf
|
||||
//#define vprintf rtl_vprintf
|
||||
//#define vsnprintf rtl_vsnprintf
|
||||
//#define vfprintf rtl_vfprintf
|
||||
#define memchr rtl_memchr
|
||||
#define memcmp rtl_memcmp
|
||||
#define memcpy rtl_memcpy
|
||||
#define memmove rtl_memmove
|
||||
#define memset rtl_memset
|
||||
#define strcat rtl_strcat
|
||||
#define strchr rtl_strchr
|
||||
#define strcmp rtl_strcmp
|
||||
#define strcpy rtl_strcpy
|
||||
#define strlen rtl_strlen
|
||||
#define strncat rtl_strncat
|
||||
#define strncmp rtl_strncmp
|
||||
#define strncpy rtl_strncpy
|
||||
#define strstr rtl_strstr
|
||||
#define strsep rtl_strsep
|
||||
#define strtok rtl_strtok
|
||||
|
||||
#define dtoi rtl_dtoi
|
||||
#define dtoui rtl_dtoui
|
||||
#define i2f rtl_i2f
|
||||
#define i2d rtl_i2d
|
||||
#define ui2f rtl_ui2f
|
||||
#define ui2d rtl_ui2d
|
||||
#define itoa rtl_itoa
|
||||
#define ltoa rtl_ltoa
|
||||
#define utoa rtl_utoa
|
||||
#define ultoa rtl_ultoa
|
||||
#define ftol rtl_ftol
|
||||
#define ftod rtl_ftod
|
||||
#define dtof rtl_dtof
|
||||
#define fadd rtl_fadd
|
||||
#define fsub rtl_fsub
|
||||
#define fmul rtl_fmul
|
||||
#define fdiv rtl_fdiv
|
||||
#define dadd rtl_dadd
|
||||
#define dsub rtl_dsub
|
||||
#define dmul rtl_dmul
|
||||
#define ddiv rtl_ddiv
|
||||
#define dcmpeq rtl_dcmpeq
|
||||
#define dcmplt rtl_dcmplt
|
||||
#define dcmple rtl_dcmple
|
||||
#define dcmpgt rtl_dcmpgt
|
||||
#define fcmplt rtl_fcmplt
|
||||
#define fcmpgt rtl_fcmpgt
|
||||
|
||||
#define fabsf rtl_fabsf
|
||||
#define fabs rtl_fabs
|
||||
#define cos_f32 rtl_cos_f32
|
||||
#define sin_f32 rtl_sin_f32
|
||||
|
||||
|
||||
#if 0
|
||||
extern void *calloc_freertos(size_t nelements, size_t elementSize);
|
||||
// ram_libc.c
|
||||
extern int rtl_snprintf(char *str, size_t size, const char *fmt, ...);
|
||||
extern int rtl_sprintf(char *str, const char *fmt, ...);
|
||||
extern int rtl_printf(const char *fmt, ...);
|
||||
extern int rtl_vprintf(const char *fmt, void *param);
|
||||
extern int rtl_vsnprintf(char *str, size_t size, const char *fmt, void *param);
|
||||
extern int rtl_vfprintf(FILE *fp, const char *fmt0, va_list ap);
|
||||
extern int rtl_memchr(const void *src_void, int c, size_t length);
|
||||
extern int rtl_memcmp(const void *m1, const void *m2, size_t n);
|
||||
extern int rtl_memcpy(void *dst0, const void *src0, size_t len0);
|
||||
extern int rtl_memmove(void *dst_void, const void *src_void, size_t length);
|
||||
extern int rtl_memset(void *m, int c, size_t n);
|
||||
extern char * rtl_strcat(char *s1, const char *s2);
|
||||
extern char * rtl_strchr(const char *s1, int i);
|
||||
extern int rtl_strcmp(const char *s1, const char *s2);
|
||||
extern char * rtl_strcpy(char *dst0, const char *src0);
|
||||
extern int rtl_strlen(const char *str);
|
||||
extern char * rtl_strncat(char *s1, const char *s2, size_t n);
|
||||
extern int rtl_strncmp(const char *s1, const char *s2, size_t n);
|
||||
extern char * rtl_strncpy(char *dst0, const char *src0, size_t count);
|
||||
extern char * rtl_strstr(const char *searchee, const char *lookfor);
|
||||
extern char * rtl_strsep(char **source_ptr, const char *delim);
|
||||
extern char * rtl_strtok(char *s, const char *delim);
|
||||
|
||||
//rtl_eabi_cast_ram.c
|
||||
extern int rtl_dtoi(double d);
|
||||
extern int rtl_dtoui(double d);
|
||||
extern float rtl_i2f(int val);
|
||||
extern int rtl_i2d(int val);
|
||||
extern float rtl_ui2f(unsigned int val);
|
||||
extern int rtl_ui2d(unsigned int val);
|
||||
extern char *rtl_itoa(int value, char *string, int radix);
|
||||
extern char *rtl_ltoa(int value, char *string, int radix);
|
||||
extern char *rtl_utoa(unsigned int value, char *string, int radix);
|
||||
extern char *rtl_ultoa(unsigned int value, char *string, int radix);
|
||||
extern int rtl_ftol(float f);
|
||||
extern int rtl_ftod(float f);
|
||||
extern float rtl_dtof(double d);
|
||||
extern float rtl_fadd(float a, float b);
|
||||
extern float rtl_fsub(float a, float b);
|
||||
extern float rtl_fmul(float a, float b);
|
||||
extern float rtl_fdiv(float a, float b);
|
||||
extern int rtl_dadd(double a, double b);
|
||||
extern int rtl_dsub(double a, double b);
|
||||
extern int rtl_dmul(double a, double b);
|
||||
extern int rtl_ddiv(double a, double b);
|
||||
extern int rtl_dcmpeq(double a, double b);
|
||||
extern int rtl_dcmplt(double a, double b);
|
||||
extern int rtl_dcmple(double a, double b);
|
||||
extern int rtl_dcmpgt(double a, double b);
|
||||
extern int rtl_fcmplt(float a, float b);
|
||||
extern int rtl_fcmpgt(float a, float b);
|
||||
|
||||
// rtl_math_ram.c
|
||||
extern float rtl_fabsf(float a);
|
||||
extern int rtl_fabs(double a);
|
||||
extern float rtl_cos_f32(float a);
|
||||
extern float rtl_sin_f32(float a);
|
||||
|
||||
// ram_pvvx_libc.c
|
||||
extern int snprintf(char *str, size_t size, const char *fmt, ...);
|
||||
extern int sprintf(char *str, const char *fmt, ...);
|
||||
extern int printf(const char *fmt, ...);
|
||||
extern int vprintf(const char *fmt, void *param);
|
||||
extern int vsnprintf(char *str, size_t size, const char *fmt, void *param);
|
||||
extern int vfprintf(FILE *fp, const char *fmt0, va_list ap);
|
||||
extern int memchr(const void *src_void, int c, size_t length);
|
||||
extern int memcmp(const void *m1, const void *m2, size_t n);
|
||||
extern int memcpy(void *dst0, const void *src0, size_t len0);
|
||||
extern int memmove(void *dst_void, const void *src_void, size_t length);
|
||||
extern int memset(void *m, int c, size_t n);
|
||||
extern char * strcat(char *s1, const char *s2);
|
||||
extern char * strchr(const char *s1, int i);
|
||||
extern int strcmp(const char *s1, const char *s2);
|
||||
extern char * strcpy(char *dst0, const char *src0);
|
||||
extern int strlen(const char *str);
|
||||
extern char * strncat(char *s1, const char *s2, size_t n);
|
||||
extern int strncmp(const char *s1, const char *s2, size_t n);
|
||||
extern char * strncpy(char *dst0, const char *src0, size_t count);
|
||||
extern char * strstr(const char *searchee, const char *lookfor);
|
||||
extern char * strsep(char **source_ptr, const char *delim);
|
||||
extern char * strtok(char *s, const char *delim);
|
||||
extern int sscanf(const char *buf, const char *fmt, ...);
|
||||
extern char toupper(char ch);
|
||||
extern int _stricmp (const char *s1, const char *s2);
|
||||
extern unsigned long long __aeabi_llsr(unsigned long long val, unsigned int shift);
|
||||
#endif
|
||||
|
||||
#endif // _INC_RTL_LIBC_
|
||||
233
arduino/realtek-ambz/cores/arduino/rtl_sys.cpp
Normal file
233
arduino/realtek-ambz/cores/arduino/rtl_sys.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
Copyright (c) 2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <diag.h>
|
||||
#include <flash_api.h>
|
||||
|
||||
extern void *pvPortMalloc( size_t xWantedSize );
|
||||
extern void vPortFree( void *pv );
|
||||
extern void *pvPortReAlloc( void *pv, size_t xWantedSize );
|
||||
extern size_t xPortGetFreeHeapSize( void );
|
||||
extern size_t xPortGetMinimumEverFreeHeapSize( void );
|
||||
|
||||
extern void *tcm_heap_malloc(int size);
|
||||
extern void *tcm_heap_calloc(int size);
|
||||
extern void tcm_heap_free(void * mem);
|
||||
extern void tcm_heap_dump(void);
|
||||
extern int tcm_heap_freeSpace(void);
|
||||
|
||||
|
||||
__attribute__((noreturn)) void __panic_func(const char* file, int line, const char* func)
|
||||
{
|
||||
DiagPrintf("\r\nPanic: %s, line: %d, %s\r\n");
|
||||
while(1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
void hexdump(void * ptr, int cnt)
|
||||
{
|
||||
char * p = (char *) ptr;
|
||||
int c = cnt;
|
||||
while(c > 64) {
|
||||
DumpForOneBytes((void *)p, 64);
|
||||
p += 64;
|
||||
c -= 64;
|
||||
}
|
||||
if(c != 0) DumpForOneBytes((void *)p, c);
|
||||
}
|
||||
|
||||
void debug_on(void)
|
||||
{
|
||||
ConfigDebugErr = -1;
|
||||
ConfigDebugInfo = -1;
|
||||
ConfigDebugWarn = -1;
|
||||
CfgSysDebugErr = -1;
|
||||
CfgSysDebugInfo = -1;
|
||||
CfgSysDebugWarn = -1;
|
||||
}
|
||||
|
||||
void sys_info(void) {
|
||||
rtl_printf("\r\nCLK CPU\t\t%d Hz\r\nRAM heap\t%d bytes\r\nTCM heap\t%d bytes\r\n",
|
||||
HalGetCpuClk(), xPortGetFreeHeapSize(), tcm_heap_freeSpace());
|
||||
}
|
||||
|
||||
unsigned int GetFlashSize(void)
|
||||
{
|
||||
unsigned int FlashSize;
|
||||
if(!fspic_isinit) flash_get_status(&flashobj);
|
||||
if(flashobj.SpicInitPara.id[3] >= 0x14 && flashobj.SpicInitPara.id[0] <= 0x19) {
|
||||
FlashSize = 1<<(flashobj.SpicInitPara.id[2]); // Flash size in bytes
|
||||
}
|
||||
else FlashSize = 1024*1024; // 1 mbytes
|
||||
return FlashSize;
|
||||
}
|
||||
|
||||
unsigned int GetFlashId(void)
|
||||
{
|
||||
if(!fspic_isinit) flash_get_status(&flashobj);
|
||||
return (flashobj.SpicInitPara.id[0]<<16) | (flashobj.SpicInitPara.id[1]<<8) | flashobj.SpicInitPara.id[2];
|
||||
}
|
||||
|
||||
|
||||
void * malloc(size_t size)
|
||||
{
|
||||
void * ret;
|
||||
if((ret = pvPortMalloc(size)) == NULL)
|
||||
ret = tcm_heap_malloc(size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void * zalloc(size_t size)
|
||||
{
|
||||
void * ret;
|
||||
if((ret = pvPortMalloc(size)) == NULL)
|
||||
ret = tcm_heap_calloc(size);
|
||||
else memset(ret, 0, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *calloc(size_t count, size_t size)
|
||||
{
|
||||
return zalloc(count * size);
|
||||
}
|
||||
|
||||
void free(void *pv)
|
||||
{
|
||||
vPortFree(pv);
|
||||
}
|
||||
|
||||
void * realloc(void *pv, size_t size)
|
||||
{
|
||||
return pvPortReAlloc(pv, size);
|
||||
}
|
||||
|
||||
void *operator new(size_t size)
|
||||
{
|
||||
void * ret;
|
||||
if((ret = zalloc(size)) == NULL) {
|
||||
DiagPrintf("\r\nMEM error!\r\n");
|
||||
while(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *operator new[](size_t size)
|
||||
{
|
||||
void * ret;
|
||||
if((ret = zalloc(size)) == NULL) {
|
||||
DiagPrintf("\r\nMEM error!\r\n");
|
||||
while(1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void operator delete(void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
/*
|
||||
extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
|
||||
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
|
||||
|
||||
void __cxa_pure_virtual(void)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
void __cxa_deleted_virtual(void)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint8_t guard;
|
||||
uint8_t ps;
|
||||
} guard_t;
|
||||
|
||||
extern "C" int __cxa_guard_acquire(__guard* pg)
|
||||
{
|
||||
uint8_t ps = xt_rsil(15);
|
||||
if (reinterpret_cast<guard_t*>(pg)->guard) {
|
||||
xt_wsr_ps(ps);
|
||||
return 0;
|
||||
}
|
||||
reinterpret_cast<guard_t*>(pg)->ps = ps;
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_release(__guard* pg)
|
||||
{
|
||||
reinterpret_cast<guard_t*>(pg)->guard = 1;
|
||||
xt_wsr_ps(reinterpret_cast<guard_t*>(pg)->ps);
|
||||
}
|
||||
|
||||
extern "C" void __cxa_guard_abort(__guard* pg)
|
||||
{
|
||||
xt_wsr_ps(reinterpret_cast<guard_t*>(pg)->ps);
|
||||
}
|
||||
|
||||
|
||||
namespace std
|
||||
{
|
||||
void __throw_bad_function_call()
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
void __throw_length_error(char const*)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
void __throw_bad_alloc()
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
void __throw_logic_error(const char* str)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
|
||||
void __throw_out_of_range(const char* str)
|
||||
{
|
||||
panic();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
146
arduino/realtek-ambz/cores/arduino/server_drv.cpp
Normal file
146
arduino/realtek-ambz/cores/arduino/server_drv.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
#include "server_drv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "ard_socket.h"
|
||||
#include "platform_stdlib.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start server TCP on port specified
|
||||
int ServerDrv::startServer(uint16_t port, uint8_t protMode)
|
||||
{
|
||||
int sock;
|
||||
|
||||
sock = start_server(port, protMode);
|
||||
if (sock >= 0) {
|
||||
if(protMode == TCP_MODE)
|
||||
sock_listen(sock, 1);
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
int ServerDrv::getAvailable(int sock)
|
||||
{
|
||||
return get_available(sock);
|
||||
}
|
||||
|
||||
int ServerDrv::availData(int sock)
|
||||
{
|
||||
int ret;
|
||||
uint8_t c;
|
||||
|
||||
if (sock < 0)
|
||||
return 0;
|
||||
|
||||
if(_available) {
|
||||
return 1;
|
||||
} else {
|
||||
// flag = MSG_PEEK
|
||||
ret = get_receive(sock, &c, 1, 1, &_peer_addr, &_peer_port);
|
||||
if ( ret == 1 ) {
|
||||
_available = true;
|
||||
return 1;
|
||||
}
|
||||
else{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ServerDrv::getData(int sock, uint8_t *data, uint8_t peek)
|
||||
{
|
||||
int ret = 0;
|
||||
int flag = 0;
|
||||
|
||||
if (peek) {
|
||||
flag |= 1;
|
||||
} else {
|
||||
_available = false;
|
||||
}
|
||||
|
||||
ret = get_receive(sock, data, 1, flag, &_peer_addr, &_peer_port);
|
||||
|
||||
if (ret == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ServerDrv::getDataBuf(int sock, uint8_t *_data, uint16_t _dataLen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
_available = false;
|
||||
|
||||
ret = get_receive(sock, _data, _dataLen, 0, &_peer_addr, &_peer_port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ServerDrv::getLastErrno(int sock)
|
||||
{
|
||||
return get_sock_errno(sock);
|
||||
}
|
||||
|
||||
void ServerDrv::stopClient(int sock)
|
||||
{
|
||||
stop_socket(sock);
|
||||
_available = false;
|
||||
}
|
||||
|
||||
bool ServerDrv::sendData(int sock, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (sock < 0)
|
||||
return false;
|
||||
|
||||
ret = send_data(sock, data, len);
|
||||
|
||||
if (ret <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ServerDrv::sendtoData(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (sock < 0)
|
||||
return false;
|
||||
|
||||
ret = sendto_data(sock, data, len, peer_ip, peer_port);
|
||||
|
||||
if (ret == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int ServerDrv::startClient(uint32_t ipAddress, uint16_t port, uint8_t protMode)
|
||||
{
|
||||
int sock;
|
||||
|
||||
sock = start_client(ipAddress, port, protMode);
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
void ServerDrv::getRemoteData(int sock, uint32_t *ip, uint16_t *port)
|
||||
{
|
||||
// TODO: These data may be outdated?
|
||||
*ip = _peer_addr;
|
||||
*port = _peer_port;
|
||||
}
|
||||
|
||||
int ServerDrv::setSockRecvTimeout(int sock, int timeout)
|
||||
{
|
||||
return set_sock_recv_timeout(sock, timeout);
|
||||
}
|
||||
|
||||
57
arduino/realtek-ambz/cores/arduino/server_drv.h
Normal file
57
arduino/realtek-ambz/cores/arduino/server_drv.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
server_drv.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef Server_Drv_h
|
||||
#define Server_Drv_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef enum eProtMode {TCP_MODE, UDP_MODE}tProtMode;
|
||||
#define DATA_LENTH 128
|
||||
class ServerDrv
|
||||
{
|
||||
public:
|
||||
int startServer(uint16_t port, uint8_t protMode=TCP_MODE);
|
||||
int getAvailable(int sock);
|
||||
int startClient(uint32_t ipAddress, uint16_t port, uint8_t protMode=TCP_MODE);
|
||||
int getLastErrno(int sock);
|
||||
void stopClient(int sock);
|
||||
bool getData(int sock, uint8_t *data, uint8_t peek = 0);
|
||||
int getDataBuf(int sock, uint8_t *_data, uint16_t _dataLen);
|
||||
|
||||
/* Usually used by TCP */
|
||||
bool sendData(int sock, const uint8_t *data, uint16_t len);
|
||||
|
||||
/* Usually used by UDP */
|
||||
bool sendtoData(int sock, const uint8_t *data, uint16_t len, uint32_t peer_ip, uint16_t peer_port);
|
||||
|
||||
int availData(int sock);
|
||||
|
||||
void getRemoteData(int sock, uint32_t *ip, uint16_t *port);
|
||||
|
||||
int setSockRecvTimeout(int sock, int timeout);
|
||||
|
||||
private:
|
||||
bool _available;
|
||||
|
||||
uint32_t _peer_addr;
|
||||
uint16_t _peer_port;
|
||||
};
|
||||
|
||||
#endif
|
||||
20
arduino/realtek-ambz/cores/arduino/spiffs/LICENSE
Normal file
20
arduino/realtek-ambz/cores/arduino/spiffs/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.com)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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 AUTHORS 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 IN THE SOFTWARE.
|
||||
146
arduino/realtek-ambz/cores/arduino/spiffs/README.md
Normal file
146
arduino/realtek-ambz/cores/arduino/spiffs/README.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# SPIFFS (SPI Flash File System)
|
||||
**V0.3.4**
|
||||
|
||||
Copyright (c) 2013-2016 Peter Andersson (pelleplutt1976 at gmail.com)
|
||||
|
||||
For legal stuff, see [LICENSE](https://github.com/pellepl/spiffs/blob/master/LICENSE). Basically, you may do whatever you want with the source. Use, modify, sell, print it out, roll it and smoke it - as long as I won't be held responsible.
|
||||
|
||||
Love to hear feedback though!
|
||||
|
||||
|
||||
## INTRODUCTION
|
||||
|
||||
Spiffs is a file system intended for SPI NOR flash devices on embedded targets.
|
||||
|
||||
Spiffs is designed with following characteristics in mind:
|
||||
- Small (embedded) targets, sparse RAM without heap
|
||||
- Only big areas of data (blocks) can be erased
|
||||
- An erase will reset all bits in block to ones
|
||||
- Writing pulls one to zeroes
|
||||
- Zeroes can only be pulled to ones by erase
|
||||
- Wear leveling
|
||||
|
||||
|
||||
## FEATURES
|
||||
|
||||
What spiffs does:
|
||||
- Specifically designed for low ram usage
|
||||
- Uses statically sized ram buffers, independent of number of files
|
||||
- Posix-like api: open, close, read, write, seek, stat, etc
|
||||
- It can be run on any NOR flash, not only SPI flash - theoretically also on embedded flash of an microprocessor
|
||||
- Multiple spiffs configurations can be run on same target - and even on same SPI flash device
|
||||
- Implements static wear leveling
|
||||
- Built in file system consistency checks
|
||||
|
||||
What spiffs does not:
|
||||
- Presently, spiffs does not support directories. It produces a flat structure. Creating a file with path *tmp/myfile.txt* will create a file called *tmp/myfile.txt* instead of a *myfile.txt* under directory *tmp*.
|
||||
- It is not a realtime stack. One write operation might take much longer than another.
|
||||
- Poor scalability. Spiffs is intended for small memory devices - the normal sizes for SPI flashes. Going beyond ~128MB is probably a bad idea. This is a side effect of the design goal to use as little ram as possible.
|
||||
- Presently, it does not detect or handle bad blocks.
|
||||
|
||||
|
||||
## MORE INFO
|
||||
|
||||
See the [wiki](https://github.com/pellepl/spiffs/wiki) for configuring, integrating and using spiffs.
|
||||
|
||||
For design, see [docs/TECH_SPEC](https://github.com/pellepl/spiffs/blob/master/docs/TECH_SPEC).
|
||||
|
||||
For a generic spi flash driver, see [this](https://github.com/pellepl/spiflash_driver).
|
||||
|
||||
## HISTORY
|
||||
|
||||
### 0.3.4
|
||||
- Added user callback file func.
|
||||
- Fixed a stat bug with obj id.
|
||||
- SPIFFS_probe_fs added
|
||||
- Add possibility to compile a read-only version of spiffs
|
||||
- Make magic dependent on fs length, if needed (see #59 & #66) (thanks @hreintke)
|
||||
- Exposed SPIFFS_open_by_page_function
|
||||
- Zero-size file cannot be seek #57 (thanks @lishen2)
|
||||
- Add tell and eof functions #54 (thanks @raburton)
|
||||
- Make api string params const #53 (thanks @raburton)
|
||||
- Preserve user_data during mount() #51 (thanks @rojer)
|
||||
|
||||
New API functions:
|
||||
- `SPIFFS_set_file_callback_func` - register a callback informing about file events
|
||||
- `SPIFFS_probe_fs` - probe a spi flash trying to figure out size of fs
|
||||
- `SPIFFS_open_by_page` - open a file by page index
|
||||
- `SPIFFS_eof` - checks if end of file is reached
|
||||
- `SPIFFS_tell` - returns current file offset
|
||||
|
||||
New config defines:
|
||||
- `SPIFFS_READ_ONLY`
|
||||
- `SPIFFS_USE_MAGIC_LENGTH`
|
||||
|
||||
### 0.3.3
|
||||
**Might not be compatible with 0.3.2 structures. See issue #40**
|
||||
- Possibility to add integer offset to file handles
|
||||
- Truncate function presumes too few free pages #49
|
||||
- Bug in truncate function #48 (thanks @PawelDefee)
|
||||
- Update spiffs_gc.c - remove unnecessary parameter (thanks @PawelDefee)
|
||||
- Update INTEGRATION docs (thanks @PawelDefee)
|
||||
- Fix pointer truncation in 64-bit platforms (thanks @igrr)
|
||||
- Zero-sized files cannot be read #44 (thanks @rojer)
|
||||
- (More) correct calculation of max_id in obj_lu_find #42 #41 (thanks @lishen2)
|
||||
- Check correct error code in obj_lu_find_free #41 (thanks @lishen2)
|
||||
- Moar comments for SPIFFS_lseek (thanks @igrr)
|
||||
- Fixed padding in spiffs_page_object_ix #40 (thanks @jmattsson @lishen2)
|
||||
- Fixed gc_quick test (thanks @jmattsson)
|
||||
- Add SPIFFS_EXCL flag #36
|
||||
- SPIFFS_close may fail silently if cache is enabled #37
|
||||
- User data in callbacks #34
|
||||
- Ignoring SINGLETON build in cache setup (thanks Luca)
|
||||
- Compilation error fixed #32 (thanks @chotasanjiv)
|
||||
- Align cand_scores (thanks @hefloryd)
|
||||
- Fix build warnings when SPIFFS_CACHE is 0 (thanks @ajaybhargav)
|
||||
|
||||
New config defines:
|
||||
- `SPIFFS_FILEHDL_OFFSET`
|
||||
|
||||
### 0.3.2
|
||||
- Limit cache size if too much cache is given (thanks pgeiem)
|
||||
- New feature - Controlled erase. #23
|
||||
- SPIFFS_rename leaks file descriptors #28 (thanks benpicco)
|
||||
- moved dbg print defines in test framework to params_test.h
|
||||
- lseek should return the resulting offset (thanks hefloryd)
|
||||
- fixed type on dbg ifdefs
|
||||
- silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco)
|
||||
- Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela)
|
||||
- Cache might writethrough too often #16
|
||||
- even moar testrunner updates
|
||||
- Test framework update and some added tests
|
||||
- Some thoughts for next gen
|
||||
- Test sigsevs when having too many sectors #13 (thanks alonewolfx2)
|
||||
- GC might be suboptimal #11
|
||||
- Fix eternal readdir when objheader at last block, last entry
|
||||
|
||||
New API functions:
|
||||
- `SPIFFS_gc_quick` - call a nonintrusive gc
|
||||
- `SPIFFS_gc` - call a full-scale intrusive gc
|
||||
|
||||
### 0.3.1
|
||||
- Removed two return warnings, was too triggerhappy on release
|
||||
|
||||
### 0.3.0
|
||||
- Added existing namecheck when creating files
|
||||
- Lots of static analysis bugs #6
|
||||
- Added rename func
|
||||
- Fix SPIFFS_read length when reading beyond file size
|
||||
- Added reading beyond file length testcase
|
||||
- Made build a bit more configurable
|
||||
- Changed name in spiffs from "errno" to "err_code" due to conflicts compiling in mingw
|
||||
- Improved GC checks, fixed an append bug, more robust truncate for very special case
|
||||
- GC checks preempts GC, truncate even less picky
|
||||
- Struct alignment needed for some targets, define in spiffs config #10
|
||||
- Spiffs filesystem magic, definable in config
|
||||
|
||||
New config defines:
|
||||
- `SPIFFS_USE_MAGIC` - enable or disable magic check upon mount
|
||||
- `SPIFFS_ALIGNED_OBJECT_INDEX_TABLES` - alignment for certain targets
|
||||
|
||||
New API functions:
|
||||
- `SPIFFS_rename` - rename files
|
||||
- `SPIFFS_clearerr` - clears last errno
|
||||
- `SPIFFS_info` - returns info on used and total bytes in fs
|
||||
- `SPIFFS_format` - formats the filesystem
|
||||
- `SPIFFS_mounted` - checks if filesystem is mounted
|
||||
239
arduino/realtek-ambz/cores/arduino/spiffs/TECH_SPEC
Normal file
239
arduino/realtek-ambz/cores/arduino/spiffs/TECH_SPEC
Normal file
@@ -0,0 +1,239 @@
|
||||
* USING SPIFFS
|
||||
|
||||
TODO
|
||||
|
||||
|
||||
* SPIFFS DESIGN
|
||||
|
||||
Spiffs is inspired by YAFFS. However, YAFFS is designed for NAND flashes, and
|
||||
for bigger targets with much more ram. Nevertheless, many wise thoughts have
|
||||
been borrowed from YAFFS when writing spiffs. Kudos!
|
||||
|
||||
The main complication writing spiffs was that it cannot be assumed the target
|
||||
has a heap. Spiffs must go along only with the work ram buffer given to it.
|
||||
This forces extra implementation on many areas of spiffs.
|
||||
|
||||
|
||||
** SPI flash devices using NOR technology
|
||||
|
||||
Below is a small description of how SPI flashes work internally. This is to
|
||||
give an understanding of the design choices made in spiffs.
|
||||
|
||||
SPI flash devices are physically divided in blocks. On some SPI flash devices,
|
||||
blocks are further divided into sectors. Datasheets sometimes name blocks as
|
||||
sectors and vice versa.
|
||||
|
||||
Common memory capacaties for SPI flashes are 512kB up to 8MB of data, where
|
||||
blocks may be 64kB. Sectors can be e.g. 4kB, if supported. Many SPI flashes
|
||||
have uniform block sizes, whereas others have non-uniform - the latter meaning
|
||||
that e.g. the first 16 blocks are 4kB big, and the rest are 64kB.
|
||||
|
||||
The entire memory is linear and can be read and written in random access.
|
||||
Erasing can only be done block- or sectorwise; or by mass erase.
|
||||
|
||||
SPI flashes can normally be erased from 100.000 up to 1.000.000 cycles before
|
||||
they fail.
|
||||
|
||||
A clean SPI flash from factory have all bits in entire memory set to one. A
|
||||
mass erase will reset the device to this state. Block or sector erasing will
|
||||
put the all bits in the area given by the sector or block to ones. Writing to a
|
||||
NOR flash pulls ones to zeroes. Writing 0xFF to an address is simply a no-op.
|
||||
|
||||
Writing 0b10101010 to a flash address holding 0b00001111 will yield 0b00001010.
|
||||
|
||||
This way of "write by nand" is used considerably in spiffs.
|
||||
|
||||
Common characteristics of NOR flashes are quick reads, but slow writes.
|
||||
|
||||
And finally, unlike NAND flashes, NOR flashes seem to not need any error
|
||||
correction. They always write correctly I gather.
|
||||
|
||||
|
||||
** Spiffs logical structure
|
||||
|
||||
Some terminology before proceeding. Physical blocks/sectors means sizes stated
|
||||
in the datasheet. Logical blocks and pages is something the integrator choose.
|
||||
|
||||
|
||||
** Blocks and pages
|
||||
|
||||
Spiffs is allocated to a part or all of the memory of the SPI flash device.
|
||||
This area is divided into logical blocks, which in turn are divided into
|
||||
logical pages. The boundary of a logical block must coincide with one or more
|
||||
physical blocks. The sizes for logical blocks and logical pages always remain
|
||||
the same, they are uniform.
|
||||
|
||||
Example: non-uniform flash mapped to spiffs with 128kB logical blocks
|
||||
|
||||
PHYSICAL FLASH BLOCKS SPIFFS LOGICAL BLOCKS: 128kB
|
||||
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| Block 1 : 16kB | | Block 1 : 128kB |
|
||||
+-----------------------+ | |
|
||||
| Block 2 : 16kB | | |
|
||||
+-----------------------+ | |
|
||||
| Block 3 : 16kB | | |
|
||||
+-----------------------+ | |
|
||||
| Block 4 : 16kB | | |
|
||||
+-----------------------+ | |
|
||||
| Block 5 : 64kB | | |
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| Block 6 : 64kB | | Block 2 : 128kB |
|
||||
+-----------------------+ | |
|
||||
| Block 7 : 64kB | | |
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| Block 8 : 64kB | | Block 3 : 128kB |
|
||||
+-----------------------+ | |
|
||||
| Block 9 : 64kB | | |
|
||||
+-----------------------+ - - - +-----------------------+
|
||||
| ... | | ... |
|
||||
|
||||
A logical block is divided further into a number of logical pages. A page
|
||||
defines the smallest data holding element known to spiffs. Hence, if a file
|
||||
is created being one byte big, it will occupy one page for index and one page
|
||||
for data - it will occupy 2 x size of a logical page on flash.
|
||||
So it seems it is good to select a small page size.
|
||||
|
||||
Each page has a metadata header being normally 5 to 9 bytes. This said, a very
|
||||
small page size will make metadata occupy a lot of the memory on the flash. A
|
||||
page size of 64 bytes will waste 8-14% on metadata, while 256 bytes 2-4%.
|
||||
So it seems it is good to select a big page size.
|
||||
|
||||
Also, spiffs uses a ram buffer being two times the page size. This ram buffer
|
||||
is used for loading and manipulating pages, but it is also used for algorithms
|
||||
to find free file ids, scanning the file system, etc. Having too small a page
|
||||
size means less work buffer for spiffs, ending up in more reads operations and
|
||||
eventually gives a slower file system.
|
||||
|
||||
Choosing the page size for the system involves many factors:
|
||||
- How big is the logical block size
|
||||
- What is the normal size of most files
|
||||
- How much ram can be spent
|
||||
- How much data (vs metadata) must be crammed into the file system
|
||||
- How fast must spiffs be
|
||||
- Other things impossible to find out
|
||||
|
||||
So, chosing the Optimal Page Size (tm) seems tricky, to say the least. Don't
|
||||
fret - there is no optimal page size. This varies from how the target will use
|
||||
spiffs. Use the golden rule:
|
||||
|
||||
~~~ Logical Page Size = Logical Block Size / 256 ~~~
|
||||
|
||||
This is a good starting point. The final page size can then be derived through
|
||||
heuristical experimenting for us non-analytical minds.
|
||||
|
||||
|
||||
** Objects, indices and look-ups
|
||||
|
||||
A file, or an object as called in spiffs, is identified by an object id.
|
||||
Another YAFFS rip-off. This object id is a part of the page header. So, all
|
||||
pages know to which object/file they belong - not counting the free pages.
|
||||
|
||||
An object is made up of two types of pages: object index pages and data pages.
|
||||
Data pages contain the data written by user. Index pages contain metadata about
|
||||
the object, more specifically what data pages are part of the object.
|
||||
|
||||
The page header also includes something called a span index. Let's say a file
|
||||
is written covering three data pages. The first data page will then have span
|
||||
index 0, the second span index 1, and the last data page will have span index
|
||||
2. Simple as that.
|
||||
|
||||
Finally, each page header contain flags, telling if the page is used,
|
||||
deleted, finalized, holds index or data, and more.
|
||||
|
||||
Object indices also have span indices, where an object index with span index 0
|
||||
is referred to as the object index header. This page does not only contain
|
||||
references to data pages, but also extra info such as object name, object size
|
||||
in bytes, flags for file or directory, etc.
|
||||
|
||||
If one were to create a file covering three data pages, named e.g.
|
||||
"spandex-joke.txt", given object id 12, it could look like this:
|
||||
|
||||
PAGE 0 <things to be unveiled soon>
|
||||
|
||||
PAGE 1 page header: [obj_id:12 span_ix:0 flags:USED|DATA]
|
||||
<first data page of joke>
|
||||
|
||||
PAGE 2 page header: [obj_id:12 span_ix:1 flags:USED|DATA]
|
||||
<second data page of joke>
|
||||
|
||||
PAGE 3 page header: [obj_id:545 span_ix:13 flags:USED|DATA]
|
||||
<some data belonging to object 545, probably not very amusing>
|
||||
|
||||
PAGE 4 page header: [obj_id:12 span_ix:2 flags:USED|DATA]
|
||||
<third data page of joke>
|
||||
|
||||
PAGE 5 page header: [obj_id:12 span_ix:0 flags:USED|INDEX]
|
||||
obj ix header: [name:spandex-joke.txt size:600 bytes flags:FILE]
|
||||
obj ix: [1 2 4]
|
||||
|
||||
Looking in detail at page 5, the object index header page, the object index
|
||||
array refers to each data page in order, as mentioned before. The index of the
|
||||
object index array correlates with the data page span index.
|
||||
|
||||
entry ix: 0 1 2
|
||||
obj ix: [1 2 4]
|
||||
| | |
|
||||
PAGE 1, DATA, SPAN_IX 0 --------/ | |
|
||||
PAGE 2, DATA, SPAN_IX 1 --------/ |
|
||||
PAGE 4, DATA, SPAN_IX 2 --------/
|
||||
|
||||
Things to be unveiled in page 0 - well.. Spiffs is designed for systems low on
|
||||
ram. We cannot keep a dynamic list on the whereabouts of each object index
|
||||
header so we can find a file fast. There might not even be a heap! But, we do
|
||||
not want to scan all page headers on the flash to find the object index header.
|
||||
|
||||
The first page(s) of each block contains the so called object look-up. These
|
||||
are not normal pages, they do not have a header. Instead, they are arrays
|
||||
pointing out what object-id the rest of all pages in the block belongs to.
|
||||
|
||||
By this look-up, only the first page(s) in each block must to scanned to find
|
||||
the actual page which contains the object index header of the desired object.
|
||||
|
||||
The object lookup is redundant metadata. The assumption is that it presents
|
||||
less overhead reading a full page of data to memory from each block and search
|
||||
that, instead of reading a small amount of data from each page (i.e. the page
|
||||
header) in all blocks. Each read operation from SPI flash normally contains
|
||||
extra data as the read command itself and the flash address. Also, depending on
|
||||
the underlying implementation, other criterions may need to be passed for each
|
||||
read transaction, like mutexes and such.
|
||||
|
||||
The veiled example unveiled would look like this, with some extra pages:
|
||||
|
||||
PAGE 0 [ 12 12 545 12 12 34 34 4 0 0 0 0 ...]
|
||||
PAGE 1 page header: [obj_id:12 span_ix:0 flags:USED|DATA] ...
|
||||
PAGE 2 page header: [obj_id:12 span_ix:1 flags:USED|DATA] ...
|
||||
PAGE 3 page header: [obj_id:545 span_ix:13 flags:USED|DATA] ...
|
||||
PAGE 4 page header: [obj_id:12 span_ix:2 flags:USED|DATA] ...
|
||||
PAGE 5 page header: [obj_id:12 span_ix:0 flags:USED|INDEX] ...
|
||||
PAGE 6 page header: [obj_id:34 span_ix:0 flags:USED|DATA] ...
|
||||
PAGE 7 page header: [obj_id:34 span_ix:1 flags:USED|DATA] ...
|
||||
PAGE 8 page header: [obj_id:4 span_ix:1 flags:USED|INDEX] ...
|
||||
PAGE 9 page header: [obj_id:23 span_ix:0 flags:DELETED|INDEX] ...
|
||||
PAGE 10 page header: [obj_id:23 span_ix:0 flags:DELETED|DATA] ...
|
||||
PAGE 11 page header: [obj_id:23 span_ix:1 flags:DELETED|DATA] ...
|
||||
PAGE 12 page header: [obj_id:23 span_ix:2 flags:DELETED|DATA] ...
|
||||
...
|
||||
|
||||
Ok, so why are page 9 to 12 marked as 0 when they belong to object id 23? These
|
||||
pages are deleted, so this is marked both in page header flags and in the look
|
||||
up. This is an example where spiffs uses NOR flashes "nand-way" of writing.
|
||||
|
||||
As a matter of fact, there are two object id's which are special:
|
||||
|
||||
obj id 0 (all bits zeroes) - indicates a deleted page in object look up
|
||||
obj id 0xff.. (all bits ones) - indicates a free page in object look up
|
||||
|
||||
Actually, the object id's have another quirk: if the most significant bit is
|
||||
set, this indicates an object index page. If the most significant bit is zero,
|
||||
this indicates a data page. So to be fully correct, page 0 in above example
|
||||
would look like this:
|
||||
|
||||
PAGE 0 [ 12 12 545 12 *12 34 34 *4 0 0 0 0 ...]
|
||||
|
||||
where the asterisk means the msb of the object id is set.
|
||||
|
||||
This is another way to speed up the searches when looking for object indices.
|
||||
By looking on the object id's msb in the object lookup, it is also possible
|
||||
to find out whether the page is an object index page or a data page.
|
||||
|
||||
15
arduino/realtek-ambz/cores/arduino/spiffs/TODO
Normal file
15
arduino/realtek-ambz/cores/arduino/spiffs/TODO
Normal file
@@ -0,0 +1,15 @@
|
||||
* When mending lost pages, also see if they fit into length specified in object index header
|
||||
|
||||
SPIFFS2 thoughts
|
||||
|
||||
* Instead of exact object id:s in the object lookup tables, use a hash of span index and object id.
|
||||
Eg. object id xor:ed with bit-reversed span index.
|
||||
This should decrease number of actual pages that needs to be visited when looking thru the obj lut.
|
||||
|
||||
* Logical number of each block. When moving stuff in a garbage collected page, the free
|
||||
page is assigned the same number as the garbage collected. Thus, object index pages do not have to
|
||||
be rewritten.
|
||||
|
||||
* Steal one page, use as a bit parity page. When starting an fs modification operation, write one bit
|
||||
as zero. When ending, write another bit as zero. On mount, if number of zeroes in page is uneven, a
|
||||
check is automatically run.
|
||||
681
arduino/realtek-ambz/cores/arduino/spiffs/spiffs.h
Normal file
681
arduino/realtek-ambz/cores/arduino/spiffs/spiffs.h
Normal file
@@ -0,0 +1,681 @@
|
||||
/*
|
||||
* spiffs.h
|
||||
*
|
||||
* Created on: May 26, 2013
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
#ifndef SPIFFS_H_
|
||||
#define SPIFFS_H_
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "spiffs_config.h"
|
||||
|
||||
#define SPIFFS_OK 0
|
||||
#define SPIFFS_ERR_NOT_MOUNTED -10000
|
||||
#define SPIFFS_ERR_FULL -10001
|
||||
#define SPIFFS_ERR_NOT_FOUND -10002
|
||||
#define SPIFFS_ERR_END_OF_OBJECT -10003
|
||||
#define SPIFFS_ERR_DELETED -10004
|
||||
#define SPIFFS_ERR_NOT_FINALIZED -10005
|
||||
#define SPIFFS_ERR_NOT_INDEX -10006
|
||||
#define SPIFFS_ERR_OUT_OF_FILE_DESCS -10007
|
||||
#define SPIFFS_ERR_FILE_CLOSED -10008
|
||||
#define SPIFFS_ERR_FILE_DELETED -10009
|
||||
#define SPIFFS_ERR_BAD_DESCRIPTOR -10010
|
||||
#define SPIFFS_ERR_IS_INDEX -10011
|
||||
#define SPIFFS_ERR_IS_FREE -10012
|
||||
#define SPIFFS_ERR_INDEX_SPAN_MISMATCH -10013
|
||||
#define SPIFFS_ERR_DATA_SPAN_MISMATCH -10014
|
||||
#define SPIFFS_ERR_INDEX_REF_FREE -10015
|
||||
#define SPIFFS_ERR_INDEX_REF_LU -10016
|
||||
#define SPIFFS_ERR_INDEX_REF_INVALID -10017
|
||||
#define SPIFFS_ERR_INDEX_FREE -10018
|
||||
#define SPIFFS_ERR_INDEX_LU -10019
|
||||
#define SPIFFS_ERR_INDEX_INVALID -10020
|
||||
#define SPIFFS_ERR_NOT_WRITABLE -10021
|
||||
#define SPIFFS_ERR_NOT_READABLE -10022
|
||||
#define SPIFFS_ERR_CONFLICTING_NAME -10023
|
||||
#define SPIFFS_ERR_NOT_CONFIGURED -10024
|
||||
|
||||
#define SPIFFS_ERR_NOT_A_FS -10025
|
||||
#define SPIFFS_ERR_MOUNTED -10026
|
||||
#define SPIFFS_ERR_ERASE_FAIL -10027
|
||||
#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
|
||||
|
||||
#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
|
||||
|
||||
#define SPIFFS_ERR_FILE_EXISTS -10030
|
||||
|
||||
#define SPIFFS_ERR_NOT_A_FILE -10031
|
||||
#define SPIFFS_ERR_RO_NOT_IMPL -10032
|
||||
#define SPIFFS_ERR_RO_ABORTED_OPERATION -10033
|
||||
#define SPIFFS_ERR_PROBE_TOO_FEW_BLOCKS -10034
|
||||
#define SPIFFS_ERR_PROBE_NOT_A_FS -10035
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
#define SPIFFS_ERR_TEST -10100
|
||||
|
||||
|
||||
// spiffs file descriptor index type. must be signed
|
||||
typedef s16_t spiffs_file;
|
||||
// spiffs file descriptor flags
|
||||
typedef u16_t spiffs_flags;
|
||||
// spiffs file mode
|
||||
typedef u16_t spiffs_mode;
|
||||
// object type
|
||||
typedef u8_t spiffs_obj_type;
|
||||
|
||||
struct spiffs_t;
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* spi read call function type */
|
||||
typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
|
||||
/* spi write call function type */
|
||||
typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *src);
|
||||
/* spi erase call function type */
|
||||
typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
|
||||
|
||||
#else // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* spi read call function type */
|
||||
typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
|
||||
/* spi write call function type */
|
||||
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
|
||||
/* spi erase call function type */
|
||||
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
|
||||
#endif // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* file system check callback report operation */
|
||||
typedef enum {
|
||||
SPIFFS_CHECK_LOOKUP = 0,
|
||||
SPIFFS_CHECK_INDEX,
|
||||
SPIFFS_CHECK_PAGE
|
||||
} spiffs_check_type;
|
||||
|
||||
/* file system check callback report type */
|
||||
typedef enum {
|
||||
SPIFFS_CHECK_PROGRESS = 0,
|
||||
SPIFFS_CHECK_ERROR,
|
||||
SPIFFS_CHECK_FIX_INDEX,
|
||||
SPIFFS_CHECK_FIX_LOOKUP,
|
||||
SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
|
||||
SPIFFS_CHECK_DELETE_PAGE,
|
||||
SPIFFS_CHECK_DELETE_BAD_FILE,
|
||||
} spiffs_check_report;
|
||||
|
||||
/* file system check callback function */
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
typedef void (*spiffs_check_callback)(struct spiffs_t *fs, spiffs_check_type type, spiffs_check_report report,
|
||||
u32_t arg1, u32_t arg2);
|
||||
#else // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
|
||||
u32_t arg1, u32_t arg2);
|
||||
#endif // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
/* file system listener callback operation */
|
||||
typedef enum {
|
||||
/* the file has been created */
|
||||
SPIFFS_CB_CREATED = 0,
|
||||
/* the file has been updated or moved to another page */
|
||||
SPIFFS_CB_UPDATED,
|
||||
/* the file has been deleted */
|
||||
SPIFFS_CB_DELETED,
|
||||
} spiffs_fileop_type;
|
||||
|
||||
/* file system listener callback function */
|
||||
typedef void (*spiffs_file_callback)(struct spiffs_t *fs, spiffs_fileop_type op, spiffs_obj_id obj_id, spiffs_page_ix pix);
|
||||
|
||||
#ifndef SPIFFS_DBG
|
||||
#define SPIFFS_DBG(...) \
|
||||
print(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_GC_DBG
|
||||
#define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_CACHE_DBG
|
||||
#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_CHECK_DBG
|
||||
#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* Any write to the filehandle is appended to end of the file */
|
||||
#define SPIFFS_APPEND (1<<0)
|
||||
/* If the opened file exists, it will be truncated to zero length before opened */
|
||||
#define SPIFFS_TRUNC (1<<1)
|
||||
/* If the opened file does not exist, it will be created before opened */
|
||||
#define SPIFFS_CREAT (1<<2)
|
||||
/* The opened file may only be read */
|
||||
#define SPIFFS_RDONLY (1<<3)
|
||||
/* The opened file may only be writted */
|
||||
#define SPIFFS_WRONLY (1<<4)
|
||||
/* The opened file may be both read and writted */
|
||||
#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY)
|
||||
/* Any writes to the filehandle will never be cached */
|
||||
#define SPIFFS_DIRECT (1<<5)
|
||||
/* If SPIFFS_CREAT and SPIFFS_EXCL are set, SPIFFS_open() shall fail if the file exists */
|
||||
#define SPIFFS_EXCL (1<<6)
|
||||
|
||||
#define SPIFFS_SEEK_SET (0)
|
||||
#define SPIFFS_SEEK_CUR (1)
|
||||
#define SPIFFS_SEEK_END (2)
|
||||
|
||||
#define SPIFFS_TYPE_FILE (1)
|
||||
#define SPIFFS_TYPE_DIR (2)
|
||||
#define SPIFFS_TYPE_HARD_LINK (3)
|
||||
#define SPIFFS_TYPE_SOFT_LINK (4)
|
||||
|
||||
#ifndef SPIFFS_LOCK
|
||||
#define SPIFFS_LOCK(fs)
|
||||
#endif
|
||||
|
||||
#ifndef SPIFFS_UNLOCK
|
||||
#define SPIFFS_UNLOCK(fs)
|
||||
#endif
|
||||
|
||||
// phys structs
|
||||
|
||||
// spiffs spi configuration struct
|
||||
typedef struct {
|
||||
// physical read function
|
||||
spiffs_read hal_read_f;
|
||||
// physical write function
|
||||
spiffs_write hal_write_f;
|
||||
// physical erase function
|
||||
spiffs_erase hal_erase_f;
|
||||
#if SPIFFS_SINGLETON == 0
|
||||
// physical size of the spi flash
|
||||
u32_t phys_size;
|
||||
// physical offset in spi flash used for spiffs,
|
||||
// must be on block boundary
|
||||
u32_t phys_addr;
|
||||
// physical size when erasing a block
|
||||
u32_t phys_erase_block;
|
||||
|
||||
// logical size of a block, must be on physical
|
||||
// block size boundary and must never be less than
|
||||
// a physical block
|
||||
u32_t log_block_size;
|
||||
// logical size of a page, must be at least
|
||||
// log_block_size / 8
|
||||
u32_t log_page_size;
|
||||
|
||||
#endif
|
||||
#if SPIFFS_FILEHDL_OFFSET
|
||||
// an integer offset added to each file handle
|
||||
u16_t fh_ix_offset;
|
||||
#endif
|
||||
} spiffs_config;
|
||||
|
||||
typedef struct spiffs_t {
|
||||
// file system configuration
|
||||
spiffs_config cfg;
|
||||
// number of logical blocks
|
||||
u32_t block_count;
|
||||
|
||||
// cursor for free blocks, block index
|
||||
spiffs_block_ix free_cursor_block_ix;
|
||||
// cursor for free blocks, entry index
|
||||
int free_cursor_obj_lu_entry;
|
||||
// cursor when searching, block index
|
||||
spiffs_block_ix cursor_block_ix;
|
||||
// cursor when searching, entry index
|
||||
int cursor_obj_lu_entry;
|
||||
|
||||
// primary work buffer, size of a logical page
|
||||
u8_t *lu_work;
|
||||
// secondary work buffer, size of a logical page
|
||||
u8_t *work;
|
||||
// file descriptor memory area
|
||||
u8_t *fd_space;
|
||||
// available file descriptors
|
||||
u32_t fd_count;
|
||||
|
||||
// last error
|
||||
s32_t err_code;
|
||||
|
||||
// current number of free blocks
|
||||
u32_t free_blocks;
|
||||
// current number of busy pages
|
||||
u32_t stats_p_allocated;
|
||||
// current number of deleted pages
|
||||
u32_t stats_p_deleted;
|
||||
// flag indicating that garbage collector is cleaning
|
||||
u8_t cleaning;
|
||||
// max erase count amongst all blocks
|
||||
spiffs_obj_id max_erase_count;
|
||||
|
||||
#if SPIFFS_GC_STATS
|
||||
u32_t stats_gc_runs;
|
||||
#endif
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
// cache memory
|
||||
void *cache;
|
||||
// cache size
|
||||
u32_t cache_size;
|
||||
#if SPIFFS_CACHE_STATS
|
||||
u32_t cache_hits;
|
||||
u32_t cache_misses;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// check callback function
|
||||
spiffs_check_callback check_cb_f;
|
||||
// file callback function
|
||||
spiffs_file_callback file_cb_f;
|
||||
// mounted flag
|
||||
u8_t mounted;
|
||||
// user data
|
||||
void *user_data;
|
||||
// config magic
|
||||
u32_t config_magic;
|
||||
} spiffs;
|
||||
|
||||
/* spiffs file status struct */
|
||||
typedef struct {
|
||||
spiffs_obj_id obj_id;
|
||||
u32_t size;
|
||||
spiffs_obj_type type;
|
||||
spiffs_page_ix pix;
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
||||
} spiffs_stat;
|
||||
|
||||
struct spiffs_dirent {
|
||||
spiffs_obj_id obj_id;
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
||||
spiffs_obj_type type;
|
||||
u32_t size;
|
||||
spiffs_page_ix pix;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
spiffs *fs;
|
||||
spiffs_block_ix block;
|
||||
int entry;
|
||||
} spiffs_DIR;
|
||||
|
||||
// functions
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
/**
|
||||
* Special function. This takes a spiffs config struct and returns the number
|
||||
* of blocks this file system was formatted with. This function relies on
|
||||
* that following info is set correctly in given config struct:
|
||||
*
|
||||
* phys_addr, log_page_size, and log_block_size.
|
||||
*
|
||||
* Also, hal_read_f must be set in the config struct.
|
||||
*
|
||||
* One must be sure of the correct page size and that the physical address is
|
||||
* correct in the probed file system when calling this function. It is not
|
||||
* checked if the phys_addr actually points to the start of the file system,
|
||||
* so one might get a false positive if entering a phys_addr somewhere in the
|
||||
* middle of the file system at block boundary. In addition, it is not checked
|
||||
* if the page size is actually correct. If it is not, weird file system sizes
|
||||
* will be returned.
|
||||
*
|
||||
* If this function detects a file system it returns the assumed file system
|
||||
* size, which can be used to set the phys_size.
|
||||
*
|
||||
* Otherwise, it returns an error indicating why it is not regarded as a file
|
||||
* system.
|
||||
*
|
||||
* Note: this function is not protected with SPIFFS_LOCK and SPIFFS_UNLOCK
|
||||
* macros. It returns the error code directly, instead of as read by
|
||||
* SPIFFS_errno.
|
||||
*
|
||||
* @param config essential parts of the physical and logical
|
||||
* configuration of the file system.
|
||||
*/
|
||||
s32_t SPIFFS_probe_fs(spiffs_config *config);
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH && SPIFFS_SINGLETON==0
|
||||
|
||||
/**
|
||||
* Initializes the file system dynamic parameters and mounts the filesystem.
|
||||
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
|
||||
* if the flash does not contain a recognizable file system.
|
||||
* In this case, SPIFFS_format must be called prior to remounting.
|
||||
* @param fs the file system struct
|
||||
* @param config the physical and logical configuration of the file system
|
||||
* @param work a memory work buffer comprising 2*config->log_page_size
|
||||
* bytes used throughout all file system operations
|
||||
* @param fd_space memory for file descriptors
|
||||
* @param fd_space_size memory size of file descriptors
|
||||
* @param cache memory for cache, may be null
|
||||
* @param cache_size memory size of cache
|
||||
* @param check_cb_f callback function for reporting during consistency checks
|
||||
*/
|
||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||
u8_t *fd_space, u32_t fd_space_size,
|
||||
void *cache, u32_t cache_size,
|
||||
spiffs_check_callback check_cb_f);
|
||||
|
||||
/**
|
||||
* Unmounts the file system. All file handles will be flushed of any
|
||||
* cached writes and closed.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
void SPIFFS_unmount(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Creates a new file.
|
||||
* @param fs the file system struct
|
||||
* @param path the path of the new file
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Opens/creates a file.
|
||||
* @param fs the file system struct
|
||||
* @param path the path of the new file
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
|
||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Opens a file by given dir entry.
|
||||
* Optimization purposes, when traversing a file system with SPIFFS_readdir
|
||||
* a normal SPIFFS_open would need to traverse the filesystem again to find
|
||||
* the file, whilst SPIFFS_open_by_dirent already knows where the file resides.
|
||||
* @param fs the file system struct
|
||||
* @param e the dir entry to the file
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
|
||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
|
||||
* SPIFFS_CREAT will have no effect in this case.
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Opens a file by given page index.
|
||||
* Optimization purposes, opens a file by directly pointing to the page
|
||||
* index in the spi flash.
|
||||
* If the page index does not point to a file header SPIFFS_ERR_NOT_A_FILE
|
||||
* is returned.
|
||||
* @param fs the file system struct
|
||||
* @param page_ix the page index
|
||||
* @param flags the flags for the open command, can be combinations of
|
||||
* SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
|
||||
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
|
||||
* SPIFFS_CREAT will have no effect in this case.
|
||||
* @param mode ignored, for posix compliance
|
||||
*/
|
||||
spiffs_file SPIFFS_open_by_page(spiffs *fs, spiffs_page_ix page_ix, spiffs_flags flags, spiffs_mode mode);
|
||||
|
||||
/**
|
||||
* Reads from given filehandle.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle
|
||||
* @param buf where to put read data
|
||||
* @param len how much to read
|
||||
* @returns number of bytes read, or -1 if error
|
||||
*/
|
||||
s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||
|
||||
/**
|
||||
* Writes to given filehandle.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle
|
||||
* @param buf the data to write
|
||||
* @param len how much to write
|
||||
* @returns number of bytes written, or -1 if error
|
||||
*/
|
||||
s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||
|
||||
/**
|
||||
* Moves the read/write file offset. Resulting offset is returned or negative if error.
|
||||
* lseek(fs, fd, 0, SPIFFS_SEEK_CUR) will thus return current offset.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle
|
||||
* @param offs how much/where to move the offset
|
||||
* @param whence if SPIFFS_SEEK_SET, the file offset shall be set to offset bytes
|
||||
* if SPIFFS_SEEK_CUR, the file offset shall be set to its current location plus offset
|
||||
* if SPIFFS_SEEK_END, the file offset shall be set to the size of the file plus offse, which should be negative
|
||||
*/
|
||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
|
||||
|
||||
/**
|
||||
* Removes a file by path
|
||||
* @param fs the file system struct
|
||||
* @param path the path of the file to remove
|
||||
*/
|
||||
s32_t SPIFFS_remove(spiffs *fs, const char *path);
|
||||
|
||||
/**
|
||||
* Removes a file by filehandle
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to remove
|
||||
*/
|
||||
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Gets file status by path
|
||||
* @param fs the file system struct
|
||||
* @param path the path of the file to stat
|
||||
* @param s the stat struct to populate
|
||||
*/
|
||||
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
|
||||
|
||||
/**
|
||||
* Gets file status by filehandle
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to stat
|
||||
* @param s the stat struct to populate
|
||||
*/
|
||||
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s);
|
||||
|
||||
/**
|
||||
* Flushes all pending write operations from cache for given file
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to flush
|
||||
*/
|
||||
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Closes a filehandle. If there are pending write operations, these are finalized before closing.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to close
|
||||
*/
|
||||
s32_t SPIFFS_close(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Renames a file
|
||||
* @param fs the file system struct
|
||||
* @param old path of file to rename
|
||||
* @param newPath new path of file
|
||||
*/
|
||||
s32_t SPIFFS_rename(spiffs *fs, const char *old, const char *newPath);
|
||||
|
||||
/**
|
||||
* Returns last error of last file operation.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
s32_t SPIFFS_errno(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Clears last error.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
void SPIFFS_clearerr(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Opens a directory stream corresponding to the given name.
|
||||
* The stream is positioned at the first entry in the directory.
|
||||
* On hydrogen builds the name argument is ignored as hydrogen builds always correspond
|
||||
* to a flat file structure - no directories.
|
||||
* @param fs the file system struct
|
||||
* @param name the name of the directory
|
||||
* @param d pointer the directory stream to be populated
|
||||
*/
|
||||
spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Closes a directory stream
|
||||
* @param d the directory stream to close
|
||||
*/
|
||||
s32_t SPIFFS_closedir(spiffs_DIR *d);
|
||||
|
||||
/**
|
||||
* Reads a directory into given spifs_dirent struct.
|
||||
* @param d pointer to the directory stream
|
||||
* @param e the dirent struct to be populated
|
||||
* @returns null if error or end of stream, else given dirent is returned
|
||||
*/
|
||||
struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
|
||||
|
||||
/**
|
||||
* Runs a consistency check on given filesystem.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
s32_t SPIFFS_check(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Returns number of total bytes available and number of used bytes.
|
||||
* This is an estimation, and depends on if there a many files with little
|
||||
* data or few files with much data.
|
||||
* NB: If used number of bytes exceeds total bytes, a SPIFFS_check should
|
||||
* run. This indicates a power loss in midst of things. In worst case
|
||||
* (repeated powerlosses in mending or gc) you might have to delete some files.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param total total number of bytes in filesystem
|
||||
* @param used used number of bytes in filesystem
|
||||
*/
|
||||
s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
|
||||
|
||||
/**
|
||||
* Formats the entire file system. All data will be lost.
|
||||
* The filesystem must not be mounted when calling this.
|
||||
*
|
||||
* NB: formatting is awkward. Due to backwards compatibility, SPIFFS_mount
|
||||
* MUST be called prior to formatting in order to configure the filesystem.
|
||||
* If SPIFFS_mount succeeds, SPIFFS_unmount must be called before calling
|
||||
* SPIFFS_format.
|
||||
* If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
|
||||
* SPIFFS_unmount first.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
s32_t SPIFFS_format(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Returns nonzero if spiffs is mounted, or zero if unmounted.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
u8_t SPIFFS_mounted(spiffs *fs);
|
||||
|
||||
/**
|
||||
* Tries to find a block where most or all pages are deleted, and erase that
|
||||
* block if found. Does not care for wear levelling. Will not move pages
|
||||
* around.
|
||||
* If parameter max_free_pages are set to 0, only blocks with only deleted
|
||||
* pages will be selected.
|
||||
*
|
||||
* NB: the garbage collector is automatically called when spiffs needs free
|
||||
* pages. The reason for this function is to give possibility to do background
|
||||
* tidying when user knows the system is idle.
|
||||
*
|
||||
* Use with care.
|
||||
*
|
||||
* Setting max_free_pages to anything larger than zero will eventually wear
|
||||
* flash more as a block containing free pages can be erased.
|
||||
*
|
||||
* Will set err_no to SPIFFS_OK if a block was found and erased,
|
||||
* SPIFFS_ERR_NO_DELETED_BLOCK if no matching block was found,
|
||||
* or other error.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param max_free_pages maximum number allowed free pages in block
|
||||
*/
|
||||
s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
|
||||
|
||||
/**
|
||||
* Will try to make room for given amount of bytes in the filesystem by moving
|
||||
* pages and erasing blocks.
|
||||
* If it is physically impossible, err_no will be set to SPIFFS_ERR_FULL. If
|
||||
* there already is this amount (or more) of free space, SPIFFS_gc will
|
||||
* silently return. It is recommended to call SPIFFS_info before invoking
|
||||
* this method in order to determine what amount of bytes to give.
|
||||
*
|
||||
* NB: the garbage collector is automatically called when spiffs needs free
|
||||
* pages. The reason for this function is to give possibility to do background
|
||||
* tidying when user knows the system is idle.
|
||||
*
|
||||
* Use with care.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param size amount of bytes that should be freed
|
||||
*/
|
||||
s32_t SPIFFS_gc(spiffs *fs, u32_t size);
|
||||
|
||||
/**
|
||||
* Check if EOF reached.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to check
|
||||
*/
|
||||
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Get position in file.
|
||||
* @param fs the file system struct
|
||||
* @param fh the filehandle of the file to check
|
||||
*/
|
||||
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
|
||||
|
||||
/**
|
||||
* Registers a callback function that keeps track on operations on file
|
||||
* headers. Do note, that this callback is called from within internal spiffs
|
||||
* mechanisms. Any operations on the actual file system being callbacked from
|
||||
* in this callback will mess things up for sure - do not do this.
|
||||
* This can be used to track where files are and move around during garbage
|
||||
* collection, which in turn can be used to build location tables in ram.
|
||||
* Used in conjuction with SPIFFS_open_by_page this may improve performance
|
||||
* when opening a lot of files.
|
||||
* Must be invoked after mount.
|
||||
*
|
||||
* @param fs the file system struct
|
||||
* @param cb_func the callback on file operations
|
||||
*/
|
||||
s32_t SPIFFS_set_file_callback_func(spiffs *fs, spiffs_file_callback cb_func);
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
/**
|
||||
* Prints out a visualization of the filesystem.
|
||||
* @param fs the file system struct
|
||||
*/
|
||||
s32_t SPIFFS_vis(spiffs *fs);
|
||||
#endif
|
||||
|
||||
#if SPIFFS_BUFFER_HELP
|
||||
/**
|
||||
* Returns number of bytes needed for the filedescriptor buffer given
|
||||
* amount of file descriptors.
|
||||
*/
|
||||
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs);
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
/**
|
||||
* Returns number of bytes needed for the cache buffer given
|
||||
* amount of cache pages.
|
||||
*/
|
||||
u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
#endif
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SPIFFS_H_ */
|
||||
299
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_cache.c
Normal file
299
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_cache.c
Normal file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* spiffs_cache.c
|
||||
*
|
||||
* Created on: Jun 23, 2013
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
|
||||
// returns cached page for give page index, or null if no such cached page
|
||||
static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) {
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) return 0;
|
||||
int i;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
if ((cache->cpage_use_map & (1<<i)) &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
|
||||
cp->pix == pix ) {
|
||||
SPIFFS_CACHE_DBG("CACHE_GET: have cache page %i for %04x\n", i, pix);
|
||||
cp->last_access = cache->last_access;
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
//SPIFFS_CACHE_DBG("CACHE_GET: no cache for %04x\n", pix);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// frees cached page
|
||||
static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, ix);
|
||||
if (cache->cpage_use_map & (1<<ix)) {
|
||||
if (write_back &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, ix);
|
||||
res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
|
||||
}
|
||||
|
||||
cp->flags = 0;
|
||||
cache->cpage_use_map &= ~(1 << ix);
|
||||
|
||||
if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) {
|
||||
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %i objid %04x\n", ix, cp->obj_id);
|
||||
} else {
|
||||
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %i pix %04x\n", ix, cp->pix);
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// removes the oldest accessed cached page
|
||||
static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t flags) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
|
||||
if ((cache->cpage_use_map & cache->cpage_use_mask) != cache->cpage_use_mask) {
|
||||
// at least one free cpage
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
|
||||
// all busy, scan thru all to find the cpage which has oldest access
|
||||
int i;
|
||||
int cand_ix = -1;
|
||||
u32_t oldest_val = 0;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
if ((cache->last_access - cp->last_access) > oldest_val &&
|
||||
(cp->flags & flag_mask) == flags) {
|
||||
oldest_val = cache->last_access - cp->last_access;
|
||||
cand_ix = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (cand_ix >= 0) {
|
||||
res = spiffs_cache_page_free(fs, cand_ix, 1);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// allocates a new cached page and returns it, or null if all cache pages are busy
|
||||
static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
if (cache->cpage_use_map == 0xffffffff) {
|
||||
// out of cache memory
|
||||
return 0;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
if ((cache->cpage_use_map & (1<<i)) == 0) {
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
cache->cpage_use_map |= (1<<i);
|
||||
cp->last_access = cache->last_access;
|
||||
SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %i\n", i);
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
// out of cache entries
|
||||
return 0;
|
||||
}
|
||||
|
||||
// drops the cache page for give page index
|
||||
void spiffs_cache_drop_page(spiffs *fs, spiffs_page_ix pix) {
|
||||
spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
|
||||
if (cp) {
|
||||
spiffs_cache_page_free(fs, cp->ix, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
|
||||
// reads from spi flash or the cache
|
||||
s32_t spiffs_phys_rd(
|
||||
spiffs *fs,
|
||||
u8_t op,
|
||||
spiffs_file fh,
|
||||
u32_t addr,
|
||||
u32_t len,
|
||||
u8_t *dst) {
|
||||
(void)fh;
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
spiffs_cache_page *cp = spiffs_cache_page_get(fs, SPIFFS_PADDR_TO_PAGE(fs, addr));
|
||||
cache->last_access++;
|
||||
if (cp) {
|
||||
#if SPIFFS_CACHE_STATS
|
||||
fs->cache_hits++;
|
||||
#endif
|
||||
cp->last_access = cache->last_access;
|
||||
} else {
|
||||
if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) {
|
||||
// for second layer lookup functions, we do not cache in order to prevent shredding
|
||||
return SPIFFS_HAL_READ(fs, addr, len, dst);
|
||||
}
|
||||
#if SPIFFS_CACHE_STATS
|
||||
fs->cache_misses++;
|
||||
#endif
|
||||
res = spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0);
|
||||
cp = spiffs_cache_page_allocate(fs);
|
||||
if (cp) {
|
||||
cp->flags = SPIFFS_CACHE_FLAG_WRTHRU;
|
||||
cp->pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
|
||||
}
|
||||
s32_t res2 = SPIFFS_HAL_READ(fs,
|
||||
addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs),
|
||||
spiffs_get_cache_page(fs, cache, cp->ix));
|
||||
if (res2 != SPIFFS_OK) {
|
||||
res = res2;
|
||||
}
|
||||
}
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
|
||||
memcpy(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len);
|
||||
return res;
|
||||
}
|
||||
|
||||
// writes to spi flash and/or the cache
|
||||
s32_t spiffs_phys_wr(
|
||||
spiffs *fs,
|
||||
u8_t op,
|
||||
spiffs_file fh,
|
||||
u32_t addr,
|
||||
u32_t len,
|
||||
u8_t *src) {
|
||||
(void)fh;
|
||||
spiffs_page_ix pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
|
||||
|
||||
if (cp && (op & SPIFFS_OP_COM_MASK) != SPIFFS_OP_C_WRTHRU) {
|
||||
// have a cache page
|
||||
// copy in data to cache page
|
||||
|
||||
if ((op & SPIFFS_OP_COM_MASK) == SPIFFS_OP_C_DELE &&
|
||||
(op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) {
|
||||
// page is being deleted, wipe from cache - unless it is a lookup page
|
||||
spiffs_cache_page_free(fs, cp->ix, 0);
|
||||
return SPIFFS_HAL_WRITE(fs, addr, len, src);
|
||||
}
|
||||
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
|
||||
memcpy(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len);
|
||||
|
||||
cache->last_access++;
|
||||
cp->last_access = cache->last_access;
|
||||
|
||||
if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
|
||||
// page is being updated, no write-cache, just pass thru
|
||||
return SPIFFS_HAL_WRITE(fs, addr, len, src);
|
||||
} else {
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
} else {
|
||||
// no cache page, no write cache - just write thru
|
||||
return SPIFFS_HAL_WRITE(fs, addr, len, src);
|
||||
}
|
||||
}
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
// returns the cache page that this fd refers, or null if no cache page
|
||||
spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
|
||||
if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) {
|
||||
// all cpages free, no cpage cannot be assigned to obj_id
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
if ((cache->cpage_use_map & (1<<i)) &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) &&
|
||||
cp->obj_id == fd->obj_id) {
|
||||
return cp;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// allocates a new cache page and refers this to given fd - flushes an old cache
|
||||
// page if all cache is busy
|
||||
spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_fd *fd) {
|
||||
// before this function is called, it is ensured that there is no already existing
|
||||
// cache page with same object id
|
||||
spiffs_cache_page_remove_oldest(fs, SPIFFS_CACHE_FLAG_TYPE_WR, 0);
|
||||
spiffs_cache_page *cp = spiffs_cache_page_allocate(fs);
|
||||
if (cp == 0) {
|
||||
// could not get cache page
|
||||
return 0;
|
||||
}
|
||||
|
||||
cp->flags = SPIFFS_CACHE_FLAG_TYPE_WR;
|
||||
cp->obj_id = fd->obj_id;
|
||||
fd->cache_page = cp;
|
||||
return cp;
|
||||
}
|
||||
|
||||
// unrefers all fds that this cache page refers to and releases the cache page
|
||||
void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) {
|
||||
if (cp == 0) return;
|
||||
u32_t i;
|
||||
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
|
||||
for (i = 0; i < fs->fd_count; i++) {
|
||||
spiffs_fd *cur_fd = &fds[i];
|
||||
if (cur_fd->file_nbr != 0 && cur_fd->cache_page == cp) {
|
||||
cur_fd->cache_page = 0;
|
||||
}
|
||||
}
|
||||
spiffs_cache_page_free(fs, cp->ix, 0);
|
||||
|
||||
cp->obj_id = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// initializes the cache
|
||||
void spiffs_cache_init(spiffs *fs) {
|
||||
if (fs->cache == 0) return;
|
||||
u32_t sz = fs->cache_size;
|
||||
u32_t cache_mask = 0;
|
||||
int i;
|
||||
int cache_entries =
|
||||
(sz - sizeof(spiffs_cache)) / (SPIFFS_CACHE_PAGE_SIZE(fs));
|
||||
if (cache_entries <= 0) return;
|
||||
|
||||
for (i = 0; i < cache_entries; i++) {
|
||||
cache_mask <<= 1;
|
||||
cache_mask |= 1;
|
||||
}
|
||||
|
||||
spiffs_cache cache;
|
||||
memset(&cache, 0, sizeof(spiffs_cache));
|
||||
cache.cpage_count = cache_entries;
|
||||
cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache));
|
||||
|
||||
cache.cpage_use_map = 0xffffffff;
|
||||
cache.cpage_use_mask = cache_mask;
|
||||
memcpy(fs->cache, &cache, sizeof(spiffs_cache));
|
||||
|
||||
spiffs_cache *c = spiffs_get_cache(fs);
|
||||
|
||||
memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs));
|
||||
|
||||
c->cpage_use_map &= ~(c->cpage_use_mask);
|
||||
for (i = 0; i < cache.cpage_count; i++) {
|
||||
spiffs_get_cache_page_hdr(fs, c, i)->ix = i;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SPIFFS_CACHE
|
||||
995
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_check.c
Normal file
995
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_check.c
Normal file
@@ -0,0 +1,995 @@
|
||||
/*
|
||||
* spiffs_check.c
|
||||
*
|
||||
* Contains functionality for checking file system consistency
|
||||
* and mending problems.
|
||||
* Three levels of consistency checks are implemented:
|
||||
*
|
||||
* Look up consistency
|
||||
* Checks if indices in lookup pages are coherent with page headers
|
||||
* Object index consistency
|
||||
* Checks if there are any orphaned object indices (missing object index headers).
|
||||
* If an object index is found but not its header, the object index is deleted.
|
||||
* This is critical for the following page consistency check.
|
||||
* Page consistency
|
||||
* Checks for pages that ought to be indexed, ought not to be indexed, are multiple indexed
|
||||
*
|
||||
*
|
||||
* Created on: Jul 7, 2013
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
|
||||
do { \
|
||||
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
|
||||
do { \
|
||||
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
//---------------------------------------
|
||||
// Look up consistency
|
||||
|
||||
// searches in the object indices and returns the referenced page index given
|
||||
// the object id and the data span index
|
||||
// destroys fs->lu_work
|
||||
static s32_t spiffs_object_get_data_page_index_reference(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix data_spix,
|
||||
spiffs_page_ix *pix,
|
||||
spiffs_page_ix *objix_pix) {
|
||||
s32_t res;
|
||||
|
||||
// calculate object index span index for given data page span index
|
||||
spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
|
||||
|
||||
// find obj index for obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
// load obj index entry
|
||||
u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, *objix_pix);
|
||||
if (objix_spix == 0) {
|
||||
// get referenced page from object index header
|
||||
addr += sizeof(spiffs_page_object_ix_header) + data_spix * sizeof(spiffs_page_ix);
|
||||
} else {
|
||||
// get referenced page from object index
|
||||
addr += sizeof(spiffs_page_object_ix) + SPIFFS_OBJ_IX_ENTRY(fs, data_spix) * sizeof(spiffs_page_ix);
|
||||
}
|
||||
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, 0, addr, sizeof(spiffs_page_ix), (u8_t *)pix);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// copies page contents to a new page
|
||||
static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spiffs_page_header *p_hdr, spiffs_page_ix *new_pix) {
|
||||
s32_t res;
|
||||
res = spiffs_page_allocate_data(fs, p_hdr->obj_id, p_hdr, 0,0,0,0, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_phys_cpy(fs, 0,
|
||||
SPIFFS_PAGE_TO_PADDR(fs, *new_pix) + sizeof(spiffs_page_header),
|
||||
SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
|
||||
SPIFFS_DATA_PAGE_SIZE(fs));
|
||||
SPIFFS_CHECK_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
// rewrites the object index for given object id and replaces the
|
||||
// data page index to a new page index
|
||||
static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_ix data_spix, spiffs_page_ix new_data_pix, spiffs_page_ix objix_pix) {
|
||||
s32_t res;
|
||||
spiffs_block_ix bix;
|
||||
int entry;
|
||||
spiffs_page_ix free_pix;
|
||||
obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
|
||||
|
||||
// find free entry
|
||||
res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
|
||||
|
||||
// calculate object index span index for given data page span index
|
||||
spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
|
||||
if (objix_spix == 0) {
|
||||
// calc index in index header
|
||||
entry = data_spix;
|
||||
} else {
|
||||
// calc entry in index
|
||||
entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix);
|
||||
|
||||
}
|
||||
// load index
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work;
|
||||
|
||||
// be ultra safe, double check header against provided data
|
||||
if (objix_p_hdr->obj_id != obj_id) {
|
||||
spiffs_page_delete(fs, free_pix);
|
||||
return SPIFFS_ERR_CHECK_OBJ_ID_MISM;
|
||||
}
|
||||
if (objix_p_hdr->span_ix != objix_spix) {
|
||||
spiffs_page_delete(fs, free_pix);
|
||||
return SPIFFS_ERR_CHECK_SPIX_MISM;
|
||||
}
|
||||
if ((objix_p_hdr->flags & (SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_INDEX |
|
||||
SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) !=
|
||||
(SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_DELET)) {
|
||||
spiffs_page_delete(fs, free_pix);
|
||||
return SPIFFS_ERR_CHECK_FLAGS_BAD;
|
||||
}
|
||||
|
||||
// rewrite in mem
|
||||
if (objix_spix == 0) {
|
||||
((spiffs_page_ix*)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix;
|
||||
} else {
|
||||
((spiffs_page_ix*)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix;
|
||||
}
|
||||
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, free_pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, free_pix) * sizeof(spiffs_page_ix),
|
||||
sizeof(spiffs_obj_id),
|
||||
(u8_t *)&obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_page_delete(fs, objix_pix);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// deletes an object just by marking object index header as deleted
|
||||
static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) {
|
||||
spiffs_page_ix objix_hdr_pix;
|
||||
s32_t res;
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, obj_id, 0, 0, &objix_hdr_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
u8_t flags = 0xff & ~SPIFFS_PH_FLAG_IXDELE;
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags),
|
||||
sizeof(u8_t),
|
||||
(u8_t *)&flags);
|
||||
return res;
|
||||
}
|
||||
|
||||
// validates the given look up entry
|
||||
static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, spiffs_page_header *p_hdr,
|
||||
spiffs_page_ix cur_pix, spiffs_block_ix cur_block, int cur_entry, int *reload_lu) {
|
||||
(void)cur_block;
|
||||
(void)cur_entry;
|
||||
u8_t delete_page = 0;
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_page_ix objix_pix;
|
||||
spiffs_page_ix ref_pix;
|
||||
// check validity, take actions
|
||||
if (((lu_obj_id == SPIFFS_OBJ_ID_DELETED) && (p_hdr->flags & SPIFFS_PH_FLAG_DELET)) ||
|
||||
((lu_obj_id == SPIFFS_OBJ_ID_FREE) && (p_hdr->flags & SPIFFS_PH_FLAG_USED) == 0)) {
|
||||
// look up entry deleted / free but used in page header
|
||||
SPIFFS_CHECK_DBG("LU: pix %04x deleted/free in lu but not on page\n", cur_pix);
|
||||
*reload_lu = 1;
|
||||
delete_page = 1;
|
||||
if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) {
|
||||
// header says data page
|
||||
// data page can be removed if not referenced by some object index
|
||||
res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
// no object with this id, so remove page safely
|
||||
res = SPIFFS_OK;
|
||||
} else {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (ref_pix == cur_pix) {
|
||||
// data page referenced by object index but deleted in lu
|
||||
// copy page to new place and re-write the object index to new place
|
||||
spiffs_page_ix new_pix;
|
||||
res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: data page not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: %04x rewritten to %04x, affected objix_pix %04x\n", cur_pix, new_pix, objix_pix);
|
||||
res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
|
||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res);
|
||||
res = spiffs_page_delete(fs, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
|
||||
} else {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// header says index page
|
||||
// index page can be removed if other index with same obj_id and spanix is found
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, 0);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
// no such index page found, check for a data page amongst page headers
|
||||
// lu cannot be trusted
|
||||
res = spiffs_obj_lu_find_id_and_span_by_phdr(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, 0);
|
||||
if (res == SPIFFS_OK) { // ignore other errors
|
||||
// got a data page also, assume lu corruption only, rewrite to new page
|
||||
spiffs_page_ix new_pix;
|
||||
res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
}
|
||||
} else {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lu_obj_id != SPIFFS_OBJ_ID_FREE && lu_obj_id != SPIFFS_OBJ_ID_DELETED) {
|
||||
// look up entry used
|
||||
if ((p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG) != (lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
SPIFFS_CHECK_DBG("LU: pix %04x differ in obj_id lu:%04x ph:%04x\n", cur_pix, lu_obj_id, p_hdr->obj_id);
|
||||
delete_page = 1;
|
||||
if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0 ||
|
||||
(p_hdr->flags & SPIFFS_PH_FLAG_FINAL) ||
|
||||
(p_hdr->flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_IXDELE)) == 0) {
|
||||
// page deleted or not finalized, just remove it
|
||||
} else {
|
||||
if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) {
|
||||
// if data page, check for reference to this page
|
||||
res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
// no object with this id, so remove page safely
|
||||
res = SPIFFS_OK;
|
||||
} else {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// if found, rewrite page with object id, update index, and delete current
|
||||
if (ref_pix == cur_pix) {
|
||||
spiffs_page_ix new_pix;
|
||||
res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
|
||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res);
|
||||
res = spiffs_page_delete(fs, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
|
||||
*reload_lu = 1;
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// else if index, check for other pages with both obj_id's and spanix
|
||||
spiffs_page_ix objix_pix_lu, objix_pix_ph;
|
||||
// see if other object index page exists for lookup obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_lu);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
objix_pix_lu = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// see if other object index exists for page header obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_ph);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
objix_pix_ph = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// if both obj_id's found, just delete current
|
||||
if (objix_pix_ph == 0 || objix_pix_lu == 0) {
|
||||
// otherwise try finding first corresponding data pages
|
||||
spiffs_page_ix data_pix_lu, data_pix_ph;
|
||||
// see if other data page exists for look up obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_lu);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
objix_pix_lu = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// see if other data page exists for page header obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_ph);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
objix_pix_ph = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
spiffs_page_header new_ph;
|
||||
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL);
|
||||
new_ph.span_ix = p_hdr->span_ix;
|
||||
spiffs_page_ix new_pix;
|
||||
if ((objix_pix_lu && data_pix_lu && data_pix_ph && objix_pix_ph == 0) ||
|
||||
(objix_pix_lu == 0 && data_pix_ph && objix_pix_ph == 0)) {
|
||||
// got a data page for page header obj id
|
||||
// rewrite as obj_id_ph
|
||||
new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x to pix %04x\n", cur_pix, new_ph.obj_id, new_pix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
} else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) ||
|
||||
(objix_pix_ph == 0 && data_pix_lu && objix_pix_lu == 0)) {
|
||||
// got a data page for look up obj id
|
||||
// rewrite as obj_id_lu
|
||||
new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x\n", cur_pix, new_ph.obj_id);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
*reload_lu = 1;
|
||||
} else {
|
||||
// cannot safely do anything
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: nothing to do, just delete\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX)) ||
|
||||
((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0 && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) == 0)) {
|
||||
SPIFFS_CHECK_DBG("LU: %04x lu/page index marking differ\n", cur_pix);
|
||||
spiffs_page_ix data_pix, objix_pix_d;
|
||||
// see if other data page exists for given obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &data_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
data_pix = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// see if other object index exists for given obj id and span index
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix_d);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
objix_pix_d = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
delete_page = 1;
|
||||
// if other data page exists and object index exists, just delete page
|
||||
if (data_pix && objix_pix_d) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: other index and data page exists, simply remove\n");
|
||||
} else
|
||||
// if only data page exists, make this page index
|
||||
if (data_pix && objix_pix_d == 0) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n");
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
|
||||
spiffs_page_header new_ph;
|
||||
spiffs_page_ix new_pix;
|
||||
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
|
||||
new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
new_ph.span_ix = p_hdr->span_ix;
|
||||
res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header),
|
||||
SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header));
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else
|
||||
// if only index exists, make data page
|
||||
if (data_pix == 0 && objix_pix_d) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n");
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
|
||||
spiffs_page_header new_ph;
|
||||
spiffs_page_ix new_pix;
|
||||
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
|
||||
new_ph.obj_id = lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
new_ph.span_ix = p_hdr->span_ix;
|
||||
res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header),
|
||||
SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header));
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// if nothing exists, we cannot safely make a decision - delete
|
||||
}
|
||||
}
|
||||
else if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0) {
|
||||
SPIFFS_CHECK_DBG("LU: pix %04x busy in lu but deleted on page\n", cur_pix);
|
||||
delete_page = 1;
|
||||
} else if ((p_hdr->flags & SPIFFS_PH_FLAG_FINAL)) {
|
||||
SPIFFS_CHECK_DBG("LU: pix %04x busy but not final\n", cur_pix);
|
||||
// page can be removed if not referenced by object index
|
||||
*reload_lu = 1;
|
||||
res = spiffs_object_get_data_page_index_reference(fs, lu_obj_id, p_hdr->span_ix, &ref_pix, &objix_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
// no object with this id, so remove page safely
|
||||
res = SPIFFS_OK;
|
||||
delete_page = 1;
|
||||
} else {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (ref_pix != cur_pix) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: other finalized page is referred, just delete\n");
|
||||
delete_page = 1;
|
||||
} else {
|
||||
// page referenced by object index but not final
|
||||
// just finalize
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n");
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
|
||||
u8_t flags = 0xff & ~SPIFFS_PH_FLAG_FINAL;
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags),
|
||||
sizeof(u8_t), (u8_t*)&flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (delete_page) {
|
||||
SPIFFS_CHECK_DBG("LU: FIXUP: deleting page %04x\n", cur_pix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry,
|
||||
const void *user_const_p, void *user_var_p) {
|
||||
(void)user_const_p;
|
||||
(void)user_var_p;
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
|
||||
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS,
|
||||
(cur_block * 256)/fs->block_count, 0);
|
||||
|
||||
// load header
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
int reload_lu = 0;
|
||||
|
||||
res = spiffs_lookup_check_validate(fs, obj_id, &p_hdr, cur_pix, cur_block, cur_entry, &reload_lu);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
if (res == SPIFFS_OK) {
|
||||
return reload_lu ? SPIFFS_VIS_COUNTINUE_RELOAD : SPIFFS_VIS_COUNTINUE;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// Scans all object look up. For each entry, corresponding page header is checked for validity.
|
||||
// If an object index header page is found, this is also checked
|
||||
s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
|
||||
(void)check_all_objects;
|
||||
s32_t res = SPIFFS_OK;
|
||||
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0);
|
||||
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
|
||||
if (res != SPIFFS_OK) {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0);
|
||||
}
|
||||
|
||||
CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
// Page consistency
|
||||
|
||||
// Scans all pages (except lu pages), reserves 4 bits in working memory for each page
|
||||
// bit 0: 0 == FREE|DELETED, 1 == USED
|
||||
// bit 1: 0 == UNREFERENCED, 1 == REFERENCED
|
||||
// bit 2: 0 == NOT_INDEX, 1 == INDEX
|
||||
// bit 3: unused
|
||||
// A consistent file system will have only pages being
|
||||
// * x000 free, unreferenced, not index
|
||||
// * x011 used, referenced only once, not index
|
||||
// * x101 used, unreferenced, index
|
||||
// The working memory might not fit all pages so several scans might be needed
|
||||
static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
||||
const u32_t bits = 4;
|
||||
const spiffs_page_ix pages_per_scan = SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8 / bits;
|
||||
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_page_ix pix_offset = 0;
|
||||
|
||||
// for each range of pages fitting into work memory
|
||||
while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) {
|
||||
// set this flag to abort all checks and rescan the page range
|
||||
u8_t restart = 0;
|
||||
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
|
||||
spiffs_block_ix cur_block = 0;
|
||||
// build consistency bitmap for id range traversing all blocks
|
||||
while (!restart && cur_block < fs->block_count) {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS,
|
||||
(pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) +
|
||||
((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count),
|
||||
0);
|
||||
// traverse each page except for lookup pages
|
||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
|
||||
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) {
|
||||
//if ((cur_pix & 0xff) == 0)
|
||||
// SPIFFS_CHECK_DBG("PA: processing pix %08x, block %08x of pix %08x, block %08x\n",
|
||||
// cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count);
|
||||
|
||||
// read header
|
||||
spiffs_page_header p_hdr;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
u8_t within_range = (cur_pix >= pix_offset && cur_pix < pix_offset + pages_per_scan);
|
||||
const u32_t pix_byte_ix = (cur_pix - pix_offset) / (8/bits);
|
||||
const u8_t pix_bit_ix = (cur_pix & ((8/bits)-1)) * bits;
|
||||
|
||||
if (within_range &&
|
||||
(p_hdr.flags & SPIFFS_PH_FLAG_DELET) && (p_hdr.flags & SPIFFS_PH_FLAG_USED) == 0) {
|
||||
// used
|
||||
fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 0));
|
||||
}
|
||||
if ((p_hdr.flags & SPIFFS_PH_FLAG_DELET) &&
|
||||
(p_hdr.flags & SPIFFS_PH_FLAG_IXDELE) &&
|
||||
(p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) == 0) {
|
||||
// found non-deleted index
|
||||
if (within_range) {
|
||||
fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 2));
|
||||
}
|
||||
|
||||
// load non-deleted index
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
// traverse index for referenced pages
|
||||
spiffs_page_ix *object_page_index;
|
||||
spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work;
|
||||
|
||||
int entries;
|
||||
int i;
|
||||
spiffs_span_ix data_spix_offset;
|
||||
if (p_hdr.span_ix == 0) {
|
||||
// object header page index
|
||||
entries = SPIFFS_OBJ_HDR_IX_LEN(fs);
|
||||
data_spix_offset = 0;
|
||||
object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix_header));
|
||||
} else {
|
||||
// object page index
|
||||
entries = SPIFFS_OBJ_IX_LEN(fs);
|
||||
data_spix_offset = SPIFFS_OBJ_HDR_IX_LEN(fs) + SPIFFS_OBJ_IX_LEN(fs) * (p_hdr.span_ix - 1);
|
||||
object_page_index = (spiffs_page_ix *)((u8_t *)fs->lu_work + sizeof(spiffs_page_object_ix));
|
||||
}
|
||||
|
||||
// for all entries in index
|
||||
for (i = 0; !restart && i < entries; i++) {
|
||||
spiffs_page_ix rpix = object_page_index[i];
|
||||
u8_t rpix_within_range = rpix >= pix_offset && rpix < pix_offset + pages_per_scan;
|
||||
|
||||
if ((rpix != (spiffs_page_ix)-1 && rpix > SPIFFS_MAX_PAGES(fs))
|
||||
|| (rpix_within_range && SPIFFS_IS_LOOKUP_PAGE(fs, rpix))) {
|
||||
|
||||
// bad reference
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x bad pix / LU referenced from page %04x\n",
|
||||
rpix, cur_pix);
|
||||
// check for data page elsewhere
|
||||
spiffs_page_ix data_pix;
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
data_spix_offset + i, 0, &data_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
data_pix = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (data_pix == 0) {
|
||||
// if not, allocate free page
|
||||
spiffs_page_header new_ph;
|
||||
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
|
||||
new_ph.obj_id = objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
new_ph.span_ix = data_spix_offset + i;
|
||||
res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &data_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: found no existing data page, created new @ %04x\n", data_pix);
|
||||
}
|
||||
// remap index
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: rewriting index pix %04x\n", cur_pix);
|
||||
res = spiffs_rewrite_index(fs, objix_p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
|
||||
data_spix_offset + i, data_pix, cur_pix);
|
||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend - delete object\n", res);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
|
||||
// delete file
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
} else {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
|
||||
} else if (rpix_within_range) {
|
||||
|
||||
// valid reference
|
||||
// read referenced page header
|
||||
spiffs_page_header rp_hdr;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
// cross reference page header check
|
||||
if (rp_hdr.obj_id != (p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) ||
|
||||
rp_hdr.span_ix != data_spix_offset + i ||
|
||||
(rp_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) !=
|
||||
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX)) {
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x has inconsistent page header ix id/span:%04x/%04x, ref id/span:%04x/%04x flags:%02x\n",
|
||||
rpix, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, data_spix_offset + i,
|
||||
rp_hdr.obj_id, rp_hdr.span_ix, rp_hdr.flags);
|
||||
// try finding correct page
|
||||
spiffs_page_ix data_pix;
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
data_spix_offset + i, rpix, &data_pix);
|
||||
if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
res = SPIFFS_OK;
|
||||
data_pix = 0;
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (data_pix == 0) {
|
||||
// not found, this index is badly borked
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id %04x\n", p_hdr.obj_id);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
break;
|
||||
} else {
|
||||
// found it, so rewrite index
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: found correct data pix %04x, rewrite ix pix %04x id %04x\n",
|
||||
data_pix, cur_pix, p_hdr.obj_id);
|
||||
res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix);
|
||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
} else {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// mark rpix as referenced
|
||||
const u32_t rpix_byte_ix = (rpix - pix_offset) / (8/bits);
|
||||
const u8_t rpix_bit_ix = (rpix & ((8/bits)-1)) * bits;
|
||||
if (fs->work[rpix_byte_ix] & (1<<(rpix_bit_ix + 1))) {
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x multiple referenced from page %04x\n",
|
||||
rpix, cur_pix);
|
||||
// Here, we should have fixed all broken references - getting this means there
|
||||
// must be multiple files with same object id. Only solution is to delete
|
||||
// the object which is referring to this page
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: removing object %04x and page %04x\n",
|
||||
p_hdr.obj_id, cur_pix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// extra precaution, delete this page also
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
}
|
||||
fs->work[rpix_byte_ix] |= (1<<(rpix_bit_ix + 1));
|
||||
}
|
||||
}
|
||||
} // for all index entries
|
||||
} // found index
|
||||
|
||||
// next page
|
||||
cur_pix++;
|
||||
}
|
||||
// next block
|
||||
cur_block++;
|
||||
}
|
||||
// check consistency bitmap
|
||||
if (!restart) {
|
||||
spiffs_page_ix objix_pix;
|
||||
spiffs_page_ix rpix;
|
||||
|
||||
u32_t byte_ix;
|
||||
u8_t bit_ix;
|
||||
for (byte_ix = 0; !restart && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs); byte_ix++) {
|
||||
for (bit_ix = 0; !restart && bit_ix < 8/bits; bit_ix ++) {
|
||||
u8_t bitmask = (fs->work[byte_ix] >> (bit_ix * bits)) & 0x7;
|
||||
spiffs_page_ix cur_pix = pix_offset + byte_ix * (8/bits) + bit_ix;
|
||||
|
||||
// 000 ok - free, unreferenced, not index
|
||||
|
||||
if (bitmask == 0x1) {
|
||||
|
||||
// 001
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x USED, UNREFERENCED, not index\n", cur_pix);
|
||||
|
||||
u8_t rewrite_ix_to_this = 0;
|
||||
u8_t delete_page = 0;
|
||||
// check corresponding object index entry
|
||||
spiffs_page_header p_hdr;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_object_get_data_page_index_reference(fs, p_hdr.obj_id, p_hdr.span_ix,
|
||||
&rpix, &objix_pix);
|
||||
if (res == SPIFFS_OK) {
|
||||
if (((rpix == (spiffs_page_ix)-1 || rpix > SPIFFS_MAX_PAGES(fs)) || (SPIFFS_IS_LOOKUP_PAGE(fs, rpix)))) {
|
||||
// pointing to a bad page altogether, rewrite index to this
|
||||
rewrite_ix_to_this = 1;
|
||||
SPIFFS_CHECK_DBG("PA: corresponding ref is bad: %04x, rewrite to this %04x\n", rpix, cur_pix);
|
||||
} else {
|
||||
// pointing to something else, check what
|
||||
spiffs_page_header rp_hdr;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (((p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) == rp_hdr.obj_id) &&
|
||||
((rp_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL)) ==
|
||||
(SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET))) {
|
||||
// pointing to something else valid, just delete this page then
|
||||
SPIFFS_CHECK_DBG("PA: corresponding ref is good but different: %04x, delete this %04x\n", rpix, cur_pix);
|
||||
delete_page = 1;
|
||||
} else {
|
||||
// pointing to something weird, update index to point to this page instead
|
||||
if (rpix != cur_pix) {
|
||||
SPIFFS_CHECK_DBG("PA: corresponding ref is weird: %04x %s%s%s%s, rewrite this %04x\n", rpix,
|
||||
(rp_hdr.flags & SPIFFS_PH_FLAG_INDEX) ? "" : "INDEX ",
|
||||
(rp_hdr.flags & SPIFFS_PH_FLAG_DELET) ? "" : "DELETED ",
|
||||
(rp_hdr.flags & SPIFFS_PH_FLAG_USED) ? "NOTUSED " : "",
|
||||
(rp_hdr.flags & SPIFFS_PH_FLAG_FINAL) ? "NOTFINAL " : "",
|
||||
cur_pix);
|
||||
rewrite_ix_to_this = 1;
|
||||
} else {
|
||||
// should not happen, destined for fubar
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
SPIFFS_CHECK_DBG("PA: corresponding ref not found, delete %04x\n", cur_pix);
|
||||
delete_page = 1;
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
|
||||
if (rewrite_ix_to_this) {
|
||||
// if pointing to invalid page, redirect index to this page
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: rewrite index id %04x data spix %04x to point to this pix: %04x\n",
|
||||
p_hdr.obj_id, p_hdr.span_ix, cur_pix);
|
||||
res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix);
|
||||
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
|
||||
// index bad also, cannot mend this file
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||
} else {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
restart = 1;
|
||||
continue;
|
||||
} else if (delete_page) {
|
||||
SPIFFS_CHECK_DBG("PA: FIXUP: deleting page %04x\n", cur_pix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
if (bitmask == 0x2) {
|
||||
|
||||
// 010
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x FREE, REFERENCED, not index\n", cur_pix);
|
||||
|
||||
// no op, this should be taken care of when checking valid references
|
||||
}
|
||||
|
||||
// 011 ok - busy, referenced, not index
|
||||
|
||||
if (bitmask == 0x4) {
|
||||
|
||||
// 100
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x FREE, unreferenced, INDEX\n", cur_pix);
|
||||
|
||||
// this should never happen, major fubar
|
||||
}
|
||||
|
||||
// 101 ok - busy, unreferenced, index
|
||||
|
||||
if (bitmask == 0x6) {
|
||||
|
||||
// 110
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x FREE, REFERENCED, INDEX\n", cur_pix);
|
||||
|
||||
// no op, this should be taken care of when checking valid references
|
||||
}
|
||||
if (bitmask == 0x7) {
|
||||
|
||||
// 111
|
||||
SPIFFS_CHECK_DBG("PA: pix %04x USED, REFERENCED, INDEX\n", cur_pix);
|
||||
|
||||
// no op, this should be taken care of when checking valid references
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_DBG("PA: processed %04x, restart %i\n", pix_offset, restart);
|
||||
// next page range
|
||||
if (!restart) {
|
||||
pix_offset += pages_per_scan;
|
||||
}
|
||||
} // while page range not reached end
|
||||
return res;
|
||||
}
|
||||
|
||||
// Checks consistency amongst all pages and fixes irregularities
|
||||
s32_t spiffs_page_consistency_check(spiffs *fs) {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
s32_t res = spiffs_page_consistency_check_i(fs);
|
||||
if (res != SPIFFS_OK) {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0);
|
||||
}
|
||||
CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
//---------------------------------------
|
||||
// Object index consistency
|
||||
|
||||
// searches for given object id in temporary object id index,
|
||||
// returns the index or -1
|
||||
static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
|
||||
u32_t i;
|
||||
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
|
||||
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id); i++) {
|
||||
if ((obj_table[i] & ~SPIFFS_OBJ_ID_IX_FLAG) == obj_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block,
|
||||
int cur_entry, const void *user_const_p, void *user_var_p) {
|
||||
(void)user_const_p;
|
||||
s32_t res_c = SPIFFS_VIS_COUNTINUE;
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t *log_ix = (u32_t*)user_var_p;
|
||||
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
|
||||
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS,
|
||||
(cur_block * 256)/fs->block_count, 0);
|
||||
|
||||
if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
|
||||
|
||||
// load header
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
if (p_hdr.span_ix == 0 &&
|
||||
(p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) ==
|
||||
(SPIFFS_PH_FLAG_DELET)) {
|
||||
SPIFFS_CHECK_DBG("IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting\n",
|
||||
cur_pix, obj_id, p_hdr.span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
return res_c;
|
||||
}
|
||||
|
||||
if ((p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) ==
|
||||
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
|
||||
return res_c;
|
||||
}
|
||||
|
||||
if (p_hdr.span_ix == 0) {
|
||||
// objix header page, register objid as reachable
|
||||
int r = spiffs_object_index_search(fs, obj_id);
|
||||
if (r == -1) {
|
||||
// not registered, do it
|
||||
obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
(*log_ix)++;
|
||||
if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) {
|
||||
*log_ix = 0;
|
||||
}
|
||||
}
|
||||
} else { // span index
|
||||
// objix page, see if header can be found
|
||||
int r = spiffs_object_index_search(fs, obj_id);
|
||||
u8_t delete = 0;
|
||||
if (r == -1) {
|
||||
// not in temporary index, try finding it
|
||||
spiffs_page_ix objix_hdr_pix;
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &objix_hdr_pix);
|
||||
res_c = SPIFFS_VIS_COUNTINUE_RELOAD;
|
||||
if (res == SPIFFS_OK) {
|
||||
// found, register as reachable
|
||||
obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
} else if (res == SPIFFS_ERR_NOT_FOUND) {
|
||||
// not found, register as unreachable
|
||||
delete = 1;
|
||||
obj_table[*log_ix] = obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
} else {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
(*log_ix)++;
|
||||
if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) {
|
||||
*log_ix = 0;
|
||||
}
|
||||
} else {
|
||||
// in temporary index, check reachable flag
|
||||
if ((obj_table[r] & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
// registered as unreachable
|
||||
delete = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (delete) {
|
||||
SPIFFS_CHECK_DBG("IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting\n",
|
||||
cur_pix, obj_id, p_hdr.span_ix);
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
} // span index
|
||||
} // valid object index id
|
||||
|
||||
return res_c;
|
||||
}
|
||||
|
||||
// Removes orphaned and partially deleted index pages.
|
||||
// Scans for index pages. When an index page is found, corresponding index header is searched for.
|
||||
// If no such page exists, the index page cannot be reached as no index header exists and must be
|
||||
// deleted.
|
||||
s32_t spiffs_object_index_consistency_check(spiffs *fs) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
// impl note:
|
||||
// fs->work is used for a temporary object index memory, listing found object ids and
|
||||
// indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit.
|
||||
// In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate
|
||||
// a reachable/unreachable object id.
|
||||
memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
u32_t obj_id_log_ix = 0;
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0);
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, &obj_id_log_ix,
|
||||
0, 0, 0);
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_OK;
|
||||
}
|
||||
if (res != SPIFFS_OK) {
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0);
|
||||
}
|
||||
CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
253
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_config.h
Normal file
253
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_config.h
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* spiffs_config.h
|
||||
*
|
||||
* Created on: Jul 3, 2013
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
#ifndef SPIFFS_CONFIG_H_
|
||||
#define SPIFFS_CONFIG_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define c_memcpy memcpy
|
||||
#define c_printf printf
|
||||
#define c_memset memset
|
||||
|
||||
typedef int16_t file_t;
|
||||
typedef int32_t s32_t;
|
||||
typedef uint32_t u32_t;
|
||||
typedef int16_t s16_t;
|
||||
typedef uint16_t u16_t;
|
||||
typedef int8_t s8_t;
|
||||
typedef uint8_t u8_t;
|
||||
|
||||
#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
|
||||
|
||||
#ifndef EOF
|
||||
#define EOF (-1)
|
||||
#endif
|
||||
|
||||
// compile time switches
|
||||
|
||||
// Set generic spiffs debug output call.
|
||||
#ifndef SPIFFS_DBG
|
||||
#define SPIFFS_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for garbage collecting.
|
||||
#ifndef SPIFFS_GC_DBG
|
||||
#define SPIFFS_GC_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for caching.
|
||||
#ifndef SPIFFS_CACHE_DBG
|
||||
#define SPIFFS_CACHE_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
// Set spiffs debug output call for system consistency checks.
|
||||
#ifndef SPIFFS_CHECK_DBG
|
||||
#define SPIFFS_CHECK_DBG(...) //printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// Enable/disable API functions to determine exact number of bytes
|
||||
// for filedescriptor and cache buffers. Once decided for a configuration,
|
||||
// this can be disabled to reduce flash.
|
||||
#ifndef SPIFFS_BUFFER_HELP
|
||||
#define SPIFFS_BUFFER_HELP 1
|
||||
#endif
|
||||
|
||||
// Enables/disable memory read caching of nucleus file system operations.
|
||||
// If enabled, memory area must be provided for cache in SPIFFS_mount.
|
||||
#ifndef SPIFFS_CACHE
|
||||
#define SPIFFS_CACHE 1
|
||||
#endif
|
||||
#if SPIFFS_CACHE
|
||||
// Enables memory write caching for file descriptors in hydrogen
|
||||
#ifndef SPIFFS_CACHE_WR
|
||||
#define SPIFFS_CACHE_WR 1
|
||||
#endif
|
||||
|
||||
// Enable/disable statistics on caching. Debug/test purpose only.
|
||||
#ifndef SPIFFS_CACHE_STATS
|
||||
#define SPIFFS_CACHE_STATS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Always check header of each accessed page to ensure consistent state.
|
||||
// If enabled it will increase number of reads, will increase flash.
|
||||
#ifndef SPIFFS_PAGE_CHECK
|
||||
#define SPIFFS_PAGE_CHECK 1
|
||||
#endif
|
||||
|
||||
// Define maximum number of gc runs to perform to reach desired free pages.
|
||||
#ifndef SPIFFS_GC_MAX_RUNS
|
||||
#define SPIFFS_GC_MAX_RUNS 5
|
||||
#endif
|
||||
|
||||
// Enable/disable statistics on gc. Debug/test purpose only.
|
||||
#ifndef SPIFFS_GC_STATS
|
||||
#define SPIFFS_GC_STATS 0
|
||||
#endif
|
||||
|
||||
// Garbage collecting examines all pages in a block which and sums up
|
||||
// to a block score. Deleted pages normally gives positive score and
|
||||
// used pages normally gives a negative score (as these must be moved).
|
||||
// To have a fair wear-leveling, the erase age is also included in score,
|
||||
// whose factor normally is the most positive.
|
||||
// The larger the score, the more likely it is that the block will
|
||||
// picked for garbage collection.
|
||||
|
||||
// Garbage collecting heuristics - weight used for deleted pages.
|
||||
#ifndef SPIFFS_GC_HEUR_W_DELET
|
||||
#define SPIFFS_GC_HEUR_W_DELET (5)
|
||||
#endif
|
||||
// Garbage collecting heuristics - weight used for used pages.
|
||||
#ifndef SPIFFS_GC_HEUR_W_USED
|
||||
#define SPIFFS_GC_HEUR_W_USED (-1)
|
||||
#endif
|
||||
// Garbage collecting heuristics - weight used for time between
|
||||
// last erased and erase of this block.
|
||||
#ifndef SPIFFS_GC_HEUR_W_ERASE_AGE
|
||||
#define SPIFFS_GC_HEUR_W_ERASE_AGE (50)
|
||||
#endif
|
||||
|
||||
// Object name maximum length.
|
||||
#ifndef SPIFFS_OBJ_NAME_LEN
|
||||
#define SPIFFS_OBJ_NAME_LEN (32)
|
||||
#endif
|
||||
|
||||
// Size of buffer allocated on stack used when copying data.
|
||||
// Lower value generates more read/writes. No meaning having it bigger
|
||||
// than logical page size.
|
||||
#ifndef SPIFFS_COPY_BUFFER_STACK
|
||||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||
#endif
|
||||
|
||||
// Enable this to have an identifiable spiffs filesystem. This will look for
|
||||
// a magic in all sectors to determine if this is a valid spiffs system or
|
||||
// not on mount point. If not, SPIFFS_format must be called prior to mounting
|
||||
// again.
|
||||
#ifndef SPIFFS_USE_MAGIC
|
||||
#define SPIFFS_USE_MAGIC (1)
|
||||
#endif
|
||||
|
||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||
// These should be defined on a multithreaded system
|
||||
|
||||
// define this to enter a mutex if you're running on a multithreaded system
|
||||
#ifndef SPIFFS_LOCK
|
||||
#define SPIFFS_LOCK(fs)
|
||||
#endif
|
||||
// define this to exit a mutex if you're running on a multithreaded system
|
||||
#ifndef SPIFFS_UNLOCK
|
||||
#define SPIFFS_UNLOCK(fs)
|
||||
#endif
|
||||
|
||||
|
||||
// Enable if only one spiffs instance with constant configuration will exist
|
||||
// on the target. This will reduce calculations, flash and memory accesses.
|
||||
// Parts of configuration must be defined below instead of at time of mount.
|
||||
#ifndef SPIFFS_SINGLETON
|
||||
#define SPIFFS_SINGLETON 0
|
||||
#endif
|
||||
|
||||
#if SPIFFS_SINGLETON
|
||||
// Instead of giving parameters in config struct, singleton build must
|
||||
// give parameters in defines below.
|
||||
#ifndef SPIFFS_CFG_PHYS_SZ
|
||||
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2)
|
||||
#endif
|
||||
#ifndef SPIFFS_CFG_PHYS_ERASE_SZ
|
||||
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536)
|
||||
#endif
|
||||
#ifndef SPIFFS_CFG_PHYS_ADDR
|
||||
#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
|
||||
#endif
|
||||
#ifndef SPIFFS_CFG_LOG_PAGE_SZ
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(ignore) (256)
|
||||
#endif
|
||||
#ifndef SPIFFS_CFG_LOG_BLOCK_SZ
|
||||
#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Enable this if your target needs aligned data for index tables
|
||||
#ifndef SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||
#define SPIFFS_ALIGNED_OBJECT_INDEX_TABLES 1
|
||||
#endif
|
||||
|
||||
// Enable this if you want the HAL callbacks to be called with the spiffs struct
|
||||
#ifndef SPIFFS_HAL_CALLBACK_EXTRA
|
||||
#define SPIFFS_HAL_CALLBACK_EXTRA 0
|
||||
#endif
|
||||
|
||||
// Enable this if you want to add an integer offset to all file handles
|
||||
// (spiffs_file). This is useful if running multiple instances of spiffs on
|
||||
// same target, in order to recognise to what spiffs instance a file handle
|
||||
// belongs.
|
||||
// NB: This adds config field fh_ix_offset in the configuration struct when
|
||||
// mounting, which must be defined.
|
||||
#ifndef SPIFFS_FILEHDL_OFFSET
|
||||
#define SPIFFS_FILEHDL_OFFSET 0
|
||||
#endif
|
||||
|
||||
// Set SPIFFS_TEST_VISUALISATION to non-zero to enable SPIFFS_vis function
|
||||
// in the api. This function will visualize all filesystem using given printf
|
||||
// function.
|
||||
#ifndef SPIFFS_TEST_VISUALISATION
|
||||
#define SPIFFS_TEST_VISUALISATION 1
|
||||
#endif
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
#ifndef spiffs_printf
|
||||
#define spiffs_printf(...) c_printf(__VA_ARGS__)
|
||||
#endif
|
||||
// spiffs_printf argument for a free page
|
||||
#ifndef SPIFFS_TEST_VIS_FREE_STR
|
||||
#define SPIFFS_TEST_VIS_FREE_STR "_"
|
||||
#endif
|
||||
// spiffs_printf argument for a deleted page
|
||||
#ifndef SPIFFS_TEST_VIS_DELE_STR
|
||||
#define SPIFFS_TEST_VIS_DELE_STR "/"
|
||||
#endif
|
||||
// spiffs_printf argument for an index page for given object id
|
||||
#ifndef SPIFFS_TEST_VIS_INDX_STR
|
||||
#define SPIFFS_TEST_VIS_INDX_STR(id) "i"
|
||||
#endif
|
||||
// spiffs_printf argument for a data page for given object id
|
||||
#ifndef SPIFFS_TEST_VIS_DATA_STR
|
||||
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Types depending on configuration such as the amount of flash bytes
|
||||
// given to spiffs file system in total (spiffs_file_system_size),
|
||||
// the logical block size (log_block_size), and the logical page size
|
||||
// (log_page_size)
|
||||
|
||||
// Block index type. Make sure the size of this type can hold
|
||||
// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size
|
||||
typedef u16_t spiffs_block_ix;
|
||||
// Page index type. Make sure the size of this type can hold
|
||||
// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size
|
||||
typedef u16_t spiffs_page_ix;
|
||||
// Object id type - most significant bit is reserved for index flag. Make sure the
|
||||
// size of this type can hold the highest object id on a full system,
|
||||
// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2
|
||||
typedef u16_t spiffs_obj_id;
|
||||
// Object span index type. Make sure the size of this type can
|
||||
// hold the largest possible span index on the system -
|
||||
// i.e. (spiffs_file_system_size / log_page_size) - 1
|
||||
typedef u16_t spiffs_span_ix;
|
||||
|
||||
#endif /* SPIFFS_CONFIG_H_ */
|
||||
576
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_gc.c
Normal file
576
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_gc.c
Normal file
@@ -0,0 +1,576 @@
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
#if !SPIFFS_READ_ONLY
|
||||
|
||||
// Erases a logical block and updates the erase counter.
|
||||
// If cache is enabled, all pages that might be cached in this block
|
||||
// is dropped.
|
||||
static s32_t spiffs_gc_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
s32_t res;
|
||||
|
||||
SPIFFS_GC_DBG("gc: erase block %i\n", bix);
|
||||
res = spiffs_erase_block(fs, bix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
{
|
||||
u32_t i;
|
||||
for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) {
|
||||
spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, bix) + i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
// Searches for blocks where all entries are deleted - if one is found,
|
||||
// the block is erased. Compared to the non-quick gc, the quick one ensures
|
||||
// that no updates are needed on existing objects on pages that are erased.
|
||||
s32_t spiffs_gc_quick(
|
||||
spiffs *fs, u16_t max_free_pages) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t blocks = fs->block_count;
|
||||
spiffs_block_ix cur_block = 0;
|
||||
u32_t cur_block_addr = 0;
|
||||
int cur_entry = 0;
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
|
||||
SPIFFS_GC_DBG("gc_quick: running\n");
|
||||
#if SPIFFS_GC_STATS
|
||||
fs->stats_gc_runs++;
|
||||
#endif
|
||||
|
||||
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
|
||||
|
||||
// find fully deleted blocks
|
||||
// check each block
|
||||
while (res == SPIFFS_OK && blocks--) {
|
||||
u16_t deleted_pages_in_block = 0;
|
||||
u16_t free_pages_in_block = 0;
|
||||
|
||||
int obj_lookup_page = 0;
|
||||
// check each object lookup page
|
||||
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
int entry_offset = obj_lookup_page * entries_per_page;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
// check each entry
|
||||
while (res == SPIFFS_OK &&
|
||||
cur_entry - entry_offset < entries_per_page &&
|
||||
cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
deleted_pages_in_block++;
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
// kill scan, go for next block
|
||||
free_pages_in_block++;
|
||||
if (free_pages_in_block > max_free_pages) {
|
||||
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||
res = 1; // kill object lu loop
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// kill scan, go for next block
|
||||
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||
res = 1; // kill object lu loop
|
||||
break;
|
||||
}
|
||||
cur_entry++;
|
||||
} // per entry
|
||||
obj_lookup_page++;
|
||||
} // per object lookup page
|
||||
if (res == 1) res = SPIFFS_OK;
|
||||
|
||||
if (res == SPIFFS_OK &&
|
||||
deleted_pages_in_block + free_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs) &&
|
||||
free_pages_in_block <= max_free_pages) {
|
||||
// found a fully deleted block
|
||||
fs->stats_p_deleted -= deleted_pages_in_block;
|
||||
res = spiffs_gc_erase_block(fs, cur_block);
|
||||
return res;
|
||||
}
|
||||
|
||||
cur_entry = 0;
|
||||
cur_block++;
|
||||
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
} // per block
|
||||
|
||||
if (res == SPIFFS_OK) {
|
||||
res = SPIFFS_ERR_NO_DELETED_BLOCKS;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Checks if garbage collecting is necessary. If so a candidate block is found,
|
||||
// cleansed and erased
|
||||
s32_t spiffs_gc_check(
|
||||
spiffs *fs,
|
||||
u32_t len) {
|
||||
s32_t res;
|
||||
s32_t free_pages =
|
||||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count-2)
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
int tries = 0;
|
||||
|
||||
if (fs->free_blocks > 3 &&
|
||||
(s32_t)len < free_pages * (s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
|
||||
u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
|
||||
// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
|
||||
// SPIFFS_GC_DBG("gc: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||
// return SPIFFS_ERR_FULL;
|
||||
// }
|
||||
if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
|
||||
SPIFFS_GC_DBG("gc_check: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
|
||||
return SPIFFS_ERR_FULL;
|
||||
}
|
||||
|
||||
do {
|
||||
SPIFFS_GC_DBG("\ngc_check #%i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
|
||||
tries,
|
||||
fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages+fs->stats_p_allocated+fs->stats_p_deleted),
|
||||
len, free_pages*SPIFFS_DATA_PAGE_SIZE(fs));
|
||||
|
||||
spiffs_block_ix *cands;
|
||||
int count;
|
||||
spiffs_block_ix cand;
|
||||
s32_t prev_free_pages = free_pages;
|
||||
// if the fs is crammed, ignore block age when selecting candidate - kind of a bad state
|
||||
res = spiffs_gc_find_candidate(fs, &cands, &count, free_pages <= 0);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (count == 0) {
|
||||
SPIFFS_GC_DBG("gc_check: no candidates, return\n");
|
||||
return (s32_t)needed_pages < free_pages ? SPIFFS_OK : SPIFFS_ERR_FULL;
|
||||
}
|
||||
#if SPIFFS_GC_STATS
|
||||
fs->stats_gc_runs++;
|
||||
#endif
|
||||
cand = cands[0];
|
||||
fs->cleaning = 1;
|
||||
//printf("gcing: cleaning block %i\n", cand);
|
||||
res = spiffs_gc_clean(fs, cand);
|
||||
fs->cleaning = 0;
|
||||
if (res < 0) {
|
||||
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
|
||||
} else {
|
||||
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_gc_erase_page_stats(fs, cand);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_gc_erase_block(fs, cand);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
free_pages =
|
||||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
|
||||
if (prev_free_pages <= 0 && prev_free_pages == free_pages) {
|
||||
// abort early to reduce wear, at least tried once
|
||||
SPIFFS_GC_DBG("gc_check: early abort, no result on gc when fs crammed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
||||
(s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||
|
||||
free_pages =
|
||||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * (fs->block_count - 2)
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
if ((s32_t)len > free_pages*(s32_t)SPIFFS_DATA_PAGE_SIZE(fs)) {
|
||||
res = SPIFFS_ERR_FULL;
|
||||
}
|
||||
|
||||
SPIFFS_GC_DBG("gc_check: finished, %i dirty, blocks %i free, %i pages free, %i tries, res %i\n",
|
||||
fs->stats_p_allocated + fs->stats_p_deleted,
|
||||
fs->free_blocks, free_pages, tries, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Updates page statistics for a block that is about to be erased
|
||||
s32_t spiffs_gc_erase_page_stats(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
int obj_lookup_page = 0;
|
||||
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
int cur_entry = 0;
|
||||
u32_t dele = 0;
|
||||
u32_t allo = 0;
|
||||
|
||||
// check each object lookup page
|
||||
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
int entry_offset = obj_lookup_page * entries_per_page;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
// check each entry
|
||||
while (res == SPIFFS_OK &&
|
||||
cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
dele++;
|
||||
} else {
|
||||
allo++;
|
||||
}
|
||||
cur_entry++;
|
||||
} // per entry
|
||||
obj_lookup_page++;
|
||||
} // per object lookup page
|
||||
SPIFFS_GC_DBG("gc_check: wipe pallo:%i pdele:%i\n", allo, dele);
|
||||
fs->stats_p_allocated -= allo;
|
||||
fs->stats_p_deleted -= dele;
|
||||
return res;
|
||||
}
|
||||
|
||||
// Finds block candidates to erase
|
||||
s32_t spiffs_gc_find_candidate(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix **block_candidates,
|
||||
int *candidate_count,
|
||||
char fs_crammed) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t blocks = fs->block_count;
|
||||
spiffs_block_ix cur_block = 0;
|
||||
u32_t cur_block_addr = 0;
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
int cur_entry = 0;
|
||||
|
||||
// using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score
|
||||
int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(s32_t)));
|
||||
*candidate_count = 0;
|
||||
memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
|
||||
// divide up work area into block indices and scores
|
||||
spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
|
||||
s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
|
||||
|
||||
// align cand_scores on s32_t boundary
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
|
||||
cand_scores = (s32_t*)(((ptrdiff_t)cand_scores + sizeof(ptrdiff_t) - 1) & ~(sizeof(ptrdiff_t) - 1));
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
*block_candidates = cand_blocks;
|
||||
|
||||
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
|
||||
|
||||
// check each block
|
||||
while (res == SPIFFS_OK && blocks--) {
|
||||
u16_t deleted_pages_in_block = 0;
|
||||
u16_t used_pages_in_block = 0;
|
||||
|
||||
int obj_lookup_page = 0;
|
||||
// check each object lookup page
|
||||
while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
int entry_offset = obj_lookup_page * entries_per_page;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
// check each entry
|
||||
while (res == SPIFFS_OK &&
|
||||
cur_entry - entry_offset < entries_per_page &&
|
||||
cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
// when a free entry is encountered, scan logic ensures that all following entries are free also
|
||||
res = 1; // kill object lu loop
|
||||
break;
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
deleted_pages_in_block++;
|
||||
} else {
|
||||
used_pages_in_block++;
|
||||
}
|
||||
cur_entry++;
|
||||
} // per entry
|
||||
obj_lookup_page++;
|
||||
} // per object lookup page
|
||||
if (res == 1) res = SPIFFS_OK;
|
||||
|
||||
// calculate score and insert into candidate table
|
||||
// stoneage sort, but probably not so many blocks
|
||||
if (res == SPIFFS_OK && deleted_pages_in_block > 0) {
|
||||
// read erase count
|
||||
spiffs_obj_id erase_count;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, cur_block),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
spiffs_obj_id erase_age;
|
||||
if (fs->max_erase_count > erase_count) {
|
||||
erase_age = fs->max_erase_count - erase_count;
|
||||
} else {
|
||||
erase_age = SPIFFS_OBJ_ID_FREE - (erase_count - fs->max_erase_count);
|
||||
}
|
||||
|
||||
s32_t score =
|
||||
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
|
||||
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
|
||||
erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
|
||||
int cand_ix = 0;
|
||||
SPIFFS_GC_DBG("gc_check: bix:%i del:%i use:%i score:%i\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
|
||||
while (cand_ix < max_candidates) {
|
||||
if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
|
||||
cand_blocks[cand_ix] = cur_block;
|
||||
cand_scores[cand_ix] = score;
|
||||
break;
|
||||
} else if (cand_scores[cand_ix] < score) {
|
||||
int reorder_cand_ix = max_candidates - 2;
|
||||
while (reorder_cand_ix >= cand_ix) {
|
||||
cand_blocks[reorder_cand_ix + 1] = cand_blocks[reorder_cand_ix];
|
||||
cand_scores[reorder_cand_ix + 1] = cand_scores[reorder_cand_ix];
|
||||
reorder_cand_ix--;
|
||||
}
|
||||
cand_blocks[cand_ix] = cur_block;
|
||||
cand_scores[cand_ix] = score;
|
||||
break;
|
||||
}
|
||||
cand_ix++;
|
||||
}
|
||||
(*candidate_count)++;
|
||||
}
|
||||
|
||||
cur_entry = 0;
|
||||
cur_block++;
|
||||
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
} // per block
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
FIND_OBJ_DATA,
|
||||
MOVE_OBJ_DATA,
|
||||
MOVE_OBJ_IX,
|
||||
FINISHED
|
||||
} spiffs_gc_clean_state;
|
||||
|
||||
typedef struct {
|
||||
spiffs_gc_clean_state state;
|
||||
spiffs_obj_id cur_obj_id;
|
||||
spiffs_span_ix cur_objix_spix;
|
||||
spiffs_page_ix cur_objix_pix;
|
||||
int stored_scan_entry_index;
|
||||
u8_t obj_id_found;
|
||||
} spiffs_gc;
|
||||
|
||||
// Empties given block by moving all data into free pages of another block
|
||||
// Strategy:
|
||||
// loop:
|
||||
// scan object lookup for object data pages
|
||||
// for first found id, check spix and load corresponding object index page to memory
|
||||
// push object scan lookup entry index
|
||||
// rescan object lookup, find data pages with same id and referenced by same object index
|
||||
// move data page, update object index in memory
|
||||
// when reached end of lookup, store updated object index
|
||||
// pop object scan lookup entry index
|
||||
// repeat loop until end of object lookup
|
||||
// scan object lookup again for remaining object index pages, move to new page in other block
|
||||
//
|
||||
s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
|
||||
int cur_entry = 0;
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
spiffs_gc gc;
|
||||
spiffs_page_ix cur_pix = 0;
|
||||
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
||||
spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
|
||||
|
||||
SPIFFS_GC_DBG("gc_clean: cleaning block %i\n", bix);
|
||||
|
||||
memset(&gc, 0, sizeof(spiffs_gc));
|
||||
gc.state = FIND_OBJ_DATA;
|
||||
|
||||
if (fs->free_cursor_block_ix == bix) {
|
||||
// move free cursor to next block, cannot use free pages from the block we want to clean
|
||||
fs->free_cursor_block_ix = (bix+1)%fs->block_count;
|
||||
fs->free_cursor_obj_lu_entry = 0;
|
||||
SPIFFS_GC_DBG("gc_clean: move free cursor to block %i\n", fs->free_cursor_block_ix);
|
||||
}
|
||||
|
||||
while (res == SPIFFS_OK && gc.state != FINISHED) {
|
||||
SPIFFS_GC_DBG("gc_clean: state = %i entry:%i\n", gc.state, cur_entry);
|
||||
gc.obj_id_found = 0;
|
||||
|
||||
// scan through lookup pages
|
||||
int obj_lookup_page = cur_entry / entries_per_page;
|
||||
u8_t scan = 1;
|
||||
// check each object lookup page
|
||||
while (scan && res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
int entry_offset = obj_lookup_page * entries_per_page;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
// check each entry
|
||||
while (scan && res == SPIFFS_OK &&
|
||||
cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, cur_entry);
|
||||
|
||||
// act upon object id depending on gc state
|
||||
switch (gc.state) {
|
||||
case FIND_OBJ_DATA:
|
||||
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
|
||||
((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) {
|
||||
SPIFFS_GC_DBG("gc_clean: FIND_DATA state:%i - found obj id %04x\n", gc.state, obj_id);
|
||||
gc.obj_id_found = 1;
|
||||
gc.cur_obj_id = obj_id;
|
||||
scan = 0;
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_DATA:
|
||||
if (obj_id == gc.cur_obj_id) {
|
||||
spiffs_page_header p_hdr;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA found data page %04x:%04x @ %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
|
||||
if (SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix) != gc.cur_objix_spix) {
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA no objix spix match, take in another run\n");
|
||||
} else {
|
||||
spiffs_page_ix new_data_pix;
|
||||
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
|
||||
// move page
|
||||
res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_data_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA move objix %04x:%04x page %04x to %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix, new_data_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// move wipes obj_lu, reload it
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// page is deleted but not deleted in lookup, scrap it
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
new_data_pix = SPIFFS_OBJ_ID_FREE;
|
||||
}
|
||||
// update memory representation of object index page with new data page
|
||||
if (gc.cur_objix_spix == 0) {
|
||||
// update object index header page
|
||||
((spiffs_page_ix*)((u8_t *)objix_hdr + sizeof(spiffs_page_object_ix_header)))[p_hdr.span_ix] = new_data_pix;
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page %04x to objix_hdr entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
|
||||
} else {
|
||||
// update object index page
|
||||
((spiffs_page_ix*)((u8_t *)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)] = new_data_pix;
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page %04x to objix entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_IX:
|
||||
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
|
||||
(obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
// found an index object id
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix new_pix;
|
||||
// load header
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
|
||||
// move page
|
||||
res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX move objix %04x:%04x page %04x to %04x\n", obj_id, p_hdr.span_ix, cur_pix, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, obj_id, p_hdr.span_ix, new_pix, 0);
|
||||
// move wipes obj_lu, reload it
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// page is deleted but not deleted in lookup, scrap it
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
if (res == SPIFFS_OK) {
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0);
|
||||
}
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
scan = 0;
|
||||
break;
|
||||
}
|
||||
cur_entry++;
|
||||
} // per entry
|
||||
obj_lookup_page++;
|
||||
} // per object lookup page
|
||||
|
||||
if (res != SPIFFS_OK) break;
|
||||
|
||||
// state finalization and switch
|
||||
switch (gc.state) {
|
||||
case FIND_OBJ_DATA:
|
||||
if (gc.obj_id_found) {
|
||||
// find out corresponding obj ix page and load it to memory
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix objix_pix;
|
||||
gc.stored_scan_entry_index = cur_entry;
|
||||
cur_entry = 0;
|
||||
gc.state = MOVE_OBJ_DATA;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
gc.cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix);
|
||||
SPIFFS_GC_DBG("gc_clean: FIND_DATA find objix span_ix:%04x\n", gc.cur_objix_spix);
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix, 0, &objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_GC_DBG("gc_clean: FIND_DATA found object index at page %04x\n", objix_pix);
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix);
|
||||
gc.cur_objix_pix = objix_pix;
|
||||
} else {
|
||||
gc.state = MOVE_OBJ_IX;
|
||||
cur_entry = 0; // restart entry scan index
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_DATA: {
|
||||
// store modified objix (hdr) page
|
||||
spiffs_page_ix new_objix_pix;
|
||||
gc.state = FIND_OBJ_DATA;
|
||||
cur_entry = gc.stored_scan_entry_index;
|
||||
if (gc.cur_objix_spix == 0) {
|
||||
// store object index header page
|
||||
res = spiffs_object_update_index_hdr(fs, 0, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_pix, fs->work, 0, 0, &new_objix_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, %04x:%04x\n", new_objix_pix, 0);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// store object index page
|
||||
res = spiffs_page_move(fs, 0, fs->work, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, gc.cur_objix_pix, &new_objix_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, %04x:%04x\n", new_objix_pix, objix->p_hdr.span_ix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, gc.cur_obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_IX:
|
||||
gc.state = FINISHED;
|
||||
break;
|
||||
default:
|
||||
cur_entry = 0;
|
||||
break;
|
||||
}
|
||||
SPIFFS_GC_DBG("gc_clean: state-> %i\n", gc.state);
|
||||
} // while state != FINISHED
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif // !SPIFFS_READ_ONLY
|
||||
1170
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_hydrogen.c
Normal file
1170
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_hydrogen.c
Normal file
File diff suppressed because it is too large
Load Diff
2005
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_nucleus.c
Normal file
2005
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_nucleus.c
Normal file
File diff suppressed because it is too large
Load Diff
751
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_nucleus.h
Normal file
751
arduino/realtek-ambz/cores/arduino/spiffs/spiffs_nucleus.h
Normal file
@@ -0,0 +1,751 @@
|
||||
/*
|
||||
* spiffs_nucleus.h
|
||||
*
|
||||
* Created on: Jun 15, 2013
|
||||
* Author: petera
|
||||
*/
|
||||
|
||||
/* SPIFFS layout
|
||||
*
|
||||
* spiffs is designed for following spi flash characteristics:
|
||||
* - only big areas of data (blocks) can be erased
|
||||
* - erasing resets all bits in a block to ones
|
||||
* - writing pulls ones to zeroes
|
||||
* - zeroes cannot be pulled to ones, without erase
|
||||
* - wear leveling
|
||||
*
|
||||
* spiffs is also meant to be run on embedded, memory constraint devices.
|
||||
*
|
||||
* Entire area is divided in blocks. Entire area is also divided in pages.
|
||||
* Each block contains same number of pages. A page cannot be erased, but a
|
||||
* block can be erased.
|
||||
*
|
||||
* Entire area must be block_size * x
|
||||
* page_size must be block_size / (2^y) where y > 2
|
||||
*
|
||||
* ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
|
||||
*
|
||||
* BLOCK 0 PAGE 0 object lookup 1
|
||||
* PAGE 1 object lookup 2
|
||||
* ...
|
||||
* PAGE n-1 object lookup n
|
||||
* PAGE n object data 1
|
||||
* PAGE n+1 object data 2
|
||||
* ...
|
||||
* PAGE n+m-1 object data m
|
||||
*
|
||||
* BLOCK 1 PAGE n+m object lookup 1
|
||||
* PAGE n+m+1 object lookup 2
|
||||
* ...
|
||||
* PAGE 2n+m-1 object lookup n
|
||||
* PAGE 2n+m object data 1
|
||||
* PAGE 2n+m object data 2
|
||||
* ...
|
||||
* PAGE 2n+2m-1 object data m
|
||||
* ...
|
||||
*
|
||||
* n is number of object lookup pages, which is number of pages needed to index all pages
|
||||
* in a block by object id
|
||||
* : block_size / page_size * sizeof(obj_id) / page_size
|
||||
* m is number data pages, which is number of pages in block minus number of lookup pages
|
||||
* : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
|
||||
* thus, n+m is total number of pages in a block
|
||||
* : block_size / page_size
|
||||
*
|
||||
* ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
|
||||
*
|
||||
* Object lookup pages contain object id entries. Each entry represent the corresponding
|
||||
* data page.
|
||||
* Assuming a 16 bit object id, an object id being 0xffff represents a free page.
|
||||
* An object id being 0x0000 represents a deleted page.
|
||||
*
|
||||
* ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
|
||||
* page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
|
||||
* page 2 : data : data for object id 0008
|
||||
* page 3 : data : data for object id 0001
|
||||
* page 4 : data : data for object id 0aaa
|
||||
* ...
|
||||
*
|
||||
*
|
||||
* Object data pages can be either object index pages or object content.
|
||||
* All object data pages contains a data page header, containing object id and span index.
|
||||
* The span index denotes the object page ordering amongst data pages with same object id.
|
||||
* This applies to both object index pages (when index spans more than one page of entries),
|
||||
* and object data pages.
|
||||
* An object index page contains page entries pointing to object content page. The entry index
|
||||
* in a object index page correlates to the span index in the actual object data page.
|
||||
* The first object index page (span index 0) is called object index header page, and also
|
||||
* contains object flags (directory/file), size, object name etc.
|
||||
*
|
||||
* ex:
|
||||
* BLOCK 1
|
||||
* PAGE 256: objectl lookup page 1
|
||||
* [*123] [ 123] [ 123] [ 123]
|
||||
* [ 123] [*123] [ 123] [ 123]
|
||||
* [free] [free] [free] [free] ...
|
||||
* PAGE 257: objectl lookup page 2
|
||||
* [free] [free] [free] [free] ...
|
||||
* PAGE 258: object index page (header)
|
||||
* obj.id:0123 span.ix:0000 flags:INDEX
|
||||
* size:1600 name:ex.txt type:file
|
||||
* [259] [260] [261] [262]
|
||||
* PAGE 259: object data page
|
||||
* obj.id:0123 span.ix:0000 flags:DATA
|
||||
* PAGE 260: object data page
|
||||
* obj.id:0123 span.ix:0001 flags:DATA
|
||||
* PAGE 261: object data page
|
||||
* obj.id:0123 span.ix:0002 flags:DATA
|
||||
* PAGE 262: object data page
|
||||
* obj.id:0123 span.ix:0003 flags:DATA
|
||||
* PAGE 263: object index page
|
||||
* obj.id:0123 span.ix:0001 flags:INDEX
|
||||
* [264] [265] [fre] [fre]
|
||||
* [fre] [fre] [fre] [fre]
|
||||
* PAGE 264: object data page
|
||||
* obj.id:0123 span.ix:0004 flags:DATA
|
||||
* PAGE 265: object data page
|
||||
* obj.id:0123 span.ix:0005 flags:DATA
|
||||
*
|
||||
*/
|
||||
#ifndef SPIFFS_NUCLEUS_H_
|
||||
#define SPIFFS_NUCLEUS_H_
|
||||
|
||||
#define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
|
||||
#define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
|
||||
#define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
|
||||
#define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
|
||||
#define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
|
||||
|
||||
#define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
|
||||
#define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
|
||||
#define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
|
||||
|
||||
#define SPIFFS_EV_IX_UPD 0
|
||||
#define SPIFFS_EV_IX_NEW 1
|
||||
#define SPIFFS_EV_IX_DEL 2
|
||||
|
||||
#define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
|
||||
|
||||
#define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
|
||||
|
||||
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
||||
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
||||
|
||||
#if SPIFFS_USE_MAGIC
|
||||
#if !SPIFFS_USE_MAGIC_LENGTH
|
||||
#define SPIFFS_MAGIC(fs, bix) \
|
||||
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
|
||||
#else // SPIFFS_USE_MAGIC_LENGTH
|
||||
#define SPIFFS_MAGIC(fs, bix) \
|
||||
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
|
||||
#endif // SPIFFS_USE_MAGIC_LENGTH
|
||||
#endif // SPIFFS_USE_MAGIC
|
||||
|
||||
#define SPIFFS_CONFIG_MAGIC (0x20090315)
|
||||
|
||||
#if SPIFFS_SINGLETON == 0
|
||||
#define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
|
||||
((fs)->cfg.log_page_size)
|
||||
#define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
|
||||
((fs)->cfg.log_block_size)
|
||||
#define SPIFFS_CFG_PHYS_SZ(fs) \
|
||||
((fs)->cfg.phys_size)
|
||||
#define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
|
||||
((fs)->cfg.phys_erase_block)
|
||||
#define SPIFFS_CFG_PHYS_ADDR(fs) \
|
||||
((fs)->cfg.phys_addr)
|
||||
#endif
|
||||
|
||||
// total number of pages
|
||||
#define SPIFFS_MAX_PAGES(fs) \
|
||||
( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// total number of pages per block, including object lookup pages
|
||||
#define SPIFFS_PAGES_PER_BLOCK(fs) \
|
||||
( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// number of object lookup pages per block
|
||||
#define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
|
||||
(MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
|
||||
// checks if page index belongs to object lookup
|
||||
#define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
|
||||
(((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
|
||||
// number of object lookup entries in all object lookup pages
|
||||
#define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
|
||||
(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
|
||||
// converts a block to physical address
|
||||
#define SPIFFS_BLOCK_TO_PADDR(fs, block) \
|
||||
( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
|
||||
// converts a object lookup entry to page index
|
||||
#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
|
||||
((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
|
||||
// converts a object lookup entry to physical address of corresponding page
|
||||
#define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
|
||||
(SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// converts a page to physical address
|
||||
#define SPIFFS_PAGE_TO_PADDR(fs, page) \
|
||||
( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// converts a physical address to page
|
||||
#define SPIFFS_PADDR_TO_PAGE(fs, addr) \
|
||||
( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// gives index in page for a physical address
|
||||
#define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
|
||||
( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// returns containing block for given page
|
||||
#define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
|
||||
( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
|
||||
// returns starting page for block
|
||||
#define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
|
||||
( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
|
||||
// converts page to entry in object lookup page
|
||||
#define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
|
||||
( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
|
||||
// returns data size in a data page
|
||||
#define SPIFFS_DATA_PAGE_SIZE(fs) \
|
||||
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
|
||||
// returns physical address for block's erase count,
|
||||
// always in the physical last entry of the last object lookup page
|
||||
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
|
||||
// returns physical address for block's magic,
|
||||
// always in the physical second last entry of the last object lookup page
|
||||
#define SPIFFS_MAGIC_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
|
||||
// checks if there is any room for magic in the object luts
|
||||
#define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
|
||||
( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
|
||||
<= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
|
||||
|
||||
// define helpers object
|
||||
|
||||
// entries in an object header page index
|
||||
#define SPIFFS_OBJ_HDR_IX_LEN(fs) \
|
||||
((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
|
||||
// entries in an object page index
|
||||
#define SPIFFS_OBJ_IX_LEN(fs) \
|
||||
((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
|
||||
// object index entry for given data span index
|
||||
#define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
|
||||
((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
|
||||
// object index span index number for given data span index or entry
|
||||
#define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
|
||||
((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
|
||||
|
||||
|
||||
#define SPIFFS_OP_T_OBJ_LU (0<<0)
|
||||
#define SPIFFS_OP_T_OBJ_LU2 (1<<0)
|
||||
#define SPIFFS_OP_T_OBJ_IX (2<<0)
|
||||
#define SPIFFS_OP_T_OBJ_DA (3<<0)
|
||||
#define SPIFFS_OP_C_DELE (0<<2)
|
||||
#define SPIFFS_OP_C_UPDT (1<<2)
|
||||
#define SPIFFS_OP_C_MOVS (2<<2)
|
||||
#define SPIFFS_OP_C_MOVD (3<<2)
|
||||
#define SPIFFS_OP_C_FLSH (4<<2)
|
||||
#define SPIFFS_OP_C_READ (5<<2)
|
||||
#define SPIFFS_OP_C_WRTHRU (6<<2)
|
||||
|
||||
#define SPIFFS_OP_TYPE_MASK (3<<0)
|
||||
#define SPIFFS_OP_COM_MASK (7<<2)
|
||||
|
||||
|
||||
// if 0, this page is written to, else clean
|
||||
#define SPIFFS_PH_FLAG_USED (1<<0)
|
||||
// if 0, writing is finalized, else under modification
|
||||
#define SPIFFS_PH_FLAG_FINAL (1<<1)
|
||||
// if 0, this is an index page, else a data page
|
||||
#define SPIFFS_PH_FLAG_INDEX (1<<2)
|
||||
// if 0, page is deleted, else valid
|
||||
#define SPIFFS_PH_FLAG_DELET (1<<7)
|
||||
// if 0, this index header is being deleted
|
||||
#define SPIFFS_PH_FLAG_IXDELE (1<<6)
|
||||
|
||||
|
||||
#define SPIFFS_CHECK_MOUNT(fs) \
|
||||
((fs)->mounted != 0)
|
||||
|
||||
#define SPIFFS_CHECK_CFG(fs) \
|
||||
((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
|
||||
|
||||
#define SPIFFS_CHECK_RES(res) \
|
||||
do { \
|
||||
if ((res) < SPIFFS_OK) return (res); \
|
||||
} while (0);
|
||||
|
||||
#define SPIFFS_API_CHECK_MOUNT(fs) \
|
||||
if (!SPIFFS_CHECK_MOUNT((fs))) { \
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_CFG(fs) \
|
||||
if (!SPIFFS_CHECK_CFG((fs))) { \
|
||||
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_RES(fs, res) \
|
||||
if ((res) < SPIFFS_OK) { \
|
||||
(fs)->err_code = (res); \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
|
||||
if ((res) < SPIFFS_OK) { \
|
||||
(fs)->err_code = (res); \
|
||||
SPIFFS_UNLOCK(fs); \
|
||||
return -1; \
|
||||
}
|
||||
|
||||
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
|
||||
if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
|
||||
//if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
|
||||
|
||||
#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
|
||||
if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
|
||||
|
||||
|
||||
// check id
|
||||
#define SPIFFS_VIS_CHECK_ID (1<<0)
|
||||
// report argument object id to visitor - else object lookup id is reported
|
||||
#define SPIFFS_VIS_CHECK_PH (1<<1)
|
||||
// stop searching at end of all look up pages
|
||||
#define SPIFFS_VIS_NO_WRAP (1<<2)
|
||||
|
||||
#if SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
|
||||
(_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
|
||||
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
|
||||
(_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
|
||||
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
|
||||
(_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
|
||||
|
||||
#else // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
|
||||
(_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
|
||||
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
|
||||
(_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
|
||||
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
|
||||
(_fs)->cfg.hal_erase_f((_paddr), (_len))
|
||||
|
||||
#endif // SPIFFS_HAL_CALLBACK_EXTRA
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
|
||||
#define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
|
||||
#define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
|
||||
#define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
|
||||
#define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
|
||||
#define SPIFFS_CACHE_FLAG_DATA (1<<4)
|
||||
#define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
|
||||
|
||||
#define SPIFFS_CACHE_PAGE_SIZE(fs) \
|
||||
(sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
|
||||
|
||||
#define spiffs_get_cache(fs) \
|
||||
((spiffs_cache *)((fs)->cache))
|
||||
|
||||
#define spiffs_get_cache_page_hdr(fs, c, ix) \
|
||||
((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
|
||||
|
||||
#define spiffs_get_cache_page(fs, c, ix) \
|
||||
((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
|
||||
|
||||
// cache page struct
|
||||
typedef struct {
|
||||
// cache flags
|
||||
u8_t flags;
|
||||
// cache page index
|
||||
u8_t ix;
|
||||
// last access of this cache page
|
||||
u32_t last_access;
|
||||
union {
|
||||
// type read cache
|
||||
struct {
|
||||
// read cache page index
|
||||
spiffs_page_ix pix;
|
||||
};
|
||||
#if SPIFFS_CACHE_WR
|
||||
// type write cache
|
||||
struct {
|
||||
// write cache
|
||||
spiffs_obj_id obj_id;
|
||||
// offset in cache page
|
||||
u32_t offset;
|
||||
// size of cache page
|
||||
u16_t size;
|
||||
};
|
||||
#endif
|
||||
};
|
||||
} spiffs_cache_page;
|
||||
|
||||
// cache struct
|
||||
typedef struct {
|
||||
u8_t cpage_count;
|
||||
u32_t last_access;
|
||||
u32_t cpage_use_map;
|
||||
u32_t cpage_use_mask;
|
||||
u8_t *cpages;
|
||||
} spiffs_cache;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// spiffs nucleus file descriptor
|
||||
typedef struct {
|
||||
// the filesystem of this descriptor
|
||||
spiffs *fs;
|
||||
// number of file descriptor - if 0, the file descriptor is closed
|
||||
spiffs_file file_nbr;
|
||||
// object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
|
||||
spiffs_obj_id obj_id;
|
||||
// size of the file
|
||||
u32_t size;
|
||||
// cached object index header page index
|
||||
spiffs_page_ix objix_hdr_pix;
|
||||
// cached offset object index page index
|
||||
spiffs_page_ix cursor_objix_pix;
|
||||
// cached offset object index span index
|
||||
spiffs_span_ix cursor_objix_spix;
|
||||
// current absolute offset
|
||||
u32_t offset;
|
||||
// current file descriptor offset
|
||||
u32_t fdoffset;
|
||||
// fd flags
|
||||
spiffs_flags flags;
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_cache_page *cache_page;
|
||||
#endif
|
||||
} spiffs_fd;
|
||||
|
||||
|
||||
// object structs
|
||||
|
||||
// page header, part of each page except object lookup pages
|
||||
// NB: this is always aligned when the data page is an object index,
|
||||
// as in this case struct spiffs_page_object_ix is used
|
||||
typedef struct __attribute(( packed )) {
|
||||
// object id
|
||||
spiffs_obj_id obj_id;
|
||||
// object span index
|
||||
spiffs_span_ix span_ix;
|
||||
// flags
|
||||
u8_t flags;
|
||||
} spiffs_page_header;
|
||||
|
||||
// object index header page header
|
||||
typedef struct __attribute(( packed ))
|
||||
#if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
|
||||
__attribute(( aligned(sizeof(spiffs_page_ix)) ))
|
||||
#endif
|
||||
{
|
||||
// common page header
|
||||
spiffs_page_header p_hdr;
|
||||
// alignment
|
||||
u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
|
||||
// size of object
|
||||
u32_t size;
|
||||
// type of object
|
||||
spiffs_obj_type type;
|
||||
// name of object
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN];
|
||||
} spiffs_page_object_ix_header;
|
||||
|
||||
// object index page header
|
||||
typedef struct __attribute(( packed )) {
|
||||
spiffs_page_header p_hdr;
|
||||
u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
|
||||
} spiffs_page_object_ix;
|
||||
|
||||
// callback func for object lookup visitor
|
||||
typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
|
||||
const void *user_const_p, void *user_var_p);
|
||||
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
#define _spiffs_rd(fs, op, fh, addr, len, dst) \
|
||||
spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
|
||||
#define _spiffs_wr(fs, op, fh, addr, len, src) \
|
||||
spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
|
||||
#else
|
||||
#define _spiffs_rd(fs, op, fh, addr, len, dst) \
|
||||
spiffs_phys_rd((fs), (addr), (len), (dst))
|
||||
#define _spiffs_wr(fs, op, fh, addr, len, src) \
|
||||
spiffs_phys_wr((fs), (addr), (len), (src))
|
||||
#endif
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_phys_rd(
|
||||
spiffs *fs,
|
||||
#if SPIFFS_CACHE
|
||||
u8_t op,
|
||||
spiffs_file fh,
|
||||
#endif
|
||||
u32_t addr,
|
||||
u32_t len,
|
||||
u8_t *dst);
|
||||
|
||||
s32_t spiffs_phys_wr(
|
||||
spiffs *fs,
|
||||
#if SPIFFS_CACHE
|
||||
u8_t op,
|
||||
spiffs_file fh,
|
||||
#endif
|
||||
u32_t addr,
|
||||
u32_t len,
|
||||
u8_t *src);
|
||||
|
||||
s32_t spiffs_phys_cpy(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
u32_t dst,
|
||||
u32_t src,
|
||||
u32_t len);
|
||||
|
||||
s32_t spiffs_phys_count_free_blocks(
|
||||
spiffs *fs);
|
||||
|
||||
s32_t spiffs_obj_lu_find_entry_visitor(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix starting_block,
|
||||
int starting_lu_entry,
|
||||
u8_t flags,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_visitor_f v,
|
||||
const void *user_const_p,
|
||||
void *user_var_p,
|
||||
spiffs_block_ix *block_ix,
|
||||
int *lu_entry);
|
||||
|
||||
s32_t spiffs_erase_block(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
|
||||
s32_t spiffs_probe(
|
||||
spiffs_config *cfg);
|
||||
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
spiffs *fs);
|
||||
|
||||
s32_t spiffs_obj_lu_find_free_obj_id(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id *obj_id,
|
||||
const u8_t *conflicting_name);
|
||||
|
||||
s32_t spiffs_obj_lu_find_free(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix starting_block,
|
||||
int starting_lu_entry,
|
||||
spiffs_block_ix *block_ix,
|
||||
int *lu_entry);
|
||||
|
||||
s32_t spiffs_obj_lu_find_id(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix starting_block,
|
||||
int starting_lu_entry,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_block_ix *block_ix,
|
||||
int *lu_entry);
|
||||
|
||||
s32_t spiffs_obj_lu_find_id_and_span(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix exclusion_pix,
|
||||
spiffs_page_ix *pix);
|
||||
|
||||
s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix exclusion_pix,
|
||||
spiffs_page_ix *pix);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_page_allocate_data(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_header *ph,
|
||||
u8_t *data,
|
||||
u32_t len,
|
||||
u32_t page_offs,
|
||||
u8_t finalize,
|
||||
spiffs_page_ix *pix);
|
||||
|
||||
s32_t spiffs_page_move(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
u8_t *page_data,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_header *page_hdr,
|
||||
spiffs_page_ix src_pix,
|
||||
spiffs_page_ix *dst_pix);
|
||||
|
||||
s32_t spiffs_page_delete(
|
||||
spiffs *fs,
|
||||
spiffs_page_ix pix);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_object_create(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
const u8_t name[SPIFFS_OBJ_NAME_LEN],
|
||||
spiffs_obj_type type,
|
||||
spiffs_page_ix *objix_hdr_pix);
|
||||
|
||||
s32_t spiffs_object_update_index_hdr(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_ix objix_hdr_pix,
|
||||
u8_t *new_objix_hdr_data,
|
||||
const u8_t name[SPIFFS_OBJ_NAME_LEN],
|
||||
u32_t size,
|
||||
spiffs_page_ix *new_pix);
|
||||
|
||||
void spiffs_cb_object_event(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd,
|
||||
int ev,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix new_pix,
|
||||
u32_t new_size);
|
||||
|
||||
s32_t spiffs_object_open_by_id(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_fd *f,
|
||||
spiffs_flags flags,
|
||||
spiffs_mode mode);
|
||||
|
||||
s32_t spiffs_object_open_by_page(
|
||||
spiffs *fs,
|
||||
spiffs_page_ix pix,
|
||||
spiffs_fd *f,
|
||||
spiffs_flags flags,
|
||||
spiffs_mode mode);
|
||||
|
||||
s32_t spiffs_object_append(
|
||||
spiffs_fd *fd,
|
||||
u32_t offset,
|
||||
u8_t *data,
|
||||
u32_t len);
|
||||
|
||||
s32_t spiffs_object_modify(
|
||||
spiffs_fd *fd,
|
||||
u32_t offset,
|
||||
u8_t *data,
|
||||
u32_t len);
|
||||
|
||||
s32_t spiffs_object_read(
|
||||
spiffs_fd *fd,
|
||||
u32_t offset,
|
||||
u32_t len,
|
||||
u8_t *dst);
|
||||
|
||||
s32_t spiffs_object_truncate(
|
||||
spiffs_fd *fd,
|
||||
u32_t new_len,
|
||||
u8_t remove_object);
|
||||
|
||||
s32_t spiffs_object_find_object_index_header_by_name(
|
||||
spiffs *fs,
|
||||
const u8_t name[SPIFFS_OBJ_NAME_LEN],
|
||||
spiffs_page_ix *pix);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_gc_check(
|
||||
spiffs *fs,
|
||||
u32_t len);
|
||||
|
||||
s32_t spiffs_gc_erase_page_stats(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
s32_t spiffs_gc_find_candidate(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix **block_candidate,
|
||||
int *candidate_count,
|
||||
char fs_crammed);
|
||||
|
||||
s32_t spiffs_gc_clean(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
s32_t spiffs_gc_quick(
|
||||
spiffs *fs, u16_t max_free_pages);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_fd_find_new(
|
||||
spiffs *fs,
|
||||
spiffs_fd **fd);
|
||||
|
||||
s32_t spiffs_fd_return(
|
||||
spiffs *fs,
|
||||
spiffs_file f);
|
||||
|
||||
s32_t spiffs_fd_get(
|
||||
spiffs *fs,
|
||||
spiffs_file f,
|
||||
spiffs_fd **fd);
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
void spiffs_cache_init(
|
||||
spiffs *fs);
|
||||
|
||||
void spiffs_cache_drop_page(
|
||||
spiffs *fs,
|
||||
spiffs_page_ix pix);
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd);
|
||||
|
||||
void spiffs_cache_fd_release(
|
||||
spiffs *fs,
|
||||
spiffs_cache_page *cp);
|
||||
|
||||
spiffs_cache_page *spiffs_cache_page_get_by_fd(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
s32_t spiffs_lookup_consistency_check(
|
||||
spiffs *fs,
|
||||
u8_t check_all_objects);
|
||||
|
||||
s32_t spiffs_page_consistency_check(
|
||||
spiffs *fs);
|
||||
|
||||
s32_t spiffs_object_index_consistency_check(
|
||||
spiffs *fs);
|
||||
|
||||
#endif /* SPIFFS_NUCLEUS_H_ */
|
||||
125
arduino/realtek-ambz/cores/arduino/ssl_drv.cpp
Normal file
125
arduino/realtek-ambz/cores/arduino/ssl_drv.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "ssl_drv.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "platform_stdlib.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
uint16_t SSLDrv::availData(sslclient_context *ssl_client)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ssl_client->socket < 0)
|
||||
return 0;
|
||||
|
||||
if(_available) {
|
||||
return 1;
|
||||
} else {
|
||||
return getData(ssl_client, c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool SSLDrv::getData(sslclient_context *ssl_client, uint8_t *data, uint8_t peek)
|
||||
{
|
||||
int ret = 0;
|
||||
int flag = 0;
|
||||
|
||||
if (_available) {
|
||||
/* we already has data to read */
|
||||
data[0] = c[0];
|
||||
if (peek) {
|
||||
} else {
|
||||
/* It's not peek and the data has been taken */
|
||||
_available = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (peek) {
|
||||
flag |= 1;
|
||||
}
|
||||
|
||||
ret = get_ssl_receive(ssl_client, c, 1, flag);
|
||||
|
||||
if (ret == 1) {
|
||||
data[0] = c[0];
|
||||
if (peek) {
|
||||
_available = true;
|
||||
} else {
|
||||
_available = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int SSLDrv::getDataBuf(sslclient_context *ssl_client, uint8_t *_data, uint16_t _dataLen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (_available) {
|
||||
/* there is one byte cached */
|
||||
_data[0] = c[0];
|
||||
_available = false;
|
||||
_dataLen--;
|
||||
if (_dataLen > 0) {
|
||||
ret = get_ssl_receive(ssl_client, _data, _dataLen, 0);
|
||||
if (ret > 0) {
|
||||
ret++;
|
||||
return ret;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
ret = get_ssl_receive(ssl_client, _data, _dataLen, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SSLDrv::stopClient(sslclient_context *ssl_client)
|
||||
{
|
||||
stop_ssl_socket(ssl_client);
|
||||
_available = false;
|
||||
}
|
||||
|
||||
bool SSLDrv::sendData(sslclient_context *ssl_client, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (ssl_client->socket < 0)
|
||||
return false;
|
||||
|
||||
ret = send_ssl_data(ssl_client, data, len);
|
||||
|
||||
if (ret == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int SSLDrv::startClient(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = start_ssl_client(ssl_client, ipAddress, port, rootCABuff, cli_cert, cli_key);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SSLDrv::getLastErrno(sslclient_context *ssl_client)
|
||||
{
|
||||
return get_ssl_sock_errno(ssl_client);
|
||||
}
|
||||
|
||||
int SSLDrv::setSockRecvTimeout(int sock, int timeout)
|
||||
{
|
||||
return setSockRecvTimeout(sock, timeout);
|
||||
}
|
||||
|
||||
31
arduino/realtek-ambz/cores/arduino/ssl_drv.h
Normal file
31
arduino/realtek-ambz/cores/arduino/ssl_drv.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef SSL_DRV_H
|
||||
#define SSL_DRV_H
|
||||
#include <inttypes.h>
|
||||
|
||||
#define DATA_LENTH 128
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#include "ard_ssl.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
class SSLDrv
|
||||
{
|
||||
public:
|
||||
int startClient(sslclient_context *ssl_client, uint32_t ipAddress, uint32_t port, unsigned char* rootCABuff, unsigned char* cli_cert, unsigned char* cli_key);
|
||||
void stopClient(sslclient_context *ssl_client);
|
||||
bool getData(sslclient_context *ssl_client, uint8_t *data, uint8_t peek=0);
|
||||
int getDataBuf(sslclient_context *ssl_client, uint8_t *_data, uint16_t _dataLen);
|
||||
bool sendData(sslclient_context *ssl_client, const uint8_t *data, uint16_t len);
|
||||
uint16_t availData(sslclient_context *ssl_client);
|
||||
sslclient_context *init(void);
|
||||
int getLastErrno(sslclient_context *ssl_client);
|
||||
|
||||
int setSockRecvTimeout(int sock, int timeout);
|
||||
|
||||
private:
|
||||
bool _available;
|
||||
uint8_t c[1];
|
||||
};
|
||||
|
||||
#endif
|
||||
60
arduino/realtek-ambz/cores/arduino/syscalls.h
Normal file
60
arduino/realtek-ambz/cores/arduino/syscalls.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file syscalls.h
|
||||
*
|
||||
* Implementation of newlib syscall.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern caddr_t _sbrk( int incr ) ;
|
||||
|
||||
extern int link( char *cOld, char *cNew ) ;
|
||||
|
||||
extern int _close( int file ) ;
|
||||
|
||||
extern int _fstat( int file, struct stat *st ) ;
|
||||
|
||||
extern int _isatty( int file ) ;
|
||||
|
||||
extern int _lseek( int file, int ptr, int dir ) ;
|
||||
|
||||
extern int _read(int file, char *ptr, int len) ;
|
||||
|
||||
extern int _write( int file, char *ptr, int len ) ;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
241
arduino/realtek-ambz/cores/arduino/uvc/uvc_drv.c
Normal file
241
arduino/realtek-ambz/cores/arduino/uvc/uvc_drv.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* uvc_drv.c
|
||||
*
|
||||
* Created on: 25/09/2017.
|
||||
* Author: pvvx
|
||||
*/
|
||||
|
||||
|
||||
#include <platform_opts.h>
|
||||
#include "rtl8195a.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "rtl8195a/rtl_libc.h"
|
||||
#include "section_config.h"
|
||||
|
||||
#include <platform/platform_stdlib.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include "sockets.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#include "freertos_pmu.h"
|
||||
|
||||
#include "os_support.h"
|
||||
#include "timer_api.h"
|
||||
|
||||
#include "videodev2.h"
|
||||
#include "uvcvideo.h"
|
||||
#include "v4l2_driver.h"
|
||||
#include "mjpeg/mjpeg.h"
|
||||
#include "rtsp/rtsp_api.h"
|
||||
#include "dwc_otg_driver.h"
|
||||
#include "v4l2_intf.h"
|
||||
|
||||
#include "uvc_drv.h"
|
||||
|
||||
//----------------------------------------------
|
||||
#undef info_printf
|
||||
#define info_printf(fmt, ...) rtl_printf(fmt, ##__VA_ARGS__)
|
||||
#undef err_printf
|
||||
#define err_printf(fmt, ...) rtl_printf(fmt, ##__VA_ARGS__)
|
||||
//----------------------------------------------
|
||||
extern struct usb_device * usb_get_dev_index(int index);
|
||||
extern void usb_hub_reset(void);
|
||||
extern void usb_stop(void);
|
||||
//----------------------------------------------
|
||||
char uvc_is_start; //
|
||||
vfrm_buf_t vfrmb; // управляющая структура
|
||||
//---start_uvc()-------------------------------------------
|
||||
int start_uvc(void) {
|
||||
int result = -1;
|
||||
if (uvc_is_start == 0) {
|
||||
do {
|
||||
info_printf("USB init...\n");
|
||||
_usb_init();
|
||||
result = wait_usb_ready();
|
||||
if (result < 0) {
|
||||
err_printf("\r\nFail to init usb driver!\n");
|
||||
break;
|
||||
}
|
||||
struct usb_device * usb_dev = usb_get_dev_index(1);
|
||||
if (usb_dev)
|
||||
printf("USB ID %04X:%04X\n", usb_dev->descriptor.idProduct,
|
||||
usb_dev->descriptor.idVendor);
|
||||
info_printf("UVC stream init...\n");
|
||||
result = uvc_stream_init();
|
||||
if (result < 0) {
|
||||
err_printf("Fail!\n");
|
||||
break;
|
||||
}
|
||||
uvc_is_start = 1;
|
||||
} while (0);
|
||||
} else if (uvc_is_start == 2) {
|
||||
do {
|
||||
info_printf("USB hub reset...\n");
|
||||
usb_hub_reset(); // ?
|
||||
result = wait_usb_ready();
|
||||
if (result < 0) {
|
||||
err_printf("\r\nFail to init usb driver!\n");
|
||||
break;
|
||||
}
|
||||
result = 2;
|
||||
} while(0);
|
||||
} else {
|
||||
result = 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//---stop_uvc()-------------------------------------------
|
||||
void stop_uvc(void) {
|
||||
//TODO: как выгрузить всё полностью? _usb_deinit() = { return; } only!
|
||||
info_printf("USB Stop.\n");
|
||||
usb_stop();
|
||||
uvc_is_start = 2;
|
||||
}
|
||||
//---get_video_frame_thrd()-------------------------------------------
|
||||
void get_video_frame_thrd(void *parm)
|
||||
{
|
||||
int ret;
|
||||
vfrm_buf_t * pvfrm = (vfrm_buf_t *) parm;
|
||||
struct uvc_buf_context buf;
|
||||
|
||||
pvfrm->run = 1;
|
||||
if (uvc_stream_on() >= 0) {
|
||||
while (uvc_is_stream_on() && !pvfrm->off) {
|
||||
memset(&buf, 0, 0x10u);
|
||||
vTaskDelay(1);
|
||||
ret = uvc_dqbuf(&buf);
|
||||
// DiagPrintf("dqbuf(%d)\r\n", ret);
|
||||
if (ret < 0) {
|
||||
if (ret == -61)
|
||||
break;
|
||||
uvc_stream_free();
|
||||
}
|
||||
// DiagPrintf("buf.index(%d)\r\n", buf.index);
|
||||
if (buf.index == -1)
|
||||
continue;
|
||||
pvfrm->frame_count++;
|
||||
#if CONFIG_DEBUG_LOG > 2
|
||||
if(pvfrm->pbuf_size != buf.len) HalSerialPutcRtl8195a('@');
|
||||
else HalSerialPutcRtl8195a('#');
|
||||
#endif
|
||||
if (pvfrm->get && pvfrm->pbuf) {
|
||||
if(pvfrm->get == 1 || pvfrm->pbuf_size == buf.len) {
|
||||
memcpy(pvfrm->pbuf, buf.data, buf.len);
|
||||
pvfrm->frame_size = buf.len;
|
||||
pvfrm->copy_count++;
|
||||
pvfrm->get = 0;
|
||||
pvfrm->ok = 1;
|
||||
// DiagPrintf("\r\nFrameBuf[%d] at %p[%d]\r\n", buf.index, buf.data, buf.len);
|
||||
}
|
||||
}
|
||||
ret = uvc_qbuf(&buf);
|
||||
// DiagPrintf("qbuf(%d)\r\n", ret);
|
||||
if (ret >= 0)
|
||||
continue;
|
||||
uvc_stream_free();
|
||||
};
|
||||
};
|
||||
pvfrm->run = 0;
|
||||
#if CONFIG_DEBUG_LOG > 2
|
||||
DiagPrintf("\r\nTask 'get-vfrm' close.\r\n");
|
||||
#endif
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
//---FreeBufCameraFrame()-------------------------------------------
|
||||
void FreeBufCameraFrame(void) {
|
||||
vfrmb.get = 0;
|
||||
if(vfrmb.pbuf != NULL) {
|
||||
free(vfrmb.pbuf);
|
||||
vfrmb.pbuf = NULL;
|
||||
}
|
||||
}
|
||||
//---StartCamera()-------------------------------------------
|
||||
unsigned int SetCameraParam(int fmt_type, int width, int height, int frame_rate, int compression_ratio) {
|
||||
FreeBufCameraFrame();
|
||||
switch(fmt_type) {
|
||||
case 0:
|
||||
vfrmb.uvc_ctx.fmt_type = V4L2_PIX_FMT_H264;
|
||||
break;
|
||||
case 1:
|
||||
vfrmb.uvc_ctx.fmt_type = V4L2_PIX_FMT_MJPEG;
|
||||
break;
|
||||
default:
|
||||
vfrmb.uvc_ctx.fmt_type = V4L2_PIX_FMT_YUYV;
|
||||
break;
|
||||
}
|
||||
vfrmb.uvc_ctx.width = width;
|
||||
vfrmb.uvc_ctx.height = height;
|
||||
vfrmb.uvc_ctx.frame_rate = frame_rate;
|
||||
vfrmb.uvc_ctx.compression_ratio = compression_ratio;
|
||||
vfrmb.pbuf_size = vfrmb.uvc_ctx.width * vfrmb.uvc_ctx.height;
|
||||
if(vfrmb.uvc_ctx.fmt_type == V4L2_PIX_FMT_YUYV) vfrmb.pbuf_size <<= 1;
|
||||
return vfrmb.pbuf_size;
|
||||
}
|
||||
//---StartCamera()-------------------------------------------
|
||||
int StartCamera(void) {
|
||||
if (vfrmb.run && vfrmb.pbuf_size) return 1;
|
||||
vfrmb.off = 0;
|
||||
vfrmb.run = 0;
|
||||
vfrmb.get = 0;
|
||||
vfrmb.ok = 0;
|
||||
vfrmb.copy_count = 0;
|
||||
vfrmb.frame_count = 0;
|
||||
if (start_uvc() >= 0) {
|
||||
info_printf("\r\nStart camera...\n");
|
||||
if (v4l_set_param(vfrmb.uvc_ctx.fmt_type, &vfrmb.uvc_ctx.width, &vfrmb.uvc_ctx.height, &vfrmb.uvc_ctx.frame_rate, &vfrmb.uvc_ctx.compression_ratio) < 0) {
|
||||
err_printf("Not set param!\r\n");
|
||||
return 0;
|
||||
}
|
||||
if(xTaskCreate((TaskFunction_t) get_video_frame_thrd, "get-vfrm", 1024, &vfrmb, tskIDLE_PRIORITY + 2, NULL) != pdPASS) { // +4 // + PRIORITIE_OFFSET
|
||||
err_printf("Not start Task 'get-vfrm'!\r\n");
|
||||
return 0;
|
||||
}
|
||||
vTaskDelay(2);
|
||||
} else return 0;
|
||||
return 1;
|
||||
}
|
||||
//---GetCameraFrame()-------------------------------------------
|
||||
unsigned int GetCameraFrame(void *pbuf) {
|
||||
if (vfrmb.run != 0) {
|
||||
if(pbuf == NULL) {
|
||||
if(vfrmb.pbuf == NULL) {
|
||||
vfrmb.pbuf = malloc(vfrmb.pbuf_size);
|
||||
if(vfrmb.pbuf == NULL) {
|
||||
#if CONFIG_DEBUG_LOG > 2
|
||||
err_printf("Not alloc frame buf!\r\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} else vfrmb.pbuf = (char *)pbuf;
|
||||
TickType_t tt = xTaskGetTickCount();
|
||||
vfrmb.get = 0; vfrmb.ok = 0;
|
||||
if(vfrmb.uvc_ctx.fmt_type == V4L2_PIX_FMT_YUYV) vfrmb.get = 2;
|
||||
else vfrmb.get = 1;
|
||||
vTaskDelay(10);
|
||||
while(vfrmb.get) {
|
||||
#if CONFIG_DEBUG_LOG > 2
|
||||
HalSerialPutcRtl8195a('.') ;
|
||||
#endif
|
||||
if(xTaskGetTickCount() - tt > 5000) {
|
||||
err_printf("USB timeout!\r\n");
|
||||
vfrmb.off = 1;
|
||||
return 0;
|
||||
}
|
||||
vTaskDelay(10);
|
||||
}
|
||||
if(!vfrmb.get && vfrmb.ok && vfrmb.frame_size) {
|
||||
return vfrmb.frame_size;
|
||||
}
|
||||
}
|
||||
#if CONFIG_DEBUG_LOG > 2
|
||||
else err_printf("Camera not run!\r\n");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
53
arduino/realtek-ambz/cores/arduino/uvc/uvc_drv.h
Normal file
53
arduino/realtek-ambz/cores/arduino/uvc/uvc_drv.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Get video frame YUYV/MGPEG (usb uvc)
|
||||
*
|
||||
* Created on: 22/09/2017
|
||||
* Author: pvvx
|
||||
*/
|
||||
#ifndef _USB_UVC_DRV_H_
|
||||
#define _USB_UVC_DRV_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define VFRMT_H264 0
|
||||
#define VFRMT_MJPEG 1
|
||||
#define VFRMT_YUYV 2
|
||||
|
||||
extern "C" {
|
||||
|
||||
#else
|
||||
|
||||
#include "uvc_intf.h"
|
||||
#include "uapi_videodev2.h"
|
||||
|
||||
typedef struct {
|
||||
volatile char off; // !=0 - завершить get_video_frame_thrd
|
||||
volatile char run; // !=0 - get_video_frame_thrd запущен
|
||||
volatile char get; // =1 - запрос копирования фрейма который влезет в буфер, = 2 - копирования фрейма только с размером pbuf_size
|
||||
volatile char ok; //
|
||||
char *pbuf;
|
||||
unsigned int pbuf_size;
|
||||
unsigned int frame_size;
|
||||
unsigned int copy_count;
|
||||
unsigned int frame_count;
|
||||
struct uvc_context uvc_ctx;
|
||||
} vfrm_buf_t;
|
||||
|
||||
extern vfrm_buf_t vfrmb; // управляющая структура драйвера get video frame
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//extern void stop_uvc(void);
|
||||
//extern int start_uvc(void);
|
||||
void FreeBufCameraFrame(void);
|
||||
unsigned int SetCameraParam(int fmt_type, int width, int height, int frame_rate, int compression_ratio);
|
||||
int StartCamera(void);
|
||||
unsigned int GetCameraFrame(void *pbuf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // _USB_UVC_DRV_H_
|
||||
488
arduino/realtek-ambz/cores/arduino/wifi_drv.cpp
Normal file
488
arduino/realtek-ambz/cores/arduino/wifi_drv.cpp
Normal file
@@ -0,0 +1,488 @@
|
||||
#include "wifi_drv.h"
|
||||
|
||||
// arduino includes
|
||||
#include "wl_definitions.h"
|
||||
#include "wl_types.h"
|
||||
#include "wiring.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
// RTK includes
|
||||
#include "main.h"
|
||||
#include "wifi_conf.h"
|
||||
#include "wifi_constants.h"
|
||||
#include "wifi_structures.h"
|
||||
#include "lwip_netconf.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/api.h"
|
||||
#include <dhcp/dhcps.h>
|
||||
|
||||
extern struct netif xnetif[NET_IF_NUM];
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// Array of data to cache the information related to the networks discovered
|
||||
uint8_t WiFiDrv::_networkCount = 0;
|
||||
char WiFiDrv::_networkSsid[][WL_SSID_MAX_LENGTH] = {{"1"},{"2"},{"3"},{"4"},{"5"}};
|
||||
int32_t WiFiDrv::_networkRssi[WL_NETWORKS_LIST_MAXNUM] = { 0 };
|
||||
uint32_t WiFiDrv::_networkEncr[WL_NETWORKS_LIST_MAXNUM] = { 0 };
|
||||
|
||||
static char init_wlan = false;
|
||||
static char init_lwip = false;
|
||||
|
||||
static rtw_network_info_t wifi = {0};
|
||||
static rtw_ap_info_t ap = {0};
|
||||
static unsigned char password[65] = {0};
|
||||
|
||||
rtw_wifi_setting_t WiFiDrv::wifi_setting;
|
||||
|
||||
static void init_wifi_struct(void)
|
||||
{
|
||||
memset(wifi.ssid.val, 0, sizeof(wifi.ssid.val));
|
||||
memset(wifi.bssid.octet, 0, ETH_ALEN);
|
||||
memset(password, 0, sizeof(password));
|
||||
wifi.ssid.len = 0;
|
||||
wifi.password = NULL;
|
||||
wifi.password_len = 0;
|
||||
wifi.key_id = -1;
|
||||
memset(ap.ssid.val, 0, sizeof(ap.ssid.val));
|
||||
ap.ssid.len = 0;
|
||||
ap.password = NULL;
|
||||
ap.password_len = 0;
|
||||
ap.channel = 1;
|
||||
}
|
||||
|
||||
void WiFiDrv::wifiDriverInit()
|
||||
{
|
||||
if (init_lwip == false) {
|
||||
init_lwip = true;
|
||||
LwIP_Init();
|
||||
}
|
||||
if (init_wlan == false) {
|
||||
init_wlan = true;
|
||||
wifi_on(RTW_MODE_STA);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::wifiSetNetwork(char* ssid, uint8_t ssid_len)
|
||||
{
|
||||
int ret;
|
||||
uint8_t dhcp_result;
|
||||
|
||||
memset(wifi.bssid.octet, 0, ETH_ALEN);
|
||||
memcpy(wifi.ssid.val, ssid, ssid_len);
|
||||
wifi.ssid.len = ssid_len;
|
||||
|
||||
wifi.security_type = RTW_SECURITY_OPEN;
|
||||
wifi.password = NULL;
|
||||
wifi.password_len = 0;
|
||||
wifi.key_id = 0;
|
||||
|
||||
ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len,
|
||||
wifi.password_len, wifi.key_id, NULL);
|
||||
|
||||
if (ret == RTW_SUCCESS) {
|
||||
|
||||
dhcp_result = LwIP_DHCP(0, DHCP_START);
|
||||
|
||||
init_wifi_struct();
|
||||
|
||||
if ( dhcp_result == DHCP_ADDRESS_ASSIGNED ) {
|
||||
return WL_SUCCESS;
|
||||
} else {
|
||||
wifi_disconnect();
|
||||
return WL_FAILURE;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
init_wifi_struct();
|
||||
|
||||
return WL_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::wifiSetPassphrase(char* ssid, uint8_t ssid_len, const char *passphrase, const uint8_t len)
|
||||
{
|
||||
int ret;
|
||||
uint8_t dhcp_result;
|
||||
|
||||
memset(wifi.bssid.octet, 0, ETH_ALEN);
|
||||
memcpy(wifi.ssid.val, ssid, ssid_len);
|
||||
wifi.ssid.len = ssid_len;
|
||||
|
||||
wifi.security_type = RTW_SECURITY_WPA2_AES_PSK;
|
||||
memset(password, 0, sizeof(password));
|
||||
memcpy(password, passphrase, len);
|
||||
wifi.password = password;
|
||||
wifi.password_len = len;
|
||||
wifi.key_id = 0;
|
||||
|
||||
ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len,
|
||||
wifi.password_len, wifi.key_id, NULL);
|
||||
|
||||
if (ret == RTW_SUCCESS) {
|
||||
|
||||
dhcp_result = LwIP_DHCP(0, DHCP_START);
|
||||
|
||||
init_wifi_struct();
|
||||
|
||||
if ( dhcp_result == DHCP_ADDRESS_ASSIGNED ) {
|
||||
return WL_SUCCESS;
|
||||
} else {
|
||||
wifi_disconnect();
|
||||
return WL_FAILURE;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
init_wifi_struct();
|
||||
|
||||
return WL_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::wifiSetKey(char* ssid, uint8_t ssid_len, uint8_t key_idx, const void *key, const uint8_t len)
|
||||
{
|
||||
int ret;
|
||||
uint8_t dhcp_result;
|
||||
int i, idx;
|
||||
const unsigned char* k = (const unsigned char *)key;
|
||||
|
||||
memset(wifi.bssid.octet, 0, ETH_ALEN);
|
||||
memcpy(wifi.ssid.val, ssid, ssid_len);
|
||||
wifi.ssid.len = ssid_len;
|
||||
|
||||
wifi.security_type = RTW_SECURITY_WEP_PSK;
|
||||
memset(password, 0, sizeof(password));
|
||||
|
||||
// convert hex sring to hex value
|
||||
for (i=0, idx=0; i<len; i++) {
|
||||
|
||||
if ( k[i] >= '0' && k[i] <= '9' ) {
|
||||
password[idx] += (k[i] - '0');
|
||||
} else if ( k[i] >= 'a' && k[i] <= 'f' ) {
|
||||
password[idx] += (k[i] - 'a' + 10);
|
||||
} else if ( k[i] >= 'A' && k[i] <= 'F' ) {
|
||||
password[idx] += (k[i] - 'A' + 10);
|
||||
}
|
||||
|
||||
if (i % 2 == 0) {
|
||||
password[idx] *= 16;
|
||||
} else {
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
wifi.password = password;
|
||||
wifi.password_len = len/2;
|
||||
wifi.key_id = key_idx;
|
||||
|
||||
ret = wifi_connect((char*)wifi.ssid.val, wifi.security_type, (char*)wifi.password, wifi.ssid.len,
|
||||
wifi.password_len, wifi.key_id, NULL);
|
||||
|
||||
if (ret == RTW_SUCCESS) {
|
||||
|
||||
dhcp_result = LwIP_DHCP(0, DHCP_START);
|
||||
|
||||
init_wifi_struct();
|
||||
|
||||
if ( dhcp_result == DHCP_ADDRESS_ASSIGNED ) {
|
||||
return WL_SUCCESS;
|
||||
} else {
|
||||
wifi_disconnect();
|
||||
return WL_FAILURE;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
init_wifi_struct();
|
||||
|
||||
return WL_FAILURE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::apSetNetwork(char* ssid, uint8_t ssid_len)
|
||||
{
|
||||
int ret = WL_SUCCESS;
|
||||
|
||||
ap.ssid.len = ssid_len;
|
||||
|
||||
if(ap.ssid.len > 32){
|
||||
printf("Error: SSID length can't exceed 32\n\r");
|
||||
ret = WL_FAILURE;
|
||||
}
|
||||
strcpy((char *)ap.ssid.val, (char*)ssid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::apSetPassphrase(const char *passphrase, uint8_t len)
|
||||
|
||||
{
|
||||
int ret = WL_SUCCESS;
|
||||
strcpy((char *)password, (char*)passphrase);
|
||||
ap.password = password;
|
||||
ap.password_len = len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::apSetChannel(const char *channel)
|
||||
{
|
||||
int ret = WL_SUCCESS;
|
||||
ap.channel = (unsigned char) atoi((const char *)channel);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::apActivate()
|
||||
{
|
||||
#if CONFIG_LWIP_LAYER
|
||||
struct ip_addr ipaddr;
|
||||
struct ip_addr netmask;
|
||||
struct ip_addr gw;
|
||||
struct netif * pnetif = &xnetif[0];
|
||||
#endif
|
||||
int timeout = 20;
|
||||
int ret = WL_SUCCESS;
|
||||
if(ap.ssid.val[0] == 0){
|
||||
printf("Error: SSID can't be empty\n\r");
|
||||
ret = WL_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
if(ap.password == NULL){
|
||||
ap.security_type = RTW_SECURITY_OPEN;
|
||||
}
|
||||
else{
|
||||
ap.security_type = RTW_SECURITY_WPA2_AES_PSK;
|
||||
}
|
||||
|
||||
#if CONFIG_LWIP_LAYER
|
||||
dhcps_deinit();
|
||||
IP4_ADDR(&ipaddr, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
IP4_ADDR(&netmask, NETMASK_ADDR0, NETMASK_ADDR1 , NETMASK_ADDR2, NETMASK_ADDR3);
|
||||
IP4_ADDR(&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
|
||||
netif_set_addr(pnetif, &ipaddr, &netmask,&gw);
|
||||
#endif
|
||||
wifi_off();
|
||||
vTaskDelay(20);
|
||||
if (wifi_on(RTW_MODE_AP) < 0){
|
||||
printf("\n\rERROR: Wifi on failed!");
|
||||
ret = WL_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
printf("\n\rStarting AP ...");
|
||||
|
||||
if((ret = wifi_start_ap((char*)ap.ssid.val, ap.security_type, (char*)ap.password, ap.ssid.len, ap.password_len, ap.channel) )< 0) {
|
||||
printf("\n\rERROR: Operation failed!");
|
||||
ret = WL_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
char essid[33];
|
||||
|
||||
if(wext_get_ssid(WLAN0_NAME, (unsigned char *) essid) > 0) {
|
||||
if(strcmp((const char *) essid, (const char *)ap.ssid.val) == 0) {
|
||||
printf("\n\r%s started\n", ap.ssid.val);
|
||||
ret = WL_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(timeout == 0) {
|
||||
printf("\n\rERROR: Start AP timeout!");
|
||||
ret = WL_FAILURE;
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(1 * configTICK_RATE_HZ);
|
||||
timeout --;
|
||||
}
|
||||
#if CONFIG_LWIP_LAYER
|
||||
//LwIP_UseStaticIP(pnetif);
|
||||
dhcps_init(pnetif);
|
||||
#endif
|
||||
|
||||
exit:
|
||||
init_wifi_struct( );
|
||||
return ret;
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::disconnect()
|
||||
{
|
||||
wifi_disconnect();
|
||||
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::off()
|
||||
{
|
||||
wifi_off();
|
||||
init_wlan = false;
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
|
||||
uint8_t WiFiDrv::getConnectionStatus()
|
||||
{
|
||||
wifiDriverInit();
|
||||
|
||||
if (wifi_is_connected_to_ap() == 0) {
|
||||
return WL_CONNECTED;
|
||||
} else {
|
||||
return WL_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* WiFiDrv::getMacAddress()
|
||||
{
|
||||
return LwIP_GetMAC(&xnetif[0]);
|
||||
}
|
||||
|
||||
void WiFiDrv::getIpAddress(IPAddress& ip)
|
||||
{
|
||||
ip = LwIP_GetIP(&xnetif[0]);
|
||||
}
|
||||
|
||||
void WiFiDrv::getSubnetMask(IPAddress& mask)
|
||||
{
|
||||
mask = LwIP_GetMASK(&xnetif[0]);
|
||||
}
|
||||
|
||||
void WiFiDrv::getGatewayIP(IPAddress& ip)
|
||||
{
|
||||
ip = LwIP_GetGW(&xnetif[0]);
|
||||
}
|
||||
|
||||
char* WiFiDrv::getCurrentSSID()
|
||||
{
|
||||
wifi_get_setting(WLAN0_NAME, &wifi_setting);
|
||||
|
||||
return (char *)(wifi_setting.ssid);
|
||||
}
|
||||
|
||||
uint8_t* WiFiDrv::getCurrentBSSID()
|
||||
{
|
||||
uint8_t bssid[ETH_ALEN];
|
||||
wext_get_bssid(WLAN0_NAME, bssid);
|
||||
return bssid;
|
||||
}
|
||||
|
||||
int32_t WiFiDrv::getCurrentRSSI()
|
||||
{
|
||||
int rssi = 0;
|
||||
|
||||
wifi_get_rssi(&rssi);
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
uint8_t WiFiDrv::getCurrentEncryptionType()
|
||||
{
|
||||
wifi_get_setting(WLAN0_NAME, &wifi_setting);
|
||||
|
||||
return (wifi_setting.security_type);
|
||||
}
|
||||
|
||||
rtw_result_t WiFiDrv::wifidrv_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result )
|
||||
{
|
||||
rtw_scan_result_t* record;
|
||||
|
||||
if (malloced_scan_result->scan_complete != RTW_TRUE) {
|
||||
record = &malloced_scan_result->ap_details;
|
||||
record->SSID.val[record->SSID.len] = 0; /* Ensure the SSID is null terminated */
|
||||
|
||||
if ( _networkCount < WL_NETWORKS_LIST_MAXNUM ) {
|
||||
strcpy( _networkSsid[_networkCount], (char *)record->SSID.val);
|
||||
_networkRssi[_networkCount] = record->signal_strength;
|
||||
_networkEncr[_networkCount] = record->security;
|
||||
_networkCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return RTW_SUCCESS;
|
||||
}
|
||||
|
||||
int8_t WiFiDrv::startScanNetworks()
|
||||
{
|
||||
_networkCount = 0;
|
||||
if( wifi_scan_networks(wifidrv_scan_result_handler, NULL ) != RTW_SUCCESS ){
|
||||
return WL_FAILURE;
|
||||
}
|
||||
|
||||
return WL_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t WiFiDrv::getScanNetworks()
|
||||
{
|
||||
return _networkCount;
|
||||
}
|
||||
|
||||
char* WiFiDrv::getSSIDNetoworks(uint8_t networkItem)
|
||||
{
|
||||
if (networkItem >= WL_NETWORKS_LIST_MAXNUM)
|
||||
return NULL;
|
||||
|
||||
return _networkSsid[networkItem];
|
||||
}
|
||||
|
||||
uint8_t WiFiDrv::getEncTypeNetowrks(uint8_t networkItem)
|
||||
{
|
||||
if (networkItem >= WL_NETWORKS_LIST_MAXNUM)
|
||||
return NULL;
|
||||
|
||||
uint8_t encType = 0;
|
||||
|
||||
if ( _networkEncr[networkItem] == RTW_SECURITY_OPEN ) {
|
||||
encType = ENC_TYPE_NONE;
|
||||
} else if ( (_networkEncr[networkItem] & AES_ENABLED) || (_networkEncr[networkItem] == RTW_SECURITY_WPA_WPA2_MIXED) ) {
|
||||
encType = ENC_TYPE_CCMP;
|
||||
} else if ( _networkEncr[networkItem] & TKIP_ENABLED ) {
|
||||
encType = ENC_TYPE_TKIP;
|
||||
} else if ( _networkEncr[networkItem] == RTW_SECURITY_WEP_PSK ) {
|
||||
encType = ENC_TYPE_WEP;
|
||||
}
|
||||
|
||||
return encType;
|
||||
}
|
||||
|
||||
uint32_t WiFiDrv::getEncTypeNetowrksEx(uint8_t networkItem)
|
||||
{
|
||||
return (networkItem >= WL_NETWORKS_LIST_MAXNUM) ? NULL : _networkEncr[networkItem];
|
||||
}
|
||||
|
||||
int32_t WiFiDrv::getRSSINetoworks(uint8_t networkItem)
|
||||
{
|
||||
if (networkItem >= WL_NETWORKS_LIST_MAXNUM)
|
||||
return NULL;
|
||||
|
||||
return _networkRssi[networkItem];
|
||||
}
|
||||
|
||||
char* WiFiDrv::getFwVersion()
|
||||
{
|
||||
// The version is for compatible to arduino example code
|
||||
return "1.1.0";
|
||||
}
|
||||
|
||||
int WiFiDrv::getHostByName(const char* aHostname, IPAddress& aResult)
|
||||
{
|
||||
ip_addr_t ip_addr;
|
||||
err_t err;
|
||||
|
||||
err = netconn_gethostbyname(aHostname, &ip_addr);
|
||||
|
||||
if (err != ERR_OK) {
|
||||
return WL_FAILURE;
|
||||
}
|
||||
else{
|
||||
aResult = ip_addr.addr;
|
||||
return WL_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int WiFiDrv::SetDTIM(uint8_t dtn)
|
||||
{
|
||||
return wifi_set_lps_dtim(dtn);
|
||||
}
|
||||
279
arduino/realtek-ambz/cores/arduino/wifi_drv.h
Normal file
279
arduino/realtek-ambz/cores/arduino/wifi_drv.h
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
wifi_drv.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WiFi_Drv_h
|
||||
#define WiFi_Drv_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "IPAddress.h"
|
||||
#include "wl_definitions.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
// rtk includes
|
||||
#include "wifi_structures.h"
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
// Key index length
|
||||
#define KEY_IDX_LEN 1
|
||||
// 5 secs of delay to have the connection established
|
||||
#define WL_DELAY_START_CONNECTION 5000
|
||||
// firmware version string length
|
||||
#define WL_FW_VER_LENGTH 6
|
||||
|
||||
class WiFiDrv
|
||||
{
|
||||
private:
|
||||
// settings of requested network
|
||||
static uint8_t _networkCount;
|
||||
static char _networkSsid[WL_NETWORKS_LIST_MAXNUM][WL_SSID_MAX_LENGTH];
|
||||
static int32_t _networkRssi[WL_NETWORKS_LIST_MAXNUM];
|
||||
static uint32_t _networkEncr[WL_NETWORKS_LIST_MAXNUM];
|
||||
|
||||
// settings of current selected network
|
||||
static rtw_wifi_setting_t wifi_setting;
|
||||
|
||||
static rtw_result_t wifidrv_scan_result_handler( rtw_scan_handler_result_t* malloced_scan_result );
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Driver initialization
|
||||
*/
|
||||
static void wifiDriverInit();
|
||||
|
||||
/*
|
||||
* Set the desired network which the connection manager should try to
|
||||
* connect to.
|
||||
*
|
||||
* The ssid of the desired network should be specified.
|
||||
*
|
||||
* param ssid: The ssid of the desired network.
|
||||
* param ssid_len: Lenght of ssid string.
|
||||
* return: WL_SUCCESS or WL_FAILURE
|
||||
*/
|
||||
static int8_t wifiSetNetwork(char* ssid, uint8_t ssid_len);
|
||||
|
||||
/* Start Wifi connection with passphrase
|
||||
* the most secure supported mode will be automatically selected
|
||||
*
|
||||
* param ssid: Pointer to the SSID string.
|
||||
* param ssid_len: Lenght of ssid string.
|
||||
* param passphrase: Passphrase. Valid characters in a passphrase
|
||||
* must be between ASCII 32-126 (decimal).
|
||||
* param len: Lenght of passphrase string.
|
||||
* return: WL_SUCCESS or WL_FAILURE
|
||||
*/
|
||||
static int8_t wifiSetPassphrase(char* ssid, uint8_t ssid_len, const char *passphrase, const uint8_t len);
|
||||
|
||||
/* Start Wifi connection with WEP encryption.
|
||||
* Configure a key into the device. The key type (WEP-40, WEP-104)
|
||||
* is determined by the size of the key (5 bytes for WEP-40, 13 bytes for WEP-104).
|
||||
*
|
||||
* param ssid: Pointer to the SSID string.
|
||||
* param ssid_len: Lenght of ssid string.
|
||||
* param key_idx: The key index to set. Valid values are 0-3.
|
||||
* param key: Key input buffer.
|
||||
* param len: Lenght of key string.
|
||||
* return: WL_SUCCESS or WL_FAILURE
|
||||
*/
|
||||
static int8_t wifiSetKey(char* ssid, uint8_t ssid_len, uint8_t key_idx, const void *key, const uint8_t len);
|
||||
|
||||
/* Set ip configuration disabling dhcp client
|
||||
*
|
||||
* param validParams: set the number of parameters that we want to change
|
||||
* i.e. validParams = 1 means that we'll change only ip address
|
||||
* validParams = 3 means that we'll change ip address, gateway and netmask
|
||||
* param local_ip: Static ip configuration
|
||||
* param gateway: Static gateway configuration
|
||||
* param subnet: Static subnet mask configuration
|
||||
*/
|
||||
static void config(uint8_t validParams, uint32_t local_ip, uint32_t gateway, uint32_t subnet);
|
||||
|
||||
/* Set DNS ip configuration
|
||||
*
|
||||
* param validParams: set the number of parameters that we want to change
|
||||
* i.e. validParams = 1 means that we'll change only dns_server1
|
||||
* validParams = 2 means that we'll change dns_server1 and dns_server2
|
||||
* param dns_server1: Static DNS server1 configuration
|
||||
* param dns_server2: Static DNS server2 configuration
|
||||
*/
|
||||
static void setDNS(uint8_t validParams, uint32_t dns_server1, uint32_t dns_server2);
|
||||
|
||||
/*
|
||||
* Disconnect from the network
|
||||
*
|
||||
* return: WL_SUCCESS or WL_FAILURE
|
||||
*/
|
||||
static int8_t disconnect();
|
||||
|
||||
/*
|
||||
* Wifi_off()
|
||||
*
|
||||
* return: WL_SUCCESS or WL_FAILURE
|
||||
*/
|
||||
static int8_t off();
|
||||
|
||||
/*
|
||||
* Disconnect from the network
|
||||
*
|
||||
* return: one value of wl_status_t enum
|
||||
*/
|
||||
static uint8_t getConnectionStatus();
|
||||
|
||||
/*
|
||||
* Get the interface MAC address.
|
||||
*
|
||||
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
*/
|
||||
static uint8_t* getMacAddress();
|
||||
|
||||
/*
|
||||
* Get the interface IP address.
|
||||
*
|
||||
* return: copy the ip address value in IPAddress object
|
||||
*/
|
||||
static void getIpAddress(IPAddress& ip);
|
||||
|
||||
/*
|
||||
* Get the interface subnet mask address.
|
||||
*
|
||||
* return: copy the subnet mask address value in IPAddress object
|
||||
*/
|
||||
static void getSubnetMask(IPAddress& mask);
|
||||
|
||||
/*
|
||||
* Get the gateway ip address.
|
||||
*
|
||||
* return: copy the gateway ip address value in IPAddress object
|
||||
*/
|
||||
static void getGatewayIP(IPAddress& ip);
|
||||
|
||||
/*
|
||||
* Return the current SSID associated with the network
|
||||
*
|
||||
* return: ssid string
|
||||
*/
|
||||
static char* getCurrentSSID();
|
||||
|
||||
/*
|
||||
* Return the current BSSID associated with the network.
|
||||
* It is the MAC address of the Access Point
|
||||
*
|
||||
* return: pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
|
||||
*/
|
||||
static uint8_t* getCurrentBSSID();
|
||||
|
||||
/*
|
||||
* Return the current RSSI /Received Signal Strength in dBm)
|
||||
* associated with the network
|
||||
*
|
||||
* return: signed value
|
||||
*/
|
||||
static int32_t getCurrentRSSI();
|
||||
|
||||
/*
|
||||
* Return the Encryption Type associated with the network
|
||||
*
|
||||
* return: one value of wl_enc_type enum
|
||||
*/
|
||||
static uint8_t getCurrentEncryptionType();
|
||||
|
||||
/*
|
||||
* Start scan WiFi networks available
|
||||
*
|
||||
* return: Number of discovered networks
|
||||
*/
|
||||
static int8_t startScanNetworks();
|
||||
|
||||
/*
|
||||
* Get the networks available
|
||||
*
|
||||
* return: Number of discovered networks
|
||||
*/
|
||||
static uint8_t getScanNetworks();
|
||||
|
||||
/*
|
||||
* Return the SSID discovered during the network scan.
|
||||
*
|
||||
* param networkItem: specify from which network item want to get the information
|
||||
*
|
||||
* return: ssid string of the specified item on the networks scanned list
|
||||
*/
|
||||
static char* getSSIDNetoworks(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
* Return the RSSI of the networks discovered during the scanNetworks
|
||||
*
|
||||
* param networkItem: specify from which network item want to get the information
|
||||
*
|
||||
* return: signed value of RSSI of the specified item on the networks scanned list
|
||||
*/
|
||||
static int32_t getRSSINetoworks(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
* Return the encryption type of the networks discovered during the scanNetworks
|
||||
*
|
||||
* param networkItem: specify from which network item want to get the information
|
||||
*
|
||||
* return: encryption type (enum wl_enc_type) of the specified item on the networks scanned list
|
||||
*/
|
||||
static uint8_t getEncTypeNetowrks(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
* Return the security type and encryption type of the networks discovered during the scanNetworks
|
||||
*
|
||||
* param networkItem: specify from which network item want to get the information
|
||||
*
|
||||
* return: security and encryption type of the specified item on the networks scanned list
|
||||
*/
|
||||
static uint32_t getEncTypeNetowrksEx(uint8_t networkItem);
|
||||
|
||||
/*
|
||||
* Resolve the given hostname to an IP address.
|
||||
* param aHostname: Name to be resolved
|
||||
* param aResult: IPAddress structure to store the returned IP address
|
||||
* result: 1 if aIPAddrString was successfully converted to an IP address,
|
||||
* else error code
|
||||
*/
|
||||
static int getHostByName(const char* aHostname, IPAddress& aResult);
|
||||
|
||||
/*
|
||||
* Get the firmware version
|
||||
* result: version as string with this format a.b.c
|
||||
*/
|
||||
static char* getFwVersion();
|
||||
|
||||
static int8_t apSetNetwork(char* ssid, uint8_t ssid_len);
|
||||
|
||||
static int8_t apSetPassphrase(const char *passphrase, uint8_t len);
|
||||
|
||||
static int8_t apSetChannel(const char *channel);
|
||||
|
||||
static int8_t apActivate();
|
||||
|
||||
static int SetDTIM(uint8_t dtn);
|
||||
};
|
||||
|
||||
extern WiFiDrv wiFiDrv;
|
||||
|
||||
#endif
|
||||
117
arduino/realtek-ambz/cores/arduino/wiring.c
Normal file
117
arduino/realtek-ambz/cores/arduino/wiring.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "cmsis_os.h"
|
||||
|
||||
#ifndef portNVIC_SYSTICK_CURRENT_VALUE_REG
|
||||
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
|
||||
#endif
|
||||
|
||||
extern uint32_t xTaskGetTickCount();
|
||||
extern uint32_t xTaskGetTickCountFromISR();
|
||||
|
||||
static __inline uint32_t __get_ipsr__(void)
|
||||
{
|
||||
volatile uint32_t __regIPSR __asm("ipsr");
|
||||
return(__regIPSR);
|
||||
}
|
||||
|
||||
void delay( uint32_t ms )
|
||||
{
|
||||
osStatus ret;
|
||||
|
||||
ret = osDelay(ms);
|
||||
if ( (ret != osEventTimeout) && (ret != osOK) ) {
|
||||
//printf("delay : ERROR : 0x%x \n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
void delayMicroseconds(uint32_t us)
|
||||
{
|
||||
int i;
|
||||
uint32_t t0, tn;
|
||||
int dfactor = 0;
|
||||
|
||||
#if defined(BOARD_RTL8710)
|
||||
// dfactor = 10 * us - 10 + (40 * us / 100);
|
||||
dfactor = 20 * us - 10 + (81 * us / 100);
|
||||
#elif defined(BOARD_RTL8195A)
|
||||
dfactor = 20 * us - 10 + (81 * us / 100);
|
||||
#else
|
||||
dfactor = 20 * us - 10 + (81 * us / 100);
|
||||
#endif
|
||||
|
||||
if ( us > 100 ) {
|
||||
t0 = micros();
|
||||
do {
|
||||
tn = micros();
|
||||
} while ( tn >= t0 && tn < (t0 + us - 1) );
|
||||
} else {
|
||||
for (i=0; i<dfactor; i++) {
|
||||
asm("nop");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t millis( void )
|
||||
{
|
||||
return (__get_ipsr__() == 0) ? xTaskGetTickCount() : xTaskGetTickCountFromISR();
|
||||
}
|
||||
|
||||
uint32_t micros( void )
|
||||
{
|
||||
uint32_t tick1, tick2;
|
||||
uint32_t us;
|
||||
uint32_t tick_per_us;
|
||||
|
||||
#if defined(BOARD_RTL8710)
|
||||
tick_per_us = 166666; // 83333;
|
||||
#elif defined(BOARD_RTL8195A)
|
||||
tick_per_us = 166666;
|
||||
#else
|
||||
tick_per_us = 166666;
|
||||
#endif
|
||||
|
||||
if (__get_ipsr__() == 0) {
|
||||
tick1 = xTaskGetTickCount();
|
||||
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
tick2 = xTaskGetTickCount();
|
||||
} else {
|
||||
tick1 = xTaskGetTickCountFromISR();
|
||||
us = portNVIC_SYSTICK_CURRENT_VALUE_REG;
|
||||
tick2 = xTaskGetTickCountFromISR();
|
||||
}
|
||||
|
||||
if (tick1 == tick2) {
|
||||
return tick1 * 1000 - us*1000 / tick_per_us;
|
||||
} else if( (us*1000 / tick_per_us) < 500 ) {
|
||||
return tick1 * 1000 - us*1000 / tick_per_us;
|
||||
} else {
|
||||
return tick1 * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
67
arduino/realtek-ambz/cores/arduino/wiring.h
Normal file
67
arduino/realtek-ambz/cores/arduino/wiring.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_
|
||||
#define _WIRING_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
extern void initVariant( void ) ;
|
||||
extern void init( void ) ;
|
||||
|
||||
/**
|
||||
* \brief Returns the number of milliseconds since the Arduino board began running the current program.
|
||||
*
|
||||
* This number will overflow (go back to zero), after approximately 50 days.
|
||||
*
|
||||
* \return Number of milliseconds since the program started (uint32_t)
|
||||
*/
|
||||
extern uint32_t millis( void ) ;
|
||||
|
||||
/**
|
||||
* \brief Returns the number of microseconds since the Arduino board began running the current program.
|
||||
*
|
||||
* This number will overflow (go back to zero), after approximately 70 minutes. On 16 MHz Arduino boards
|
||||
* (e.g. Duemilanove and Nano), this function has a resolution of four microseconds (i.e. the value returned is
|
||||
* always a multiple of four). On 8 MHz Arduino boards (e.g. the LilyPad), this function has a resolution
|
||||
* of eight microseconds.
|
||||
*
|
||||
* \note There are 1,000 microseconds in a millisecond and 1,000,000 microseconds in a second.
|
||||
*/
|
||||
extern uint32_t micros( void ) ;
|
||||
|
||||
/**
|
||||
* \brief Pauses the program for the amount of time (in miliseconds) specified as parameter.
|
||||
* (There are 1000 milliseconds in a second.)
|
||||
*
|
||||
* \param dwMs the number of milliseconds to pause (uint32_t)
|
||||
*/
|
||||
extern void delay( uint32_t dwMs ) ;
|
||||
extern void delayMicroseconds(uint32_t usec);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIRING_ */
|
||||
259
arduino/realtek-ambz/cores/arduino/wiring_analog.c
Normal file
259
arduino/realtek-ambz/cores/arduino/wiring_analog.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
// RTL8710 module do not support ADC/DAC
|
||||
#if 1 // !defined(BOARD_RTL8710)
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "analogin_api.h"
|
||||
#include "analogout_api.h"
|
||||
#include "pwmout_api.h"
|
||||
#include "gpio_ex_api.h"
|
||||
|
||||
|
||||
/* ADC */
|
||||
analogin_t adc1;
|
||||
analogin_t adc2;
|
||||
analogin_t adc3;
|
||||
|
||||
static const float ADC_slope1 = (3.12)/(3410.0-674.0);
|
||||
static const float ADC_slope2 = (3.3-3.12)/(3454.0-3410.0);
|
||||
|
||||
bool g_adc_enabled[] = {
|
||||
false, false, false
|
||||
};
|
||||
|
||||
/* DAC */
|
||||
dac_t dac0;
|
||||
|
||||
bool g_dac_enabled[] = {
|
||||
false
|
||||
};
|
||||
|
||||
extern void *gpio_pin_struct[];
|
||||
|
||||
//
|
||||
// Arduino
|
||||
//
|
||||
|
||||
static int _readResolution = 10;
|
||||
static int _writeResolution = 8;
|
||||
static int _writePeriod = 20000;
|
||||
|
||||
void analogReadResolution(int res) {
|
||||
_readResolution = res;
|
||||
}
|
||||
|
||||
void analogWriteResolution(int res) {
|
||||
_writeResolution = res;
|
||||
}
|
||||
|
||||
void analogWritePeriod(int us) {
|
||||
_writePeriod = us;
|
||||
}
|
||||
|
||||
static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to) {
|
||||
if (from == to)
|
||||
return value;
|
||||
if (from > to)
|
||||
return value >> (from-to);
|
||||
else
|
||||
return value << (to-from);
|
||||
}
|
||||
|
||||
eAnalogReference analog_reference = AR_DEFAULT;
|
||||
|
||||
void analogReference(eAnalogReference ulMode)
|
||||
{
|
||||
analog_reference = ulMode;
|
||||
}
|
||||
|
||||
uint32_t analogRead(uint32_t ulPin)
|
||||
{
|
||||
uint32_t ulValue = 0;
|
||||
uint32_t ulChannel;
|
||||
uint16_t ret = 0;
|
||||
float voltage;
|
||||
float adc_value;
|
||||
|
||||
switch ( ulPin ) {
|
||||
case A0:
|
||||
if (g_adc_enabled[0] == false)
|
||||
{
|
||||
analogin_init(&adc1, AD_1);
|
||||
g_adc_enabled[0] = true;
|
||||
}
|
||||
case A1:
|
||||
if (g_adc_enabled[1] == false)
|
||||
{
|
||||
analogin_init(&adc2, AD_2);
|
||||
g_adc_enabled[1] = true;
|
||||
}
|
||||
ret = analogin_read_u16(&adc2);
|
||||
break;
|
||||
case A2:
|
||||
if (g_adc_enabled[2] == false)
|
||||
{
|
||||
analogin_init(&adc3, AD_3);
|
||||
g_adc_enabled[2] = true;
|
||||
}
|
||||
ret = analogin_read_u16(&adc3);
|
||||
break;
|
||||
default:
|
||||
printf("%s : ulPin %d wrong\n", __FUNCTION__, ulPin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret >>= 4;
|
||||
if (ret < 674) {
|
||||
voltage = 0;
|
||||
} else if ( ret > 3410){
|
||||
voltage = (float)(ret - 3410)*ADC_slope2 + 3.12;
|
||||
} else {
|
||||
voltage = (float)(ret-674)*ADC_slope1;
|
||||
}
|
||||
|
||||
ret = round((1<<_readResolution)*voltage/3.3);
|
||||
if ( ret >= (1<<_readResolution) ) ret = (1<<_readResolution) - 1;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void analogOutputInit(void) {
|
||||
// nop
|
||||
}
|
||||
|
||||
// Right now, PWM output only works on the pins with
|
||||
// hardware support. These are defined in the appropriate
|
||||
// pins_*.c file. For the rest of the pins, we default
|
||||
// to digital output.
|
||||
void analogWrite(uint32_t ulPin, uint32_t ulValue)
|
||||
{
|
||||
pwmout_t *obj;
|
||||
|
||||
if (ulPin == DAC0)
|
||||
{
|
||||
if (g_dac_enabled[0] == false) {
|
||||
analogout_init(&dac0, DA_0);
|
||||
g_dac_enabled[0] = true;
|
||||
}
|
||||
ulValue %= (1<<_writeResolution);
|
||||
analogout_write(&dac0, ulValue * 1.0 / (1<<_writeResolution) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((g_APinDescription[ulPin].ulPinAttribute & PIO_PWM) == PIO_PWM) {
|
||||
/* Handle */
|
||||
if ( g_APinDescription[ulPin].ulPinType != PIO_PWM )
|
||||
{
|
||||
if ( (g_APinDescription[ulPin].ulPinType == PIO_GPIO) || (g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ) ) {
|
||||
pinRemoveMode(ulPin);
|
||||
}
|
||||
gpio_pin_struct[ulPin] = malloc ( sizeof(pwmout_t) );
|
||||
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
|
||||
pwmout_init( obj, g_APinDescription[ulPin].pinname );
|
||||
pwmout_period_us( obj, _writePeriod);
|
||||
pwmout_write( obj, ulValue * 1.0 / (1<<_writeResolution));
|
||||
g_APinDescription[ulPin].ulPinType = PIO_PWM;
|
||||
g_APinDescription[ulPin].ulPinMode = PWM_MODE_ENABLED;
|
||||
} else {
|
||||
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
|
||||
pwmout_period_us( obj, _writePeriod);
|
||||
pwmout_write( obj, ulValue * 1.0 / (1<<_writeResolution));
|
||||
if ( g_APinDescription[ulPin].ulPinMode == PWM_MODE_DISABLED ) {
|
||||
HAL_Pwm_Enable( &obj->pwm_hal_adp );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct _tone_argument {
|
||||
uint32_t ulPin;
|
||||
uint32_t timer_id;
|
||||
};
|
||||
|
||||
void _tone_timer_handler(void const *argument)
|
||||
{
|
||||
struct _tone_argument *arg = (struct _tone_argument *)argument;
|
||||
|
||||
uint32_t ulPin = (uint32_t) argument;
|
||||
|
||||
noTone(arg->ulPin);
|
||||
|
||||
os_timer_delete(arg->timer_id);
|
||||
|
||||
free( (struct _tone_argument *) arg );
|
||||
}
|
||||
|
||||
void _tone(uint32_t ulPin, unsigned int frequency, unsigned long duration)
|
||||
{
|
||||
pwmout_t *obj;
|
||||
|
||||
if ((g_APinDescription[ulPin].ulPinAttribute & PIO_PWM) != PIO_PWM) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType != PIO_PWM )
|
||||
{
|
||||
if ( (g_APinDescription[ulPin].ulPinType == PIO_GPIO) || (g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ) ) {
|
||||
pinRemoveMode(ulPin);
|
||||
}
|
||||
gpio_pin_struct[ulPin] = malloc ( sizeof(pwmout_t) );
|
||||
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
|
||||
pwmout_init( obj, g_APinDescription[ulPin].pinname);
|
||||
pwmout_period( obj, 1.0/frequency );
|
||||
pwmout_pulsewidth( obj, 1.0/(frequency * 2) );
|
||||
g_APinDescription[ulPin].ulPinType = PIO_PWM;
|
||||
g_APinDescription[ulPin].ulPinMode = PWM_MODE_ENABLED;
|
||||
|
||||
} else {
|
||||
// There is already a PWM configured
|
||||
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
|
||||
pwmout_period( obj, 1.0/frequency );
|
||||
pwmout_pulsewidth( obj, 1.0/(frequency * 2));
|
||||
if (g_APinDescription[ulPin].ulPinMode == PWM_MODE_DISABLED) {
|
||||
HAL_Pwm_Enable( &obj->pwm_hal_adp );
|
||||
}
|
||||
}
|
||||
|
||||
if (duration > 0) {
|
||||
struct _tone_argument *arg = (struct _tone_argument *) malloc ( sizeof(struct _tone_argument) );
|
||||
arg->ulPin = ulPin;
|
||||
arg->timer_id = os_timer_create(_tone_timer_handler, 0, arg);
|
||||
os_timer_start(arg->timer_id, duration);
|
||||
}
|
||||
}
|
||||
|
||||
void noTone(uint32_t ulPin)
|
||||
{
|
||||
pinRemoveMode(ulPin);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
//#else // #if !defined(BOARD_RTL8710)
|
||||
|
||||
#endif // #if !defined(BOARD_RTL8710)
|
||||
88
arduino/realtek-ambz/cores/arduino/wiring_analog.h
Normal file
88
arduino/realtek-ambz/cores/arduino/wiring_analog.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_ANALOG_
|
||||
#define _WIRING_ANALOG_
|
||||
|
||||
// RTL8710 module do not support ADC/DAC
|
||||
#if 1 // !defined(BOARD_RTL8710)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* \brief SAM3 products have only one reference for ADC
|
||||
*/
|
||||
typedef enum _eAnalogReference
|
||||
{
|
||||
AR_DEFAULT,
|
||||
} eAnalogReference ;
|
||||
|
||||
/*
|
||||
* \brief Configures the reference voltage used for analog input (i.e. the value used as the top of the input range).
|
||||
* This function is kept only for compatibility with existing AVR based API.
|
||||
*
|
||||
* \param ulMmode Should be set to AR_DEFAULT.
|
||||
*/
|
||||
extern void analogReference( eAnalogReference ulMode ) ;
|
||||
|
||||
/*
|
||||
* \brief Writes an analog value (PWM wave) to a pin.
|
||||
*
|
||||
* \param ulPin
|
||||
* \param ulValue
|
||||
*/
|
||||
extern void analogWrite( uint32_t ulPin, uint32_t ulValue ) ;
|
||||
|
||||
/*
|
||||
* \brief Reads the value from the specified analog pin.
|
||||
*
|
||||
* \param ulPin
|
||||
*
|
||||
* \return Read value from selected pin, if no error.
|
||||
*/
|
||||
extern uint32_t analogRead( uint32_t ulPin ) ;
|
||||
|
||||
/*
|
||||
* \brief Set the resolution of analogRead return values. Default is 10 bits (range from 0 to 1023).
|
||||
*
|
||||
* \param res
|
||||
*/
|
||||
extern void analogReadResolution(int res);
|
||||
|
||||
/*
|
||||
* \brief Set the resolution of analogWrite parameters. Default is 8 bits (range from 0 to 255).
|
||||
*
|
||||
* \param res
|
||||
*/
|
||||
extern void analogWriteResolution(int res);
|
||||
|
||||
extern void analogOutputInit( void ) ;
|
||||
|
||||
extern void noTone(uint32_t ulPin);
|
||||
|
||||
extern void analogWritePeriod(int us);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // #if !defined(BOARD_RTL8710)
|
||||
|
||||
#endif /* _WIRING_ANALOG_ */
|
||||
115
arduino/realtek-ambz/cores/arduino/wiring_constants.h
Normal file
115
arduino/realtek-ambz/cores/arduino/wiring_constants.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_CONSTANTS_
|
||||
#define _WIRING_CONSTANTS_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define HIGH 0x1
|
||||
#define LOW 0x0
|
||||
|
||||
#define INPUT_PULLDOWN 0x00
|
||||
#define INPUT INPUT_PULLDOWN
|
||||
#define OUTPUT 0x01
|
||||
#define INPUT_PULLUP 0x02
|
||||
#define INPUT_PULLNONE 0x03
|
||||
#define OUTPUT_OPENDRAIN 0x04
|
||||
#define INPUT_IRQ_FALL 0x05
|
||||
#define INPUT_IRQ_RISE 0x06
|
||||
#define INPUT_IRQ_LOW 0x07
|
||||
#define INPUT_IRQ_HIGH 0x08
|
||||
|
||||
|
||||
#define true 0x1
|
||||
#define false 0x0
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
#define TWO_PI 6.283185307179586476925286766559
|
||||
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||
#define EULER 2.718281828459045235360287471352
|
||||
|
||||
#define SERIAL 0x0
|
||||
#define DISPLAY 0x1
|
||||
|
||||
enum BitOrder {
|
||||
LSBFIRST = 0,
|
||||
MSBFIRST = 1
|
||||
};
|
||||
|
||||
// LOW 0
|
||||
// HIGH 1
|
||||
#define CHANGE 2
|
||||
#define FALLING 3
|
||||
#define RISING 4
|
||||
|
||||
#define DEFAULT 1
|
||||
#define EXTERNAL 0
|
||||
|
||||
// undefine stdlib's abs if encountered
|
||||
#ifdef abs
|
||||
#undef abs
|
||||
#endif // abs
|
||||
|
||||
#ifndef min
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#endif // min
|
||||
|
||||
#ifndef max
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#endif // max
|
||||
|
||||
#define abs(x) ((x)>0?(x):-(x))
|
||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||
#define sq(x) ((x)*(x))
|
||||
|
||||
extern uint32_t ulPortSetInterruptMask( void );
|
||||
extern void vPortClearInterruptMask( uint32_t ulNewMask );
|
||||
|
||||
#define interrupts() vPortClearInterruptMask(0)
|
||||
#define noInterrupts() ulPortSetInterruptMask()
|
||||
|
||||
#define lowByte(w) ((uint8_t) ((w) & 0xff))
|
||||
#define highByte(w) ((uint8_t) ((w) >> 8))
|
||||
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
|
||||
|
||||
typedef unsigned int word;
|
||||
|
||||
#define bit(b) (1UL << (b))
|
||||
|
||||
// TODO: to be checked
|
||||
typedef uint8_t boolean ;
|
||||
typedef uint8_t byte ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif /* _WIRING_CONSTANTS_ */
|
||||
266
arduino/realtek-ambz/cores/arduino/wiring_digital.c
Normal file
266
arduino/realtek-ambz/cores/arduino/wiring_digital.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "gpio_api.h"
|
||||
#include "gpio_irq_api.h"
|
||||
#include "gpio_irq_ex_api.h"
|
||||
#include "pwmout_api.h"
|
||||
|
||||
extern void *gpio_pin_struct[TOTAL_GPIO_PIN_NUM];
|
||||
extern void *gpio_irq_handler_list[TOTAL_GPIO_PIN_NUM];
|
||||
|
||||
void gpioIrqHandler(uint32_t id, gpio_irq_event event) {
|
||||
if ( gpio_irq_handler_list[id] != NULL ) {
|
||||
( (void (*)(uint32_t,uint32_t) )gpio_irq_handler_list[id] ) ( id, (uint32_t)event );
|
||||
}
|
||||
}
|
||||
|
||||
void pinMode( uint32_t ulPin, uint32_t ulMode)
|
||||
{
|
||||
void *pGpio_t;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) )
|
||||
{
|
||||
// Invalid pin
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (g_APinDescription[ulPin].ulPinType == PIO_GPIO || g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ)
|
||||
&& g_APinDescription[ulPin].ulPinMode == ulMode)
|
||||
{
|
||||
// Nothing changes in pin mode
|
||||
return;
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType == PIO_PWM ) {
|
||||
// If this pin has been configured as PWM, then it cannot change to another mode
|
||||
return;
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType == PIO_GPIO &&
|
||||
(ulMode == INPUT_IRQ_FALL || ulMode == INPUT_IRQ_RISE) ) {
|
||||
// Pin mode changes from gpio_t to gpio_irq_t
|
||||
pinRemoveMode(ulPin);
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ &&
|
||||
(ulMode == INPUT || ulMode == OUTPUT || ulMode == INPUT_PULLUP || ulMode == INPUT_PULLNONE || ulMode == OUTPUT_OPENDRAIN) ) {
|
||||
// Pin mode changes from gpio_irq_t to gpio_t
|
||||
pinRemoveMode(ulPin);
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType == NOT_INITIAL ) {
|
||||
if (ulMode == INPUT_IRQ_FALL || ulMode == INPUT_IRQ_RISE || ulMode == INPUT_IRQ_LOW || ulMode == INPUT_IRQ_HIGH) {
|
||||
gpio_pin_struct[ulPin] = malloc ( sizeof(gpio_irq_t) );
|
||||
pGpio_t = gpio_pin_struct[ulPin];
|
||||
gpio_irq_init( pGpio_t, g_APinDescription[ulPin].pinname, gpioIrqHandler, ulPin);
|
||||
g_APinDescription[ulPin].ulPinType = PIO_GPIO_IRQ;
|
||||
} else {
|
||||
gpio_pin_struct[ulPin] = malloc ( sizeof(gpio_t) );
|
||||
pGpio_t = gpio_pin_struct[ulPin];
|
||||
gpio_init( pGpio_t, g_APinDescription[ulPin].pinname );
|
||||
g_APinDescription[ulPin].ulPinType = PIO_GPIO;
|
||||
}
|
||||
g_APinDescription[ulPin].ulPinMode = ulMode;
|
||||
} else {
|
||||
pGpio_t = gpio_pin_struct[ulPin];
|
||||
}
|
||||
|
||||
switch ( ulMode )
|
||||
{
|
||||
case INPUT:
|
||||
gpio_dir( (gpio_t *)pGpio_t, PIN_INPUT );
|
||||
gpio_mode( (gpio_t *)pGpio_t, PullDown );
|
||||
break;
|
||||
|
||||
case INPUT_PULLNONE:
|
||||
gpio_dir( (gpio_t *)pGpio_t, PIN_INPUT );
|
||||
gpio_mode( (gpio_t *)pGpio_t, PullNone );
|
||||
break;
|
||||
|
||||
case INPUT_PULLUP:
|
||||
gpio_dir( (gpio_t *)pGpio_t, PIN_INPUT );
|
||||
gpio_mode( (gpio_t *)pGpio_t, PullUp );
|
||||
break;
|
||||
|
||||
case OUTPUT:
|
||||
gpio_dir( (gpio_t *)pGpio_t, PIN_OUTPUT );
|
||||
gpio_mode( (gpio_t *)pGpio_t, PullNone );
|
||||
break;
|
||||
|
||||
case OUTPUT_OPENDRAIN:
|
||||
gpio_dir( (gpio_t *)pGpio_t, PIN_OUTPUT );
|
||||
gpio_mode( (gpio_t *)pGpio_t, OpenDrain );
|
||||
break;
|
||||
|
||||
case INPUT_IRQ_FALL:
|
||||
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_FALL, 1 );
|
||||
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
|
||||
break;
|
||||
|
||||
case INPUT_IRQ_RISE:
|
||||
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_RISE, 1 );
|
||||
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
|
||||
break;
|
||||
|
||||
case INPUT_IRQ_LOW:
|
||||
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_LOW, 1 );
|
||||
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
|
||||
break;
|
||||
|
||||
case INPUT_IRQ_HIGH:
|
||||
gpio_irq_set( (gpio_irq_t *)pGpio_t, IRQ_HIGH, 1 );
|
||||
gpio_irq_enable( (gpio_irq_t *)pGpio_t );
|
||||
break;
|
||||
|
||||
default:
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite( uint32_t ulPin, uint32_t ulVal )
|
||||
{
|
||||
gpio_t *pGpio_t;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType != PIO_GPIO )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pGpio_t = (gpio_t *)gpio_pin_struct[ulPin];
|
||||
|
||||
gpio_write( pGpio_t, ulVal );
|
||||
}
|
||||
|
||||
int digitalRead( uint32_t ulPin )
|
||||
{
|
||||
gpio_t *pGpio_t;
|
||||
int pin_status;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType != PIO_GPIO )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
pGpio_t = (gpio_t *)gpio_pin_struct[ulPin];
|
||||
|
||||
pin_status = gpio_read( pGpio_t );
|
||||
|
||||
return pin_status;
|
||||
}
|
||||
|
||||
void digitalChangeDir( uint32_t ulPin, uint8_t direction)
|
||||
{
|
||||
gpio_t *pGpio_t;
|
||||
u32 RegValue;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( g_APinDescription[ulPin].ulPinType != PIO_GPIO )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pGpio_t = (gpio_t *)gpio_pin_struct[ulPin];
|
||||
|
||||
gpio_dir( pGpio_t, direction );
|
||||
}
|
||||
|
||||
/**************************** Extend API by RTK ***********************************/
|
||||
|
||||
uint32_t digitalPinToPort( uint32_t ulPin )
|
||||
{
|
||||
uint32_t pin_name;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) )
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
pin_name = HAL_GPIO_GetPinName(g_APinDescription[ulPin].pinname);
|
||||
return HAL_GPIO_GET_PORT_BY_NAME(pin_name);
|
||||
}
|
||||
|
||||
uint32_t digitalPinToBitMask( uint32_t ulPin )
|
||||
{
|
||||
uint32_t pin_name;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) )
|
||||
{
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
pin_name = HAL_GPIO_GetPinName(g_APinDescription[ulPin].pinname);
|
||||
|
||||
return 1 << (HAL_GPIO_GET_PIN_BY_NAME(pin_name));
|
||||
}
|
||||
|
||||
uint32_t digitalSetIrqHandler( uint32_t ulPin, void (*handler)(uint32_t id, uint32_t event) ) {
|
||||
gpio_irq_handler_list[ulPin] = (void *) handler;
|
||||
}
|
||||
|
||||
uint32_t digitalClearIrqHandler( uint32_t ulPin ) {
|
||||
gpio_irq_handler_list[ulPin] = NULL;
|
||||
}
|
||||
|
||||
void pinRemoveMode(uint32_t ulPin) {
|
||||
if ( g_APinDescription[ulPin].ulPinType == PIO_PWM ) {
|
||||
// The PWM pin can only be disabled
|
||||
pwmout_t *obj = (pwmout_t *)gpio_pin_struct[ulPin];
|
||||
HAL_Pwm_Disable( &obj->pwm_hal_adp );
|
||||
g_APinDescription[ulPin].ulPinMode = PWM_MODE_DISABLED;
|
||||
}
|
||||
if ( g_APinDescription[ulPin].ulPinType == PIO_GPIO ) {
|
||||
gpio_deinit( (gpio_t *)gpio_pin_struct[ulPin], g_APinDescription[ulPin].pinname );
|
||||
free ( (gpio_t *)gpio_pin_struct[ulPin] );
|
||||
gpio_pin_struct[ulPin] = NULL;
|
||||
g_APinDescription[ulPin].ulPinType = NOT_INITIAL;
|
||||
g_APinDescription[ulPin].ulPinMode = NOT_INITIAL;
|
||||
}
|
||||
if ( g_APinDescription[ulPin].ulPinType == PIO_GPIO_IRQ ) {
|
||||
gpio_irq_deinit( (gpio_irq_t *)gpio_pin_struct[ulPin] );
|
||||
free ( (gpio_irq_t *)gpio_pin_struct[ulPin] );
|
||||
gpio_pin_struct[ulPin] = NULL;
|
||||
g_APinDescription[ulPin].ulPinType = NOT_INITIAL;
|
||||
g_APinDescription[ulPin].ulPinMode = NOT_INITIAL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
77
arduino/realtek-ambz/cores/arduino/wiring_digital.h
Normal file
77
arduino/realtek-ambz/cores/arduino/wiring_digital.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_DIGITAL_
|
||||
#define _WIRING_DIGITAL_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Configures the specified pin to behave either as an input or an output. See the description of digital pins for details.
|
||||
*
|
||||
* \param ulPin The number of the pin whose mode you wish to set
|
||||
* \param ulMode Either INPUT or OUTPUT
|
||||
*/
|
||||
extern void pinMode( uint32_t dwPin, uint32_t dwMode ) ;
|
||||
|
||||
/**
|
||||
* \brief Write a HIGH or a LOW value to a digital pin.
|
||||
*
|
||||
* If the pin has been configured as an OUTPUT with pinMode(), its voltage will be set to the
|
||||
* corresponding value: 5V (or 3.3V on 3.3V boards) for HIGH, 0V (ground) for LOW.
|
||||
*
|
||||
* If the pin is configured as an INPUT, writing a HIGH value with digitalWrite() will enable an internal
|
||||
* 20K pullup resistor (see the tutorial on digital pins). Writing LOW will disable the pullup. The pullup
|
||||
* resistor is enough to light an LED dimly, so if LEDs appear to work, but very dimly, this is a likely
|
||||
* cause. The remedy is to set the pin to an output with the pinMode() function.
|
||||
*
|
||||
* \note Digital pin PIN_LED is harder to use as a digital input than the other digital pins because it has an LED
|
||||
* and resistor attached to it that's soldered to the board on most boards. If you enable its internal 20k pull-up
|
||||
* resistor, it will hang at around 1.7 V instead of the expected 5V because the onboard LED and series resistor
|
||||
* pull the voltage level down, meaning it always returns LOW. If you must use pin PIN_LED as a digital input, use an
|
||||
* external pull down resistor.
|
||||
*
|
||||
* \param dwPin the pin number
|
||||
* \param dwVal HIGH or LOW
|
||||
*/
|
||||
extern void digitalWrite( uint32_t dwPin, uint32_t dwVal ) ;
|
||||
|
||||
/**
|
||||
* \brief Reads the value from a specified digital pin, either HIGH or LOW.
|
||||
*
|
||||
* \param ulPin The number of the digital pin you want to read (int)
|
||||
*
|
||||
* \return HIGH or LOW
|
||||
*/
|
||||
extern int digitalRead( uint32_t ulPin ) ;
|
||||
|
||||
extern void digitalChangeDir( uint32_t ulPin, uint8_t direction);
|
||||
/**************************** Extend API by RTK ***********************************/
|
||||
extern uint32_t digitalPinToPort( uint32_t ulPin );
|
||||
extern uint32_t digitalPinToBitMask( uint32_t ulPin );
|
||||
extern uint32_t digitalSetIrqHandler( uint32_t ulPin, void (*handler)(uint32_t id, uint32_t event) );
|
||||
extern uint32_t digitalClearIrqHandler( uint32_t ulPin );
|
||||
extern void pinRemoveMode(uint32_t ulPin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIRING_DIGITAL_ */
|
||||
118
arduino/realtek-ambz/cores/arduino/wiring_os.c
Normal file
118
arduino/realtek-ambz/cores/arduino/wiring_os.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "wiring_os.h"
|
||||
#include "cmsis_os.h"
|
||||
|
||||
uint32_t os_thread_create( void (*task)(const void *argument), void *argument, int priority, uint32_t stack_size ) {
|
||||
|
||||
osThreadDef_t thread_def;
|
||||
|
||||
thread_def.pthread = task;
|
||||
thread_def.tpriority = (osPriority)priority;
|
||||
// the underlying freertos implementation on cmsis os divide stack size by 4
|
||||
thread_def.stacksize = stack_size * 4;
|
||||
thread_def.name = "ARDUINO";
|
||||
|
||||
return (uint32_t)osThreadCreate(&thread_def, argument);
|
||||
}
|
||||
|
||||
uint32_t os_thread_get_id( void ) {
|
||||
return osThreadGetId();
|
||||
}
|
||||
|
||||
uint32_t os_thread_terminate( uint32_t thread_id ) {
|
||||
return (uint32_t)osThreadTerminate(thread_id);
|
||||
}
|
||||
|
||||
uint32_t os_thread_yield( void ) {
|
||||
return (uint32_t)osThreadYield();
|
||||
}
|
||||
|
||||
uint32_t os_thread_set_priority( uint32_t thread_id, int priority ) {
|
||||
return (uint32_t)osThreadSetPriority(thread_id, (osPriority)priority);
|
||||
}
|
||||
|
||||
int os_thread_get_priority( uint32_t thread_id ) {
|
||||
return (int)osThreadGetPriority(thread_id);
|
||||
}
|
||||
|
||||
int32_t os_signal_set( uint32_t thread_id, int32_t signals ) {
|
||||
return osSignalSet(thread_id, signals);
|
||||
}
|
||||
|
||||
int32_t os_signal_clear( uint32_t thread_id, int32_t signals ) {
|
||||
return osSignalClear(thread_id, signals);
|
||||
}
|
||||
|
||||
os_event_t os_signal_wait( int32_t signals, uint32_t millisec ) {
|
||||
|
||||
osEvent evt;
|
||||
os_event_t ret;
|
||||
|
||||
evt = osSignalWait(signals, millisec);
|
||||
ret.status = (uint32_t)evt.status;
|
||||
ret.value.signals = evt.value.signals;
|
||||
ret.def.message_id = evt.def.message_id;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef void (*os_ptimer) (void const *argument);
|
||||
|
||||
uint32_t os_timer_create(void (*callback)(void const *argument), uint8_t isPeriodic, void *argument) {
|
||||
|
||||
osTimerDef_t *pTimerDef;
|
||||
|
||||
pTimerDef = (osTimerDef_t *) malloc ( sizeof(osTimerDef_t) );
|
||||
pTimerDef->ptimer = callback;
|
||||
pTimerDef->custom = (struct os_timer_custom *) malloc ( sizeof (struct os_timer_custom) );
|
||||
|
||||
return osTimerCreate(pTimerDef, (isPeriodic ? osTimerPeriodic : osTimerOnce), argument);
|
||||
}
|
||||
|
||||
uint32_t os_timer_start (uint32_t timer_id, uint32_t millisec) {
|
||||
return osTimerStart (timer_id, millisec);
|
||||
}
|
||||
|
||||
uint32_t os_timer_stop (uint32_t timer_id) {
|
||||
return osTimerStop(timer_id);
|
||||
}
|
||||
|
||||
uint32_t os_timer_delete(uint32_t timer_id) {
|
||||
|
||||
osTimerDef_t *pTimerDef;
|
||||
|
||||
pTimerDef = (osTimerDef_t *) pvTimerGetTimerID(timer_id);
|
||||
free (pTimerDef->custom);
|
||||
free (pTimerDef);
|
||||
|
||||
return osTimerDelete(timer_id);
|
||||
}
|
||||
|
||||
uint32_t os_semaphore_create(int32_t count) {
|
||||
return (uint32_t)osSemaphoreCreate(NULL, count);
|
||||
}
|
||||
|
||||
int32_t os_semaphore_wait(uint32_t semaphore_id, uint32_t millisec) {
|
||||
if (osSemaphoreWait((osSemaphoreId)semaphore_id, millisec) == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t os_semaphore_release(uint32_t semaphore_id) {
|
||||
return (uint32_t)osSemaphoreRelease((osSemaphoreId)semaphore_id);
|
||||
}
|
||||
|
||||
uint32_t os_semaphore_delete(uint32_t semaphore_id) {
|
||||
return (uint32_t)osSemaphoreDelete((osSemaphoreId)semaphore_id);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
310
arduino/realtek-ambz/cores/arduino/wiring_os.h
Normal file
310
arduino/realtek-ambz/cores/arduino/wiring_os.h
Normal file
@@ -0,0 +1,310 @@
|
||||
/** @file wiring_os.h */
|
||||
|
||||
/**
|
||||
* @defgroup wiring_os wiring_os
|
||||
* OS realted function for thread, signal, software timer, semaphore
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_OS_H_
|
||||
#define _WIRING_OS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @defgroup os_status os_status
|
||||
* Redefinition from enum osStatus
|
||||
* @{
|
||||
*/
|
||||
/** function completed; no error or event occurred. */
|
||||
#define OS_OK 0x00
|
||||
/** function completed; signal event occurred. */
|
||||
#define OS_EVENT_SIGNAL 0x08
|
||||
/** function completed; message event occurred. */
|
||||
#define OS_EVENT_MESSAGE 0x10
|
||||
/** function completed; mail event occurred. */
|
||||
#define OS_EVENT_MAIL 0x20
|
||||
/** function completed; timeout occurred. */
|
||||
#define OS_EVENT_TIMEOUT 0x40
|
||||
/** parameter error: a mandatory parameter was missing or specified an incorrect object. */
|
||||
#define OS_ERROR_PARAMETER 0x80
|
||||
/** resource not available: a specified resource was not available. */
|
||||
#define OS_ERROR_RESOURCE 0x81
|
||||
/** resource not available within given time: a specified resource was not available within the timeout period. */
|
||||
#define OS_ERROR_TIMEOUT_RESOURCE 0xC1
|
||||
/** not allowed in ISR context: the function cannot be called from interrupt service routines. */
|
||||
#define OS_ERROR_ISR 0x82
|
||||
/** function called multiple times from ISR with same object. */
|
||||
#define OS_ERROR_ISR_RECURSIVE 0x83
|
||||
/** system cannot determine priority or thread has illegal priority. */
|
||||
#define OS_ERROR_PRIORITY 0x84
|
||||
/** system is out of memory: it was impossible to allocate or reserve memory for the operation. */
|
||||
#define OS_ERROR_NO_MEMORY 0x85
|
||||
/** value of a parameter is out of range. */
|
||||
#define OS_ERROR_VALUE 0x86
|
||||
/** unspecified RTOS error: run-time error but no other error message fits. */
|
||||
#define OS_ERROR_OS 0xFF
|
||||
/** @} */ // end of group os_status
|
||||
|
||||
/**
|
||||
* @defgroup os_priority os_priority
|
||||
* Redefinition from enum osPriority
|
||||
* @{
|
||||
*/
|
||||
/** priority: idle (lowest) */
|
||||
#define OS_PRIORITY_IDLE (-3)
|
||||
/** priority: low */
|
||||
#define OS_PRIORITY_LOW (-2)
|
||||
/** priority: below normal */
|
||||
#define OS_PRIORITY_BELOW_NORMAL (-1)
|
||||
/** priority: normal (default) */
|
||||
#define OS_PRIORITY_NORMAL ( 0)
|
||||
/** priority: above normal */
|
||||
#define OS_PRIORITY_ABOVENORMAL (+1)
|
||||
/** priority: high */
|
||||
#define OS_PRIORITY_HIGH (+2)
|
||||
/** priority: realtime (highest) */
|
||||
#define OS_PRIORITY_REALTIME (+3)
|
||||
/** @} */ // end of group os_priority
|
||||
|
||||
#ifndef DEFAULT_STACK_SIZE
|
||||
/**
|
||||
* @ingroup wiring_os
|
||||
* @brief default stack size
|
||||
*
|
||||
* It is suggest that thread is assigned stack size more than DEFAULT_STACK_SIZE
|
||||
*/
|
||||
#define DEFAULT_STACK_SIZE 512
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @ingroup wiring_os
|
||||
* @struct os_event_t
|
||||
* Redefine osEvent in cmsis_os.h
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t status; ///< status code: event or error information
|
||||
union {
|
||||
uint32_t v; ///< message as 32-bit value
|
||||
void *p; ///< message or mail as void pointer
|
||||
int32_t signals; ///< signal flags
|
||||
} value; ///< event value
|
||||
union {
|
||||
void *mail_id; ///< mail id obtained by osMailCreate
|
||||
void *message_id; ///< message id obtained by osMessageCreate
|
||||
} def; ///< event definition
|
||||
} os_event_t;
|
||||
|
||||
/**
|
||||
* @defgroup thread_management thread_management
|
||||
* Thread management include create, get thread id, terminate, yield, and set/get priority
|
||||
**/
|
||||
|
||||
/**
|
||||
* @ingroup thread_management
|
||||
* @brief Create a thread and add it to Active Threads and set it to state READY.
|
||||
*
|
||||
* @param[in] task Function pointer which is the thread body. It should not run into the end of function unless os_thread_terminate is invoked
|
||||
* @param[in] argument the data pointer which brings to task
|
||||
* @param[in] priority The underlying os is FreeRTOS. It executes tasks with highest priority which are not in idle state.\n
|
||||
* If there are more than 2 tasks to be executed, then they share the time slice.
|
||||
* @param[in] stack_size The stack_size is used as memory heap only for this task. \n
|
||||
* The local variables and call stacks would occupy this heap. Please make sure the the stack_size is big enough to avoid curroption
|
||||
* @return The thread id which is used in thread operation and signaling.
|
||||
*/
|
||||
extern uint32_t os_thread_create(void (*task)(const void *argument), void *argument, int priority, uint32_t stack_size);
|
||||
|
||||
/**
|
||||
* @ingroup thread_management
|
||||
* @brief Return the thread ID of the current running thread.
|
||||
*
|
||||
* @return Current thread id which calls os_thread_get_id
|
||||
*/
|
||||
extern uint32_t os_thread_get_id( void );
|
||||
|
||||
/**
|
||||
* @ingroup thread_management
|
||||
* @brief Terminate execution of a thread and remove it from Active Threads.
|
||||
*
|
||||
* Thread should not ended without terminate first
|
||||
*
|
||||
* @param[in] thread_id Terminate the thread with specific thread_id
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_thread_terminate(uint32_t thread_id);
|
||||
|
||||
/**
|
||||
* @ingroup thread_management
|
||||
* @brief Pass control to next thread that is in state \b READY.
|
||||
*
|
||||
* By default the minimal execution unit is 1 millisecond. In a scenario that if a thread with smaller want to handout execution right to a thread with
|
||||
* higher priority immediately without waiting for the ending of current 1 millisecond, then invoke os_thread_yield can transfer exection right to
|
||||
* OS's idle task and check which is the next execution thread.
|
||||
*
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_thread_yield(void);
|
||||
|
||||
/**
|
||||
* @ingroup thread_management
|
||||
* @brief Change priority of an active thread.
|
||||
*
|
||||
* @param[in] thread_id The target thread with the thread id to be changed
|
||||
* @param[in] priority The updated priority
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_thread_set_priority(uint32_t thread_id, int priority);
|
||||
|
||||
/**
|
||||
* @ingroup thread_management
|
||||
* @brief Get current priority of an active thread.
|
||||
*
|
||||
* @param[in] thread_id The target thread with the thread id to be searched
|
||||
* @return os_priority
|
||||
*/
|
||||
extern int os_thread_get_priority(uint32_t thread_id);
|
||||
|
||||
/**
|
||||
* @defgroup signal_management signal_management
|
||||
* Signaling between threads include set, clear, and wait
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup signal_management
|
||||
* @brief Set the specified Signal Flags of an active thread.
|
||||
*
|
||||
* @param[in] thread_id Send signal to a thread with the thread id
|
||||
* @param[in] signals the signals to be send
|
||||
* @return os_status code
|
||||
*/
|
||||
extern int32_t os_signal_set(uint32_t thread_id, int32_t signals);
|
||||
|
||||
/**
|
||||
* @ingroup signal_management
|
||||
* @brief Clear the specified Signal Flags of an active thread.
|
||||
*
|
||||
* @param[in] thread_id Clear signal to a thread with the thread id
|
||||
* @param[in] signals The signals to be clear
|
||||
* @return os_status code
|
||||
*/
|
||||
extern int32_t os_signal_clear(uint32_t thread_id, int32_t signals);
|
||||
|
||||
/**
|
||||
* @ingroup signal_management
|
||||
* @brief Wait for one or more Signal Flags to become signaled for the current \b RUNNING thread.
|
||||
*
|
||||
* @param[in] signals the signals to be wait
|
||||
* @param[in] millisec the timeout value if no signal comes in. Fill in 0xFFFFFFFF for infinite wait.
|
||||
* @return os_status code
|
||||
*/
|
||||
extern os_event_t os_signal_wait(int32_t signals, uint32_t millisec);
|
||||
|
||||
/**
|
||||
* @defgroup timer_management timer_management
|
||||
* Software timer management include create, start, stop, delete.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup timer_management
|
||||
* @brief specify timer type that invoke only once
|
||||
*/
|
||||
#define OS_TIMER_ONCE (0)
|
||||
|
||||
/**
|
||||
* @ingroup timer_management
|
||||
* @brief specify timer type that invoke periodically
|
||||
*/
|
||||
#define OS_TIMER_PERIODIC (1)
|
||||
|
||||
/**
|
||||
* @ingroup timer_management
|
||||
* @brief Create a timer.
|
||||
*
|
||||
* @param[in] callback The function to be invoke when timer timeout
|
||||
* @param[in] isPeriodic \b OS_TIMER_ONCE or \b OS_TIMER_PERIODIC
|
||||
* @param[in] argument The argument that is bring into callback function
|
||||
* @return timer id
|
||||
*/
|
||||
extern uint32_t os_timer_create(void (*callback)(void const *argument), uint8_t isPeriodic, void *argument);
|
||||
|
||||
/**
|
||||
* @ingroup timer_management
|
||||
* @brief Start or restart a timer.
|
||||
*
|
||||
* @param[in] timer_id The timer id obtained from by os_timer_create
|
||||
* @param[in] millisec The delays after timer starts
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_timer_start (uint32_t timer_id, uint32_t millisec);
|
||||
|
||||
/**
|
||||
* @ingroup timer_management
|
||||
* @brief Stop the timer.
|
||||
*
|
||||
* @param[in] timer_id The timer id obtained from by os_timer_create
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_timer_stop (uint32_t timer_id);
|
||||
|
||||
/**
|
||||
* @ingroup timer_management
|
||||
* @brief Delete a timer that was created by os_timer_create
|
||||
*
|
||||
* @param[in] timer_id The timer id obtained from by os_timer_create
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_timer_delete(uint32_t timer_id);
|
||||
|
||||
/**
|
||||
* @defgroup semaphore_management semaphore_management
|
||||
* Semaphore API between threads include create, wait, release, delete.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup semaphore_management
|
||||
* @brief Create and Initialize a Semaphore object used for managing resources
|
||||
*
|
||||
* @param[in] count The number of available resources
|
||||
* @return semaphore ID
|
||||
*/
|
||||
extern uint32_t os_semaphore_create(int32_t count);
|
||||
|
||||
/**
|
||||
* @ingroup semaphore_management
|
||||
* @brief Wait until a Semaphore token becomes available
|
||||
*
|
||||
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
|
||||
* @param[in] millisec timeout value
|
||||
* @return os_status code
|
||||
*/
|
||||
extern int32_t os_semaphore_wait(uint32_t semaphore_id, uint32_t millisec);
|
||||
|
||||
/**
|
||||
* @ingroup semaphore_management
|
||||
* @brief Release a Semaphore token
|
||||
*
|
||||
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_semaphore_release(uint32_t semaphore_id);
|
||||
|
||||
/**
|
||||
* @ingroup semaphore_management
|
||||
* @brief Delete a Semaphore that was created by os_semaphore_create.
|
||||
*
|
||||
* @param[in] semaphore_id semaphore id obtained from os_semaphore_create
|
||||
* @return os_status code
|
||||
*/
|
||||
extern uint32_t os_semaphore_delete(uint32_t semaphore_id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */ // end of group wiring_os
|
||||
42
arduino/realtek-ambz/cores/arduino/wiring_private.h
Normal file
42
arduino/realtek-ambz/cores/arduino/wiring_private.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef WiringPrivate_h
|
||||
#define WiringPrivate_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
// Includes Atmel CMSIS
|
||||
//#include <chip.h>
|
||||
|
||||
#include "wiring_constants.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
89
arduino/realtek-ambz/cores/arduino/wiring_pulse.cpp
Normal file
89
arduino/realtek-ambz/cores/arduino/wiring_pulse.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "wiring_private.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "PinNames.h"
|
||||
#include "objects.h"
|
||||
#include "gpio_api.h"
|
||||
#include "us_ticker_api.h"
|
||||
|
||||
extern void *gpio_pin_struct[];
|
||||
|
||||
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
|
||||
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
|
||||
* to 3 minutes in length, but must be called at least a few dozen microseconds
|
||||
* before the start of the pulse. */
|
||||
extern uint32_t pulseIn( uint32_t ulPin, uint32_t state, uint32_t timeout )
|
||||
{
|
||||
// cache the port and bit of the pin in order to speed up the
|
||||
// pulse width measuring loop and achieve finer resolution. calling
|
||||
// digitalRead() instead yields much coarser resolution.
|
||||
gpio_t *pGpio_t;
|
||||
|
||||
uint32_t start_ticks, cur_ticks;
|
||||
|
||||
if ( ulPin < 0 || ulPin > TOTAL_GPIO_PIN_NUM || (g_APinDescription[ulPin].pinname == NC) ) return 0;
|
||||
|
||||
/* Handle */
|
||||
if ( g_APinDescription[ulPin].ulPinType != PIO_GPIO )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
pGpio_t = (gpio_t *)gpio_pin_struct[ulPin];
|
||||
|
||||
// wait for any previous pulse to end
|
||||
start_ticks = us_ticker_read();
|
||||
while (gpio_read(pGpio_t) == state) {
|
||||
cur_ticks = us_ticker_read();
|
||||
if ( cur_ticks - start_ticks > timeout ) return 0;
|
||||
}
|
||||
|
||||
// wait for the pulse to start
|
||||
while (gpio_read(pGpio_t) != state) {
|
||||
cur_ticks = us_ticker_read();
|
||||
if ( cur_ticks - start_ticks > timeout ) return 0;
|
||||
}
|
||||
|
||||
// wait for the pulse to stop
|
||||
start_ticks = us_ticker_read();
|
||||
while (gpio_read(pGpio_t) == state) {
|
||||
cur_ticks = us_ticker_read();
|
||||
if ( cur_ticks - start_ticks > timeout ) return 0;
|
||||
}
|
||||
|
||||
cur_ticks = us_ticker_read();
|
||||
|
||||
// convert the reading to microseconds. The loop has been determined
|
||||
// to be 52 clock cycles long and have about 16 clocks between the edge
|
||||
// and the start of the loop. There will be some error introduced by
|
||||
// the interrupt handlers.
|
||||
return cur_ticks - start_ticks;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
39
arduino/realtek-ambz/cores/arduino/wiring_pulse.h
Normal file
39
arduino/realtek-ambz/cores/arduino/wiring_pulse.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_PULSE_
|
||||
#define _WIRING_PULSE_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* \brief Measures the length (in microseconds) of a pulse on the pin; state is HIGH
|
||||
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
|
||||
* to 3 minutes in length, but must be called at least a few dozen microseconds
|
||||
* before the start of the pulse.
|
||||
*/
|
||||
extern uint32_t pulseIn( uint32_t ulPin, uint32_t ulState, uint32_t ulTimeout = 1000000L );
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIRING_PULSE_ */
|
||||
71
arduino/realtek-ambz/cores/arduino/wiring_shift.c
Normal file
71
arduino/realtek-ambz/cores/arduino/wiring_shift.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
|
||||
{
|
||||
uint8_t value = 0 ;
|
||||
uint8_t i ;
|
||||
|
||||
for ( i=0 ; i < 8 ; ++i )
|
||||
{
|
||||
digitalWrite( ulClockPin, HIGH ) ;
|
||||
|
||||
if ( ulBitOrder == LSBFIRST )
|
||||
{
|
||||
value |= digitalRead( ulDataPin ) << i ;
|
||||
}
|
||||
else
|
||||
{
|
||||
value |= digitalRead( ulDataPin ) << (7 - i) ;
|
||||
}
|
||||
|
||||
digitalWrite( ulClockPin, LOW ) ;
|
||||
}
|
||||
|
||||
return value ;
|
||||
}
|
||||
|
||||
void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal )
|
||||
{
|
||||
uint8_t i ;
|
||||
|
||||
for ( i=0 ; i < 8 ; i++ )
|
||||
{
|
||||
if ( ulBitOrder == LSBFIRST )
|
||||
{
|
||||
digitalWrite( ulDataPin, !!(ulVal & (1 << i)) ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite( ulDataPin, !!(ulVal & (1 << (7 - i))) ) ;
|
||||
}
|
||||
|
||||
digitalWrite( ulClockPin, HIGH ) ;
|
||||
digitalWrite( ulClockPin, LOW ) ;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
42
arduino/realtek-ambz/cores/arduino/wiring_shift.h
Normal file
42
arduino/realtek-ambz/cores/arduino/wiring_shift.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_SHIFT_
|
||||
#define _WIRING_SHIFT_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* \brief
|
||||
*/
|
||||
extern uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder ) ;
|
||||
|
||||
|
||||
/*
|
||||
* \brief
|
||||
*/
|
||||
extern void shiftOut( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder, uint32_t ulVal ) ;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIRING_SHIFT_ */
|
||||
37
arduino/realtek-ambz/cores/arduino/wiring_watchdog.c
Normal file
37
arduino/realtek-ambz/cores/arduino/wiring_watchdog.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "Arduino.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "wdt_api.h"
|
||||
|
||||
extern uint32_t ConfigDebugErr;
|
||||
|
||||
void wdt_reset() {
|
||||
watchdog_refresh();
|
||||
}
|
||||
|
||||
void wdt_enable(uint32_t timeout_ms) {
|
||||
|
||||
uint32_t backup_ConfigDebugErr;
|
||||
|
||||
backup_ConfigDebugErr = ConfigDebugErr;
|
||||
ConfigDebugErr = 0x00000000;
|
||||
|
||||
if (timeout_ms > 8000) {
|
||||
timeout_ms = 8000;
|
||||
}
|
||||
watchdog_init(timeout_ms);
|
||||
watchdog_start();
|
||||
|
||||
ConfigDebugErr = backup_ConfigDebugErr;
|
||||
}
|
||||
|
||||
void wdt_disable() {
|
||||
watchdog_stop();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
46
arduino/realtek-ambz/cores/arduino/wiring_watchdog.h
Normal file
46
arduino/realtek-ambz/cores/arduino/wiring_watchdog.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/** @file wiring_watchdog.h */
|
||||
|
||||
/**
|
||||
* @defgroup wiring_watchdog wiring_watchdog
|
||||
* watchdog is used for reboot system when device hang
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _WIRING_WATCHDOG_H_
|
||||
#define _WIRING_WATCHDOG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup watchdog */
|
||||
|
||||
/**
|
||||
* @ingroup watchdog
|
||||
* Feed watchdog to avoid it barks
|
||||
*/
|
||||
extern void wdt_reset();
|
||||
|
||||
/**
|
||||
* @ingroup watchdog
|
||||
* @brief Enable watchdog
|
||||
*
|
||||
* After enbling watchdog, user defined code needs to reset it before watchdog barks. Otherwise it would make system reboot.
|
||||
*
|
||||
* @param[in] timeout_ms The timeout value that watchdog barks. The maximum value is 8 seconds.
|
||||
*/
|
||||
extern void wdt_enable(uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @ingroup watchdog
|
||||
* Disable watchdog
|
||||
*/
|
||||
extern void wdt_disable();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _WIRING_WATCHDOG_H_ */
|
||||
|
||||
/** @} */ // end of group wiring_watchdog
|
||||
98
arduino/realtek-ambz/cores/arduino/wl_definitions.h
Normal file
98
arduino/realtek-ambz/cores/arduino/wl_definitions.h
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
wl_definitions.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* wl_definitions.h
|
||||
*
|
||||
* Created on: Mar 6, 2011
|
||||
* Author: dlafauci
|
||||
*/
|
||||
|
||||
#ifndef WL_DEFINITIONS_H_
|
||||
#define WL_DEFINITIONS_H_
|
||||
|
||||
// Maximum size of a SSID
|
||||
#define WL_SSID_MAX_LENGTH 32
|
||||
// Length of passphrase. Valid lengths are 8-63.
|
||||
#define WL_WPA_KEY_MAX_LENGTH 63
|
||||
// Length of key in bytes. Valid values are 5 and 13.
|
||||
#define WL_WEP_KEY_MAX_LENGTH 13
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_MAC_ADDR_LENGTH 6
|
||||
// Size of a MAC-address or BSSID
|
||||
#define WL_IPV4_LENGTH 4
|
||||
// Maximum size of a SSID list
|
||||
#define WL_NETWORKS_LIST_MAXNUM 50
|
||||
// Maxmium number of socket
|
||||
#define MAX_SOCK_NUM 4
|
||||
// Socket not available constant
|
||||
#define SOCK_NOT_AVAIL 255
|
||||
// Default state value for Wifi state field
|
||||
#define NA_STATE -1
|
||||
//Maximum number of attempts to establish wifi connection
|
||||
#define WL_MAX_ATTEMPT_CONNECTION 10
|
||||
|
||||
typedef enum {
|
||||
WL_NO_SHIELD = 255,
|
||||
WL_IDLE_STATUS = 0,
|
||||
WL_NO_SSID_AVAIL,
|
||||
WL_SCAN_COMPLETED,
|
||||
WL_CONNECTED,
|
||||
WL_CONNECT_FAILED,
|
||||
WL_CONNECTION_LOST,
|
||||
WL_DISCONNECTED
|
||||
} wl_status_t;
|
||||
|
||||
/* Encryption modes */
|
||||
enum wl_enc_type { /* Values map to 802.11 encryption suites... */
|
||||
ENC_TYPE_WEP = 5,
|
||||
ENC_TYPE_TKIP = 2,
|
||||
ENC_TYPE_CCMP = 4,
|
||||
/* ... except these two, 7 and 8 are reserved in 802.11-2007 */
|
||||
ENC_TYPE_NONE = 7,
|
||||
ENC_TYPE_AUTO = 8
|
||||
};
|
||||
|
||||
/* RTK added type */
|
||||
#ifndef WEP_ENABLED
|
||||
|
||||
#define WEP_ENABLED 0x0001
|
||||
#define TKIP_ENABLED 0x0002
|
||||
#define AES_ENABLED 0x0004
|
||||
#define WSEC_SWFLAG 0x0008
|
||||
|
||||
#define SHARED_ENABLED 0x00008000
|
||||
#define WPA_SECURITY 0x00200000
|
||||
#define WPA2_SECURITY 0x00400000
|
||||
#define WPS_ENABLED 0x10000000
|
||||
|
||||
#endif // #ifndef WEP_ENABLED
|
||||
|
||||
/* redefined from enum rtw_security_t */
|
||||
#define SECURITY_OPEN ( 0 )
|
||||
#define SECURITY_WEP_PSK ( WEP_ENABLED )
|
||||
#define SECURITY_WEP_SHARED ( WEP_ENABLED | SHARED_ENABLED )
|
||||
#define SECURITY_WPA_TKIP_PSK ( WPA_SECURITY | TKIP_ENABLED )
|
||||
#define SECURITY_WPA_AES_PSK ( WPA_SECURITY | AES_ENABLED )
|
||||
#define SECURITY_WPA2_AES_PSK ( WPA2_SECURITY | AES_ENABLED )
|
||||
#define SECURITY_WPA2_TKIP_PSK ( WPA2_SECURITY | TKIP_ENABLED )
|
||||
#define SECURITY_WPA2_MIXED_PSK ( WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED )
|
||||
#define SECURITY_WPA_WPA2_MIXED ( WPA_SECURITY | WPA2_SECURITY )
|
||||
|
||||
|
||||
#endif /* WL_DEFINITIONS_H_ */
|
||||
49
arduino/realtek-ambz/cores/arduino/wl_types.h
Normal file
49
arduino/realtek-ambz/cores/arduino/wl_types.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
wl_types.h - Library for Arduino Wifi shield.
|
||||
Copyright (c) 2011-2014 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* wl_types.h
|
||||
*
|
||||
* Created on: Jul 30, 2010
|
||||
* Author: dlafauci
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _WL_TYPES_H_
|
||||
#define _WL_TYPES_H_
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef enum {
|
||||
WL_FAILURE = -1,
|
||||
WL_SUCCESS = 1,
|
||||
} wl_error_code_t;
|
||||
|
||||
/* Authentication modes */
|
||||
enum wl_auth_mode {
|
||||
AUTH_MODE_INVALID,
|
||||
AUTH_MODE_AUTO,
|
||||
AUTH_MODE_OPEN_SYSTEM,
|
||||
AUTH_MODE_SHARED_KEY,
|
||||
AUTH_MODE_WPA,
|
||||
AUTH_MODE_WPA2,
|
||||
AUTH_MODE_WPA_PSK,
|
||||
AUTH_MODE_WPA2_PSK
|
||||
};
|
||||
|
||||
#endif //_WL_TYPES_H_
|
||||
108
arduino/realtek-ambz/cores/arduino/wsclient_api.h
Normal file
108
arduino/realtek-ambz/cores/arduino/wsclient_api.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef WSCLIENT_H
|
||||
#define WSCLIENT_H
|
||||
#include <websocket/libwsclient.h>
|
||||
|
||||
|
||||
/******Define the maximum bytes of data send and receive********/
|
||||
#define MAX_DATA_LEN 1500
|
||||
/****************Define if using the polarssl*******************/
|
||||
#define USING_SSL
|
||||
|
||||
|
||||
/******************Define the function used*********************/
|
||||
#ifdef USING_SSL
|
||||
int wss_set_fun_ops(wsclient_context *wsclient);
|
||||
#define wsclient_set_fun_ops(wsclient) wss_set_fun_ops(wsclient)
|
||||
#else
|
||||
int ws_set_fun_ops(wsclient_context *wsclient);
|
||||
#define wsclient_set_fun_ops(wsclient) ws_set_fun_ops(wsclient)
|
||||
#endif
|
||||
/***************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : create_wsclient
|
||||
** Description : Creating the websocket client context structure
|
||||
** Input : url:websocket server's url
|
||||
** port:websocket server's port, if not given, default 80 for "ws", 443 for "wss"
|
||||
** origin: the address or url of your self
|
||||
** Return : Created: websocket client context structure
|
||||
** Failed: NULL
|
||||
**************************************************************************************************/
|
||||
wsclient_context *create_wsclient(char *url, int port,char *path, char* origin);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_connect_url
|
||||
** Description : Connecting to the websocket server
|
||||
** Input : wsclient: the websocket client context created by create_wsclientfunction
|
||||
** Return : Connected: the socket value
|
||||
** Failed: -1
|
||||
**************************************************************************************************/
|
||||
int ws_connect_url(wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_send
|
||||
** Description : Create the sending string data and copy to tx_buf
|
||||
** Input : message: the string that send to server(cannot exceeding the MAX_DATA_LEN
|
||||
** message_len: the length of the string
|
||||
** use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_send(char* message, int message_len, int use_mask, wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_sendBinary
|
||||
** Description : Create the sending binary data and copy to tx_buf
|
||||
** Input : message: the binary that send to server(cannot exceeding the MAX_DATA_LEN
|
||||
** message_len: the length of the binary
|
||||
** use_mask: 0/1; 1 means using mask for bynary
|
||||
** wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_sendBinary(uint8_t* message, int message_len, int use_mask, wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_sendPing
|
||||
** Description : Sending Ping to websocket server
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_sendPing(wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_poll
|
||||
** Description : Receicing data from server and send the data in tx_buf
|
||||
** Input : timeout(in milliseconds)
|
||||
wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_poll(int timeout, wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_dispatch
|
||||
** Description : callback function when getting message from server
|
||||
** Input : function that resolve the message received and the message length
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_dispatch(void (*callback)(wsclient_context *, int)) ;
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_getReadyState
|
||||
** Description : Getting the connection status
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : readyStateValues(4 types:CLOSING, CLOSED, CONNECTING, OPEN)
|
||||
**************************************************************************************************/
|
||||
readyStateValues ws_getReadyState(wsclient_context *wsclient);
|
||||
|
||||
/*************************************************************************************************
|
||||
** Function Name : ws_close
|
||||
** Description : Closing the connection with websocket server
|
||||
** Input : wsclient: the websocket client context
|
||||
** Return : None
|
||||
**************************************************************************************************/
|
||||
void ws_close(wsclient_context *wsclient);
|
||||
|
||||
#endif
|
||||
182
arduino/realtek-ambz/platform.txt
Normal file
182
arduino/realtek-ambz/platform.txt
Normal file
@@ -0,0 +1,182 @@
|
||||
|
||||
# Realtek module Core and platform.
|
||||
# ------------------------------
|
||||
#
|
||||
# For more info:
|
||||
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5-3rd-party-Hardware-specification
|
||||
|
||||
name=RTL871x ARM (32-bits) Boards
|
||||
version=0.0.1
|
||||
|
||||
# rtlmodule project settings
|
||||
# ----------------------
|
||||
|
||||
rtlmodule.sdkpath={build.system.path}/sdk
|
||||
rtlmodule.project={build.variant}
|
||||
rtlmodule.libs={build.system.path}/libs
|
||||
|
||||
# rtlmodule compile variables
|
||||
# ----------------------
|
||||
|
||||
compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/
|
||||
compiler.c.cmd=arm-none-eabi-gcc
|
||||
compiler.c.flags=-c -g -mcpu=cortex-m3 -mthumb -Os -std=c++11 -fno-short-enums -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-short-enums -MMD
|
||||
compiler.c.elf.cmd=arm-none-eabi-gcc
|
||||
compiler.c.elf.flags= -mcpu=cortex-m3 -Os -Wl,--gc-sections -mcpu=cortex-m3 -mthumb --specs=nano.specs
|
||||
compiler.S.flags=-c -g -x assembler-with-cpp
|
||||
compiler.cpp.cmd=arm-none-eabi-g++
|
||||
compiler.cpp.flags=-c -g -Os -std=gnu++11 -mcpu=cortex-m3 -mthumb -fno-short-enums -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-rtti -fno-short-enums -MMD
|
||||
compiler.ar.cmd=arm-none-eabi-ar
|
||||
compiler.ar.flags=rcs
|
||||
compiler.strip.cmd=arm-none-eabi-strip
|
||||
compiler.nm.cmd=arm-none-eabi-nm
|
||||
compiler.objcopy.cmd=arm-none-eabi-objcopy
|
||||
compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0
|
||||
compiler.elf2hex.flags=-O binary
|
||||
compiler.elf2hex.cmd=arm-none-eabi-objcopy
|
||||
compiler.ldflags=
|
||||
compiler.size.cmd=arm-none-eabi-size
|
||||
compiler.define=-DARDUINO=
|
||||
|
||||
# this can be overriden in boards.txt
|
||||
build.extra_flags=
|
||||
|
||||
# These can be overridden in platform.local.txt
|
||||
compiler.c.extra_flags=
|
||||
#compiler.c.elf.extra_flags= -Wl,--cref -Wl,--gc-sections -Wl,--entry=InfraStart -Wl,--no-enum-size-warning -Wl,--no-wchar-size-warning
|
||||
compiler.c.elf.extra_flags= -Wl,--cref -Wl,--gc-sections -Wl,--entry=Reset_Handler -Wl,--no-enum-size-warning -Wl,--no-wchar-size-warning -Wl,--undefined=InfraStart
|
||||
compiler.cpp.extra_flags=
|
||||
compiler.ar.extra_flags=
|
||||
compiler.elf2hex.extra_flags=
|
||||
|
||||
# rtlmodule include path
|
||||
# ------------------
|
||||
|
||||
compiler.rtlmodule.c.include="-I{rtlmodule.sdkpath}/project/{rtlmodule.project}/inc" "-I{rtlmodule.sdkpath}/component/soc/realtek/common/bsp" "-I{rtlmodule.sdkpath}/component/os/freertos" "-I{rtlmodule.sdkpath}/component/os/freertos/freertos_v8.1.2/Source/include" "-I{rtlmodule.sdkpath}/component/os/freertos/freertos_v8.1.2/Source/portable/GCC/ARM_CM3" "-I{rtlmodule.sdkpath}/component/os/os_dep/include" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/misc/driver" "-I{rtlmodule.sdkpath}/component/common/api/network/include" "-I{rtlmodule.sdkpath}/component/common/api" "-I{rtlmodule.sdkpath}/component/common/api/platform" "-I{rtlmodule.sdkpath}/component/common/api/wifi" "-I{rtlmodule.sdkpath}/component/common/api/wifi/rtw_wpa_supplicant/src" "-I{rtlmodule.sdkpath}/component/common/application" "-I{rtlmodule.sdkpath}/component/common/media/framework" "-I{rtlmodule.sdkpath}/component/common/example" "-I{rtlmodule.sdkpath}/component/common/example/wlan_fast_connect" "-I{rtlmodule.sdkpath}/component/common/mbed/api" "-I{rtlmodule.sdkpath}/component/common/mbed/hal" "-I{rtlmodule.sdkpath}/component/common/mbed/hal_ext" "-I{rtlmodule.sdkpath}/component/common/mbed/targets/hal/rtl8195a" "-I{rtlmodule.sdkpath}/component/common/network" "-I{rtlmodule.sdkpath}/component/common/network/lwip/lwip_v1.4.1/port/realtek/freertos" "-I{rtlmodule.sdkpath}/component/common/network/lwip/lwip_v1.4.1/src/include" "-I{rtlmodule.sdkpath}/component/common/network/lwip/lwip_v1.4.1/src/include/lwip" "-I{rtlmodule.sdkpath}/component/common/network/lwip/lwip_v1.4.1/src/include/ipv4" "-I{rtlmodule.sdkpath}/component/common/network/lwip/lwip_v1.4.1/port/realtek" "-I{rtlmodule.sdkpath}/component/common/test" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/cmsis" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/cmsis/device" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/fwlib" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/fwlib/rtl8195a" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/misc/rtl_std_lib/include" "-I{rtlmodule.sdkpath}/component/common/drivers/wlan/realtek/include" "-I{rtlmodule.sdkpath}/component/common/drivers/wlan/realtek/src/osdep" "-I{rtlmodule.sdkpath}/component/common/drivers/wlan/realtek/src/hci" "-I{rtlmodule.sdkpath}/component/common/drivers/wlan/realtek/src/hal" "-I{rtlmodule.sdkpath}/component/common/drivers/wlan/realtek/src/hal/OUTSRC" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/fwlib/ram_lib/wlan/realtek/wlan_ram_map/rom" "-I{rtlmodule.sdkpath}/component/common/network/ssl/polarssl-1.3.8/include" "-I{rtlmodule.sdkpath}/component/common/network/ssl/ssl_ram_map/rom" "-I{rtlmodule.sdkpath}/component/common/utilities" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/misc/rtl_std_lib/include" "-I{rtlmodule.sdkpath}/component/soc/realtek/8195a/fwlib/ram_lib/usb_otg/include" "-I{rtlmodule.sdkpath}/component/common/video/v4l2/inc" "-I{rtlmodule.sdkpath}/component/common/media/codec" "-I{rtlmodule.sdkpath}/component/common/drivers/usb_class/host/uvc/inc" "-I{rtlmodule.sdkpath}/component/common/drivers/usb_class/device" "-I{rtlmodule.sdkpath}/component/common/drivers/usb_class/device/class" "-I{rtlmodule.sdkpath}/component/common/file_system/fatfs" "-I{rtlmodule.sdkpath}/component/common/file_system/fatfs/r0.10c/include" "-I{rtlmodule.sdkpath}/component/common/drivers/sdio/realtek/sdio_host/inc" "-I{rtlmodule.sdkpath}/component/common/audio" "-I{rtlmodule.sdkpath}/component/common/drivers/i2s" "-I{rtlmodule.sdkpath}/component/common/application/xmodem" "-I{rtlmodule.sdkpath}/component/common/network/mdns" "-I{rtlmodule.sdkpath}/component/common/network/libwsclient"
|
||||
compiler.arduino.c.include="-I{build.core.path}"
|
||||
|
||||
compiler.rtlmodule.c.flags= -DCONFIG_PLATFORM_8195A -DARDUINO_SDK -DARDUINO_AMEBA {compiler.arduino.c.include} {compiler.rtlmodule.c.include}
|
||||
|
||||
# rtlmodule archieve list
|
||||
# -------------------
|
||||
compiler.rtlmodule.ar.list="{rtlmodule.libs}/lib_{build.variant}.a" "{rtlmodule.libs}/lib_lwip.a" "{rtlmodule.libs}/lib_mmf.a" "{rtlmodule.libs}/lib_p2p.a" "{rtlmodule.libs}/lib_rtlstd.a" "{rtlmodule.libs}/lib_rtsp.a" "{rtlmodule.libs}/lib_sdcard_v2.a" "{rtlmodule.libs}/lib_usbd.a" "{rtlmodule.libs}/lib_usbh.a" "{rtlmodule.libs}/lib_websocket.a" "{rtlmodule.libs}/lib_wlan.a" "{rtlmodule.libs}/lib_wps.a" "{rtlmodule.libs}/lib_xmodem.a" "{rtlmodule.libs}/lib_mdns.a" "{rtlmodule.libs}/lib_websocket.a" "{rtlmodule.libs}/lib_ssl.a"
|
||||
#compiler.rtlmodule.ar.list="{build.variant.path}/lib_arlib.a" "{build.variant.path}/lib_lwip.a" "{build.variant.path}/lib_mdns.a" "{build.variant.path}/lib_p2p.a" "{build.variant.path}/lib_platform.a" "{build.variant.path}/lib_rtlstd.a" "{build.variant.path}/lib_sdcard.a" "{build.variant.path}/lib_uvc.a" "{build.variant.path}/lib_websocket.a" "{build.variant.path}/lib_wlan.a" "{build.variant.path}/lib_wps.a" "{build.variant.path}/lib_xmodem.a"
|
||||
|
||||
# USB Flags
|
||||
# ---------
|
||||
build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'
|
||||
|
||||
# Default usb manufacturer will be replaced at compile time using
|
||||
# numeric vendor ID if available or by board's specific value.
|
||||
build.usb_manufacturer="Unknown"
|
||||
|
||||
|
||||
# rtlmodule compile patterns
|
||||
# ---------------------
|
||||
|
||||
## Compile c files
|
||||
recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.rtlmodule.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Compile c++ files
|
||||
recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -mcpu={build.mcu} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {compiler.rtlmodule.c.flags} {includes} "{source_file}" -o "{object_file}"
|
||||
|
||||
## Create archives
|
||||
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
|
||||
|
||||
## Combine gc-sections, archives, and objects
|
||||
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} "-L{build.variant.path}/linker_scripts/gcc" "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map={build.path}/application.map" {compiler.c.elf.extra_flags} -o "{build.path}/application.axf" "-L{build.path}" -Wl,--start-group {object_files} -Wl,--end-group -Wl,--start-group "{build.path}/{archive_file}" {compiler.rtlmodule.ar.list} -Wl,--end-group -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys
|
||||
|
||||
## Create nm map
|
||||
recipe.nm.pattern=cp "{build.path}/{build.project_name}.axf" "{build.path}/application.axf"
|
||||
|
||||
## Create strip
|
||||
recipe.strip.pattern="{compiler.path}{compiler.strip.cmd}" "{build.path}/{build.project_name}.axf"
|
||||
|
||||
## Create image
|
||||
recipe.objcopy.hex.cmd=postbuild_img2_arduino_windows.exe
|
||||
recipe.objcopy.hex.cmd.windows=postbuild_img2_arduino_windows.exe
|
||||
recipe.objcopy.hex.cmd.macosx=postbuild_img2_arduino_mac
|
||||
recipe.objcopy.hex.cmd.linux=postbuild_img2_arduino_linux
|
||||
recipe.objcopy.hex.imagepath={build.path}\application.axf
|
||||
recipe.objcopy.hex.imagepath.macosx="{build.path}/application.axf"
|
||||
recipe.objcopy.hex.imagepath.linux="{build.path}/application.axf"
|
||||
recipe.objcopy.hex.pattern="{runtime.tools.ameba_tools.path}/{recipe.objcopy.hex.cmd}" "{runtime.tools.ameba_tools.path}" "{recipe.objcopy.hex.imagepath}" "{compiler.path}" "{build.variant.path}/{build.sym_bklist}"
|
||||
|
||||
## Compute size
|
||||
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/application.axf"
|
||||
#recipe.size.regex=\.text\s+([0-9]+).*
|
||||
recipe.size.regex=^(?:\.ram_image1.text|\.ram_image2.text|\.image3)\s+([0-9]+).*
|
||||
|
||||
|
||||
# rtlmodule Uploader tools
|
||||
# -------------------
|
||||
|
||||
tools.jlink.upload.params.verbose=
|
||||
tools.jlink.cmd=jlink_upload
|
||||
tools.jlink.cmd.windows=jlink_upload.cmd
|
||||
tools.jlink.cmd.macosx=
|
||||
tools.jlink.path.macosx=
|
||||
tools.jlink.path.linux=
|
||||
tools.jlink.path.linux64=
|
||||
tools.jlink.path={runtime.tools.ameba_tools.path}
|
||||
tools.jlink.upload.params.quiet=
|
||||
tools.jlink.upload.pattern="{runtime.platform.path}/tools/jlink_upload.cmd" "{runtime.tools.ameba_tools.path}" "{runtime.platform.path}/tools"
|
||||
|
||||
tools.jlinkam.upload.params.verbose=
|
||||
tools.jlinkam.cmd=jlink_uploadam
|
||||
tools.jlinkam.cmd.windows=jlink_uploadam.cmd
|
||||
tools.jlinkam.cmd.macosx=
|
||||
tools.jlinkam.path.macosx=
|
||||
tools.jlinkam.path.linux=
|
||||
tools.jlinkam.path.linux64=
|
||||
tools.jlinkam.path={runtime.tools.ameba_tools.path}
|
||||
tools.jlinkam.upload.params.quiet=
|
||||
tools.jlinkam.upload.pattern="{runtime.platform.path}/tools/jlink_uploadam.cmd" "{runtime.tools.ameba_tools.path}" "{runtime.platform.path}/tools"
|
||||
|
||||
tools.network.upload.params.verbose=
|
||||
tools.network.cmd=upload_ota
|
||||
tools.network.cmd.windows="{runtime.tools.ameba_tools.path}/upload_ota.exe" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}\ota.bin"
|
||||
tools.network.cmd.macosx=
|
||||
tools.network.path.macosx=
|
||||
tools.network.path.linux=
|
||||
tools.network.path.linux64=
|
||||
tools.network.path={runtime.tools.ameba_tools.path}
|
||||
tools.network.upload.params.quiet=
|
||||
tools.network.upload.pattern="{runtime.tools.ameba_tools.path}/upload_ota.exe" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}\ota.bin"
|
||||
tools.network.upload.network_pattern="{runtime.tools.ameba_tools.path}/upload_ota.exe" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}\ota.bin"
|
||||
tools.network.network_pattern.windows="{runtime.tools.ameba_tools.path}/upload_ota.exe" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}\ota.bin"
|
||||
tools.network.network_pattern.macosx="{runtime.tools.ameba_tools.path}/upload_ota_mac" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}/ota.bin"
|
||||
tools.network.network_pattern.linux="{runtime.tools.ameba_tools.path}/upload_ota_linux" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}/ota.bin"
|
||||
|
||||
tools.jlgdbota.upload.params.verbose=
|
||||
tools.jlgdbota.cmd=JLinkGDB_OTA
|
||||
tools.jlgdbota.cmd.windows=JLinkGDB_OTA.cmd
|
||||
tools.jlgdbota.cmd.macosx=
|
||||
tools.jlgdbota.path.macosx=
|
||||
tools.jlgdbota.path.linux=
|
||||
tools.jlgdbota.path.linux64=
|
||||
tools.jlgdbota.path={runtime.tools.ameba_tools.path}
|
||||
tools.jlgdbota.upload.params.quiet=
|
||||
tools.jlgdbota.upload.pattern="{runtime.platform.path}/tools/JLinkGDB_OTA.cmd" "{runtime.tools.ameba_tools.path}" "{runtime.platform.path}\tools" "{runtime.tools.arm-none-eabi-gcc.path}\bin\"
|
||||
|
||||
tools.jlgdbimg.upload.params.verbose=
|
||||
tools.jlgdbimg.cmd=JLinkGDB_IMG
|
||||
tools.jlgdbimg.cmd.windows=JLinkGDB_IMG.cmd
|
||||
tools.jlgdbimg.cmd.macosx=
|
||||
tools.jlgdbimg.path.macosx=
|
||||
tools.jlgdbimg.path.linux=
|
||||
tools.jlgdbimg.path.linux64=
|
||||
tools.jlgdbimg.path={runtime.tools.ameba_tools.path}
|
||||
tools.jlgdbimg.upload.params.quiet=
|
||||
tools.jlgdbimg.upload.pattern="{runtime.platform.path}/tools/JLinkGDB_IMG.cmd" "{runtime.tools.ameba_tools.path}" "{runtime.platform.path}\tools" "{runtime.tools.arm-none-eabi-gcc.path}\bin\"
|
||||
|
||||
tools.dapimg.upload.params.verbose=
|
||||
tools.dapimg.upload.params.quiet=
|
||||
tools.dapimg.upload.pattern="{runtime.tools.ameba_tools.path}/upload_dap.sh" {upload.verbose}
|
||||
tools.dapimg.upload.pattern.windows="{runtime.tools.ameba_tools.path}/upload_dap.exe" "{runtime.tools.ameba_tools.path}\ram_all.bin"{upload.verbose}
|
||||
tools.dapimg.upload.pattern.macosx="{runtime.tools.ameba_tools.path}/upload_dap_macosx" "{runtime.tools.ameba_tools.path}/ram_all.bin"{upload.verbose}
|
||||
tools.dapimg.upload.pattern.linux="{runtime.tools.ameba_tools.path}/upload_dap_linux" "{runtime.tools.ameba_tools.path}/ram_all.bin"{upload.verbose}
|
||||
tools.dapimg.upload.network_pattern="{runtime.tools.ameba_tools.path}/upload_ota.exe" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}\ota.bin"
|
||||
tools.dapimg.upload.network_pattern.windows="{runtime.tools.ameba_tools.path}/upload_ota.exe" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}\ota.bin"
|
||||
tools.dapimg.upload.network_pattern.macosx="{runtime.tools.ameba_tools.path}/upload_ota_macosx" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}/ota.bin"
|
||||
tools.dapimg.upload.network_pattern.linux="{runtime.tools.ameba_tools.path}/upload_ota_linux" -i "{serial.port}" -p "{network.port}" -f "{runtime.tools.ameba_tools.path}/ota.bin"
|
||||
Reference in New Issue
Block a user