Check-in of hardware abstraction layer
This commit is contained in:
parent
459f1d3217
commit
69d2363b59
26
README.md
26
README.md
@ -9,6 +9,21 @@ targeted to RPi and Dragino LoRA/GPS HAT.
|
||||
The goal was to keep the LMIC 1.6 sourcecode untouched, and just provide a
|
||||
Hardware Abstraction Layer (HAL) for Raspberry Pi and Dragino LoRa/GPS HAT.
|
||||
|
||||
## Installation
|
||||
|
||||
### WiringPi
|
||||
To control the RPi's GPI ports, the WiringPi GPIO interface library has to
|
||||
be installed. On some operating systems WiringPi is already installed per
|
||||
default. For instructions on manual installation please refer to the
|
||||
following site:
|
||||
http://wiringpi.com/download-and-install/
|
||||
|
||||
### Enable SPI interface
|
||||
Per default, the SPI ports on the Raspberry Pi are disabled. You need to
|
||||
manually enable them using raspi-config.
|
||||
Follow the instructions given here:
|
||||
https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
|
||||
|
||||
## Note on LMIC 1.6 license
|
||||
Text copied from https://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html
|
||||
|
||||
@ -16,4 +31,15 @@ IBM "LoRa WAN in C" is the LoRa WAN implementation of choice, and a perfect
|
||||
match to the IBM LRSC on the end device. It is provided as open source under
|
||||
the BSD License.
|
||||
|
||||
## Example "hello"
|
||||
Directory: /examples/hello
|
||||
|
||||
Modifications neccessary: None
|
||||
|
||||
This example does not use radio, it just periodically logs a counter value.
|
||||
Can be used to checked if the timer implemenation on RPi works as expected.
|
||||
|
||||
cd examples/hello
|
||||
make clean
|
||||
make
|
||||
sudo ./build/hello.out
|
||||
|
BIN
examples/hello/build/aes.o
Normal file
BIN
examples/hello/build/aes.o
Normal file
Binary file not shown.
BIN
examples/hello/build/debug.o
Normal file
BIN
examples/hello/build/debug.o
Normal file
Binary file not shown.
BIN
examples/hello/build/gpio.o
Normal file
BIN
examples/hello/build/gpio.o
Normal file
Binary file not shown.
BIN
examples/hello/build/hal.o
Normal file
BIN
examples/hello/build/hal.o
Normal file
Binary file not shown.
BIN
examples/hello/build/hello.out
Executable file
BIN
examples/hello/build/hello.out
Executable file
Binary file not shown.
BIN
examples/hello/build/lmic.o
Normal file
BIN
examples/hello/build/lmic.o
Normal file
Binary file not shown.
BIN
examples/hello/build/main.o
Normal file
BIN
examples/hello/build/main.o
Normal file
Binary file not shown.
BIN
examples/hello/build/oslmic.o
Normal file
BIN
examples/hello/build/oslmic.o
Normal file
Binary file not shown.
BIN
examples/hello/build/radio.o
Normal file
BIN
examples/hello/build/radio.o
Normal file
Binary file not shown.
@ -1,89 +1,25 @@
|
||||
# SELECT TOOLCHAIN GNU/IAR/KEIL
|
||||
TOOLCHAIN = keil
|
||||
|
||||
# EDIT CONFIGURATIONS BELOW TO REFLECT COMPILER INSTALL DIR AND CMSIS INCLUDE DIR
|
||||
|
||||
# IAR TOOLCHAIN
|
||||
ifeq (${TOOLCHAIN}, iar)
|
||||
IAR = C:/PROGRA~2/IARSYS~1/EMBEDD~1.5_2/arm
|
||||
INC = ${IAR}/CMSIS/Include
|
||||
CC = ${IAR}/bin/iccarm
|
||||
AS = ${IAR}/bin/iasmarm
|
||||
LN = ${IAR}/bin/ilinkarm
|
||||
HEX = ${IAR}/bin/ielftool --ihex
|
||||
BIN = ${IAR}/bin/ielftool --bin
|
||||
|
||||
CCOPTS = --cpu=Cortex-M3 --endian=little --diag_suppress Pa050,Pa089,Pe066
|
||||
ASOPTS = --cpu Cortex-M3
|
||||
LNOPTS = --semihosting --config ${IAR}/config/linker/ST/STM32L152xB.icf
|
||||
endif
|
||||
|
||||
# KEIL TOOLCHAIN
|
||||
ifeq (${TOOLCHAIN}, keil)
|
||||
KEIL = C:/Keil_v5
|
||||
INC = ${KEIL}/ARM/Pack/ARM/CMSIS/4.1.0/CMSIS/Include
|
||||
CC = ${KEIL}/ARM/ARMCC/bin/armcc.exe
|
||||
AS = ${KEIL}/ARM/ARMCC/bin/armasm.exe
|
||||
LN = ${KEIL}/ARM/ARMCC/bin/armlink.exe
|
||||
HEX = ${KEIL}/ARM/ARMCC/bin/fromelf.exe --i32
|
||||
BIN = ${KEIL}/ARM/ARMCC/bin/fromelf.exe --bin
|
||||
|
||||
CCOPTS = --cpu=Cortex-M3 -c --c99 -D__MICROLIB --apcs=interwork --split_sections
|
||||
ASOPTS = --cpu Cortex-M3 --pd "__MICROLIB SETA 1"
|
||||
LNOPTS = --library_type=microlib --ro-base 0x08000000 --entry 0x08000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors --strict --summary_stderr --info summarysizes
|
||||
HEXOPTS = --output
|
||||
endif
|
||||
|
||||
# GNU TOOLCHAIN
|
||||
ifeq (${TOOLCHAIN}, gnu)
|
||||
GNU = /opt/arm-gnu-toolchain-4.9.3.475/arm-none-eabi
|
||||
CC = ${GNU}/bin/arm-none-eabi-gcc
|
||||
AS = ${GNU}/bin/arm-none-eabi-as
|
||||
LN = ${GNU}/bin/arm-none-eabi-gcc
|
||||
HEX = ${GNU}/bin/arm-none-eabi-objcopy -O ihex
|
||||
BIN = ${GNU}/bin/arm-none-eabi-objcopy -O binary
|
||||
|
||||
# OpenOCD
|
||||
OPENOCD := /opt/openocd-0.9.0/bin/openocd
|
||||
|
||||
CMSIS_INC = ../../stm32/CMSIS/Include
|
||||
define CMSIS_MSG
|
||||
ERROR: CMSIS Library missing: $(CMSIS_INC)
|
||||
## CMSIS: Cortex Microcontroller Software Interface Standard
|
||||
## CMSIS Library can be obtained from the STM32L1xx standard peripherals library
|
||||
## Download URL: www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257913
|
||||
endef
|
||||
ifeq (,$(wildcard $(CMSIS_INC)))
|
||||
$(error $(CMSIS_MSG))
|
||||
endif
|
||||
|
||||
LINKER_SCRIPT = ../../stm32/STM32L152VB_FLASH.ld
|
||||
define LNK_SCRIPT_MSG
|
||||
ERROR: Linker Script missing: $(LINKER_SCRIPT)
|
||||
## Linker Script can be obtained from the STM32L1xx standard peripherals library
|
||||
## Download URL: www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257913
|
||||
endef
|
||||
ifeq (,$(wildcard $(LINKER_SCRIPT)))
|
||||
$(error $(LNK_SCRIPT_MSG))
|
||||
endif
|
||||
|
||||
INC = $(CMSIS_INC)
|
||||
|
||||
CPU = -mcpu=cortex-m3 -mthumb
|
||||
CCOPTS = $(CPU) -c -std=gnu99
|
||||
CCOPTS += -fno-common -fmessage-length=0 -fno-builtin -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
|
||||
ASOPTS = $(CPU)
|
||||
LNOPTS = $(CPU) -Wl,--gc-sections -T$(LINKER_SCRIPT)
|
||||
endif
|
||||
#
|
||||
# 2017-04-12 Wolfgang Klenk
|
||||
#
|
||||
# Adapted for use on Raspberry Pi and Dragino LoRa/GPS HAT
|
||||
# working in EU868 MHz Band
|
||||
|
||||
# LMIC CONFIG
|
||||
LMICCFG += -DSTM32L1XX_MD -DCFG_DEBUG -DCFG_eu868 -DCFG_wimod_board -DCFG_sx1272_radio -DCFG_lmic_clib
|
||||
LMICCFG += -DCFG_DEBUG -DCFG_eu868 -DCFG_sx1276_radio -DDEBUG_LMIC -DDEBUG_HAL
|
||||
|
||||
CCOPTS = -c -std=gnu99
|
||||
|
||||
LNOPTS = -lwiringPi
|
||||
INC = .
|
||||
CC = gcc
|
||||
LN = gcc
|
||||
|
||||
LMICDIR = ../../lmic
|
||||
HALDIR = ../../stm32
|
||||
HALDIR = ../../lora_gps_hat
|
||||
TOOLSDIR = ../../tools
|
||||
BUILDDIR = build
|
||||
|
||||
|
||||
# RULES
|
||||
SRCS = $(notdir $(wildcard ${LMICDIR}/*.c ${HALDIR}/*.c ${HALDIR}/*_${TOOLCHAIN}.s *.c))
|
||||
OBJS = $(patsubst %, ${BUILDDIR}/%.o, $(basename ${SRCS}))
|
||||
@ -99,20 +35,13 @@ ${BUILDDIR}/%.o: %.s | ${BUILDDIR}
|
||||
${BUILDDIR}/%.out: ${OBJS}
|
||||
${LN} ${LNOPTS} -o $@ $^
|
||||
|
||||
${BUILDDIR}/%.hex: ${BUILDDIR}/%.out
|
||||
${HEX} $< ${HEXOPTS} $@
|
||||
|
||||
${BUILDDIR}/%.bin: ${BUILDDIR}/%.out
|
||||
${BIN} $< ${HEXOPTS} $@
|
||||
|
||||
all: ${BUILDDIR}/$(notdir ${CURDIR}).bin ${BUILDDIR}/$(notdir ${CURDIR}).hex
|
||||
#all: ${BUILDDIR}/$(notdir ${CURDIR}).out ${BUILDDIR}/$(notdir ${CURDIR}).bin ${BUILDDIR}/$(notdir ${CURDIR}).hex
|
||||
all: ${BUILDDIR}/$(notdir ${CURDIR}).out
|
||||
|
||||
clean:
|
||||
rm -rf ${BUILDDIR} Debug RTE settings *.dep *.bak *.sfr *.map *.uvguix.*
|
||||
|
||||
load: ${BUILDDIR}/$(notdir ${CURDIR}).bin
|
||||
$(OPENOCD) -f $(TOOLSDIR)/openocd/wimod.cfg -f $(TOOLSDIR)/openocd/flash.cfg -c "flash_binary $<"
|
||||
|
||||
${BUILDDIR}:
|
||||
mkdir $@
|
||||
|
||||
|
121
examples/projects.gmk.lmic_1.6_original
Normal file
121
examples/projects.gmk.lmic_1.6_original
Normal file
@ -0,0 +1,121 @@
|
||||
# SELECT TOOLCHAIN GNU/IAR/KEIL
|
||||
TOOLCHAIN = keil
|
||||
|
||||
# EDIT CONFIGURATIONS BELOW TO REFLECT COMPILER INSTALL DIR AND CMSIS INCLUDE DIR
|
||||
|
||||
# IAR TOOLCHAIN
|
||||
ifeq (${TOOLCHAIN}, iar)
|
||||
IAR = C:/PROGRA~2/IARSYS~1/EMBEDD~1.5_2/arm
|
||||
INC = ${IAR}/CMSIS/Include
|
||||
CC = ${IAR}/bin/iccarm
|
||||
AS = ${IAR}/bin/iasmarm
|
||||
LN = ${IAR}/bin/ilinkarm
|
||||
HEX = ${IAR}/bin/ielftool --ihex
|
||||
BIN = ${IAR}/bin/ielftool --bin
|
||||
|
||||
CCOPTS = --cpu=Cortex-M3 --endian=little --diag_suppress Pa050,Pa089,Pe066
|
||||
ASOPTS = --cpu Cortex-M3
|
||||
LNOPTS = --semihosting --config ${IAR}/config/linker/ST/STM32L152xB.icf
|
||||
endif
|
||||
|
||||
# KEIL TOOLCHAIN
|
||||
ifeq (${TOOLCHAIN}, keil)
|
||||
KEIL = C:/Keil_v5
|
||||
INC = ${KEIL}/ARM/Pack/ARM/CMSIS/4.1.0/CMSIS/Include
|
||||
CC = ${KEIL}/ARM/ARMCC/bin/armcc.exe
|
||||
AS = ${KEIL}/ARM/ARMCC/bin/armasm.exe
|
||||
LN = ${KEIL}/ARM/ARMCC/bin/armlink.exe
|
||||
HEX = ${KEIL}/ARM/ARMCC/bin/fromelf.exe --i32
|
||||
BIN = ${KEIL}/ARM/ARMCC/bin/fromelf.exe --bin
|
||||
|
||||
CCOPTS = --cpu=Cortex-M3 -c --c99 -D__MICROLIB --apcs=interwork --split_sections
|
||||
ASOPTS = --cpu Cortex-M3 --pd "__MICROLIB SETA 1"
|
||||
LNOPTS = --library_type=microlib --ro-base 0x08000000 --entry 0x08000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors --strict --summary_stderr --info summarysizes
|
||||
HEXOPTS = --output
|
||||
endif
|
||||
|
||||
# GNU TOOLCHAIN
|
||||
ifeq (${TOOLCHAIN}, gnu)
|
||||
GNU = /opt/arm-gnu-toolchain-4.9.3.475/arm-none-eabi
|
||||
CC = ${GNU}/bin/arm-none-eabi-gcc
|
||||
AS = ${GNU}/bin/arm-none-eabi-as
|
||||
LN = ${GNU}/bin/arm-none-eabi-gcc
|
||||
HEX = ${GNU}/bin/arm-none-eabi-objcopy -O ihex
|
||||
BIN = ${GNU}/bin/arm-none-eabi-objcopy -O binary
|
||||
|
||||
# OpenOCD
|
||||
OPENOCD := /opt/openocd-0.9.0/bin/openocd
|
||||
|
||||
CMSIS_INC = ../../stm32/CMSIS/Include
|
||||
define CMSIS_MSG
|
||||
ERROR: CMSIS Library missing: $(CMSIS_INC)
|
||||
## CMSIS: Cortex Microcontroller Software Interface Standard
|
||||
## CMSIS Library can be obtained from the STM32L1xx standard peripherals library
|
||||
## Download URL: www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257913
|
||||
endef
|
||||
ifeq (,$(wildcard $(CMSIS_INC)))
|
||||
$(error $(CMSIS_MSG))
|
||||
endif
|
||||
|
||||
LINKER_SCRIPT = ../../stm32/STM32L152VB_FLASH.ld
|
||||
define LNK_SCRIPT_MSG
|
||||
ERROR: Linker Script missing: $(LINKER_SCRIPT)
|
||||
## Linker Script can be obtained from the STM32L1xx standard peripherals library
|
||||
## Download URL: www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/PF257913
|
||||
endef
|
||||
ifeq (,$(wildcard $(LINKER_SCRIPT)))
|
||||
$(error $(LNK_SCRIPT_MSG))
|
||||
endif
|
||||
|
||||
INC = $(CMSIS_INC)
|
||||
|
||||
CPU = -mcpu=cortex-m3 -mthumb
|
||||
CCOPTS = $(CPU) -c -std=gnu99
|
||||
CCOPTS += -fno-common -fmessage-length=0 -fno-builtin -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -MMD -MP
|
||||
ASOPTS = $(CPU)
|
||||
LNOPTS = $(CPU) -Wl,--gc-sections -T$(LINKER_SCRIPT)
|
||||
endif
|
||||
|
||||
# LMIC CONFIG
|
||||
LMICCFG += -DSTM32L1XX_MD -DCFG_DEBUG -DCFG_eu868 -DCFG_wimod_board -DCFG_sx1272_radio -DCFG_lmic_clib
|
||||
|
||||
LMICDIR = ../../lmic
|
||||
HALDIR = ../../stm32
|
||||
TOOLSDIR = ../../tools
|
||||
BUILDDIR = build
|
||||
|
||||
# RULES
|
||||
SRCS = $(notdir $(wildcard ${LMICDIR}/*.c ${HALDIR}/*.c ${HALDIR}/*_${TOOLCHAIN}.s *.c))
|
||||
OBJS = $(patsubst %, ${BUILDDIR}/%.o, $(basename ${SRCS}))
|
||||
|
||||
VPATH = ${LMICDIR} ${HALDIR} .
|
||||
|
||||
${BUILDDIR}/%.o: %.c | ${BUILDDIR}
|
||||
${CC} ${CCOPTS} ${LMICCFG} -I${INC} -I${LMICDIR} -I${HALDIR} $< -o$@
|
||||
|
||||
${BUILDDIR}/%.o: %.s | ${BUILDDIR}
|
||||
${AS} ${ASOPTS} -I${INC} $< -o $@
|
||||
|
||||
${BUILDDIR}/%.out: ${OBJS}
|
||||
${LN} ${LNOPTS} -o $@ $^
|
||||
|
||||
${BUILDDIR}/%.hex: ${BUILDDIR}/%.out
|
||||
${HEX} $< ${HEXOPTS} $@
|
||||
|
||||
${BUILDDIR}/%.bin: ${BUILDDIR}/%.out
|
||||
${BIN} $< ${HEXOPTS} $@
|
||||
|
||||
all: ${BUILDDIR}/$(notdir ${CURDIR}).bin ${BUILDDIR}/$(notdir ${CURDIR}).hex
|
||||
|
||||
clean:
|
||||
rm -rf ${BUILDDIR} Debug RTE settings *.dep *.bak *.sfr *.map *.uvguix.*
|
||||
|
||||
load: ${BUILDDIR}/$(notdir ${CURDIR}).bin
|
||||
$(OPENOCD) -f $(TOOLSDIR)/openocd/wimod.cfg -f $(TOOLSDIR)/openocd/flash.cfg -c "flash_binary $<"
|
||||
|
||||
${BUILDDIR}:
|
||||
mkdir $@
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
.SECONDARY:
|
82
lora_gps_hat/debug.c
Normal file
82
lora_gps_hat/debug.c
Normal file
@ -0,0 +1,82 @@
|
||||
//
|
||||
// BSD 3-Clause License
|
||||
//
|
||||
// Hardware Abstraction Layer (HAL) targeted to Raspberry Pi and
|
||||
// Dragino LoRa/GPS HAT
|
||||
//
|
||||
// Copyright (c) 2017, Wolfgang Klenk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lmic.h"
|
||||
#include "debug.h"
|
||||
|
||||
void debug_init () {
|
||||
fprintf(stdout, "%09d Debug: Initializing\n", osticks2ms(hal_ticks()));
|
||||
}
|
||||
|
||||
void debug_str (const char* str) {
|
||||
fprintf(stdout, "%09d Debug: %s\n", osticks2ms(hal_ticks()), str);
|
||||
}
|
||||
|
||||
void debug_val (const char* label, u4_t val) {
|
||||
fprintf(stdout, "%09d Debug: Label '%s' value 0x%x\n", osticks2ms(hal_ticks()), label, val);
|
||||
}
|
||||
|
||||
void debug_led (int val) {
|
||||
// fprintf(stdout, "Debug: Set LED to 0x%02x\n", val);
|
||||
}
|
||||
|
||||
void debug_event (int ev) {
|
||||
static const char* evnames[] = {
|
||||
[EV_SCAN_TIMEOUT] = "SCAN_TIMEOUT",
|
||||
[EV_BEACON_FOUND] = "BEACON_FOUND",
|
||||
[EV_BEACON_MISSED] = "BEACON_MISSED",
|
||||
[EV_BEACON_TRACKED] = "BEACON_TRACKED",
|
||||
[EV_JOINING] = "JOINING",
|
||||
[EV_JOINED] = "JOINED",
|
||||
[EV_RFU1] = "RFU1",
|
||||
[EV_JOIN_FAILED] = "JOIN_FAILED",
|
||||
[EV_REJOIN_FAILED] = "REJOIN_FAILED",
|
||||
[EV_TXCOMPLETE] = "TXCOMPLETE",
|
||||
[EV_LOST_TSYNC] = "LOST_TSYNC",
|
||||
[EV_RESET] = "RESET",
|
||||
[EV_RXCOMPLETE] = "RXCOMPLETE",
|
||||
[EV_LINK_DEAD] = "LINK_DEAD",
|
||||
[EV_LINK_ALIVE] = "LINK_ALIVE",
|
||||
[EV_SCAN_FOUND] = "SCAN_FOUND",
|
||||
[EV_TXSTART] = "EV_TXSTART",
|
||||
};
|
||||
debug_str((ev < sizeof(evnames)/sizeof(evnames[0])) ? evnames[ev] : "EV_UNKNOWN" );
|
||||
}
|
||||
|
||||
void debug_buf (const u1_t* buf, int len) {
|
||||
fprintf(stdout, "%09d Debug: Buffer received. length=%d\n", osticks2ms(hal_ticks()), len);
|
||||
}
|
63
lora_gps_hat/debug.h
Normal file
63
lora_gps_hat/debug.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2014-2016 IBM Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the <organization> nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
// intialize debug library
|
||||
void debug_init (void);
|
||||
|
||||
// set LED state
|
||||
void debug_led (int val);
|
||||
|
||||
// write character to USART
|
||||
void debug_char (char c);
|
||||
|
||||
// write byte as two hex digits to USART
|
||||
void debug_hex (u1_t b);
|
||||
|
||||
// write buffer as hex dump to USART
|
||||
void debug_buf (const u1_t* buf, int len);
|
||||
|
||||
// write 32-bit integer as eight hex digits to USART
|
||||
void debug_uint (u4_t v);
|
||||
|
||||
// write 32-bit integer as signed decimal digits to USART
|
||||
void debug_int (s4_t v);
|
||||
|
||||
// write nul-terminated string to USART
|
||||
void debug_str (const char* str);
|
||||
|
||||
// write LMiC event name to USART
|
||||
void debug_event (int ev);
|
||||
|
||||
// write label and 32-bit value as hex to USART
|
||||
void debug_val (const char* label, u4_t val);
|
||||
|
||||
// write label and 32-bit value as signed decimal to USART
|
||||
void debug_valdec (const char* label, s4_t val);
|
||||
|
||||
// convert integer 'val' to ASCII string (bin/oct/dec/hex/base36)
|
||||
// store string at 'buf', return number of characters written
|
||||
int debug_fmt (char* buf, int max, s4_t val, int base, int width, char pad);
|
200
lora_gps_hat/gpio.c
Normal file
200
lora_gps_hat/gpio.c
Normal file
@ -0,0 +1,200 @@
|
||||
//
|
||||
// BSD 3-Clause License
|
||||
//
|
||||
// Hardware Abstraction Layer (HAL) targeted to Raspberry Pi and
|
||||
// Dragino LoRa/GPS HAT
|
||||
//
|
||||
// Copyright (c) 2017, Wolfgang Klenk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
/**
|
||||
* Ask the kernel to export control of a GPIO to userspace by writing its number to file
|
||||
* /sys/class/gpio/export.
|
||||
*/
|
||||
void gpioExportPin(int pin) {
|
||||
static const char* fn = "/sys/class/gpio/export";
|
||||
int fd = open(fn, O_WRONLY);
|
||||
if(fd < 0) {
|
||||
perror(fn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char str_pin[16];
|
||||
snprintf(str_pin, 16, "%d", pin);
|
||||
|
||||
size_t rc = write(fd, str_pin, strlen(str_pin));
|
||||
if(rc != strlen(str_pin)) {
|
||||
perror("exportPin");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the effect of exporting a GPIO to userspace by writing its number to file
|
||||
* /sys/class/gpio/unexport.
|
||||
*/
|
||||
void gpioUnexportPin(int pin) {
|
||||
static const char* fn = "/sys/class/gpio/unexport";
|
||||
int fd = open(fn, O_WRONLY);
|
||||
if(fd < 0) {
|
||||
perror(fn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char str_pin[16];
|
||||
snprintf(str_pin, 16, "%d", pin);
|
||||
|
||||
size_t rc = write(fd, str_pin, strlen(str_pin));
|
||||
if(rc != strlen(str_pin)) {
|
||||
// perror("gpioUnexportPin");
|
||||
// exit(1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the direction of a GPIO pin.
|
||||
* Reads as either "in" or "out". This value may normally be written.
|
||||
* Writing as "out" defaults to initializing the value as low.
|
||||
* To ensure glitch free operation, values "low" and "high" may be written to
|
||||
* configure the GPIO as an output with that initial value.
|
||||
*/
|
||||
void gpioSetPinDirection(int pin, const char* direction) {
|
||||
|
||||
const int BUFSIZE = 64;
|
||||
char fn[BUFSIZE];
|
||||
snprintf(fn, BUFSIZE, "/sys/class/gpio/gpio%d/direction", pin);
|
||||
int fd = open(fn, O_WRONLY);
|
||||
if(fd < 0) {
|
||||
perror(fn);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
size_t rc = write(fd, direction, strlen(direction));
|
||||
if(rc != strlen(direction)) {
|
||||
perror("gpioSetPinDirection");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the signal edge(s) that will make poll(2) on the "value" file return.
|
||||
* Reads as either "none", "rising", "falling", or "both".
|
||||
* This file exists only if the pin can be configured as an interrupt generating input pin.
|
||||
*/
|
||||
void gpioSetPinEdge(int pin, void* edge) {
|
||||
|
||||
const int BUFSIZE = 64;
|
||||
char fn[BUFSIZE];
|
||||
snprintf(fn, BUFSIZE, "/sys/class/gpio/gpio%d/edge", pin);
|
||||
int fd = open(fn, O_WRONLY);
|
||||
if(fd < 0) {
|
||||
perror(fn);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
size_t rc = write(fd, edge, strlen(edge));
|
||||
if(rc != strlen(edge)) {
|
||||
perror("setPinEdge");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int gpioWaitForInterrupt(const int *pins, size_t npins, int timeout_ms) {
|
||||
|
||||
struct pollfd pl[npins];
|
||||
|
||||
const int BUFSIZE = 64;
|
||||
char fn[BUFSIZE];
|
||||
|
||||
for (int i=0 ; i<npins ; i++) {
|
||||
snprintf(fn, BUFSIZE, "/sys/class/gpio/gpio%d/value", pins[i]);
|
||||
int fd = open(fn, O_RDONLY);
|
||||
if(fd < 0) {
|
||||
perror(fn);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Clear the interrupt by reading
|
||||
char c;
|
||||
int rc = read(fd, &c, 1);
|
||||
if (rc < 0) {
|
||||
perror("Clear interrupt.");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
pl[i].fd = fd;
|
||||
pl[i].events = POLLPRI | POLLERR;
|
||||
}
|
||||
|
||||
int rc = poll(pl, npins, timeout_ms);
|
||||
if(rc < 0) {
|
||||
fprintf(stderr, "HAL: Cannot poll: %s\n", strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Timeout
|
||||
if (rc == 0) {
|
||||
for (int i=0 ; i<npins ; i++) {
|
||||
close(pl[i].fd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
for (int i=0 ; i<npins ; i++) {
|
||||
close(pl[i].fd);
|
||||
|
||||
if (pl[i].revents > 0) {
|
||||
rc |= (1<<i);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
62
lora_gps_hat/gpio.h
Normal file
62
lora_gps_hat/gpio.h
Normal file
@ -0,0 +1,62 @@
|
||||
//
|
||||
// BSD 3-Clause License
|
||||
//
|
||||
// Hardware Abstraction Layer (HAL) targeted to Raspberry Pi and
|
||||
// Dragino LoRa/GPS HAT
|
||||
//
|
||||
// Copyright (c) 2017, Wolfgang Klenk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef GPIO_H
|
||||
#define GPIO_H
|
||||
|
||||
//
|
||||
// Implement some functionalities that WiringPi does not provide.
|
||||
//
|
||||
// Enables us to use OS call "poll" to _blocking_ check if there
|
||||
// was a transition on of several input pins.
|
||||
//
|
||||
|
||||
static char *GPIO_DIRECTION_IN = "in";
|
||||
static char *GPIO_DIRECTION_OUT = "out";
|
||||
static char *GPIO_DIRECTION_OUT_HIGH = "high";
|
||||
static char *GPIO_DIRECTION_OUT_LOW = "low";
|
||||
|
||||
static void* GPIO_EDGE_NONE = "none";
|
||||
static void* GPIO_EDGE_RISING = "rising";
|
||||
static void* GPIO_EDGE_FALLING = "falling";
|
||||
static void* GPIO_EDGE_BOTH = "both";
|
||||
|
||||
void gpioExportPin(int pin);
|
||||
void gpioUnexportPin(int pin);
|
||||
void gpioSetPinDirection(int pin, const char *direction);
|
||||
void gpioSetPinEdge(int pin, void* edge);
|
||||
int gpioWaitForInterrupt(const int *pins, size_t npins, int timeout_ms);
|
||||
|
||||
#endif
|
292
lora_gps_hat/hal.c
Normal file
292
lora_gps_hat/hal.c
Normal file
@ -0,0 +1,292 @@
|
||||
//
|
||||
// BSD 3-Clause License
|
||||
//
|
||||
// Hardware Abstraction Layer (HAL) targeted to Raspberry Pi and
|
||||
// Dragino LoRa/GPS HAT
|
||||
//
|
||||
// Copyright (c) 2017, Wolfgang Klenk
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <wiringPi.h>
|
||||
#include <wiringPiSPI.h>
|
||||
|
||||
#include "lmic.h"
|
||||
#include "gpio.h"
|
||||
|
||||
// Note: WiringPi Pin Numbering Schema
|
||||
const int WIRING_PI_PIN_NSS = 6;
|
||||
const int WIRING_PI_PIN_RST = 0;
|
||||
const int WIRING_PI_PIN_DIO[3] = { 7, 4, 5 };
|
||||
|
||||
// Note: BCM Pin Numbering Schema
|
||||
const int BCM_PIN_DIO[3] = { 4, 23, 24 };
|
||||
|
||||
// Local function prototypes
|
||||
void hal_time_init();
|
||||
void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result);
|
||||
|
||||
// Used to store the current time
|
||||
static struct timespec ts_start;
|
||||
|
||||
static s4_t sleep_interval_ms = 0;
|
||||
|
||||
void hal_init () {
|
||||
hal_time_init();
|
||||
|
||||
#ifdef DEBUG_HAL
|
||||
fprintf(stdout, "%09d HAL: Initializing ...\n", osticks2ms(hal_ticks()));
|
||||
#endif
|
||||
|
||||
wiringPiSetup();
|
||||
|
||||
// Pin Direction
|
||||
pinMode(WIRING_PI_PIN_NSS, OUTPUT);
|
||||
pinMode(WIRING_PI_PIN_RST, INPUT);
|
||||
|
||||
// WiringPi is missing a feature to _blocking_ wait for pins change
|
||||
// their values using the OS system call "poll". For this reason, we
|
||||
// needed to implement it on our own.
|
||||
for (int i=0 ; i<3 ; i++) {
|
||||
gpioUnexportPin(BCM_PIN_DIO[i]);
|
||||
}
|
||||
|
||||
for (int i=0 ; i<3 ; i++) {
|
||||
gpioExportPin(BCM_PIN_DIO[i]);
|
||||
gpioSetPinDirection(BCM_PIN_DIO[i], GPIO_DIRECTION_IN);
|
||||
gpioSetPinEdge(BCM_PIN_DIO[i], GPIO_EDGE_RISING);
|
||||
}
|
||||
|
||||
int rc = wiringPiSPISetup(0, 10000000);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "HAL: Initialization of SPI failed: %s\n", strerror(errno));
|
||||
hal_failed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void hal_failed () {
|
||||
fprintf(stderr, "%09d HAL: Failed. Aborting.\n", osticks2ms(hal_ticks()));
|
||||
for (int i=0 ; i<3 ; i++) {
|
||||
gpioUnexportPin(BCM_PIN_DIO[i]);
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// set radio NSS pin to given value
|
||||
void hal_pin_nss (u1_t val) {
|
||||
digitalWrite(WIRING_PI_PIN_NSS, val==0 ? LOW : HIGH);
|
||||
}
|
||||
|
||||
// switch between radio RX/TX
|
||||
void hal_pin_rxtx (u1_t val) {
|
||||
#ifdef DEBUG_HAL
|
||||
val > 0 ? fprintf(stdout, "%09d HAL: Sending ...\n", osticks2ms(hal_ticks()), val) : fprintf(stdout, "%09d HAL: Receiving ...\n", osticks2ms(hal_ticks()), val);
|
||||
#endif
|
||||
|
||||
// Nothing to do. There is no such pin in the Lora/GPS HAT module.
|
||||
}
|
||||
|
||||
// set radio RST pin to given value (or keep floating!)
|
||||
void hal_pin_rst (u1_t val) {
|
||||
#ifdef DEBUG_HAL
|
||||
fprintf(stdout, "%09d HAL: Set radio RST pin to 0x%02x\n", osticks2ms(hal_ticks()), val);
|
||||
#endif
|
||||
|
||||
if(val == 0 || val == 1) { // drive pin
|
||||
pinMode(WIRING_PI_PIN_RST, OUTPUT);
|
||||
digitalWrite(WIRING_PI_PIN_RST, val==0 ? LOW : HIGH);
|
||||
} else { // keep pin floating
|
||||
pinMode(WIRING_PI_PIN_RST, INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
// perform 8-bit SPI transaction.
|
||||
// write given byte outval to radio, read byte from radio and return value.
|
||||
u1_t hal_spi (u1_t out) {
|
||||
static u1_t isAddress = 0x01;
|
||||
static u1_t address = 0x00;
|
||||
u1_t value = out;
|
||||
|
||||
if (isAddress) {
|
||||
address = out;
|
||||
}
|
||||
|
||||
u1_t rc = wiringPiSPIDataRW(0, &out, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "HAL: Cannot send data on SPI: %s\n", strerror(errno));
|
||||
hal_failed();
|
||||
}
|
||||
|
||||
/*
|
||||
if (!isAddress && (address != 0x2c)) {
|
||||
if (address & 0x80) {
|
||||
fprintf(stdout, "%09d HAL: SPI write to address 0x%02x value 0x%02x\n", osticks2ms(hal_ticks()), address & 0x7F, value);
|
||||
fprintf(stdout, " writeReg(0x%02x, 0x%02x);\n", address & 0x7F, value);
|
||||
} else {
|
||||
fprintf(stdout, "%09d HAL: SPI read from address 0x%02x value 0x%02x\n", osticks2ms(hal_ticks()), address, out);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
isAddress = !isAddress;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void hal_disableIRQs () {
|
||||
}
|
||||
|
||||
void hal_enableIRQs () {
|
||||
}
|
||||
|
||||
// store current timer value of the system.
|
||||
void hal_time_init() {
|
||||
int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &ts_start);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "HAL: Cannot initialize timer: %s\n", strerror(errno));
|
||||
hal_failed();
|
||||
}
|
||||
}
|
||||
|
||||
// return 32 bit system time in ticks.
|
||||
// OSTICKS_PER_SEC has to be defined, else the default 32768 is used.
|
||||
// OSTICKS_PER_SEC must be in range [10000:64516]. One tick must be 15.5us .. 100us long.
|
||||
u4_t hal_ticks () {
|
||||
|
||||
struct timespec ts;
|
||||
int rc = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "HAL: Cannot get current time: %s\n", strerror(errno));
|
||||
hal_failed();
|
||||
}
|
||||
|
||||
struct timespec ts_diff;
|
||||
timespec_diff(&ts_start, &ts, &ts_diff);
|
||||
|
||||
ostime_t ticks_sec = sec2osticks(ts_diff.tv_sec);
|
||||
ostime_t ticks_nsec = us2osticks(ts_diff.tv_nsec / 1000);
|
||||
|
||||
u4_t ticks = ticks_sec + ticks_nsec;
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
// busy wait until timestamp (in ticks) is reached
|
||||
void hal_waitUntil (u4_t target_ticks) {
|
||||
#ifdef DEBUG_HAL
|
||||
fprintf(stdout, "%09d HAL: Wait until %09d ms\n", osticks2ms(hal_ticks()), osticks2ms(target_ticks));
|
||||
#endif
|
||||
|
||||
// TODO: Deal with tick counter overflow
|
||||
|
||||
u4_t current_ticks = hal_ticks();
|
||||
s4_t diff_ticks = target_ticks - current_ticks;
|
||||
|
||||
if (diff_ticks > 0) {
|
||||
s4_t diff_us = osticks2us(diff_ticks);
|
||||
usleep(diff_us);
|
||||
}
|
||||
}
|
||||
|
||||
void timespec_diff(struct timespec *start, struct timespec *stop, struct timespec *result)
|
||||
{
|
||||
if ((stop->tv_nsec - start->tv_nsec) < 0) {
|
||||
result->tv_sec = stop->tv_sec - start->tv_sec - 1;
|
||||
result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000;
|
||||
} else {
|
||||
result->tv_sec = stop->tv_sec - start->tv_sec;
|
||||
result->tv_nsec = stop->tv_nsec - start->tv_nsec;
|
||||
}
|
||||
}
|
||||
|
||||
// Used for scheduled jobs:
|
||||
// If target time is reached, then 1 is returned and the scheduled job is executed.
|
||||
// If 0 is returned, then control goes back into the LMIC main loop.
|
||||
u1_t hal_checkTimer (u4_t target_ticks) {
|
||||
|
||||
u4_t current_ticks = hal_ticks();
|
||||
s4_t diff_ticks = target_ticks - current_ticks;
|
||||
s4_t diff_ms = osticks2ms(diff_ticks);
|
||||
|
||||
if (diff_ticks <= 0) { // Reached target ticks
|
||||
return 1; // Execute scheduled job
|
||||
} else if (diff_ms < 21) {
|
||||
// We have not reached the target ticks, but we also don't
|
||||
// want to execute the scheduled job now. By returning 0 the code
|
||||
// will continue looping in the LMIC main loop.
|
||||
sleep_interval_ms = 0;
|
||||
return 0;
|
||||
} else {
|
||||
sleep_interval_ms = diff_ms - 20;
|
||||
assert(sleep_interval_ms > 0);
|
||||
|
||||
// Use (diff_ms - 20) as timeout, to reduce the risk that the linux OS
|
||||
// causes the timeout longer as desired.
|
||||
// Let the code actively loop in the LMIC main loop until the final target time is reached.
|
||||
|
||||
return 0; // Will cause a "sleep" in the LMIC main loop
|
||||
}
|
||||
}
|
||||
|
||||
void hal_sleep () {
|
||||
if (sleep_interval_ms > 0) {
|
||||
int rc = gpioWaitForInterrupt(BCM_PIN_DIO, 3, sleep_interval_ms);
|
||||
if(rc < 0) {
|
||||
fprintf(stderr, "HAL: Cannot poll: %s\n", strerror(errno));
|
||||
hal_failed();
|
||||
}
|
||||
|
||||
sleep_interval_ms = 0;
|
||||
|
||||
if (rc > 0) {
|
||||
if (rc & 0x01) radio_irq_handler(0);
|
||||
if (rc & 0x02) radio_irq_handler(1);
|
||||
if (rc & 0x04) radio_irq_handler(2);
|
||||
}
|
||||
} else {
|
||||
// We need to check if one of the DIO ports where set to HIGH
|
||||
// to signal an interrupt condition.
|
||||
for (int i=0 ; i<3 ; i++) {
|
||||
if (HIGH == digitalRead(WIRING_PI_PIN_DIO[i])) {
|
||||
radio_irq_handler(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user