Added support for BM-Lite UART interface.
Implemented UART interface support in stm32Wb55 HAL
This commit is contained in:
parent
fe5daad7bb
commit
27c95abeba
18
.vscode/c_cpp_properties.json
vendored
Normal file
18
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Linux",
|
||||
"defines": ["BMLITE_ON_UART", "NRF52840_XXAA", "BOARD_PCA10056", "BMLITE_USE_CALLBACK"],
|
||||
"cStandard": "c11",
|
||||
"cppStandard": "c++17",
|
||||
"intelliSenseMode": "${default}",
|
||||
"compilerPath": "/usr/bin/arm-none-eabi-gcc",
|
||||
"compilerArgs": [
|
||||
"-mcpu=cortex-m4",
|
||||
"-mthumb",
|
||||
"-mfloat-abi=hard"
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
@ -14,17 +14,17 @@
|
||||
"device": "STM32WB55xx",
|
||||
"interface": "swd",
|
||||
"runToMain": true,
|
||||
}
|
||||
{
|
||||
"name": "Cortex Debug nRF52840",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"executable": "${workspaceRoot}/BMLite_examples/out/embedded_app/nRF52840/embedded_app",
|
||||
"request": "launch",
|
||||
"type": "cortex-debug",
|
||||
"servertype": "jlink",
|
||||
"device": "nRF52840_xxAA",
|
||||
"interface": "swd",
|
||||
"runToMain": true,
|
||||
}
|
||||
},
|
||||
// {
|
||||
// "name": "Cortex Debug nRF52840",
|
||||
// "cwd": "${workspaceRoot}",
|
||||
// "executable": "${workspaceRoot}/BMLite_examples/out/embedded_app/nRF52840/embedded_app",
|
||||
// "request": "launch",
|
||||
// "type": "cortex-debug",
|
||||
// "servertype": "jlink",
|
||||
// "device": "nRF52840_xxAA",
|
||||
// "interface": "swd",
|
||||
// "runToMain": true,
|
||||
// }
|
||||
]
|
||||
}
|
||||
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@ -7,7 +7,7 @@
|
||||
"type": "shell",
|
||||
"label": "wb55 make",
|
||||
"command": "make",
|
||||
"args": ["-j4", "-C", "BMLite_examples", "PLATFORM=stm32wb55", "APP=embedded_app", "DEBUG=y"],
|
||||
"args": ["-j4", "-C", "BMLite_examples", "PLATFORM=stm32wb55", "PORT=UART", "APP=embedded_app", "DEBUG=y"],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
|
||||
@ -73,7 +73,25 @@ void hal_bmlite_reset(bool state);
|
||||
* @param[in] Leave CS asserted
|
||||
* @return ::fpc_bep_result_t
|
||||
*/
|
||||
fpc_bep_result_t hal_bmlite_spi_write_read(uint8_t *buff, size_t size);
|
||||
fpc_bep_result_t hal_bmlite_spi_write_read(uint8_t *write, uint8_t *read, size_t size,
|
||||
bool leave_cs_asserted);
|
||||
|
||||
/*
|
||||
* @brief UART write
|
||||
* @param[in] Write buffer
|
||||
* @param[in] Size
|
||||
* @return ::size_t Number of bytes actually written
|
||||
*/
|
||||
size_t hal_bmlite_uart_write(const uint8_t *data, size_t size);
|
||||
|
||||
/*
|
||||
* @brief UART read
|
||||
* @param[in] Read buffer
|
||||
* @param[in] Size
|
||||
* @return ::size_t Number of butes actually read
|
||||
*/
|
||||
size_t hal_bmlite_uart_read(uint8_t *buff, size_t size);
|
||||
|
||||
|
||||
/*
|
||||
* @brief Check if BM-Lite IRQ pin is set
|
||||
|
||||
@ -72,6 +72,13 @@ CFLAGS +=\
|
||||
-MMD \
|
||||
-MP
|
||||
|
||||
ifeq ($(PORT),UART)
|
||||
CFLAGS += -DBMLITE_ON_UART
|
||||
else
|
||||
CFLAGS += -DBMLITE_ON_SPI
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(DEBUG),y)
|
||||
CFLAGS +=\
|
||||
-g3\
|
||||
|
||||
@ -36,8 +36,13 @@ static uint8_t hcp_txrx_buffer[MTU];
|
||||
static uint8_t hcp_data_buffer[DATA_BUFFER_SIZE];
|
||||
|
||||
static HCP_comm_t hcp_chain = {
|
||||
#ifdef BMLITE_ON_UART
|
||||
.read = platform_bmlite_uart_receive,
|
||||
.write = platform_bmlite_uart_send,
|
||||
#else
|
||||
.read = platform_bmlite_spi_receive,
|
||||
.write = platform_bmlite_spi_send,
|
||||
#endif
|
||||
.pkt_buffer = hcp_data_buffer,
|
||||
.txrx_buffer = hcp_txrx_buffer,
|
||||
.pkt_size = 0,
|
||||
|
||||
@ -76,6 +76,22 @@ void hal_bmlite_reset(bool state);
|
||||
fpc_bep_result_t hal_bmlite_spi_write_read(uint8_t *write, uint8_t *read, size_t size,
|
||||
bool leave_cs_asserted);
|
||||
|
||||
/*
|
||||
* @brief UART write
|
||||
* @param[in] Write buffer
|
||||
* @param[in] Size
|
||||
* @return ::size_t Number of bytes actually written
|
||||
*/
|
||||
size_t hal_bmlite_uart_write(const uint8_t *data, size_t size);
|
||||
|
||||
/*
|
||||
* @brief UART read
|
||||
* @param[in] Read buffer
|
||||
* @param[in] Size
|
||||
* @return ::size_t Number of butes actually read
|
||||
*/
|
||||
size_t hal_bmlite_uart_read(uint8_t *buff, size_t size);
|
||||
|
||||
/*
|
||||
* @brief Check if BM-Lite IRQ pin is set
|
||||
* @return ::bool
|
||||
|
||||
@ -65,8 +65,7 @@ fpc_bep_result_t platform_bmlite_spi_send(uint16_t size, const uint8_t *data, ui
|
||||
*
|
||||
* @return ::fpc_com_result_t
|
||||
*/
|
||||
fpc_bep_result_t platform_bmlite_uart_send(uint16_t size, const uint8_t *data, uint32_t timeout,
|
||||
void *session);
|
||||
fpc_bep_result_t platform_bmlite_uart_send(uint16_t size, const uint8_t *data, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Receives data from SPI port in blocking mode.
|
||||
@ -88,8 +87,7 @@ fpc_bep_result_t platform_bmlite_spi_receive(uint16_t size, uint8_t *data, uint3
|
||||
*
|
||||
* @return ::fpc_com_result_t
|
||||
*/
|
||||
fpc_bep_result_t platform_bmlite_uart_receive(uint16_t size, uint8_t *data, uint32_t timeout,
|
||||
void *session);
|
||||
fpc_bep_result_t platform_bmlite_uart_receive(uint16_t size, uint8_t *data, uint32_t timeout);
|
||||
|
||||
/**
|
||||
* @brief Stops execution if a debug interface is attached.
|
||||
|
||||
@ -36,9 +36,9 @@
|
||||
fpc_bep_result_t platform_init(void *params)
|
||||
{
|
||||
fpc_bep_result_t result;
|
||||
hal_timebase_init();
|
||||
result = hal_board_init(params);
|
||||
if(result == FPC_BEP_RESULT_OK) {
|
||||
hal_timebase_init();
|
||||
platform_bmlite_reset();
|
||||
}
|
||||
return result;
|
||||
@ -52,6 +52,56 @@ void platform_bmlite_reset(void)
|
||||
hal_timebase_busy_wait(100);
|
||||
}
|
||||
|
||||
#ifdef BMLITE_ON_UART
|
||||
|
||||
fpc_bep_result_t platform_bmlite_uart_send(uint16_t size, const uint8_t *data, uint32_t timeout)
|
||||
{
|
||||
#ifdef DEBUG_COMM
|
||||
LOG_DEBUG("-> ");
|
||||
for (int i=0; i<size; i++)
|
||||
LOG_DEBUG("%02X ", data[i]);
|
||||
LOG_DEBUG("\n");
|
||||
#endif
|
||||
|
||||
size_t bytes_sent = hal_bmlite_uart_write(data, size);
|
||||
if(bytes_sent == size)
|
||||
return FPC_BEP_RESULT_OK;
|
||||
|
||||
return FPC_BEP_RESULT_IO_ERROR;
|
||||
}
|
||||
|
||||
fpc_bep_result_t platform_bmlite_uart_receive(uint16_t size, uint8_t *data, uint32_t timeout)
|
||||
{
|
||||
size_t total = 0;
|
||||
|
||||
volatile uint32_t start_time = hal_timebase_get_tick();
|
||||
volatile uint32_t curr_time = start_time;
|
||||
while (total < size &&
|
||||
(!timeout || (curr_time = hal_timebase_get_tick()) - start_time < timeout)) {
|
||||
total += hal_bmlite_uart_read(data + total, size);
|
||||
if(hal_check_button_pressed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(total < size) {
|
||||
return FPC_BEP_RESULT_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_COMM
|
||||
LOG_DEBUG("<- ");
|
||||
if(res == FPC_BEP_RESULT_OK) {
|
||||
for (int i=0; i<size; i++)
|
||||
LOG_DEBUG("%02X ", data[i]);
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
#endif
|
||||
|
||||
return FPC_BEP_RESULT_OK;
|
||||
}
|
||||
|
||||
#else // BMLITE_ON_SPI
|
||||
|
||||
fpc_bep_result_t platform_bmlite_spi_send(uint16_t size, const uint8_t *data, uint32_t timeout)
|
||||
{
|
||||
uint8_t buff[size];
|
||||
@ -93,6 +143,8 @@ fpc_bep_result_t platform_bmlite_spi_receive(uint16_t size, uint8_t *data, uint3
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) uint32_t hal_check_button_pressed()
|
||||
{
|
||||
return 0;
|
||||
|
||||
@ -86,8 +86,8 @@ fpc_bep_result_t hal_board_init(void *params)
|
||||
}
|
||||
|
||||
if (p->iface == COM_INTERFACE) {
|
||||
p->hcp_comm->read = rpi_com_receive;
|
||||
p->hcp_comm->write = rpi_com_send;
|
||||
p->hcp_comm->read = platform_bmlite_uart_receive;
|
||||
p->hcp_comm->write = platform_bmlite_uart_send;
|
||||
} else {
|
||||
p->hcp_comm->read = platform_bmlite_spi_receive;
|
||||
p->hcp_comm->write = platform_bmlite_spi_send;
|
||||
|
||||
@ -84,26 +84,20 @@ bool rpi_com_init(char *port, int baudrate, int timeout)
|
||||
return true;
|
||||
}
|
||||
|
||||
fpc_bep_result_t rpi_com_send(uint16_t size, const uint8_t *data, uint32_t timeout)
|
||||
size_t hal_bmlite_uart_write(const uint8_t *data, size_t size)
|
||||
{
|
||||
fpc_bep_result_t res = FPC_BEP_RESULT_OK;
|
||||
int n;
|
||||
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "error invalid file descriptor");
|
||||
return FPC_BEP_RESULT_INVALID_ARGUMENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = write(fd, data, size);
|
||||
return write(fd, data, size);
|
||||
|
||||
if (n != size) {
|
||||
res = FPC_BEP_RESULT_IO_ERROR;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
fpc_bep_result_t rpi_com_receive(uint16_t size, uint8_t *data, uint32_t timeout)
|
||||
size_t hal_bmlite_uart_read(uint8_t *data, size_t size)
|
||||
{
|
||||
fpc_bep_result_t res = FPC_BEP_RESULT_OK;
|
||||
int n_read = 0;
|
||||
@ -136,7 +130,7 @@ fpc_bep_result_t rpi_com_receive(uint16_t size, uint8_t *data, uint32_t timeout)
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
return n_read;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@
|
||||
|
||||
|
||||
/**
|
||||
* @file board_leds.c
|
||||
* @file hal_leds.c
|
||||
* @brief Leds control functions.
|
||||
*/
|
||||
|
||||
|
||||
@ -18,10 +18,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file platform_spi.c
|
||||
* @brief SPI functions
|
||||
* @file hal_spi.c
|
||||
* @brief SPI HAL functions
|
||||
*/
|
||||
|
||||
#ifdef BMLITE_ON_SPI
|
||||
|
||||
#include "nrf_drv_spi.h"
|
||||
#include "boards.h"
|
||||
#include "nrf_gpio.h"
|
||||
@ -110,3 +112,4 @@ void nordic_bmlite_spi_init(uint32_t speed_hz)
|
||||
nrf_drv_gpiote_out_init(BMLITE_CS_PIN, &out_config);
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file platform_timebase.c
|
||||
* @file hal_timebase.c
|
||||
* @brief timebase interface functions
|
||||
*/
|
||||
|
||||
|
||||
29
HAL_Driver/nRF52840/src/hal_uart.c
Normal file
29
HAL_Driver/nRF52840/src/hal_uart.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Fingerprint Cards AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Modified by Andrey Perminov <andrey.ppp@gmail.com>
|
||||
* for FPC BM-Lite applications
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_uart.c
|
||||
* @brief UART HAL functions
|
||||
*/
|
||||
|
||||
#ifdef BMLITE_ON_UART
|
||||
|
||||
#error "UART HAL for nRF52840 is not implemented yet"
|
||||
|
||||
#endif
|
||||
@ -68,6 +68,32 @@
|
||||
#define BMLITE_SPI_DMA_IRQn_TX DMA1_Channel3_IRQn
|
||||
#define BMLITE_SPI_DMA_IRQ_HANDLER_TX DMA1_Channel3_IRQHandler
|
||||
|
||||
/**
|
||||
* Configuration of UART used for BM-Lite communication.
|
||||
*/
|
||||
#define FPC_BMLITE_USART USART1
|
||||
#define FPC_BMLITE_USART_AF GPIO_AF7_USART1
|
||||
#define FPC_BMLITE_USART_CLK_ENABLE __HAL_RCC_USART1_CLK_ENABLE
|
||||
#define FPC_BMLITE_USART_IRQn USART1_IRQn
|
||||
#define FPC_BMLITE_USART_IRQ_HANDLER USART1_IRQHandler
|
||||
|
||||
#define FPC_BMLITE_USART_RX_PORT GPIOA
|
||||
#define FPC_BMLITE_USART_RX_PIN GPIO_PIN_10
|
||||
#define FPC_BMLITE_USART_TX_PORT GPIOA
|
||||
#define FPC_BMLITE_USART_TX_PIN GPIO_PIN_9
|
||||
#define FPC_BMLITE_USART_RX_PORT_CLK_ENABLE __HAL_RCC_GPIOA_CLK_ENABLE
|
||||
#define FPC_BMLITE_USART_TX_PORT_CLK_ENABLE __HAL_RCC_GPIOB_CLK_ENABLE
|
||||
|
||||
#define FPC_BMLITE_USART_DMA_CHANNEL_RX DMA1_Channel6
|
||||
#define FPC_BMLITE_USART_DMA_REQ_RX DMA_REQUEST_USART1_RX
|
||||
#define FPC_BMLITE_USART_DMA_IRQn_RX DMA1_Channel6_IRQn
|
||||
#define FPC_BMLITE_USART_DMA_IRQ_HANDLER_RX DMA1_Channel6_IRQHandler
|
||||
#define FPC_BMLITE_USART_DMA_CHANNEL_TX DMA1_Channel7
|
||||
#define FPC_BMLITE_USART_DMA_REQ_TX DMA_REQUEST_USART1_TX
|
||||
#define FPC_BMLITE_USART_DMA_IRQn_TX DMA1_Channel7_IRQn
|
||||
#define FPC_BMLITE_USART_DMA_IRQ_HANDLER_TX DMA1_Channel7_IRQHandler
|
||||
|
||||
|
||||
/**
|
||||
* Configuration of GPIO used for sensor reset / sensor interrupt.
|
||||
*/
|
||||
|
||||
@ -56,8 +56,8 @@
|
||||
#define HAL_SPI_MODULE_ENABLED
|
||||
/*#define HAL_TIM_MODULE_ENABLED */
|
||||
/*#define HAL_TSC_MODULE_ENABLED */
|
||||
/*#define HAL_UART_MODULE_ENABLED */
|
||||
/*#define HAL_USART_MODULE_ENABLED */
|
||||
#define HAL_UART_MODULE_ENABLED
|
||||
/* #define HAL_USART_MODULE_ENABLED */
|
||||
/*#define HAL_WWDG_MODULE_ENABLED */
|
||||
#define HAL_EXTI_MODULE_ENABLED
|
||||
#define HAL_CORTEX_MODULE_ENABLED
|
||||
|
||||
@ -36,6 +36,7 @@ static void dma_init();
|
||||
static void system_irq_init();
|
||||
|
||||
void stm_spi_init(uint32_t speed_hz);
|
||||
void stm_uart_init(uint32_t speed_hz);
|
||||
void board_led_init();
|
||||
void board_button_init();
|
||||
|
||||
@ -60,7 +61,15 @@ fpc_bep_result_t hal_board_init(void *params)
|
||||
/* Initialize DMA */
|
||||
dma_init();
|
||||
|
||||
#ifdef BMLITE_ON_UART
|
||||
stm_uart_init(115200);
|
||||
#else
|
||||
#ifdef BMLITE_ON_SPI
|
||||
stm_spi_init(4000000);
|
||||
#else
|
||||
#error "BMLITE_ON_SPI or BMLITE_ON_SPI must be defined"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (debugger) {
|
||||
HAL_DBGMCU_EnableDBGStandbyMode();
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file button.c
|
||||
* @file hal_buttons.c
|
||||
* @brief Initialization and access of button.
|
||||
*/
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file led.c
|
||||
* @file hal_leds.c
|
||||
* @brief Initialization and access of LED.
|
||||
*
|
||||
* The user LED on the Nucleo-L476RG is using the same pin as SPI SCK (PA5) so the LED
|
||||
|
||||
@ -18,10 +18,12 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file platform_spi.c
|
||||
* @brief SPI functions
|
||||
* @file hal_spi.c
|
||||
* @brief SPI HAL functions
|
||||
*/
|
||||
|
||||
#ifdef BMLITE_ON_SPI
|
||||
|
||||
#include "stm32wbxx_hal.h"
|
||||
|
||||
#include "bmlite_hal.h"
|
||||
@ -246,3 +248,5 @@ void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
spi_rx_tx_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
359
HAL_Driver/stm32wb55/src/hal_uart.c
Normal file
359
HAL_Driver/stm32wb55/src/hal_uart.c
Normal file
@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Fingerprint Cards AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Modified by Andrey Perminov <andrey.ppp@gmail.com>
|
||||
* for FPC BM-Lite applications
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file hal_uart.c
|
||||
* @brief UART HAL functions
|
||||
*/
|
||||
|
||||
#ifdef BMLITE_ON_UART
|
||||
|
||||
#include "stm32wbxx_hal.h"
|
||||
|
||||
#include "bmlite_hal.h"
|
||||
#include "fpc_bep_types.h"
|
||||
#include "hal_config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile uint8_t flag; /* Timeout event flag */
|
||||
uint16_t prev_cndtr; /* Holds previous value of DMA_CNDTR (counts down) */
|
||||
uint32_t idle_irq_count; /* Debug */
|
||||
uint32_t rx_complete_count; /* Debug */
|
||||
uint32_t rx_half_count; /* Debug */
|
||||
} dma_event_t;
|
||||
|
||||
UART_HandleTypeDef huart_host = { 0 };
|
||||
static DMA_HandleTypeDef hdma_rx = { 0 };
|
||||
static DMA_HandleTypeDef hdma_tx = { 0 };
|
||||
|
||||
static volatile bool tx_half;
|
||||
static volatile bool tx_done;
|
||||
static volatile bool error;
|
||||
static volatile bool rx_available;
|
||||
|
||||
#define DMA_BUF_SIZE 128
|
||||
#define DMA_TIMEOUT_MS 2
|
||||
|
||||
static uint8_t uart_rx_fifo[DMA_BUF_SIZE];
|
||||
static dma_event_t dma_uart_rx = { 0, DMA_BUF_SIZE, 0, 0, 0 };
|
||||
|
||||
// static bool tx_active(void)
|
||||
// {
|
||||
// return !tx_done;
|
||||
// }
|
||||
|
||||
// static bool rx_data_available(void)
|
||||
// {
|
||||
// bool avail = rx_available;
|
||||
|
||||
// rx_available = false;
|
||||
|
||||
// return avail;
|
||||
// }
|
||||
|
||||
/**
|
||||
* This function handles Host USART global interrupt.
|
||||
*/
|
||||
void FPC_BMLITE_USART_IRQ_HANDLER(void)
|
||||
{
|
||||
HAL_UART_IRQHandler(&huart_host);
|
||||
|
||||
/* UART IDLE Interrupt */
|
||||
if ((huart_host.Instance->ISR & USART_ISR_IDLE) != RESET) {
|
||||
huart_host.Instance->ICR = UART_CLEAR_IDLEF;
|
||||
dma_uart_rx.flag = 1;
|
||||
dma_uart_rx.idle_irq_count++;
|
||||
if(hdma_rx.XferCpltCallback != NULL) {
|
||||
hdma_rx.XferCpltCallback(&hdma_rx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function handles Host USART DMA RX global interrupt.
|
||||
*/
|
||||
void FPC_BMLITE_USART_DMA_IRQ_HANDLER_RX(void)
|
||||
{
|
||||
HAL_DMA_IRQHandler(huart_host.hdmarx);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function handles Host USART DMA TX global interrupt.
|
||||
*/
|
||||
void FPC_BMLITE_USART_DMA_IRQ_HANDLER_TX(void)
|
||||
{
|
||||
HAL_DMA_IRQHandler(huart_host.hdmatx);
|
||||
}
|
||||
|
||||
/**
|
||||
* USART init function.
|
||||
* @param[in] baudrate Initial baud rate.
|
||||
*/
|
||||
void stm_uart_init(uint32_t baudrate)
|
||||
{
|
||||
// HAL_StatusTypeDef status;
|
||||
|
||||
huart_host.Instance = FPC_BMLITE_USART;
|
||||
huart_host.Init.BaudRate = baudrate;
|
||||
huart_host.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart_host.Init.StopBits = UART_STOPBITS_1;
|
||||
huart_host.Init.Parity = UART_PARITY_NONE;
|
||||
huart_host.Init.Mode = UART_MODE_TX_RX;
|
||||
huart_host.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
huart_host.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
huart_host.Init.ClockPrescaler = UART_PRESCALER_DIV1;
|
||||
huart_host.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
|
||||
huart_host.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
|
||||
|
||||
// huart_host.Init.BaudRate = 921600;
|
||||
|
||||
HAL_UART_Init(&huart_host);
|
||||
HAL_UARTEx_EnableFifoMode(&huart_host);
|
||||
|
||||
/* UART1 IDLE Interrupt Configuration */
|
||||
SET_BIT(FPC_BMLITE_USART->CR1, USART_CR1_IDLEIE);
|
||||
|
||||
hal_timebase_busy_wait(100);
|
||||
|
||||
/* Start UART RX */
|
||||
HAL_UART_Receive_DMA(&huart_host, uart_rx_fifo, DMA_BUF_SIZE);
|
||||
}
|
||||
|
||||
void uart_host_reinit(void)
|
||||
{
|
||||
if (huart_host.Init.BaudRate) {
|
||||
huart_host.Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(SystemCoreClock,
|
||||
huart_host.Init.BaudRate, huart_host.Init.ClockPrescaler));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize UART GPIO.
|
||||
* @param[in, out] huart UART Handle.
|
||||
*/
|
||||
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = { 0 };
|
||||
// HAL_StatusTypeDef status;
|
||||
|
||||
if (huart->Instance == FPC_BMLITE_USART) {
|
||||
/* Peripheral clock enable */
|
||||
FPC_BMLITE_USART_CLK_ENABLE();
|
||||
FPC_BMLITE_USART_RX_PORT_CLK_ENABLE();
|
||||
FPC_BMLITE_USART_TX_PORT_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
|
||||
GPIO_InitStruct.Alternate = FPC_BMLITE_USART_AF;
|
||||
|
||||
GPIO_InitStruct.Pin = FPC_BMLITE_USART_RX_PIN;
|
||||
HAL_GPIO_Init(FPC_BMLITE_USART_RX_PORT, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = FPC_BMLITE_USART_TX_PIN;
|
||||
HAL_GPIO_Init(FPC_BMLITE_USART_TX_PORT, &GPIO_InitStruct);
|
||||
|
||||
/* Peripheral DMA init*/
|
||||
hdma_rx.Instance = FPC_BMLITE_USART_DMA_CHANNEL_RX;
|
||||
hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_rx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_rx.Init.Mode = DMA_CIRCULAR;
|
||||
hdma_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
|
||||
hdma_rx.Init.Request = FPC_BMLITE_USART_DMA_REQ_RX;
|
||||
|
||||
HAL_DMA_Init(&hdma_rx);
|
||||
__HAL_LINKDMA(huart, hdmarx, hdma_rx);
|
||||
|
||||
hdma_tx.Instance = FPC_BMLITE_USART_DMA_CHANNEL_TX;
|
||||
hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
|
||||
hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
|
||||
hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
|
||||
hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
|
||||
hdma_tx.Init.Mode = DMA_NORMAL;
|
||||
hdma_tx.Init.Priority = DMA_PRIORITY_LOW;
|
||||
hdma_tx.Init.Request = FPC_BMLITE_USART_DMA_REQ_TX;
|
||||
|
||||
HAL_DMA_Init(&hdma_tx);
|
||||
__HAL_LINKDMA(huart, hdmatx, hdma_tx);
|
||||
|
||||
/* UART Host RX DMA interrupt configuration */
|
||||
HAL_NVIC_SetPriority(FPC_BMLITE_USART_DMA_IRQn_RX, 6, 0);
|
||||
HAL_NVIC_EnableIRQ(FPC_BMLITE_USART_DMA_IRQn_RX);
|
||||
|
||||
/* UART Host TX DMA interrupt configuration */
|
||||
HAL_NVIC_SetPriority(FPC_BMLITE_USART_DMA_IRQn_TX, 6, 0);
|
||||
HAL_NVIC_EnableIRQ(FPC_BMLITE_USART_DMA_IRQn_TX);
|
||||
|
||||
/* Peripheral interrupt init*/
|
||||
HAL_NVIC_SetPriority(FPC_BMLITE_USART_IRQn, 1, 0);
|
||||
HAL_NVIC_EnableIRQ(FPC_BMLITE_USART_IRQn);
|
||||
|
||||
HAL_GPIO_WritePin(BMLITE_RST_PORT, BMLITE_RST_PIN, GPIO_PIN_RESET);
|
||||
GPIO_InitStruct.Pin = BMLITE_RST_PIN;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_PULLUP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
|
||||
GPIO_InitStruct.Alternate = 0;
|
||||
HAL_GPIO_Init(BMLITE_RST_PORT, &GPIO_InitStruct);
|
||||
}
|
||||
}
|
||||
|
||||
size_t hal_bmlite_uart_write(const uint8_t *data, size_t size)
|
||||
{
|
||||
HAL_StatusTypeDef result = HAL_ERROR;
|
||||
|
||||
tx_half = false;
|
||||
tx_done = false;
|
||||
error = false;
|
||||
|
||||
result = HAL_UART_Transmit_DMA(&huart_host, data, size);
|
||||
if (result != HAL_OK) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (!tx_done) {
|
||||
|
||||
if (error) {
|
||||
result = HAL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
size_t hal_bmlite_uart_read(uint8_t *data, size_t size)
|
||||
{
|
||||
uint32_t n_sent = 0;
|
||||
|
||||
/* Restart Host UART RX DMA transfer if it has stopped for some reason */
|
||||
if (huart_host.RxState != HAL_UART_STATE_BUSY_RX) {
|
||||
dma_uart_rx.prev_cndtr = DMA_BUF_SIZE;
|
||||
HAL_UART_Receive_DMA(&huart_host, uart_rx_fifo, DMA_BUF_SIZE);
|
||||
}
|
||||
|
||||
if (!size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t curr_cndtr = __HAL_DMA_GET_COUNTER(&hdma_rx);
|
||||
|
||||
if (curr_cndtr != dma_uart_rx.prev_cndtr) {
|
||||
uint32_t cur_pos = DMA_BUF_SIZE - curr_cndtr;
|
||||
uint32_t prev_pos;
|
||||
uint32_t length;
|
||||
|
||||
/* Determine start position in DMA buffer based on previous CNDTR value */
|
||||
prev_pos = DMA_BUF_SIZE - dma_uart_rx.prev_cndtr;
|
||||
if (prev_pos < cur_pos) {
|
||||
length = MIN(cur_pos - prev_pos, size);
|
||||
} else {
|
||||
/* Copy until end of buffer first */
|
||||
length = MIN(DMA_BUF_SIZE - prev_pos, size);
|
||||
}
|
||||
memcpy(data, &uart_rx_fifo[prev_pos], length);
|
||||
data += length;
|
||||
n_sent += length;
|
||||
dma_uart_rx.prev_cndtr -= length;
|
||||
if (dma_uart_rx.prev_cndtr == 0) {
|
||||
dma_uart_rx.prev_cndtr = DMA_BUF_SIZE;
|
||||
}
|
||||
if (prev_pos > cur_pos) {
|
||||
/* Copy from start of buffer */
|
||||
length = MIN(cur_pos, size);
|
||||
memcpy(data, uart_rx_fifo, length);
|
||||
data += length;
|
||||
n_sent += length;
|
||||
dma_uart_rx.prev_cndtr -= length;
|
||||
}
|
||||
}
|
||||
|
||||
return n_sent;
|
||||
|
||||
}
|
||||
|
||||
bool uart_host_rx_data_available(void)
|
||||
{
|
||||
return rx_available;
|
||||
}
|
||||
|
||||
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == huart_host.Instance) {
|
||||
rx_available = true;
|
||||
dma_uart_rx.rx_half_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == huart_host.Instance) {
|
||||
uint16_t curr_cndtr = __HAL_DMA_GET_COUNTER(huart->hdmarx);
|
||||
|
||||
/*
|
||||
* Ignore IDLE Timeout when the received characters exactly filled up the DMA buffer and
|
||||
* DMA Rx Complete Interrupt is generated, but there is no new character during timeout.
|
||||
*/
|
||||
if (dma_uart_rx.flag && curr_cndtr == DMA_BUF_SIZE) {
|
||||
dma_uart_rx.flag = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dma_uart_rx.flag) {
|
||||
dma_uart_rx.rx_complete_count++;
|
||||
}
|
||||
dma_uart_rx.flag = 0;
|
||||
|
||||
rx_available = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == huart_host.Instance) {
|
||||
tx_half = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == huart_host.Instance) {
|
||||
tx_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == huart_host.Instance) {
|
||||
error = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -63,6 +63,7 @@ LDFLAGS += -T $(HAL)/STM32WB55RGVX_FLASH.ld
|
||||
$(OUT)/obj/stm32wbxx_hal_pwr_ex.o: CFLAGS+=-Wno-unused-parameter
|
||||
$(OUT)/obj/stm32wbxx_hal_rtc_ex.o: CFLAGS+=-Wno-unused-parameter
|
||||
$(OUT)/obj/syscalls.o: CFLAGS+=-Wno-unused-parameter
|
||||
$(OUT)/obj/hal_uart.o: CFLAGS+=-Wno-discarded-qualifiers
|
||||
|
||||
ifeq ($(FPU),soft)
|
||||
AR_LIBS +=\
|
||||
@ -87,6 +88,9 @@ HAL_SRCS := \
|
||||
$(SDK_ROOT)/Src/stm32wbxx_hal_rtc.c \
|
||||
$(SDK_ROOT)/Src/stm32wbxx_hal_rtc_ex.c \
|
||||
$(SDK_ROOT)/Src/stm32wbxx_hal_spi.c \
|
||||
$(SDK_ROOT)/Src/stm32wbxx_hal_uart.c \
|
||||
$(SDK_ROOT)/Src/stm32wbxx_hal_uart_ex.c \
|
||||
|
||||
|
||||
VPATH += $(dir $(HAL_SRCS))
|
||||
C_SRCS += $(notdir $(HAL_SRCS))
|
||||
|
||||
20
README.md
20
README.md
@ -14,6 +14,7 @@ There are some variables controlling application building:
|
||||
APP - defines application
|
||||
PLATFORM - defines HW plaform with HAL implementation
|
||||
DEBUG - if defined as 'y' will produce debug output and add debug information
|
||||
PORT - if defined as UART, BM-Lite HAL will use UART interface. Else will use SPI interface
|
||||
|
||||
Not all applications can be built for a particular platform. To build embedded application for nRF52840 platform with additional debug info use:
|
||||
|
||||
@ -35,14 +36,17 @@ There are some useful makefile targets:
|
||||
|
||||
Platform-independent interface implemented in [platform.c](BMLite_sdk/src/platform.c)
|
||||
|
||||
| Platform function | Description |
|
||||
| :-------- | :-------- |
|
||||
| fpc_bep_result_t **platform_init**(void *params) | Initilalizes hardware |
|
||||
| void **platform_bmlite_reset**(void) | Implements BM-Lite HW Reset |
|
||||
| fpc_bep_result_t **platform_bmlite_spi_send**(uint16_t size, const uint8_t *data, uint32_t timeout) | Send data packet to FPC BM-Lite |
|
||||
| fpc_bep_result_t **platform_bmlite_spi_receive**(uint16_t size, uint8_t *data, uint32_t timeout) | Receive data packet from FPC BM-Lite. If timeout = **0**, the function will wait for data from BM-Lite indefinitely. The waiting loop will be breaked if **hal_check_button_pressed()** returns non-zero value. It is recommended to do HW or SW reset of BM-Lite if **platform_bmlite_spi_receive()** returns **FPC_BEP_RESULT_TIMEOUT** in order to return is into known state. |
|
||||
<table>
|
||||
<tr><th> Platform function <th> Description</tr>
|
||||
<tr><td> fpc_bep_result_t <b>platform_init</b>(void *params) <td> Initilalizes hardware </tr>
|
||||
<tr><td> void <b>platform_bmlite_reset</b>(void) <td> Implements BM-Lite HW Reset </tr>
|
||||
<tr><td> fpc_bep_result_t <b>platform_bmlite_spi_send</b>(uint16_t size, const uint8_t *data, uint32_t timeout) <br> fpc_bep_result_t <b>platform_bmlite_uart_send</b>(uint16_t size, const uint8_t *data, uint32_t timeout) <td> Send data packet to FPC BM-Lite </tr>
|
||||
<tr><td> fpc_bep_result_t <b>platform_bmlite_spi_receive</b>(uint16_t size, uint8_t *data, uint32_t timeout) <br> fpc_bep_result_t <b>platform_bmlite_uart_receive</b>(uint16_t size, uint8_t *data, uint32_t timeout)<td> Receive data packet from FPC BM-Lite. If timeout = <b>0</b>, the function will wait for data from BM-Lite indefinitely. The waiting loop will be breaked if <b>hal_check_button_pressed()</b> returns non-zero value. It is recommended to do HW or SW reset of BM-Lite if <b>platform_bmlite_spi_receive()</b> returns **FPC_BEP_RESULT_TIMEOUT** in order to return is into known state. </tr>
|
||||
</table>
|
||||
|
||||
Currently **platform_bmlite_uart_send()** and **platform_bmlite_uart_receive()** are not implemented. For UART interface there is no need to wait for **IRQ** pin ready. However because in UART mode there is no signal from FPC-BM-LIte that it will send data, I would recommend to use UART interrupt or DMA to receive data from UART and store it to a separate buffer and read data in **platform_bmlite_uart_receive()** from that buffer. Activation UART data reading only inside **platform_bmlite_uart_receive()** could lead to loosing some incoming data and causing HCP protocol errors.
|
||||
|
||||
For UART interface **IRQ/READY** pin is not used, so in UART mode there is no signal from FPC-BM-Lite indicating that BM-Lite is going to send data. To avoid data loss, all data received from UART must be stored into an incoming circular buffer. I would recommend to use UART interrupt or DMA to receive data from UART and store it to the buffer.
|
||||
**platform_bmlite_uart_receive()** will read from that buffer when HCP protocol requests to read a data block. Activation UART data reading only inside **platform_bmlite_uart_receive()** will lead to loosing incoming data and causing HCP protocol errors.
|
||||
|
||||
------------
|
||||
|
||||
@ -57,6 +61,8 @@ For porting the project to a new microcontroller, all functions from [bmlite_hal
|
||||
| fpc_bep_result_t **hal_board_init**(void *params) | Initialize GPIO, System timer, SPI |
|
||||
| void **hal_bmlite_reset**(bool state) | Activate/Deactivate BM-Lite **RST_N** pin (***Active Low***) |
|
||||
| fpc_bep_result_t **hal_bmlite_spi_write_read**(uint8_t *write, uint8_t *read, size_t size, bool leave_cs_asserted) | SPI data exchange |
|
||||
| size_t **hal_bmlite_uart_write**(const uint8_t *data, size_t size); | Write data to UART interface |
|
||||
| size_t **hal_bmlite_uart_read**(uint8_t *buff, size_t size); | Read data from UART interface |
|
||||
| bool **hal_bmlite_get_status**(void) | Return status of BM-Lite **IRQ** pin (***Active High***) |
|
||||
| void **hal_timebase_init**(void) | Initialize system clock with 1 msec tick |
|
||||
| uint32_t **hal_timebase_get_tick**(void) | Read currect system clock value |
|
||||
|
||||
Loading…
Reference in New Issue
Block a user