diff --git a/BMLite_examples/Makefile b/BMLite_examples/Makefile index 5e9f593..e6a73af 100644 --- a/BMLite_examples/Makefile +++ b/BMLite_examples/Makefile @@ -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 diff --git a/BMLite_examples/console_app/src/main.c b/BMLite_examples/console_app/src/main.c index 4370d11..5fa189f 100644 --- a/BMLite_examples/console_app/src/main.c +++ b/BMLite_examples/console_app/src/main.c @@ -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"); diff --git a/BMLite_sdk/inc/console_params.h b/BMLite_sdk/inc/console_params.h new file mode 100644 index 0000000..139853a --- /dev/null +++ b/BMLite_sdk/inc/console_params.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Andrey Perminov + * + * 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 +#include + +#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 \ No newline at end of file diff --git a/HAL_Driver/Linux/Linux.mk b/HAL_Driver/Linux/Linux.mk new file mode 100644 index 0000000..e6efc77 --- /dev/null +++ b/HAL_Driver/Linux/Linux.mk @@ -0,0 +1,30 @@ +# +# Copyright (c) 2020 Andrey Perminov +# +# 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)) \ No newline at end of file diff --git a/HAL_Driver/Linux/README.md b/HAL_Driver/Linux/README.md new file mode 100644 index 0000000..16ac22c --- /dev/null +++ b/HAL_Driver/Linux/README.md @@ -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** \ No newline at end of file diff --git a/HAL_Driver/Linux/inc/platform_defs.h b/HAL_Driver/Linux/inc/platform_defs.h new file mode 100644 index 0000000..bd673d2 --- /dev/null +++ b/HAL_Driver/Linux/inc/platform_defs.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 Andrey Perminov + * + * 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 \ No newline at end of file diff --git a/HAL_Driver/Linux/inc/platform_linux.h b/HAL_Driver/Linux/inc/platform_linux.h new file mode 100644 index 0000000..6f07e35 --- /dev/null +++ b/HAL_Driver/Linux/inc/platform_linux.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 Andrey Perminov + * + * 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 +#include + +#include "fpc_bep_types.h" +#include "hcp_tiny.h" + +void clear_screen(void); + +#endif /* PLATFORM_RPI_H */ diff --git a/HAL_Driver/Linux/src/platform_linux.c b/HAL_Driver/Linux/src/platform_linux.c new file mode 100644 index 0000000..43b092c --- /dev/null +++ b/HAL_Driver/Linux/src/platform_linux.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2020 Andrey Perminov + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(¤t_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; +} + diff --git a/HAL_Driver/RaspberryPi/README.md b/HAL_Driver/RaspberryPi/README.md index 4ec75d4..b05ff1c 100644 --- a/HAL_Driver/RaspberryPi/README.md +++ b/HAL_Driver/RaspberryPi/README.md @@ -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** \ No newline at end of file +HW configuration can be changed in **BMLite_examples/RaspberryPi/inc/platform_rpi.h** \ No newline at end of file diff --git a/HAL_Driver/RaspberryPi/inc/platform_linux.h b/HAL_Driver/RaspberryPi/inc/platform_linux.h new file mode 100644 index 0000000..6f07e35 --- /dev/null +++ b/HAL_Driver/RaspberryPi/inc/platform_linux.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 Andrey Perminov + * + * 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 +#include + +#include "fpc_bep_types.h" +#include "hcp_tiny.h" + +void clear_screen(void); + +#endif /* PLATFORM_RPI_H */ diff --git a/HAL_Driver/RaspberryPi/inc/platform_rpi.h b/HAL_Driver/RaspberryPi/inc/platform_rpi.h index cc0d3bd..556473e 100644 --- a/HAL_Driver/RaspberryPi/inc/platform_rpi.h +++ b/HAL_Driver/RaspberryPi/inc/platform_rpi.h @@ -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. diff --git a/HAL_Driver/RaspberryPi/src/platform_linux.c b/HAL_Driver/RaspberryPi/src/platform_rpi.c similarity index 95% rename from HAL_Driver/RaspberryPi/src/platform_linux.c rename to HAL_Driver/RaspberryPi/src/platform_rpi.c index 4874a64..9dd0b5e 100644 --- a/HAL_Driver/RaspberryPi/src/platform_linux.c +++ b/HAL_Driver/RaspberryPi/src/platform_rpi.c @@ -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)) { diff --git a/HAL_Driver/RaspberryPi/src/rpi_spi.c b/HAL_Driver/RaspberryPi/src/rpi_spi.c index 1dffbc6..5b963d5 100644 --- a/HAL_Driver/RaspberryPi/src/rpi_spi.c +++ b/HAL_Driver/RaspberryPi/src/rpi_spi.c @@ -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) { /*