MXC-A36_2024.04.18/fr3092_mcu/examples/common/btdm/controller.c

314 lines
10 KiB
C
Raw Normal View History

2024-04-17 19:45:26 +08:00
#include "fr30xx.h"
#include "FreeRTOS.h"
#include "SWD.h"
#include "fdb_app.h"
#include "controller.h"
#define CONTROLLER_CODE_SPLIT
#define HCI_UART UART0
#define HCI_UART_IRQn UART0_IRQn
#define CONTROLLER_PARAM_DUMMY 0x00
#define CONTROLLER_PARAM_BAUDRATE 0x01
#define CONTROLLER_PARAM_KEY 0x02
#define CONTROLLER_PARAM_BT_ADDR 0x03
#define CONTROLLER_PARAM_BLE_ADDR 0x04
static const uint8_t app_boot_conn_req[] = {'f','r','e','q','c','h','i','p'};//from embedded to pc, request
static const uint8_t app_boot_conn_ack[] = {'F','R','1','0','1','0','O','K'};//from pc to embedded,ack
static const uint8_t app_boot_conn_success[] = {'o','k'};
static const uint8_t controller_param_header[] = {'f', 'r', 'e', 'q'};
static const uint8_t controller_param_tail[] = {'c', 'h', 'i', 'p'};
///default feature
//static uint8_t bt_feature_param[] = {
// 0x41,0x08,
// 0xaf,0x2a,0x4d,0xde,0xc3,0x2f,0x5b,0x87,
//};
static uint8_t btdm_internal_param[] = {
///bt_feature:disable 3M(Byte3,bit3),0xde->0xda
0x41,0x08,
0xaf,0x2a,0x4d,0xda,0xc3,0x2f,0x5b,0x87,
///to add
};
/* hardware handlers */
static UART_HandleTypeDef HCI_handle;
bool controller_start(uint32_t baudrate, const uint8_t *ble_addr, const uint8_t *bt_addr, uint32_t src_addr)
{
GPIO_InitTypeDef gpio_config;
uint8_t buffer[8];
uint32_t length;
uint8_t *src, *dst;
uint16_t tx_length;
uint8_t opcode, param_type;
struct {
uint32_t dst;
uint32_t len;
} header;
src_addr += 0x10;
/* configure PA0, PA1, PA2, PA3 to UART0 function */
gpio_config.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3;
gpio_config.Mode = GPIO_MODE_AF_PP;
gpio_config.Pull = GPIO_PULLUP;
gpio_config.Alternate = GPIO_FUNCTION_1;
gpio_init(GPIOA, &gpio_config);
/* UART0: used for Log and AT command */
__SYSTEM_UART0_CLK_ENABLE();
HCI_handle.UARTx = HCI_UART;
HCI_handle.Init.BaudRate = 115200;
HCI_handle.Init.DataLength = UART_DATA_LENGTH_8BIT;
HCI_handle.Init.StopBits = UART_STOPBITS_1;
HCI_handle.Init.Parity = UART_PARITY_NONE;
HCI_handle.Init.FIFO_Mode = UART_FIFO_ENABLE;
HCI_handle.TxCpltCallback = NULL;
HCI_handle.RxCpltCallback = NULL;
uart_init(&HCI_handle);
/* keep RTS is inactive before HCI is ready */
__UART_AUTO_FLOW_CONTROL_DISABLE(HCI_handle.UARTx);
__UART_RTS_INACTIVE(HCI_handle.UARTx);
/* reset controller */
/* configure PA15 GPIO function */
__SYSTEM_GPIOA_CLK_ENABLE();
gpio_config.Pin = GPIO_PIN_15;
gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
gpio_config.Pull = GPIO_PULLUP;
gpio_config.Alternate = GPIO_FUNCTION_0;
gpio_init(GPIOA, &gpio_config);
gpio_write_pin(GPIOA, GPIO_PIN_15, 0);
system_delay_us(3000);
gpio_write_pin(GPIOA, GPIO_PIN_15, 1);
/* change PA15 to input mode, used to avoid current leakage */
gpio_config.Pin = GPIO_PIN_15;
gpio_config.Mode = GPIO_MODE_INPUT;
gpio_config.Pull = GPIO_NOPULL;
gpio_config.Alternate = GPIO_FUNCTION_0;
gpio_init(GPIOA, &gpio_config);
/* hand shake with controller */
uart_receive(&HCI_handle, buffer, 8);
while (memcmp(buffer, app_boot_conn_req, 8)) {
memcpy(&buffer[0], &buffer[1], 7);
uart_receive(&HCI_handle, &buffer[7], 1);
}
uart_transmit(&HCI_handle, (void *)app_boot_conn_ack, 8);
uart_receive(&HCI_handle, buffer, 2);
if (memcmp(buffer, app_boot_conn_success, 2)) {
return false;
}
/* SWD Enable RAM */
SWD_W_SystemReg();
/* change uart baudrate */
opcode = 0x12;
buffer[0] = 11; // 921600
buffer[1] = 0;
buffer[2] = 0;
buffer[3] = 0;
buffer[4] = 0;
buffer[5] = 0;
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&buffer, 6);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x13) {
return false;
}
HCI_handle.Init.BaudRate = 921600;
uart_config_baudRate(&HCI_handle);
system_delay_us(5000);
memcpy((void *)&header, (void *)src_addr, sizeof(header));
src_addr += sizeof(header);
/* write code into RAM */
opcode = 0x04;
src = (void *)src_addr;
dst = (void *)header.dst;
length = header.len;
while (length) {
tx_length = length > 256 ? 256 : length;
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
uart_transmit(&HCI_handle, (void *)&tx_length, 2);
uart_transmit(&HCI_handle, src, tx_length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
length -= tx_length;
src += tx_length;
dst += tx_length;
}
src_addr += header.len;
/* write parameters to exchange memory */
opcode = 0x04;
dst = (void *)0x40014000;
/* write header to remote device */
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
length = sizeof(controller_param_header);
dst += length;
uart_transmit(&HCI_handle, (void *)&length, 2);
uart_transmit(&HCI_handle, (void *)&controller_param_header[0], length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
/* write baudrate to remote device */
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
length = sizeof(baudrate) + 1 + 2;
dst += length;
uart_transmit(&HCI_handle, (void *)&length, 2);
param_type = CONTROLLER_PARAM_BAUDRATE;
uart_transmit(&HCI_handle, (void *)&param_type, 1);
length = sizeof(baudrate);
uart_transmit(&HCI_handle, (void *)&length, 2);
uart_transmit(&HCI_handle, (void *)&baudrate, length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
/* write keys to remote device */
length = flashdb_get_length(FDB_KEY_CONTROLLER_INFO) + sizeof(btdm_internal_param);
if (length) {
uint8_t *tmp = pvPortMalloc(length);
uint16_t sub_length = length;
uint16_t key_len = length - sizeof(btdm_internal_param);
if(key_len){
flashdb_get(FDB_KEY_CONTROLLER_INFO, tmp, key_len);
memcpy(&tmp[key_len],btdm_internal_param,sizeof(btdm_internal_param));
}
else{
memcpy(&tmp[0],btdm_internal_param,sizeof(btdm_internal_param));
}
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
length = sub_length + 1 + 2;
dst += length;
uart_transmit(&HCI_handle, (void *)&length, 2);
param_type = CONTROLLER_PARAM_KEY;
uart_transmit(&HCI_handle, (void *)&param_type, 1);
length = sub_length;
uart_transmit(&HCI_handle, (void *)&length, 2);
uart_transmit(&HCI_handle, (void *)&tmp[0], length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
vPortFree(tmp);
return false;
}
vPortFree(tmp);
}
/* write bt address to remote device */
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
length = 6 + 1 + 2;
dst += length;
uart_transmit(&HCI_handle, (void *)&length, 2);
param_type = CONTROLLER_PARAM_BT_ADDR;
uart_transmit(&HCI_handle, (void *)&param_type, 1);
length = 6;
uart_transmit(&HCI_handle, (void *)&length, 2);
uart_transmit(&HCI_handle, (void *)&bt_addr[0], length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
/* write parameter to remote device */
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
length = 6 + 1 + 2;
dst += length;
uart_transmit(&HCI_handle, (void *)&length, 2);
param_type = CONTROLLER_PARAM_BLE_ADDR;
uart_transmit(&HCI_handle, (void *)&param_type, 1);
length = 6;
uart_transmit(&HCI_handle, (void *)&length, 2);
uart_transmit(&HCI_handle, (void *)&ble_addr[0], length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
/* write tail to remote device */
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
length = sizeof(controller_param_tail);
dst += length;
uart_transmit(&HCI_handle, (void *)&length, 2);
uart_transmit(&HCI_handle, (void *)&controller_param_tail[0], length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
/* boot from RAM */
opcode = 0x2b;
dst = (void *)header.dst;
tx_length = 0;
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
uart_transmit(&HCI_handle, (void *)&tx_length, 2);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x2c) {
return false;
}
memcpy((void *)&header, (void *)src_addr, sizeof(header));
src_addr += sizeof(header);
system_delay_us(50000);
opcode = 0x04;
if (header.len) {
src = (void *)src_addr;
dst = (void *)header.dst;
length = header.len;
while (length) {
tx_length = length > 256 ? 256 : length;
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
uart_transmit(&HCI_handle, (void *)&tx_length, 2);
uart_transmit(&HCI_handle, src, tx_length);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x05) {
return false;
}
length -= tx_length;
src += tx_length;
dst += tx_length;
}
src_addr += header.len;
/* disconnect */
opcode = 0x10;
dst = (void *)1; /* normal disconnect */
tx_length = 0;
uart_transmit(&HCI_handle, (void *)&opcode, 1);
uart_transmit(&HCI_handle, (void *)&dst, 4);
uart_transmit(&HCI_handle, (void *)&tx_length, 2);
uart_receive(&HCI_handle, buffer, 7);
if (buffer[0] != 0x11) {
return false;
}
}
return true;
}