314 lines
10 KiB
C
314 lines
10 KiB
C
#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 *)¶m_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 *)¶m_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 *)¶m_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 *)¶m_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;
|
|
}
|