demo工程暂存 优化菜单界面UI和功能
This commit is contained in:
387
MCU/examples/application/ble_simple_periphreal/Src/app_at.c
Normal file
387
MCU/examples/application/ble_simple_periphreal/Src/app_at.c
Normal file
@ -0,0 +1,387 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "fr30xx.h"
|
||||
|
||||
#include "co_util.h"
|
||||
|
||||
#include "bt_types.h"
|
||||
#include "me_api.h"
|
||||
#include "hfg_api.h"
|
||||
#include "gatt_api.h"
|
||||
|
||||
#include "app_at.h"
|
||||
#include "app_task.h"
|
||||
#include "app_ble.h"
|
||||
|
||||
#define AT_RECV_MAX_LEN 32
|
||||
|
||||
static uint8_t app_at_recv_char;
|
||||
static uint8_t at_recv_buffer[AT_RECV_MAX_LEN];
|
||||
static uint8_t at_recv_index = 0;
|
||||
static uint8_t at_recv_state = 0;
|
||||
|
||||
void btdm_host_send_vendor_cmd(uint8_t type, uint8_t length, void *data);
|
||||
|
||||
void btdm_host_vendor_cmd_cmp_evt(uint8_t status, uint8_t len, uint8_t const *param)
|
||||
{
|
||||
printf("status: 0x%02x.\r\n", status);
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
printf("%02x ", param[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
void btdm_host_recv_vendor_evt(uint8_t len, uint8_t *param)
|
||||
{
|
||||
if (param[1] == 0x10) {
|
||||
float acc[3];
|
||||
memcpy((void *)&acc[0], ¶m[3], sizeof(float) * 3);
|
||||
printf("%0.6f, %0.6f, %0.6f\r\n", acc[0], acc[1], acc[2]);
|
||||
return;
|
||||
}
|
||||
printf("EVENT: ");
|
||||
for (uint32_t i=0; i<len; i++) {
|
||||
printf("%02x ", param[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
}
|
||||
|
||||
static void app_at_recv_cmd_A(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
switch(sub_cmd)
|
||||
{
|
||||
// case 'A':
|
||||
// {
|
||||
// mac_addr_t addr;
|
||||
// addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
// addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2);
|
||||
// addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2);
|
||||
// addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2);
|
||||
// addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2);
|
||||
// addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2);
|
||||
// gap_start_conn(&addr, ascii_strn2val((const char *)&data[12], 16, 2), 64, 64, 0, 500);
|
||||
// }
|
||||
// break;
|
||||
// case 'B':
|
||||
// {
|
||||
// gap_stop_conn();
|
||||
// }
|
||||
// break;
|
||||
case 'A':
|
||||
{
|
||||
uint8_t addr = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
btdm_host_send_vendor_cmd(0x00, 1, &addr);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'B':
|
||||
{
|
||||
uint8_t buffer[2];
|
||||
buffer[0] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
buffer[1] = ascii_strn2val((const char *)&data[3], 16, 2);
|
||||
btdm_host_send_vendor_cmd(0x01, 2, (void *)&buffer[0]);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'C':
|
||||
{
|
||||
uint32_t addr = ascii_strn2val((const char *)&data[0], 16, 8);
|
||||
btdm_host_send_vendor_cmd(0x02, 4, (void *)&addr);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'D':
|
||||
{
|
||||
uint32_t buffer[2];
|
||||
buffer[0] = ascii_strn2val((const char *)&data[0], 16, 8);
|
||||
buffer[1] = ascii_strn2val((const char *)&data[9], 16, 8);
|
||||
btdm_host_send_vendor_cmd(0x03, 8, (void *)&buffer[0]);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
// case 'C':
|
||||
// {
|
||||
// btdm_host_send_vendor_cmd(0x15, 0, NULL);
|
||||
// }
|
||||
// printf("OK\r\n");
|
||||
// break;
|
||||
// case 'D':
|
||||
// {
|
||||
// uint8_t mode = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
// btdm_host_send_vendor_cmd(0x14, 1, &mode);
|
||||
// }
|
||||
// printf("OK\r\n");
|
||||
// break;
|
||||
case 'E':
|
||||
{
|
||||
// btdm_host_send_vendor_cmd(0x11, 0, NULL);
|
||||
|
||||
uint8_t sleep_dur[2];
|
||||
sleep_dur[0] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
sleep_dur[1] = ascii_strn2val((const char *)&data[3], 16, 2);
|
||||
btdm_host_send_vendor_cmd(0x16, 2, &sleep_dur);
|
||||
}
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'F':
|
||||
{
|
||||
static uint8_t hour = 0;
|
||||
static uint8_t minute = 0;
|
||||
static uint8_t second = 0;
|
||||
static uint16_t mini_second = 0;
|
||||
uint8_t gsensor_cmd[] = {0x00, 0xe7, 0x07, 0x09, 0x12, 0x14, 0x36, 0x10, 0x20, 0x00, 0x2c, 0x01};
|
||||
mini_second += 200;
|
||||
if (mini_second >= 1000) {
|
||||
mini_second = 0;
|
||||
second++;
|
||||
if (second >= 60) {
|
||||
second = 0;
|
||||
minute++;
|
||||
if (minute >= 60) {
|
||||
minute = 0;
|
||||
hour++;
|
||||
}
|
||||
}
|
||||
}
|
||||
gsensor_cmd[5] = hour;
|
||||
gsensor_cmd[6] = minute;
|
||||
gsensor_cmd[7] = second;
|
||||
gsensor_cmd[8] = mini_second;
|
||||
gsensor_cmd[9] = mini_second >> 8;
|
||||
btdm_host_send_vendor_cmd(0x12, sizeof(gsensor_cmd), gsensor_cmd);
|
||||
}
|
||||
break;
|
||||
case 'G':
|
||||
printf("hello world!\r\n");
|
||||
break;
|
||||
case 'H':
|
||||
printf("VAL: 0x%08x.\r\n", *(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8));
|
||||
break;
|
||||
case 'I':
|
||||
*(volatile uint32_t *)ascii_strn2val((const char *)&data[0], 16, 8) = ascii_strn2val((const char *)&data[9], 16, 8);
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'J':
|
||||
printf("OOL VAL: 0x%02x.\r\n", ool_read(ascii_strn2val((const char *)&data[0], 16, 2)));
|
||||
break;
|
||||
case 'K':
|
||||
ool_write(ascii_strn2val((const char *)&data[0], 16, 2), ascii_strn2val((const char *)&data[3], 16, 2));
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
case 'L':
|
||||
printf("VAL: 0x%02x.\r\n", *(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)));
|
||||
break;
|
||||
case 'M':
|
||||
*(volatile uint8_t *)(ascii_strn2val((const char *)&data[0], 16, 8)) = ascii_strn2val((const char *)&data[9], 16, 2);
|
||||
printf("OK\r\n");
|
||||
break;
|
||||
// case 'P':
|
||||
// co_printf("VAL: 0x%02x.\r\n", *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)));
|
||||
// break;
|
||||
// case 'Q':
|
||||
// *(uint8_t *)(MODEM_BASE + ascii_strn2val((const char *)&data[0], 16, 2)) = ascii_strn2val((const char *)&data[3], 16, 2);
|
||||
// co_printf("OK\r\n");
|
||||
// break;
|
||||
// case 'S':
|
||||
// co_printf("VAL: 0x%02x.\r\n", frspim_rd(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1));
|
||||
// break;
|
||||
// case 'T':
|
||||
// frspim_wr(FR_SPI_RF_COB_CHAN, ascii_strn2val((const char *)&data[0], 16, 2), 1, ascii_strn2val((const char *)&data[3], 16, 2));
|
||||
// co_printf("OK\r\n");
|
||||
// break;
|
||||
case 'U':
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)(ascii_strn2val((const char *)&data[0], 16, 8) & (~3));
|
||||
uint8_t count = ascii_strn2val((const char *)&data[9], 16, 2);
|
||||
uint32_t *start = (uint32_t *)((uint32_t)ptr & (~0x0f));
|
||||
for(uint8_t i=0; i<count;) {
|
||||
if(((uint32_t)start & 0x0c) == 0) {
|
||||
printf("0x%08x: ", (uint32_t)start);
|
||||
}
|
||||
if(start < ptr) {
|
||||
printf(" ");
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
printf("%08x", *start);
|
||||
}
|
||||
if(((uint32_t)start & 0x0c) == 0x0c) {
|
||||
printf("\r\n");
|
||||
}
|
||||
else {
|
||||
printf(" ");
|
||||
}
|
||||
start++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
flash_erase(QSPI0, ascii_strn2val((const char *)&data[0], 16, 8), ascii_strn2val((const char *)&data[9], 16, 8));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void app_at_recv_cmd_B(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
struct gap_ble_addr peer_addr;
|
||||
BD_ADDR addr;
|
||||
|
||||
switch(sub_cmd) {
|
||||
case 'A':
|
||||
// AT#BA00
|
||||
//app_ble_advertising_start(ascii_strn2val((const char *)&data[0], 16, 2));
|
||||
break;
|
||||
case 'B':
|
||||
// AT#BB01
|
||||
//app_ble_advertising_stop(ascii_strn2val((const char *)&data[0], 16, 2));
|
||||
break;
|
||||
case 'C':
|
||||
//app_ble_scan_start();
|
||||
break;
|
||||
case 'D':
|
||||
//app_ble_scan_stop();
|
||||
break;
|
||||
case 'E':
|
||||
// AT#BE0123456789ab_01
|
||||
peer_addr.addr.addr[5] = ascii_strn2val((const char *)&data[0], 16, 2);
|
||||
peer_addr.addr.addr[4] = ascii_strn2val((const char *)&data[2], 16, 2);
|
||||
peer_addr.addr.addr[3] = ascii_strn2val((const char *)&data[4], 16, 2);
|
||||
peer_addr.addr.addr[2] = ascii_strn2val((const char *)&data[6], 16, 2);
|
||||
peer_addr.addr.addr[1] = ascii_strn2val((const char *)&data[8], 16, 2);
|
||||
peer_addr.addr.addr[0] = ascii_strn2val((const char *)&data[10], 16, 2);
|
||||
peer_addr.addr_type = ascii_strn2val((const char *)&data[13], 16, 2);
|
||||
//app_ble_conn_start(&peer_addr);
|
||||
break;
|
||||
case 'F':
|
||||
//app_ble_conn_stop();
|
||||
break;
|
||||
case 'H':
|
||||
ME_Inquiry(BT_IAC_GIAC, 5, 5);
|
||||
break;
|
||||
case 'I':
|
||||
ME_CancelInquiry();
|
||||
break;
|
||||
case 'J':
|
||||
{
|
||||
BtStatus status;
|
||||
addr.A[0] = ascii_strn2val((const char*)&data[0],16,2);
|
||||
addr.A[1] = ascii_strn2val((const char*)&data[2],16,2);
|
||||
addr.A[2] = ascii_strn2val((const char*)&data[4],16,2);
|
||||
addr.A[3] = ascii_strn2val((const char*)&data[6],16,2);
|
||||
addr.A[4] = ascii_strn2val((const char*)&data[8],16,2);
|
||||
addr.A[5] = ascii_strn2val((const char*)&data[10],16,2);
|
||||
|
||||
//status = HFG_CreateServiceLink(&hfg_channel[0], &addr);
|
||||
|
||||
if (status == BT_STATUS_PENDING) {
|
||||
printf("Opening Channel...\r\n");
|
||||
} else {
|
||||
printf("Could not open channel, status: %d\r\n", status);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
// {
|
||||
// uint8_t battery_level[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
|
||||
// struct gatt_send_event ntf[6];
|
||||
// uint8_t i=0;
|
||||
// for(i=0;i<6;i++){
|
||||
// ntf[i].conidx = 0;
|
||||
// ntf[i].svc_id = svc_id;
|
||||
// ntf[i].att_idx = 2;
|
||||
// ntf[i].data_len = 15;
|
||||
// ntf[i].p_data = &battery_level[0];
|
||||
// gatt_notification(&ntf[i]);
|
||||
// }
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
printf("OK\r\n");
|
||||
}
|
||||
|
||||
static void app_at_recv_cmd_D(uint8_t sub_cmd, uint8_t *data)
|
||||
{
|
||||
switch(sub_cmd) {
|
||||
case 'A':
|
||||
flash_erase(QSPI0, ascii_strn2val((const char*)&data[0],16,8), 0x1000);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void app_at_cmd_recv_handler(uint8_t *data, uint16_t length)
|
||||
{
|
||||
switch(data[0])
|
||||
{
|
||||
case 'A':
|
||||
app_at_recv_cmd_A(data[1], &data[2]);
|
||||
break;
|
||||
case 'B':
|
||||
app_at_recv_cmd_B(data[1], &data[2]);
|
||||
break;
|
||||
case 'D':
|
||||
app_at_recv_cmd_D(data[1], &data[2]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void app_at_recv_c(uint8_t c)
|
||||
{
|
||||
switch(at_recv_state)
|
||||
{
|
||||
case 0:
|
||||
if(c == 'A')
|
||||
{
|
||||
at_recv_state++;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if(c == 'T')
|
||||
at_recv_state++;
|
||||
else
|
||||
at_recv_state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if(c == '#')
|
||||
at_recv_state++;
|
||||
else
|
||||
at_recv_state = 0;
|
||||
break;
|
||||
case 3:
|
||||
at_recv_buffer[at_recv_index++] = c;
|
||||
if((c == '\n')
|
||||
||(at_recv_index >= AT_RECV_MAX_LEN))
|
||||
{
|
||||
struct app_task_event *event;
|
||||
event = app_task_event_alloc(APP_TASK_EVENT_AT_CMD, at_recv_index, false);
|
||||
if(event) {
|
||||
memcpy(event->param, at_recv_buffer, at_recv_index);
|
||||
app_task_event_post(event, false);
|
||||
}
|
||||
at_recv_state = 0;
|
||||
at_recv_index = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void app_at_rx_done(struct __UART_HandleTypeDef *handle)
|
||||
{
|
||||
app_at_recv_c(app_at_recv_char);
|
||||
if (handle) {
|
||||
uart_receive_IT(handle, &app_at_recv_char, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void app_at_init(struct __UART_HandleTypeDef *handle)
|
||||
{
|
||||
uart_receive_IT(handle, &app_at_recv_char, 1);
|
||||
}
|
14
MCU/examples/application/ble_simple_periphreal/Src/app_at.h
Normal file
14
MCU/examples/application/ble_simple_periphreal/Src/app_at.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef _APP_AT_H
|
||||
#define _APP_AT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "driver_uart.h"
|
||||
|
||||
void app_at_cmd_recv_handler(uint8_t *data, uint16_t length);
|
||||
|
||||
void app_at_rx_done(struct __UART_HandleTypeDef *handle);
|
||||
|
||||
void app_at_init(struct __UART_HandleTypeDef *handle);
|
||||
|
||||
#endif // _APP_AT_H
|
436
MCU/examples/application/ble_simple_periphreal/Src/app_ble.c
Normal file
436
MCU/examples/application/ble_simple_periphreal/Src/app_ble.c
Normal file
@ -0,0 +1,436 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "co_log.h"
|
||||
|
||||
#include "gap_api.h"
|
||||
#include "gatt_api.h"
|
||||
#include "fdb_app.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "timers.h"
|
||||
#include "portable.h"
|
||||
#include "btdm_mem.h"
|
||||
|
||||
#define SP_SVC_UUID 0xFFF0
|
||||
#define SP_CHAR1_UUID 0xFFF3
|
||||
#define SP_CHAR2_UUID {0xba, 0x5c, 0xFF, 0xF4, 0x04, 0xa3, 0x40, 0x71, 0xa0, 0xb5, 0x35, 0x85, 0x3e, 0xb0, 0x83, 0x07}
|
||||
|
||||
// Element index of gatt service table
|
||||
enum
|
||||
{
|
||||
SP_IDX_SERVICE,
|
||||
|
||||
SP_IDX_CHAR1_DECLARATION,
|
||||
SP_IDX_CHAR1_VALUE,
|
||||
SP_IDX_CHAR1_CFG,
|
||||
SP_IDX_CHAR1_USER_DESCRIPTION,
|
||||
|
||||
SP_IDX_CHAR2_DECLARATION,
|
||||
SP_IDX_CHAR2_VALUE,
|
||||
SP_IDX_CHAR2_USER_DESCRIPTION,
|
||||
|
||||
SP_IDX_NB,
|
||||
};
|
||||
|
||||
// Simple GATT Profile Service UUID: 0xFFF0
|
||||
static const uint8_t sp_svc_uuid[] = UUID16_ARR(SP_SVC_UUID);
|
||||
|
||||
/******************************* Characteristic 1 defination *******************************/
|
||||
// Characteristic 1 UUID: 0xFFF3
|
||||
// Characteristic 1 data
|
||||
#define SP_CHAR1_VALUE_LEN 20
|
||||
static uint8_t sp_char1_value[SP_CHAR1_VALUE_LEN] = {0};
|
||||
|
||||
#define SP_CHAR1_USER_DESC_LEN 17
|
||||
static char sp_char1_user_desc_data[] = "Characteristic 1";
|
||||
|
||||
static uint8_t desc_data[2] = {0};
|
||||
|
||||
/******************************* Characteristic 2 defination *******************************/
|
||||
// Characteristic 2 UUID: 0xBA5C-FFF4-04A3-4071-A0B5-3585-3EB0-8307
|
||||
// Characteristic 2 data
|
||||
#define SP_CHAR2_VALUE_LEN 5
|
||||
static uint8_t sp_char2_value[SP_CHAR2_VALUE_LEN] = {0x11, 0x22, 0x33, 0x44, 0x55};
|
||||
|
||||
#define SP_CHAR2_USER_DESC_LEN 17
|
||||
static char sp_char2_user_desc_data[] = "Characteristic 2";
|
||||
|
||||
static const gatt_attribute_t simple_profile_att_table[] =
|
||||
{
|
||||
// Simple gatt Service Declaration
|
||||
[SP_IDX_SERVICE] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(GATT_PRIMARY_SERVICE_UUID) }, /* UUID */
|
||||
GATT_PROP_READ, /* Permissions */
|
||||
UUID_SIZE_2, /* Max size of the value */ /* Service UUID size in service declaration */
|
||||
(uint8_t*)sp_svc_uuid, /* Value of the attribute */ /* Service UUID value in service declaration */
|
||||
},
|
||||
|
||||
/******************************* Characteristic 1 defination *******************************/
|
||||
// Characteristic 1 Declaration
|
||||
[SP_IDX_CHAR1_DECLARATION] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
|
||||
GATT_PROP_READ, /* Permissions */
|
||||
0, /* Max size of the value */
|
||||
NULL, /* Value of the attribute */
|
||||
},
|
||||
// Characteristic 1 Value
|
||||
[SP_IDX_CHAR1_VALUE] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(SP_CHAR1_UUID) }, /* UUID */
|
||||
GATT_PROP_READ | GATT_PROP_NOTI | GATT_PROP_WRITE_REQ, /* Permissions */
|
||||
SP_CHAR1_VALUE_LEN, /* Max size of the value */
|
||||
NULL, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
|
||||
/* When the buffer is null, if a read request is received,
|
||||
* the lower layer will report a read event to the gatt callback.
|
||||
* The user must assign a value to the data pointer in the callback event
|
||||
* to reply to the read request
|
||||
*/
|
||||
},
|
||||
|
||||
// Characteristic 1 client characteristic configuration
|
||||
[SP_IDX_CHAR1_CFG] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(GATT_CLIENT_CHAR_CFG_UUID) }, /* UUID */
|
||||
GATT_PROP_READ | GATT_PROP_WRITE_REQ, /* Permissions */
|
||||
2, /* Max size of the value */
|
||||
desc_data, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
|
||||
},
|
||||
|
||||
// Characteristic 1 User Description
|
||||
[SP_IDX_CHAR1_USER_DESCRIPTION] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */
|
||||
GATT_PROP_READ, /* Permissions */
|
||||
SP_CHAR1_USER_DESC_LEN, /* Max size of the value */
|
||||
(uint8_t *)sp_char1_user_desc_data, /* Value of the attribute */
|
||||
},
|
||||
|
||||
/******************************* Characteristic 2 defination *******************************/
|
||||
// Characteristic 2 Declaration
|
||||
[SP_IDX_CHAR2_DECLARATION] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(GATT_CHARACTER_UUID) }, /* UUID */
|
||||
GATT_PROP_READ, /* Permissions */
|
||||
0, /* Max size of the value */
|
||||
NULL, /* Value of the attribute */
|
||||
},
|
||||
|
||||
// Characteristic 2 Value
|
||||
[SP_IDX_CHAR2_VALUE] = {
|
||||
{ UUID_SIZE_16, SP_CHAR2_UUID }, /* UUID */
|
||||
GATT_PROP_READ , /* Permissions */
|
||||
SP_CHAR2_VALUE_LEN, /* Max size of the value */
|
||||
sp_char2_value, /* Value of the attribute */ /* Can assign a buffer here, or can be assigned in the application by user */
|
||||
/* When the buffer is null, if a read request is received,
|
||||
* the lower layer will report a read event to the gatt callback.
|
||||
* The user must assign a value to the data pointer in the callback event
|
||||
* to reply to the read request
|
||||
*/
|
||||
},
|
||||
|
||||
// Characteristic 2 User Description
|
||||
[SP_IDX_CHAR2_USER_DESCRIPTION] = {
|
||||
{ UUID_SIZE_2, UUID16_ARR(GATT_CHAR_USER_DESC_UUID) }, /* UUID */
|
||||
GATT_PROP_READ, /* Permissions */
|
||||
SP_CHAR2_USER_DESC_LEN, /* Max size of the value */
|
||||
(uint8_t *)sp_char2_user_desc_data, /* Value of the attribute */
|
||||
},
|
||||
};
|
||||
|
||||
static void app_ble_start_advertising(void);
|
||||
|
||||
static char local_device_name[] = "30xx_Ble_Periphreal";
|
||||
static adv_handle adv;
|
||||
|
||||
/*
|
||||
* Advertising data, max size is 28 bytes
|
||||
*/
|
||||
static uint8_t adv_data[] = {
|
||||
/* gatt service information */
|
||||
0x03, //length of this AD
|
||||
GAP_ADVTYPE_16BIT_MORE, //16bit service uuid AD type
|
||||
0xff, 0xf0, //value.service uuid:0xFFF0
|
||||
|
||||
/* local device name information */
|
||||
0x14, //length of this AD
|
||||
GAP_ADVTYPE_LOCAL_NAME_COMPLETE, //complete name AD type
|
||||
'3','0','x','x','_','B','l','e','_','P','e','r','i','p','h','r','e','a','l', //value.local device name
|
||||
};
|
||||
|
||||
/*
|
||||
* Advertising scan response data, max size is 31 bytes
|
||||
*/
|
||||
static uint8_t adv_scan_rsp_data[] = {
|
||||
/* local device name information */
|
||||
0x14, //length of this AD
|
||||
GAP_ADVTYPE_LOCAL_NAME_COMPLETE, //complete name AD type
|
||||
'3','0','x','x','_','B','l','e','_','P','e','r','i','p','h','r','e','a','l', //value.local device name
|
||||
};
|
||||
|
||||
uint8_t service_id;
|
||||
|
||||
static uint16_t gap_callback(struct gap_event *event)
|
||||
{
|
||||
// printf("gap_callback: type = %d\r\n", event->type);
|
||||
|
||||
switch(event->type) {
|
||||
case GATT_EVT_PROFILE_ADDED:
|
||||
{
|
||||
printf("gap_callback: GATT_EVT_PROFILE_ADDED: 0x%02X\r\n", event->param.profile_added_status);
|
||||
|
||||
/* service profile has been added successfully, then the advertising can be started */
|
||||
app_ble_start_advertising();
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_SET_PARAM:
|
||||
printf("adv param set: 0x%02X\r\n", event->param.adv_set_param.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_SET_ADV_DATA:
|
||||
printf("adv data set: 0x%02X\r\n", event->param.adv_set_adv_data.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_SET_SCAN_RSP:
|
||||
printf("adv scan rsp data set: 0x%02X\r\n", event->param.adv_set_scan_rsp.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_START:
|
||||
printf("adv start :0x%02X\r\n", event->param.adv_start.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_ADV_END:
|
||||
printf("adv end: 0x%02X\r\n", event->param.adv_end.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_SLAVE_CONNECT:
|
||||
{
|
||||
//gap_get_link_version(event->param.connect.conidx);
|
||||
//gap_get_link_rssi(event->param.connect.conidx);
|
||||
//gap_get_link_features(event->param.connect.conidx);
|
||||
printf("slave connect[%d], connect num: %d\r\n", event->param.connect.conidx, gap_get_connect_num());
|
||||
gatt_mtu_exchange_req(service_id, event->param.connect.conidx, 247);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_DISCONNECT:
|
||||
{
|
||||
printf("gap_callback: GAP_EVT_DISCONNECT, conidx:%d, reason:0x%02X\r\n", event->param.disconnect.conidx,
|
||||
event->param.disconnect.reason);
|
||||
gap_adv_start(adv, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case GATT_EVT_MTU:
|
||||
printf("gap_callback: conidx: %d, GATT_EVT_MTU: %d\r\n", event->param.mtu_ind.conidx, event->param.mtu_ind.mtu);
|
||||
break;
|
||||
|
||||
case GAP_EVT_NAME_REQ:
|
||||
{
|
||||
gap_name_req_rsp(event->param.name_req.conidx,
|
||||
event->param.name_req.token,
|
||||
sizeof(local_device_name),
|
||||
(uint8_t *)local_device_name);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_APPEARANCE_REQ:
|
||||
{
|
||||
gap_appearance_req_rsp(event->param.appearance_req.conidx,
|
||||
event->param.appearance_req.token,
|
||||
GAP_APPEARE_UNKNOWN);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_PARAM_REQ:
|
||||
{
|
||||
struct gap_link_param_update_rsp rsp;
|
||||
rsp.accept = true;
|
||||
rsp.conidx = event->param.link_param_update_req.conidx;
|
||||
rsp.ce_len_max = 2;
|
||||
rsp.ce_len_min = 2;
|
||||
gap_param_update_rsp(&rsp);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_PARAM_UPDATE:
|
||||
{
|
||||
printf("conn param update,conidx:%d, con_int:%d, latency:%d, timeout%d\r\n", event->param.link_param_update.conidx,
|
||||
event->param.link_param_update.con_interval,
|
||||
event->param.link_param_update.con_latency,
|
||||
event->param.link_param_update.sup_to);
|
||||
}
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_RSSI:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_LINK_RSSI: %d\r\n", event->param.gap_link_rssi.conidx, event->param.gap_link_rssi.link_rssi);
|
||||
break;
|
||||
|
||||
case GAP_EVT_PHY_IND:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_PHY_IND: %d\r\n", event->param.gap_phy_ind.conidx, event->param.gap_phy_ind.tx_phy);
|
||||
break;
|
||||
|
||||
case GAP_EVT_PHY_REJECT:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_PHY_REJECT, status: %d\r\n", event->param.gap_phy_update_reject.conidx, event->param.gap_phy_update_reject.status);
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_VER:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_LINK_VER\r\n", event->param.gap_link_ver.conidx);
|
||||
break;
|
||||
|
||||
case GAP_EVT_LINK_FEATURE:
|
||||
printf("gap_callback: conidx: %d, GAP_EVT_LINK_FEATURE:%d\r\n", event->param.gap_link_feature.conidx, event->param.gap_link_feature.features[0]);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t gatt_callback(struct gatt_msg *p_msg)
|
||||
{
|
||||
uint8_t uuid_temp[16];
|
||||
uint16_t uuid_2 = 0;
|
||||
|
||||
switch(p_msg->msg_evt) {
|
||||
case GATTC_MSG_CMP_EVT:
|
||||
{
|
||||
switch(p_msg->param.gatt_op_cmp.operation) {
|
||||
case GATT_OP_NOTIFY:
|
||||
/*opearation of notification is complete */
|
||||
printf("notify cmp, conidx:%d, status:0x%02X\r\n", p_msg->conn_idx, p_msg->param.gatt_op_cmp.status);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Received a read request from the peer device */
|
||||
case GATTS_MSG_READ_REQ:
|
||||
{
|
||||
printf("GATTS_MSG_READ_REQ, conidx:%d, att idx:%d\r\n", p_msg->conn_idx, p_msg->att_idx);
|
||||
|
||||
if(p_msg->att_idx == SP_IDX_CHAR1_VALUE)
|
||||
{
|
||||
/*
|
||||
* Because the buffer pointer of SP_IDX_CHAR1_VALUE is NULL,
|
||||
* read requests will be report to the application layer for user response
|
||||
*/
|
||||
uint8_t read_rsp_data[] = {0x00, 0x01, 0x02, 0x03, 0x04};
|
||||
memcpy(p_msg->param.gatt_data.p_msg_data, read_rsp_data, sizeof(read_rsp_data));
|
||||
|
||||
/* Return the length of response data */
|
||||
return (sizeof(read_rsp_data));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
/* Received a write request from the peer device */
|
||||
case GATTS_MSG_WRITE_REQ:
|
||||
{
|
||||
printf("GATTS_MSG_WRITE_REQ, conidx:%d, att idx:%d\r\n", p_msg->conn_idx, p_msg->att_idx);
|
||||
|
||||
if(p_msg->att_idx == SP_IDX_CHAR1_VALUE)
|
||||
{
|
||||
printf("recv data: 0x");
|
||||
for(uint8_t i=0; i<p_msg->param.gatt_data.msg_len; i++)
|
||||
printf("%02X", p_msg->param.gatt_data.p_msg_data[i]);
|
||||
printf("\r\n");
|
||||
}
|
||||
else if(p_msg->att_idx == SP_IDX_CHAR1_CFG)
|
||||
{
|
||||
uint8_t data[2];
|
||||
memcpy(data, p_msg->param.gatt_data.p_msg_data, 2);
|
||||
if(data[0] & 0x01)
|
||||
{
|
||||
/* peer device enable notify */
|
||||
printf("ntf enable, att_idx:%d\r\n", p_msg->att_idx);
|
||||
uint8_t send_data[5] = {0x01, 0x02, 0x03, 0x04, 0x05};
|
||||
struct gatt_send_event ntf;
|
||||
ntf.conidx = p_msg->conn_idx;
|
||||
ntf.att_idx = SP_IDX_CHAR1_VALUE;
|
||||
ntf.p_data = send_data;
|
||||
ntf.data_len = sizeof(send_data);
|
||||
ntf.svc_id = service_id;
|
||||
|
||||
/* Send a notification to the peer device */
|
||||
gatt_notification(&ntf);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GATTC_MSG_LINK_CREATE:
|
||||
printf("gatt linkk create, conidx:%d\r\n", p_msg->conn_idx);
|
||||
break;
|
||||
|
||||
case GATTC_MSG_LINK_LOST:
|
||||
printf("gatt linkk lost, conidx:%d\r\n", p_msg->conn_idx);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void app_ble_add_service(void)
|
||||
{
|
||||
struct gatt_service service;
|
||||
|
||||
service.att_nb = SP_IDX_NB;
|
||||
service.p_att_tb = simple_profile_att_table;
|
||||
service.gatt_msg_handler = gatt_callback; //set GATT event callback
|
||||
|
||||
service_id = gatt_add_service(&service);
|
||||
}
|
||||
|
||||
static void app_ble_start_advertising(void)
|
||||
{
|
||||
/* creat a handle of advertising*/
|
||||
adv = gap_adv_create();
|
||||
|
||||
gap_adv_param_t adv_param = {
|
||||
.own_addr_type = GAP_ADDR_TYPE_STATIC, //own address type
|
||||
.adv_mode = GAP_ADV_MODE_UNDIRECT,
|
||||
.disc_mode = GAP_ADV_DISC_MODE_GEN_DISC,
|
||||
.adv_chnl_map = GAP_ADV_CHAN_ALL,
|
||||
.filt_policy = GAP_ADV_FILTER_SCAN_ANY_CON_ANY, //Policy for filtering scanning or connection requests from peer devices
|
||||
.phy_mode = GAP_PHY_TYPE_LE_1M,
|
||||
.adv_intv_min = 160, //advertising min interval, in unit of 0.625ms
|
||||
.adv_intv_max = 160, //advertising max interval, in unit of 0.625ms
|
||||
};
|
||||
|
||||
/* set advertising param */
|
||||
gap_adv_set_param(adv, &adv_param);
|
||||
/* set advertising data */
|
||||
gap_adv_set_adv_data(adv, adv_data, sizeof(adv_data));
|
||||
/* set advertising scan response data */
|
||||
gap_adv_set_scan_rsp(adv, adv_scan_rsp_data, sizeof(adv_scan_rsp_data));
|
||||
/* start sadvertising */
|
||||
gap_adv_start(adv, 0, 0);
|
||||
}
|
||||
|
||||
void app_ble_init(void)
|
||||
{
|
||||
printf("app_ble_init\r\n");
|
||||
|
||||
/* set GAP event callback*/
|
||||
gap_set_cb_func(gap_callback);
|
||||
|
||||
/* set security param */
|
||||
struct gap_security_param smp_param;
|
||||
smp_param.mitm = true;
|
||||
smp_param.secure_connection = false;
|
||||
smp_param.bond = true;
|
||||
smp_param.rsp_mode = ENABLE_AUTO_RSP;
|
||||
smp_param.oob_used = GAP_OOB_AUTH_DATA_NOT_PRESENT;
|
||||
smp_param.io_cap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT;
|
||||
|
||||
gap_security_param_init(&smp_param);
|
||||
|
||||
/* add service profile, The GAP callback event is GATT_EVT_PROFILE_ADDED*/
|
||||
app_ble_add_service();
|
||||
}
|
||||
|
||||
|
19
MCU/examples/application/ble_simple_periphreal/Src/app_ble.h
Normal file
19
MCU/examples/application/ble_simple_periphreal/Src/app_ble.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef _APP_BLE_H
|
||||
#define _APP_BLE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "gap_api.h"
|
||||
|
||||
void app_ble_init(void);
|
||||
|
||||
void app_ble_advertising_start(uint8_t adv_chn);
|
||||
void app_ble_advertising_stop(uint8_t adv_chn);
|
||||
|
||||
void app_ble_scan_start(void);
|
||||
void app_ble_scan_stop(void);
|
||||
|
||||
void app_ble_conn_start(struct gap_ble_addr *addr);
|
||||
void app_ble_conn_stop(void);
|
||||
|
||||
#endif // _APP_BLE_H
|
107
MCU/examples/application/ble_simple_periphreal/Src/app_btdm.c
Normal file
107
MCU/examples/application/ble_simple_periphreal/Src/app_btdm.c
Normal file
@ -0,0 +1,107 @@
|
||||
#include "app_config.h"
|
||||
#include "app_task.h"
|
||||
#include "app_btdm.h"
|
||||
#include "app_ble.h"
|
||||
|
||||
#include "controller.h"
|
||||
#include "host.h"
|
||||
|
||||
typedef int32_t app_btdm_ret_t;
|
||||
|
||||
static const uint8_t bt_addr[] = {0x12, 0x00, 0x12, 0x12, 0x12, 0x12};
|
||||
static const uint8_t ble_public_addr[] = {0x13, 0x00, 0x12, 0x12, 0x12, 0x12};
|
||||
static const uint8_t ble_static_addr[] = {0x13, 0x00, 0x12, 0x12, 0x12, 0xc2};
|
||||
|
||||
void app_btdm_start(void)
|
||||
{
|
||||
app_ble_init();
|
||||
}
|
||||
|
||||
void host_ready_cb(void)
|
||||
{
|
||||
struct app_task_event *event;
|
||||
/* notify application BTDM stack is ready. */
|
||||
event = app_task_event_alloc(APP_TASK_EVENT_HOST_INITED, 0, true);
|
||||
app_task_event_post(event, false);
|
||||
}
|
||||
|
||||
void app_btdm_init(void)
|
||||
{
|
||||
/* prepare for BTDM stack */
|
||||
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||
extern uint8_t CONTROLLER_CODE_OTA_BASE;
|
||||
uint32_t controller_code_base_addr = (uint32_t)&CONTROLLER_CODE_OTA_BASE;
|
||||
controller_start(BTDM_STACK_HCI_BAUDRATE, ble_public_addr, bt_addr, controller_code_base_addr);
|
||||
#elif defined(__GNUC__) || defined(__ICCARM__)
|
||||
extern const uint8_t controller_code_buffer[];
|
||||
controller_start(BTDM_STACK_HCI_BAUDRATE, ble_public_addr, bt_addr, (uint32_t)&controller_code_buffer[0]);
|
||||
#else
|
||||
#error "not supported platform"
|
||||
#endif
|
||||
|
||||
host_ble_start(BTDM_STACK_HCI_BAUDRATE, HOST_TASK_STACK_SIZE, HOST_TASK_PRIORITY, ble_static_addr);
|
||||
|
||||
/*
|
||||
* init MCU->BT pin, configure PMU_PIN_8 output BBG_EN signal, this pin is used to
|
||||
* notice BT core that MCU is in working mode.
|
||||
*/
|
||||
ool_write(PMU_REG_DIAG_CTRL, 0x82);
|
||||
ool_write(PMU_REG_PIN_IOMUX_H, 0x03);
|
||||
/* disable PMU pin input as default setting */
|
||||
ool_write16(PMU_REG_PIN_INPUT_EN, 0x0002);
|
||||
|
||||
/*
|
||||
* init BT->MCU pin, system should not enter sleep mode when this pin is low level.
|
||||
* This pin is used by BT core to notice MCU than BT core is in working mode.
|
||||
*/
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_HCI_RX);
|
||||
pmu_gpio_int_init(PMU_PIN_9, PMU_GPIO_PULL_UP, 0);
|
||||
pmu_enable_isr(PMU_GPIO_PMU_INT_MSK_BIT);
|
||||
NVIC_SetPriority(PMU_IRQn, 4);
|
||||
NVIC_EnableIRQ(PMU_IRQn);
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_ble_adv_start(uint16_t dur)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_ble_adv_stop(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_ble_disconnect(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_bt_access_mode_set(uint8_t mode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_bt_scan_start(uint16_t dur)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_bt_scan_stop(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_bt_connect(uint8_t *peer_addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_bt_disconnect(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
app_btdm_ret_t app_btdm_bt_profile_enable(uint16_t profiles)
|
||||
{
|
||||
return -1;
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
#ifndef _APP_BTDM_H
|
||||
#define _APP_BTDM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum {
|
||||
APP_BTDM_EVT_BLE_CONNECTED,
|
||||
APP_BTDM_EVT_BLE_DISCONNECTED,
|
||||
|
||||
APP_BTDM_EVT_BT_CONNECTED,
|
||||
APP_BTDM_EVT_BT_DISCONNECTED,
|
||||
APP_BTDM_EVT_HF_INCOMING,
|
||||
APP_BTDM_EVT_HF_CALL_ACTIVE,
|
||||
APP_BTDM_EVT_HF_CALL_REMOVE,
|
||||
APP_BTDM_EVT_A2DP_STREAM_STARTED,
|
||||
APP_BTDM_EVT_A2DP_STREAM_STOPPED,
|
||||
APP_BTDM_EVT_A2DP_STREAM_DATA,
|
||||
APP_BTDM_EVT_AVRCP_VOL_CHANGE,
|
||||
APP_BTDM_EVT_AVRCP_NEXT,
|
||||
APP_BTDM_EVT_AVRCP_PREV,
|
||||
APP_BTDM_EVT_AVRCP_PAUSE,
|
||||
APP_BTDM_EVT_AVRCP_FAST_FORWARD,
|
||||
APP_BTDM_EVT_AVRCP_FAST_BACKWARD,
|
||||
APP_BTDM_EVT_SCO_CREATED,
|
||||
APP_BTDM_EVT_SCO_REMOVED,
|
||||
APP_BTDM_EVT_SCO_DATA,
|
||||
};
|
||||
|
||||
enum {
|
||||
APP_BTDM_CODEC_SBC,
|
||||
APP_BTDM_CODEC_AAC,
|
||||
APP_BTDM_CODEC_mSBC,
|
||||
APP_BTDM_CODEC_PCM,
|
||||
APP_BTDM_CODEC_UNKNOWN,
|
||||
};
|
||||
|
||||
struct app_btdm_event_t {
|
||||
uint8_t event;
|
||||
union {
|
||||
struct {
|
||||
uint8_t *buffer;
|
||||
uint32_t length;
|
||||
} a2dp_data;
|
||||
struct {
|
||||
uint8_t codec_type;
|
||||
uint32_t sample_rate;
|
||||
} a2dp_codec;
|
||||
struct {
|
||||
bool valid;
|
||||
uint8_t codec_type;
|
||||
uint8_t *buffer;
|
||||
uint32_t length;
|
||||
} sco_data;
|
||||
struct {
|
||||
void *hf_channel;
|
||||
uint8_t codec_type;
|
||||
} sco_codec;
|
||||
} param;
|
||||
};
|
||||
|
||||
typedef void (*app_btdm_callback_t)(struct app_btdm_event_t *e);
|
||||
|
||||
void app_btdm_start(void);
|
||||
void app_btdm_init(void);
|
||||
|
||||
#endif // _APP_BTDM_H
|
134
MCU/examples/application/ble_simple_periphreal/Src/app_task.c
Normal file
134
MCU/examples/application/ble_simple_periphreal/Src/app_task.c
Normal file
@ -0,0 +1,134 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "app_at.h"
|
||||
#include "app_task.h"
|
||||
#include "app_ble.h"
|
||||
#include "app_btdm.h"
|
||||
#include "app_config.h"
|
||||
|
||||
static struct co_list event_list;
|
||||
|
||||
extern TaskHandle_t app_task_handle;
|
||||
|
||||
void hci_controller_read(void);
|
||||
void hci_host_read(void);
|
||||
|
||||
static void app_gpio_wakeup_demo_init(void)
|
||||
{
|
||||
printf("pmu_io0 wakeup init\r\n");
|
||||
|
||||
/*PMU_IO0 Wakeup Init */
|
||||
pmu_gpio_int_init(PMU_PIN_0, PMU_GPIO_PULL_UP, 1);
|
||||
pmu_enable_isr(PMU_GPIO_PMU_INT_MSK_BIT);
|
||||
|
||||
/* gpio_PD Wakeup Init */
|
||||
printf("gpio_PD wakeup init\r\n");
|
||||
SYSTEM->PortD_PullSelect = 0x0000ffff;
|
||||
SYSTEM->PortD_PullEN = 0x0000ffff;
|
||||
SYSTEM->PortD_InputCutoffDisable= 0x0000ffff;
|
||||
|
||||
pmu_enable_isr(PMU_GPIO_GROUPH_INT_MSK_BIT | PMU_GPIO_GROUPL_INT_MSK_BIT);
|
||||
ool_write(PMU_REG_WKUP_INT_EN,0x03);
|
||||
NVIC_EnableIRQ(PMU_IRQn);
|
||||
}
|
||||
|
||||
static void app_task_event_handler(void)
|
||||
{
|
||||
struct app_task_event *event = NULL;
|
||||
|
||||
vTaskSuspendAll();
|
||||
event = (struct app_task_event *)co_list_pop_front(&event_list);
|
||||
xTaskResumeAll();
|
||||
|
||||
if(event) {
|
||||
switch(event->event_type) {
|
||||
case APP_TASK_EVENT_AT_CMD:
|
||||
app_at_cmd_recv_handler(event->param, event->param_len);
|
||||
break;
|
||||
case APP_TASK_EVENT_HOST_INITED:
|
||||
app_btdm_start();
|
||||
break;
|
||||
case APP_TASK_EVENT_PMU_WAKEUP:
|
||||
printf("this is pmu_io0 wakeup\r\n");
|
||||
break;
|
||||
case APP_TASK_EVENT_GPIO_PD_WAKEUP:
|
||||
printf("this is gpio_PD wakeup\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
vPortFree((void *)event);
|
||||
}
|
||||
}
|
||||
|
||||
void app_task_event_post(struct app_task_event *event, bool high)
|
||||
{
|
||||
uint32_t old_basepri;
|
||||
|
||||
if(xPortIsInsideInterrupt()) {
|
||||
old_basepri = taskENTER_CRITICAL_FROM_ISR();
|
||||
if(high) {
|
||||
co_list_push_front(&event_list, &event->hdr);
|
||||
}
|
||||
else {
|
||||
co_list_push_back(&event_list, &event->hdr);
|
||||
}
|
||||
taskEXIT_CRITICAL_FROM_ISR(old_basepri);
|
||||
vTaskNotifyGiveFromISR(app_task_handle, NULL);
|
||||
}
|
||||
else {
|
||||
taskENTER_CRITICAL();
|
||||
if(high) {
|
||||
co_list_push_front(&event_list, &event->hdr);
|
||||
}
|
||||
else {
|
||||
co_list_push_back(&event_list, &event->hdr);
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
xTaskNotifyGive(app_task_handle);
|
||||
}
|
||||
}
|
||||
|
||||
struct app_task_event *app_task_event_alloc(uint8_t event_type, uint32_t param_len, bool block)
|
||||
{
|
||||
struct app_task_event *event = NULL;
|
||||
|
||||
while(event == NULL) {
|
||||
event = pvPortMalloc(sizeof(struct app_task_event) + param_len);
|
||||
if (event == NULL) {
|
||||
if (block) {
|
||||
vTaskDelay(10);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event->event_type = event_type;
|
||||
event->param_len = param_len;
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
static void app_task(void *arg)
|
||||
{
|
||||
co_list_init(&event_list);
|
||||
|
||||
app_btdm_init();
|
||||
|
||||
//wake up demo init
|
||||
// app_gpio_wakeup_demo_init();
|
||||
|
||||
while(1) {
|
||||
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
|
||||
app_task_event_handler();
|
||||
}
|
||||
}
|
||||
|
||||
void app_task_init(void)
|
||||
{
|
||||
xTaskCreate(app_task, "app", APP_TASK_STACK_SIZE, NULL, APP_TASK_PRIORITY, &app_task_handle);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
#ifndef _APP_TASK_H
|
||||
#define _APP_TASK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "co_list.h"
|
||||
|
||||
#define APP_TASK_EVENT_AT_CMD 0x00
|
||||
#define APP_TASK_EVENT_HOST_INITED 0x01
|
||||
#define APP_TASK_EVENT_PMU_WAKEUP 0x02
|
||||
#define APP_TASK_EVENT_GPIO_PD_WAKEUP 0x03
|
||||
|
||||
struct app_task_event {
|
||||
struct co_list_hdr hdr;
|
||||
|
||||
uint8_t event_type;
|
||||
|
||||
uint16_t param_len;
|
||||
uint8_t param[];
|
||||
};
|
||||
|
||||
void app_task_event_post(struct app_task_event *event, bool high);
|
||||
|
||||
struct app_task_event *app_task_event_alloc(uint8_t event_type, uint32_t param_len, bool block);
|
||||
|
||||
void app_task_init(void);
|
||||
|
||||
#endif // _APP_TASK_H
|
331
MCU/examples/application/ble_simple_periphreal/Src/main.c
Normal file
331
MCU/examples/application/ble_simple_periphreal/Src/main.c
Normal file
@ -0,0 +1,331 @@
|
||||
/* Standard includes. */
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "fr30xx.h"
|
||||
|
||||
/* FreeRTOS kernel includes. */
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "fdb_app.h"
|
||||
#include "host.h"
|
||||
|
||||
#include "app_task.h"
|
||||
#include "app_at.h"
|
||||
|
||||
/* hardware handlers */
|
||||
static UART_HandleTypeDef Uart3_handle;
|
||||
static CALI_HandleTypeDef cali_handle;
|
||||
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
/* FreeRTOS running status monitor task */
|
||||
static TaskHandle_t monitor_task_handle;
|
||||
volatile unsigned int CPU_RunTime;
|
||||
static uint8_t CPU_RunInfo[2048];
|
||||
#endif
|
||||
|
||||
/* APP task */
|
||||
TaskHandle_t app_task_handle;
|
||||
|
||||
void controller_start(void);
|
||||
void host_start(void);
|
||||
|
||||
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
|
||||
int fputc(int c, FILE *fp)
|
||||
{
|
||||
uart_transmit(&Uart3_handle, (void *)&c, 1);
|
||||
while(!(Uart3_handle.UARTx->USR.TFE));
|
||||
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
int _write(int file, char *ptr, int len)
|
||||
{
|
||||
uart_transmit(&Uart3_handle, (void *)ptr, len);
|
||||
while(!(Uart3_handle.UARTx->USR.TFE));
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __ICCARM__
|
||||
int putchar(int c)
|
||||
{
|
||||
uart_transmit(&Uart3_handle, (void *)&c, 1);
|
||||
while(!(Uart3_handle.UARTx->USR.TFE));
|
||||
return c;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
static void monitor_task(void *arg)
|
||||
{
|
||||
while(1) {
|
||||
vTaskDelay(2000000);
|
||||
|
||||
memset(CPU_RunInfo,0,2048);
|
||||
vTaskList((char *)&CPU_RunInfo);
|
||||
printf("---------------------------------------------\r\n");
|
||||
printf("name state priority stack seq\r\n");
|
||||
printf("%s", CPU_RunInfo);
|
||||
printf("---------------------------------------------\r\n");
|
||||
|
||||
memset(CPU_RunInfo,0,400);
|
||||
vTaskGetRunTimeStats((char *)&CPU_RunInfo);
|
||||
printf("name counter usage\r\n");
|
||||
printf("%s", CPU_RunInfo);
|
||||
printf("---------------------------------------------\r\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName )
|
||||
{
|
||||
( void ) pcTaskName;
|
||||
( void ) pxTask;
|
||||
|
||||
assert( 0 );
|
||||
}
|
||||
|
||||
void vApplicationTickHook(void)
|
||||
{
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
CPU_RunTime++;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cali_done_handle(CALI_HandleTypeDef *hcali, uint32_t result)
|
||||
{
|
||||
system_set_LPRCCLK(cali_calc_rc_freq(hcali, result));
|
||||
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_CALIBRATION);
|
||||
}
|
||||
|
||||
__RAM_CODE bool user_deep_sleep_check(void)
|
||||
{
|
||||
return host_before_sleep_check();
|
||||
}
|
||||
|
||||
__RAM_CODE void user_entry_before_sleep(void)
|
||||
{
|
||||
ool_write16(PMU_REG_PIN_PULL_EN, 0x3fff);
|
||||
ool_write16(PMU_REG_PIN_PULL_SEL, 0x3fff);
|
||||
|
||||
/* gpio_PD Wakeup Init */
|
||||
SYSTEM->PortD_InputCutoffDisable = 0x0000ffff;
|
||||
|
||||
ool_write(PMU_REG_PMU_GATE_M, ool_read(PMU_REG_PMU_GATE_M) | 0x40);
|
||||
}
|
||||
|
||||
__RAM_CODE void user_entry_after_sleep(void)
|
||||
{
|
||||
GPIO_InitTypeDef gpio_config;
|
||||
|
||||
/*
|
||||
* enable pull up of all 3.3v IO, these configuration will be latched by set
|
||||
* BIT6 of PMU_REG_PMU_GATE_M regsiter. used to avoid electric leakage
|
||||
*/
|
||||
SYSTEM->PortA_PullSelect = 0x0000ffff;
|
||||
SYSTEM->PortB_PullSelect = 0x00000fff;
|
||||
SYSTEM->PortC_PullSelect = 0x00000000;
|
||||
SYSTEM->PortD_PullSelect = 0x0000ffff;
|
||||
SYSTEM->PortA_PullEN = 0x00007fff;
|
||||
SYSTEM->PortB_PullEN = 0x00000dff;
|
||||
SYSTEM->PortC_PullEN = 0x00000000;
|
||||
SYSTEM->PortD_PullEN = 0x0000ffff;
|
||||
SYSTEM->QspiPadConfig.QSPI_PullEN = 0x0000000;
|
||||
|
||||
host_hci_reinit();
|
||||
ool_write(PMU_REG_PMU_GATE_M, ool_read(PMU_REG_PMU_GATE_M) & (~0x40));
|
||||
NVIC_SetPriority(UART0_IRQn, 2);
|
||||
NVIC_EnableIRQ(UART0_IRQn);
|
||||
NVIC_SetPriority(PMU_IRQn, 4);
|
||||
NVIC_EnableIRQ(PMU_IRQn);
|
||||
|
||||
/* configure PA0 and PA1 to UART0 function */
|
||||
__SYSTEM_GPIOA_CLK_ENABLE();
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_5;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||||
gpio_init(GPIOB, &gpio_config);
|
||||
|
||||
/* UART0: used for Log and AT command */
|
||||
__SYSTEM_UART3_CLK_ENABLE();
|
||||
Uart3_handle.UARTx = UART3;
|
||||
Uart3_handle.Init.BaudRate = 115200;
|
||||
Uart3_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
|
||||
Uart3_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
Uart3_handle.Init.Parity = UART_PARITY_NONE;
|
||||
Uart3_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
|
||||
Uart3_handle.TxCpltCallback = NULL;
|
||||
Uart3_handle.RxCpltCallback = app_at_rx_done;
|
||||
uart_init(&Uart3_handle);
|
||||
|
||||
/* restart calibration */
|
||||
__SYSTEM_CALI_CLK_ENABLE();
|
||||
cali_handle.mode = CALI_UP_MODE_NORMAL;
|
||||
cali_handle.rc_cnt = 60;
|
||||
cali_handle.DoneCallback = cali_done_handle;
|
||||
cali_init(&cali_handle);
|
||||
cali_start_IT(&cali_handle);
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_CALIBRATION);
|
||||
NVIC_SetPriority(CALI_IRQn, 2);
|
||||
NVIC_EnableIRQ(CALI_IRQn);
|
||||
}
|
||||
|
||||
int main( void )
|
||||
{
|
||||
GPIO_InitTypeDef gpio_config;
|
||||
|
||||
system_delay_us(1000000);
|
||||
|
||||
/* configure all interrupt priority to 2 */
|
||||
*(volatile uint32_t *)0xE000E400 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E404 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E408 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E40C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E410 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E414 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E418 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E41C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E420 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E424 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E428 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E42C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E430 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E434 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E438 = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E43C = 0x40404040;
|
||||
*(volatile uint32_t *)0xE000E440 = 0x40404040;
|
||||
|
||||
pmu_init();
|
||||
/* Power Keep: 32KB PRAM, 128KB SRAM */
|
||||
ool_write16(PMU_REG_PKSRAM_GATE, ~0x0063);
|
||||
|
||||
/* reinit flash controller */
|
||||
system_cache_enable(true);
|
||||
SYSTEM->QspiPadConfig.QSPI_FuncMux = 0x00000500;
|
||||
flash_enable_quad(QSPI0);
|
||||
flash_init_controller(QSPI0, FLASH_RD_TYPE_DUAL, FLASH_WR_TYPE_SINGLE);
|
||||
flash_set_baudrate(QSPI0, QSPI_BAUDRATE_DIV_4);
|
||||
|
||||
/* configure PB4 and PB5 to UART3 function */
|
||||
gpio_config.Pin = GPIO_PIN_4 | GPIO_PIN_5;
|
||||
gpio_config.Mode = GPIO_MODE_AF_PP;
|
||||
gpio_config.Pull = GPIO_PULLUP;
|
||||
gpio_config.Alternate = GPIO_FUNCTION_1;
|
||||
gpio_init(GPIOB, &gpio_config);
|
||||
|
||||
/* UART2: used for Log and AT command */
|
||||
__SYSTEM_UART3_CLK_ENABLE();
|
||||
Uart3_handle.UARTx = UART3;
|
||||
Uart3_handle.Init.BaudRate = 115200;
|
||||
Uart3_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
|
||||
Uart3_handle.Init.StopBits = UART_STOPBITS_1;
|
||||
Uart3_handle.Init.Parity = UART_PARITY_NONE;
|
||||
Uart3_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
|
||||
Uart3_handle.TxCpltCallback = NULL;
|
||||
Uart3_handle.RxCpltCallback = app_at_rx_done;
|
||||
uart_init(&Uart3_handle);
|
||||
NVIC_SetPriority(UART3_IRQn, 4);
|
||||
NVIC_EnableIRQ(UART3_IRQn);
|
||||
|
||||
/* do calibration, get current RC frequency */
|
||||
__SYSTEM_CALI_CLK_ENABLE();
|
||||
cali_handle.mode = CALI_UP_MODE_NORMAL;
|
||||
cali_handle.rc_cnt = 200;
|
||||
cali_handle.DoneCallback = cali_done_handle;
|
||||
cali_init(&cali_handle);
|
||||
cali_start_IT(&cali_handle);
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_CALIBRATION);
|
||||
NVIC_SetPriority(CALI_IRQn, 4);
|
||||
NVIC_EnableIRQ(CALI_IRQn);
|
||||
|
||||
/* init flashdb to store user data */
|
||||
flashdb_init();
|
||||
printf("start running\r\n");
|
||||
/* Create tasks */
|
||||
#if ENABLE_RTOS_MONITOR == 1
|
||||
xTaskCreate(monitor_task, "monitor", MONITOR_TASK_STACK_SIZE, NULL, MONITOR_TASK_PRIORITY, &monitor_task_handle);
|
||||
#endif
|
||||
|
||||
/* create application task */
|
||||
app_task_init();
|
||||
|
||||
/* initialize AT command */
|
||||
app_at_init(&Uart3_handle);
|
||||
|
||||
/*
|
||||
* enable pull up of all 3.3v IO, these configuration will be latched by set
|
||||
* BIT6 of PMU_REG_PMU_GATE_M regsiter. used to avoid electric leakage
|
||||
*/
|
||||
SYSTEM->PortA_PullSelect = 0x0000ffff;
|
||||
SYSTEM->PortB_PullSelect = 0x00000fff;
|
||||
SYSTEM->PortC_PullSelect = 0x00000000;
|
||||
SYSTEM->PortD_PullSelect = 0x0000ffff;
|
||||
SYSTEM->PortA_PullEN = 0x00007fff;
|
||||
SYSTEM->PortB_PullEN = 0x00000dff;
|
||||
SYSTEM->PortC_PullEN = 0x00000000;
|
||||
SYSTEM->PortD_PullEN = 0x0000ffff;
|
||||
SYSTEM->QspiPadConfig.QSPI_PullEN = 0x0000000;
|
||||
|
||||
/* enable sleep */
|
||||
// system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_DISABLE);
|
||||
|
||||
printf("FR5090: BTDM test: 0x%04x.\r\n", ool_read16(PMU_REG_PIN_INPUT_EN));
|
||||
|
||||
/* Start the scheduler itself. */
|
||||
vTaskStartScheduler();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uart3_irq(void)
|
||||
{
|
||||
uart_IRQHandler(&Uart3_handle);
|
||||
}
|
||||
|
||||
void PMU_GPIO_GROUPH_IRQHandler(void)
|
||||
{
|
||||
struct app_task_event *event;
|
||||
event = app_task_event_alloc(APP_TASK_EVENT_GPIO_PD_WAKEUP, 0, true);
|
||||
app_task_event_post(event, false);
|
||||
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_DISABLE);
|
||||
}
|
||||
|
||||
void PMU_GPIO_PMU_IRQHandler(void)
|
||||
{
|
||||
uint16_t data = ool_read16(PMU_REG_PIN_DATA);
|
||||
uint16_t result = ool_read16(PMU_REG_PIN_XOR_RESULT);
|
||||
|
||||
/* update last value with latest data */
|
||||
ool_write16(PMU_REG_PIN_LAST_V, data);
|
||||
/* clear last XOR result */
|
||||
ool_write16(PMU_REG_PIN_XOR_CLR, result);
|
||||
|
||||
if (((data & PMU_PIN_0) == 0) &(ool_read(PMU_REG_PIN_XOR_EN) & PMU_PIN_0)) {
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_DISABLE);
|
||||
|
||||
struct app_task_event *event;
|
||||
event = app_task_event_alloc(APP_TASK_EVENT_PMU_WAKEUP, 0, true);
|
||||
app_task_event_post(event, false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (data & PMU_PIN_9) {
|
||||
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_HCI_RX);
|
||||
}
|
||||
else {
|
||||
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_HCI_RX);
|
||||
}
|
||||
}
|
||||
|
||||
void cali_irq(void)
|
||||
{
|
||||
cali_IRQHandler(&cali_handle);
|
||||
}
|
||||
|
Reference in New Issue
Block a user