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