800*320工程文件+初始demo提交

This commit is contained in:
2024-03-07 16:46:43 +08:00
parent 33e6eb45b3
commit 70ec3005bb
3306 changed files with 3374364 additions and 2563 deletions

View File

@ -0,0 +1,445 @@
/*
******************************************************************************
* @file SWD.c
* @author FreqChip Firmware Team
* @version V1.0.0
* @date 2023
* @brief SWD module Demo.
******************************************************************************
* @attention
*
* Copyright (c) 2023 FreqChip.
* All rights reserved.
******************************************************************************
*/
#include "co_util.h"
#include "fr30xx.h"
#include "SWD.h"
#define PMU_SWD_IE 0x43
#define PMU_SWD_DATA 0x49
#define PMU_SWD_DIR 0x4b
#define PMU_SWD_IOMUX 0x5b
#define PMU_SWD_PULL_EN 0x45
#define PMU_SWD_PULL_SEL 0x47
//#define PMU_SWD_IE 0x42
//#define PMU_SWD_DATA 0x48
//#define PMU_SWD_DIR 0x4a
//#define PMU_SWD_IOMUX 0x59
#define SWD_CLK_H 0x01
#define SWD_CLK_L 0x02
#define SWD_DATA_H 0x02
#define SWD_DATA_L 0x01
static uint8_t SWD_DATA,SWD_CLK;
#define ool_write_ram(addr, data) frspim_wr_ram(FR_SPI_PMU_CHAN,(addr),1, (data))
#define ool_read_ram(addr) (uint8_t)frspim_rd_ram(FR_SPI_PMU_CHAN,(addr),1)
/*---------------------------------- Porting ----------------------------------------*/
#define RAM_CODE __RAM_CODE
#define SWD_CLK_SET_H() {SWD_CLK = SWD_CLK_H; \
ool_write_ram(PMU_SWD_DATA,SWD_DATA | SWD_CLK);}
#define SWD_CLK_SET_L() {SWD_CLK = SWD_CLK_L; \
ool_write_ram(PMU_SWD_DATA,SWD_DATA & SWD_CLK);}
#define SWD_IO_SET_H() {SWD_DATA = SWD_DATA_H; \
ool_write_ram(PMU_SWD_DATA,SWD_CLK | SWD_DATA);}
#define SWD_IO_SET_L() {SWD_DATA = SWD_DATA_L; \
ool_write_ram(PMU_SWD_DATA,SWD_CLK & SWD_DATA);}
#define SWD_IO_IN() (ool_read_ram(PMU_SWD_DATA) & 0x02)
#define SWD_IO_OUT_ENABLE() (ool_write_ram(PMU_SWD_DIR,0x00))
#define SWD_IO_OUT_DISABLE() (ool_write_ram(PMU_SWD_DIR,0x02))
void SWD_IO_init(void)
{
ool_write_ram(PMU_SWD_PULL_EN, 0x03);
ool_write_ram(PMU_SWD_PULL_SEL, 0x00);
ool_write_ram(PMU_SWD_IE, 0x03);
ool_write_ram(PMU_SWD_DIR, 0x00);
ool_write_ram(PMU_SWD_DATA, 0x03);
ool_write_ram(PMU_SWD_IOMUX, 0x00);
SWD_CLK_SET_L();
SWD_IO_SET_L();
}
/*---------------------------------- Porting end ----------------------------------------*/
#define SW_CLOCK_CYCLE() \
SWD_CLK_SET_H(); \
SWD_DELAY(); \
SWD_CLK_SET_L(); \
SWD_DELAY()
#define SW_WRITE_BIT_0() \
SWD_IO_SET_L(); \
SWD_DELAY(); \
SWD_DELAY(); \
SWD_CLK_SET_H(); \
SWD_DELAY(); \
SWD_DELAY(); \
SWD_CLK_SET_L()
#define SW_WRITE_BIT_1() \
SWD_IO_SET_H(); \
SWD_DELAY(); \
SWD_DELAY(); \
SWD_CLK_SET_H(); \
SWD_DELAY(); \
SWD_DELAY(); \
SWD_CLK_SET_L()
#define SW_READ_BIT(BIT) \
SWD_CLK_SET_H(); \
SWD_DELAY(); \
SWD_DELAY(); \
SWD_CLK_SET_L(); \
SWD_DELAY(); \
SWD_DELAY(); \
BIT = SWD_IO_IN()
RAM_CODE static inline void SW_WRITE_BIT(uint32_t BIT)
{
switch (BIT)
{
case 0:
{
SW_WRITE_BIT_0();
}break;
case 1:
{
SW_WRITE_BIT_1();
}break;
default:break;
}
}
RAM_CODE int SWD_TransferFunction(uint32_t request, uint32_t *data, uint32_t Trailing)
{
int i;
uint32_t W_Parity;
uint32_t ACK;
bool BitBuffer[33];
bool ACKBuffer[3];
bool APnDP = (request >> 0) & 1;
bool RnW = (request >> 1) & 1;
bool A2 = (request >> 2) & 1;
bool A3 = (request >> 3) & 1;
bool parity = (APnDP + RnW + A2 + A3) & 0x01;
if (RnW == 0)
{
/* Prepare data */
W_Parity = 0;
for (i = 0; i < 32; i++)
{
BitBuffer[i] = (*data >> i) & 1;
W_Parity += BitBuffer[i];
}
W_Parity &= 0x01;
BitBuffer[32] = W_Parity;
}
SWD_IO_OUT_ENABLE();
/* Packet Request */
SW_WRITE_BIT(1U); /* Start Bit */
SW_WRITE_BIT(APnDP); /* APnDP Bit */
SW_WRITE_BIT(RnW); /* RnW Bit */
SW_WRITE_BIT(A2); /* A2 Bit */
SW_WRITE_BIT(A3); /* A3 Bit */
SW_WRITE_BIT(parity); /* parity Bit */
SW_WRITE_BIT(0U); /* Stop Bit */
SW_WRITE_BIT(1U); /* Park Bit */
/* Turnaround */
SWD_IO_OUT_DISABLE();
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
SWD_CLK_SET_H();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
/* Acknowledge response */
SW_READ_BIT(ACKBuffer[0]);
SW_READ_BIT(ACKBuffer[1]);
SW_READ_BIT(ACKBuffer[2]);
ACK = (ACKBuffer[0] << 2) | (ACKBuffer[1] << 1) | ACKBuffer[2];
/* OK response */
if (ACK == DAP_TRANSFER_OK)
{
/* Data transfer */
if (RnW == 1)
{
/* Read data */
/* Read RDATA[0:31] */
SW_READ_BIT(BitBuffer[0]);
SW_READ_BIT(BitBuffer[1]);
SW_READ_BIT(BitBuffer[2]);
SW_READ_BIT(BitBuffer[3]);
SW_READ_BIT(BitBuffer[4]);
SW_READ_BIT(BitBuffer[5]);
SW_READ_BIT(BitBuffer[6]);
SW_READ_BIT(BitBuffer[7]);
SW_READ_BIT(BitBuffer[8]);
SW_READ_BIT(BitBuffer[9]);
SW_READ_BIT(BitBuffer[10]);
SW_READ_BIT(BitBuffer[11]);
SW_READ_BIT(BitBuffer[12]);
SW_READ_BIT(BitBuffer[13]);
SW_READ_BIT(BitBuffer[14]);
SW_READ_BIT(BitBuffer[15]);
SW_READ_BIT(BitBuffer[16]);
SW_READ_BIT(BitBuffer[17]);
SW_READ_BIT(BitBuffer[18]);
SW_READ_BIT(BitBuffer[19]);
SW_READ_BIT(BitBuffer[20]);
SW_READ_BIT(BitBuffer[21]);
SW_READ_BIT(BitBuffer[22]);
SW_READ_BIT(BitBuffer[23]);
SW_READ_BIT(BitBuffer[24]);
SW_READ_BIT(BitBuffer[25]);
SW_READ_BIT(BitBuffer[26]);
SW_READ_BIT(BitBuffer[27]);
SW_READ_BIT(BitBuffer[28]);
SW_READ_BIT(BitBuffer[29]);
SW_READ_BIT(BitBuffer[30]);
SW_READ_BIT(BitBuffer[31]);
/* Read Parity */
SW_READ_BIT(BitBuffer[32]);
/* Trailing */
__NOP();__NOP();__NOP();__NOP();__NOP();
for (i = 0; i < Trailing; i++)
{
SW_CLOCK_CYCLE();
}
*data = 0;
for (i = 0; i < 32; i++)
{
*data |= (BitBuffer[i] << i);
}
}
else
{
/* Write data */
/* Turnaround */
SWD_CLK_SET_H();
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
SWD_CLK_SET_L();
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
SWD_CLK_SET_H();
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
SWD_CLK_SET_L();
__NOP();__NOP();__NOP();__NOP();__NOP();SWD_DELAY();
SWD_IO_OUT_ENABLE();
/* Write WDATA[0:31] */
SW_WRITE_BIT(BitBuffer[0]);
SW_WRITE_BIT(BitBuffer[1]);
SW_WRITE_BIT(BitBuffer[2]);
SW_WRITE_BIT(BitBuffer[3]);
SW_WRITE_BIT(BitBuffer[4]);
SW_WRITE_BIT(BitBuffer[5]);
SW_WRITE_BIT(BitBuffer[6]);
SW_WRITE_BIT(BitBuffer[7]);
SW_WRITE_BIT(BitBuffer[8]);
SW_WRITE_BIT(BitBuffer[9]);
SW_WRITE_BIT(BitBuffer[10]);
SW_WRITE_BIT(BitBuffer[11]);
SW_WRITE_BIT(BitBuffer[12]);
SW_WRITE_BIT(BitBuffer[13]);
SW_WRITE_BIT(BitBuffer[14]);
SW_WRITE_BIT(BitBuffer[15]);
SW_WRITE_BIT(BitBuffer[16]);
SW_WRITE_BIT(BitBuffer[17]);
SW_WRITE_BIT(BitBuffer[18]);
SW_WRITE_BIT(BitBuffer[19]);
SW_WRITE_BIT(BitBuffer[20]);
SW_WRITE_BIT(BitBuffer[21]);
SW_WRITE_BIT(BitBuffer[22]);
SW_WRITE_BIT(BitBuffer[23]);
SW_WRITE_BIT(BitBuffer[24]);
SW_WRITE_BIT(BitBuffer[25]);
SW_WRITE_BIT(BitBuffer[26]);
SW_WRITE_BIT(BitBuffer[27]);
SW_WRITE_BIT(BitBuffer[28]);
SW_WRITE_BIT(BitBuffer[29]);
SW_WRITE_BIT(BitBuffer[30]);
SW_WRITE_BIT(BitBuffer[31]);
/* Write Parity Bit */
SW_WRITE_BIT(BitBuffer[32]);
SWD_IO_OUT_DISABLE();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
/* Trailing */
for (i = 0; i < Trailing; i++)
{
SW_CLOCK_CYCLE();
}
}
}
else
{
/* WAIT or FAULT response */
if (ACK == DAP_TRANSFER_WAIT)
{
SW_CLOCK_CYCLE();
SW_CLOCK_CYCLE();
return -1;
}
else
{
return -2;
}
}
return 0;
}
RAM_CODE void SWD_Line_Reset(uint32_t fu32_CNT)
{
int i;
SWD_IO_OUT_ENABLE();
SWD_IO_SET_H();
for (i = 0; i < fu32_CNT; i++)
{
SW_CLOCK_CYCLE();
}
SWD_IO_SET_L();
for (int i = 0; i < 16; i++)
{
SW_CLOCK_CYCLE();
}
}
RAM_CODE void SWD_Connect(void)
{
uint32_t Data;
/* Line Reset */
SWD_Line_Reset(56);
SWD_Line_Reset(59);
SWD_Line_Reset(59);
for (int i = 0; i < 16; i++)
{
SW_CLOCK_CYCLE();
}
/* Read IDCODE */
SWD_TransferFunction(REQ_DP|REQ_R|REQ_ADDR_0, &Data, 6); co_delay_10us(1);
}
RAM_CODE void SWD_Enable_Debug(void)
{
uint32_t Data;
/* Write Abort */
Data = 0x0000001E;
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_0, &Data, 7); co_delay_10us(1);
/* Write CTRL/STAT */
Data = 0x50000000;
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_1, &Data, 7); co_delay_10us(1);
}
RAM_CODE void SWD_W_REG(uint32_t ADDR, uint32_t Value)
{
uint32_t Data;
/* Write Abort */
Data = 0x0000001E;
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_0, &Data, 7);
/* Write Select */
Data = 0x00000000;
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_2, &Data, 0);
/* Write CSW */
Data = 0x23000012;
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_0, &Data, 0);
/* Write TAR */
Data = ADDR;
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_1, &Data, 0);
/* Write DRW */
Data = Value;
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_3, &Data, 7);
/* Read RDBUFF */
SWD_TransferFunction(REQ_DP|REQ_R|REQ_ADDR_3, &Data, 3);
}
RAM_CODE void SWD_R_REG(uint32_t ADDR, uint32_t *Buffer, uint32_t Length)
{
int ERR;int first = 0;
uint32_t Data;
/* Write Abort */
Data = 0x0000001E;
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_0, &Data, 7);
/* Write Select */
Data = 0x00000000;
SWD_TransferFunction(REQ_DP|REQ_W|REQ_ADDR_2, &Data, 0);
/* Write CSW */
Data = 0x23000012;
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_0, &Data, 0);
/* Write TAR */
Data = ADDR;
SWD_TransferFunction(REQ_AP|REQ_W|REQ_ADDR_1, &Data, 0);
while(Length)
{
/* Read DRW */
ERR = SWD_TransferFunction(REQ_AP|REQ_R|REQ_ADDR_3, Buffer, 3);
if (ERR == 0)
{
if (first)
{
Length--;
Buffer++;
}
first++;
}
else if (ERR == -2)
Length = 0;
SWD_DELAY();
SWD_DELAY();
}
}
RAM_CODE void SWD_W_SystemReg(void)
{
SWD_IO_init();
SWD_Connect();
SWD_Enable_Debug();
/* BIT24: enable cache clock */
SWD_W_REG(0x50000008, 0x09000803);
/* enable exchange memory clock */
SWD_W_REG(0x50000010, 0x1000);
}

View File

@ -0,0 +1,140 @@
/*
******************************************************************************
* @file SWD.h
* @author FreqChip Firmware Team
* @version V1.0.0
* @date 2023
* @brief Header file of SWD.c
******************************************************************************
* @attention
*
* Copyright (c) 2023 FreqChip.
* All rights reserved.
******************************************************************************
*/
#ifndef __SWD_H__
#define __SWD_H__
#include <stdint.h>
#include <stdbool.h>
#include "fr30xx.h"
static inline void SWD_DELAY(void)
{
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
}
#define DELAY_CYCLES 10U
static inline void PIN_DELAY(void)
{
#if (DELAY_CYCLES >= 1U)
__NOP();
#endif
#if (DELAY_CYCLES >= 2U)
__NOP();
#endif
#if (DELAY_CYCLES >= 3U)
__NOP();
#endif
#if (DELAY_CYCLES >= 4U)
__NOP();
#endif
#if (DELAY_CYCLES >= 5U)
__NOP();
#endif
#if (DELAY_CYCLES >= 6U)
__NOP();
#endif
#if (DELAY_CYCLES >= 7U)
__NOP();
#endif
#if (DELAY_CYCLES >= 8U)
__NOP();
#endif
#if (DELAY_CYCLES >= 9U)
__NOP();
#endif
#if (DELAY_CYCLES >= 10U)
__NOP();
#endif
#if (DELAY_CYCLES >= 20U)
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
#endif
#if (DELAY_CYCLES >= 30U)
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
#endif
#if (DELAY_CYCLES >= 40U)
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
#endif
#if (DELAY_CYCLES >= 50U)
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
#endif
#if (DELAY_CYCLES >= 60U)
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
__NOP();__NOP();__NOP();__NOP();__NOP();
#endif
}
#if DELAY_CYCLES == 0
#define SWD_DELAY()
#else
#define SWD_DELAY() PIN_DELAY()
#endif
// DAP Transfer Request
#define DAP_TRANSFER_APnDP (1)
#define DAP_TRANSFER_RnW (2)
#define DAP_TRANSFER_A2 (3)
#define DAP_TRANSFER_A3 (8)
#define REQ_AP (1)
#define REQ_DP (0)
#define REQ_R (2)
#define REQ_W (0)
#define REQ_ADDR_0 (0x00)
#define REQ_ADDR_1 (0x04)
#define REQ_ADDR_2 (0x08)
#define REQ_ADDR_3 (0x0C)
// DAP Transfer Response
#define DAP_TRANSFER_OK (0x04)
#define DAP_TRANSFER_WAIT (0x02)
#define DAP_TRANSFER_FAULT (0x01)
/* Exported functions --------------------------------------------------------*/
void SWD_IO_init(void);
void SWD_Connect(void);
void SWD_Enable_Debug(void);
void SWD_W_REG(uint32_t ADDR, uint32_t Value);
void SWD_R_REG(uint32_t ADDR, uint32_t *Buffer, uint32_t Length);
void SWD_W_SystemReg(void);
#endif

View File

@ -0,0 +1,39 @@
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "fr30xx.h"
#include "heap.h"
#define configTOTAL_BTDM_HEAP_SIZE ( ( 20 * 1024 ) )
static bool is_mem_poll_inited = false;
__attribute__((section("dram_section"))) static uint32_t ucHeap[ (configTOTAL_BTDM_HEAP_SIZE >> 2) + 0x10];
void * btdm_malloc( size_t xWantedSize )
{
if (is_mem_poll_inited == false) {
is_mem_poll_inited = true;
heap_mem_init(HEAP_TYPE_BTDM_BLOCK, (void *)ucHeap, configTOTAL_BTDM_HEAP_SIZE);
}
return heap_mem_alloc(HEAP_TYPE_BTDM_BLOCK, xWantedSize);
}
void btdm_free( void * pv )
{
heap_mem_free(pv);
}
__RAM_CODE void *btdm_calloc(unsigned int count, unsigned int size)
{
void *ptr;
ptr = btdm_malloc(count * size);
if (ptr) {
memset(ptr, 0, count * size);
}
return ptr;
}

View File

@ -0,0 +1,86 @@
/**
****************************************************************************************
*
* @file ke_mem.h
*
* @brief API for the heap management module.
*
* Copyright (C) RivieraWaves 2009-2015
*
*
****************************************************************************************
*/
#ifndef _BTDM_MEM_H_
#define _BTDM_MEM_H_
#include <stdint.h> // standard integer
#include <stdbool.h> // standard includes
/**
****************************************************************************************
* @defgroup MEM Memory
* @ingroup KERNEL
* @brief Heap management module.
*
* This module implements heap management functions that allow initializing heap,
* allocating and freeing memory.
*
* @{
****************************************************************************************
*/
/**
****************************************************************************************
* @brief Allocation of a block of memory.
*
* Allocates a memory block whose size is size; if no memory is available return NULL
*
* @param[in] size Size of the memory area that need to be allocated.
* @param[in] type Type of memory block
*
* @return A pointer to the allocated memory area.
*
****************************************************************************************
*/
void *btdm_malloc(uint32_t size);
/**
****************************************************************************************
* @brief Freeing of a block of memory.
*
* Free the memory area pointed by mem_ptr : mark the block as free and insert it in
* the pool of free block.
*
* @param[in] mem_ptr Pointer to the memory area that need to be freed.
*
****************************************************************************************
*/
void btdm_free(void *mem_ptr);
/**
****************************************************************************************
* @brief Retrieve memory usage of selected heap.
*
* @param[in] type Type of memory heap block
*
* @return current memory usage of current heap.
****************************************************************************************
*/
uint16_t btdm_get_mem_usage(uint8_t type);
/**
****************************************************************************************
* @brief Retrieve max memory usage of all heap.
* This command also resets max measured value.
*
* @return max memory usage of all heap.
****************************************************************************************
*/
uint32_t btdm_get_max_mem_usage(void);
///@} MEM
#endif // _btdm_MEM_H_

View File

@ -0,0 +1,313 @@
#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;
}

View File

@ -0,0 +1,10 @@
#ifndef __CONTROLLER_H__
#define __CONTROLLER_H__
#include <stdint.h>
#include <stdbool.h>
bool controller_start(uint32_t baudrate, const uint8_t *ble_addr, const uint8_t *bt_addr, uint32_t src_addr);
#endif // __CONTROLLER_H__

View File

@ -0,0 +1,381 @@
#include "fr30xx.h"
#include "FreeRTOS.h"
#include "SWD.h"
#include "fdb_app.h"
#include "controller_bootloader.h"
//#define CONTROLLER_CODE_SPLIT
#define HCI_UART UART0
#define HCI_UART_IRQn UART0_IRQn
#ifndef CONTROLLER_CODE_SPLIT
#define CODE_EXEC_BASE_ADDR 0x1FFFA000
extern uint8_t CODE_BASE, CODE_END;
#else
#define CODE_EXEC_L_BASE_ADDR 0x1FFF8000
#define CODE_EXEC_H_BASE_ADDR_P1 0x20008700
//#define CODE_EXEC_H_BASE_ADDR_P2 0x20008700
extern uint8_t CODE_L_BASE, CODE_L_END;
extern uint8_t CODE_H_BASE, CODE_H_END;
#endif
#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;
/************************************************************************************
* @fn controller_start
*
* @brief Initializes bluetooth controller.
*
* @param baudrate: uart baudrate of HCI
* ble_addr: ble public address
* bt_addr: bt address
*/
bool controller_start(uint32_t baudrate, const uint8_t *ble_addr, const uint8_t *bt_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;
/* 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);
/* write code into RAM */
#ifndef CONTROLLER_CODE_SPLIT
opcode = 0x04;
src = (void *)&CODE_BASE;
dst = (void *)CODE_EXEC_BASE_ADDR;
length = (uint32_t)&CODE_END - (uint32_t)&CODE_BASE;
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;
}
#else
opcode = 0x04;
src = (void *)&CODE_L_BASE;
dst = (void *)CODE_EXEC_L_BASE_ADDR;
length = (uint32_t)&CODE_L_END - (uint32_t)&CODE_L_BASE;
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;
}
// opcode = 0x04;
// src = (void *)&CODE_H_BASE;
// dst = (void *)CODE_EXEC_H_BASE_ADDR_P2;
// length = (uint32_t)&CODE_H_END - (uint32_t)&CODE_H_BASE;
// if (length > (CODE_EXEC_H_BASE_ADDR_P2 - CODE_EXEC_H_BASE_ADDR_P1)) {
// length -= (CODE_EXEC_H_BASE_ADDR_P2 - CODE_EXEC_H_BASE_ADDR_P1);
// src += (CODE_EXEC_H_BASE_ADDR_P2 - CODE_EXEC_H_BASE_ADDR_P1);
// }
// else {
// length = 0;
// }
// 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;
// }
#endif
/* 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;
#ifndef CONTROLLER_CODE_SPLIT
dst = (void *)CODE_EXEC_BASE_ADDR;
#else
dst = (void *)CODE_EXEC_L_BASE_ADDR;
#endif
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;
}
#ifdef CONTROLLER_CODE_SPLIT
system_delay_us(50000);
opcode = 0x04;
src = (void *)&CODE_H_BASE;
dst = (void *)CODE_EXEC_H_BASE_ADDR_P1;
length = (uint32_t)&CODE_H_END - (uint32_t)&CODE_H_BASE;
// if (length > (CODE_EXEC_H_BASE_ADDR_P2 - CODE_EXEC_H_BASE_ADDR_P1)) {
// length = (CODE_EXEC_H_BASE_ADDR_P2 - CODE_EXEC_H_BASE_ADDR_P1);
// }
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;
}
/* 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;
}
#endif
return true;
}

View File

@ -0,0 +1,10 @@
#ifndef __CONTROLLER_H__
#define __CONTROLLER_H__
#include <stdint.h>
#include <stdbool.h>
bool controller_start(uint32_t baudrate, const uint8_t *ble_addr, const uint8_t *bt_addr);
#endif // __CONTROLLER_H__

Binary file not shown.

View File

@ -0,0 +1,9 @@
AREA RO,DATA,READONLY
EXPORT CODE_BASE
EXPORT CODE_END
CODE_BASE
incbin controller_code
CODE_END
END

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
AREA RO,DATA,READONLY
EXPORT CONTROLLER_CODE_OTA_BASE
EXPORT CONTROLLER_CODE_OTA_END
CONTROLLER_CODE_OTA_BASE
incbin controller_code_single_ota
CONTROLLER_CODE_OTA_END
END

View File

@ -0,0 +1,10 @@
AREA RO,DATA,READONLY
EXPORT CONTROLLER_CODE_SPLIT_OTA_BASE
EXPORT CONTROLLER_CODE_SPLIT_OTA_END
CONTROLLER_CODE_SPLIT_OTA_BASE
incbin controller_code_splite_ota
CONTROLLER_CODE_SPLIT_OTA_END
END

Binary file not shown.

View File

@ -0,0 +1,21 @@
import os, sys
import struct
import zlib
def fill_header(f_in_file,
f_out_file,
version):
code_length = os.path.getsize(f_in_file)
f_out = open(f_out_file, 'wb')
f_out.write(struct.pack('I', 0x55AAAA55))
f_out.write(struct.pack('I', version))
f_out.write(struct.pack('I', code_length))
f_in = open(f_in_file, 'rb')
array = f_in.read(code_length)
image_crc = zlib.crc32(array)
f_out.write(struct.pack('I', image_crc))
f_out.seek(0x10)
f_out.write(array)
fill_header("controller_code", "controller_code_burn.bin", 0x00010000)

View File

@ -0,0 +1,678 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include "fr30xx.h"
#include "btdm_host.h"
#include "FreeRTOS.h"
#include "timers.h"
#include "semphr.h"
#include "fdb_app.h"
#include "host.h"
#include "me_api.h"
#include "bt_types.h"
#include "app_config.h"
#define HOST_DDB_RECORD_COUNT 8
#define HOST_DDB_INFOR_VERSION 0x01
#define HCI_UART UART0
#define HCI_UART_IRQn UART0_IRQn
/* Uart backup/restore */
typedef struct
{
volatile uint8_t BAK_DLL;
volatile uint8_t BAK_DLH;
volatile uint8_t BAK_DLF;
volatile uint8_t BAK_IER;
volatile uint8_t BAK_FCR;
volatile uint8_t BAK_LCR;
volatile uint8_t BAK_MCR;
}struct_UartRES_t;
struct host_ddb_info {
uint8_t version;
uint8_t used_count;
BtDeviceRecord ddb[HOST_DDB_RECORD_COUNT];
};
static TimerHandle_t btdm_host_timer = NULL;
static bool btdm_host_timer_inited = false;
static const uint8_t *write_buffer = 0;
static uint32_t write_length = 0;
static void (*write_callback)(void) = 0;
static uint8_t *read_buffer = 0;
static uint32_t read_length = 0;
static void (*read_callback)(void *, uint8_t) = 0;
static void *read_dummy = 0;
/* host semaphore handle */
SemaphoreHandle_t host_Semaphore_handle;
/* host task handle */
static TaskHandle_t btdm_host_handle;
/* hardware handlers */
static UART_HandleTypeDef HCI_handle;
/* structure used to save and restore uart configuration when sleep mode is enabled */
static struct_UartRES_t uart_regs;
#define READ_REG(__ADDR__) (*(volatile uint32_t *)(__ADDR__))
#define WRTIE_REG(__ADDR__, __VALUE__) (*(volatile uint32_t *)(__ADDR__) = (__VALUE__))
/************************************************************************************
* @fn Uart_backup/Uart_restore
*
* @brief Uart low-power backup/restore
*/
__RAM_CODE static void __Uart_backup(struct_UART_t *Uartx, struct_UartRES_t *UartRES)
{
volatile uint32_t UartxBase = (uint32_t)Uartx;
UartRES->BAK_LCR = READ_REG(UartxBase + 0x0C);
UartRES->BAK_MCR = READ_REG(UartxBase + 0x10);
UartRES->BAK_FCR = 0x09;
UartRES->BAK_IER = READ_REG(UartxBase + 0x04);
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR | 0x80);
UartRES->BAK_DLL = READ_REG(UartxBase);
UartRES->BAK_DLH = READ_REG(UartxBase + 0x04);
UartRES->BAK_DLF = READ_REG(UartxBase + 0xC0);
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR);
}
__RAM_CODE static void __Uart_restore(struct_UART_t *Uartx, struct_UartRES_t *UartRES)
{
volatile uint32_t UartxBase = (uint32_t)Uartx;
WRTIE_REG(UartxBase + 0x04, UartRES->BAK_IER);
WRTIE_REG(UartxBase + 0x08, UartRES->BAK_FCR);
WRTIE_REG(UartxBase + 0x10, UartRES->BAK_MCR);
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR | 0x80);
WRTIE_REG(UartxBase, UartRES->BAK_DLL);
WRTIE_REG(UartxBase + 0x04, UartRES->BAK_DLH);
WRTIE_REG(UartxBase + 0xC0, UartRES->BAK_DLF);
WRTIE_REG(UartxBase + 0x0C, UartRES->BAK_LCR);
}
static void hci_uart_rx_callback(UART_HandleTypeDef *h)
{
read_length = 0;
read_callback(read_dummy, 0);
}
static void hci_uart_tx_callback(UART_HandleTypeDef *h)
{
write_length = 0;
write_callback();
system_prevent_sleep_clear(SYSTEM_PREVENT_SLEEP_TYPE_HCI_TX);
}
static void vTimerCallback( TimerHandle_t pxTimer )
{
btdm_timer_trigger();
}
void btdm_timer_start(uint32_t ms)
{
if (!btdm_host_timer_inited) {
btdm_host_timer = xTimerCreate( "Timer", ms / portTICK_PERIOD_MS, pdTRUE, NULL, vTimerCallback);
btdm_host_timer_inited = true;
}
xTimerStop(btdm_host_timer, portMAX_DELAY);
xTimerChangePeriod(btdm_host_timer, ms / portTICK_RATE_MS, portMAX_DELAY);
xTimerStart(btdm_host_timer, portMAX_DELAY);
}
void btdm_timer_stop(void)
{
if(btdm_host_timer) {
xTimerStop(btdm_host_timer, portMAX_DELAY);
}
}
uint32_t btdm_get_system_time(void)
{
return xTaskGetTickCount() * portTICK_RATE_MS;
}
int btdm_time_diff(uint32_t a_time, uint32_t b_time)
{
return b_time - a_time;
}
void hci_if_do_send(const uint8_t *buffer, uint32_t length, void (*func)(void))
{
struct app_task_event * event;
uint32_t print_size = length > 8 ? 8 : length;
assert(write_length == 0);
write_buffer = buffer;
write_length = length;
write_callback = func;
#if 1
system_prevent_sleep_set(SYSTEM_PREVENT_SLEEP_TYPE_HCI_TX);
uart_transmit_IT(&HCI_handle, (void *)buffer, length);
#else
uart_transmit(&HCI_handle, (void *)buffer, length);
write_callback();
write_length = 0;
#endif
}
void hci_if_do_recv(uint8_t *bufptr, uint32_t size, void *arg, void* dummy)
{
struct app_task_event * event;
assert(read_length == 0);
read_buffer = bufptr;
read_length = size;
read_callback = (void (*)(void *, uint8_t))arg;
read_dummy = dummy;
uart_receive_IT(&HCI_handle, bufptr, size);
}
void btdm_host_notify_schedule(void)
{
if(xPortIsInsideInterrupt()) {
vTaskNotifyGiveFromISR(btdm_host_handle, NULL);
}
else {
xTaskNotifyGive(btdm_host_handle);
}
}
__WEAK 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);
}
static void host_hw_init(uint32_t baudrate)
{
GPIO_InitTypeDef gpio_config;
/* configure PA0 and PA1 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 */
HCI_handle.UARTx = HCI_UART;
HCI_handle.Init.BaudRate = baudrate;
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 = hci_uart_tx_callback;
HCI_handle.RxCpltCallback = hci_uart_rx_callback;
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);
// __UART_RxFIFO_THRESHOLD((&HCI_handle), 2);
NVIC_SetPriority(HCI_UART_IRQn, 2);
NVIC_EnableIRQ(HCI_UART_IRQn);
}
static void host_btdm_task(void *ble_static_addr)
{
struct host_ddb_info *info;
size_t size;
/* Initialize BLE stack */
struct ble_host_param param;
if (ble_static_addr) {
param.own_addr_type = 1;
memcpy(&param.own_addr.addr[0], ble_static_addr, 6);
}
else {
param.own_addr_type = 0;
}
host_Semaphore_handle = xSemaphoreCreateRecursiveMutex();
ble_host_init(&param);
/* HCI is ready */
__UART_AUTO_FLOW_CONTROL_ENABLE(HCI_handle.UARTx);
__UART_RTS_ACTIVE(HCI_handle.UARTx);
while(ble_host_ready() == false) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
btdm_host_schedule_ble();
}
/* check whether link key information stored in flashdb is valid or not */
info = pvPortMalloc(sizeof(struct host_ddb_info));
size = flashdb_get(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
if ((size != 0)
&& ((sizeof(struct host_ddb_info) != size)
|| (info->version != HOST_DDB_INFOR_VERSION)
|| (info->used_count > HOST_DDB_RECORD_COUNT))) {
flashdb_del(FDB_KEY_BT_LINKKEY);
}
vPortFree(info);
// Initialize BT stack
bt_host_init();
#if BTDM_STACK_ENABLE_A2DP_SNK | BTDM_STACK_ENABLE_A2DP_SRC
bt_a2dp_init();
#endif
#if BTDM_STACK_ENABLE_AVRCP
bt_avrcp_init();
#endif
#if BTDM_STACK_ENABLE_HF
bt_hf_init();
#endif
#if BTDM_STACK_ENABLE_AG
bt_hfg_init();
#endif
#if BTDM_STACK_ENABLE_PAN
bt_pan_init();
#endif
#if BTDM_STACK_ENABLE_PBAP
bt_pbap_init();
#endif
#if BTDM_STACK_ENABLE_SPP
bt_spp_init();
#endif
while(bt_host_ready() == false) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
btdm_host_schedule();
}
host_ready_cb();
while(1) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
btdm_host_schedule();
}
}
static void host_ble_task(void *ble_static_addr)
{
struct app_task_event *event;
struct host_ddb_info *info;
size_t size;
/* Initialize BLE stack */
struct ble_host_param param;
if (ble_static_addr) {
param.own_addr_type = 1;
memcpy(&param.own_addr.addr[0], ble_static_addr, 6);
}
else {
param.own_addr_type = 0;
}
ble_host_init(&param);
printf("HCI is ready.\r\n");
/* HCI is ready */
__UART_AUTO_FLOW_CONTROL_ENABLE(HCI_handle.UARTx);
__UART_RTS_ACTIVE(HCI_handle.UARTx);
while(ble_host_ready() == false) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
btdm_host_schedule_ble();
}
host_ready_cb();
while(1) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
btdm_host_schedule_ble();
}
}
/************************************************************************************
* @fn host_btdm_start
*
* @brief Initializes bt dual mode host, host task will be created in this function.
* host_ble_start and host_btdm_start should not be called together.
*
* @param baudrate: uart baudrate of HCI
* stack_size: stack size of host task
* priority: priority of host task
* ble_static_addr: If public address will be used as identity address, this field
* should be set NULL. Otherwise random static address stored in
* ble_static_addr will be used as identity address.
*/
void host_btdm_start(uint32_t baudrate, uint32_t stack_size, uint8_t priority, const uint8_t *ble_static_addr)
{
host_hw_init(baudrate);
xTaskCreate(host_btdm_task, "host", stack_size, (void *)ble_static_addr, priority, &btdm_host_handle);
}
/************************************************************************************
* @fn host_ble_start
*
* @brief Initializes ble host, host task will be created in this function.
* host_ble_start and host_btdm_start should not be called together.
*
* @param baudrate: uart baudrate of HCI
* stack_size: stack size of host task
* priority: priority of host task
* ble_static_addr: If public address will be used as identity address, this field
* should be set NULL. Otherwise random static address stored in
* ble_static_addr will be used as identity address.
*/
void host_ble_start(uint32_t baudrate, uint32_t stack_size, uint8_t priority, const uint8_t *ble_static_addr)
{
host_hw_init(baudrate);
xTaskCreate(host_ble_task, "host", stack_size, (void *)ble_static_addr, priority, &btdm_host_handle);
}
//void host_stop(void)
//{
// uint32_t *dst, *src, *end;
// if(btdm_host_timer_inited) {
// xTimerDelete(btdm_host_timer, portMAX_DELAY);
// btdm_host_timer = NULL;
// btdm_host_timer_inited = false;
// }
// vTaskDelete(btdm_host_handle);
//
// btdm_mem_uninit();
// write_buffer = 0;
// write_length = 0;
// write_callback = 0;
// read_buffer = 0;
// read_length = 0;
// read_callback = 0;
// read_dummy = 0;
//
// dst = (uint32_t *)&Image$$HOST_DATA$$RW$$Base;
// src=(uint32_t *)&Load$$HOST_DATA$$RW$$Base;
// end = (uint32_t *)&Load$$HOST_DATA$$RW$$Limit;
// for(; (uint32_t)src<(uint32_t)end;)
// {
// *dst++ = *src++;
// }
// dst = (uint32_t *)&Image$$HOST_DATA$$ZI$$Base;
// end = (uint32_t *)&Image$$HOST_DATA$$ZI$$Limit;
// for(; dst < end;)
// {
// *dst++ = 0;
// }
//}
BtStatus DDB_AddRecord(const BtDeviceRecord* record)
{
fdb_err_t err;
struct host_ddb_info *info;
size_t size;
info = pvPortMalloc(sizeof(struct host_ddb_info));
if (info) {
uint32_t index = 0;
size = flashdb_get(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
if (size == 0) {
info->version = HOST_DDB_INFOR_VERSION;
info->used_count = 0;
}
else {
if ((size != sizeof(struct host_ddb_info))
|| (info->version != HOST_DDB_INFOR_VERSION)
|| (info->used_count > HOST_DDB_RECORD_COUNT)) {
if (flashdb_del(FDB_KEY_BT_LINKKEY) != FDB_NO_ERR) {
vPortFree(info);
return BT_STATUS_FAILED;
}
else {
info->version = HOST_DDB_INFOR_VERSION;
info->used_count = 0;
}
}
}
/* search for duplicated record according to bluetooth device address */
for (index = 0; index < info->used_count; index++) {
if (memcmp((void *)&info->ddb[index].bdAddr.A, (void *)&record->bdAddr, sizeof(BD_ADDR)) == 0) {
break;
}
}
if (index < info->used_count) {
/* duplicated device is found, delete the found device and move forward the information of subsequence devices */
memcpy((void *)&info->ddb[index], (void *)&info->ddb[index+1], sizeof(BtDeviceRecord) * (info->used_count-1-index));
index = info->used_count - 1;
}
else {
if (info->used_count == HOST_DDB_RECORD_COUNT) {
/* the table is full, remove the oldest device information */
memcpy((void *)&info->ddb[0], (void *)&info->ddb[1], sizeof(BtDeviceRecord) * (HOST_DDB_RECORD_COUNT-1));
index = HOST_DDB_RECORD_COUNT-1;
}
else {
index = info->used_count;
info->used_count++;
}
}
memcpy((void *)&info->ddb[index], (void *)record, sizeof(BtDeviceRecord));
printf("linkey: ");
for(uint8_t i=0; i<16; i++){
printf("%02x ",record->linkKey[i]);
}
printf("\r\n");
err = flashdb_set(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
vPortFree(info);
if (err != FDB_NO_ERR) {
return BT_STATUS_FAILED;
}
else {
return BT_STATUS_SUCCESS;
}
}
else {
return BT_STATUS_FAILED;
}
}
BtStatus DDB_FindRecord(const BD_ADDR *bdAddr, BtDeviceRecord* record)
{
fdb_err_t err;
struct host_ddb_info *info;
size_t size;
BtStatus status;
info = pvPortMalloc(sizeof(struct host_ddb_info));
if (info) {
uint32_t index = 0;
size = flashdb_get(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
if (size == 0) {
vPortFree(info);
return BT_STATUS_FAILED;
}
else {
if ((size != sizeof(struct host_ddb_info))
|| (info->version != HOST_DDB_INFOR_VERSION)
|| (info->used_count > HOST_DDB_RECORD_COUNT)) {
flashdb_del(FDB_KEY_BT_LINKKEY);
vPortFree(info);
return BT_STATUS_FAILED;
}
}
/* search for duplicated record according to bluetooth device address */
for (index = 0; index < info->used_count; index++) {
if (memcmp((void *)&info->ddb[index].bdAddr.A, (void *)bdAddr, sizeof(BD_ADDR)) == 0) {
break;
}
}
if (index < info->used_count) {
/* information is found */
memcpy((void *)record, (void *)&info->ddb[index], sizeof(BtDeviceRecord));
status = BT_STATUS_SUCCESS;
if ((index+1) != info->used_count) {
memcpy((void *)&info->ddb[index], (void *)&info->ddb[index+1], sizeof(BtDeviceRecord) * (info->used_count-1-index));
memcpy((void *)&info->ddb[info->used_count - 1], (void *)record, sizeof(BtDeviceRecord));
err = flashdb_set(FDB_KEY_BT_LINKKEY, (void *)info, sizeof(struct host_ddb_info));
if (err != FDB_NO_ERR) {
status = BT_STATUS_FAILED;
}
}
}
else {
status = BT_STATUS_FAILED;
}
vPortFree(info);
return status;
}
else {
return BT_STATUS_FAILED;
}
}
enum btdm_nvds_status btdm_nvds_put(uint8_t tag, uint16_t length, uint8_t *data)
{
enum btdm_nvds_status status = BTDM_NVDS_STATUS_FAILED;
uint32_t fdb_key;
if (tag == BTDM_NVDS_TAG_CONTROLLER_INFO) {
fdb_key = FDB_KEY_CONTROLLER_INFO;
}
else {
fdb_key = FDB_KEY_BTDM_LIB_BASE | tag;
}
if (flashdb_set(fdb_key, data, length) == FDB_NO_ERR) {
status = BTDM_NVDS_STATUS_OK;
}
else {
status = BTDM_NVDS_STATUS_FAILED;
}
return status;
}
enum btdm_nvds_status btdm_nvds_get(uint8_t tag, uint16_t *length, uint8_t *buffer)
{
*length = flashdb_get(FDB_KEY_BTDM_LIB_BASE | tag, buffer, *length);
if (*length == 0) {
return BTDM_NVDS_STATUS_FAILED;
}
else {
return BTDM_NVDS_STATUS_OK;
}
}
enum btdm_nvds_status btdm_nvds_del(uint8_t tag)
{
enum btdm_nvds_status status = BTDM_NVDS_STATUS_FAILED;
if (flashdb_del(FDB_KEY_BTDM_LIB_BASE | tag) == FDB_NO_ERR) {
status = BTDM_NVDS_STATUS_OK;
}
else {
status = BTDM_NVDS_STATUS_FAILED;
}
return status;
}
void uart0_irq(void)
{
uart_IRQHandler(&HCI_handle);
}
/************************************************************************************
* @fn host_before_sleep_check
*
* @brief user should call this function to check whether HCI is in busy state before
* enter sleep mode. When HCI is in IDLE state, this function will return True and
* RTS will be changed to GPIO mode and output high level to suspend HCI transfer.
*
* @return True: HCI is in IDLE state, user is allowed to enter sleep mode.
* False: HCI is in busy state, user is not allowed to enter sleep mode.
*/
__RAM_CODE bool host_before_sleep_check(void)
{
if (__UART_IS_TxFIFO_EMPTY(HCI_handle.UARTx) == 0) {
return false;
}
/* set RTS to notice host device that UART is not available*/
__SYSTEM_GPIOA_CLK_ENABLE();
GPIOA->GPIO_OutputEN &= (~GPIO_PIN_3);
GPIOA->GPIO_BIT_SET = GPIO_PIN_3;
SYSTEM->PortA_L_FuncMux &= (~(0xf<<12));
system_delay_us(100);
if (__UART_IS_RxFIFO_EMPTY(HCI_handle.UARTx)) {
/* keep RTS pin is controllered by GPIO */
__Uart_backup(HCI_handle.UARTx, &uart_regs);
return true;
}
else {
/* recover RTS pin is controllered by UART */
SYSTEM->PortA_L_FuncMux |= (GPIO_FUNCTION_1<<12);
return false;
}
}
/************************************************************************************
* @fn host_hci_reinit
*
* @brief When system wake up from sleep mode, user should call this function to recover
* HCI.
*/
__RAM_CODE void host_hci_reinit(void)
{
GPIO_InitTypeDef gpio_config;
/* configure PA0 and PA1 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);
__SYSTEM_UART0_CLK_ENABLE();
__Uart_restore(HCI_handle.UARTx, &uart_regs);
NVIC_SetPriority(HCI_UART_IRQn, 2);
NVIC_EnableIRQ(HCI_UART_IRQn);
}
void btdm_host_lock(void)
{
// volatile uint32_t address;
// __asm("MOV %[result], LR":[result] "=r" (address));
if(xPortIsInsideInterrupt() == 0){
xSemaphoreTakeRecursive(host_Semaphore_handle,portMAX_DELAY);
}
else{
while(1);
//xSemaphoreTakeFromISR(host_Semaphore_handle,NULL);
}
}
void btdm_host_unlock(void)
{
if(xPortIsInsideInterrupt() == 0){
xSemaphoreGiveRecursive(host_Semaphore_handle);
}
else{
while(1);
}
}

View File

@ -0,0 +1,14 @@
#ifndef __HOST_H__
#define __HOST_H__
#include <stdint.h>
#include <stdbool.h>
void host_btdm_start(uint32_t baudrate, uint32_t stack_size, uint8_t priority, const uint8_t *ble_static_addr);
void host_ble_start(uint32_t baudrate, uint32_t stack_size, uint8_t priority, const uint8_t *ble_static_addr);
bool host_before_sleep_check(void);
void host_hci_reinit(void);
#endif // __HOST_H__

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
AREA RO,DATA,READONLY
; dsp_code_flash is compiled based on ROM code is stored in XIP flash
EXPORT DSP_CODE_FLASH_BASE
EXPORT DSP_CODE_FLASH_END
DSP_CODE_FLASH_BASE
incbin dsp_code_flash
DSP_CODE_FLASH_END
END

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,10 @@
AREA RO,DATA,READONLY
; dsp_code_flash is compiled based on ROM code is stored in IROM
EXPORT DSP_CODE_ROM_BASE
EXPORT DSP_CODE_ROM_END
DSP_CODE_ROM_BASE
incbin dsp_code_rom
DSP_CODE_ROM_END
END

View File

@ -0,0 +1,44 @@
import os
import struct
import zlib
def fill_header(f_in_file,
f_out_file,
version):
code_length = os.path.getsize(f_in_file)
f_out = open(f_out_file, 'wb')
f_out.write(struct.pack('I', 0xAA5555AA))
f_out.write(struct.pack('I', version))
f_out.write(struct.pack('I', code_length))
f_in = open(f_in_file, 'rb')
array = f_in.read(code_length)
image_crc = zlib.crc32(array)
f_out.write(struct.pack('I', image_crc))
f_out.seek(0x10)
f_out.write(array)
def binary_to_c_array(input_file, output_file, array_name):
with open(input_file, 'rb') as f:
binary_data = f.read()
with open(output_file, 'w') as f:
f.write('#include <stdint.h>\n')
f.write('const uint8_t {}[] = {{\n'.format(array_name))
counter = 0
for byte in binary_data:
if counter == 0:
f.write(' ')
f.write('0x{:02X}, '.format(byte))
counter = counter + 1
if counter == 16:
counter = 0
f.write('\n')
f.write('\n};')
fill_header("dsp_code_flash", "dsp_code_flash_burn.bin", 0x00010000)
fill_header("dsp_code_rom", "dsp_code_rom_burn.bin", 0x00010000)
binary_to_c_array("dsp_code_flash", "dsp_code_flash.c", "dsp_code_flash_buffer")
binary_to_c_array("dsp_code_rom", "dsp_code_rom.c", "dsp_code_rom_buffer")

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-01-26 armink the first version
*/
#include <fal.h>
#include <string.h>
#include "fr30xx.h"
#include "FreeRTOS.h" // pvPortMalloc
static int init(void);
static int read(long offset, uint8_t *buf, size_t size);
static int write(long offset, uint8_t *buf, size_t size);
static int erase(long offset, size_t size);
//static sfud_flash_t sfud_dev = NULL;
const struct fal_flash_dev onchip_flash =
{
.name = "flashdb_onchip",
.addr = 0,
.len = 2 * 1024 * 1024,
.blk_size = 4*1024,
.ops = {init, read, write, erase},
.write_gran = 16
};
static int init(void)
{
return 0;
}
static int read(long offset, uint8_t *buf, size_t size)
{
flash_read(QSPI0, offset, size, buf);
return size;
}
static int write(long offset, uint8_t *buf, size_t size)
{
uint8_t *temp_ptr = NULL;
if(((uint32_t )buf & 0xff000000) == FLASH_DAC_BASE) {
temp_ptr = pvPortMalloc(size);
memcpy(temp_ptr,buf,size);
flash_write(QSPI0, offset, size, temp_ptr);
vPortFree(temp_ptr);
}
else
flash_write(QSPI0, offset, size, buf);
return size;
}
static int erase(long offset, size_t size)
{
flash_erase(QSPI0, offset,size);
return size;
}

View File

@ -0,0 +1,86 @@
#include <stdio.h>
#include "fr30xx.h"
#include "flashdb.h"
/* KVDB object */
static struct fdb_kvdb kvdb={0};
/* critical zone protection */
static CPU_SR cpu_sr = 0;
static void lock(fdb_db_t db)
{
/* used to avoid reentry */
if (cpu_sr & 0xff00) {
while(1);
}
cpu_sr = CPU_SR_Save(0x20);
cpu_sr |= 0xff00;
}
static void unlock(fdb_db_t db)
{
cpu_sr &= 0xff;
CPU_SR_Restore(cpu_sr);
}
int flashdb_init(void)
{
fdb_err_t result;
/* set the lock and unlock function if you want */
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_LOCK, (void *)lock);
fdb_kvdb_control(&kvdb, FDB_KVDB_CTRL_SET_UNLOCK, (void *)unlock);
/* Key-Value database initialization
*
* &kvdb: database object
* "env": database name
* "fdb_kvdb1": The flash partition name base on FAL. Please make sure it's in FAL partition table.
* Please change to YOUR partition name.
* &default_kv: The default KV nodes. It will auto add to KVDB when first initialize successfully.
* NULL: The user data if you need, now is empty.
*/
result = fdb_kvdb_init(&kvdb, "env", "FlashEnv", NULL, NULL);
if (result != FDB_NO_ERR) {
return -1;
}
return 0;
}
fdb_err_t flashdb_set(uint32_t key, uint8_t *value, uint32_t length)
{
struct fdb_blob blob;
return fdb_kv_set_blob(&kvdb, key, fdb_blob_make(&blob, value, length));
}
size_t flashdb_get(uint32_t key, uint8_t *value, uint32_t length)
{
struct fdb_blob blob;
return fdb_kv_get_blob(&kvdb, key, fdb_blob_make(&blob, value, length));
}
size_t flashdb_get_length(uint32_t key)
{
struct fdb_kv kv;
if (fdb_kv_get_obj(&kvdb, key, &kv) == NULL) {
return 0;
}
else {
return kv.value_len;
}
}
fdb_err_t flashdb_del(uint32_t key)
{
return fdb_kv_del(&kvdb, key);
}

View File

@ -0,0 +1,29 @@
#ifndef _FAL_APP_H_
#define _FAL_APP_H_
#include <stdint.h>
#include <stddef.h>
#include "fdb_def.h"
#define FDB_KEY_BT_LINKKEY 0x00010000 //!< bt link key storage index
#define FDB_KEY_CONTROLLER_INFO 0x00010001 //!< controller information storage index
#define FDB_KEY_BTDM_LIB_BASE 0x00020000 //!< base index used to store host data
#define FDB_KEY_USER_BASE 0x00030000
#define FDB_KEY_USER_RANDOM_SEED 0x00030001
#define FDB_KEY_TOTAL_MILEAGE 0x00030002 //add by hsp 2024.03.04
#define FDB_KEY_TRIP_MILEAGE 0x00030003 //add by hsp 2024.03.04
int flashdb_init(void);
fdb_err_t flashdb_set(uint32_t key, uint8_t *value, uint32_t length);
size_t flashdb_get(uint32_t key, uint8_t *value, uint32_t length);
size_t flashdb_get_length(uint32_t key);
fdb_err_t flashdb_del(uint32_t key);
#endif