Added Linux HAL

BM-Lite HAL implementation for Linux use spidev for SPI access
and /sys/class/gpio for BM-Lite Reset & Status pin access
This commit is contained in:
Andrey Perminov 2021-07-07 14:30:30 -07:00
parent a0cf9ce125
commit 563f7c9f3a
13 changed files with 455 additions and 47 deletions

View File

@ -32,7 +32,7 @@ OUT := $(OUT_BASE)/$(APP)/$(PLATFORM)
HAL_DIRS = $(subst $(HAL_BASE),, $(sort $(dir $(wildcard $(HAL_BASE)/*/))))
HAL_LIST = $(subst /,,$(HAL_DIRS))
APP_LIST = $(subst /,, $(sort $(dir $(wildcard */))))
APP_LIST = $(filter-out out, $(subst /,, $(sort $(dir $(wildcard */)))))
ifneq ($(PLATFORM),)
ifeq ($(filter $(PLATFORM),$(HAL_LIST)),)
@ -42,19 +42,19 @@ endif
ifneq ($(APP),)
ifeq ($(filter $(APP),$(APP_LIST)),)
$(error "Unknown application: $(APP). Use one of $(HAL_LIST)")
$(error "Unknown application: $(APP). Use one of $(APP_LIST)")
endif
endif
ifeq ($(PLATFORM),RaspberryPi)
ifeq ($(APP),embedded_app)
$(error 'embedded_app is not supported for $(PLATFORM)')
endif
else
ifeq ($(filter $(PLATFORM), RaspberryPi Linux),)
ifeq ($(APP),console_app)
$(error 'console_app is not supported for $(PLATFORM)')
endif
else
ifeq ($(APP),embedded_app)
$(error 'embedded_app is not supported for $(PLATFORM)')
endif
endif
# Main target

View File

@ -36,7 +36,9 @@
#include "hcp_tiny.h"
#include "platform.h"
#include "bmlite_hal.h"
#include "platform_rpi.h"
#include "platform_linux.h"
#include "console_params.h"
#define DATA_BUFFER_SIZE 102400
static uint8_t hcp_txrx_buffer[MTU];
@ -112,32 +114,32 @@ int main (int argc, char **argv)
{
int index;
int c;
rpi_initparams_t rpi_params;
console_initparams_t app_params;
rpi_params.iface = SPI_INTERFACE;
rpi_params.hcp_comm = &hcp_chain;
rpi_params.baudrate = 921600;
rpi_params.timeout = 5;
rpi_params.port = NULL;
app_params.iface = SPI_INTERFACE;
app_params.hcp_comm = &hcp_chain;
app_params.baudrate = 921600;
app_params.timeout = 5;
app_params.port = NULL;
opterr = 0;
while ((c = getopt (argc, argv, "sb:p:t:")) != -1) {
switch (c) {
case 's':
rpi_params.iface = SPI_INTERFACE;
if(rpi_params.baudrate == 921600)
rpi_params.baudrate = 1000000;
app_params.iface = SPI_INTERFACE;
if(app_params.baudrate == 921600)
app_params.baudrate = 1000000;
break;
case 'b':
rpi_params.baudrate = atoi(optarg);
app_params.baudrate = atoi(optarg);
break;
case 'p':
rpi_params.iface = COM_INTERFACE;
rpi_params.port = optarg;
app_params.iface = COM_INTERFACE;
app_params.port = optarg;
break;
case 't':
rpi_params.timeout = atoi(optarg);
app_params.timeout = atoi(optarg);
break;
case '?':
if (optopt == 'b')
@ -155,7 +157,7 @@ int main (int argc, char **argv)
}
}
if (rpi_params.iface == COM_INTERFACE && rpi_params.port == NULL) {
if (app_params.iface == COM_INTERFACE && app_params.port == NULL) {
printf("port must be specified\n");
help();
exit(1);
@ -165,7 +167,7 @@ int main (int argc, char **argv)
printf ("Non-option argument %s\n", argv[index]);
}
if(platform_init(&rpi_params) != FPC_BEP_RESULT_OK) {
if(platform_init(&app_params) != FPC_BEP_RESULT_OK) {
help();
exit(1);
}
@ -176,13 +178,13 @@ int main (int argc, char **argv)
uint16_t template_id;
bool match;
rpi_clear_screen();
clear_screen();
printf("BM-Lite Interface\n");
if (rpi_params.iface == SPI_INTERFACE)
printf("SPI port: speed %d Hz\n", rpi_params.baudrate);
if (app_params.iface == SPI_INTERFACE)
printf("SPI port: speed %d Hz\n", app_params.baudrate);
else
printf("Com port: %s [speed: %d]\n", rpi_params.port, rpi_params.baudrate);
printf("Timeout: %ds\n", rpi_params.timeout);
printf("Com port: %s [speed: %d]\n", app_params.port, app_params.baudrate);
printf("Timeout: %ds\n", app_params.timeout);
printf("-------------------\n\n");
printf("Possible options:\n");
printf("a: Enroll finger\n");

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* 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.
*/
#ifndef CONSOLE_PARAMS_H
#define CONSOLE_PARAMS_H
#include <stdint.h>
#include <stdbool.h>
#include "fpc_bep_types.h"
#include "hcp_tiny.h"
typedef enum {
COM_INTERFACE = 0,
SPI_INTERFACE
} interface_t;
typedef struct {
interface_t iface;
char *port;
uint32_t baudrate;
uint32_t timeout;
HCP_comm_t *hcp_comm;
} console_initparams_t;
#endif

30
HAL_Driver/Linux/Linux.mk Normal file
View File

@ -0,0 +1,30 @@
#
# Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
#
# 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.
HAL = $(ROOT)/HAL_Driver/Linux
CC := gcc
CFLAGS +=\
-D_DEFAULT_SOURCE
VPATH += $(HAL)
C_INC += -I$(HAL)/inc
# Source Folders
VPATH += $(HAL)/src/
# C Sources
C_SRCS += $(notdir $(wildcard $(HAL)/src/*.c))

View File

@ -0,0 +1,5 @@
# BM-Lite Linux HAL
BM-Lite HAL implementation for Linux use spidev for SPI access and /sys/class/gpio for BM-Lite Reset & Status pin access
HW configuration can be changed in **BMLite_examples/Linux/inc/platform_defs.h**

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* 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.
*/
#ifndef PLATFORM_DEFS_H
#define PLATFORM_DEFS_H
#define BMLITE_SPI_DEV "/dev/spidev2.1"
#define BMLITE_RESET_PIN (504 + 3)
#define BMLITE_READY_PIN ((6 - 1) * 32 + 14)
typedef enum {
GPIO_DIR_IN,
GPIO_DIR_OUT
} gpio_dir_t;
#endif

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* 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.
*/
#ifndef PLATFORM_LINUX_H
#define PLATFORM_LINUX_H
/**
* @file platform.h
* @brief Platform specific function interface
*/
#include <stdint.h>
#include <stdbool.h>
#include "fpc_bep_types.h"
#include "hcp_tiny.h"
void clear_screen(void);
#endif /* PLATFORM_RPI_H */

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* 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.
*/
/**
* @file platform_linux.c
* @brief Linux platform specific functions
*/
#include <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include "bmlite_hal.h"
#include "platform.h"
#include "console_params.h"
#include "platform_defs.h"
#define MAX_FNAME_LEN 128
static int fd_spi = -1;
static int fd_reset_value = -1;
static int fd_ready_value = -1;
static struct spi_ioc_transfer spi_tr = {
.tx_buf = (unsigned long)0,
.rx_buf = (unsigned long)0,
.len = 0,
.delay_usecs = 1000,
.speed_hz = 500000,
.bits_per_word = 8,
};
static fpc_bep_result_t platform_spi_init(char *device, uint32_t baudrate);
static fpc_bep_result_t platform_gpio_init();
static int gpio_init(uint32_t pin, gpio_dir_t dir);
hal_tick_t hal_timebase_get_tick(void)
{
struct timeval current_time;
uint64_t time_in_ms;
gettimeofday(&current_time, NULL);
/* Seconds and microseconds are converted to milliseconds */
time_in_ms = current_time.tv_usec / 1000 + current_time.tv_sec * 1000;
return time_in_ms;
}
void hal_timebase_busy_wait(uint32_t ms)
{
usleep(ms * 1000);
}
void clear_screen(void)
{
system("clear");
}
void hal_timebase_init()
{
}
fpc_bep_result_t hal_board_init(void *params)
{
console_initparams_t *p = (console_initparams_t *)params;
switch (p->iface) {
case SPI_INTERFACE:
if(p->port == NULL)
p->port = BMLITE_SPI_DEV;
if(platform_spi_init(p->port, p->baudrate) != FPC_BEP_RESULT_OK) {
printf("SPI initialization failed\n");
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
break;
default:
printf("Interface not specified'n");
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
p->hcp_comm->read = platform_bmlite_spi_receive;
p->hcp_comm->write = platform_bmlite_spi_send;
p->hcp_comm->phy_rx_timeout = p->timeout*1000;
return platform_gpio_init();
}
void hal_bmlite_reset(bool state)
{
/* The reset pin is controlled by WiringPis digitalWrite function*/
if (state) {
write(fd_reset_value, "0", 2);
} else {
write(fd_reset_value, "1", 2);
}
}
bool hal_bmlite_get_status(void)
{
char res[2];
lseek (fd_ready_value, 0, SEEK_SET);
read (fd_ready_value, res, 2);
return res[0] == '1';
}
fpc_bep_result_t hal_bmlite_spi_write_read(uint8_t *write, uint8_t *read, size_t size,
bool leave_cs_asserted)
{
size_t status;
spi_tr.tx_buf = (unsigned long)write;
spi_tr.rx_buf = (unsigned long)read;
spi_tr.len = size;
status = ioctl(fd_spi, SPI_IOC_MESSAGE(1), &spi_tr);
/*
* Status returns the number of bytes sent, if this number is different
* from the the number of bytes written an error has occured.
*/
if (status == size) {
return FPC_BEP_RESULT_OK;
}
return FPC_BEP_RESULT_IO_ERROR;
}
static fpc_bep_result_t platform_spi_init(char *device, uint32_t baudrate)
{
uint8_t mode = 0;
uint32_t speed = baudrate;
uint8_t bits = 8;
spi_tr.bits_per_word = bits;
spi_tr.speed_hz = baudrate;
fd_spi = open(device, O_RDWR);
if (fd_spi < 0) {
printf("Can't open device %s\n", device);
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
if(ioctl(fd_spi, SPI_IOC_WR_MODE, &mode) < 0) {
printf("Can't set spi mode");
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
if(ioctl(fd_spi, SPI_IOC_WR_BITS_PER_WORD, &bits) < 0) {
printf("Can't set bits per word");
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
if(ioctl(fd_spi, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) {
printf("Can't set speed hz");
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
return FPC_BEP_RESULT_OK;
}
static fpc_bep_result_t platform_gpio_init()
{
fd_reset_value = gpio_init(BMLITE_RESET_PIN, GPIO_DIR_OUT);
fd_ready_value = gpio_init(BMLITE_READY_PIN, GPIO_DIR_IN);
if(fd_ready_value < 0 || fd_ready_value < 0)
return FPC_BEP_RESULT_INTERNAL_ERROR;
else
return FPC_BEP_RESULT_OK;
}
static int gpio_init(uint32_t pin, gpio_dir_t dir)
{
char fn_val[MAX_FNAME_LEN];
char tmp[MAX_FNAME_LEN];
int fd;
int flags;
snprintf(fn_val, MAX_FNAME_LEN, "/sys/class/gpio/gpio%d/value", pin);
// Export pin
if((fd = open(fn_val, O_SYNC | O_WRONLY)) < 0) {
fd = open("/sys/class/gpio/export", O_SYNC | O_WRONLY);
if(fd < 0) {
if(dir == GPIO_DIR_OUT)
printf("Can't export BM-Lite RESET pin\n");
else
printf("Can't export BM-Lite READY pin\n");
return FPC_BEP_RESULT_INTERNAL_ERROR;
}
int size = snprintf(tmp, MAX_FNAME_LEN, "%d", pin);
write(fd, tmp, size);
close(fd);
} else {
close(fd);
}
// Set pin direction
snprintf (tmp, MAX_FNAME_LEN, "/sys/class/gpio/gpio%d/direction", pin);
fd = open(tmp, O_SYNC | O_WRONLY);
if(fd >= 0) {
// Some GPIO doesn't allow to change pin direction
if(dir == GPIO_DIR_OUT)
write(fd, "out", 4);
else
write(fd, "in", 4);
close(fd);
}
if(dir == GPIO_DIR_OUT)
flags = O_SYNC | O_WRONLY;
else
flags = O_SYNC | O_RDONLY;
fd = open(fn_val, flags);
if(fd < 0) {
printf("Can't open %s\n", fn_val);
}
return fd;
}

View File

@ -10,4 +10,4 @@ Based on [BM-LIte Development Kit](https://www.fingerprints.com/solutions/access
| BMLITE_IRQ | 22 |
| SPI_CHANNEL | 1 |
HW configuration can be changed in **BMLite_examples/RaspberryPiinc/raspberry_pi_hal.h**
HW configuration can be changed in **BMLite_examples/RaspberryPi/inc/platform_rpi.h**

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2020 Andrey Perminov <andrey.ppp@gmail.com>
*
* 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.
*/
#ifndef PLATFORM_LINUX_H
#define PLATFORM_LINUX_H
/**
* @file platform.h
* @brief Platform specific function interface
*/
#include <stdint.h>
#include <stdbool.h>
#include "fpc_bep_types.h"
#include "hcp_tiny.h"
void clear_screen(void);
#endif /* PLATFORM_RPI_H */

View File

@ -31,24 +31,11 @@
#include "fpc_bep_types.h"
#include "hcp_tiny.h"
typedef enum {
COM_INTERFACE = 0,
SPI_INTERFACE
} interface_t;
typedef struct {
interface_t iface;
char *port;
uint32_t baudrate;
uint32_t timeout;
HCP_comm_t *hcp_comm;
} rpi_initparams_t;
/*
* Pin definitions for RPI 3
*/
#define BMLITE_RESET_PIN 0
#define BMLITE_READY_PIN 22
#define BMLITE_READY_PIN 22
#define SPI_CHANNEL 0
/**
@ -123,7 +110,7 @@ fpc_bep_result_t platform_spi_receive(uint16_t size, uint8_t *data, uint32_t tim
/**
* @brief Clear console screen
*/
void rpi_clear_screen(void);
void clear_screen(void);
/**
* @brief Busy wait.

View File

@ -36,6 +36,7 @@
#include "bmlite_hal.h"
#include "platform_rpi.h"
#include "platform.h"
#include "console_params.h"
hal_tick_t hal_timebase_get_tick(void)
{
@ -54,7 +55,7 @@ void hal_timebase_busy_wait(uint32_t ms)
usleep(ms * 1000);
}
void rpi_clear_screen(void)
void clear_screen(void)
{
system("clear");
}
@ -65,7 +66,7 @@ void hal_timebase_init()
fpc_bep_result_t hal_board_init(void *params)
{
rpi_initparams_t *p = (rpi_initparams_t *)params;
console_initparams_t *p = (console_initparams_t *)params;
switch (p->iface) {
case SPI_INTERFACE:
if(!rpi_spi_init(p->baudrate)) {

View File

@ -138,7 +138,7 @@ bool rpi_spi_init(uint32_t speed_hz)
return true;
}
fpc_bep_result_t hal_bmlite_spi_write_read(const uint8_t *write, uint8_t *read, 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)
{
/*