A36 PCB1.1 软件工程整理
This commit is contained in:
445
fr3092_mcu/examples/common/btdm/SWD.c
Normal file
445
fr3092_mcu/examples/common/btdm/SWD.c
Normal 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);
|
||||
}
|
140
fr3092_mcu/examples/common/btdm/SWD.h
Normal file
140
fr3092_mcu/examples/common/btdm/SWD.h
Normal 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
|
39
fr3092_mcu/examples/common/btdm/btdm_mem.c
Normal file
39
fr3092_mcu/examples/common/btdm/btdm_mem.c
Normal 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;
|
||||
}
|
86
fr3092_mcu/examples/common/btdm/btdm_mem.h
Normal file
86
fr3092_mcu/examples/common/btdm/btdm_mem.h
Normal 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_
|
||||
|
313
fr3092_mcu/examples/common/btdm/controller.c
Normal file
313
fr3092_mcu/examples/common/btdm/controller.c
Normal 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 *)¶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;
|
||||
}
|
10
fr3092_mcu/examples/common/btdm/controller.h
Normal file
10
fr3092_mcu/examples/common/btdm/controller.h
Normal 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__
|
||||
|
381
fr3092_mcu/examples/common/btdm/controller_bootloader.c
Normal file
381
fr3092_mcu/examples/common/btdm/controller_bootloader.c
Normal 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 *)¶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;
|
||||
#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;
|
||||
}
|
||||
|
10
fr3092_mcu/examples/common/btdm/controller_bootloader.h
Normal file
10
fr3092_mcu/examples/common/btdm/controller_bootloader.h
Normal 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__
|
||||
|
BIN
fr3092_mcu/examples/common/btdm/controller_code
Normal file
BIN
fr3092_mcu/examples/common/btdm/controller_code
Normal file
Binary file not shown.
9
fr3092_mcu/examples/common/btdm/controller_code.s
Normal file
9
fr3092_mcu/examples/common/btdm/controller_code.s
Normal file
@ -0,0 +1,9 @@
|
||||
AREA RO,DATA,READONLY
|
||||
|
||||
EXPORT CODE_BASE
|
||||
EXPORT CODE_END
|
||||
CODE_BASE
|
||||
incbin controller_code
|
||||
CODE_END
|
||||
|
||||
END
|
BIN
fr3092_mcu/examples/common/btdm/controller_code_single_ota
Normal file
BIN
fr3092_mcu/examples/common/btdm/controller_code_single_ota
Normal file
Binary file not shown.
BIN
fr3092_mcu/examples/common/btdm/controller_code_single_ota-old
Normal file
BIN
fr3092_mcu/examples/common/btdm/controller_code_single_ota-old
Normal file
Binary file not shown.
1762
fr3092_mcu/examples/common/btdm/controller_code_single_ota.c
Normal file
1762
fr3092_mcu/examples/common/btdm/controller_code_single_ota.c
Normal file
File diff suppressed because it is too large
Load Diff
10
fr3092_mcu/examples/common/btdm/controller_code_single_ota.s
Normal file
10
fr3092_mcu/examples/common/btdm/controller_code_single_ota.s
Normal 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
|
10
fr3092_mcu/examples/common/btdm/controller_code_split_ota.s
Normal file
10
fr3092_mcu/examples/common/btdm/controller_code_split_ota.s
Normal 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
|
BIN
fr3092_mcu/examples/common/btdm/controller_code_splite_ota
Normal file
BIN
fr3092_mcu/examples/common/btdm/controller_code_splite_ota
Normal file
Binary file not shown.
21
fr3092_mcu/examples/common/btdm/controller_post_process.py
Normal file
21
fr3092_mcu/examples/common/btdm/controller_post_process.py
Normal 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)
|
678
fr3092_mcu/examples/common/btdm/host.c
Normal file
678
fr3092_mcu/examples/common/btdm/host.c
Normal 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(¶m.own_addr.addr[0], ble_static_addr, 6);
|
||||
}
|
||||
else {
|
||||
param.own_addr_type = 0;
|
||||
}
|
||||
|
||||
host_Semaphore_handle = xSemaphoreCreateRecursiveMutex();
|
||||
|
||||
ble_host_init(¶m);
|
||||
|
||||
/* 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(¶m.own_addr.addr[0], ble_static_addr, 6);
|
||||
}
|
||||
else {
|
||||
param.own_addr_type = 0;
|
||||
}
|
||||
ble_host_init(¶m);
|
||||
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);
|
||||
}
|
||||
}
|
14
fr3092_mcu/examples/common/btdm/host.h
Normal file
14
fr3092_mcu/examples/common/btdm/host.h
Normal 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__
|
||||
|
Reference in New Issue
Block a user