RTL8710B/RTL8711AM (#1501)

* --

* test

* ota

* ameba1/rtl8711am

* workflow build

* uart tcp bridge driver

* fix build

* Static ip fix

* fix

* Rework amebaz ota

---------

Co-authored-by: Tester23 <85486843+openshwprojects@users.noreply.github.com>
This commit is contained in:
NonPIayerCharacter 2025-02-01 21:04:23 +03:00 committed by GitHub
parent 017929d189
commit 6ac1f260ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
59 changed files with 7832 additions and 111 deletions

View File

@ -107,7 +107,7 @@ jobs:
strategy:
fail-fast: false
matrix:
platform: [OpenBK7231T, OpenBK7231N, OpenXR809, OpenBL602, OpenW800, OpenW600, OpenLN882H, OpenTR6260, OpenRTL87X0C]
platform: [OpenBK7231T, OpenBK7231N, OpenXR809, OpenBL602, OpenW800, OpenW600, OpenLN882H, OpenTR6260, OpenRTL87X0C, OpenRTL8710B, OpenRTL8710A]
steps:
- name: Source checkout
uses: actions/checkout@v4

4
.gitmodules vendored
View File

@ -37,3 +37,7 @@
path = sdk/OpenRTL87X0C
url = https://github.com/NonPIayerCharacter/OpenRTL87X0C.git
branch = main
[submodule "sdk/OpenRTL8710A_B"]
path = sdk/OpenRTL8710A_B
url = https://github.com/NonPIayerCharacter/OpenRTL8710A_B.git
branch = master

View File

@ -158,6 +158,26 @@ prebuild_OpenRTL87X0C:
else echo "prebuild for OpenRTL87X0C not found ... "; \
fi
prebuild_OpenRTL8710B:
git submodule update --init --recursive sdk/OpenRTL8710A_B
@if [ -e platforms/RTL8710B/pre_build.sh ]; then \
echo "prebuild found for OpenRTL8710B"; \
sh platforms/RTL8710B/pre_build.sh; \
else echo "prebuild for OpenRTL8710B not found ... "; \
fi
@if [ -e platforms/RTL8710B/tools/amebaz_ota_combine ]; then \
echo "amebaz_ota_combine is already compiled"; \
else g++ -o platforms/RTL8710B/tools/amebaz_ota_combine platforms/RTL8710B/tools/amebaz_ota_combine.cpp --std=c++17 -lstdc++fs; \
fi
prebuild_OpenRTL8710A:
git submodule update --init --recursive sdk/OpenRTL8710A_B
@if [ -e platforms/RTL8710A/pre_build.sh ]; then \
echo "prebuild found for OpenRTL8710A"; \
sh platforms/RTL8710A/pre_build.sh; \
else echo "prebuild for OpenRTL8710A not found ... "; \
fi
# Build main binaries
OpenBK7231T: prebuild_OpenBK7231T
$(MAKE) APP_NAME=OpenBK7231T TARGET_PLATFORM=bk7231t SDK_PATH=sdk/OpenBK7231T APPS_BUILD_PATH=../bk7231t_os build-BK7231
@ -301,6 +321,22 @@ OpenRTL87X0C: prebuild_OpenRTL87X0C
mkdir -p output/$(APP_VERSION)
cp sdk/OpenRTL87X0C/project/OpenBeken/GCC-RELEASE/application_is/Debug/bin/flash_is.bin output/$(APP_VERSION)/OpenRTL87X0C_$(APP_VERSION).bin
cp sdk/OpenRTL87X0C/project/OpenBeken/GCC-RELEASE/application_is/Debug/bin/firmware_is.bin output/$(APP_VERSION)/OpenRTL87X0C_$(APP_VERSION)_ota.img
.PHONY: OpenRTL8710B
OpenRTL8710B: prebuild_OpenRTL8710B
$(MAKE) -C sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE APP_VERSION=$(APP_VERSION) -j $(shell nproc)
$(MAKE) -C sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE APP_VERSION=$(APP_VERSION) ota_idx=2
mkdir -p output/$(APP_VERSION)
cp sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE/application/Debug/bin/boot_all.bin output/$(APP_VERSION)/OpenRTL8710B_boot.bin
cp sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE/application/Debug/bin/image2_all_ota1.bin output/$(APP_VERSION)/OpenRTL8710B_$(APP_VERSION).bin
./platforms/RTL8710B/tools/amebaz_ota_combine sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE/application/Debug/bin/image2_all_ota1.bin sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE/application/Debug/bin/image2_all_ota2.bin output/$(APP_VERSION)/OpenRTL8710B_$(APP_VERSION)_ota.img
.PHONY: OpenRTL8710A
OpenRTL8710A: prebuild_OpenRTL8710A
$(MAKE) -C sdk/OpenRTL8710A_B/project/obk_ameba1/GCC-RELEASE APP_VERSION=$(APP_VERSION) -j $(shell nproc)
mkdir -p output/$(APP_VERSION)
cp sdk/OpenRTL8710A_B/project/obk_ameba1/GCC-RELEASE/application/Debug/bin/ram_all.bin output/$(APP_VERSION)/OpenRTL8710A_$(APP_VERSION).bin
cp sdk/OpenRTL8710A_B/project/obk_ameba1/GCC-RELEASE/application/Debug/bin/ota.bin output/$(APP_VERSION)/OpenRTL8710A_$(APP_VERSION)_ota.img
# clean .o files and output directory
.PHONY: clean
@ -313,6 +349,8 @@ clean:
$(MAKE) -C sdk/OpenW600 clean
$(MAKE) -C sdk/OpenTR6260/scripts tr6260s1_clean
$(MAKE) -C sdk/OpenRTL87X0C/project/OpenBeken/GCC-RELEASE clean
$(MAKE) -C sdk/OpenRTL8710A_B/project/obk_amebaz/GCC-RELEASE clean
$(MAKE) -C sdk/OpenRTL8710A_B/project/obk_ameba1/GCC-RELEASE clean
test -d ./sdk/OpenLN882H/build && cmake --build ./sdk/OpenLN882H/build --target clean
test -d ./platforms/ESP-IDF/build-32 && cmake --build ./platforms/ESP-IDF/build-32 --target clean
test -d ./platforms/ESP-IDF/build-c3 && cmake --build ./platforms/ESP-IDF/build-c3 --target clean

40
libraries/easyflash/.gitattributes vendored Normal file
View File

@ -0,0 +1,40 @@
* text=auto
*.S text
*.asm text
*.c text
*.cc text
*.cpp text
*.cxx text
*.h text
*.htm text
*.html text
*.in text
*.ld text
*.m4 text
*.mak text
*.mk text
*.py text
*.rb text
*.s text
*.sct text
*.sh text
*.txt text
*.xml text
Makefile text
AUTHORS text
COPYING text
*.LZO -text
*.Opt -text
*.Uv2 -text
*.ewp -text
*.eww -text
*.vcproj -text
*.bat -text
*.dos -text
*.icf -text
*.inf -text
*.ini -text
*.sct -text
*.xsd -text

View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2014-2020 Armink (armink.ztl@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.

View File

@ -0,0 +1,107 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2014-2019, Armink, <armink.ztl@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.
*
* Function: It is an head file for this library. You can see all be called functions.
* Created on: 2014-09-10
*/
#ifndef EASYFLASH_H_
#define EASYFLASH_H_
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <ef_cfg.h>
#include <ef_def.h>
#ifdef __cplusplus
extern "C" {
#endif
/* easyflash.c */
EfErrCode easyflash_init(void);
#ifdef EF_USING_ENV
/* only supported on ef_env.c */
size_t ef_get_env_blob(const char *key, void *value_buf, size_t buf_len, size_t *saved_value_len);
bool ef_get_env_obj(const char *key, env_node_obj_t env);
size_t ef_read_env_value(env_node_obj_t env, uint8_t *value_buf, size_t buf_len);
EfErrCode ef_set_env_blob(const char *key, const void *value_buf, size_t buf_len);
/* ef_env.c, ef_env_legacy_wl.c and ef_env_legacy.c */
EfErrCode ef_load_env(void);
void ef_print_env(void);
char *ef_get_env(const char *key);
EfErrCode ef_set_env(const char *key, const char *value);
EfErrCode ef_del_env(const char *key);
EfErrCode ef_save_env(void);
EfErrCode ef_env_set_default(void);
size_t ef_get_env_write_bytes(void);
EfErrCode ef_set_and_save_env(const char *key, const char *value);
EfErrCode ef_del_and_save_env(const char *key);
#endif
#ifdef EF_USING_IAP
/* ef_iap.c */
EfErrCode ef_erase_bak_app(size_t app_size);
EfErrCode ef_erase_user_app(uint32_t user_app_addr, size_t user_app_size);
EfErrCode ef_erase_spec_user_app(uint32_t user_app_addr, size_t app_size,
EfErrCode (*app_erase)(uint32_t addr, size_t size));
EfErrCode ef_erase_bl(uint32_t bl_addr, size_t bl_size);
EfErrCode ef_write_data_to_bak(uint8_t *data, size_t size, size_t *cur_size,
size_t total_size);
EfErrCode ef_copy_app_from_bak(uint32_t user_app_addr, size_t app_size);
EfErrCode ef_copy_spec_app_from_bak(uint32_t user_app_addr, size_t app_size,
EfErrCode (*app_write)(uint32_t addr, const uint32_t *buf, size_t size));
EfErrCode ef_copy_bl_from_bak(uint32_t bl_addr, size_t bl_size);
uint32_t ef_get_bak_app_start_addr(void);
#endif
#ifdef EF_USING_LOG
/* ef_log.c */
EfErrCode ef_log_read(size_t index, uint32_t *log, size_t size);
EfErrCode ef_log_write(const uint32_t *log, size_t size);
EfErrCode ef_log_clean(void);
size_t ef_log_get_used_size(void);
#endif
/* ef_utils.c */
uint32_t ef_calc_crc32(uint32_t crc, const void *buf, size_t size);
/* ef_port.c */
EfErrCode ef_port_read(uint32_t addr, uint32_t *buf, size_t size);
EfErrCode ef_port_erase(uint32_t addr, size_t size);
EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size);
void ef_port_env_lock(void);
void ef_port_env_unlock(void);
void ef_log_debug(const char *file, const long line, const char *format, ...);
void ef_log_info(const char *format, ...);
void ef_print(const char *format, ...);
#ifdef __cplusplus
}
#endif
#endif /* EASYFLASH_H_ */

View File

@ -0,0 +1,115 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2015-2019, Armink, <armink.ztl@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.
*
* Function: It is the configure head file for this library.
* Created on: 2015-07-14
*/
#ifndef EF_CFG_H_
#define EF_CFG_H_
#define PKG_EASYFLASH_ENV
/* using ENV function */
#ifdef PKG_EASYFLASH_ENV
#define EF_USING_ENV
#ifdef PKG_EASYFLASH_ENV_AUTO_UPDATE
/* Auto update ENV to latest default when current ENV version number is changed. */
#define EF_ENV_AUTO_UPDATE
/**
* ENV version number defined by user.
* Please change it when your firmware add a new ENV to default_env_set.
*/
#define EF_ENV_VER_NUM PKG_EASYFLASH_ENV_VER_NUM
#endif
#endif /* PKG_EASYFLASH_ENV */
/* using IAP function */
#ifdef PKG_EASYFLASH_IAP
#define EF_USING_IAP
#endif
/* using save log function */
#ifdef PKG_EASYFLASH_LOG
#define EF_USING_LOG
/* saved log area size */
#define LOG_AREA_SIZE (PKG_EASYFLASH_LOG_AREA_SIZE)
#endif
/* the minimum size of flash erasure */
#define EF_ERASE_MIN_SIZE 4096
/* the flash write granularity, unit: bit
* only support 1(nor flash)/ 8(stm32f4)/ 32(stm32f1)/ 64(stm32l4) */
#define EF_WRITE_GRAN 1
/*
*
* This all Backup Area Flash storage index. All used flash area configure is under here.
* |----------------------------| Storage Size
* | Environment variables area | ENV area size @see ENV_AREA_SIZE
* |----------------------------|
* | Saved log area | Log area size @see LOG_AREA_SIZE
* |----------------------------|
* |(IAP)Downloaded application | IAP already downloaded application, unfixed size
* |----------------------------|
*
* @note all area sizes must be aligned with EF_ERASE_MIN_SIZE
*
* The EasyFlash add the NG (Next Generation) mode start from V4.0. All old mode before V4.0, called LEGACY mode.
*
* - NG (Next Generation) mode is default mode from V4.0. It's easy to settings, only defined the ENV_AREA_SIZE.
* - The LEGACY mode has been DEPRECATED. It is NOT RECOMMENDED to continue using.
* Beacuse it will use ram to buffer the ENV and spend more flash erase times.
* If you want use it please using the V3.X version.
*/
#ifdef PLATFORM_RTL87X0C
/* backup area start address */
#define EF_START_ADDR 0x1F0000
/* ENV area size. It's at least one empty sector for GC. So it's definition must more then or equal 2 flash sector size. */
#define ENV_AREA_SIZE 0x10000 /* default is the double erase min size */
#elif PLATFORM_RTL8710B
#define EF_START_ADDR 0x195000
#define ENV_AREA_SIZE 0x8000
#elif PLATFORM_RTL8710A
#define EF_START_ADDR 0x2E3000
#define ENV_AREA_SIZE 0x1C000
#endif
/* print debug information of flash */
#ifdef PKG_EASYFLASH_DEBUG
#define PRINT_DEBUG
#endif
#endif /* EF_CFG_H_ */

View File

@ -0,0 +1,124 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2019-2020, Armink, <armink.ztl@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.
*
* Function: It is the definitions head file for this library.
* Created on: 2019-11-20
*/
#ifndef EF_DEF_H_
#define EF_DEF_H_
#ifdef __cplusplus
extern "C" {
#endif
/* EasyFlash software version number */
#define EF_SW_VERSION "4.1.0"
#define EF_SW_VERSION_NUM 0x40100
/*
* ENV version number defined by user.
* Please change it when your firmware add a new ENV to default_env_set.
*/
#ifndef EF_ENV_VER_NUM
#define EF_ENV_VER_NUM 0
#endif
/* the ENV max name length must less then it */
#ifndef EF_ENV_NAME_MAX
#define EF_ENV_NAME_MAX 32
#endif
/* EasyFlash debug print function. Must be implement by user. */
#ifdef PRINT_DEBUG
#define EF_DEBUG(...) ef_log_debug(__FILE__, __LINE__, __VA_ARGS__)
#else
#define EF_DEBUG(...)
#endif
/* EasyFlash routine print function. Must be implement by user. */
#define EF_INFO(...) ef_log_info(__VA_ARGS__)
/* EasyFlash assert for developer. */
#define EF_ASSERT(EXPR) \
if (!(EXPR)) \
{ \
EF_DEBUG("(%s) has assert failed at %s.\n", #EXPR, __FUNCTION__); \
while (1); \
}
typedef struct _ef_env {
char *key;
void *value;
size_t value_len;
} ef_env, *ef_env_t;
/* EasyFlash error code */
typedef enum {
EF_NO_ERR,
EF_ERASE_ERR,
EF_READ_ERR,
EF_WRITE_ERR,
EF_ENV_NAME_ERR,
EF_ENV_NAME_EXIST,
EF_ENV_FULL,
EF_ENV_INIT_FAILED,
} EfErrCode;
/* the flash sector current status */
typedef enum {
EF_SECTOR_EMPTY,
EF_SECTOR_USING,
EF_SECTOR_FULL,
} EfSecrorStatus;
enum env_status {
ENV_UNUSED,
ENV_PRE_WRITE,
ENV_WRITE,
ENV_PRE_DELETE,
ENV_DELETED,
ENV_ERR_HDR,
ENV_STATUS_NUM,
};
typedef enum env_status env_status_t;
struct env_node_obj {
env_status_t status; /**< ENV node status, @see node_status_t */
bool crc_is_ok; /**< ENV node CRC32 check is OK */
uint8_t name_len; /**< name length */
uint32_t magic; /**< magic word(`K`, `V`, `4`, `0`) */
uint32_t len; /**< ENV node total length (header + name + value), must align by EF_WRITE_GRAN */
uint32_t value_len; /**< value length */
char name[EF_ENV_NAME_MAX]; /**< name */
struct {
uint32_t start; /**< ENV node start address */
uint32_t value; /**< value start address */
} addr;
};
typedef struct env_node_obj *env_node_obj_t;
#ifdef __cplusplus
}
#endif
#endif /* EF_DEF_H_ */

View File

@ -0,0 +1,192 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2015, Armink, <armink.ztl@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.
*
* Function: Portable interface for SFUD flash driver.
* Created on: 2015-01-16
*/
#include <easyflash.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "FreeRTOS.h"
#include "semphr.h"
#include "queue.h"
#include "flash_api.h"
#include "device_lock.h"
flash_t flash;
/* default ENV set for user */
static const ef_env default_env_set[] =
{
{"nv_version","0.01"}
};
QueueHandle_t ef_mutex;
/**
* Flash port for hardware initialize.
*
* @param default_env default ENV set for user
* @param default_env_size default ENV size
*
* @return result
*/
EfErrCode ef_port_init(ef_env const** default_env, size_t* default_env_size)
{
EfErrCode result = EF_NO_ERR;
*default_env = default_env_set;
*default_env_size = sizeof(default_env_set) / sizeof(default_env_set[0]);
ef_mutex = xSemaphoreCreateMutex();
return result;
}
/**
* Read data from flash.
* @note This operation's units is word.
*
* @param addr flash address
* @param buf buffer to store read data
* @param size read bytes size
*
* @return result
*/
EfErrCode ef_port_read(uint32_t addr, uint32_t* buf, size_t size)
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
int res = flash_stream_read(&flash, addr, size, buf);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
if(res) return EF_NO_ERR;
else return EF_READ_ERR;
}
/**
* Erase data on flash.
* @note This operation is irreversible.
* @note This operation's units is different which on many chips.
*
* @param addr flash address
* @param size erase bytes size
*
* @return result
*/
EfErrCode ef_port_erase(uint32_t addr, size_t size)
{
EfErrCode result = EF_NO_ERR;
/* make sure the start address is a multiple of FLASH_ERASE_MIN_SIZE */
EF_ASSERT(addr % EF_ERASE_MIN_SIZE == 0);
device_mutex_lock(RT_DEV_LOCK_FLASH);
flash_erase_sector(&flash, addr);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
return result;
}
/**
* Write data to flash.
* @note This operation's units is word.
* @note This operation must after erase. @see flash_erase.
*
* @param addr flash address
* @param buf the write data buffer
* @param size write bytes size
*
* @return result
*/
EfErrCode ef_port_write(uint32_t addr, const uint32_t* buf, size_t size)
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
int res = flash_stream_write(&flash, addr, size, buf);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
if(res) return EF_NO_ERR;
else return EF_WRITE_ERR;
}
/**
* lock the ENV ram cache
*/
void ef_port_env_lock(void)
{
xSemaphoreTake(ef_mutex, 0xFFFFFFFF);
}
/**
* unlock the ENV ram cache
*/
void ef_port_env_unlock(void)
{
xSemaphoreGive(ef_mutex);
}
/**
* This function is print flash debug info.
*
* @param file the file which has call this function
* @param line the line number which has call this function
* @param format output format
* @param ... args
*
*/
void ef_log_debug(const char* file, const long line, const char* format, ...)
{
}
/**
* This function is print flash routine info.
*
* @param format output format
* @param ... args
*/
void ef_log_info(const char* format, ...)
{
va_list args;
/* args point to the first variable parameter */
va_start(args, format);
vprintf(format, args);
va_end(args);
}
/**
* This function is print flash non-package info.
*
* @param format output format
* @param ... args
*/
void ef_print(const char* format, ...)
{
va_list args;
/* args point to the first variable parameter */
va_start(args, format);
vprintf(format, args);
va_end(args);
}

View File

@ -0,0 +1,103 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2014-2019, Armink, <armink.ztl@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.
*
* Function: Initialize interface for this library.
* Created on: 2014-09-09
*/
/*
*
* This all Backup Area Flash storage index. All used flash area configure is under here.
* |----------------------------| Storage Size
* | Environment variables area | ENV area size @see ENV_AREA_SIZE
* |----------------------------|
* | Saved log area | Log area size @see LOG_AREA_SIZE
* |----------------------------|
* |(IAP)Downloaded application | IAP already downloaded application, unfixed size
* |----------------------------|
*
* @note all area sizes must be aligned with EF_ERASE_MIN_SIZE
*
* The EasyFlash add the NG (Next Generation) mode start from V4.0. All old mode before V4.0, called LEGACY mode.
*
* - NG (Next Generation) mode is default mode from V4.0. It's easy to settings, only defined the ENV_AREA_SIZE.
* - The LEGACY mode has been DEPRECATED. It is NOT RECOMMENDED to continue using.
* Beacuse it will use ram to buffer the ENV and spend more flash erase times.
* If you want use it please using the V3.X version.
*/
#include <easyflash.h>
#if !defined(EF_START_ADDR)
#error "Please configure backup area start address (in ef_cfg.h)"
#endif
#if !defined(EF_ERASE_MIN_SIZE)
#error "Please configure minimum size of flash erasure (in ef_cfg.h)"
#endif
/**
* EasyFlash system initialize.
*
* @return result
*/
EfErrCode easyflash_init(void) {
extern EfErrCode ef_port_init(ef_env const **default_env, size_t *default_env_size);
extern EfErrCode ef_env_init(ef_env const *default_env, size_t default_env_size);
extern EfErrCode ef_iap_init(void);
extern EfErrCode ef_log_init(void);
size_t default_env_set_size = 0;
const ef_env *default_env_set;
EfErrCode result = EF_NO_ERR;
result = ef_port_init(&default_env_set, &default_env_set_size);
#ifdef EF_USING_ENV
if (result == EF_NO_ERR) {
result = ef_env_init(default_env_set, default_env_set_size);
}
#endif
#ifdef EF_USING_IAP
if (result == EF_NO_ERR) {
result = ef_iap_init();
}
#endif
#ifdef EF_USING_LOG
if (result == EF_NO_ERR) {
result = ef_log_init();
}
#endif
if (result == EF_NO_ERR) {
EF_INFO("EasyFlash V%s is initialize success.\n", EF_SW_VERSION);
} else {
EF_INFO("EasyFlash V%s is initialize fail.\n", EF_SW_VERSION);
}
EF_INFO("You can get the latest version on https://github.com/armink/EasyFlash .\n");
return result;
}

View File

@ -0,0 +1,80 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2015, Armink, <armink.ztl@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.
*
* Function: RT-Thread Finsh/MSH command for EasyFlash.
* Created on: 2018-05-19
*/
#include <easyflash.h>
#include <rtthread.h>
#if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) && defined(EF_USING_ENV)
#include <finsh.h>
#if defined(EF_USING_ENV)
static void __setenv(uint8_t argc, char **argv) {
uint8_t i;
if (argc > 3) {
/* environment variable value string together */
for (i = 0; i < argc - 2; i++) {
argv[2 + i][rt_strlen(argv[2 + i])] = ' ';
}
}
if (argc == 1) {
rt_kprintf("Please input: setenv <key> [value]\n");
} else if (argc == 2) {
ef_set_env(argv[1], NULL);
} else {
ef_set_env(argv[1], argv[2]);
}
}
MSH_CMD_EXPORT_ALIAS(__setenv, setenv, Set an envrionment variable.);
static void printenv(uint8_t argc, char **argv) {
ef_print_env();
}
MSH_CMD_EXPORT(printenv, Print all envrionment variables.);
static void saveenv(uint8_t argc, char **argv) {
ef_save_env();
}
MSH_CMD_EXPORT(saveenv, Save all envrionment variables to flash.);
static void getvalue(uint8_t argc, char **argv) {
char *value = NULL;
value = ef_get_env(argv[1]);
if (value) {
rt_kprintf("The %s value is %s.\n", argv[1], value);
} else {
rt_kprintf("Can't find %s.\n", argv[1]);
}
}
MSH_CMD_EXPORT(getvalue, Get an envrionment variable by name.);
static void resetenv(uint8_t argc, char **argv) {
ef_env_set_default();
}
MSH_CMD_EXPORT(resetenv, Reset all envrionment variable to default.);
#endif /* defined(EF_USING_ENV) */
#endif /* defined(RT_USING_FINSH) && defined(FINSH_USING_MSH) */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,922 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2014-2018, Armink, <armink.ztl@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.
*
* Function: Environment variables operating interface. (normal mode)
* Created on: 2014-10-06
*/
#include <easyflash.h>
#include <string.h>
#include <stdlib.h>
#if defined(EF_USING_ENV) && defined(EF_ENV_USING_LEGACY_MODE)
#ifndef EF_ENV_USING_WL_MODE
#if defined(EF_USING_ENV) && (!defined(ENV_USER_SETTING_SIZE) || !defined(ENV_AREA_SIZE))
#error "Please configure user setting ENV size or ENV area size (in ef_cfg.h)"
#endif
/**
* ENV area has 2 sections
* 1. System section
* It storages ENV parameters. (Units: Word)
* 2. Data section
* It storages all ENV. Storage format is key=value\0.
* All ENV must be 4 bytes alignment. The remaining part must fill '\0'.
*
* @note Word = 4 Bytes in this file
* @note When using power fail safeguard mode, it has two ENV areas(Area0, Area1).
*/
/* flash ENV parameters index and size in system section */
enum {
/* data section ENV end address index in system section */
ENV_PARAM_INDEX_END_ADDR = 0,
#ifdef EF_ENV_USING_PFS_MODE
/* saved count for ENV area */
ENV_PARAM_INDEX_SAVED_COUNT,
#endif
#ifdef EF_ENV_AUTO_UPDATE
/* current version number for ENV */
ENV_PARAM_INDEX_VER_NUM,
#endif
/* data section CRC32 code index in system section */
ENV_PARAM_INDEX_DATA_CRC,
/* flash ENV parameters word size */
ENV_PARAM_WORD_SIZE,
/* flash ENV parameters byte size */
ENV_PARAM_BYTE_SIZE = ENV_PARAM_WORD_SIZE * 4,
};
/* default ENV set, must be initialized by user */
static ef_env const *default_env_set;
/* default ENV set size, must be initialized by user */
static size_t default_env_set_size = 0;
/* ENV ram cache */
static uint32_t env_cache[ENV_USER_SETTING_SIZE / 4] = { 0 };
/* ENV start address in flash */
static uint32_t env_start_addr = 0;
/* ENV ram cache has changed when ENV created, deleted and changed value. */
static bool env_cache_changed = false;
/* initialize OK flag */
static bool init_ok = false;
#ifdef EF_ENV_USING_PFS_MODE
/* current load ENV area address */
static uint32_t cur_load_area_addr = 0;
/* next save ENV area address */
static uint32_t next_save_area_addr = 0;
#endif
static uint32_t get_env_system_addr(void);
static uint32_t get_env_data_addr(void);
static uint32_t get_env_end_addr(void);
static void set_env_end_addr(uint32_t end_addr);
static EfErrCode write_env(const char *key, const char *value);
static char *find_env(const char *key);
static EfErrCode del_env(const char *key);
static size_t get_env_data_size(void);
static size_t get_env_user_used_size(void);
static EfErrCode create_env(const char *key, const char *value);
static uint32_t calc_env_crc(void);
static bool env_crc_is_ok(void);
#ifdef EF_ENV_AUTO_UPDATE
static EfErrCode env_auto_update(void);
#endif
/**
* Flash ENV initialize.
*
* @param default_env default ENV set for user
* @param default_env_size default ENV set size
*
* @note user_size must equal with total_size in normal mode
*
* @return result
*/
EfErrCode ef_env_init(ef_env const *default_env, size_t default_env_size) {
EfErrCode result = EF_NO_ERR;
EF_ASSERT(ENV_AREA_SIZE);
EF_ASSERT(ENV_USER_SETTING_SIZE);
EF_ASSERT(EF_ERASE_MIN_SIZE);
/* must be word alignment for ENV */
EF_ASSERT(ENV_USER_SETTING_SIZE % 4 == 0);
EF_ASSERT(ENV_AREA_SIZE % 4 == 0);
EF_ASSERT(default_env);
EF_ASSERT(default_env_size < ENV_USER_SETTING_SIZE);
#ifndef EF_ENV_USING_PFS_MODE
/* total_size must be aligned with erase_min_size */
if (ENV_USER_SETTING_SIZE % EF_ERASE_MIN_SIZE == 0) {
EF_ASSERT(ENV_USER_SETTING_SIZE == ENV_AREA_SIZE);
} else {
EF_ASSERT((ENV_USER_SETTING_SIZE / EF_ERASE_MIN_SIZE + 1)*EF_ERASE_MIN_SIZE == ENV_AREA_SIZE);
}
#else
/* total_size must be aligned with erase_min_size */
if (ENV_USER_SETTING_SIZE % EF_ERASE_MIN_SIZE == 0) {
/* it has double area when used power fail safeguard mode */
EF_ASSERT(2 * ENV_USER_SETTING_SIZE == ENV_AREA_SIZE);
} else {
/* it has double area when used power fail safeguard mode */
EF_ASSERT(2 * (ENV_USER_SETTING_SIZE / EF_ERASE_MIN_SIZE + 1)*EF_ERASE_MIN_SIZE == ENV_AREA_SIZE);
}
#endif
env_start_addr = EF_START_ADDR;
default_env_set = default_env;
default_env_set_size = default_env_size;
EF_DEBUG("ENV start address is 0x%08X, size is %d bytes.\n", EF_START_ADDR, ENV_AREA_SIZE);
result = ef_load_env();
#ifdef EF_ENV_AUTO_UPDATE
if (result == EF_NO_ERR) {
env_auto_update();
}
#endif
if (result == EF_NO_ERR) {
init_ok = true;
}
return result;
}
/**
* ENV set default.
*
* @return result
*/
EfErrCode ef_env_set_default(void) {
extern EfErrCode ef_env_ver_num_set_default(void);
EfErrCode result = EF_NO_ERR;
size_t i;
EF_ASSERT(default_env_set);
EF_ASSERT(default_env_set_size);
/* lock the ENV cache */
ef_port_env_lock();
/* set environment end address is at data section start address */
set_env_end_addr(get_env_data_addr());
#ifdef EF_ENV_USING_PFS_MODE
/* set saved count to default 0 */
env_cache[ENV_PARAM_INDEX_SAVED_COUNT] = 0;
#endif
#ifdef EF_ENV_AUTO_UPDATE
/* initialize version number */
env_cache[ENV_PARAM_INDEX_VER_NUM] = EF_ENV_VER_NUM;
#endif
/* create default ENV */
for (i = 0; i < default_env_set_size; i++) {
create_env(default_env_set[i].key, default_env_set[i].value);
}
/* unlock the ENV cache */
ef_port_env_unlock();
result = ef_save_env();
#ifdef EF_ENV_USING_PFS_MODE
/* reset other PFS area's data */
if (result == EF_NO_ERR) {
env_cache_changed = true;
result = ef_save_env();
}
#endif
return result;
}
/**
* Get ENV system section start address.
*
* @return system section start address
*/
static uint32_t get_env_system_addr(void) {
#ifndef EF_ENV_USING_PFS_MODE
return env_start_addr;
#else
return cur_load_area_addr;
#endif
}
/**
* Get ENV data section start address.
*
* @return data section start address
*/
static uint32_t get_env_data_addr(void) {
return get_env_system_addr() + ENV_PARAM_BYTE_SIZE;
}
/**
* Get ENV end address.
* It's the first word in ENV.
*
* @return ENV end address
*/
static uint32_t get_env_end_addr(void) {
/* it is the first word */
return env_cache[ENV_PARAM_INDEX_END_ADDR];
}
/**
* Set ENV end address.
* It's the first word in ENV.
*
* @param end_addr ENV end address
*/
static void set_env_end_addr(uint32_t end_addr) {
env_cache[ENV_PARAM_INDEX_END_ADDR] = end_addr;
}
/**
* Get current ENV data section size.
*
* @return size
*/
static size_t get_env_data_size(void) {
if (get_env_end_addr() > get_env_data_addr()) {
return get_env_end_addr() - get_env_data_addr();
} else {
return 0;
}
}
/**
* Get current user used ENV size.
*
* @return bytes
*/
static size_t get_env_user_used_size(void) {
if (get_env_end_addr() > get_env_system_addr()) {
return get_env_end_addr() - get_env_system_addr();
} else {
return 0;
}
}
/**
* Get current ENV already write bytes.
*
* @return write bytes
*/
size_t ef_get_env_write_bytes(void) {
#ifndef EF_ENV_USING_PFS_MODE
return get_env_user_used_size();
#else
return get_env_user_used_size() * 2;
#endif
}
/**
* Write an ENV at the end of cache.
*
* @param key ENV name
* @param value ENV value
*
* @return result
*/
static EfErrCode write_env(const char *key, const char *value) {
EfErrCode result = EF_NO_ERR;
size_t key_len = strlen(key), value_len = strlen(value), env_str_len;
char *env_cache_bak = (char *)env_cache;
/* calculate ENV storage length, contain '=' and '\0'. */
env_str_len = key_len + value_len + 2;
if (env_str_len % 4 != 0) {
env_str_len = (env_str_len / 4 + 1) * 4;
}
/* check capacity of ENV */
if (env_str_len + get_env_user_used_size() >= ENV_USER_SETTING_SIZE) {
return EF_ENV_FULL;
}
/* calculate current ENV ram cache end address */
env_cache_bak += get_env_user_used_size();
/* copy key name */
memcpy(env_cache_bak, key, key_len);
env_cache_bak += key_len;
/* copy equal sign */
*env_cache_bak = '=';
env_cache_bak++;
/* copy value */
memcpy(env_cache_bak, value, value_len);
env_cache_bak += value_len;
/* fill '\0' for string end sign */
*env_cache_bak = '\0';
env_cache_bak ++;
/* fill '\0' for word alignment */
memset(env_cache_bak, 0, env_str_len - (key_len + value_len + 2));
set_env_end_addr(get_env_end_addr() + env_str_len);
/* ENV ram cache has changed */
env_cache_changed = true;
return result;
}
/**
* Find ENV.
*
* @param key ENV name
*
* @return found ENV in ram cache
*/
static char *find_env(const char *key) {
char *env_start, *env_end, *env, *found_env = NULL;
size_t key_len = strlen(key), env_len;
if ((key == NULL) || *key == '\0') {
EF_INFO("Flash ENV name must be not empty!\n");
return NULL;
}
/* from data section start to data section end */
env_start = (char *) ((char *) env_cache + ENV_PARAM_BYTE_SIZE);
env_end = (char *) ((char *) env_cache + get_env_user_used_size());
/* ENV is null */
if (env_start == env_end) {
return NULL;
}
env = env_start;
while (env < env_end) {
/* the key length must be equal */
if (!strncmp(env, key, key_len) && (env[key_len] == '=')) {
found_env = env;
break;
} else {
/* calculate ENV length, contain '\0'. */
env_len = strlen(env) + 1;
/* next ENV and word alignment */
if (env_len % 4 == 0) {
env += env_len;
} else {
env += (env_len / 4 + 1) * 4;
}
}
}
return found_env;
}
/**
* If the ENV is not exist, create it.
* @see flash_write_env
*
* @param key ENV name
* @param value ENV value
*
* @return result
*/
static EfErrCode create_env(const char *key, const char *value) {
EfErrCode result = EF_NO_ERR;
EF_ASSERT(key);
EF_ASSERT(value);
if ((key == NULL) || *key == '\0') {
EF_INFO("Flash ENV name must be not empty!\n");
return EF_ENV_NAME_ERR;
}
if (strchr(key, '=')) {
EF_INFO("Flash ENV name can't contain '='.\n");
return EF_ENV_NAME_ERR;
}
/* find ENV */
if (find_env(key)) {
EF_INFO("The name of \"%s\" is already exist.\n", key);
return EF_ENV_NAME_EXIST;
}
/* write ENV at the end of cache */
result = write_env(key, value);
return result;
}
/**
* Delete an ENV in cache.
*
* @param key ENV name
*
* @return result
*/
static EfErrCode del_env(const char *key) {
EfErrCode result = EF_NO_ERR;
char *del_env = NULL;
size_t del_env_length, remain_env_length;
EF_ASSERT(key);
if ((key == NULL) || *key == '\0') {
EF_INFO("Flash ENV name must be not NULL!\n");
return EF_ENV_NAME_ERR;
}
if (strchr(key, '=')) {
EF_INFO("Flash ENV name or value can't contain '='.\n");
return EF_ENV_NAME_ERR;
}
/* find ENV */
del_env = find_env(key);
if (!del_env) {
EF_INFO("Not find \"%s\" in ENV.\n", key);
return EF_ENV_NAME_ERR;
}
del_env_length = strlen(del_env);
/* '\0' also must be as ENV length */
del_env_length ++;
/* the address must multiple of 4 */
if (del_env_length % 4 != 0) {
del_env_length = (del_env_length / 4 + 1) * 4;
}
/* calculate remain ENV length */
remain_env_length = get_env_data_size()
- (((uint32_t) del_env + del_env_length) - ((uint32_t) env_cache + ENV_PARAM_BYTE_SIZE));
/* remain ENV move forward */
memcpy(del_env, del_env + del_env_length, remain_env_length);
/* reset ENV end address */
set_env_end_addr(get_env_end_addr() - del_env_length);
/* ENV ram cache has changed */
env_cache_changed = true;
return result;
}
/**
* Set an ENV.If it value is NULL, delete it.
* If not find it in ENV table, then create it.
*
* @param key ENV name
* @param value ENV value
*
* @return result
*/
EfErrCode ef_set_env(const char *key, const char *value) {
EfErrCode result = EF_NO_ERR;
char *old_env, *old_value;
if (!init_ok) {
EF_INFO("ENV isn't initialize OK.\n");
return EF_ENV_INIT_FAILED;
}
/* lock the ENV cache */
ef_port_env_lock();
/* if ENV value is NULL, delete it */
if (value == NULL) {
result = del_env(key);
} else {
old_env = find_env(key);
/* If find this ENV, then compare the new value and old value. */
if (old_env) {
/* find the old value address */
old_env = strchr(old_env, '=');
old_value = old_env + 1;
/* If it is changed then delete it and recreate it */
if (strcmp(old_value, value)) {
result = del_env(key);
if (result == EF_NO_ERR) {
result = create_env(key, value);
}
}
} else {
result = create_env(key, value);
}
}
/* unlock the ENV cache */
ef_port_env_unlock();
return result;
}
/**
* Del an ENV.
*
* @param key ENV name
*
* @return result
*/
EfErrCode ef_del_env(const char *key) {
EfErrCode result = EF_NO_ERR;
if (!init_ok) {
EF_INFO("ENV isn't initialize OK.\n");
return EF_ENV_INIT_FAILED;
}
/* lock the ENV cache */
ef_port_env_lock();
result = del_env(key);
/* unlock the ENV cache */
ef_port_env_unlock();
return result;
}
/**
* Get an ENV value by key name.
*
* @param key ENV name
*
* @return value
*/
char *ef_get_env(const char *key) {
char *env = NULL, *value = NULL;
if (!init_ok) {
EF_INFO("ENV isn't initialize OK.\n");
return NULL;
}
/* find ENV */
env = find_env(key);
if (env == NULL) {
return NULL;
}
/* get value address */
value = strchr(env, '=');
if (value != NULL) {
/* the equal sign next character is value */
value++;
}
return value;
}
/**
* Print ENV.
*/
void ef_print_env(void) {
uint32_t *env_cache_data_addr = env_cache + ENV_PARAM_WORD_SIZE,
*env_cache_end_addr =
(uint32_t *) (env_cache + ENV_PARAM_WORD_SIZE + get_env_data_size() / 4);
uint8_t j;
char c;
if (!init_ok) {
EF_INFO("ENV isn't initialize OK.\n");
return;
}
for (; env_cache_data_addr < env_cache_end_addr; env_cache_data_addr += 1) {
for (j = 0; j < 4; j++) {
c = (*env_cache_data_addr) >> (8 * j);
ef_print("%c", c);
if (c == '\0') {
ef_print("\n");
break;
}
}
}
#ifndef EF_ENV_USING_PFS_MODE
ef_print("\nmode: normal\n");
ef_print("size: %ld/%ld bytes.\n", get_env_user_used_size(), ENV_USER_SETTING_SIZE);
#else
ef_print("\nmode: power fail safeguard\n");
ef_print("size: %ld/%ld bytes, write bytes %ld/%ld.\n", get_env_user_used_size(),
ENV_USER_SETTING_SIZE, ef_get_env_write_bytes(), ENV_AREA_SIZE);
ef_print("saved count: %ld\n", env_cache[ENV_PARAM_INDEX_SAVED_COUNT]);
#endif
#ifdef EF_ENV_AUTO_UPDATE
ef_print("ver num: %d\n", env_cache[ENV_PARAM_INDEX_VER_NUM]);
#endif
}
/**
* Load flash ENV to ram.
*
* @return result
*/
#ifndef EF_ENV_USING_PFS_MODE
EfErrCode ef_load_env(void) {
EfErrCode result = EF_NO_ERR;
uint32_t *env_cache_bak, env_end_addr;
/* read ENV end address from flash */
ef_port_read(get_env_system_addr() + ENV_PARAM_INDEX_END_ADDR * 4, &env_end_addr, 4);
/* if ENV is not initialize or flash has dirty data, set default for it */
if ((env_end_addr == 0xFFFFFFFF) || (env_end_addr < env_start_addr)
|| (env_end_addr > env_start_addr + ENV_USER_SETTING_SIZE)) {
result = ef_env_set_default();
} else {
/* set ENV end address */
set_env_end_addr(env_end_addr);
env_cache_bak = env_cache + ENV_PARAM_WORD_SIZE;
/* read all ENV from flash */
ef_port_read(get_env_data_addr(), env_cache_bak, get_env_data_size());
/* read ENV CRC code from flash */
ef_port_read(get_env_system_addr() + ENV_PARAM_INDEX_DATA_CRC * 4,
&env_cache[ENV_PARAM_INDEX_DATA_CRC] , 4);
/* if ENV CRC32 check is fault, set default for it */
if (!env_crc_is_ok()) {
EF_INFO("Warning: ENV CRC check failed. Set it to default.\n");
result = ef_env_set_default();
}
}
return result;
}
#else
EfErrCode ef_load_env(void) {
EfErrCode result = EF_NO_ERR;
uint32_t area0_start_address = env_start_addr, area1_start_address = env_start_addr
+ ENV_AREA_SIZE / 2;
uint32_t area0_end_addr, area1_end_addr, area0_crc, area1_crc, area0_saved_count, area1_saved_count;
bool area0_is_valid = true, area1_is_valid = true;
/* read ENV area end address from flash */
ef_port_read(area0_start_address + ENV_PARAM_INDEX_END_ADDR * 4, &area0_end_addr, 4);
ef_port_read(area1_start_address + ENV_PARAM_INDEX_END_ADDR * 4, &area1_end_addr, 4);
if ((area0_end_addr == 0xFFFFFFFF) || (area0_end_addr < area0_start_address)
|| (area0_end_addr > area0_start_address + ENV_USER_SETTING_SIZE)) {
area0_is_valid = false;
}
if ((area1_end_addr == 0xFFFFFFFF) || (area1_end_addr < area1_start_address)
|| (area1_end_addr > area1_start_address + ENV_USER_SETTING_SIZE)) {
area1_is_valid = false;
}
/* check area0 CRC when it is valid */
if (area0_is_valid) {
/* read ENV area0 crc32 code from flash */
ef_port_read(area0_start_address + ENV_PARAM_INDEX_DATA_CRC * 4, &area0_crc, 4);
/* read ENV from ENV area0 */
ef_port_read(area0_start_address, env_cache, area0_end_addr - area0_start_address);
/* current load ENV area address is area0 start address */
cur_load_area_addr = area0_start_address;
if (!env_crc_is_ok()) {
area0_is_valid = false;
}
}
/* check area1 CRC when it is valid */
if (area1_is_valid) {
/* read ENV area1 crc32 code from flash */
ef_port_read(area1_start_address + ENV_PARAM_INDEX_DATA_CRC * 4, &area1_crc, 4);
/* read ENV from ENV area1 */
ef_port_read(area1_start_address, env_cache, area1_end_addr - area1_start_address);
/* current load ENV area address is area1 start address */
cur_load_area_addr = area1_start_address;
if (!env_crc_is_ok()) {
area1_is_valid = false;
}
}
/* all ENV area CRC is OK then compare saved count */
if (area0_is_valid && area1_is_valid) {
/* read ENV area saved count from flash */
ef_port_read(area0_start_address + ENV_PARAM_INDEX_SAVED_COUNT * 4,
&area0_saved_count, 4);
ef_port_read(area1_start_address + ENV_PARAM_INDEX_SAVED_COUNT * 4,
&area1_saved_count, 4);
/* the bigger saved count area is valid */
if ((area0_saved_count > area1_saved_count) || ((area0_saved_count == 0) && (area1_saved_count == 0xFFFFFFFF))) {
area1_is_valid = false;
} else {
area0_is_valid = false;
}
}
if (area0_is_valid) {
/* current load ENV area address is area0 start address */
cur_load_area_addr = area0_start_address;
/* next save ENV area address is area1 start address */
next_save_area_addr = area1_start_address;
/* read all ENV from area0 */
ef_port_read(area0_start_address, env_cache, area0_end_addr - area0_start_address);
} else if (area1_is_valid) {
/* next save ENV area address is area0 start address */
next_save_area_addr = area0_start_address;
} else {
/* current load ENV area address is area1 start address */
cur_load_area_addr = area1_start_address;
/* next save ENV area address is area0 start address */
next_save_area_addr = area0_start_address;
/* set the ENV to default */
result = ef_env_set_default();
}
return result;
}
#endif
/**
* Save ENV to flash.
*/
EfErrCode ef_save_env(void) {
EfErrCode result = EF_NO_ERR;
uint32_t write_addr, write_size;
/* ENV ram cache has not changed don't need to save */
if (!env_cache_changed) {
return result;
}
#ifndef EF_ENV_USING_PFS_MODE
write_addr = get_env_system_addr();
write_size = get_env_user_used_size();
/* calculate and cache CRC32 code */
env_cache[ENV_PARAM_INDEX_DATA_CRC] = calc_env_crc();
#else
write_addr = next_save_area_addr;
write_size = get_env_user_used_size();
/* replace next_save_area_addr with cur_load_area_addr */
next_save_area_addr = cur_load_area_addr;
cur_load_area_addr = write_addr;
/* change the ENV end address to next save area address */
set_env_end_addr(write_addr + write_size);
/* ENV area saved count +1 */
env_cache[ENV_PARAM_INDEX_SAVED_COUNT]++;
/* calculate and cache CRC32 code */
env_cache[ENV_PARAM_INDEX_DATA_CRC] = calc_env_crc();
#endif
/* erase ENV */
result = ef_port_erase(write_addr, write_size);
switch (result) {
case EF_NO_ERR: {
EF_DEBUG("Erased ENV OK.\n");
break;
}
case EF_ERASE_ERR: {
EF_INFO("Error: Erased ENV fault! Start address is 0x%08X, size is %ld.\n", write_addr, write_size);
/* will return when erase fault */
return result;
}
}
/* write ENV to flash */
result = ef_port_write(write_addr, env_cache, write_size);
switch (result) {
case EF_NO_ERR: {
EF_DEBUG("Saved ENV OK.\n");
break;
}
case EF_WRITE_ERR: {
EF_INFO("Error: Saved ENV fault! Start address is 0x%08X, size is %ld.\n", write_addr, write_size);
break;
}
}
env_cache_changed = false;
return result;
}
/**
* Calculate the cached ENV CRC32 value.
*
* @return CRC32 value
*/
static uint32_t calc_env_crc(void) {
uint32_t crc32 = 0;
/* Calculate the ENV end address CRC32. The 4 is ENV end address bytes size. */
crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_INDEX_END_ADDR], 4);
#ifdef EF_ENV_USING_PFS_MODE
/* Calculate the ENV area saved count CRC32. */
crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_INDEX_SAVED_COUNT], 4);
#endif
/* Calculate the all ENV data CRC32. */
crc32 = ef_calc_crc32(crc32, &env_cache[ENV_PARAM_WORD_SIZE], get_env_data_size());
EF_DEBUG("Calculate ENV CRC32 number is 0x%08X.\n", crc32);
return crc32;
}
/**
* Check the ENV CRC32
*
* @return true is ok
*/
static bool env_crc_is_ok(void) {
if (calc_env_crc() == env_cache[ENV_PARAM_INDEX_DATA_CRC]) {
EF_DEBUG("Verify ENV CRC32 result is OK.\n");
return true;
} else {
return false;
}
}
/**
* Set and save an ENV. If set ENV is success then will save it.
*
* @param key ENV name
* @param value ENV value
*
* @return result
*/
EfErrCode ef_set_and_save_env(const char *key, const char *value) {
EfErrCode result = EF_NO_ERR;
result = ef_set_env(key, value);
if (result == EF_NO_ERR) {
result = ef_save_env();
}
return result;
}
/**
* Del and save an ENV. If del ENV is success then will save it.
*
* @param key ENV name
*
* @return result
*/
EfErrCode ef_del_and_save_env(const char *key) {
EfErrCode result = EF_NO_ERR;
result = ef_del_env(key);
if (result == EF_NO_ERR) {
result = ef_save_env();
}
return result;
}
#ifdef EF_ENV_AUTO_UPDATE
/**
* Auto update ENV to latest default when current EF_ENV_VER is changed.
*
* @return result
*/
static EfErrCode env_auto_update(void)
{
size_t i;
/* lock the ENV cache */
ef_port_env_lock();
/* read ENV version number from flash*/
ef_port_read(get_env_system_addr() + ENV_PARAM_INDEX_VER_NUM * 4,
&env_cache[ENV_PARAM_INDEX_VER_NUM] , 4);
/* check version number */
if (env_cache[ENV_PARAM_INDEX_VER_NUM] != EF_ENV_VER_NUM) {
env_cache_changed = true;
/* update version number */
env_cache[ENV_PARAM_INDEX_VER_NUM] = EF_ENV_VER_NUM;
/* add a new ENV when it's not found */
for (i = 0; i < default_env_set_size; i++) {
if (find_env(default_env_set[i].key) == NULL) {
create_env(default_env_set[i].key, default_env_set[i].value);
}
}
}
/* unlock the ENV cache */
ef_port_env_unlock();
return ef_save_env();
}
#endif /* EF_ENV_AUTO_UPDATE */
#endif /* EF_ENV_USING_WL_MODE */
#endif /* defined(EF_USING_ENV) && defined(EF_ENV_USING_LEGACY_MODE) */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,289 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2015-2017, Armink, <armink.ztl@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.
*
* Function: IAP(In-Application Programming) operating interface.
* Created on: 2015-01-05
*/
#include <easyflash.h>
#ifdef EF_USING_IAP
/* IAP section backup application section start address in flash */
static uint32_t bak_app_start_addr = 0;
/**
* Flash IAP function initialize.
*
* @return result
*/
EfErrCode ef_iap_init(void) {
EfErrCode result = EF_NO_ERR;
bak_app_start_addr = EF_START_ADDR ;
#if defined(EF_USING_ENV)
bak_app_start_addr += ENV_AREA_SIZE;
#endif
#if defined(EF_USING_LOG)
bak_app_start_addr += LOG_AREA_SIZE;
#endif
return result;
}
/**
* Erase backup area application data.
*
* @param app_size application size
*
* @return result
*/
EfErrCode ef_erase_bak_app(size_t app_size) {
EfErrCode result = EF_NO_ERR;
result = ef_port_erase(ef_get_bak_app_start_addr(), app_size);
switch (result) {
case EF_NO_ERR: {
EF_INFO("Erased backup area application OK.\n");
break;
}
case EF_ERASE_ERR: {
EF_INFO("Warning: Erase backup area application fault!\n");
/* will return when erase fault */
return result;
}
}
return result;
}
/**
* Erase user old application by using specified erase function.
*
* @param user_app_addr application entry address
* @param app_size application size
* @param app_erase user specified application erase function
*
* @return result
*/
EfErrCode ef_erase_spec_user_app(uint32_t user_app_addr, size_t app_size,
EfErrCode (*app_erase)(uint32_t addr, size_t size)) {
EfErrCode result = EF_NO_ERR;
result = app_erase(user_app_addr, app_size);
switch (result) {
case EF_NO_ERR: {
EF_INFO("Erased user application OK.\n");
break;
}
case EF_ERASE_ERR: {
EF_INFO("Warning: Erase user application fault!\n");
/* will return when erase fault */
return result;
}
}
return result;
}
/**
* Erase user old application by using default `ef_port_erase` function.
*
* @param user_app_addr application entry address
* @param app_size application size
*
* @return result
*/
EfErrCode ef_erase_user_app(uint32_t user_app_addr, size_t app_size) {
return ef_erase_spec_user_app(user_app_addr, app_size, ef_port_erase);
}
/**
* Erase old bootloader
*
* @param bl_addr bootloader entry address
* @param bl_size bootloader size
*
* @return result
*/
EfErrCode ef_erase_bl(uint32_t bl_addr, size_t bl_size) {
EfErrCode result = EF_NO_ERR;
result = ef_port_erase(bl_addr, bl_size);
switch (result) {
case EF_NO_ERR: {
EF_INFO("Erased bootloader OK.\n");
break;
}
case EF_ERASE_ERR: {
EF_INFO("Warning: Erase bootloader fault!\n");
/* will return when erase fault */
return result;
}
}
return result;
}
/**
* Write data of application to backup area.
*
* @param data a part of application
* @param size data size
* @param cur_size current write application size
* @param total_size application total size
*
* @return result
*/
EfErrCode ef_write_data_to_bak(uint8_t *data, size_t size, size_t *cur_size,
size_t total_size) {
EfErrCode result = EF_NO_ERR;
/* make sure don't write excess data */
if (*cur_size + size > total_size) {
size = total_size - *cur_size;
}
result = ef_port_write(ef_get_bak_app_start_addr() + *cur_size, (uint32_t *) data, size);
switch (result) {
case EF_NO_ERR: {
*cur_size += size;
EF_DEBUG("Write data to backup area OK.\n");
break;
}
case EF_WRITE_ERR: {
EF_INFO("Warning: Write data to backup area fault!\n");
break;
}
}
return result;
}
/**
* Copy backup area application to application entry by using specified write function.
*
* @param user_app_addr application entry address
* @param app_size application size
* @param app_write user specified application write function
*
* @return result
*/
EfErrCode ef_copy_spec_app_from_bak(uint32_t user_app_addr, size_t app_size,
EfErrCode (*app_write)(uint32_t addr, const uint32_t *buf, size_t size)) {
size_t cur_size;
uint32_t app_cur_addr, bak_cur_addr;
EfErrCode result = EF_NO_ERR;
/* 32 words size buffer */
uint32_t buff[32];
/* cycle copy data */
for (cur_size = 0; cur_size < app_size; cur_size += sizeof(buff)) {
app_cur_addr = user_app_addr + cur_size;
bak_cur_addr = ef_get_bak_app_start_addr() + cur_size;
ef_port_read(bak_cur_addr, buff, sizeof(buff));
result = app_write(app_cur_addr, buff, sizeof(buff));
if (result != EF_NO_ERR) {
break;
}
}
switch (result) {
case EF_NO_ERR: {
EF_INFO("Write data to application entry OK.\n");
break;
}
case EF_WRITE_ERR: {
EF_INFO("Warning: Write data to application entry fault!\n");
break;
}
}
return result;
}
/**
* Copy backup area application to application entry by using default `ef_port_write` function.
*
* @param user_app_addr application entry address
* @param app_size application size
*
* @return result
*/
EfErrCode ef_copy_app_from_bak(uint32_t user_app_addr, size_t app_size) {
return ef_copy_spec_app_from_bak(user_app_addr, app_size, ef_port_write);
}
/**
* Copy backup area bootloader to bootloader entry.
*
* @param bl_addr bootloader entry address
* @param bl_size bootloader size
*
* @return result
*/
EfErrCode ef_copy_bl_from_bak(uint32_t bl_addr, size_t bl_size) {
size_t cur_size;
uint32_t bl_cur_addr, bak_cur_addr;
EfErrCode result = EF_NO_ERR;
/* 32 words buffer */
uint32_t buff[32];
/* cycle copy data by 32bytes buffer */
for (cur_size = 0; cur_size < bl_size; cur_size += sizeof(buff)) {
bl_cur_addr = bl_addr + cur_size;
bak_cur_addr = ef_get_bak_app_start_addr() + cur_size;
ef_port_read(bak_cur_addr, buff, sizeof(buff));
result = ef_port_write(bl_cur_addr, buff, sizeof(buff));
if (result != EF_NO_ERR) {
break;
}
}
switch (result) {
case EF_NO_ERR: {
EF_INFO("Write data to bootloader entry OK.\n");
break;
}
case EF_WRITE_ERR: {
EF_INFO("Warning: Write data to bootloader entry fault!\n");
break;
}
}
return result;
}
/**
* Get IAP section start address in flash.
*
* @return size
*/
uint32_t ef_get_bak_app_start_addr(void) {
return bak_app_start_addr;
}
#endif /* EF_USING_IAP */

View File

@ -0,0 +1,731 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2015-2019, Armink, <armink.ztl@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.
*
* Function: Save logs to flash.
* Created on: 2015-06-04
*/
#include <easyflash.h>
#ifdef EF_USING_LOG
#if defined(EF_USING_LOG) && !defined(LOG_AREA_SIZE)
#error "Please configure log area size (in ef_cfg.h)"
#endif
/* magic code on every sector header. 'EF' is 0xEF30EF30 */
#define LOG_SECTOR_MAGIC 0xEF30EF30
/* sector header size, includes the sector magic code and status magic code */
#define LOG_SECTOR_HEADER_SIZE 12
/* sector header word size,what is equivalent to the total number of sectors header index */
#define LOG_SECTOR_HEADER_WORD_SIZE 3
/**
* Sector status magic code
* The sector status is 8B after LOG_SECTOR_MAGIC at every sector header.
* ==============================================
* | header(12B) | status |
* ----------------------------------------------
* | 0xEF30EF30 0xFFFFFFFF 0xFFFFFFFF | empty |
* | 0xEF30EF30 0xFEFEFEFE 0xFFFFFFFF | using |
* | 0xEF30EF30 0xFEFEFEFE 0xFCFCFCFC | full |
* ==============================================
*
* State transition relationship: empty->using->full
* The FULL status will change to EMPTY after sector clean.
*/
#define SECTOR_STATUS_MAGIC_EMPUT 0xFFFFFFFF
#define SECTOR_STATUS_MAGIC_USING 0xFEFEFEFE
#define SECTOR_STATUS_MAGIC_FULL 0xFCFCFCFC
typedef enum {
SECTOR_STATUS_EMPUT,
SECTOR_STATUS_USING,
SECTOR_STATUS_FULL,
SECTOR_STATUS_HEADER_ERROR,
} SectorStatus;
typedef enum {
SECTOR_HEADER_MAGIC_INDEX,
SECTOR_HEADER_USING_INDEX,
SECTOR_HEADER_FULL_INDEX,
} SectorHeaderIndex;
/* the stored logs start address and end address. It's like a ring buffer implemented on flash. */
static uint32_t log_start_addr = 0, log_end_addr = 0;
/* saved log area address for flash */
static uint32_t log_area_start_addr = 0;
/* initialize OK flag */
static bool init_ok = false;
static void find_start_and_end_addr(void);
static uint32_t get_next_flash_sec_addr(uint32_t cur_addr);
/**
* The flash save log function initialize.
*
* @return result
*/
EfErrCode ef_log_init(void) {
EfErrCode result = EF_NO_ERR;
EF_ASSERT(LOG_AREA_SIZE);
EF_ASSERT(EF_ERASE_MIN_SIZE);
/* the log area size must be an integral multiple of erase minimum size. */
EF_ASSERT(LOG_AREA_SIZE % EF_ERASE_MIN_SIZE == 0);
/* the log area size must be more than twice of EF_ERASE_MIN_SIZE */
EF_ASSERT(LOG_AREA_SIZE / EF_ERASE_MIN_SIZE >= 2);
#ifdef EF_USING_ENV
log_area_start_addr = EF_START_ADDR + ENV_AREA_SIZE;
#else
log_area_start_addr = EF_START_ADDR;
#endif
/* find the log store start address and end address */
find_start_and_end_addr();
/* initialize OK */
init_ok = true;
return result;
}
/**
* Get flash sector current status.
*
* @param addr sector address, this function will auto calculate the sector header address by this address.
*
* @return the flash sector current status
*/
static SectorStatus get_sector_status(uint32_t addr) {
uint32_t header_buf[LOG_SECTOR_HEADER_WORD_SIZE] = {0}, header_addr = 0;
uint32_t sector_header_magic = 0;
uint32_t status_full_magic = 0, status_use_magic = 0;
/* calculate the sector header address */
header_addr = addr & (~(EF_ERASE_MIN_SIZE - 1));
if (ef_port_read(header_addr, header_buf, sizeof(header_buf)) == EF_NO_ERR) {
sector_header_magic = header_buf[SECTOR_HEADER_MAGIC_INDEX];
status_use_magic = header_buf[SECTOR_HEADER_USING_INDEX];
status_full_magic = header_buf[SECTOR_HEADER_FULL_INDEX];
} else {
EF_DEBUG("Error: Read sector header data error.\n");
return SECTOR_STATUS_HEADER_ERROR;
}
/* compare header magic code */
if(sector_header_magic == LOG_SECTOR_MAGIC){
if((status_use_magic == SECTOR_STATUS_MAGIC_EMPUT) && (status_full_magic == SECTOR_STATUS_MAGIC_EMPUT)) {
return SECTOR_STATUS_EMPUT;
} else if((status_use_magic == SECTOR_STATUS_MAGIC_USING) && (status_full_magic == SECTOR_STATUS_MAGIC_EMPUT)) {
return SECTOR_STATUS_USING;
} else if((status_use_magic == SECTOR_STATUS_MAGIC_USING) && (status_full_magic == SECTOR_STATUS_MAGIC_FULL)) {
return SECTOR_STATUS_FULL;
} else {
return SECTOR_STATUS_HEADER_ERROR;
}
} else {
return SECTOR_STATUS_HEADER_ERROR;
}
}
/**
* Write flash sector current status.
*
* @param addr sector address, this function will auto calculate the sector header address by this address.
* @param status sector cur status
*
* @return result
*/
static EfErrCode write_sector_status(uint32_t addr, SectorStatus status) {
uint32_t header, header_addr = 0;
/* calculate the sector header address */
header_addr = addr & (~(EF_ERASE_MIN_SIZE - 1));
/* calculate the sector staus magic */
switch (status) {
case SECTOR_STATUS_EMPUT: {
header = LOG_SECTOR_MAGIC;
return ef_port_write(header_addr, &header, sizeof(header));
}
case SECTOR_STATUS_USING: {
header = SECTOR_STATUS_MAGIC_USING;
return ef_port_write(header_addr + sizeof(header), &header, sizeof(header));
}
case SECTOR_STATUS_FULL: {
header = SECTOR_STATUS_MAGIC_FULL;
return ef_port_write(header_addr + sizeof(header) * 2, &header, sizeof(header));
}
default:
return EF_WRITE_ERR;
}
}
/**
* Find the current flash sector using end address by continuous 0xFF.
*
* @param addr sector address
*
* @return current flash sector using end address
*/
static uint32_t find_sec_using_end_addr(uint32_t addr) {
/* read section data buffer size */
#define READ_BUF_SIZE 32
uint32_t sector_start = addr, data_start = addr, continue_ff = 0, read_buf_size = 0, i;
uint8_t buf[READ_BUF_SIZE];
EF_ASSERT(READ_BUF_SIZE % 4 == 0);
/* calculate the sector start and data start address */
sector_start = addr & (~(EF_ERASE_MIN_SIZE - 1));
data_start = sector_start + LOG_SECTOR_HEADER_SIZE;
/* counts continuous 0xFF which is end of sector */
while (data_start < sector_start + EF_ERASE_MIN_SIZE) {
if (data_start + READ_BUF_SIZE < sector_start + EF_ERASE_MIN_SIZE) {
read_buf_size = READ_BUF_SIZE;
} else {
read_buf_size = sector_start + EF_ERASE_MIN_SIZE - data_start;
}
ef_port_read(data_start, (uint32_t *)buf, read_buf_size);
for (i = 0; i < read_buf_size; i++) {
if (buf[i] == 0xFF) {
continue_ff++;
} else {
continue_ff = 0;
}
}
data_start += read_buf_size;
}
/* calculate current flash sector using end address */
if (continue_ff >= EF_ERASE_MIN_SIZE - LOG_SECTOR_HEADER_SIZE) {
/* from 0 to sec_size all sector is 0xFF, so the sector is empty */
return sector_start + LOG_SECTOR_HEADER_SIZE;
} else if (continue_ff >= 4) {
/* form end_addr - 4 to sec_size length all area is 0xFF, so it's used part of the sector.
* the address must be word alignment. */
if (continue_ff % 4 != 0) {
continue_ff = (continue_ff / 4 + 1) * 4;
}
return sector_start + EF_ERASE_MIN_SIZE - continue_ff;
} else {
/* all sector not has continuous 0xFF, so the sector is full */
return sector_start + EF_ERASE_MIN_SIZE;
}
}
/**
* Find the log store start address and end address.
* It's like a ring buffer implemented on flash.
* The flash log area can be in two states depending on start address and end address:
* state 1 state 2
* |============| |============|
* log area start--> |############| <-- start address |############| <-- end address
* |############| | empty |
* |------------| |------------|
* |############| |############| <-- start address
* |############| |############|
* |------------| |------------|
* | . | | . |
* | . | | . |
* | . | | . |
* |------------| |------------|
* |############| <-- end address |############|
* | empty | |############|
* log area end --> |============| |============|
*
* LOG_AREA_SIZE = log area end - log area star
*
*/
static void find_start_and_end_addr(void) {
size_t cur_size = 0;
SectorStatus cur_sec_status, last_sec_status;
uint32_t cur_using_sec_addr = 0;
/* all status sector counts */
size_t empty_sec_counts = 0, using_sec_counts = 0, full_sector_counts = 0;
/* total sector number */
size_t total_sec_num = LOG_AREA_SIZE / EF_ERASE_MIN_SIZE;
/* see comment of find_start_and_end_addr function */
uint8_t cur_log_sec_state = 0;
/* get the first sector status */
cur_sec_status = get_sector_status(log_area_start_addr);
last_sec_status = cur_sec_status;
for (cur_size = EF_ERASE_MIN_SIZE; cur_size < LOG_AREA_SIZE; cur_size += EF_ERASE_MIN_SIZE) {
/* get current sector status */
cur_sec_status = get_sector_status(log_area_start_addr + cur_size);
/* compare last and current status */
switch (last_sec_status) {
case SECTOR_STATUS_EMPUT: {
switch (cur_sec_status) {
case SECTOR_STATUS_EMPUT:
break;
case SECTOR_STATUS_USING:
EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
ef_log_clean();
return;
case SECTOR_STATUS_FULL:
EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
ef_log_clean();
return;
}
empty_sec_counts++;
break;
}
case SECTOR_STATUS_USING: {
switch (cur_sec_status) {
case SECTOR_STATUS_EMPUT:
/* like state 1 */
cur_log_sec_state = 1;
log_start_addr = log_area_start_addr;
cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
break;
case SECTOR_STATUS_USING:
EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
ef_log_clean();
return;
case SECTOR_STATUS_FULL:
/* like state 2 */
cur_log_sec_state = 2;
log_start_addr = log_area_start_addr + cur_size;
cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
break;
}
using_sec_counts++;
break;
}
case SECTOR_STATUS_FULL: {
switch (cur_sec_status) {
case SECTOR_STATUS_EMPUT:
/* like state 1 */
if (cur_log_sec_state == 2) {
EF_DEBUG("Error: Log area error! Now will clean all log area.\n");
ef_log_clean();
return;
} else {
cur_log_sec_state = 1;
log_start_addr = log_area_start_addr;
log_end_addr = log_area_start_addr + cur_size;
cur_using_sec_addr = log_area_start_addr + cur_size - EF_ERASE_MIN_SIZE;
}
break;
case SECTOR_STATUS_USING:
if(total_sec_num <= 2) {
/* like state 1 */
cur_log_sec_state = 1;
log_start_addr = log_area_start_addr;
cur_using_sec_addr = log_area_start_addr + cur_size;
} else {
/* like state 2 when the sector is the last one */
if (cur_size + EF_ERASE_MIN_SIZE >= LOG_AREA_SIZE) {
cur_log_sec_state = 2;
log_start_addr = get_next_flash_sec_addr(log_area_start_addr + cur_size);
cur_using_sec_addr = log_area_start_addr + cur_size;
}
}
break;
case SECTOR_STATUS_FULL:
break;
}
full_sector_counts++;
break;
}
case SECTOR_STATUS_HEADER_ERROR:
EF_DEBUG("Error: Log sector header error! Now will clean all log area.\n");
ef_log_clean();
return;
}
last_sec_status = cur_sec_status;
}
/* the last sector status counts */
if (cur_sec_status == SECTOR_STATUS_EMPUT) {
empty_sec_counts++;
} else if (cur_sec_status == SECTOR_STATUS_USING) {
using_sec_counts++;
} else if (cur_sec_status == SECTOR_STATUS_FULL) {
full_sector_counts++;
} else if (cur_sec_status == SECTOR_STATUS_HEADER_ERROR) {
EF_DEBUG("Error: Log sector header error! Now will clean all log area.\n");
ef_log_clean();
return;
}
if (using_sec_counts != 1) {
/* this state is almost impossible */
EF_DEBUG("Error: There must be only one sector status is USING! Now will clean all log area.\n");
ef_log_clean();
} else {
/* find the end address */
log_end_addr = find_sec_using_end_addr(cur_using_sec_addr);
}
}
/**
* Get log used flash total size.
*
* @return log used flash total size. @note NOT contain sector headers
*/
size_t ef_log_get_used_size(void) {
size_t header_total_num = 0, physical_size = 0;
/* must be call this function after initialize OK */
if (!init_ok) {
return 0;
}
if (log_start_addr < log_end_addr) {
physical_size = log_end_addr - log_start_addr;
} else {
physical_size = LOG_AREA_SIZE - (log_start_addr - log_end_addr);
}
header_total_num = physical_size / EF_ERASE_MIN_SIZE + 1;
return physical_size - header_total_num * LOG_SECTOR_HEADER_SIZE;
}
/**
* Sequential reading log data. It will ignore sector headers.
*
* @param addr address
* @param log log buffer
* @param size log size, not contain sector headers.
*
* @return result
*/
static EfErrCode log_seq_read(uint32_t addr, uint32_t *log, size_t size) {
EfErrCode result = EF_NO_ERR;
size_t read_size = 0, read_size_temp = 0;
while (size) {
/* move to sector data address */
if ((addr + read_size) % EF_ERASE_MIN_SIZE == 0) {
addr += LOG_SECTOR_HEADER_SIZE;
}
/* calculate current sector last data size */
read_size_temp = EF_ERASE_MIN_SIZE - (addr % EF_ERASE_MIN_SIZE);
if (size < read_size_temp) {
read_size_temp = size;
}
result = ef_port_read(addr + read_size, log + read_size / 4, read_size_temp);
if (result != EF_NO_ERR) {
return result;
}
read_size += read_size_temp;
size -= read_size_temp;
}
return result;
}
/**
* Calculate flash physical address by log index.
*
* @param index log index
*
* @return flash physical address
*/
static uint32_t log_index2addr(size_t index) {
size_t header_total_offset = 0;
/* total include sector number */
size_t sector_num = index / (EF_ERASE_MIN_SIZE - LOG_SECTOR_HEADER_SIZE) + 1;
header_total_offset = sector_num * LOG_SECTOR_HEADER_SIZE;
if (log_start_addr < log_end_addr) {
return log_start_addr + index + header_total_offset;
} else {
if (log_start_addr + index + header_total_offset < log_area_start_addr + LOG_AREA_SIZE) {
return log_start_addr + index + header_total_offset;
} else {
return log_start_addr + index + header_total_offset - LOG_AREA_SIZE;
}
}
}
/**
* Read log from flash.
*
* @param index index for saved log.
* Minimum index is 0.
* Maximum index is ef_log_get_used_size() - 1.
* @param log the log which will read from flash
* @param size read bytes size
*
* @return result
*/
EfErrCode ef_log_read(size_t index, uint32_t *log, size_t size) {
EfErrCode result = EF_NO_ERR;
size_t cur_using_size = ef_log_get_used_size();
size_t read_size_temp = 0;
size_t header_total_num = 0;
if (!size) {
return result;
}
EF_ASSERT(size % 4 == 0);
EF_ASSERT(index < cur_using_size);
if (index + size > cur_using_size) {
EF_DEBUG("Warning: Log read size out of bound. Cut read size.\n");
size = cur_using_size - index;
}
/* must be call this function after initialize OK */
if (!init_ok) {
return EF_ENV_INIT_FAILED;
}
if (log_start_addr < log_end_addr) {
log_seq_read(log_index2addr(index), log, size);
} else {
if (log_index2addr(index) + size <= log_area_start_addr + LOG_AREA_SIZE) {
/* Flash log area
* |--------------|
* log_area_start_addr --> |##############|
* |##############|
* |##############|
* |--------------|
* |##############|
* |##############|
* |##############| <-- log_end_addr
* |--------------|
* log_start_addr --> |##############|
* read start --> |**************| <-- read end
* |##############|
* |--------------|
*
* read from (log_start_addr + log_index2addr(index)) to (log_start_addr + index + log_index2addr(index))
*/
result = log_seq_read(log_index2addr(index), log, size);
} else if (log_index2addr(index) < log_area_start_addr + LOG_AREA_SIZE) {
/* Flash log area
* |--------------|
* log_area_start_addr --> |**************| <-- read end
* |##############|
* |##############|
* |--------------|
* |##############|
* |##############|
* |##############| <-- log_end_addr
* |--------------|
* log_start_addr --> |##############|
* read start --> |**************|
* |**************|
* |--------------|
* read will by 2 steps
* step1: read from (log_start_addr + log_index2addr(index)) to flash log area end address
* step2: read from flash log area start address to read size's end address
*/
read_size_temp = (log_area_start_addr + LOG_AREA_SIZE) - log_index2addr(index);
header_total_num = read_size_temp / EF_ERASE_MIN_SIZE;
/* Minus some ignored bytes */
read_size_temp -= header_total_num * LOG_SECTOR_HEADER_SIZE;
result = log_seq_read(log_index2addr(index), log, read_size_temp);
if (result == EF_NO_ERR) {
result = log_seq_read(log_area_start_addr, log + read_size_temp / 4, size - read_size_temp);
}
} else {
/* Flash log area
* |--------------|
* log_area_start_addr --> |##############|
* read start --> |**************|
* |**************| <-- read end
* |--------------|
* |##############|
* |##############|
* |##############| <-- log_end_addr
* |--------------|
* log_start_addr --> |##############|
* |##############|
* |##############|
* |--------------|
* read from (log_start_addr + log_index2addr(index) - LOG_AREA_SIZE) to read size's end address
*/
result = log_seq_read(log_index2addr(index) - LOG_AREA_SIZE, log, size);
}
}
return result;
}
/**
* Write log to flash.
*
* @param log the log which will be write to flash
* @param size write bytes size
*
* @return result
*/
EfErrCode ef_log_write(const uint32_t *log, size_t size) {
EfErrCode result = EF_NO_ERR;
size_t write_size = 0, writable_size = 0;
uint32_t write_addr = log_end_addr, erase_addr;
SectorStatus sector_status;
EF_ASSERT(size % 4 == 0);
/* must be call this function after initialize OK */
if (!init_ok) {
return EF_ENV_INIT_FAILED;
}
if ((sector_status = get_sector_status(write_addr)) == SECTOR_STATUS_HEADER_ERROR) {
return EF_WRITE_ERR;
}
/* write some log when current sector status is USING and EMPTY */
if ((sector_status == SECTOR_STATUS_USING) || (sector_status == SECTOR_STATUS_EMPUT)) {
/* write the already erased but not used area */
writable_size = EF_ERASE_MIN_SIZE - ((write_addr - log_area_start_addr) % EF_ERASE_MIN_SIZE);
if (size >= writable_size) {
result = ef_port_write(write_addr, log, writable_size);
if (result != EF_NO_ERR) {
goto exit;
}
/* change the current sector status to FULL */
result = write_sector_status(write_addr, SECTOR_STATUS_FULL);
if (result != EF_NO_ERR) {
goto exit;
}
write_size += writable_size;
} else {
result = ef_port_write(write_addr, log, size);
log_end_addr = write_addr + size;
goto exit;
}
}
/* erase and write remain log */
while (true) {
/* calculate next available sector address */
erase_addr = write_addr = get_next_flash_sec_addr(write_addr - 4);
/* move the flash log start address to next available sector address */
if (log_start_addr == erase_addr) {
log_start_addr = get_next_flash_sec_addr(log_start_addr);
}
/* erase sector */
result = ef_port_erase(erase_addr, EF_ERASE_MIN_SIZE);
if (result != EF_NO_ERR) {
goto exit;
}
/* change the sector status to EMPTY and USING when write begin sector start address */
result = write_sector_status(write_addr, SECTOR_STATUS_EMPUT);
result = write_sector_status(write_addr, SECTOR_STATUS_USING);
if (result == EF_NO_ERR) {
write_addr += LOG_SECTOR_HEADER_SIZE;
} else {
goto exit;
}
/* calculate current sector writable data size */
writable_size = EF_ERASE_MIN_SIZE - LOG_SECTOR_HEADER_SIZE;
if (size - write_size >= writable_size) {
result = ef_port_write(write_addr, log + write_size / 4, writable_size);
if (result != EF_NO_ERR) {
goto exit;
}
/* change the current sector status to FULL */
result = write_sector_status(write_addr, SECTOR_STATUS_FULL);
if (result != EF_NO_ERR) {
goto exit;
}
log_end_addr = write_addr + writable_size;
write_size += writable_size;
write_addr += writable_size;
} else {
result = ef_port_write(write_addr, log + write_size / 4, size - write_size);
if (result != EF_NO_ERR) {
goto exit;
}
log_end_addr = write_addr + (size - write_size);
break;
}
}
exit:
return result;
}
/**
* Get next flash sector address.The log total sector like ring buffer which implement by flash.
*
* @param cur_addr cur flash address
*
* @return next flash sector address
*/
static uint32_t get_next_flash_sec_addr(uint32_t cur_addr) {
size_t cur_sec_id = (cur_addr - log_area_start_addr) / EF_ERASE_MIN_SIZE;
size_t sec_total_num = LOG_AREA_SIZE / EF_ERASE_MIN_SIZE;
if (cur_sec_id + 1 >= sec_total_num) {
/* return to ring head */
return log_area_start_addr;
} else {
return log_area_start_addr + (cur_sec_id + 1) * EF_ERASE_MIN_SIZE;
}
}
/**
* Clean all log which in flash.
*
* @return result
*/
EfErrCode ef_log_clean(void) {
EfErrCode result = EF_NO_ERR;
uint32_t write_addr = log_area_start_addr;
/* clean address */
log_start_addr = log_area_start_addr;
log_end_addr = log_start_addr + LOG_SECTOR_HEADER_SIZE;
/* erase log flash area */
result = ef_port_erase(log_area_start_addr, LOG_AREA_SIZE);
if (result != EF_NO_ERR) {
goto exit;
}
/* setting first sector is EMPTY to USING */
write_sector_status(write_addr, SECTOR_STATUS_EMPUT);
write_sector_status(write_addr, SECTOR_STATUS_USING);
if (result != EF_NO_ERR) {
goto exit;
}
write_addr += EF_ERASE_MIN_SIZE;
/* add sector header */
while (true) {
write_sector_status(write_addr, SECTOR_STATUS_EMPUT);
if (result != EF_NO_ERR) {
goto exit;
}
write_addr += EF_ERASE_MIN_SIZE;
if (write_addr >= log_area_start_addr + LOG_AREA_SIZE) {
break;
}
}
exit:
return result;
}
#endif /* EF_USING_LOG */

View File

@ -0,0 +1,99 @@
/*
* This file is part of the EasyFlash Library.
*
* Copyright (c) 2015-2017, Armink, <armink.ztl@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.
*
* Function: Some utils for this library.
* Created on: 2015-01-14
*/
#include <easyflash.h>
static const uint32_t crc32_table[] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
/**
* Calculate the CRC32 value of a memory buffer.
*
* @param crc accumulated CRC32 value, must be 0 on first call
* @param buf buffer to calculate CRC32 value for
* @param size bytes in buffer
*
* @return calculated CRC32 value
*/
uint32_t ef_calc_crc32(uint32_t crc, const void *buf, size_t size)
{
const uint8_t *p;
p = (const uint8_t *)buf;
crc = crc ^ ~0U;
while (size--) {
crc = crc32_table[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^ ~0U;
}

View File

@ -0,0 +1,156 @@
OBK_DIR = ../../../../..
CFLAGS += -DPLATFORM_RTL8710A -DPLATFORM_REALTEK -DUSER_SW_VER='"$(APP_VERSION)"'
INCLUDES += -I$(OBK_DIR)/libraries/easyflash/inc
SRC_C += $(OBK_DIR)/platforms/RTL8710A/main.c
SRC_C += $(OBK_DIR)/platforms/RTL8710A/stdlib.c
SRC_C += $(OBK_DIR)/src/base64/base64.c
SRC_C += $(OBK_DIR)/src/bitmessage/bitmessage_read.c
SRC_C += $(OBK_DIR)/src/bitmessage/bitmessage_write.c
SRC_C += $(OBK_DIR)/src/cJSON/cJSON.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_channels.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_eventHandlers.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_if.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_main.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_newLEDDriver_colors.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_newLEDDriver.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_repeatingEvents.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_script.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_simulatorOnly.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_tasmota.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_tcp.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_test.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_tokenizer.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_read.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_util.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_write.c
SRC_C += $(OBK_DIR)/src/driver/drv_main.c
#SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710a/hal_adc_rtl8710a.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710a/hal_generic_rtl8710a.c
#SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710a/hal_main_rtl8710a.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710a/hal_uart_rtl8710a.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710a/hal_pins_rtl8710a.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_flashConfig_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_flashVars_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_pins_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_wifi_realtek.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_adc_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_flashConfig_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_flashVars_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_main_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_pins_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_wifi_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_uart_generic.c
SRC_C += $(OBK_DIR)/src/httpserver/hass.c
SRC_C += $(OBK_DIR)/src/httpserver/http_basic_auth.c
SRC_C += $(OBK_DIR)/src/httpserver/http_fns.c
SRC_C += $(OBK_DIR)/src/httpserver/http_tcp_server.c
SRC_C += $(OBK_DIR)/src/httpserver/new_tcp_server.c
SRC_C += $(OBK_DIR)/src/httpserver/json_interface.c
SRC_C += $(OBK_DIR)/src/httpserver/new_http.c
SRC_C += $(OBK_DIR)/src/httpserver/rest_interface.c
SRC_C += $(OBK_DIR)/src/mqtt/new_mqtt_deduper.c
SRC_C += $(OBK_DIR)/src/jsmn/jsmn.c
SRC_C += $(OBK_DIR)/src/logging/logging.c
SRC_C += $(OBK_DIR)/src/mqtt/new_mqtt.c
SRC_C += $(OBK_DIR)/src/new_cfg.c
SRC_C += $(OBK_DIR)/src/new_common.c
SRC_C += $(OBK_DIR)/src/new_ping.c
SRC_C += $(OBK_DIR)/src/new_pins.c
SRC_C += $(OBK_DIR)/src/rgb2hsv.c
SRC_C += $(OBK_DIR)/src/tiny_crc8.c
SRC_C += $(OBK_DIR)/src/user_main.c
#SRC_C += $(OBK_DIR)/src/cmnds/cmd_send.c
SRC_C += $(OBK_DIR)/src/driver/drv_adcButton.c
SRC_C += $(OBK_DIR)/src/driver/drv_adcSmoother.c
SRC_C += $(OBK_DIR)/src/driver/drv_aht2x.c
SRC_C += $(OBK_DIR)/src/driver/drv_battery.c
SRC_C += $(OBK_DIR)/src/driver/drv_bl_shared.c
SRC_C += $(OBK_DIR)/src/driver/drv_bl0937.c
SRC_C += $(OBK_DIR)/src/driver/drv_bl0942.c
#SRC_C += $(OBK_DIR)/src/driver/drv_bmp280.c
SRC_C += $(OBK_DIR)/src/driver/drv_bmpi2c.c
SRC_C += $(OBK_DIR)/src/driver/drv_bp1658cj.c
SRC_C += $(OBK_DIR)/src/driver/drv_bp5758d.c
SRC_C += $(OBK_DIR)/src/driver/drv_bridge_driver.c
SRC_C += $(OBK_DIR)/src/driver/drv_chargingLimit.c
SRC_C += $(OBK_DIR)/src/driver/drv_charts.c
SRC_C += $(OBK_DIR)/src/driver/drv_cht8305.c
SRC_C += $(OBK_DIR)/src/driver/drv_cse7766.c
SRC_C += $(OBK_DIR)/src/driver/drv_ddp.c
SRC_C += $(OBK_DIR)/src/driver/drv_debouncer.c
SRC_C += $(OBK_DIR)/src/driver/drv_dht_internal.c
SRC_C += $(OBK_DIR)/src/driver/drv_dht.c
SRC_C += $(OBK_DIR)/src/driver/drv_doorSensorWithDeepSleep.c
SRC_C += $(OBK_DIR)/src/driver/drv_gn6932.c
SRC_C += $(OBK_DIR)/src/driver/drv_hd2015.c
SRC_C += $(OBK_DIR)/src/driver/drv_ht16k33.c
SRC_C += $(OBK_DIR)/src/driver/drv_httpButtons.c
SRC_C += $(OBK_DIR)/src/driver/drv_hue.c
SRC_C += $(OBK_DIR)/src/driver/drv_kp18058.c
SRC_C += $(OBK_DIR)/src/driver/drv_kp18068.c
SRC_C += $(OBK_DIR)/src/driver/drv_max72xx_clock.c
SRC_C += $(OBK_DIR)/src/driver/drv_max72xx_internal.c
SRC_C += $(OBK_DIR)/src/driver/drv_max72xx_single.c
SRC_C += $(OBK_DIR)/src/driver/drv_mcp9808.c
SRC_C += $(OBK_DIR)/src/driver/drv_ntp_events.c
SRC_C += $(OBK_DIR)/src/driver/drv_ntp.c
SRC_C += $(OBK_DIR)/src/driver/drv_pt6523.c
SRC_C += $(OBK_DIR)/src/driver/drv_pwm_groups.c
SRC_C += $(OBK_DIR)/src/driver/drv_pwmToggler.c
SRC_C += $(OBK_DIR)/src/driver/drv_pwrCal.c
SRC_C += $(OBK_DIR)/src/driver/drv_rn8209.c
SRC_C += $(OBK_DIR)/src/driver/drv_sgp.c
SRC_C += $(OBK_DIR)/src/driver/drv_shiftRegister.c
SRC_C += $(OBK_DIR)/src/driver/drv_sht3x.c
#SRC_C += $(OBK_DIR)/src/driver/drv_sm15155e.c
#SRC_C += $(OBK_DIR)/src/driver/drv_sm16703P.c
SRC_C += $(OBK_DIR)/src/driver/drv_sm2135.c
SRC_C += $(OBK_DIR)/src/driver/drv_sm2235.c
SRC_C += $(OBK_DIR)/src/driver/drv_soft_i2c.c
#SRC_C += $(OBK_DIR)/src/driver/drv_soft_spi.c
#SRC_C += $(OBK_DIR)/src/driver/drv_spi_flash.c
#SRC_C += $(OBK_DIR)/src/driver/drv_spi.c
#SRC_C += $(OBK_DIR)/src/driver/drv_spidma.c
SRC_C += $(OBK_DIR)/src/driver/drv_ssdp.c
SRC_C += $(OBK_DIR)/src/driver/drv_tasmotaDeviceGroups.c
SRC_C += $(OBK_DIR)/src/driver/drv_test_drivers.c
SRC_C += $(OBK_DIR)/src/driver/drv_textScroller.c
SRC_C += $(OBK_DIR)/src/driver/drv_tm_gn_display_shared.c
SRC_C += $(OBK_DIR)/src/driver/drv_tm1637.c
SRC_C += $(OBK_DIR)/src/driver/drv_tm1638.c
SRC_C += $(OBK_DIR)/src/driver/drv_tuyaMCU.c
SRC_C += $(OBK_DIR)/src/driver/drv_tuyaMCUSensor.c
SRC_C += $(OBK_DIR)/src/driver/drv_uart.c
SRC_C += $(OBK_DIR)/src/driver/drv_ucs1912.c
SRC_C += $(OBK_DIR)/src/driver/drv_wemo.c
SRC_C += $(OBK_DIR)/src/driver/drv_ds1820_simple.c
SRC_C += $(OBK_DIR)/src/driver/drv_uart_tcp.c
#SRC_C += $(OBK_DIR)/src/httpclient/http_client.c
#SRC_C += $(OBK_DIR)/src/httpclient/utils_net.c
#SRC_C += $(OBK_DIR)/src/httpclient/utils_timer.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_lcd_pcf8574t.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_main.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_mcp23017.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_tc74.c
SRC_C += $(OBK_DIR)/src/littlefs/lfs_util.c
SRC_C += $(OBK_DIR)/src/littlefs/lfs.c
SRC_C += $(OBK_DIR)/src/littlefs/our_lfs.c
#SRC_C += $(OBK_DIR)/src/memory/memtest.c
#SRC_C += $(OBK_DIR)/src/ota/ota.c
#SRC_C += $(OBK_DIR)/src/sim/sim_uart.c
SRC_C += $(OBK_DIR)/libraries/easyflash/ports/ef_port.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/easyflash.c
#SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_cmd.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env_legacy.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env_legacy_wl.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_iap.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_log.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_utils.c

56
platforms/RTL8710A/main.c Normal file
View File

@ -0,0 +1,56 @@
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "main.h"
#include "wifi_constants.h"
#include "platform_stdlib.h"
#include <lwip/netif.h>
#include "rtl8195a_sys_on.h"
#include "device_lock.h"
extern void Main_Init();
extern void Main_OnEverySecond();
extern struct netif xnetif[NET_IF_NUM];
rtw_mode_t wifi_mode = RTW_MODE_NONE;
TaskHandle_t g_sys_task_handle1;
uint8_t wmac[6] = { 0 };
static void obk_task(void* pvParameters)
{
Main_Init();
for(;;)
{
vTaskDelay(1000 / portTICK_PERIOD_MS);
Main_OnEverySecond();
}
vTaskDelete(NULL);
}
int main(void)
{
wlan_network();
//sys_jtag_off();
// this is not mac, but at least it should be unique
device_mutex_lock(RT_DEV_LOCK_EFUSE);
for(int i = 0xF4; i < 0xFA; i++)
{
HALEFUSEOneByteReadROM(HAL_READ32(SYSTEM_CTRL_BASE, REG_SYS_EFUSE_CTRL), i, &wmac[i - 0xF4], 7);
}
device_mutex_unlock(RT_DEV_LOCK_EFUSE);
xTaskCreate(
obk_task,
"OpenBeken",
8 * 256,
NULL,
tskIDLE_PRIORITY + 1,
NULL);
/* Enable Schedule, Start Kernel */
vTaskStartScheduler();
/* Should NEVER reach here */
return 0;
}

167
platforms/RTL8710A/stdlib.c Normal file
View File

@ -0,0 +1,167 @@
// copied from https://github.com/libretiny-eu/libretiny/blob/master/cores/realtek-ambz/base/wraps/stdlib.c
#include <stddef.h>
#define ROM __attribute__((long_call))
ROM int prvAtoi(const char* str);
ROM long simple_strtol(const char* str, char** str_end, int base);
ROM unsigned long simple_strtoul(const char* str, char** str_end, int base);
ROM int Rand();
ROM char* __rtl_strcat_v1_00(char* dest, const char* src);
ROM char* _strcpy(char* dest, const char* src);
ROM char* __rtl_strncat_v1_00(char* dest, const char* src, size_t count);
ROM char* _strncpy(char* dest, const char* src, size_t count);
ROM char* _strchr(const char* str, int ch);
ROM int prvStrCmp(const char* lhs, const char* rhs);
ROM size_t prvStrLen(const char* str);
ROM int _strncmp(const char* lhs, const char* rhs, size_t count);
ROM char* _strpbrk(const char* dest, const char* breakset);
ROM char* prvStrStr(const char* str, const char* substr);
ROM char* prvStrtok(char* str, const char* delim);
ROM void* __rtl_memchr_v1_00(const void* ptr, int ch, size_t count);
ROM int _memcmp(const void* lhs, const void* rhs, size_t count);
ROM void* _memcpy(void* dest, const void* src, size_t count);
ROM void* __rtl_memmove_v1_00(void* dest, const void* src, size_t count);
ROM void* _memset(void* dest, int ch, size_t count);
ROM char* _strsep(char** stringp, const char* delim);
int __wrap_atoi(const char* str)
{
register int num, neg;
register char c;
num = neg = 0;
c = *str;
while((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))c = *++str;
if(c == '-')
{ /* get an optional sign */
neg = 1;
c = *++str;
}
else if(c == '+')
{
c = *++str;
}
while((c >= '0') && (c <= '9'))
{
num = (10 * num) + (c - '0');
c = *++str;
}
if(neg)return(0 - num);
return(num);
}
long __wrap_atol(const char* str)
{
return simple_strtol(str, NULL, 10);
}
long __wrap_strtol(const char* str, char** str_end, int base)
{
return simple_strtol(str, str_end, base);
}
unsigned long __wrap_strtoul(const char* str, char** str_end, int base)
{
return simple_strtoul(str, str_end, base);
}
int __wrap_rand()
{
return Rand();
}
char* __wrap_strcat(char* dest, const char* src)
{
return __rtl_strcat_v1_00(dest, src);
}
char* __wrap_strcpy(char* dest, const char* src)
{
return _strcpy(dest, src);
}
char* __wrap_strncat(char* dest, const char* src, size_t count)
{
return __rtl_strncat_v1_00(dest, src, count);
}
char* __wrap_strncpy(char* dest, const char* src, size_t count)
{
return _strncpy(dest, src, count);
}
char* __wrap_strchr(const char* str, int ch)
{
return _strchr(str, ch);
}
int __wrap_strcmp(const char* lhs, const char* rhs)
{
return prvStrCmp(lhs, rhs);
}
size_t __wrap_strlen(const char* str)
{
return prvStrLen(str);
}
int __wrap_strncmp(const char* lhs, const char* rhs, size_t count)
{
return _strncmp(lhs, rhs, count);
}
char* __wrap_strpbrk(const char* dest, const char* breakset)
{
return _strpbrk(dest, breakset);
}
char* __wrap_strstr(const char* str, const char* substr)
{
return prvStrStr(str, substr);
}
char* __wrap_strtok(char* str, const char* delim)
{
return prvStrtok(str, delim);
}
void* __wrap_memchr(const void* ptr, int ch, size_t count)
{
return __rtl_memchr_v1_00(ptr, ch, count);
}
int __wrap_memcmp(const void* lhs, const void* rhs, size_t count)
{
return _memcmp(lhs, rhs, count);
}
void* __wrap_memcpy(void* dest, const void* src, size_t count)
{
return _memcpy(dest, src, count);
}
void* __wrap_memmove(void* dest, const void* src, size_t count)
{
return __rtl_memmove_v1_00(dest, src, count);
}
void* __wrap_memset(void* dest, int ch, size_t count)
{
return _memset(dest, ch, count);
}
char* __wrap_strsep(char** stringp, const char* delim)
{
return _strsep(stringp, delim);
}
void* os_malloc(size_t size)
{
return pvPortMalloc(size);
}
void os_free(void* ptr)
{
vPortFree(ptr);
}

View File

@ -0,0 +1,156 @@
OBK_DIR = ../../../../..
CFLAGS += -DPLATFORM_RTL8710B -DPLATFORM_REALTEK -DUSER_SW_VER='"$(APP_VERSION)"'
INCLUDES += -I$(OBK_DIR)/libraries/easyflash/inc
SRC_C += $(OBK_DIR)/platforms/RTL8710B/main.c
SRC_C += $(OBK_DIR)/platforms/RTL8710B/stdlib.c
SRC_C += $(OBK_DIR)/src/base64/base64.c
SRC_C += $(OBK_DIR)/src/bitmessage/bitmessage_read.c
SRC_C += $(OBK_DIR)/src/bitmessage/bitmessage_write.c
SRC_C += $(OBK_DIR)/src/cJSON/cJSON.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_channels.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_eventHandlers.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_if.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_main.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_newLEDDriver_colors.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_newLEDDriver.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_repeatingEvents.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_script.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_simulatorOnly.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_tasmota.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_tcp.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_test.c
SRC_C += $(OBK_DIR)/src/cmnds/cmd_tokenizer.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_read.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_util.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_write.c
SRC_C += $(OBK_DIR)/src/driver/drv_main.c
#SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710b/hal_adc_rtl8710b.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710b/hal_generic_rtl8710b.c
#SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710b/hal_main_rtl8710b.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710b/hal_uart_rtl8710b.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl8710b/hal_pins_rtl8710b.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_flashConfig_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_flashVars_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_pins_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_wifi_realtek.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_adc_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_flashConfig_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_flashVars_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_main_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_pins_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_wifi_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_uart_generic.c
SRC_C += $(OBK_DIR)/src/httpserver/hass.c
SRC_C += $(OBK_DIR)/src/httpserver/http_basic_auth.c
SRC_C += $(OBK_DIR)/src/httpserver/http_fns.c
SRC_C += $(OBK_DIR)/src/httpserver/http_tcp_server.c
SRC_C += $(OBK_DIR)/src/httpserver/new_tcp_server.c
SRC_C += $(OBK_DIR)/src/httpserver/json_interface.c
SRC_C += $(OBK_DIR)/src/httpserver/new_http.c
SRC_C += $(OBK_DIR)/src/httpserver/rest_interface.c
SRC_C += $(OBK_DIR)/src/mqtt/new_mqtt_deduper.c
SRC_C += $(OBK_DIR)/src/jsmn/jsmn.c
SRC_C += $(OBK_DIR)/src/logging/logging.c
SRC_C += $(OBK_DIR)/src/mqtt/new_mqtt.c
SRC_C += $(OBK_DIR)/src/new_cfg.c
SRC_C += $(OBK_DIR)/src/new_common.c
SRC_C += $(OBK_DIR)/src/new_ping.c
SRC_C += $(OBK_DIR)/src/new_pins.c
SRC_C += $(OBK_DIR)/src/rgb2hsv.c
SRC_C += $(OBK_DIR)/src/tiny_crc8.c
SRC_C += $(OBK_DIR)/src/user_main.c
#SRC_C += $(OBK_DIR)/src/cmnds/cmd_send.c
SRC_C += $(OBK_DIR)/src/driver/drv_adcButton.c
SRC_C += $(OBK_DIR)/src/driver/drv_adcSmoother.c
SRC_C += $(OBK_DIR)/src/driver/drv_aht2x.c
SRC_C += $(OBK_DIR)/src/driver/drv_battery.c
SRC_C += $(OBK_DIR)/src/driver/drv_bl_shared.c
SRC_C += $(OBK_DIR)/src/driver/drv_bl0937.c
SRC_C += $(OBK_DIR)/src/driver/drv_bl0942.c
#SRC_C += $(OBK_DIR)/src/driver/drv_bmp280.c
SRC_C += $(OBK_DIR)/src/driver/drv_bmpi2c.c
SRC_C += $(OBK_DIR)/src/driver/drv_bp1658cj.c
SRC_C += $(OBK_DIR)/src/driver/drv_bp5758d.c
SRC_C += $(OBK_DIR)/src/driver/drv_bridge_driver.c
SRC_C += $(OBK_DIR)/src/driver/drv_chargingLimit.c
SRC_C += $(OBK_DIR)/src/driver/drv_charts.c
SRC_C += $(OBK_DIR)/src/driver/drv_cht8305.c
SRC_C += $(OBK_DIR)/src/driver/drv_cse7766.c
SRC_C += $(OBK_DIR)/src/driver/drv_ddp.c
SRC_C += $(OBK_DIR)/src/driver/drv_debouncer.c
SRC_C += $(OBK_DIR)/src/driver/drv_dht_internal.c
SRC_C += $(OBK_DIR)/src/driver/drv_dht.c
SRC_C += $(OBK_DIR)/src/driver/drv_doorSensorWithDeepSleep.c
SRC_C += $(OBK_DIR)/src/driver/drv_gn6932.c
SRC_C += $(OBK_DIR)/src/driver/drv_hd2015.c
SRC_C += $(OBK_DIR)/src/driver/drv_ht16k33.c
SRC_C += $(OBK_DIR)/src/driver/drv_httpButtons.c
SRC_C += $(OBK_DIR)/src/driver/drv_hue.c
SRC_C += $(OBK_DIR)/src/driver/drv_kp18058.c
SRC_C += $(OBK_DIR)/src/driver/drv_kp18068.c
SRC_C += $(OBK_DIR)/src/driver/drv_max72xx_clock.c
SRC_C += $(OBK_DIR)/src/driver/drv_max72xx_internal.c
SRC_C += $(OBK_DIR)/src/driver/drv_max72xx_single.c
SRC_C += $(OBK_DIR)/src/driver/drv_mcp9808.c
SRC_C += $(OBK_DIR)/src/driver/drv_ntp_events.c
SRC_C += $(OBK_DIR)/src/driver/drv_ntp.c
SRC_C += $(OBK_DIR)/src/driver/drv_pt6523.c
SRC_C += $(OBK_DIR)/src/driver/drv_pwm_groups.c
SRC_C += $(OBK_DIR)/src/driver/drv_pwmToggler.c
SRC_C += $(OBK_DIR)/src/driver/drv_pwrCal.c
SRC_C += $(OBK_DIR)/src/driver/drv_rn8209.c
SRC_C += $(OBK_DIR)/src/driver/drv_sgp.c
SRC_C += $(OBK_DIR)/src/driver/drv_shiftRegister.c
SRC_C += $(OBK_DIR)/src/driver/drv_sht3x.c
#SRC_C += $(OBK_DIR)/src/driver/drv_sm15155e.c
#SRC_C += $(OBK_DIR)/src/driver/drv_sm16703P.c
SRC_C += $(OBK_DIR)/src/driver/drv_sm2135.c
SRC_C += $(OBK_DIR)/src/driver/drv_sm2235.c
SRC_C += $(OBK_DIR)/src/driver/drv_soft_i2c.c
#SRC_C += $(OBK_DIR)/src/driver/drv_soft_spi.c
#SRC_C += $(OBK_DIR)/src/driver/drv_spi_flash.c
#SRC_C += $(OBK_DIR)/src/driver/drv_spi.c
#SRC_C += $(OBK_DIR)/src/driver/drv_spidma.c
SRC_C += $(OBK_DIR)/src/driver/drv_ssdp.c
SRC_C += $(OBK_DIR)/src/driver/drv_tasmotaDeviceGroups.c
SRC_C += $(OBK_DIR)/src/driver/drv_test_drivers.c
SRC_C += $(OBK_DIR)/src/driver/drv_textScroller.c
SRC_C += $(OBK_DIR)/src/driver/drv_tm_gn_display_shared.c
SRC_C += $(OBK_DIR)/src/driver/drv_tm1637.c
SRC_C += $(OBK_DIR)/src/driver/drv_tm1638.c
SRC_C += $(OBK_DIR)/src/driver/drv_tuyaMCU.c
SRC_C += $(OBK_DIR)/src/driver/drv_tuyaMCUSensor.c
SRC_C += $(OBK_DIR)/src/driver/drv_uart.c
SRC_C += $(OBK_DIR)/src/driver/drv_ucs1912.c
SRC_C += $(OBK_DIR)/src/driver/drv_wemo.c
SRC_C += $(OBK_DIR)/src/driver/drv_ds1820_simple.c
SRC_C += $(OBK_DIR)/src/driver/drv_uart_tcp.c
#SRC_C += $(OBK_DIR)/src/httpclient/http_client.c
#SRC_C += $(OBK_DIR)/src/httpclient/utils_net.c
#SRC_C += $(OBK_DIR)/src/httpclient/utils_timer.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_lcd_pcf8574t.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_main.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_mcp23017.c
SRC_C += $(OBK_DIR)/src/i2c/drv_i2c_tc74.c
SRC_C += $(OBK_DIR)/src/littlefs/lfs_util.c
SRC_C += $(OBK_DIR)/src/littlefs/lfs.c
SRC_C += $(OBK_DIR)/src/littlefs/our_lfs.c
#SRC_C += $(OBK_DIR)/src/memory/memtest.c
#SRC_C += $(OBK_DIR)/src/ota/ota.c
#SRC_C += $(OBK_DIR)/src/sim/sim_uart.c
SRC_C += $(OBK_DIR)/libraries/easyflash/ports/ef_port.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/easyflash.c
#SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_cmd.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env_legacy.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env_legacy_wl.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_iap.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_log.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_utils.c

57
platforms/RTL8710B/main.c Normal file
View File

@ -0,0 +1,57 @@
#include "FreeRTOS.h"
#include "task.h"
#include "diag.h"
#include "main.h"
#include "wifi_constants.h"
#include "rtl8711b_efuse.h"
#include "platform_stdlib.h"
extern void Main_Init();
extern void Main_OnEverySecond();
extern int g_sleepfactor;
rtw_mode_t wifi_mode = RTW_MODE_NONE;
TaskHandle_t g_sys_task_handle1;
uint8_t wmac[6] = { 0 };
char set_key[40];
uint32_t current_fw_idx;
void LOGUART_SetBaud_FromFlash(void) {}
static void obk_task(void* pvParameters)
{
Main_Init();
for(;;)
{
vTaskDelay(1000 / portTICK_PERIOD_MS / g_sleepfactor);
Main_OnEverySecond();
}
vTaskDelete(NULL);
}
int main(void)
{
wlan_network();
sys_jtag_off();
uint8_t* efuse = (uint8_t*)malloc(512);
EFUSE_LogicalMap_Read(efuse);
memcpy(wmac, efuse + 0x11A, 6);
free(efuse);
current_fw_idx = ota_get_cur_index();
xTaskCreate(
obk_task,
"OpenBeken",
8 * 256,
NULL,
tskIDLE_PRIORITY + 1,
NULL);
/* Enable Schedule, Start Kernel */
vTaskStartScheduler();
/* Should NEVER reach here */
return 0;
}

157
platforms/RTL8710B/stdlib.c Normal file
View File

@ -0,0 +1,157 @@
// copied from https://github.com/libretiny-eu/libretiny/blob/master/cores/realtek-ambz/base/wraps/stdlib.c
#include <stddef.h>
#define ROM __attribute__((long_call))
ROM int prvAtoi(const char* str);
ROM long simple_strtol(const char* str, char** str_end, int base);
ROM unsigned long simple_strtoul(const char* str, char** str_end, int base);
ROM int Rand();
ROM char* __rtl_strcat_v1_00(char* dest, const char* src);
ROM char* _strcpy(char* dest, const char* src);
ROM char* __rtl_strncat_v1_00(char* dest, const char* src, size_t count);
ROM char* _strncpy(char* dest, const char* src, size_t count);
ROM char* _strchr(const char* str, int ch);
ROM int prvStrCmp(const char* lhs, const char* rhs);
ROM size_t prvStrLen(const char* str);
ROM int _strncmp(const char* lhs, const char* rhs, size_t count);
ROM char* _strpbrk(const char* dest, const char* breakset);
ROM char* prvStrStr(const char* str, const char* substr);
ROM char* prvStrtok(char* str, const char* delim);
ROM void* __rtl_memchr_v1_00(const void* ptr, int ch, size_t count);
ROM int _memcmp(const void* lhs, const void* rhs, size_t count);
ROM void* _memcpy(void* dest, const void* src, size_t count);
ROM void* __rtl_memmove_v1_00(void* dest, const void* src, size_t count);
ROM void* _memset(void* dest, int ch, size_t count);
ROM char* _strsep(char** stringp, const char* delim);
int __wrap_atoi(const char* str)
{
register int num, neg;
register char c;
num = neg = 0;
c = *str;
while((c == ' ') || (c == '\n') || (c == '\r') || (c == '\t'))c = *++str;
if(c == '-')
{ /* get an optional sign */
neg = 1;
c = *++str;
}
else if(c == '+')
{
c = *++str;
}
while((c >= '0') && (c <= '9'))
{
num = (10 * num) + (c - '0');
c = *++str;
}
if(neg)return(0 - num);
return(num);
}
long __wrap_atol(const char* str)
{
return simple_strtol(str, NULL, 10);
}
long __wrap_strtol(const char* str, char** str_end, int base)
{
return simple_strtol(str, str_end, base);
}
unsigned long __wrap_strtoul(const char* str, char** str_end, int base)
{
return simple_strtoul(str, str_end, base);
}
int __wrap_rand()
{
return Rand();
}
char* __wrap_strcat(char* dest, const char* src)
{
return __rtl_strcat_v1_00(dest, src);
}
char* __wrap_strcpy(char* dest, const char* src)
{
return _strcpy(dest, src);
}
char* __wrap_strncat(char* dest, const char* src, size_t count)
{
return __rtl_strncat_v1_00(dest, src, count);
}
char* __wrap_strncpy(char* dest, const char* src, size_t count)
{
return _strncpy(dest, src, count);
}
char* __wrap_strchr(const char* str, int ch)
{
return _strchr(str, ch);
}
int __wrap_strcmp(const char* lhs, const char* rhs)
{
return prvStrCmp(lhs, rhs);
}
size_t __wrap_strlen(const char* str)
{
return prvStrLen(str);
}
int __wrap_strncmp(const char* lhs, const char* rhs, size_t count)
{
return _strncmp(lhs, rhs, count);
}
char* __wrap_strpbrk(const char* dest, const char* breakset)
{
return _strpbrk(dest, breakset);
}
char* __wrap_strstr(const char* str, const char* substr)
{
return prvStrStr(str, substr);
}
char* __wrap_strtok(char* str, const char* delim)
{
return prvStrtok(str, delim);
}
void* __wrap_memchr(const void* ptr, int ch, size_t count)
{
return __rtl_memchr_v1_00(ptr, ch, count);
}
int __wrap_memcmp(const void* lhs, const void* rhs, size_t count)
{
return _memcmp(lhs, rhs, count);
}
void* __wrap_memcpy(void* dest, const void* src, size_t count)
{
return _memcpy(dest, src, count);
}
void* __wrap_memmove(void* dest, const void* src, size_t count)
{
return __rtl_memmove_v1_00(dest, src, count);
}
void* __wrap_memset(void* dest, int ch, size_t count)
{
return _memset(dest, ch, count);
}
char* __wrap_strsep(char** stringp, const char* delim)
{
return _strsep(stringp, delim);
}

1
platforms/RTL8710B/tools/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
amebaz_ota_combine

View File

@ -0,0 +1,43 @@
#include <iostream>
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
int main(int argc, char* argv[])
{
if(argc == 1)
{
std::cout << "arg1: ota1_path, arg2: ota2_path\n";
exit(1);
}
else if(argc < 3)
{
std::cout << "Not enough args\n";
exit(1);
}
std::string out_path = "OpenRTL8710B_Test_ota.img";
if(argc >= 4)
{
out_path = argv[3];
}
fs::path ota1_path{ argv[1] };
fs::path ota2_path{ argv[2] };
uint32_t ota1_size = fs::file_size(ota1_path);
uint32_t ota2_size = fs::file_size(ota2_path);
std::cout << "OpenBeken AmebaZ OTA image generator.\n";
std::cout << "The size of " << ota1_path.filename() << " is " << ota1_size << " bytes.\n";
std::cout << "The size of " << ota2_path.filename() << " is " << ota2_size << " bytes.\n";
std::cout << "Output image path: " << out_path << "\n";
std::cout << "Generating OpenBeken OTA image...\n";
std::ofstream obkota(out_path, std::ios_base::binary);
std::ifstream ota1(ota1_path, std::ios_base::binary);
std::ifstream ota2(ota2_path, std::ios_base::binary);
obkota.write(reinterpret_cast<char*>(&ota1_size), sizeof(ota1_size));
obkota.write(reinterpret_cast<char*>(&ota2_size), sizeof(ota2_size));
obkota << ota1.rdbuf() << ota2.rdbuf();
obkota.close();
ota1.close();
ota2.close();
std::cout << "Done, OTA image size: " << fs::file_size(out_path) << "\n";
}

View File

@ -1,6 +1,8 @@
OBK_DIR = ../../../../..
CFLAGS += -DPLATFORM_RTL87X0C -DUSER_SW_VER='"$(APP_VERSION)"'
CFLAGS += -DPLATFORM_RTL87X0C -DPLATFORM_REALTEK -DUSER_SW_VER='"$(APP_VERSION)"'
INCLUDES += -I$(OBK_DIR)/libraries/easyflash/inc
SRC_C += ../../../../../platforms/RTL87X0C/main.c
@ -25,14 +27,14 @@ SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_read.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_util.c
SRC_C += $(OBK_DIR)/src/devicegroups/deviceGroups_write.c
SRC_C += $(OBK_DIR)/src/driver/drv_main.c
#SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_adc_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_flashConfig_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_flashVars_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_generic_rtl87x0c.c
#SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_main_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_pins_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_wifi_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/rtl87x0c/hal_uart_rtl87x0c.c
#SRC_C += $(OBK_DIR)/src/hal/realtek/rtl87x0c/hal_adc_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl87x0c/hal_generic_rtl87x0c.c
#SRC_C += $(OBK_DIR)/src/hal/realtek/rtl87x0c/hal_main_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl87x0c/hal_pins_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/realtek/rtl87x0c/hal_uart_rtl87x0c.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_flashConfig_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_flashVars_realtek.c
SRC_C += $(OBK_DIR)/src/hal/realtek/hal_wifi_realtek.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_adc_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_flashConfig_generic.c
SRC_C += $(OBK_DIR)/src/hal/generic/hal_flashVars_generic.c
@ -138,3 +140,13 @@ SRC_C += $(OBK_DIR)/src/littlefs/our_lfs.c
#SRC_C += $(OBK_DIR)/src/memory/memtest.c
#SRC_C += $(OBK_DIR)/src/ota/ota.c
#SRC_C += $(OBK_DIR)/src/sim/sim_uart.c
SRC_C += $(OBK_DIR)/libraries/easyflash/ports/ef_port.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/easyflash.c
#SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_cmd.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env_legacy.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_env_legacy_wl.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_iap.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_log.c
SRC_C += $(OBK_DIR)/libraries/easyflash/src/ef_utils.c

1
sdk/OpenRTL8710A_B Submodule

@ -0,0 +1 @@
Subproject commit e8022abf49395c32f8b1e17f1c1185012a31f678

@ -1 +1 @@
Subproject commit f4710e02a72a50ef5e21c51aaf2010835ba600de
Subproject commit 63d5079232f73e749fbcea6281b77068d5f2f695

View File

@ -29,8 +29,17 @@ int cmd_uartInitIndex = 0;
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_check.h"
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
#if PLATFORM_RTL8710B
#include "wlan_intf.h"
extern WLAN_LOW_PW_MODE rtw_wlan_low_pw_mode;
extern int rtw_wlan_low_pw_mode4_c1;
extern int rtw_wlan_low_pw_mode4_c2;
extern int rtw_reduce_pa_gain;
extern void rtw_enable_wlan_low_pwr_mode(WLAN_LOW_PW_MODE mode);
#endif
#include "wifi_conf.h"
int g_sleepfactor = 1;
#endif
#define HASH_SIZE 128
@ -163,7 +172,7 @@ static commandResult_t CMD_PowerSave(const void* context, const char* cmd, const
ADDLOG_INFO(LOG_FEATURE_CMD, "PowerSave disabled");
esp_wifi_set_ps(WIFI_PS_NONE);
}
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
if(!wifi_is_up(RTW_STA_INTERFACE))
{
ADDLOG_ERROR(LOG_FEATURE_CMD, "Wifi is not on or in AP mode, failed setting powersave!");
@ -171,10 +180,42 @@ static commandResult_t CMD_PowerSave(const void* context, const char* cmd, const
}
if(bOn)
{
#if PLATFORM_RTL8710B
if(bOn >= 2)
{
rtw_wlan_low_pw_mode = PW_MODE_2 | PW_MODE_3 | PW_MODE_4 | PW_MODE_6;
rtw_wlan_low_pw_mode |= bOn >= 3 ? PW_MODE_1 : PW_MODE_5;
rtw_wlan_low_pw_mode4_c1 = 24;
rtw_wlan_low_pw_mode4_c2 = 16;
rtw_reduce_pa_gain = bOn == 2 ? 1 : 2; //0:not reduce, 1:reduce 2, 2:reduce 3
rtw_enable_wlan_low_pwr_mode(rtw_wlan_low_pw_mode);
g_sleepfactor = bOn >= 3 ? 2 : 1;
}
else if(g_powersave >= 2)
{
rtw_wlan_low_pw_mode = PW_MODE_NONE;
rtw_wlan_low_pw_mode4_c1 = 0;
rtw_wlan_low_pw_mode4_c2 = 0;
rtw_reduce_pa_gain = 0;
rtw_enable_wlan_low_pwr_mode(rtw_wlan_low_pw_mode);
g_sleepfactor = 1;
}
#endif
wifi_enable_powersave();
}
else
{
#if PLATFORM_RTL8710B
if(g_powersave >= 2)
{
rtw_wlan_low_pw_mode = PW_MODE_NONE;
rtw_wlan_low_pw_mode4_c1 = 0;
rtw_wlan_low_pw_mode4_c2 = 0;
rtw_reduce_pa_gain = 0;
rtw_enable_wlan_low_pwr_mode(rtw_wlan_low_pw_mode);
}
g_sleepfactor = 1;
#endif
wifi_disable_powersave();
}
#else
@ -311,7 +352,7 @@ static commandResult_t CMD_ClearAll(const void* context, const char* cmd, const
CMD_ClearAllHandlers(0, 0, 0, 0);
RepeatingEvents_Cmd_ClearRepeatingEvents(0, 0, 0, 0);
#if defined(WINDOWS) || defined(PLATFORM_BL602) || defined(PLATFORM_BEKEN) || defined(PLATFORM_LN882H) \
|| defined(PLATFORM_ESPIDF) || defined(PLATFORM_TR6260) || defined(PLATFORM_RTL87X0C)
|| defined(PLATFORM_ESPIDF) || defined(PLATFORM_TR6260) || defined(PLATFORM_REALTEK)
CMD_resetSVM(0, 0, 0, 0);
#endif
@ -875,7 +916,6 @@ void CMD_Init_Early() {
//cmddetail:"examples":""}
CMD_RegisterCommand("IndexRefreshInterval", CMD_IndexRefreshInterval, NULL);
#if ENABLE_OBK_SCRIPTING
CMD_InitScripting();
#endif
@ -896,7 +936,7 @@ void CMD_Init_Delayed() {
}
#endif
#if defined(PLATFORM_BEKEN) || defined(WINDOWS) || defined(PLATFORM_BL602) || defined(PLATFORM_ESPIDF) \
|| defined(PLATFORM_RTL87X0C)
|| defined(PLATFORM_REALTEK)
UART_AddCommands();
#endif
}

View File

@ -22,7 +22,7 @@ static int tok_flags = 0;
#define g_bAllowExpand (!(tok_flags&TOKENIZER_DONT_EXPAND))
int str_to_ip(const char *s, byte *ip) {
#if PLATFORM_W600 || PLATFORM_LN882H || PLATFORM_RTL87X0C
#if PLATFORM_W600 || PLATFORM_LN882H || PLATFORM_REALTEK
//seems like sscanf in W600 does not support %hhu and uses it as %u, thus overwriting more memory, use temp array for it
// same for LN882h: %hhu isn't recognised, so we have to use %u for IP_STRING_FORMAT, which will lead to problems in sscanf, too
int tmp_ip[4];

View File

@ -38,10 +38,10 @@
#include "../../sdk/OpenLN882H/mcu/driver_ln882h/hal/hal_common.h"
#include "../../sdk/OpenLN882H/mcu/driver_ln882h/hal/hal_gpio.h"
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
#include "gpio_irq_api.h"
#include "../hal/rtl87x0c/hal_generic_rtl87x0c.h"
#include "../hal/realtek/hal_generic_realtek.h"
extern rtlPinMapping_t g_pins[];
rtlPinMapping_t* rtl_cf;
rtlPinMapping_t* rtl_cf1;
@ -158,7 +158,7 @@ void GPIOB_IRQHandler()
}
}
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
void cf_irq_handler(uint32_t id, gpio_irq_event event)
{
@ -223,7 +223,7 @@ void BL0937_Shutdown_Pins()
gpio_int_disable(GPIO_HLW_CF1);
gpio_int_disable(GPIO_HLW_CF);
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
gpio_irq_free(rtl_cf1->irq);
gpio_irq_free(rtl_cf->irq);
@ -261,10 +261,11 @@ void BL0937_Init_Pins()
//printf("GPIO_HLW_CF=%d GPIO_HLW_CF1=%d\n", GPIO_HLW_CF, GPIO_HLW_CF1);
//printf("GPIO_HLW_CF1_pin=%d GPIO_HLW_CF_pin=%d\n", GPIO_HLW_CF1_pin, GPIO_HLW_CF_pin);
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
rtl_cf = g_pins + GPIO_HLW_CF;
rtl_cf1 = g_pins + GPIO_HLW_CF1;
#if PLATFORM_RTL87X0C
if(rtl_cf->gpio != NULL)
{
hal_pinmux_unregister(rtl_cf->pin, PID_GPIO);
@ -277,6 +278,7 @@ void BL0937_Init_Pins()
os_free(rtl_cf1->gpio);
rtl_cf1->gpio = NULL;
}
#endif
rtl_cf1->irq = os_malloc(sizeof(gpio_irq_t));
rtl_cf->irq = os_malloc(sizeof(gpio_irq_t));
memset(rtl_cf1->irq, 0, sizeof(gpio_irq_t));
@ -312,7 +314,7 @@ void BL0937_Init_Pins()
gpio_int_enable(GPIO_HLW_CF1, IRQ_TRIGGER_FALLING_EDGE, HlwCf1Interrupt);
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
gpio_irq_init(rtl_cf1->irq, rtl_cf1->pin, cf1_irq_handler, NULL);
gpio_irq_set(rtl_cf1->irq, IRQ_FALL, 1);
@ -343,7 +345,7 @@ void BL0937_Init_Pins()
gpio_int_enable(GPIO_HLW_CF, IRQ_TRIGGER_FALLING_EDGE, HlwCfInterrupt);
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
gpio_irq_init(rtl_cf->irq, rtl_cf->pin, cf_irq_handler, NULL);
gpio_irq_set(rtl_cf->irq, IRQ_FALL, 1);

View File

@ -180,6 +180,9 @@ void Drawers_QuickTick();
void HGS02_Init(void);
void HGS02_RunEverySecond(void);
void UART_TCP_Init(void);
void UART_TCP_Deinit(void);
#define SM2135_DELAY 4
// Software I2C

View File

@ -445,6 +445,13 @@ static driver_t g_drivers[] = {
//drvdetail:"requires":""}
{ "Bridge", Bridge_driver_Init, NULL, NULL, Bridge_driver_QuickFrame, Bridge_driver_DeInit, Bridge_driver_OnChannelChanged, false }
#endif
#if ENABLE_DRIVER_UART_TCP
//drvdetail:{"name":"UART to TCP bridge",
//drvdetail:"title":"TODO",
//drvdetail:"descr":"UART to TCP, mainly for WiFi Zigbee coordinators.",
//drvdetail:"requires":""}
{ "UartTCP", UART_TCP_Init, NULL, NULL, NULL, UART_TCP_Deinit, NULL, false }
#endif
};

309
src/driver/drv_uart_tcp.c Normal file
View File

@ -0,0 +1,309 @@
#include "../new_common.h"
#include "../new_pins.h"
#include "../new_cfg.h"
#include "../quicktick.h"
#include "../logging/logging.h"
#include "errno.h"
#include <lwip/sockets.h>
#if ENABLE_DRIVER_UART_TCP
#define DEFAULT_BUF_SIZE 512
#define DEFAULT_UART_TCP_PORT 8888
#define INVALID_SOCK -1
#define UTCP_DEBUG 1
static uint16_t buf_size = DEFAULT_BUF_SIZE;
static int g_tx_channel = -1;
static int g_baudRate = 115200;
static int listen_sock = INVALID_SOCK;
static int client_sock = INVALID_SOCK;
static xTaskHandle g_trx_thread = NULL;
static xTaskHandle g_rx_thread = NULL;
static xTaskHandle g_tx_thread = NULL;
static bool rx_closed, tx_closed;
static byte* g_utcpBuf = 0;
void Start_UART_TCP(void* arg);
static void UTCP_TX_Thd(void* param)
{
int client_fd = *(int*)param;
while(1)
{
int ret = 0;
int delay = 0;
memset(g_utcpBuf, 0, buf_size);
int len = UART_GetDataSize();
while(len < buf_size && delay < 10)
{
rtos_delay_milliseconds(5);
len = UART_GetDataSize();
delay++;
}
if(len > 0)
{
for(int i = 0; i < len; i++)
{
g_utcpBuf[i] = UART_GetByte(i);
}
UART_ConsumeBytes(len);
#if UTCP_DEBUG
char data[len * 2];
char* p = data;
for(int i = 0; i < len; i++)
{
sprintf(p, "%02X", g_utcpBuf[i]);
p += 2;
}
ADDLOG_EXTRADEBUG(LOG_FEATURE_DRV, "%d bytes UART RX->TCP TX: %s", len, data);
#endif
ret = send(client_fd, g_utcpBuf, len, 0);
}
else
{
if(rx_closed)
{
goto exit;
}
continue;
}
if(ret <= 0)
goto exit;
rtos_delay_milliseconds(20);
}
exit:
ADDLOG_DEBUG(LOG_FEATURE_DRV, "UTCP_TX_Thd closed");
tx_closed = true;
rtos_delete_thread(NULL);
}
static void UTCP_RX_Thd(void* param)
{
int client_fd = *(int*)param;
unsigned char buffer[1024];
while(1)
{
int ret = 0;
ret = recv(client_fd, buffer, sizeof(buffer), 0);
if(ret > 0)
{
#if UTCP_DEBUG
char data[ret * 2];
char* p = data;
for(int i = 0; i < ret; i++)
{
sprintf(p, "%02X", buffer[i]);
p += 2;
}
ADDLOG_EXTRADEBUG(LOG_FEATURE_DRV, "%d bytes TCP RX->UART TX: %s", ret, data);
#endif
if(g_tx_channel >= 0) CHANNEL_Set(g_tx_channel, 1, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
for(int i = 0; i < ret; i++)
{
UART_SendByte(buffer[i]);
}
if(g_tx_channel >= 0) CHANNEL_Set(g_tx_channel, 0, CHANNEL_SET_FLAG_SKIP_MQTT | CHANNEL_SET_FLAG_SILENT);
}
else if(tx_closed)
{
goto exit;
}
// ret == -1 and socket error == EAGAIN when no data received for nonblocking
if((ret == -1) && (errno == EAGAIN))
continue;
else if(ret <= 0)
{
ADDLOG_DEBUG(LOG_FEATURE_DRV, "ret: %i, errno: %i", ret, errno);
goto exit;
}
rtos_delay_milliseconds(10);
}
exit:
ADDLOG_DEBUG(LOG_FEATURE_DRV, "UTCP_RX_Thd closed");
rx_closed = true;
rtos_delete_thread(NULL);
}
void UART_TCP_TRX_Thread()
{
OSStatus err = kNoErr;
int reuse = 1;
struct sockaddr_in server_addr =
{
.sin_family = AF_INET,
.sin_addr =
{
.s_addr = INADDR_ANY,
},
.sin_port = htons(DEFAULT_UART_TCP_PORT),
};
if(listen_sock != INVALID_SOCK) close(listen_sock);
if(client_sock != INVALID_SOCK) close(client_sock);
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(listen_sock < 0)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "Unable to create socket");
goto error;
}
int flags = fcntl(listen_sock, F_GETFL, 0);
if(fcntl(listen_sock, F_SETFL, flags | O_NONBLOCK) == -1)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "Unable to set socket non blocking");
goto error;
}
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse));
err = bind(listen_sock, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(err != 0)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "Socket unable to bind");
goto error;
}
err = listen(listen_sock, 2);
if(err != 0)
{
ADDLOG_ERROR(LOG_FEATURE_HTTP, "Error occurred during listen");
goto error;
}
while(1)
{
struct sockaddr_storage source_addr;
socklen_t addr_len = sizeof(source_addr);
client_sock = accept(listen_sock, (struct sockaddr*)&source_addr, &addr_len);
if(client_sock != INVALID_SOCK)
{
rx_closed = true;
tx_closed = true;
err = rtos_create_thread(&g_tx_thread, tskIDLE_PRIORITY + 1,
"UTCP_TX_Thd",
(beken_thread_function_t)UTCP_TX_Thd,
0x800,
(beken_thread_arg_t)&client_sock);
if(err != kNoErr)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "create \"UTCP_TX_Thd\" thread failed with %i!", err);
}
else tx_closed = false;
rtos_delay_milliseconds(10);
err = rtos_create_thread(&g_rx_thread, tskIDLE_PRIORITY + 1,
"UTCP_RX_Thd",
(beken_thread_function_t)UTCP_RX_Thd,
0x800,
(beken_thread_arg_t)&client_sock);
if(err != kNoErr)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "create \"UTCP_RX_Thd\" thread failed with %i!", err);
}
else rx_closed = false;
while(1)
{
if(tx_closed && rx_closed)
{
close(client_sock);
ADDLOG_DEBUG(LOG_FEATURE_DRV, "UART TCP connection closed", err);
break;
}
else rtos_delay_milliseconds(50);
}
}
}
error:
ADDLOG_ERROR(LOG_FEATURE_DRV, "UART TCP Error");
if(listen_sock != INVALID_SOCK) close(listen_sock);
if(client_sock != INVALID_SOCK) close(client_sock);
xTaskCreate(
(TaskFunction_t)Start_UART_TCP,
"UART TCP Restart",
2048 / sizeof(StackType_t),
NULL,
BEKEN_APPLICATION_PRIORITY,
NULL);
}
void Start_UART_TCP(void* arg)
{
if(g_trx_thread != NULL)
{
rtos_delete_thread(&g_trx_thread);
}
OSStatus err = rtos_create_thread(&g_trx_thread, tskIDLE_PRIORITY + 1,
"UART_TCP_TRX",
(beken_thread_function_t)UART_TCP_TRX_Thread,
0x800,
(beken_thread_arg_t)0);
if(err != kNoErr)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "create \"UART_TCP_TRX\" thread failed with %i!\r\n", err);
}
vTaskDelete(NULL);
}
// startDriver UartTCP [baudrate] [buffer size] [tx action channel]
// tx action channel is for led.
void UART_TCP_Init()
{
g_baudRate = Tokenizer_GetArgIntegerDefault(1, g_baudRate);
uint32_t reqbufsize = Tokenizer_GetArgIntegerDefault(2, DEFAULT_BUF_SIZE);
buf_size = reqbufsize > 16384 ? 16384 : reqbufsize;
g_tx_channel = Tokenizer_GetArgIntegerDefault(3, -1);
UART_InitUART(g_baudRate, 0);
UART_InitReceiveRingBuffer(buf_size * 2);
g_utcpBuf = (byte*)malloc(buf_size);
OSStatus err = rtos_create_thread(NULL, BEKEN_APPLICATION_PRIORITY,
"UART_TCP",
(beken_thread_function_t)Start_UART_TCP,
0x800,
(beken_thread_arg_t)0);
if(err != kNoErr)
{
ADDLOG_ERROR(LOG_FEATURE_DRV, "create \"UART_TCP\" thread failed with %i!", err);
}
}
void UART_TCP_Deinit()
{
if(g_trx_thread != NULL)
{
rtos_delete_thread(&g_trx_thread);
g_trx_thread = NULL;
}
if(!rx_closed)
{
rtos_delete_thread(&g_rx_thread);
g_rx_thread = NULL;
}
if(!tx_closed)
{
rtos_delete_thread(&g_tx_thread);
g_tx_thread = NULL;
}
rtos_delay_milliseconds(200);
if(g_utcpBuf) free(g_utcpBuf);
}
#endif

View File

@ -1,4 +1,4 @@
#ifdef PLATFORM_RTL87X0C
#ifdef PLATFORM_REALTEK
#include "../hal_flashConfig.h"
#include <easyflash.h>
@ -26,4 +26,4 @@ int HAL_Configuration_SaveConfigMemory(void* src, int dataLen)
return 1;
}
#endif // PLATFORM_RTL87X0C
#endif // PLATFORM_REALTEK

View File

@ -1,4 +1,4 @@
#ifdef PLATFORM_RTL87X0C
#ifdef PLATFORM_REALTEK
#include "../../new_common.h"
#include "../hal_flashVars.h"
@ -178,5 +178,5 @@ void HAL_FlashVars_SaveTotalConsumption(float total_consumption)
flash_vars.emetering.TotalConsumption = total_consumption;
}
#endif // PLATFORM_RTL87X0C
#endif // PLATFORM_REALTEK

View File

@ -1,5 +1,9 @@
#ifdef PLATFORM_RTL87X0C
#ifdef PLATFORM_REALTEK
#include "../../new_common.h"
#include "../../logging/logging.h"
#include "../../new_cfg.h"
#include "../../new_pins.h"
#include <gpio_api.h>
#include "pwmout_api.h"
@ -12,4 +16,4 @@ typedef struct rtlPinMapping_s
pwmout_t* pwm;
} rtlPinMapping_t;
#endif // PLATFORM_RTL87X0C
#endif // PLATFORM_REALTEK

View File

@ -1,41 +1,14 @@
#ifdef PLATFORM_RTL87X0C
#ifdef PLATFORM_REALTEK
#include "../../new_common.h"
#include "../../logging/logging.h"
#include "../../new_cfg.h"
#include "../../new_pins.h"
#include "hal_generic_rtl87x0c.h"
#include "hal_generic_realtek.h"
extern int g_pwmFrequency;
rtlPinMapping_t g_pins[] = {
{ "PA0 (RX1)", PA_0, NULL, NULL },
{ "PA1 (TX1)", PA_1, NULL, NULL },
{ "PA2 (RX1)", PA_2, NULL, NULL },
{ "PA3 (TX1)", PA_3, NULL, NULL },
{ "PA4", PA_4, NULL, NULL },
{ "PA5", PA_5, NULL, NULL },
{ "PA6", PA_6, NULL, NULL },
{ "PA7", PA_7, NULL, NULL },
{ "PA8", PA_8, NULL, NULL },
{ "PA9", PA_9, NULL, NULL },
{ "PA10", PA_10, NULL, NULL },
{ "PA11", PA_11, NULL, NULL },
{ "PA12", PA_12, NULL, NULL },
{ "PA13 (RX0)", PA_13, NULL, NULL },
{ "PA14 (TX0)", PA_14, NULL, NULL },
{ "PA15 (RX2)", PA_15, NULL, NULL },
{ "PA16 (TX2)", PA_16, NULL, NULL },
{ "PA17", PA_17, NULL, NULL },
{ "PA18", PA_18, NULL, NULL },
{ "PA19", PA_19, NULL, NULL },
{ "PA20", PA_20, NULL, NULL },
{ "PA21", PA_21, NULL, NULL },
{ "PA22", PA_22, NULL, NULL },
{ "PA23", PA_23, NULL, NULL },
};
static int g_numPins = sizeof(g_pins) / sizeof(g_pins[0]);
extern rtlPinMapping_t g_pins[];
extern int g_numPins;
int PIN_GetPWMIndexForPinIndex(int pin)
{
@ -49,12 +22,6 @@ const char* HAL_PIN_GetPinNameAlias(int index)
return g_pins[index].name;
}
int HAL_PIN_CanThisPinBePWM(int index)
{
if(index > 6 && index < 11) return 0;
return 1;
}
void RTL_GPIO_Init(rtlPinMapping_t* pin)
{
if(pin->gpio != NULL || pin->irq != NULL)
@ -150,7 +117,7 @@ void HAL_PIN_PWM_Start(int index)
if(pin->pwm != NULL) return;
if(pin->gpio != NULL)
{
hal_pinmux_unregister(pin->pin, PID_GPIO);
gpio_deinit(pin->gpio);
os_free(pin->gpio);
pin->gpio = NULL;
}
@ -158,7 +125,9 @@ void HAL_PIN_PWM_Start(int index)
memset(pin->pwm, 0, sizeof(pwmout_t));
pwmout_init(pin->pwm, pin->pin);
pwmout_period_us(pin->pwm, g_pwmFrequency);
#ifndef PLATFORM_RTL8710A
pwmout_start(pin->pwm);
#endif
}
void HAL_PIN_PWM_Update(int index, float value)
@ -166,7 +135,11 @@ void HAL_PIN_PWM_Update(int index, float value)
if(index >= g_numPins || !HAL_PIN_CanThisPinBePWM(index))
return;
rtlPinMapping_t* pin = g_pins + index;
#ifdef PLATFORM_RTL87X0C
if(pin->pwm == NULL || !pin->pwm->is_init) return;
#elif PLATFORM_RTL8710B
if(pin->pwm == NULL) return;
#endif
pwmout_write(pin->pwm, value / 100);
}
@ -175,4 +148,4 @@ unsigned int HAL_GetGPIOPin(int index)
return index;
}
#endif // PLATFORM_RTL87X0C
#endif // PLATFORM_REALTEK

View File

@ -1,4 +1,4 @@
#ifdef PLATFORM_RTL87X0C
#ifdef PLATFORM_REALTEK
#include "../hal_wifi.h"
#include "../../new_cfg.h"
@ -212,7 +212,8 @@ void ConnectToWiFiTask(void* args)
break;
}
security_retry_count++;
if(security_retry_count >= 3)
delay_ms(50);
if(security_retry_count >= 5)
{
printf("Can't get AP security mode and channel.\r\n");
goto exit;
@ -233,7 +234,13 @@ void ConnectToWiFiTask(void* args)
LwIP_DHCP(0, DHCP_START);
}
if(wifi_is_up(RTW_STA_INTERFACE) && g_powersave) wifi_enable_powersave();
vTaskDelete(NULL);
return;
exit:
if(g_wifiStatusCallback != NULL)
{
g_wifiStatusCallback(WIFI_STA_DISCONNECTED);
}
vTaskDelete(NULL);
}
@ -247,14 +254,14 @@ void HAL_ConnectToWiFi(const char* oob_ssid, const char* connect_key, obkStaticI
strcpy((char*)&wdata.pwd, connect_key);
wifi_set_autoreconnect(0);
if (ip->localIPAddr[0] == 0) {
//dhcps_init(&xnetif[0]);
if (ip->localIPAddr[0] == 0)
{
//dhcps_init(&xnetif[0]);
g_bStaticIP = 0;
}
else {
// dhcps_deinit();
else
{
// dhcps_deinit();
g_bStaticIP = 1;
IP4_ADDR(ip_2_ip4(&ipaddr), ip->localIPAddr[0], ip->localIPAddr[1], ip->localIPAddr[2], ip->localIPAddr[3]);
@ -265,15 +272,12 @@ void HAL_ConnectToWiFi(const char* oob_ssid, const char* connect_key, obkStaticI
netif_set_hostname(&xnetif[0], CFG_GetDeviceName());
wifi_reg_event_handler(WIFI_EVENT_DISCONNECT, (rtw_event_handler_t)wifi_dis_hdl, NULL);
if (g_bStaticIP) {
if (g_bStaticIP)
{
// with static IP, assume that connect is enough?
wifi_reg_event_handler(WIFI_EVENT_CONNECT, (rtw_event_handler_t)wifi_conned_hdl, NULL);
}
else {
//wifi_reg_event_handler(WIFI_EVENT_CONNECT, (rtw_event_handler_t)wifi_con_hdl, NULL);
// GOT IP won't get called if DHCP is off
wifi_reg_event_handler(WIFI_EVENT_STA_GOT_IP, (rtw_event_handler_t)wifi_conned_hdl, NULL);
}
wifi_reg_event_handler(WIFI_EVENT_STA_GOT_IP, (rtw_event_handler_t)wifi_conned_hdl, NULL);
wifi_reg_event_handler(WIFI_EVENT_CHALLENGE_FAIL, (rtw_event_handler_t)wifi_af_hdl, NULL);
xTaskCreate(
@ -319,4 +323,4 @@ int HAL_SetupWiFiOpenAccessPoint(const char* ssid)
return 0;
}
#endif // PLATFORM_RTL87X0C
#endif // PLATFORM_REALTEK

View File

@ -0,0 +1,30 @@
#ifdef PLATFORM_RTL8710A
#include "../../hal_generic.h"
#include "sys_api.h"
extern int g_sleepfactor;
void HAL_RebootModule()
{
//sys_cpu_reset();
ota_platform_reset();
}
void HAL_Delay_us(int delay)
{
HalDelayUs(delay);
}
void HAL_Configure_WDT()
{
watchdog_init(10 * 1000);
watchdog_start();
}
void HAL_Run_WDT()
{
watchdog_refresh();
}
#endif // PLATFORM_RTL8710A

View File

@ -0,0 +1,81 @@
#ifdef PLATFORM_RTL8710A
#include "../hal_generic_realtek.h"
// commented out pins are those not wired out on RTL8711AM
rtlPinMapping_t g_pins[] = {
//{ "PA0", PA_0, NULL, NULL },
//{ "PA1", PA_1, NULL, NULL },
//{ "PA2", PA_2, NULL, NULL },
{ "PA3", PA_3, NULL, NULL },
{ "PA4", PA_4, NULL, NULL },
{ "PA5", PA_5, NULL, NULL },
{ "PA6", PA_6, NULL, NULL },
{ "PA7", PA_7, NULL, NULL },
{ "PB0 (L_TX)", PB_0, NULL, NULL },
{ "PB1 (L_RX)", PB_1, NULL, NULL },
{ "PB2", PB_2, NULL, NULL },
{ "PB3", PB_3, NULL, NULL },
//{ "PB4", PB_4, NULL, NULL },
//{ "PB5", PB_5, NULL, NULL },
//{ "PB6", PB_6, NULL, NULL },
//{ "PB7", PB_7, NULL, NULL },
{ "PC0", PC_0, NULL, NULL },
{ "PC1", PC_1, NULL, NULL },
{ "PC2", PC_2, NULL, NULL },
{ "PC3", PC_3, NULL, NULL },
{ "PC4", PC_4, NULL, NULL },
{ "PC5", PC_5, NULL, NULL },
//{ "PC6", PC_6, NULL, NULL },
//{ "PC7", PC_7, NULL, NULL },
//{ "PC8", PC_8, NULL, NULL },
//{ "PC9", PC_9, NULL, NULL },
//{ "PD0", PD_0, NULL, NULL },
//{ "PD1", PD_1, NULL, NULL },
//{ "PD2", PD_2, NULL, NULL },
//{ "PD3", PD_3, NULL, NULL },
//{ "PD4", PD_4, NULL, NULL },
//{ "PD5", PD_5, NULL, NULL },
//{ "PD6", PD_6, NULL, NULL },
//{ "PD7", PD_7, NULL, NULL },
//{ "PD8", PD_8, NULL, NULL },
//{ "PD9", PD_9, NULL, NULL },
{ "PE0 (JTAG)", PE_0, NULL, NULL }, // JTAG, cannot be used until sys_jtag_off()
{ "PE1 (JTAG)", PE_1, NULL, NULL }, // JTAG, cannot be used until sys_jtag_off()
{ "PE2 (JTAG)", PE_2, NULL, NULL }, // JTAG, cannot be used until sys_jtag_off()
{ "PE3 (JTAG)", PE_3, NULL, NULL }, // JTAG, cannot be used until sys_jtag_off()
{ "PE4 (JTAG)", PE_4, NULL, NULL }, // JTAG, cannot be used until sys_jtag_off()
//{ "PE5", PE_5, NULL, NULL },
//{ "PE6", PE_6, NULL, NULL },
//{ "PE7", PE_7, NULL, NULL },
//{ "PE8", PE_8, NULL, NULL },
//{ "PE9", PE_9, NULL, NULL },
};
int g_numPins = sizeof(g_pins) / sizeof(g_pins[0]);
int HAL_PIN_CanThisPinBePWM(int index)
{
if(index >= g_numPins)
return 0;
rtlPinMapping_t* pin = g_pins + index;
switch(pin->pin)
{
case PC_0:
case PC_1:
case PC_2:
case PC_3:
case PE_0:
case PE_1:
case PE_2:
case PE_3:
return 1;
default: return 0;
}
}
#endif // PLATFORM_RTL8710A

View File

@ -0,0 +1,50 @@
#ifdef PLATFORM_RTL8710A
#include "../../../new_pins.h"
#include "../../../new_cfg.h"
#include "../../hal_uart.h"
#include "serial_api.h"
#define UART0_TX PA_7
#define UART0_RX PA_6
serial_t sobj;
static bool isInitialized;
static void uart_cb(uint32_t id, SerialIrq event)
{
if(event != RxIrq)
return;
serial_t* obj = (void*)id;
uint8_t c = (uint8_t)serial_getc(obj);
UART_AppendByteToReceiveRingBuffer(c);
}
void HAL_UART_SendByte(byte b)
{
while(!serial_writable(&sobj));
serial_putc(&sobj, b);
}
int HAL_UART_Init(int baud, int parity)
{
if(isInitialized)
{
serial_free(&sobj);
}
PinName tx = UART0_TX, rx = UART0_RX;
//if(CFG_HasFlag(OBK_FLAG_USE_SECONDARY_UART))
//{
// tx = UART2_TX;
// rx = UART2_RX;
//}
serial_init(&sobj, tx, rx);
serial_baud(&sobj, baud);
serial_format(&sobj, 8, parity, 1);
serial_irq_handler(&sobj, uart_cb, (uint32_t)&sobj);
serial_irq_set(&sobj, RxIrq, 1);
isInitialized = true;
return 1;
}
#endif

View File

@ -0,0 +1,30 @@
#ifdef PLATFORM_RTL8710B
#include "../../hal_generic.h"
#include "sys_api.h"
extern int g_sleepfactor;
void HAL_RebootModule()
{
//sys_cpu_reset();
ota_platform_reset();
}
void HAL_Delay_us(int delay)
{
DelayUs(delay * g_sleepfactor);
}
void HAL_Configure_WDT()
{
watchdog_init(10 * 1000);
watchdog_start();
}
void HAL_Run_WDT()
{
watchdog_refresh();
}
#endif // PLATFORM_RTL8710B

View File

@ -0,0 +1,48 @@
#ifdef PLATFORM_RTL8710B
#include "../hal_generic_realtek.h"
rtlPinMapping_t g_pins[] = {
{ "PA0", PA_0, NULL, NULL },
{ "PA5", PA_5, NULL, NULL },
{ "PA6", PA_6, NULL, NULL },
{ "PA7", PA_7, NULL, NULL },
{ "PA8", PA_8, NULL, NULL },
{ "PA9", PA_9, NULL, NULL },
{ "PA10", PA_10, NULL, NULL },
{ "PA11", PA_11, NULL, NULL },
{ "PA12", PA_12, NULL, NULL },
{ "PA14", PA_14, NULL, NULL },
{ "PA15", PA_15, NULL, NULL },
{ "PA18 (RX0)", PA_18, NULL, NULL },
{ "PA19 (ADC1)",PA_19, NULL, NULL },
{ "PA22", PA_22, NULL, NULL },
{ "PA23 (TX0)", PA_23, NULL, NULL },
{ "PA29 (RX2)", PA_29, NULL, NULL },
{ "PA30 (TX2)", PA_30, NULL, NULL },
};
int g_numPins = sizeof(g_pins) / sizeof(g_pins[0]);
int HAL_PIN_CanThisPinBePWM(int index)
{
if(index >= g_numPins)
return 0;
rtlPinMapping_t* pin = g_pins + index;
switch(pin->pin)
{
case PA_0:
case PA_5:
case PA_12:
case PA_14:
case PA_15:
case PA_22:
case PA_23:
case PA_29:
case PA_30:
return 1;
default: return 0;
}
}
#endif // PLATFORM_RTL8710B

View File

@ -0,0 +1,53 @@
#ifdef PLATFORM_RTL8710B
#include "../../../new_pins.h"
#include "../../../new_cfg.h"
#include "../../hal_uart.h"
#include "serial_api.h"
#include "rtl8711b_uart.h"
#define UART0_TX PA_23
#define UART0_RX PA_18
#define UART2_TX PA_30
#define UART2_RX PA_29
serial_t sobj;
static bool isInitialized;
static void uart_cb(uint32_t id, SerialIrq event)
{
if(event != RxIrq)
return;
serial_t* obj = (void*)id;
uint8_t c = (uint8_t)serial_getc(obj);
UART_AppendByteToReceiveRingBuffer(c);
}
void HAL_UART_SendByte(byte b)
{
while(!serial_writable(&sobj));
serial_putc(&sobj, b);
}
int HAL_UART_Init(int baud, int parity)
{
if(isInitialized)
{
serial_free(&sobj);
}
PinName tx = UART0_TX, rx = UART0_RX;
//if(CFG_HasFlag(OBK_FLAG_USE_SECONDARY_UART))
//{
// tx = UART2_TX;
// rx = UART2_RX;
//}
serial_init(&sobj, tx, rx);
serial_baud(&sobj, baud);
serial_format(&sobj, 8, parity, 1);
serial_irq_handler(&sobj, uart_cb, (uint32_t)&sobj);
serial_irq_set(&sobj, RxIrq, 1);
isInitialized = true;
return 1;
}
#endif

View File

@ -1,6 +1,6 @@
#ifdef PLATFORM_RTL87X0C
#include "../hal_generic.h"
#include "../../hal_generic.h"
#include "sys_api.h"
#include "hal_timer.h"
#include "hal_wdt.h"

View File

@ -0,0 +1,40 @@
#ifdef PLATFORM_RTL87X0C
#include "../hal_generic_realtek.h"
rtlPinMapping_t g_pins[] = {
{ "PA0 (RX1)", PA_0, NULL, NULL },
{ "PA1 (TX1)", PA_1, NULL, NULL },
{ "PA2 (RX1)", PA_2, NULL, NULL },
{ "PA3 (TX1)", PA_3, NULL, NULL },
{ "PA4", PA_4, NULL, NULL },
{ "PA5", PA_5, NULL, NULL },
{ "PA6", PA_6, NULL, NULL },
{ "PA7", PA_7, NULL, NULL },
{ "PA8", PA_8, NULL, NULL },
{ "PA9", PA_9, NULL, NULL },
{ "PA10", PA_10, NULL, NULL },
{ "PA11", PA_11, NULL, NULL },
{ "PA12", PA_12, NULL, NULL },
{ "PA13 (RX0)", PA_13, NULL, NULL },
{ "PA14 (TX0)", PA_14, NULL, NULL },
{ "PA15 (RX2)", PA_15, NULL, NULL },
{ "PA16 (TX2)", PA_16, NULL, NULL },
{ "PA17", PA_17, NULL, NULL },
{ "PA18", PA_18, NULL, NULL },
{ "PA19", PA_19, NULL, NULL },
{ "PA20", PA_20, NULL, NULL },
{ "PA21", PA_21, NULL, NULL },
{ "PA22", PA_22, NULL, NULL },
{ "PA23", PA_23, NULL, NULL },
};
int g_numPins = sizeof(g_pins) / sizeof(g_pins[0]);
int HAL_PIN_CanThisPinBePWM(int index)
{
if(index > 6 && index < 11) return 0;
return 1;
}
#endif // PLATFORM_RTL87X0C

View File

@ -1,8 +1,8 @@
#ifdef PLATFORM_RTL87X0C
#include "../../new_pins.h"
#include "../../new_cfg.h"
#include "../hal_uart.h"
#include "../../../new_pins.h"
#include "../../../new_cfg.h"
#include "../../hal_uart.h"
#include "serial_api.h"
#include "hal_uart.h"
#define UART0_TX PA_14

View File

@ -44,10 +44,12 @@ static char SUBMIT_AND_END_FORM[] = "<br><input type=\"submit\" value=\"Submit\"
#include "hal_sys_ctrl.h"
extern hal_reset_reason_t reset_reason;
extern uint32_t current_fw_idx;
#elif defined(PLATFORM_RTL8710B)
extern uint32_t current_fw_idx;
#elif defined(PLATFORM_ESPIDF)
#include "esp_wifi.h"
#include "esp_system.h"
#else
#elif defined(PLATFORM_BK7231T)
// REALLY? A typo in Tuya SDK? Storge?
// tuya-iotos-embeded-sdk-wifi-ble-bk7231t/platforms/bk7231t/tuya_os_adapter/include/driver/tuya_hal_storge.h
#include "tuya_hal_storge.h"
@ -906,6 +908,8 @@ typedef enum {
}
hprintf255(request, "<h5>Reboot reason: %i - %s</h5>", reset_reason, s);
hprintf255(request, "<h5>Current fw: FW%i</h5>", current_fw_idx);
#elif PLATFORM_RTL8710B
hprintf255(request, "<h5>Current fw: FW%i</h5>", current_fw_idx + 1);
#endif
#if ENABLE_MQTT
if (CFG_GetMQTTHost()[0] == 0) {
@ -1346,8 +1350,8 @@ int http_fn_cfg_wifi(http_request_t* request) {
}
#elif PLATFORM_TR6260
poststr(request, "TODO TR6260<br>");
#elif defined(PLATFORM_RTL87X0C)
poststr(request, "TODO RTL87X0C<br>");
#elif defined(PLATFORM_REALTEK)
poststr(request, "TODO Realtek<br>");
#else
#error "Unknown platform"
poststr(request, "Unknown platform<br>");
@ -3010,6 +3014,7 @@ void OTA_RequestDownloadFromHTTP(const char* s) {
#elif PLATFORM_ESPIDF
#elif PLATFORM_TR6260
#elif PLATFORM_RTL87X0C
#elif PLATFORM_RTL8710B || PLATFORM_RTL8710A
#elif PLATFORM_W600 || PLATFORM_W800
t_http_fwup(s);
#elif PLATFORM_XR809

View File

@ -17,7 +17,7 @@ void HTTPServer_Start();
#define HTTP_SERVER_PORT 80
#define REPLY_BUFFER_SIZE 2048
#define INCOMING_BUFFER_SIZE 1024
#define INCOMING_BUFFER_SIZE 2048
#define INVALID_SOCK -1
#define HTTP_CLIENT_STACK_SIZE 8192
@ -74,8 +74,8 @@ static void tcp_client_thread(tcp_thread_t* arg)
{
break;
}
// grow by 1024
request.receivedLenmax += 1024;
// grow by INCOMING_BUFFER_SIZE
request.receivedLenmax += INCOMING_BUFFER_SIZE;
GLOBAL_INT_DISABLE();
request.received = (char*)realloc(request.received, request.receivedLenmax + 2);
GLOBAL_INT_RESTORE();

View File

@ -11,6 +11,8 @@
#include "../littlefs/our_lfs.h"
#include "lwip/sockets.h"
#define DEFAULT_FLASH_LEN 0x200000
#if PLATFORM_XR809
#include <image/flash.h>
@ -67,6 +69,28 @@ extern void sys_disable_fast_boot(void);
extern void get_fw_info(uint32_t* targetFWaddr, uint32_t* currentFWaddr, uint32_t* fw1_sn, uint32_t* fw2_sn);
static flash_t flash_ota;
#elif PLATFORM_RTL8710B
#include "flash_api.h"
#include "device_lock.h"
#include "sys_api.h"
#include "rtl8710b_ota.h"
extern flash_t flash;
extern uint32_t current_fw_idx;
#elif PLATFORM_RTL8710A
#include "flash_api.h"
#include "device_lock.h"
#include "sys_api.h"
extern flash_t flash;
extern uint32_t current_fw_idx;
#undef DEFAULT_FLASH_LEN
#define DEFAULT_FLASH_LEN 0x400000
#else
extern UINT32 flash_read(char* user_buf, UINT32 count, UINT32 address);
@ -267,7 +291,7 @@ static int http_rest_post(http_request_t* request) {
return http_rest_post_flash(request, -1, -1);
#elif PLATFORM_ESPIDF
return http_rest_post_flash(request, -1, -1);
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
return http_rest_post_flash(request, 0, -1);
#else
// TODO
@ -2207,6 +2231,367 @@ update_ota_exit:
if(buf) free(buf);
return http_rest_error(request, ret, "error");
}
#elif PLATFORM_RTL8710B
int NewImg2BlkSize = 0;
uint32_t NewFWLen = 0, NewFWAddr = 0;
uint32_t address = 0;
uint32_t flash_checksum = 0;
uint32_t ota2_addr = OTA2_ADDR;
union { uint32_t u; unsigned char c[4]; } file_checksum;
unsigned char sig_backup[32];
int ret = 1;
char* hbuf = NULL;
bool foundhdr = false;
if(request->contentLength > 0)
{
towrite = request->contentLength;
}
else
{
ret = -1;
ADDLOG_ERROR(LOG_FEATURE_OTA, "Content-length is 0");
goto update_ota_exit;
}
int ota1_len = 0, ota2_len = 0;
char* msg = "Incorrect amount of bytes received: %i, required: %i";
writebuf = request->received;
writelen = recv(request->fd, &ota1_len, sizeof(ota1_len), 0);
if(writelen != sizeof(ota1_len))
{
ADDLOG_ERROR(LOG_FEATURE_OTA, msg, writelen, sizeof(ota1_len));
ret = -1;
goto update_ota_exit;
}
writebuf = request->received;
writelen = recv(request->fd, &ota2_len, sizeof(ota2_len), 0);
if(writelen != sizeof(ota2_len))
{
ADDLOG_ERROR(LOG_FEATURE_OTA, msg, writelen, sizeof(ota2_len));
ret = -1;
goto update_ota_exit;
}
ADDLOG_INFO(LOG_FEATURE_OTA, "OTA1 len: %u, OTA2 len: %u", ota1_len, ota2_len);
if(ota1_len <= 0 || ota2_len <= 0)
{
ret = -1;
goto update_ota_exit;
}
towrite -= 8;
if(current_fw_idx == OTA_INDEX_1)
{
towrite = ota2_len;
// skip ota1
int toskip = ota1_len;
do
{
writebuf = request->received;
writelen = recv(request->fd, writebuf, request->receivedLenmax < toskip ? request->receivedLenmax : toskip, 0);
ADDLOG_EXTRADEBUG(LOG_FEATURE_OTA, "Skipping %i at %i", writelen, total);
total += writelen;
toskip -= writelen;
} while((toskip > 0) && (writelen >= 0));
ADDLOG_DEBUG(LOG_FEATURE_OTA, "Skipped %i bytes, towrite: %i", total, towrite);
}
else
{
towrite = ota1_len;
}
writelen = 0;
total = 0;
NewFWAddr = update_ota_prepare_addr();
ADDLOG_INFO(LOG_FEATURE_OTA, "OTA address: %#010x, len: %u", NewFWAddr - SPI_FLASH_BASE, towrite);
if(NewFWAddr == -1 || NewFWAddr == 0xFFFFFFFF)
{
ret = -1;
ADDLOG_ERROR(LOG_FEATURE_OTA, "Wrong OTA address:", NewFWAddr);
goto update_ota_exit;
}
NewFWLen = towrite;
if(NewFWAddr == OTA1_ADDR)
{
if(NewFWLen > (OTA2_ADDR - OTA1_ADDR))
{
// firmware size too large
ret = -1;
ADDLOG_ERROR(LOG_FEATURE_OTA, "image size should not cross OTA2");
goto update_ota_exit;
}
}
else if(NewFWAddr == OTA2_ADDR)
{
if(NewFWLen > (0x195000 + SPI_FLASH_BASE - OTA2_ADDR))
{
ret = -1;
ADDLOG_ERROR(LOG_FEATURE_OTA, "image size crosses OTA2 boundary");
goto update_ota_exit;
}
}
else if(NewFWAddr == 0xFFFFFFFF)
{
ret = -1;
ADDLOG_ERROR(LOG_FEATURE_OTA, "update address is invalid");
goto update_ota_exit;
}
address = NewFWAddr - SPI_FLASH_BASE;
NewImg2BlkSize = ((NewFWLen - 1) / 4096) + 1;
device_mutex_lock(RT_DEV_LOCK_FLASH);
for(int i = 0; i < NewImg2BlkSize; i++)
{
flash_erase_sector(&flash, address + i * 4096);
}
device_mutex_unlock(RT_DEV_LOCK_FLASH);
OTF_Mask(1, (address), NewImg2BlkSize, 1);
do
{
if(startaddr < 32)
{
memcpy(sig_backup + startaddr, writebuf, (startaddr + writelen > 32 ? (32 - startaddr) : writelen));
memset(writebuf, 0xFF, (startaddr + writelen > 32 ? (32 - startaddr) : writelen));
ADDLOG_DEBUG(LOG_FEATURE_OTA, "sig_backup for% d bytes from index% d", (startaddr + writelen > 32 ? (32 - startaddr) : writelen), startaddr);
}
device_mutex_lock(RT_DEV_LOCK_FLASH);
if(flash_burst_write(&flash, address + startaddr, writelen, (uint8_t*)writebuf) < 0)
{
ADDLOG_ERROR(LOG_FEATURE_OTA, "Write stream failed");
device_mutex_unlock(RT_DEV_LOCK_FLASH);
ret = -1;
goto update_ota_exit;
}
device_mutex_unlock(RT_DEV_LOCK_FLASH);
rtos_delay_milliseconds(10);
ADDLOG_DEBUG(LOG_FEATURE_OTA, "Writelen %i at %i", writelen, total);
total += writelen;
startaddr += writelen;
towrite -= writelen;
if(startaddr + writelen > NewFWLen - 4)
{
file_checksum.c[0] = writebuf[writelen - 4];
file_checksum.c[1] = writebuf[writelen - 3];
file_checksum.c[2] = writebuf[writelen - 2];
file_checksum.c[3] = writebuf[writelen - 1];
}
if(towrite > 0)
{
writebuf = request->received;
writelen = recv(request->fd, writebuf, request->receivedLenmax < towrite ? request->receivedLenmax : towrite, 0);
if(writelen < 0)
{
ADDLOG_DEBUG(LOG_FEATURE_OTA, "recv returned %d - end of data - remaining %d", writelen, towrite);
}
}
} while((towrite > 0) && (writelen >= 0));
uint8_t* buf = (uint8_t*)os_malloc(2048);
memset(buf, 0, 2048);
for(int i = 0; i < NewFWLen; i += 2048)
{
int k;
int rlen = (startaddr - 4 - i) > 2048 ? 2048 : (startaddr - 4 - i);
device_mutex_lock(RT_DEV_LOCK_FLASH);
flash_stream_read(&flash, address + i, rlen, buf);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
for(k = 0; k < rlen; k++)
{
if(i + k < 32)
{
flash_checksum += sig_backup[i + k];
}
else
{
flash_checksum += buf[k];
}
}
}
ADDLOG_INFO(LOG_FEATURE_OTA, "Update file size = %d flash checksum 0x%8x attached checksum 0x%8x", NewFWLen, flash_checksum, file_checksum.u);
OTF_Mask(1, (address), NewImg2BlkSize, 0);
if(file_checksum.u == flash_checksum)
{
ADDLOG_INFO(LOG_FEATURE_OTA, "Update OTA success!");
ret = 0;
}
else
{
/*if checksum error, clear the signature zone which has been
written in flash in case of boot from the wrong firmware*/
device_mutex_lock(RT_DEV_LOCK_FLASH);
flash_erase_sector(&flash, address);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
ret = -1;
}
// make it to be similar to rtl8720c - write signature only after success - to prevent boot failure if something goes wrong
if(flash_burst_write(&flash, address + 16, 16, sig_backup + 16) < 0)
{
ret = -1;
}
else
{
if(flash_burst_write(&flash, address, 16, sig_backup) < 0)
{
ret = -1;
}
}
if(current_fw_idx != OTA_INDEX_1)
{
// receive file fully
int toskip = ota2_len;
do
{
writebuf = request->received;
writelen = recv(request->fd, writebuf, request->receivedLenmax < toskip ? request->receivedLenmax : toskip, 0);
total += writelen;
toskip -= writelen;
} while((toskip > 0) && (writelen >= 0));
}
update_ota_exit:
if(ret != -1)
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
if(current_fw_idx == OTA_INDEX_1)
{
OTA_Change(OTA_INDEX_2);
//ota_write_ota2_addr(OTA2_ADDR);
}
else
{
OTA_Change(OTA_INDEX_1);
//ota_write_ota2_addr(0xffffffff);
}
device_mutex_unlock(RT_DEV_LOCK_FLASH);
if(buf) free(buf);
}
else
{
if(buf) free(buf);
ADDLOG_ERROR(LOG_FEATURE_OTA, "OTA failed");
return http_rest_error(request, ret, "error");
}
#elif PLATFORM_RTL8710A
uint32_t NewFWLen = 0, NewFWAddr = 0;
uint32_t address = 0;
uint32_t flash_checksum = 0;
union { uint32_t u; unsigned char c[4]; } file_checksum;
int ret = 0;
if(request->contentLength > 0)
{
towrite = request->contentLength;
}
else
{
ret = -1;
ADDLOG_ERROR(LOG_FEATURE_OTA, "Content-length is 0");
goto update_ota_exit;
}
NewFWAddr = update_ota_prepare_addr();
if(NewFWAddr == -1)
{
goto update_ota_exit;
}
int reserase = update_ota_erase_upg_region(towrite, 0, NewFWAddr);
NewFWLen = towrite;
if(reserase == -1)
{
ADDLOG_ERROR(LOG_FEATURE_OTA, "Erase failed");
ret = -1;
goto update_ota_exit;
}
address = NewFWAddr;
ADDLOG_INFO(LOG_FEATURE_OTA, "Start to read data %i bytes, flash address: 0x%8x", NewFWLen, address);
do
{
device_mutex_lock(RT_DEV_LOCK_FLASH);
if(flash_stream_write(&flash, address + startaddr, writelen, (uint8_t*)writebuf) < 0)
{
ADDLOG_ERROR(LOG_FEATURE_OTA, "Write stream failed");
device_mutex_unlock(RT_DEV_LOCK_FLASH);
ret = -1;
goto update_ota_exit;
}
device_mutex_unlock(RT_DEV_LOCK_FLASH);
rtos_delay_milliseconds(10);
ADDLOG_DEBUG(LOG_FEATURE_OTA, "Writelen %i at %i", writelen, total);
total += writelen;
startaddr += writelen;
towrite -= writelen;
// checksum attached at file end
if(startaddr + writelen > NewFWLen - 4)
{
file_checksum.c[0] = writebuf[writelen - 4];
file_checksum.c[1] = writebuf[writelen - 3];
file_checksum.c[2] = writebuf[writelen - 2];
file_checksum.c[3] = writebuf[writelen - 1];
}
if(towrite > 0)
{
writebuf = request->received;
writelen = recv(request->fd, writebuf, request->receivedLenmax, 0);
if(writelen < 0)
{
ADDLOG_DEBUG(LOG_FEATURE_OTA, "recv returned %d - end of data - remaining %d", writelen, towrite);
}
}
} while((towrite > 0) && (writelen >= 0));
ADDLOG_DEBUG(LOG_FEATURE_OTA, "%d total bytes written, verifying checksum %u", total, flash_checksum);
uint8_t* buf = (uint8_t*)os_malloc(512);
memset(buf, 0, 512);
// read flash data back and calculate checksum
for(int i = 0; i < NewFWLen; i += 512)
{
int k;
int rlen = (NewFWLen - 4 - i) > 512 ? 512 : (NewFWLen - 4 - i);
device_mutex_lock(RT_DEV_LOCK_FLASH);
flash_stream_read(&flash, NewFWAddr + i, rlen, buf);
device_mutex_unlock(RT_DEV_LOCK_FLASH);
for(k = 0; k < rlen; k++)
{
flash_checksum += buf[k];
}
}
ADDLOG_INFO(LOG_FEATURE_OTA, "flash checksum 0x%8x attached checksum 0x%8x", flash_checksum, file_checksum.u);
delay_ms(50);
ret = update_ota_checksum(&file_checksum, flash_checksum, NewFWAddr);
if(ret == -1)
{
ADDLOG_ERROR(LOG_FEATURE_OTA, "The checksum is wrong!");
goto update_ota_exit;
}
update_ota_exit:
if(ret != -1)
{
//device_mutex_lock(RT_DEV_LOCK_FLASH);
//device_mutex_unlock(RT_DEV_LOCK_FLASH);
if(buf) free(buf);
}
else
{
if(buf) free(buf);
ADDLOG_ERROR(LOG_FEATURE_OTA, "OTA failed");
return http_rest_error(request, ret, "error");
}
#else
init_ota(startaddr);
@ -2286,7 +2671,7 @@ static int http_rest_get_flash(http_request_t* request, int startaddr, int len)
char* buffer;
int res;
if (startaddr < 0 || (startaddr + len > 0x200000)) {
if (startaddr < 0 || (startaddr + len > DEFAULT_FLASH_LEN)) {
return http_rest_error(request, -1, "requested flash read out of range");
}
@ -2309,7 +2694,7 @@ static int http_rest_get_flash(http_request_t* request, int startaddr, int len)
#elif PLATFORM_LN882H || PLATFORM_ESPIDF || PLATFORM_TR6260
// TODO:LN882H flash read?
res = 0;
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
device_mutex_lock(RT_DEV_LOCK_FLASH);
flash_stream_read(&flash, startaddr, readlen, (uint8_t*)buffer);
device_mutex_unlock(RT_DEV_LOCK_FLASH);

View File

@ -9,7 +9,7 @@
#if PLATFORM_BEKEN
#include "mem_pub.h"
#elif PLATFORM_BL602 || PLATFORM_LN882H || PLATFORM_ESPIDF
#elif PLATFORM_BL602 || PLATFORM_LN882H || PLATFORM_ESPIDF || PLATFORM_RTL8710B
#define os_free free
#define os_malloc malloc
#endif

View File

@ -35,7 +35,7 @@
#include "esp_partition.h"
esp_partition_t* esplfs = NULL;
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
#include "flash_api.h"
#include "device_lock.h"
@ -729,7 +729,7 @@ static int lfs_erase(const struct lfs_config* c, lfs_block_t block)
return res;
}
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
extern flash_t flash;

View File

@ -80,6 +80,19 @@
#define LFS_BLOCKS_START_MIN 0x1D0000
#define LFS_BLOCKS_END LFS_BLOCKS_START + 0x20000
#elif PLATFORM_RTL8710B
#define LFS_BLOCKS_START 0x19D000
#define LFS_BLOCKS_START_MIN 0x19D000
#define LFS_BLOCKS_END 0x1E0000
#elif PLATFORM_RTL8710A
#define LFS_BLOCKS_START 0x300000
#define LFS_BLOCKS_START_MIN 0x300000
#define LFS_BLOCKS_END 0x380000
#else
// TODO
// start 0x1000 after OTA addr

View File

@ -1643,7 +1643,8 @@ static BENCHMARK_TEST_INFO* info = NULL;
#if WINDOWS
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_ESPIDF || PLATFORM_TR6260 || PLATFORM_RTL87X0C
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_ESPIDF || PLATFORM_TR6260 \
|| PLATFORM_REALTEK
static void mqtt_timer_thread(void* param)
{
while (1)
@ -1683,7 +1684,8 @@ commandResult_t MQTT_StartMQTTTestThread(const void* context, const char* cmd, c
#if WINDOWS
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_ESPIDF || PLATFORM_TR6260 || PLATFORM_RTL87X0C
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_ESPIDF || PLATFORM_TR6260 \
|| PLATFORM_REALTEK
xTaskCreate(mqtt_timer_thread, "mqtt", 1024, (void*)info, 15, NULL);
#elif PLATFORM_XR809 || PLATFORM_LN882H
OS_TimerSetInvalid(&timer);

View File

@ -110,6 +110,16 @@ typedef long BaseType_t;
#define DEVICENAME_PREFIX_SHORT "rtl87x0C"
#define PLATFORM_MCU_NAME "RTL87X0C"
#define MANUFACTURER "Realtek"
#elif PLATFORM_RTL8710B
#define DEVICENAME_PREFIX_FULL "OpenRTL8710B"
#define DEVICENAME_PREFIX_SHORT "rtl8710b"
#define PLATFORM_MCU_NAME "RTL8710B"
#define MANUFACTURER "Realtek"
#elif PLATFORM_RTL8710A
#define DEVICENAME_PREFIX_FULL "OpenRTL8710A"
#define DEVICENAME_PREFIX_SHORT "rtl8710a"
#define PLATFORM_MCU_NAME "RTL8710A"
#define MANUFACTURER "Realtek"
#else
#error "You must define a platform.."
This platform is not supported, error!
@ -141,6 +151,8 @@ This platform is not supported, error!
#define USER_SW_VER "TR6260_Test"
#elif defined(PLATFORM_RTL87X0C)
#define USER_SW_VER "RTL87X0C_Test"
#elif defined(PLATFORM_RTL8710B)
#define USER_SW_VER "RTL8710B_Test"
#else
#define USER_SW_VER "unknown"
#endif
@ -500,7 +512,7 @@ OSStatus rtos_suspend_thread(beken_thread_t* thread);
#define GLOBAL_INT_DISABLE() ;
#define GLOBAL_INT_RESTORE() ;
#elif PLATFORM_RTL87X0C
#elif PLATFORM_REALTEK
#include <stdbool.h>
#include "FreeRTOS.h"
@ -517,6 +529,7 @@ OSStatus rtos_suspend_thread(beken_thread_t* thread);
#include "cmsis_os.h"
typedef unsigned int UINT32;
extern int g_sleepfactor;
#undef ASSERT
#define ASSERT
@ -528,9 +541,17 @@ typedef unsigned int UINT32;
#define bk_printf printf
// OS_MSleep?
#if PLATFORM_RTL8710B || PLATFORM_RTL8710A
#define atoi __wrap_atoi
#endif
#if PLATFORM_RTL8710B
#define rtos_delay_milliseconds(x) vTaskDelay(x / portTICK_PERIOD_MS / g_sleepfactor)
#define delay_ms(x) vTaskDelay(x / portTICK_PERIOD_MS / g_sleepfactor)
#else
#define rtos_delay_milliseconds(x) vTaskDelay(x / portTICK_PERIOD_MS)
#define delay_ms(x) vTaskDelay(x / portTICK_PERIOD_MS)
#endif
#define kNoErr 0 //! No error occurred.
typedef void* beken_thread_arg_t;
@ -681,7 +702,7 @@ typedef enum
EXCELLENT,
} WIFI_RSSI_LEVEL;
#if PLATFORM_LN882H || PLATFORM_RTL87X0C
#if PLATFORM_LN882H || PLATFORM_REALTEK
#define IP_STRING_FORMAT "%u.%u.%u.%u"
#else
#define IP_STRING_FORMAT "%hhu.%hhu.%hhu.%hhu"

View File

@ -1027,6 +1027,10 @@ typedef enum channelType_e {
#define PLATFORM_GPIO_MAX 25
#elif PLATFORM_RTL87X0C
#define PLATFORM_GPIO_MAX 24
#elif PLATFORM_RTL8710B
#define PLATFORM_GPIO_MAX 17
#elif PLATFORM_RTL8710A
#define PLATFORM_GPIO_MAX 20
#else
#define PLATFORM_GPIO_MAX 29
#endif

View File

@ -320,8 +320,37 @@
#define ENABLE_DRIVER_BL0942 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_CSE7766 1
#define ENABLE_OBK_SCRIPTING 1
#define ENABLE_ADVANCED_CHANNELTYPES_DISCOVERY 1
#define OBK_OTA_EXTENSION ".img"
#define ENABLE_OBK_SCRIPTING 1
#elif PLATFORM_RTL8710B || PLATFORM_RTL8710A
#define ENABLE_HA_DISCOVERY 1
#define ENABLE_MQTT 1
#define NO_CHIP_TEMPERATURE 1
#define ENABLE_LITTLEFS 1
#define NEW_TCP_SERVER 1
#define ENABLE_DRIVER_TUYAMCU 1
#define ENABLE_TASMOTADEVICEGROUPS 1
#define ENABLE_NTP 1
#define ENABLE_CALENDAR_EVENTS 1
#define ENABLE_EXPAND_CONSTANT 1
#define ENABLE_TASMOTA_JSON 1
#define ENABLE_I2C 1
#define ENABLE_DRIVER_AHT2X 1
#define ENABLE_DRIVER_BMPI2C 1
#define ENABLE_DRIVER_DS1820 1
#define ENABLE_DRIVER_LED 1
#define ENABLE_DRIVER_WEMO 1
#define ENABLE_DRIVER_CHT83XX 1
#define ENABLE_DRIVER_DHT 1
#define ENABLE_DRIVER_BL0942 1
#define ENABLE_DRIVER_BL0937 1
#define ENABLE_DRIVER_CSE7766 1
#define ENABLE_DRIVER_UART_TCP 1
#define OBK_OTA_EXTENSION ".img"
#define ENABLE_OBK_SCRIPTING 1
#else

View File

@ -213,7 +213,8 @@ int LWIP_GetActiveSockets() {
}
#endif
#if defined(PLATFORM_BL602) || defined(PLATFORM_W800) || defined(PLATFORM_W600) || defined(PLATFORM_LN882H) || defined(PLATFORM_ESPIDF) || defined(PLATFORM_TR6260) || defined(PLATFORM_RTL87X0C)
#if defined(PLATFORM_BL602) || defined(PLATFORM_W800) || defined(PLATFORM_W600) || defined(PLATFORM_LN882H) \
|| defined(PLATFORM_ESPIDF) || defined(PLATFORM_TR6260) || defined(PLATFORM_REALTEK)
OSStatus rtos_create_thread(beken_thread_t* thread,
uint8_t priority, const char* name,
@ -957,7 +958,6 @@ void QuickTick(void* param)
}
g_last_time = g_time;
#if ENABLE_OBK_SCRIPTING
SVM_RunThreads(g_deltaTimeMS);
#endif
@ -1013,7 +1013,7 @@ void QuickTick(void* param)
// this is the bit which runs the quick tick timer
#if WINDOWS
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_RTL87X0C)
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_REALTEK)
void quick_timer_thread(void* param)
{
while (1) {
@ -1032,8 +1032,7 @@ void QuickTick_StartThread(void)
{
#if WINDOWS
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_RTL87X0C)
#elif PLATFORM_BL602 || PLATFORM_W600 || PLATFORM_W800 || PLATFORM_TR6260 || defined(PLATFORM_REALTEK)
xTaskCreate(quick_timer_thread, "quick", 1024, NULL, 15, NULL);
#elif PLATFORM_ESPIDF
const esp_timer_create_args_t g_quick_timer_args =