diff --git a/components/ble/blecontroller/lib/libblecontroller_702_m0s1p.a b/components/ble/blecontroller/lib/libblecontroller_702_m0s1p.a new file mode 100644 index 00000000..785fd49c Binary files /dev/null and b/components/ble/blecontroller/lib/libblecontroller_702_m0s1p.a differ diff --git a/examples/ble/bl702_flash_ble_pds.ld b/examples/ble/bl702_flash_ble_pds.ld new file mode 100644 index 00000000..57436062 --- /dev/null +++ b/examples/ble/bl702_flash_ble_pds.ld @@ -0,0 +1,272 @@ +/**************************************************************************************** +* @file bl702_flash_pds.ld +* +* @brief This file is the map file (gnuarm or armgcc). +* +* Copyright (C) BouffaloLab 2021 +* +**************************************************************************************** +*/ + +/* configure the CPU type */ +OUTPUT_ARCH( "riscv" ) +/* link with the standard c library */ +/* INPUT(-lc) */ +/* link with the standard GCC library */ +/* INPUT(-lgcc) */ +/* configure the entry point */ +ENTRY(_enter) + +StackSize = 0x1000; /* 4KB */ +HeapSize = 0x800; /* 2KB */ +__EM_SIZE = DEFINED(ble_controller_init) ? 8K : 0K; + +MEMORY +{ + xip_memory (rx) : ORIGIN = 0x23000000, LENGTH = 1024K + itcm_memory (rx) : ORIGIN = 0x22014000, LENGTH = 16K + dtcm_memory (rx) : ORIGIN = 0x42018000, LENGTH = 32K + ram_memory (!rx) : ORIGIN = 0x42020000, LENGTH = 20K /* OCRAM_1*/ + ram1_memory (!rx) : ORIGIN = 0x42025000, LENGTH = 4K + rsvd_memory (!rx) : ORIGIN = 0x42026000, LENGTH = 16K /*OCRAM_2*/ + ram2_memory (!rx) : ORIGIN = 0x4202A000, LENGTH = (24K - __EM_SIZE) /*OCRAM_3*/ + hbn_memory (rx) : ORIGIN = 0x40010000, LENGTH = 0xE00 +} + +SECTIONS +{ + PROVIDE(__metal_chicken_bit = 0); + + .text : + { + . = ALIGN(4); + __text_code_start__ = .; + + KEEP (*(.text.metal.init.enter)) + KEEP (*(SORT_NONE(.init))) + /* section information for shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + + /* section information for usb desc */ + . = ALIGN(4); + _usb_desc_start = .; + KEEP(*(usb_desc)) + . = ALIGN(4); + _usb_desc_end = .; + + *(.text) + *(.text.*) + + /*put .rodata**/ + *(EXCLUDE_FILE( *bl702_glb*.o* \ + *bl702_pds*.o* \ + *bl702_common*.o* \ + *bl702_sf_cfg*.o* \ + *bl702_sf_cfg_ext*.o* \ + *bl702_sf_ctrl*.o* \ + *bl702_sflash*.o* \ + *bl702_sflash_ext*.o* \ + *bl702_xip_sflash*.o* \ + *bl702_xip_sflash_ext*.o* \ + *bl702_ef_ctrl*.o*) .rodata*) + + *(.rodata) + *(.rodata.*) + + *(.srodata) + *(.srodata.*) + + _bt_gatt_service_static_list_start = .; + KEEP(*(SORT_BY_NAME("._bt_gatt_service_static.static.*"))) + _bt_gatt_service_static_list_end = .; + _bt_l2cap_fixed_chan_list_start = .; + KEEP(*(SORT_BY_NAME("._bt_l2cap_fixed_chan.static.*"))) + _bt_l2cap_fixed_chan_list_end = .; + + . = ALIGN(4); + __text_code_end__ = .; + } > xip_memory + + . = ALIGN(4); + __itcm_load_addr = .; + + .itcm_region : AT (__itcm_load_addr) + { + . = ALIGN(4); + __tcm_code_start__ = .; + + *(.tcm_code.*) + *(.tcm_const.*) + *(.sclock_rlt_code.*) + *(.sclock_rlt_const.*) + + *bl702_glb*.o*(.rodata*) + *bl702_pds*.o*(.rodata*) + *bl702_common*.o*(.rodata*) + *bl702_sf_cfg*.o*(.rodata*) + *bl702_sf_cfg_ext*.o*(.rodata*) + *bl702_sf_ctrl*.o*(.rodata*) + *bl702_sflash*.o*(.rodata*) + *bl702_sflash_ext*.o*(.rodata*) + *bl702_xip_sflash*.o*(.rodata*) + *bl702_xip_sflash_ext*.o*(.rodata*) + *bl702_ef_ctrl*.o*(.rodata*) + + . = ALIGN(4); + __tcm_code_end__ = .; + } > itcm_memory + + __hbn_load_addr = __itcm_load_addr + SIZEOF(.itcm_region); + + .hbn_ram_region : AT (__hbn_load_addr) + { + . = ALIGN(4); + __hbn_ram_start__ = .; + *bl702_hbn_wakeup*.o*(.rodata*) + *(.hbn_ram_code*) + *(.hbn_ram_data) + . = ALIGN(4); + __hbn_ram_end__ = .; + } > hbn_memory + + __dtcm_load_addr = __hbn_load_addr + SIZEOF(.hbn_ram_region); + + .dtcm_region : AT (__dtcm_load_addr) + { + . = ALIGN(4); + __tcm_data_start__ = .; + + *(.tcm_data) + /* *finger_print.o(.data*) */ + + . = ALIGN(4); + __tcm_data_end__ = .; + } > dtcm_memory + + + + __system_ram_load_addr = __dtcm_load_addr + SIZEOF(.dtcm_region); + + .system_ram_data_region : AT (__system_ram_load_addr) + { + . = ALIGN(4); + __system_ram_data_start__ = .; + + *(.system_ram) + *hal_pm_util*.o*(.rodata*) + *(.pds_ram_code*) + *(.pds_ram_data) + . = ALIGN(4); + __system_ram_data_end__ = .; + } > ram_memory + + __ram_load_addr = __system_ram_load_addr + SIZEOF(.system_ram_data_region); + + /* Data section */ + RAM_DATA : AT (__ram_load_addr) + { + . = ALIGN(4); + __ram_data_start__ = .; + + PROVIDE( __global_pointer$ = . + 0x800 ); + + *(.data) + *(.data.*) + *(.sdata) + *(.sdata.*) + *(.sdata2) + *(.sdata2.*) + + . = ALIGN(4); + __ram_data_end__ = .; + } > ram_memory + + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start__ = .; + + *(.bss*) + *(.sbss*) + *(COMMON) + + . = ALIGN(4); + __bss_end__ = .; + } > ram_memory + + .noinit_data (NOLOAD) : + { + . = ALIGN(4); + __noinit_data_start__ = .; + + *(.noinit_data*) + + . = ALIGN(4); + __noinit_data_end__ = .; + } > ram_memory + + /*************************************************************************/ + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (NOLOAD): + { + . = ALIGN(0x4); + . = . + StackSize; + . = ALIGN(0x4); + } > ram_memory + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(ram_memory) + LENGTH(ram_memory); + PROVIDE( __freertos_irq_stack_top = __StackTop); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __noinit_data_end__, "region RAM overflowed with stack") + + + + /*************************************************************************/ + .heap (NOLOAD): + { + . = ALIGN(8); + __HeapBase = .; + + /*__end__ = .;*/ + /*end = __end__;*/ + KEEP(*(.heap*)) + + . = ALIGN(8); + . = . + HeapSize; + . = ALIGN(8); + __HeapLimit = .; + + } > ram_memory + + /*__HeapBase = __noinit_data_end__; + __HeapLimit = ORIGIN(ram_memory) + LENGTH(ram_memory) - StackSize; + */ + /* + PROVIDE( _heap_start = . ); + PROVIDE( _heap_size = ORIGIN(ram_memory) + LENGTH(ram_memory) - _heap_start ); + */ + PROVIDE( _heap_start = ORIGIN(ram1_memory) ); + PROVIDE( _heap_size = LENGTH(ram1_memory) ); + + PROVIDE( _heap2_start = ORIGIN(ram2_memory) ); + PROVIDE( _heap2_size = LENGTH(ram2_memory) ); + + + /* PDS backup address */ + PROVIDE ( __ld_pds_bak_addr = 0x40010E00 ); +} + diff --git a/examples/ble/ble_pds/CMakeLists.txt b/examples/ble/ble_pds/CMakeLists.txt new file mode 100644 index 00000000..76065381 --- /dev/null +++ b/examples/ble/ble_pds/CMakeLists.txt @@ -0,0 +1,8 @@ +set(BSP_COMMON_DIR ${CMAKE_SOURCE_DIR}/bsp/bsp_common) +set(TARGET_REQUIRED_SRCS ${CMAKE_CURRENT_LIST_DIR}/ble_peripheral_tp_server.c) +set(TARGET_REQUIRED_LIBS freertos ble mbedtls) +set(mains main.c) +set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/examples/ble/bl702_flash_ble_pds.ld) +generate_bin() + + diff --git a/examples/ble/ble_pds/ble_peripheral_tp_server.c b/examples/ble/ble_pds/ble_peripheral_tp_server.c new file mode 100644 index 00000000..a6e8cb0d --- /dev/null +++ b/examples/ble/ble_pds/ble_peripheral_tp_server.c @@ -0,0 +1,361 @@ +/**************************************************************************** +FILE NAME + ble_peripheral_tp_server.c + +DESCRIPTION + test profile demo + +NOTES +*/ +/****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "bluetooth.h" +#include "conn.h" +#include "gatt.h" +#include "hci_core.h" +#include "uuid.h" +#include "ble_peripheral_tp_server.h" +#include "log.h" + + +#define BLE_CONN_PDS 0 +extern bool pds_start; + +static void ble_tp_connected(struct bt_conn *conn, u8_t err); +static void ble_tp_disconnected(struct bt_conn *conn, u8_t reason); +static void ble_param_updated(struct bt_conn *conn, u16_t interval,u16_t latency, u16_t timeout); + + +static struct bt_conn *ble_tp_conn; +#if !defined(CONFIG_BT_OAD_SERVER) +static struct bt_gatt_exchange_params exchg_mtu; +#endif +static TaskHandle_t ble_tp_task_h; + +static struct k_sem notify_poll_sem; + +static int tx_mtu_size = 20; +static u8_t created_tp_task = 0; +static u8_t isRegister = 0; + +static struct bt_conn_cb ble_tp_conn_callbacks = { + .connected = ble_tp_connected, + .disconnected = ble_tp_disconnected, + .le_param_updated = ble_param_updated, +}; + +#if !defined(CONFIG_BT_OAD_SERVER) +/************************************************************************* +NAME + ble_tp_tx_mtu_size +*/ +static void ble_tp_tx_mtu_size(struct bt_conn *conn, u8_t err, + struct bt_gatt_exchange_params *params) +{ + if (!err) { + tx_mtu_size = bt_gatt_get_mtu(ble_tp_conn); + BT_WARN("ble tp echange mtu size success, mtu size: %d", tx_mtu_size); + } else { + BT_WARN("ble tp echange mtu size failure, err: %d", err); + } +} +#endif +/************************************************************************* +NAME + ble_tp_connected +*/ +static void ble_tp_connected(struct bt_conn *conn, u8_t err) +{ + #if !defined(CONFIG_BT_OAD_SERVER) + int tx_octets = 0x00fb; + int tx_time = 0x0848; + int ret = -1; + #endif + + #if (BLE_CONN_PDS) + struct bt_le_conn_param param; + #endif + + if (err) { + return; + } + + BT_WARN("Tp connected"); + ble_tp_conn = conn; + pds_start = false; + + #if (BLE_CONN_PDS) + param.interval_min = param.interval_max = 0x320; + param.latency = 0; + param.timeout = 0x05dc; + ret = bt_conn_le_param_update(ble_tp_conn, ¶m); + if (ret) + { + BT_WARN("conn update failed (err %d)\r\n", ret); + } + else + { + BT_WARN("conn update initiated\r\n"); + } + #endif + + #if !defined(CONFIG_BT_OAD_SERVER) + //set data length after connected. + ret = bt_le_set_data_len(ble_tp_conn, tx_octets, tx_time); + + if (!ret) { + BT_WARN("ble tp set data length success"); + } else { + BT_WARN("ble tp set data length failure, err: %d", ret); + } + + //exchange mtu size after connected. + exchg_mtu.func = ble_tp_tx_mtu_size; + ret = bt_gatt_exchange_mtu(ble_tp_conn, &exchg_mtu); + + if (!ret) { + BT_WARN("ble tp exchange mtu size pending"); + } else { + BT_WARN("ble tp exchange mtu size failure, err: %d", ret); + } + #endif + +} + +/************************************************************************* +NAME + ble_tp_disconnected +*/ +static void ble_tp_disconnected(struct bt_conn *conn, u8_t reason) +{ + BT_WARN("Tp disconnected"); + + if (created_tp_task) { + BT_WARN("Delete throughput tx task"); + vTaskDelete(ble_tp_task_h); + created_tp_task = 0; + } + + ble_tp_conn = NULL; +} + +/************************************************************************* +NAME + ble_param_updated +*/ + +static void ble_param_updated(struct bt_conn *conn, u16_t interval, + u16_t latency, u16_t timeout) +{ + BT_WARN("LE conn param updated: int 0x%04x lat %d to %d \r\n", interval, latency, timeout); + #if (BLE_CONN_PDS) + if( interval > 80) + { + pds_start = true; + } + else + { + pds_start = false; + + } + #endif + +} + +/************************************************************************* +NAME + ble_tp_recv_rd +*/ +static int ble_tp_recv_rd(struct bt_conn *conn, const struct bt_gatt_attr *attr, + void *buf, u16_t len, u16_t offset) +{ + int size = 9; + char data[9] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; + + memcpy(buf, data, size); + + return size; +} + +/************************************************************************* +NAME + ble_tp_recv_wr(receive data from client) +*/ +static int ble_tp_recv_wr(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *buf, u16_t len, u16_t offset, u8_t flags) +{ + BT_WARN("recv data len=%d, offset=%d, flag=%d", len, offset, flags); + BT_WARN("recv data:%s", bt_hex(buf, len)); + + if (flags & BT_GATT_WRITE_FLAG_PREPARE) { + //Don't use prepare write data, execute write will upload data again. + BT_WARN("recv prepare write request"); + return 0; + } + + if (flags & BT_GATT_WRITE_FLAG_CMD) { + //Use write command data. + BT_WARN("recv write command"); + } else { + //Use write request / execute write data. + BT_WARN("recv write request / exce write"); + } + + k_sem_give(¬ify_poll_sem); + return len; +} + +/************************************************************************* +NAME + indicate_rsp /bl_tp_send_indicate +*/ + +static void indicate_rsp(struct bt_conn *conn, const struct bt_gatt_attr *attr, u8_t err) +{ + BT_WARN("receive comfirmation, err:%d", err); +} + +static int bl_tp_send_indicate(struct bt_conn *conn, const struct bt_gatt_attr *attr, + const void *data, u16_t len) +{ + static struct bt_gatt_indicate_params ind_params; + + ind_params.attr = attr; + ind_params.data = data; + ind_params.len = len; + ind_params.func = indicate_rsp; + ind_params.uuid = NULL; + + return bt_gatt_indicate(conn, &ind_params); +} + +/************************************************************************* +NAME + ble_tp_ind_ccc_changed +*/ +static void ble_tp_ind_ccc_changed(const struct bt_gatt_attr *attr, u16_t value) +{ + int err = -1; + char data[9] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; + + if (value == BT_GATT_CCC_INDICATE) { + err = bl_tp_send_indicate(ble_tp_conn, get_attr(BT_CHAR_BLE_TP_IND_ATTR_VAL_INDEX), data, 9); + BT_WARN("ble tp send indatcate: %d", err); + } +} + +/************************************************************************* +NAME + ble_tp_notify(send data to client) +*/ +static void ble_tp_notify_task(void *pvParameters) +{ + int err = -1; + u8_t data[244] = { 0x01 }; + k_sem_give(¬ify_poll_sem); + + while (1) { + k_sem_take(¬ify_poll_sem, K_FOREVER); + //send data to client + err = bt_gatt_notify(ble_tp_conn, get_attr(BT_CHAR_BLE_TP_NOT_ATTR_VAL_INDEX), data, (tx_mtu_size - 3)); + data[0] = data[0] + 1; + BT_WARN("ble tp send notify : %d", err); + } +} + +/************************************************************************* +NAME + ble_tp_not_ccc_changed +*/ +static void ble_tp_notify_ccc_changed(const struct bt_gatt_attr *attr, u16_t value) +{ + BT_WARN("ccc:value=[%d]", value); + + if (value == BT_GATT_CCC_NOTIFY) { + + if (xTaskCreate(ble_tp_notify_task, (char *)"bletp", 512, NULL, 15, &ble_tp_task_h) == pdPASS) { + created_tp_task = 1; + BT_WARN("Create throughput tx task success"); + } else { + created_tp_task = 0; + BT_WARN("Create throughput tx taskfail"); + } + } else { + if (created_tp_task) { + BT_WARN("Delete throughput tx task"); + vTaskDelete(ble_tp_task_h); + created_tp_task = 0; + } + } +} + +/************************************************************************* +* DEFINE : attrs +*/ +static struct bt_gatt_attr attrs[] = { + BT_GATT_PRIMARY_SERVICE(BT_UUID_SVC_BLE_TP), + + BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_RD, + BT_GATT_CHRC_READ, + BT_GATT_PERM_READ, + ble_tp_recv_rd, + NULL, + NULL), + + BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_WR, + BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP, + BT_GATT_PERM_WRITE | BT_GATT_PERM_PREPARE_WRITE, + NULL, + ble_tp_recv_wr, + NULL), + + BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_IND, + BT_GATT_CHRC_INDICATE, + 0, + NULL, + NULL, + NULL), + + BT_GATT_CCC(ble_tp_ind_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE), + + BT_GATT_CHARACTERISTIC(BT_UUID_CHAR_BLE_TP_NOT, + BT_GATT_CHRC_NOTIFY, + 0, + NULL, + NULL, + NULL), + + BT_GATT_CCC(ble_tp_notify_ccc_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE) + +}; + +/************************************************************************* +NAME + get_attr +*/ +struct bt_gatt_attr *get_attr(u8_t index) +{ + return &attrs[index]; +} + +static struct bt_gatt_service ble_tp_server = BT_GATT_SERVICE(attrs); + +/************************************************************************* +NAME + ble_tp_init +*/ +void ble_tp_init() +{ + if (!isRegister) { + isRegister = 1; + bt_conn_cb_register(&ble_tp_conn_callbacks); + bt_gatt_service_register(&ble_tp_server); + k_sem_init(¬ify_poll_sem, 0, 1); + } +} diff --git a/examples/ble/ble_pds/ble_peripheral_tp_server.h b/examples/ble/ble_pds/ble_peripheral_tp_server.h new file mode 100644 index 00000000..9c20922e --- /dev/null +++ b/examples/ble/ble_pds/ble_peripheral_tp_server.h @@ -0,0 +1,38 @@ +/**************************************************************************** +FILE NAME + ble_peripheral_tp_server.h + +DESCRIPTION +NOTES +*/ +/****************************************************************************/ + +#ifndef _BLE_TP_SVC_H_ +#define _BLE_TP_SVC_H_ + +#include "config.h" + +//07af27a5-9c22-11ea-9afe-02fcdc4e7412 +#define BT_UUID_SVC_BLE_TP BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a5, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412)) +//07af27a6-9c22-11ea-9afe-02fcdc4e7412 +#define BT_UUID_CHAR_BLE_TP_RD BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a6, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412)) +//07af27a7-9c22-11ea-9afe-02fcdc4e7412 +#define BT_UUID_CHAR_BLE_TP_WR BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a7, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412)) +//07af27a8-9c22-11ea-9afe-02fcdc4e7412 +#define BT_UUID_CHAR_BLE_TP_IND BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a8, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412)) +//07af27a9-9c22-11ea-9afe-02fcdc4e7412 +#define BT_UUID_CHAR_BLE_TP_NOT BT_UUID_DECLARE_128(BT_UUID_128_ENCODE(0x07af27a9, 0x9c22, 0x11ea, 0x9afe, 0x02fcdc4e7412)) + +//read value handle offset 2 +#define BT_CHAR_BLE_TP_RD_ATTR_VAL_INDEX (2) +//write value handle offset 4 +#define BT_CHAR_BLE_TP_WR_ATTR_VAL_INDEX (4) +//indicate value handle offset 6 +#define BT_CHAR_BLE_TP_IND_ATTR_VAL_INDEX (6) +//notity value handle offset 9 +#define BT_CHAR_BLE_TP_NOT_ATTR_VAL_INDEX (9) + +void ble_tp_init(); +struct bt_gatt_attr *get_attr(u8_t index); + +#endif diff --git a/examples/ble/ble_pds/main.c b/examples/ble/ble_pds/main.c new file mode 100644 index 00000000..46659ba3 --- /dev/null +++ b/examples/ble/ble_pds/main.c @@ -0,0 +1,446 @@ +/** + * @file main.c + * @brief + * + * Copyright (c) 2021 Bouffalolab team + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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 "bflb_platform.h" +#include "hal_uart.h" +#include +#include "semphr.h" +#include "bluetooth.h" +#include "gap.h" +#include "bl702_glb.h" +#include "ble_peripheral_tp_server.h" +#include "ble_lib_api.h" +#include "hci_driver.h" + +#if defined(CONFIG_BT_OAD_SERVER) +#include "oad_main.h" +#include "oad_service.h" +#endif + +#include "hal_pm.h" +#include "hal_pm_util.h" + +extern uint32_t __hbn_load_addr; +extern uint32_t __hbn_ram_start__; +extern uint32_t __hbn_ram_end__; + +extern uint32_t __itcm_load_addr; +extern uint32_t __dtcm_load_addr; +extern uint32_t __system_ram_load_addr; + +extern uint32_t __tcm_code_start__; +extern uint32_t __tcm_code_end__; +extern uint32_t __tcm_data_start__; +extern uint32_t __tcm_data_end__; +extern uint32_t __system_ram_data_start__; +extern uint32_t __system_ram_data_end__; + +#define ITCH_LOAD_ADDR __itcm_load_addr +#define TCM_CODE_START __tcm_code_start__ +#define TCM_CODE_END __tcm_code_end__ + +#define DTCH_LOAD_ADDR __dtcm_load_addr +#define TCM_DATA_START __tcm_data_start__ +#define TCM_DATA_END __tcm_data_start__ + +extern uint8_t _heap_start; +extern uint8_t _heap_size; // @suppress("Type cannot be resolved") +extern uint8_t _heap2_start; +extern uint8_t _heap2_size; // @suppress("Type cannot be resolved") + +static HeapRegion_t xHeapRegions[] = { + { &_heap_start, (unsigned int)&_heap_size }, + { &_heap2_start, (unsigned int) &_heap2_size }, + { NULL, 0 }, /* Terminates the array. */ + { NULL, 0 } /* Terminates the array. */ +}; + +bool pds_start = false; +#define TIME_5MS_IN_32768CYCLE (164) // (45000/(1000000/32768)) +void bl_pds_restore(void); + +//For test +extern int32_t rwip_get_sleep_stat_cnt(void); +//end + +uint8_t sharedBuf[16]; +void user_vAssertCalled(void) __attribute__((weak, alias("vAssertCalled"))); + +void vApplicationIdleHook(void) +{ + + if(!pds_start){ + __asm volatile( + " wfi " + ); + /*empty*/ + } +} +void vAssertCalled(void) +{ + MSG("vAssertCalled\r\n"); + + while (1) + ; +} + +void vApplicationTickHook(void) +{ + //MSG("vApplicationTickHook\r\n"); +} + +void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) +{ + MSG("vApplicationStackOverflowHook\r\n"); + + if (pcTaskName) { + MSG("Stack name %s\r\n", pcTaskName); + } + + while (1) + ; +} + +void vApplicationMallocFailedHook(void) +{ + MSG("vApplicationMallocFailedHook\r\n"); + + while (1) + ; +} +void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize) +{ + /* If the buffers to be provided to the Idle task are declared inside this + function then they must be declared static - otherwise they will be allocated on + the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[configMINIMAL_STACK_SIZE]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the +application must provide an implementation of vApplicationGetTimerTaskMemory() +to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize) +{ + /* If the buffers to be provided to the Timer task are declared inside this + function then they must be declared static - otherwise they will be allocated on + the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[configTIMER_TASK_STACK_DEPTH]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + +extern bool le_check_valid_scan(void); +extern bool le_check_valid_conn(void); +//Allocate retention memory +void *bl_alloc_retmem(size_t xWantedSize ) +{ + return pvPortMalloc(xWantedSize); +} + +void bflb_load_hbn_ram(void) +{ + uint32_t *pSrc, *pDest; + /* BF Add HBNRAM data copy */ + pSrc = &__hbn_load_addr; + pDest = &__hbn_ram_start__; + + for (; pDest < &__hbn_ram_end__;) { + *pDest++ = *pSrc++; + } +} + +// can be placed in flash, here placed in pds section to reduce fast boot time +void ATTR_PDS_RAM_SECTION user_pds_restore_tcm(void) +{ + uint32_t src = 0; + uint32_t dst = 0; + uint32_t end = 0; + + /* Copy ITCM code */ + src = (uint32_t)&ITCH_LOAD_ADDR; + dst = (uint32_t)&TCM_CODE_START; + end = (uint32_t)&TCM_CODE_END; + + while (dst < end) { + *(uint32_t *)dst = *(uint32_t *)src; + src += 4; + dst += 4; + } + +} + +// can be placed in flash, here placed in pds section to reduce fast boot time +void ATTR_PDS_RAM_SECTION user_pds_recovery_board(void) +{ + extern void board_init(void); + extern void system_clock_init(void); + board_init(); + system_clock_init(); +} + +void enter_sleep(uint32_t pdsSleepCycles) +{ + uint32_t actualSleepDuration_ms; + uint32_t mtimerClkCfg; + uint32_t ulCurrentTimeHigh, ulCurrentTimeLow; + volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFFC ); + volatile uint32_t * const pulTimeLow = ( volatile uint32_t * const ) ( configCLINT_BASE_ADDRESS + 0xBFF8 ); + + extern volatile uint64_t * const pullMachineTimerCompareRegister; + extern const size_t uxTimerIncrementsForOneTick; + extern void vPortSetupTimerInterrupt(void); + + mtimerClkCfg = *(volatile uint32_t *)0x40000090; // store mtimer clock + + *pullMachineTimerCompareRegister -= (uxTimerIncrementsForOneTick + 1); // avoid mtimer interrupt pending + *(volatile uint8_t *)0x02800407 = 0; + + do + { + ulCurrentTimeHigh = *pulTimeHigh; + ulCurrentTimeLow = *pulTimeLow; + } while( ulCurrentTimeHigh != *pulTimeHigh ); + + actualSleepDuration_ms = hal_pds_enter_with_time_compensation(PM_PDS_LEVEL_31, pdsSleepCycles); + + *(volatile uint32_t *)0x40000090 = mtimerClkCfg; + + *pulTimeHigh = ulCurrentTimeHigh; + *pulTimeLow = ulCurrentTimeLow; + + vPortSetupTimerInterrupt(); + *(volatile uint8_t *)0x02800407 = 1; + + vTaskStepTick(actualSleepDuration_ms); + +} + +void vApplicationSleep( TickType_t xExpectedIdleTime_ms) +{ + + int32_t bleSleepDuration_32768cycles = 0; + int32_t expectedIdleTime_32768cycles = 0; + eSleepModeStatus eSleepStatus; + bool freertos_max_idle = false; + + if (pds_start == 0 || le_check_valid_scan()) + return; + + if(xExpectedIdleTime_ms + xTaskGetTickCount() == portMAX_DELAY){ + freertos_max_idle = true; + }else{ + xExpectedIdleTime_ms -= 1; + expectedIdleTime_32768cycles = 32768 * xExpectedIdleTime_ms / 1000; + } + + if((!freertos_max_idle)&&(expectedIdleTime_32768cycles < TIME_5MS_IN_32768CYCLE)){ + return; + } + + eSleepStatus = eTaskConfirmSleepModeStatus(); + if(eSleepStatus == eAbortSleep || ble_controller_sleep_is_ongoing()) + { + return; + } + bleSleepDuration_32768cycles = ble_controller_sleep(); + + + if(bleSleepDuration_32768cycles < TIME_5MS_IN_32768CYCLE) + { + return; + } + else + { + MSG("Sleep_cycles=%ld,state_cnt=%d\r\n", bleSleepDuration_32768cycles, rwip_get_sleep_stat_cnt()); + + uint32_t reduceSleepTime; + SPI_Flash_Cfg_Type *flashCfg; + uint32_t len; + extern BL_Err_Type flash_get_cfg(uint8_t **cfg_addr, uint32_t *len); + flash_get_cfg((uint8_t**)&flashCfg,&len); + uint8_t ioMode = flashCfg->ioMode & 0xF; + uint8_t contRead = flashCfg->cReadSupport; + uint8_t cpuClk = GLB_Get_Root_CLK_Sel(); + if(ioMode == 4 && contRead == 1 && cpuClk == GLB_ROOT_CLK_XTAL) + { + reduceSleepTime = 100; + } + else if(ioMode == 1 && contRead == 0 && cpuClk == GLB_ROOT_CLK_XTAL) + { + reduceSleepTime = 130; + } + else + { + reduceSleepTime = 130; + } + if(eSleepStatus == eStandardSleep && ((!freertos_max_idle) && (expectedIdleTime_32768cycles < bleSleepDuration_32768cycles))) + { + enter_sleep( expectedIdleTime_32768cycles - reduceSleepTime); + } + else + { + enter_sleep( bleSleepDuration_32768cycles - reduceSleepTime); + } + + bl_pds_restore(); + } +} + +void bl_pds_restore(void) +{ + struct device *uart = device_find("debug_log"); + if (uart) { + device_close(uart); + device_open(uart, DEVICE_OFLAG_STREAM_TX | DEVICE_OFLAG_INT_RX); + device_set_callback(uart, NULL); + device_control(uart, DEVICE_CTRL_CLR_INT, (void *)(UART_RX_FIFO_IT)); + } + + HBN_Set_XCLK_CLK_Sel(HBN_XCLK_CLK_XTAL); + + ble_controller_sleep_restore(); +} + +int ble_start_adv(void) +{ + struct bt_le_adv_param adv_param = { + //options:3, connectable undirected, adv one time + .options = 3, + .interval_min = 0x280, + .interval_max = 0x280, + }; + + char *adv_name = "BL_PDS_TEST_01"; // This name must be the same as adv_name in ble_central + struct bt_data adv_data[] = { + BT_DATA(BT_DATA_NAME_COMPLETE, adv_name, strlen(adv_name)), + }; + + return bt_le_adv_start(&adv_param, adv_data, ARRAY_SIZE(adv_data), NULL, 0); + +} + +#if defined(CONFIG_BT_OAD_SERVER) +bool app_check_oad(u32_t cur_file_ver, u32_t new_file_ver) +{ + //App layer decides whether to do oad according to file version + /*if(new_file_ver > cur_file_ver) + return true; + else + return false;*/ + return true; +} +#endif + +void bt_enable_cb(int err) +{ + MSG("ble_tp_init\r\n"); + ble_tp_init(); +#if defined(CONFIG_BT_OAD_SERVER) + oad_service_enable(app_check_oad); +#endif + MSG("Start adv\r\n"); + ble_start_adv(); + MSG("Advertising.........\r\n"); + pds_start = true; +} + +void ble_stack_start(void) +{ + MSG("[OS] ble_controller_init...\r\n"); + GLB_Set_EM_Sel(GLB_EM_8KB); + ble_controller_init(configMAX_PRIORITIES - 1); + + // Initialize BLE Host stack + MSG("[OS] hci_driver_init...\r\n"); + hci_driver_init(); + + MSG("[OS] bt_enable...\r\n"); + bt_enable(bt_enable_cb); +} + +void ble_init(void) +{ + ble_stack_start(); +} + +static void ble_init_task(void *pvParameters) +{ + ble_init(); + vTaskDelete(NULL); +} + +int main(void) +{ + static StaticTask_t ble_init_task_h; + uint32_t tmpVal = 0; + + bflb_load_hbn_ram(); + bflb_platform_init(0); + HBN_Clear_RTC_Counter(); + HBN_Enable_RTC_Counter(); + pm_set_tcm_recovery_callback(user_pds_restore_tcm); + pm_set_board_recovery_callback(user_pds_recovery_board); + + HBN_Set_XCLK_CLK_Sel(HBN_XCLK_CLK_XTAL); + + //Set capcode + tmpVal = BL_RD_REG(AON_BASE, AON_XTAL_CFG); + tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_XTAL_CAPCODE_IN_AON, 33); + tmpVal = BL_SET_REG_BITS_VAL(tmpVal, AON_XTAL_CAPCODE_OUT_AON, 33); + BL_WR_REG(AON_BASE, AON_XTAL_CFG, tmpVal); + + vPortDefineHeapRegions(xHeapRegions); + + MSG("[OS] ble_init_task.....\r\n"); + xTaskCreate( ble_init_task, "ble_init_task", 512,NULL, 15, (TaskHandle_t * const)&ble_init_task_h); + + vTaskStartScheduler(); + + BL_CASE_SUCCESS; + while (1) { + bflb_platform_delay_ms(100); + } +}