Added OTA.

Signed-off-by: Dmytro Kosmii <dmytro.kosmii@telink-semi.com>
This commit is contained in:
Dmytro Kosmii
2022-06-16 00:11:34 +03:00
parent 6f153a8aa3
commit b43d1d0d38
16 changed files with 1431 additions and 0 deletions
+2
View File
@@ -72,6 +72,7 @@ _attribute_ram_code_ int32_t gpio_handler(uint16_t gpio, void *data)
void AppMain(void)
{
#if 0
UINT32 ret;
UINT32 taskId = 0;
TSK_INIT_PARAM_S taskParam = {0};
@@ -101,6 +102,7 @@ void AppMain(void)
GpioSetIrq(SW1_3_GPIO_HDF, GPIO_IRQ_TRIGGER_RISING, gpio_handler, NULL);
GpioEnableIrq(SW1_3_GPIO_HDF);
#endif /* TELINK_GPIO_IRQ_SAMPLE_ENABLE */
#endif
}
SYS_RUN(AppMain);
+28
View File
@@ -0,0 +1,28 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//device/soc/telink/util/util.gni")
b91_firmware("ota_demo") {
explicit_libs = [
"bootstrap",
"broadcast",
]
deps = [
"//build/lite:ohos",
"ota_demo",
]
}
+59
View File
@@ -0,0 +1,59 @@
{
"product_name": "ota_demo",
"ohos_version": "OpenHarmony 3.x",
"device_company": "telink",
"board": "b91_devkit",
"kernel_type": "liteos_m",
"kernel_version": "3.0.0",
"subsystems": [
{
"subsystem": "kernel",
"components": [
{ "component": "liteos_m", "features": [] }
]
},
{
"subsystem": "startup",
"components": [
{ "component": "bootstrap_lite", "features":[] }
]
},
{
"subsystem": "distributedschedule",
"components": [
{ "component": "samgr_lite", "features":[] }
]
},
{
"subsystem": "hiviewdfx",
"components": [
{ "component": "hilog_lite", "features":[] },
{ "component": "hievent_lite", "features":[] }
]
},
{
"subsystem": "update",
"components": [
{ "component": "hota", "features": [
"ohos_security_huks_mbedtls_porting_path = \"//device/soc/telink/b91/adapter/hals/mbedtls\""
]
}
]
},
{
"subsystem": "utils",
"components": [
{ "component": "file", "features":[] },
{
"component": "kv_store",
"features": [
"enable_ohos_utils_native_lite_kv_store_use_posix_kv_api = false"
]
}
]
}
],
"third_party_dir": "//third_party",
"vendor_adapter_dir": "//device/soc/telink/b91/adapter",
"product_adapter_dir": "//vendor/telink/led_demo/hals"
}
+27
View File
@@ -0,0 +1,27 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
static_library("hal_sysparam") {
sources = [ "hal_sys_param.c" ]
include_dirs = [ "//base/startup/syspara_lite/hals" ]
defines = [
"INCREMENTAL_VERSION=\"${ohos_version}\"",
"BUILD_TYPE=\"${ohos_build_type}\"",
"BUILD_USER=\"${ohos_build_user}\"",
"BUILD_TIME=\"${ohos_build_time}\"",
"BUILD_HOST=\"${ohos_build_host}\"",
"BUILD_ROOTHASH=\"${ohos_build_roothash}\"",
]
}
+129
View File
@@ -0,0 +1,129 @@
/******************************************************************************
* Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include "hal_sys_param.h"
static const char OHOS_DEVICE_TYPE[] = {"Evaluation Board"};
static const char OHOS_DISPLAY_VERSION[] = {"OpenHarmony 3.x"};
static const char OHOS_MANUFACTURE[] = {"Telink"};
static const char OHOS_BRAND[] = {"Telink"};
static const char OHOS_MARKET_NAME[] = {"B91 Generic Starter Kit"};
static const char OHOS_PRODUCT_SERIES[] = {"TLSR9"};
static const char OHOS_PRODUCT_MODEL[] = {"v1.0.0"};
static const char OHOS_SOFTWARE_MODEL[] = {"v1.0.0"};
static const char OHOS_HARDWARE_MODEL[] = {"v1.3"};
static const char OHOS_HARDWARE_PROFILE[] = {"BLE:true"};
static const char OHOS_BOOTLOADER_VERSION[] = {"bootloader"};
static const char OHOS_ABI_LIST[] = {"default"};
static const char OHOS_SERIAL[] = {"1234567890"};
static const int OHOS_FIRST_API_VERSION = 1;
const char *HalGetDeviceType(void)
{
return OHOS_DEVICE_TYPE;
}
const char *HalGetManufacture(void)
{
return OHOS_MANUFACTURE;
}
const char *HalGetBrand(void)
{
return OHOS_BRAND;
}
const char *HalGetMarketName(void)
{
return OHOS_MARKET_NAME;
}
const char *HalGetProductSeries(void)
{
return OHOS_PRODUCT_SERIES;
}
const char *HalGetProductModel(void)
{
return OHOS_PRODUCT_MODEL;
}
const char *HalGetSoftwareModel(void)
{
return OHOS_SOFTWARE_MODEL;
}
const char *HalGetHardwareModel(void)
{
return OHOS_HARDWARE_MODEL;
}
const char *HalGetHardwareProfile(void)
{
return OHOS_HARDWARE_PROFILE;
}
const char *HalGetSerial(void)
{
return OHOS_SERIAL;
}
const char *HalGetBootloaderVersion(void)
{
return OHOS_BOOTLOADER_VERSION;
}
const char *HalGetAbiList(void)
{
return OHOS_ABI_LIST;
}
const char *HalGetDisplayVersion(void)
{
return OHOS_DISPLAY_VERSION;
}
const char *HalGetIncrementalVersion(void)
{
return INCREMENTAL_VERSION;
}
const char *HalGetBuildType(void)
{
return BUILD_TYPE;
}
const char *HalGetBuildUser(void)
{
return BUILD_USER;
}
const char *HalGetBuildHost(void)
{
return BUILD_HOST;
}
const char *HalGetBuildTime(void)
{
return BUILD_TIME;
}
int HalGetFirstApiVersion(void)
{
return OHOS_FIRST_API_VERSION;
}
+24
View File
@@ -0,0 +1,24 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
static_library("hal_token_static") {
sources = [ "hal_token.c" ]
include_dirs = [
"//base/startup/syspara_lite/hals",
"//utils/native/lite/include",
]
deps = []
}
+107
View File
@@ -0,0 +1,107 @@
/******************************************************************************
* Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include "hal_token.h"
#include "ohos_errno.h"
#include "ohos_types.h"
static int OEMReadToken(char *token, unsigned int len)
{
// OEM need add here, read token from device
(void)(token);
(void)(len);
return EC_SUCCESS;
}
static int OEMWriteToken(const char *token, unsigned int len)
{
// OEM need add here, write token to device
(void)(token);
(void)(len);
return EC_SUCCESS;
}
static int OEMGetAcKey(char *acKey, unsigned int len)
{
// OEM need add here, get AcKey
(void)(acKey);
(void)(len);
return EC_SUCCESS;
}
static int OEMGetProdId(char *productId, unsigned int len)
{
// OEM need add here, get ProdId
(void)(productId);
(void)(len);
return EC_SUCCESS;
}
static int OEMGetProdKey(char *productKey, unsigned int len)
{
// OEM need add here, get ProdKey
(void)(productKey);
(void)(len);
return EC_SUCCESS;
}
int HalReadToken(char *token, unsigned int len)
{
if (token == NULL) {
return EC_FAILURE;
}
return OEMReadToken(token, len);
}
int HalWriteToken(const char *token, unsigned int len)
{
if (token == NULL) {
return EC_FAILURE;
}
return OEMWriteToken(token, len);
}
int HalGetAcKey(char *acKey, unsigned int len)
{
if (acKey == NULL) {
return EC_FAILURE;
}
return OEMGetAcKey(acKey, len);
}
int HalGetProdId(char *productId, unsigned int len)
{
if (productId == NULL) {
return EC_FAILURE;
}
return OEMGetProdId(productId, len);
}
int HalGetProdKey(char *productKey, unsigned int len)
{
if (productKey == NULL) {
return EC_FAILURE;
}
return OEMGetProdKey(productKey, len);
}
+25
View File
@@ -0,0 +1,25 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//drivers/adapter/khdf/liteos_m/hdf.gni")
module_name = "hdf_hcs"
hdf_driver(module_name) {
hcs_sources = [ "hdf.hcs" ]
visibility += [
"$device_path",
".",
]
}
+1
View File
@@ -0,0 +1 @@
#include "../../../device/soc/telink/b91/hcs/hdf.hcs"
+9
View File
@@ -0,0 +1,9 @@
LOSCFG_PLATFORM_QEMU_RISCV32_VIRT=y
LOSCFG_SOC_SERIES_B91=y
LOSCFG_FS_LITTLEFS=y
LOSCFG_DRIVERS_HDF=y
LOSCFG_DRIVERS_HDF_PLATFORM=y
LOSCFG_DRIVERS_HDF_PLATFORM_GPIO=y
#LOSCFG_CC_NO_STACKPROTECTOR=y
LOSCFG_COMPILE_OPTIMIZE_SIZE=n
#LOSCFG_COMPILE_OPTIMIZE=n
+6
View File
@@ -0,0 +1,6 @@
LOSCFG_PLATFORM_QEMU_RISCV32_VIRT=y
LOSCFG_SOC_SERIES_B91=y
LOSCFG_FS_LITTLEFS=y
LOSCFG_DRIVERS_HDF=y
LOSCFG_DRIVERS_HDF_PLATFORM=y
LOSCFG_DRIVERS_HDF_PLATFORM_GPIO=y
+10
View File
@@ -0,0 +1,10 @@
{
"parts": {
"product_ota_demo": {
"module_list": [
"//vendor/telink/ota_demo:ota_demo"
]
}
},
"subsystem": "product_ota_demo"
}
+65
View File
@@ -0,0 +1,65 @@
# Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
# All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import("//drivers/adapter/khdf/liteos_m/hdf.gni")
declare_args() {
telink_gpio_irq_sample_enable = false
}
config("myapp_config") {
include_dirs = [
"//utils/native/lite/include",
"//base/update/ota_lite/interfaces/kits",
"//base/update/ota_lite/frameworks/source/verify",
"$ohos_third_party_dir/mbedtls/include",
]
configs = [
"//device/soc/telink/b91:B91_config",
]
}
source_set("myapp_inner") {
sources = [
"app.c",
"serial.c",
]
deps = [
"//base/hiviewdfx/hiview_lite",
"//base/update/ota_lite/frameworks:ota_lite",
]
if (!defined(defines)) {
defines = []
}
if (telink_gpio_irq_sample_enable) {
defines += [ "TELINK_GPIO_IRQ_SAMPLE_ENABLE=1" ]
} else {
defines += [ "TELINK_GPIO_IRQ_SAMPLE_ENABLE=0" ]
}
configs += [ ":myapp_config" ]
}
static_library("ota_demo") {
deps = [
":myapp_inner",
]
configs += [ ":myapp_config" ]
}
+630
View File
@@ -0,0 +1,630 @@
/******************************************************************************
* Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <los_arch_interrupt.h>
#include <los_task.h>
#include <hota_updater.h>
#include <ohos_init.h>
#include <ohos_types.h>
#include <hiview_log.h>
#include <app_sha256.h>
#include <hota_verify.h>
#include <mbedtls/entropy.h>
#include <mbedtls/pk.h>
#include <board_config.h>
#include <B91/flash.h>
#include <B91/uart.h>
#include "serial.h"
#define OTA_UART_TASK_PRIO 7
#define SOH 0x01
#define STX 0x02
#define EOT 0x04
#define ACK 0x06
#define NAK 0x15
#define CAN 0x18
#define CTRLZ 0x1A
#define DLY_1S 1000
#define MAXRETRANS 25
#define XMODEM_BUF_SIZE 1024
typedef enum {
COMMAND_TYPE_ERROR_TIMEOUT = -1,
COMMAND_TYPE_ERROR_PREAMBLE = -2,
COMMAND_TYPE_ERROR_WRONG_COMMAND = -3,
COMMAND_TYPE_ERROR_WRONG_ARGS = -4,
COMMAND_TYPE_UPLOAD = 0,
COMMAND_TYPE_PRINT = 1,
COMMAND_TYPE_CANCEL = 2,
COMMAND_TYPE_ERASE = 3,
COMMAND_TYPE_HASH_SHA256 = 4,
COMMAND_TYPE_RESTART = 5,
COMMAND_TYPE_ROLLBACK = 6,
COMMAND_TYPE_DEBUG = 7,
COMMAND_TYPE_SIGN = 8,
} CommandType;
unsigned short crc16_ccitt(const unsigned char *buf, int len)
{
unsigned short crc = 0;
while (len--) {
int i;
crc ^= *(char *)buf++ << 8;
for (i = 0; i < 8; ++i) {
if (crc & 0x8000) {
crc = (crc << 1) ^ 0x1021;
} else {
crc = crc << 1;
}
}
}
return crc;
}
static int check(bool is_crc, const unsigned char *buf, int sz)
{
if (is_crc) {
unsigned short crc = crc16_ccitt(buf, sz);
unsigned short tcrc = (buf[sz] << 8) + buf[sz + 1];
if (crc == tcrc) {
return 1;
}
} else {
int i;
unsigned char cks = 0;
for (i = 0; i < sz; ++i) {
cks += buf[i];
}
if (cks == buf[sz]) {
return 1;
}
}
return 0;
}
static int _inbyte(unsigned short timeout_ms)
{
int c = uart_read(LOS_MS2Tick(timeout_ms));
return c;
}
STATIC int read_with_echo(UINT32 timeout_ms)
{
int c = uart_read(LOS_MS2Tick(timeout_ms));
if (c > 0) {
if (0x7f == c) {
uart_send_byte(UART1, 0x08);
uart_send_byte(UART1, ' ');
c = 0x08;
}
uart_send_byte(UART1, (unsigned char)c);
}
return c;
}
static void _outbyte(int c)
{
uart_send_byte(UART1, (unsigned char)c);
}
static void flushinput(void)
{
while (_inbyte(((DLY_1S)*3) >> 1) >= 0) {
}
}
typedef void (*XModemReceiveCB)(uint8_t *buf, size_t addr, size_t len, void *arg);
int xmodemReceive(unsigned char *xbuff, int destsz, XModemReceiveCB cb, void *arg)
{
unsigned char *p;
int bufsz, crc = 0;
unsigned char trychar = 'C';
unsigned char packetno = 1;
int c, len = 0;
int retry, retrans = MAXRETRANS;
for (;;) {
for (retry = 0; retry < 16; ++retry) {
if (trychar) {
_outbyte(trychar);
}
if ((c = _inbyte((DLY_1S) << 1)) >= 0) {
switch (c) {
case SOH: {
bufsz = 128;
goto start_recv;
}
case STX: {
bufsz = 1024;
goto start_recv;
}
case EOT: {
flushinput();
_outbyte(ACK);
return len; /* normal end */
}
case CAN: {
if ((c = _inbyte(DLY_1S)) == CAN) {
flushinput();
_outbyte(ACK);
return -1; /* canceled by remote */
}
break;
}
default: {
break;
}
}
}
}
if (trychar == 'C') {
trychar = NAK;
continue;
}
flushinput();
_outbyte(CAN);
_outbyte(CAN);
_outbyte(CAN);
return -2; /* sync error */
start_recv:
if (trychar == 'C') {
crc = 1;
}
trychar = 0;
p = xbuff;
*p++ = c;
INT32 to_read = (bufsz + (crc ? 1 : 0) + 3);
INT32 nread = uart_read_buf(LOS_MS2Tick(DLY_1S * 10), p, to_read);
if (nread < to_read) {
printf(" === %s:%d to_read: %d nread: %d\r\n", __func__, __LINE__, to_read, nread);
goto reject;
}
if (xbuff[1] == (unsigned char)(~xbuff[2]) &&
(xbuff[1] == packetno || xbuff[1] == (unsigned char)packetno - 1) && check(crc, &xbuff[3], bufsz)) {
if (xbuff[1] == packetno) {
int count = destsz - len;
if (count > bufsz) {
count = bufsz;
}
if (count > 0) {
cb(&xbuff[3], len, count, arg);
len += count;
}
++packetno;
retrans = MAXRETRANS + 1;
}
if (--retrans <= 0) {
flushinput();
_outbyte(CAN);
_outbyte(CAN);
_outbyte(CAN);
return -3; /* too many retry error */
}
_outbyte(ACK);
continue;
}
reject:
flushinput();
_outbyte(NAK);
}
}
STATIC ptrdiff_t ReadLine(char *buf, size_t bufLen)
{
ptrdiff_t i;
for (i = 0; i < bufLen;) {
char c;
if ((c = read_with_echo(5000)) < 0) {
return COMMAND_TYPE_ERROR_TIMEOUT;
}
if ('\r' == c) {
continue;
}
if ('\n' == c) {
break;
}
if ((0x08 == c)) {
if (i > 0) {
buf[--i] = '\0';
}
continue;
}
buf[i++] = c;
}
return i;
}
STATIC CommandType CommandProcess(UINT32 *arg1, UINT32 *arg2)
{
int c;
if ((c = read_with_echo(LOS_WAIT_FOREVER)) < 0) {
return COMMAND_TYPE_ERROR_TIMEOUT;
}
if ('{' != c) {
return COMMAND_TYPE_ERROR_PREAMBLE;
}
if ((c = read_with_echo(5000)) < 0) {
return COMMAND_TYPE_ERROR_TIMEOUT;
}
CommandType cmd;
switch (c) {
case 'u': {
cmd = COMMAND_TYPE_UPLOAD;
break;
}
case 'p': {
cmd = COMMAND_TYPE_PRINT;
break;
}
case 'c': {
cmd = COMMAND_TYPE_CANCEL;
break;
}
case 'h': {
cmd = COMMAND_TYPE_HASH_SHA256;
break;
}
case 'r': {
cmd = COMMAND_TYPE_RESTART;
break;
}
case 'b': {
cmd = COMMAND_TYPE_ROLLBACK;
break;
}
case 'd': {
cmd = COMMAND_TYPE_DEBUG;
break;
}
case 's': {
cmd = COMMAND_TYPE_SIGN;
return cmd;
}
default: {
return COMMAND_TYPE_ERROR_WRONG_COMMAND;
}
}
char buf[32] = {0};
ptrdiff_t res = ReadLine(buf, sizeof(buf));
if (res < 0) {
return res;
}
*arg1 = UINT32_MAX;
*arg2 = UINT32_MAX;
if ((COMMAND_TYPE_UPLOAD == cmd) || (COMMAND_TYPE_PRINT == cmd) || (COMMAND_TYPE_HASH_SHA256 == cmd)) {
char *p;
errno = ENOERR;
*arg1 = strtoul(buf, &p, 10);
if (((0 == *arg1) || (ULONG_MAX == *arg1)) && (ENOERR != errno)) {
printf(" === %s:%d errno: %d\r\n", __func__, __LINE__, errno);
return COMMAND_TYPE_ERROR_WRONG_ARGS;
}
*arg2 = strtoul(p, &p, 10);
if (((0 == *arg2) || (ULONG_MAX == *arg2)) && (ENOERR != errno)) {
printf(" === %s:%d errno: %d\r\n", __func__, __LINE__, errno);
*arg2 = UINT32_MAX;
}
} else if (COMMAND_TYPE_CANCEL == cmd) {
if (0 != strcmp("ancel", buf)) {
return COMMAND_TYPE_ERROR_WRONG_COMMAND;
}
} else if (COMMAND_TYPE_RESTART == cmd) {
if (0 != strcmp("estart", buf)) {
return COMMAND_TYPE_ERROR_WRONG_COMMAND;
}
} else if (COMMAND_TYPE_ROLLBACK == cmd) {
if (0 != strcmp("ack", buf)) {
return COMMAND_TYPE_ERROR_WRONG_COMMAND;
}
} else if (COMMAND_TYPE_DEBUG == cmd) {
c = buf[0];
if (c != 'm' && c != 'f') {
return COMMAND_TYPE_ERROR_WRONG_COMMAND;
}
char *p;
errno = ENOERR;
UINT32 addr = strtoul(buf + 1, &p, 10);
if (((0 == addr) || (ULONG_MAX == addr)) && (ENOERR != errno)) {
printf(" === %s:%d errno: %d\r\n", __func__, __LINE__, errno);
return COMMAND_TYPE_ERROR_WRONG_ARGS;
}
UINT32 sz = strtoul(p, &p, 10);
if (((0 == sz) || (ULONG_MAX == sz)) && (ENOERR != errno)) {
printf(" === %s:%d errno: %d\r\n", __func__, __LINE__, errno);
sz = 1;
}
if (c == 'm') {
p = (const char *)addr;
} else if (c == 'f') {
p = malloc(sz);
flash_read_page(addr, sz, p);
}
printf("Debug(%c): ", c);
for (size_t i = 0; i < sz; ++i) {
printf("%02x", p[i]);
}
printf("\r\n");
if (c == 'f') {
free(p);
}
} else if (COMMAND_TYPE_SIGN == cmd) {
if (0 != strcmp("ign", buf)) {
return COMMAND_TYPE_ERROR_WRONG_COMMAND;
}
}
return cmd;
}
void OtaErrorCallBack(HotaErrorCode errorCode)
{
printf(" === %s:%d errorCode: %d\r\n", __func__, __LINE__, errorCode);
}
void OtaStatusCallBack(HotaStatus status)
{
printf(" === %s:%d status: %d\r\n", __func__, __LINE__, status);
}
typedef struct {
int sz, start;
AppSha256Context sha256;
} xmodemReceiveCBArg;
void xmodemReceiveCB(uint8_t *buf, size_t addr, size_t len, void *_arg)
{
xmodemReceiveCBArg *arg = _arg;
int to_print = len;
if (to_print > 0) {
printf("Received[%d %d %u %d]: \"", arg->sz, arg->start, addr, to_print);
printf("\"\r\n");
AppSha256Update(&arg->sha256, buf, len);
unsigned int offset = (unsigned)(arg->start > 0 ? arg->start : 0) + addr;
HotaWrite(buf, offset, len);
}
}
STATIC ptrdiff_t ReadSign(UINT8 *sign, unsigned len)
{
char buf[32];
size_t nbytes = 0;
while (nbytes < len) {
ptrdiff_t res = ReadLine(buf, sizeof(buf));
if (res < 0) {
return res;
}
if (nbytes + (res / 2) > len) {
return -1;
}
for (size_t i = 0; i < res; i += 2) {
char hex[3] = {buf[i], buf[i + 1], '\0'};
errno = ENOERR;
UINT32 num = strtoul(hex, NULL, 16);
if (((0 == num) || (ULONG_MAX == num)) && (ENOERR != errno)) {
printf(" === %s:%d errno: %d \"%s\"\r\n", __func__, __LINE__, errno, hex);
return -1;
}
sign[nbytes++] = num;
}
if (res < sizeof(buf)) {
break;
}
}
return nbytes;
}
STATIC VOID OTA_TestThread(VOID)
{
printf(" === %s:%d\r\n", __func__, __LINE__);
SerialInit();
unsigned char *workBuf = malloc(XMODEM_BUF_SIZE + 6); /* 6 bytes XModem overhead */
uint8_t hash[32];
while (1) {
int sz, sz2;
CommandType cmd = CommandProcess((UINT32 *)&sz, (UINT32 *)&sz2);
printf(" === %s:%d cmd: %d sz: %d sz2: %d\r\n", __func__, __LINE__, cmd, sz, sz2);
int res = 0;
if (COMMAND_TYPE_UPLOAD == cmd) {
xmodemReceiveCBArg arg = {sz, sz2, {0}};
AppSha256Init(&arg.sha256);
res = xmodemReceive(workBuf, sz, xmodemReceiveCB, &arg);
AppSha256Finish(&arg.sha256, hash);
printf("sha256: ");
for (size_t i = 0; i < sizeof(hash); ++i) {
printf("%02x", hash[i]);
}
printf("\r\n");
} else if (COMMAND_TYPE_PRINT == cmd) {
unsigned start = sz; // & ~0xFF; //(sz / 256) * 256;
unsigned bufLen = (unsigned)(sz2 >= 0 ? sz2 : 256);
for (unsigned offset = 0, next = XMODEM_BUF_SIZE; next < bufLen; offset = next, next += XMODEM_BUF_SIZE) {
if (OHOS_SUCCESS == HotaRead(start + offset, XMODEM_BUF_SIZE, workBuf)) {
}
printf("Read[%u %u %u %u]: {", start, start + offset, XMODEM_BUF_SIZE, bufLen);
for (size_t i = 0; i < XMODEM_BUF_SIZE; ++i) {
printf("%02x", workBuf[i]);
}
printf("}\r\n");
}
unsigned rem = bufLen % XMODEM_BUF_SIZE;
if (0 != rem) {
if (OHOS_SUCCESS == HotaRead(start + bufLen - rem, rem, workBuf)) {
}
printf("Read[%u %u %u %u]: {", start, start + bufLen - rem, rem, bufLen);
for (size_t i = 0; i < rem; ++i) {
printf("%02x", workBuf[i]);
}
printf("}\r\n");
}
} else if (COMMAND_TYPE_HASH_SHA256 == cmd) {
unsigned start = sz;
unsigned bufLen = (unsigned)(sz2 >= 0 ? sz2 : 256);
uint8_t hashLocal[32];
AppSha256Context sha256;
AppSha256Init(&sha256);
for (unsigned offset = 0, next = XMODEM_BUF_SIZE; next < bufLen; offset = next, next += XMODEM_BUF_SIZE) {
if (OHOS_SUCCESS == HotaRead(start + offset, XMODEM_BUF_SIZE, workBuf)) {
}
AppSha256Update(&sha256, workBuf, XMODEM_BUF_SIZE);
}
unsigned rem = bufLen % XMODEM_BUF_SIZE;
if (0 != rem) {
if (OHOS_SUCCESS == HotaRead(start + bufLen - rem, rem, workBuf)) {
}
AppSha256Update(&sha256, workBuf, rem);
}
AppSha256Finish(&sha256, hashLocal);
printf("sha256: ");
for (size_t i = 0; i < sizeof(hashLocal); ++i) {
printf("%02x", hashLocal[i]);
}
printf("\r\n");
} else if (COMMAND_TYPE_SIGN == cmd) {
UINT8 sign[128];
ptrdiff_t len = ReadSign(sign, sizeof(sign));
if (len < 0) {
printf(" === ERROR %s:%d res: %d\r\n", __func__, __LINE__, len);
} else {
mbedtls_pk_context context;
uint32 length = 0;
mbedtls_pk_init(&context);
uint8 *keyBuf = HotaGetPubKey(&length);
if (keyBuf == NULL) {
printf("Get key fail\r\n");
}
int32 parseRet = mbedtls_pk_parse_public_key(&context, keyBuf, length);
if (parseRet != 0) {
printf("Parse public key failed.\r\n");
} else {
int ret;
mbedtls_entropy_context entropy;
mbedtls_rsa_set_padding(mbedtls_pk_rsa(context), MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256);
mbedtls_entropy_init(&entropy);
if ((ret = mbedtls_rsa_pkcs1_verify(mbedtls_pk_rsa(context), NULL, NULL, MBEDTLS_RSA_PUBLIC,
MBEDTLS_MD_SHA256, sizeof(hash), hash, sign)) != 0) {
printf("Sign check fail!\r\n");
} else {
printf("Sign check success!\r\n");
}
mbedtls_pk_free(&context);
}
}
} else if (COMMAND_TYPE_CANCEL == cmd) {
HotaCancel();
(VOID) HotaInit(OtaErrorCallBack, OtaStatusCallBack);
(VOID) HotaSetPackageType(NOT_USE_DEFAULT_PKG);
} else if (COMMAND_TYPE_RESTART == cmd) {
int ret = HotaRestart();
printf("HotaRestart() = %d\r\n", ret);
} else if (COMMAND_TYPE_ROLLBACK == cmd) {
int HotaHalRollback(void);
int ret = HotaHalRollback();
printf("HotaHalRollback() = %d\r\n", ret);
}
printf(" === %s:%d res: %d\r\n", __func__, __LINE__, res);
}
free(workBuf);
}
VOID OtaUartTestInit(VOID)
{
(VOID) HotaInit(OtaErrorCallBack, OtaStatusCallBack);
(VOID) HotaSetPackageType(NOT_USE_DEFAULT_PKG);
UINT32 ret = LOS_OK;
unsigned int task_id;
TSK_INIT_PARAM_S task_param = {0};
task_param.pfnTaskEntry = (TSK_ENTRY_FUNC)OTA_TestThread;
task_param.uwStackSize = 1024 * 16;
task_param.pcName = "OTA_TestThread";
task_param.usTaskPrio = OTA_UART_TASK_PRIO;
ret = LOS_TaskCreate(&task_id, &task_param);
if (ret != LOS_OK) {
printf("Create Task failed! ERROR: 0x%x\r\n", ret);
}
}
void AppMain(void)
{
printf("%s %s\r\n", __DATE__, __TIME__);
printf("%s: %p\r\n", __func__, AppMain);
OtaUartTestInit();
}
SYS_RUN(AppMain);
+280
View File
@@ -0,0 +1,280 @@
/******************************************************************************
* Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <los_event.h>
#include <los_mux.h>
#include <los_interrupt.h>
#include <B91/clock.h>
#include <B91/plic.h>
#include <B91/uart.h>
#include <b91_irq.h>
#include "serial.h"
#define SERVICE_UART_PORT UART1
#define SERVICE_UART_PIN_TX UART1_TX_PE0
#define SERVICE_UART_PIN_RX UART1_RX_PE2
#define SERVICE_UART_PARITY UART_PARITY_NONE
#define SERVICE_UART_STOP_BITS UART_STOP_BIT_ONE
#define SERVICE_UART_BAUDRATE 115200
#define UARTS_COUNT 2
#define UART_RX_BUF 256
#define NON_VALID_MUTEX_ID UINT32_MAX
//#define NUM_HAL_INTERRUPT_UART (RISCV_INTERRUPT__PLATFORM_USE + IRQ19_UART0)
/**
* TX:
* - Any interface functions are thread-safe after kernel started and @c uart_init is called.
* - If buffer is enabled then data are stored in buffer and sent on background using @c UartIdleThreadHandler.
* - Considering that Idle thread will capture mutex, all threads that want put data to buffer will wait while Idle
* thread will send data to UART. To prevent it, there is mechanism of preemption. Threads that indend to put data
* to buffer signalize about it using @c threadWait variable and Idle function will exit after next byte printed.
*
* RX:
* LiteOS Queue has very huge overhead for byte buffer where access is performed byte by byte. LiteOS Ringbuf
* doesn't support blocking when no data available. So there is implemented simple ring buffer using Spinlock for
* thread-safety and Event for data waiting.
*/
static struct {
struct {
struct {
UINT32 mux;
#if LOSCFG_UART_BUFFERED_TX_BUFFER_ENABLE
size_t start;
size_t end;
#if UART_TX_THREAD_PREEMTION_ENABLE
bool threadWait;
#endif /* ENABLE_UART_THREAD_PREEMTION */
#endif /* LOSCFG_UART_BUFFERED_TX_BUFFER_ENABLE */
} tx;
struct {
size_t start;
size_t end;
EVENT_CB_S event;
struct {
UINT8 *ptr;
INT32 nbytes;
INT32 max;
} irq_buf;
} rx;
} dev[UARTS_COUNT];
bool init;
} g_uartState = {
.dev[0 ...(UARTS_COUNT - 1)] =
{
.tx =
{
.mux = NON_VALID_MUTEX_ID,
#if LOSCFG_UART_BUFFERED_TX_BUFFER_ENABLE
.start = 0,
.end = 0,
#if UART_TX_THREAD_PREEMTION_ENABLE
.threadWait = false,
#endif /* ENABLE_UART_THREAD_PREEMTION */
#endif /* LOSCFG_UART_BUFFERED_TX_BUFFER_ENABLE */
},
.rx =
{
.start = 0,
.end = 0,
},
},
.init = false,
};
__attribute__((unused)) static struct {
#if LOSCFG_UART_BUFFERED_TX_BUFFER_ENABLE
CHAR tx[UART_TX_BUF];
#endif /* LOSCFG_UART_BUFFERED_TX_BUFFER_ENABLE */
CHAR rx[UART_RX_BUF];
} g_uartBuf[UARTS_COUNT];
VOID VendorUartInit(UINT32 uartNum, UINT32 baudrate);
STATIC_INLINE VOID VendorUartSendByte(UINT32 uartNum, UINT8 txData)
{
uart_send_byte(uartNum, txData);
}
/**
* @brief This function serves to send data by byte with not DMA method. Returns immediately.
* @param[in] uart_num - UART0 or UART1.
* @param[in] tx_data - the data to be send.
* @return @c true - if data is sent successfully, @c false - if fifo is full
*/
static inline bool uart_send_byte_nonblock(uart_num_e uart_num, unsigned char tx_data)
{
if (uart_get_txfifo_num(uart_num) > 7) {
return false;
}
unsigned char index = uart_tx_byte_index[uart_num];
reg_uart_data_buf(uart_num, index) = tx_data;
index = (index + 1) & 0x03;
uart_tx_byte_index[uart_num] = index;
return true;
}
STATIC INLINE bool VendorUartSendByteNonBlock(UINT32 uartNum, UINT8 txData)
{
return uart_send_byte_nonblock(uartNum, txData);
}
STATIC INLINE char VendorUartGetChar(UINT32 uartNum)
{
return (char)uart_read_byte(uartNum);
}
STATIC INLINE void VendorUartTxIrqEnable(UINT32 uartNum, bool state)
{
if (state) {
uart_set_irq_mask(uartNum, UART_TX_IRQ_MASK);
} else {
uart_clr_irq_mask(uartNum, UART_TX_IRQ_MASK);
}
}
STATIC INLINE void VendorUartRxIrqEnable(UINT32 uartNum, bool state)
{
if (state) {
uart_set_irq_mask(uartNum, UART_RX_IRQ_MASK);
} else {
uart_clr_irq_mask(uartNum, UART_RX_IRQ_MASK);
}
}
INT32 uart_read(UINT32 timeOut)
{
UINT32 intSave;
INT32 rec = 0;
intSave = LOS_IntLock();
/* Spinlock disables interrupts. So it should be unlocked while waiting for data.
* Data availability check is looped because another thread can consume data before Spinlock will be locked again.
*/
while (g_uartState.dev[SERVICE_UART_PORT].rx.start == g_uartState.dev[SERVICE_UART_PORT].rx.end) {
LOS_IntRestore(intSave);
UINT32 ret = LOS_EventRead(&g_uartState.dev[SERVICE_UART_PORT].rx.event, 1, LOS_WAITMODE_OR | LOS_WAITMODE_CLR,
timeOut);
if (0 != (ret & LOS_ERRTYPE_ERROR)) {
return -1;
}
intSave = LOS_IntLock();
}
rec = (UINT8)g_uartBuf[SERVICE_UART_PORT].rx[g_uartState.dev[SERVICE_UART_PORT].rx.start];
g_uartState.dev[SERVICE_UART_PORT].rx.start = (g_uartState.dev[SERVICE_UART_PORT].rx.start + 1) % UART_RX_BUF;
LOS_IntRestore(intSave);
return rec;
}
INT32 uart_read_buf(UINT32 timeOut, UINT8 *buf, INT32 max)
{
UINT32 intSave;
INT32 nbytes = 0;
intSave = LOS_IntLock();
while ((nbytes < max) &&
(g_uartState.dev[SERVICE_UART_PORT].rx.start != g_uartState.dev[SERVICE_UART_PORT].rx.end)) {
buf[nbytes++] = (UINT8)g_uartBuf[SERVICE_UART_PORT].rx[g_uartState.dev[SERVICE_UART_PORT].rx.start];
g_uartState.dev[SERVICE_UART_PORT].rx.start = (g_uartState.dev[SERVICE_UART_PORT].rx.start + 1) % UART_RX_BUF;
}
if ((nbytes < max) && (0 != timeOut)) {
g_uartState.dev->rx.irq_buf.ptr = buf;
g_uartState.dev->rx.irq_buf.nbytes = nbytes;
g_uartState.dev->rx.irq_buf.max = max;
LOS_EventClear(&g_uartState.dev[SERVICE_UART_PORT].rx.event, ~1);
LOS_IntRestore(intSave);
LOS_EventRead(&g_uartState.dev[SERVICE_UART_PORT].rx.event, 1, LOS_WAITMODE_OR | LOS_WAITMODE_CLR, timeOut);
intSave = LOS_IntLock();
nbytes = g_uartState.dev->rx.irq_buf.nbytes;
g_uartState.dev->rx.irq_buf.ptr = NULL;
g_uartState.dev->rx.irq_buf.nbytes = 0;
g_uartState.dev->rx.irq_buf.max = 0;
}
LOS_IntRestore(intSave);
return nbytes;
}
STATIC UINT8 uart_getc_unsafe(uart_num_e uartNum)
{
UINT8 c = VendorUartGetChar(uartNum);
size_t nextEnd = (g_uartState.dev[uartNum].rx.end + 1) % UART_RX_BUF;
if (nextEnd != g_uartState.dev[uartNum].rx.start) {
g_uartBuf[uartNum].rx[g_uartState.dev[uartNum].rx.end] = c;
g_uartState.dev[uartNum].rx.end = nextEnd;
LOS_EventWrite(&g_uartState.dev[uartNum].rx.event, 1);
}
return c;
}
STATIC VOID UartIrqHandler(void *arg)
{
uart_num_e uartNum = (uart_num_e)arg;
while (uart_get_rxfifo_num(uartNum) > 0) {
if (NULL != g_uartState.dev->rx.irq_buf.ptr) {
UINT8 c = VendorUartGetChar(uartNum);
g_uartState.dev->rx.irq_buf.ptr[g_uartState.dev->rx.irq_buf.nbytes++] = c;
if (g_uartState.dev->rx.irq_buf.nbytes >= g_uartState.dev->rx.irq_buf.max) {
g_uartState.dev->rx.irq_buf.ptr = NULL;
LOS_EventWrite(&g_uartState.dev[uartNum].rx.event, 1);
}
} else {
(VOID) uart_getc_unsafe(uartNum);
}
}
}
void SerialInit(void)
{
LOS_EventInit(&g_uartState.dev[SERVICE_UART_PORT].rx.event);
unsigned short div;
unsigned char bwpc;
uart_set_pin(SERVICE_UART_PIN_TX, SERVICE_UART_PIN_RX);
uart_reset(SERVICE_UART_PORT);
uart_cal_div_and_bwpc(SERVICE_UART_BAUDRATE, sys_clk.pclk * 1000 * 1000, &div, &bwpc);
telink_b91_uart_init(SERVICE_UART_PORT, div, bwpc, SERVICE_UART_PARITY, SERVICE_UART_STOP_BITS);
uart_rx_irq_trig_level(SERVICE_UART_PORT, 1);
uart_tx_irq_trig_level(SERVICE_UART_PORT, 0);
B91IrqRegister(IRQ18_UART1, UartIrqHandler, SERVICE_UART_PORT);
plic_interrupt_enable(IRQ18_UART1);
VendorUartRxIrqEnable(SERVICE_UART_PORT, true);
}
+29
View File
@@ -0,0 +1,29 @@
/******************************************************************************
* Copyright (c) 2022 Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#ifndef SERIAL_H
#define SERIAL_H
#include <los_compiler.h>
void SerialInit(void);
INT32 uart_read(UINT32 timeOut);
INT32 uart_read_buf(UINT32 timeOut, UINT8 *buf, INT32 max);
#endif // SERIAL_H