[feat][examples/ble] add ble pds31 demo

This commit is contained in:
jzlv 2021-10-19 19:00:25 +08:00
parent 00a000d1cb
commit 49a2082160
6 changed files with 1125 additions and 0 deletions

View file

@ -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 );
}

View file

@ -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()

View file

@ -0,0 +1,361 @@
/****************************************************************************
FILE NAME
ble_peripheral_tp_server.c
DESCRIPTION
test profile demo
NOTES
*/
/****************************************************************************/
#include <errno.h>
#include <stdbool.h>
#include <stdlib.h>
#include <FreeRTOS.h>
#include <task.h>
#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, &param);
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(&notify_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(&notify_poll_sem);
while (1) {
k_sem_take(&notify_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(&notify_poll_sem, 0, 1);
}
}

View file

@ -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

446
examples/ble/ble_pds/main.c Normal file
View file

@ -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 <FreeRTOS.h>
#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);
}
}