From 01d731f1d52388df716fd18fcf2c7e38d91e7603 Mon Sep 17 00:00:00 2001 From: Miguel Luis Date: Fri, 30 Jan 2015 09:55:00 +0100 Subject: [PATCH] Release v3.1 --- Keil/LoRaMote/Bootloader/BootLoader.uvproj | 2 +- Keil/LoRaMote/LoRaMac/classA/LoRaMac.uvproj | 4 +- Keil/LoRaMote/LoRaMac/classB/LoRaMac.uvproj | 4 +- Keil/SensorNode/Bootloader/BootLoader.uvproj | 2 +- Keil/SensorNode/LoRaMac/classA/LoRaMac.uvopt | 16 +- Keil/SensorNode/LoRaMac/classA/LoRaMac.uvproj | 8 +- Keil/SensorNode/LoRaMac/classB/LoRaMac.uvproj | 8 +- Ride/LoRaMote/Bootloader/Bootloader.rapp | 47 +- Ride/SensorNode/Bootloader/Bootloader.rapp | 47 +- coIDE/LoRaMote/Bootloader/Bootloader.coproj | 135 ++++ .../LoRaMac/classA/LoRaMacClassA.coproj | 384 ++++++++++ .../LoRaMac/classB/LoRaMacClassB.coproj | 384 ++++++++++ coIDE/LoRaMote/ping-pong/Ping-Pong.coproj | 377 ++++++++++ coIDE/SensorNode/Bootloader/Bootloader.coproj | 135 ++++ .../LoRaMac/classA/LoRaMacClassA.coproj | 700 ++++++++++++++++++ .../LoRaMac/classB/LoRaMacClassB.coproj | 700 ++++++++++++++++++ coIDE/SensorNode/ping-pong/Ping-Pong.coproj | 377 ++++++++++ readme.md | 61 +- src/apps/LoRaMac/tstIndoor/Bleeper-72/main.c | 5 +- src/apps/LoRaMac/tstIndoor/Bleeper-76/main.c | 5 +- src/apps/ping-pong/Bleeper-72/main.c | 25 +- src/apps/ping-pong/Bleeper-76/main.c | 25 +- src/apps/ping-pong/LoRaMote/main.c | 25 +- src/apps/ping-pong/SK-iM880A/main.c | 25 +- src/apps/ping-pong/SensorNode/main.c | 25 +- src/apps/rx-sensi/Bleeper-72/main.c | 10 +- src/apps/rx-sensi/Bleeper-76/main.c | 10 +- src/apps/rx-sensi/LoRaMote/main.c | 10 +- src/apps/rx-sensi/SK-iM880A/main.c | 10 +- src/apps/rx-sensi/SensorNode/main.c | 10 +- src/apps/tx-cw/Bleeper-72/main.c | 2 +- src/apps/tx-cw/Bleeper-76/main.c | 2 +- src/apps/tx-cw/LoRaMote/main.c | 2 +- src/apps/tx-cw/SK-iM880A/main.c | 2 +- src/apps/tx-cw/SensorNode/main.c | 2 +- src/boards/Bleeper-72/board.c | 24 +- .../cmsis/arm-gcc/stm32l1xx_hd_flash.ld | 284 +++---- src/boards/Bleeper-72/gpio-board.c | 49 +- src/boards/Bleeper-72/i2c-board.c | 158 +++- src/boards/Bleeper-72/i2c-board.h | 25 + src/boards/Bleeper-72/rtc-board.c | 136 ++-- src/boards/Bleeper-72/sx1272-board.c | 1 + src/boards/Bleeper-72/timer-board.c | 105 ++- src/boards/Bleeper-76/board.c | 25 +- .../cmsis/arm-gcc/stm32l1xx_hd_flash.ld | 284 +++---- src/boards/Bleeper-76/gpio-board.c | 49 +- src/boards/Bleeper-76/i2c-board.c | 158 +++- src/boards/Bleeper-76/i2c-board.h | 25 + src/boards/Bleeper-76/rtc-board.c | 136 ++-- src/boards/Bleeper-76/sx1276-board.c | 1 + src/boards/Bleeper-76/timer-board.c | 105 ++- src/boards/LoRaMote/board.c | 64 +- .../cmsis/arm-gcc/stm32l1xx_md_flash.ld | 284 +++---- .../arm-gcc/stm32l1xx_md_flash_bootloader.ld | 284 +++---- .../arm-gcc/stm32l1xx_md_flash_offset.ld | 284 +++---- src/boards/LoRaMote/gpio-board.c | 49 +- src/boards/LoRaMote/i2c-board.c | 158 +++- src/boards/LoRaMote/i2c-board.h | 25 + src/boards/LoRaMote/rtc-board.c | 136 ++-- src/boards/LoRaMote/sx1272-board.c | 1 + src/boards/LoRaMote/timer-board.c | 105 ++- src/boards/LoRaMote/uart-usb-board.c | 98 +-- src/boards/LoRaMote/uart-usb-board.h | 10 + src/boards/LoRaMote/usb-cdc-board.c | 4 +- src/boards/LoRaMote/usb/cdc/inc/usb_prop.h | 1 + src/boards/LoRaMote/usb/cdc/src/usb_prop.c | 23 + src/boards/LoRaMote/usb/cdc/src/usb_pwr.c | 95 +-- src/boards/SK-iM880A/board.c | 54 +- .../cmsis/arm-gcc/stm32l1xx_md_flash.ld | 284 +++---- src/boards/SK-iM880A/gpio-board.c | 49 +- src/boards/SK-iM880A/i2c-board.c | 158 +++- src/boards/SK-iM880A/i2c-board.h | 25 + src/boards/SK-iM880A/rtc-board.c | 136 ++-- src/boards/SK-iM880A/sx1272-board.c | 1 + src/boards/SK-iM880A/timer-board.c | 105 ++- src/boards/SensorNode/board.c | 65 +- .../cmsis/arm-gcc/stm32l1xx_md_flash.ld | 284 +++---- .../arm-gcc/stm32l1xx_md_flash_bootloader.ld | 284 +++---- .../arm-gcc/stm32l1xx_md_flash_offset.ld | 284 +++---- src/boards/SensorNode/gpio-board.c | 49 +- src/boards/SensorNode/i2c-board.c | 158 +++- src/boards/SensorNode/i2c-board.h | 25 + src/boards/SensorNode/rtc-board.c | 136 ++-- src/boards/SensorNode/sx1276-board.c | 1 + src/boards/SensorNode/timer-board.c | 105 ++- src/boards/SensorNode/uart-usb-board.c | 98 +-- src/boards/SensorNode/uart-usb-board.h | 10 + src/boards/SensorNode/usb-cdc-board.c | 4 +- src/boards/SensorNode/usb/cdc/inc/usb_prop.h | 1 + src/boards/SensorNode/usb/cdc/src/usb_prop.c | 23 + src/boards/SensorNode/usb/cdc/src/usb_pwr.c | 95 +-- src/boards/mcu/stm32/sysIrqHandlers.c | 70 +- src/mac/LoRaMac.c | 158 ++-- src/mac/LoRaMac.h | 107 ++- src/peripherals/sx9500.h | 4 +- src/radio/radio.h | 45 +- src/radio/sx1272/sx1272.c | 246 ++++-- src/radio/sx1272/sx1272.h | 38 +- src/radio/sx1272/sx1272Regs-LoRa.h | 10 +- src/radio/sx1276/sx1276.c | 247 ++++-- src/radio/sx1276/sx1276.h | 36 +- src/radio/sx1276/sx1276Regs-LoRa.h | 11 +- src/system/delay.c | 13 +- src/system/eeprom.c | 218 ++++++ src/system/eeprom.h | 25 + src/system/i2c.c | 20 +- src/system/i2c.h | 32 +- src/system/timer.c | 75 +- src/system/timer.h | 14 + src/system/uart.c | 35 +- 110 files changed, 7810 insertions(+), 2800 deletions(-) create mode 100644 coIDE/LoRaMote/Bootloader/Bootloader.coproj create mode 100644 coIDE/LoRaMote/LoRaMac/classA/LoRaMacClassA.coproj create mode 100644 coIDE/LoRaMote/LoRaMac/classB/LoRaMacClassB.coproj create mode 100644 coIDE/LoRaMote/ping-pong/Ping-Pong.coproj create mode 100644 coIDE/SensorNode/Bootloader/Bootloader.coproj create mode 100644 coIDE/SensorNode/LoRaMac/classA/LoRaMacClassA.coproj create mode 100644 coIDE/SensorNode/LoRaMac/classB/LoRaMacClassB.coproj create mode 100644 coIDE/SensorNode/ping-pong/Ping-Pong.coproj create mode 100644 src/system/eeprom.c create mode 100644 src/system/eeprom.h diff --git a/Keil/LoRaMote/Bootloader/BootLoader.uvproj b/Keil/LoRaMote/Bootloader/BootLoader.uvproj index 5852e077d..f0d798b69 100644 --- a/Keil/LoRaMote/Bootloader/BootLoader.uvproj +++ b/Keil/LoRaMote/Bootloader/BootLoader.uvproj @@ -362,7 +362,7 @@ 0 - USE_DEBUGGER + USE_DEBUGGER USE_NO_TIMER ..\..\..\src;..\..\..\src\boards\LoRaMote;..\..\..\src\boards\LoRaMote\cmsis;..\..\..\src\boards\LoRaMote\usb\dfu\inc;..\..\..\src\boards\mcu\stm32;..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\src\boards\mcu\stm32\STM32_USB-FS-Device_Driver\inc;..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\src\peripherals;..\..\..\src\radio;..\..\..\src\system diff --git a/Keil/LoRaMote/LoRaMac/classA/LoRaMac.uvproj b/Keil/LoRaMote/LoRaMac/classA/LoRaMac.uvproj index 66be622a4..ba50a35c3 100644 --- a/Keil/LoRaMote/LoRaMac/classA/LoRaMac.uvproj +++ b/Keil/LoRaMote/LoRaMac/classA/LoRaMac.uvproj @@ -1052,7 +1052,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\LoRaMote;..\..\..\..\src\boards\LoRaMote\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -2432,7 +2432,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\LoRaMote;..\..\..\..\src\boards\LoRaMote\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto diff --git a/Keil/LoRaMote/LoRaMac/classB/LoRaMac.uvproj b/Keil/LoRaMote/LoRaMac/classB/LoRaMac.uvproj index 28b1bc142..3d601f9d8 100644 --- a/Keil/LoRaMote/LoRaMac/classB/LoRaMac.uvproj +++ b/Keil/LoRaMote/LoRaMac/classB/LoRaMac.uvproj @@ -1052,7 +1052,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\LoRaMote;..\..\..\..\src\boards\LoRaMote\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -2432,7 +2432,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\LoRaMote;..\..\..\..\src\boards\LoRaMote\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto diff --git a/Keil/SensorNode/Bootloader/BootLoader.uvproj b/Keil/SensorNode/Bootloader/BootLoader.uvproj index d01c568b3..4949e871a 100644 --- a/Keil/SensorNode/Bootloader/BootLoader.uvproj +++ b/Keil/SensorNode/Bootloader/BootLoader.uvproj @@ -362,7 +362,7 @@ 0 - USE_DEBUGGER + USE_DEBUGGER USE_NO_TIMER ..\..\..\src;..\..\..\src\boards\SensorNode;..\..\..\src\boards\SensorNode\cmsis;..\..\..\src\boards\SensorNode\usb\dfu\inc;..\..\..\src\boards\mcu\stm32;..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\src\boards\mcu\stm32\STM32_USB-FS-Device_Driver\inc;..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\src\peripherals;..\..\..\src\radio;..\..\..\src\system diff --git a/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvopt b/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvopt index 9ef17bfa9..44f92b2a6 100644 --- a/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvopt +++ b/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvopt @@ -93,7 +93,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -252,7 +252,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -411,7 +411,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -570,7 +570,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -729,7 +729,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -888,7 +888,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -1047,7 +1047,7 @@ 1 0 0 - 1 + 0 1 1 1 @@ -1206,7 +1206,7 @@ 1 0 0 - 1 + 0 1 1 1 diff --git a/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvproj b/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvproj index dc065bb84..304bda9b0 100644 --- a/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvproj +++ b/Keil/SensorNode/LoRaMac/classA/LoRaMac.uvproj @@ -1052,7 +1052,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_433 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_433 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -2432,7 +2432,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_470 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_470 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -3812,7 +3812,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -5192,7 +5192,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto diff --git a/Keil/SensorNode/LoRaMac/classB/LoRaMac.uvproj b/Keil/SensorNode/LoRaMac/classB/LoRaMac.uvproj index 09d8d6586..a1321cc5a 100644 --- a/Keil/SensorNode/LoRaMac/classB/LoRaMac.uvproj +++ b/Keil/SensorNode/LoRaMac/classB/LoRaMac.uvproj @@ -1052,7 +1052,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_433 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_433 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -2432,7 +2432,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_470 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_470 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -3812,7 +3812,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_868 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto @@ -5192,7 +5192,7 @@ 0 - USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 USE_BOOTLOADER LORAMAC_R3 + USE_DEBUGGER LOW_POWER_MODE_ENABLE USE_BAND_915 LORAMAC_R3 USE_BOOTLOADER ..\..\..\..\src;..\..\..\..\src\boards\SensorNode;..\..\..\..\src\boards\SensorNode\cmsis;..\..\..\..\src\boards\mcu\stm32;..\..\..\..\src\boards\mcu\stm32\cmsis;..\..\..\..\src\boards\mcu\stm32\STM32L1xx_StdPeriph_Driver\inc;..\..\..\..\src\mac;..\..\..\..\src\peripherals;..\..\..\..\src\radio;..\..\..\..\src\system;..\..\..\..\src\system\crypto diff --git a/Ride/LoRaMote/Bootloader/Bootloader.rapp b/Ride/LoRaMote/Bootloader/Bootloader.rapp index e8cefa1dd..7e57c99c4 100644 --- a/Ride/LoRaMote/Bootloader/Bootloader.rapp +++ b/Ride/LoRaMote/Bootloader/Bootloader.rapp @@ -9,7 +9,6 @@ - @@ -18,7 +17,6 @@ - @@ -27,7 +25,6 @@ - @@ -42,15 +39,10 @@
-
-
- - -
@@ -61,152 +53,115 @@ -
- - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - +
-
-
-
-
-
-
diff --git a/Ride/SensorNode/Bootloader/Bootloader.rapp b/Ride/SensorNode/Bootloader/Bootloader.rapp index 2456de00a..b2900be10 100644 --- a/Ride/SensorNode/Bootloader/Bootloader.rapp +++ b/Ride/SensorNode/Bootloader/Bootloader.rapp @@ -9,7 +9,6 @@ - @@ -18,7 +17,6 @@ - @@ -27,7 +25,6 @@ - @@ -42,15 +39,10 @@
-
-
- - -
@@ -61,152 +53,115 @@ -
- - - - - - -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- - +
-
-
-
-
-
-
diff --git a/coIDE/LoRaMote/Bootloader/Bootloader.coproj b/coIDE/LoRaMote/Bootloader/Bootloader.coproj new file mode 100644 index 000000000..c1a9246da --- /dev/null +++ b/coIDE/LoRaMote/Bootloader/Bootloader.coproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/LoRaMote/LoRaMac/classA/LoRaMacClassA.coproj b/coIDE/LoRaMote/LoRaMac/classA/LoRaMacClassA.coproj new file mode 100644 index 000000000..af5a66ac2 --- /dev/null +++ b/coIDE/LoRaMote/LoRaMac/classA/LoRaMacClassA.coproj @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/LoRaMote/LoRaMac/classB/LoRaMacClassB.coproj b/coIDE/LoRaMote/LoRaMac/classB/LoRaMacClassB.coproj new file mode 100644 index 000000000..579d4690a --- /dev/null +++ b/coIDE/LoRaMote/LoRaMac/classB/LoRaMacClassB.coproj @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/LoRaMote/ping-pong/Ping-Pong.coproj b/coIDE/LoRaMote/ping-pong/Ping-Pong.coproj new file mode 100644 index 000000000..7833e73db --- /dev/null +++ b/coIDE/LoRaMote/ping-pong/Ping-Pong.coproj @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/SensorNode/Bootloader/Bootloader.coproj b/coIDE/SensorNode/Bootloader/Bootloader.coproj new file mode 100644 index 000000000..4f4656a05 --- /dev/null +++ b/coIDE/SensorNode/Bootloader/Bootloader.coproj @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/SensorNode/LoRaMac/classA/LoRaMacClassA.coproj b/coIDE/SensorNode/LoRaMac/classA/LoRaMacClassA.coproj new file mode 100644 index 000000000..7885d4697 --- /dev/null +++ b/coIDE/SensorNode/LoRaMac/classA/LoRaMacClassA.coproj @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/SensorNode/LoRaMac/classB/LoRaMacClassB.coproj b/coIDE/SensorNode/LoRaMac/classB/LoRaMacClassB.coproj new file mode 100644 index 000000000..1e6369cdc --- /dev/null +++ b/coIDE/SensorNode/LoRaMac/classB/LoRaMacClassB.coproj @@ -0,0 +1,700 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/coIDE/SensorNode/ping-pong/Ping-Pong.coproj b/coIDE/SensorNode/ping-pong/Ping-Pong.coproj new file mode 100644 index 000000000..a859d4b99 --- /dev/null +++ b/coIDE/SensorNode/ping-pong/Ping-Pong.coproj @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/readme.md b/readme.md index c3e4c925c..22e5b7575 100644 --- a/readme.md +++ b/readme.md @@ -13,11 +13,20 @@ SX1272/76 radio drivers plus Ping-Pong firmware and LoRa MAC node firmware imple The aim of this project is to show an example of the LoRaMac endpoint firmware implementation. -**REMARK 1:** This is a Class A endpoint. +**REMARK 1:** Next version of the project will include big changes. -**REMARK 2:** Implements version R3.0 of LoRaMac specification. +*This is the last version based on the Semtech LoRaMac implementation. The next +version will be based on the [IBM 'LoRaWAN in C'](http://www.research.ibm.com/labs/zurich/ics/lrsc/lmic.html) +implementation.* -*LoRaMac R3.0 has been made incompatible with previous versions of the specification.* +*The IBM 'LoRaWAN in C' implementation adds the support of the Class A endpoint +fully implemented and Class B endpoints.* + +*The biggest change resides on the MAC layer API which is completely different.* + +**REMARK 2:** This is a Class A endpoint. + +**REMARK 3:** Implements version R3.0 of LoRaMac specification. *By default the LORAMAC_R3 compiler option is enabled. Disabling this option will enable LoRaMac specification R2.2.1* @@ -122,7 +131,7 @@ platforms are: 5. Usage --------- -Projects for Ride7 and Keil Integrated Development Environments are available. +Projects for CooCox-CoIDE (partial), Ride7 and Keil Integrated Development Environments are available. One project is available per application and for each hardware platform in each development environment. Different targets/configurations have been created in @@ -131,6 +140,50 @@ not of a bootloader and the radio frequency band to be used. 6. Changelog ------------- +2015-01-30, v3.1 +* General + 1. Started to add support for CooCox CoIDE Integrated Development Environment. + Currently only LoRaMote and SensorNode platform projects are available. + 2. Updated GCC compiler linker scripts. + 3. Added the support of different tool chains for the HardFault_Handler function. + + 4. Corrected Radio drivers I&Q signals inversion to be possible in Rx and in Tx. + Added some missing radio state machine initialization. + 5. Changed the RSSI values type from int8_t to int16_t. We can have RSSI values below -128 dBm. + 6. Corrected SNR computation on RxDone interrupt. + 7. Updated radio API to support FHSS and CAD handling. + 8. Corrected in SetRxConfig function the FSK modem preamble register name. + 9. Added an invalid bandwidth to the Bandwidths table in order to avoid an error + when selecting 250 kHz bandwidth when using FSK modem. + + 10. Corrected RTC alarm setup which could be set to an invalid date. + 11. Added another timer in order increment the tick counter without blocking the normal timer count. + 12. Added the possibility to switch between low power timers and normal timers on the fly. + 13. I2C driver corrected the 2 bytes internal address management. + Corrected buffer read function when more that 1 byte was to be read. + Added a function to wait for the I2C bus to become IDLE. + 14. Added an I2C EEPROM driver. + 15. Corrected and improved USB Virtual COM Port management files. + Corrected the USB CDC and USB UART drivers. + 16. Added the possibility to analyze a hard fault interrupt. + +* LoRaMac + 1. Corrected RxWindow2 Datarate management. + 2. SrvAckRequested variable was never reset. + 3. Corrected tstIndoor applications for LoRaMac R3.0 support. + 4. LoRaMac added the possibility to configure almost all the MAC parameters. + 5. Corrected the LoRaMacSetNextChannel function. + 6. Corrected the port 0 MAC command decoding. + 7. Changed all structures declarations to be packed. + 8. Corrected the Acknowledgement retries management when only 1 trial is needed. + Before the device was issuing at least 2 trials. + 9. Corrected server mac new channel req answer. + 10. Added the functions to read the Up and Down Link sequence counters. + 11. Corrected SRV_MAC_RX2_SETUP_REQ frequency handling. Added a 100 multiplication. + 12. Corrected SRV_MAC_NEW_CHANNEL_REQ. Removed the DutyCycle parameter decoding. + 13. Automatically activate the channel once it is created. + 14. Corrected NbRepTimeoutTimer initial value. RxWindow2Delay already contains RxWindow1Delay in it. + 2014-07-18, v3.0 * General 1. Added to Radio API the possibility to select the modem. diff --git a/src/apps/LoRaMac/tstIndoor/Bleeper-72/main.c b/src/apps/LoRaMac/tstIndoor/Bleeper-72/main.c index 9567a0e1e..15a1eaeec 100644 --- a/src/apps/LoRaMac/tstIndoor/Bleeper-72/main.c +++ b/src/apps/LoRaMac/tstIndoor/Bleeper-72/main.c @@ -242,8 +242,11 @@ int main( void ) // Initialize MAC frame macHdr.Value = 0; +#if defined( LORAMAC_R3 ) + macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP; +#else macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED; - +#endif fCtrl.Value = 0; fCtrl.Bits.OptionsLength = 0; fCtrl.Bits.FPending = 0; diff --git a/src/apps/LoRaMac/tstIndoor/Bleeper-76/main.c b/src/apps/LoRaMac/tstIndoor/Bleeper-76/main.c index d240d3d56..1e9357383 100644 --- a/src/apps/LoRaMac/tstIndoor/Bleeper-76/main.c +++ b/src/apps/LoRaMac/tstIndoor/Bleeper-76/main.c @@ -252,8 +252,11 @@ int main( void ) // Initialize MAC frame macHdr.Value = 0; +#if defined( LORAMAC_R3 ) + macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED_UP; +#else macHdr.Bits.MType = FRAME_TYPE_DATA_UNCONFIRMED; - +#endif fCtrl.Value = 0; fCtrl.Bits.OptionsLength = 0; fCtrl.Bits.FPending = 0; diff --git a/src/apps/ping-pong/Bleeper-72/main.c b/src/apps/ping-pong/Bleeper-72/main.c index 864a8745a..bfee8fa76 100644 --- a/src/apps/ping-pong/Bleeper-72/main.c +++ b/src/apps/ping-pong/Bleeper-72/main.c @@ -85,7 +85,7 @@ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * \brief Function executed on Radio Tx Timeout event @@ -130,24 +130,24 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, FSK_DATARATE, 0, FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, - true, 0, 3000000 ); + true, 0, 0, 0, 3000000 ); Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0,false, true ); #else #error "Please define a frequency band in the compiler options." @@ -187,6 +187,11 @@ int main( void ) isMaster = false; GpioWrite( &Led2, 1 ); // Set LED off Radio.Rx( RX_TIMEOUT_VALUE ); + } + else // valid reception but neither a PING or a PONG message + { // Set device as master ans start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); } } } @@ -212,6 +217,11 @@ int main( void ) DelayMs( 1 ); Radio.Send( Buffer, BufferSize ); } + else // valid reception but not a PING as expected + { // Set device as master and start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } } } State = LOWPOWER; @@ -262,10 +272,11 @@ int main( void ) void OnTxDone( void ) { + Radio.Sleep( ); State = TX; } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { Radio.Sleep( ); BufferSize = size; diff --git a/src/apps/ping-pong/Bleeper-76/main.c b/src/apps/ping-pong/Bleeper-76/main.c index 058a3f375..6ac57546a 100644 --- a/src/apps/ping-pong/Bleeper-76/main.c +++ b/src/apps/ping-pong/Bleeper-76/main.c @@ -104,7 +104,7 @@ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * \brief Function executed on Radio Tx Timeout event @@ -149,24 +149,24 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, FSK_DATARATE, 0, FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, - true, 0, 3000000 ); + true, 0, 0, 0, 3000000 ); Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0,false, true ); #else #error "Please define a frequency band in the compiler options." @@ -206,6 +206,11 @@ int main( void ) isMaster = false; GpioWrite( &Led2, 1 ); // Set LED off Radio.Rx( RX_TIMEOUT_VALUE ); + } + else // valid reception but neither a PING or a PONG message + { // Set device as master ans start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); } } } @@ -231,6 +236,11 @@ int main( void ) DelayMs( 1 ); Radio.Send( Buffer, BufferSize ); } + else // valid reception but not a PING as expected + { // Set device as master and start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } } } State = LOWPOWER; @@ -281,10 +291,11 @@ int main( void ) void OnTxDone( void ) { + Radio.Sleep( ); State = TX; } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { Radio.Sleep( ); BufferSize = size; diff --git a/src/apps/ping-pong/LoRaMote/main.c b/src/apps/ping-pong/LoRaMote/main.c index 272fe124d..a5f546b0b 100644 --- a/src/apps/ping-pong/LoRaMote/main.c +++ b/src/apps/ping-pong/LoRaMote/main.c @@ -96,7 +96,7 @@ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * \brief Function executed on Radio Tx Timeout event @@ -141,24 +141,24 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, FSK_DATARATE, 0, FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, - true, 0, 3000000 ); + true, 0, 0, 0, 3000000 ); Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0,false, true ); #else #error "Please define a frequency band in the compiler options." @@ -198,6 +198,11 @@ int main( void ) isMaster = false; GpioWrite( &Led2, 1 ); // Set LED off Radio.Rx( RX_TIMEOUT_VALUE ); + } + else // valid reception but neither a PING or a PONG message + { // Set device as master ans start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); } } } @@ -223,6 +228,11 @@ int main( void ) DelayMs( 1 ); Radio.Send( Buffer, BufferSize ); } + else // valid reception but not a PING as expected + { // Set device as master and start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } } } State = LOWPOWER; @@ -273,10 +283,11 @@ int main( void ) void OnTxDone( void ) { + Radio.Sleep( ); State = TX; } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { Radio.Sleep( ); BufferSize = size; diff --git a/src/apps/ping-pong/SK-iM880A/main.c b/src/apps/ping-pong/SK-iM880A/main.c index 8bae0e051..17876f597 100644 --- a/src/apps/ping-pong/SK-iM880A/main.c +++ b/src/apps/ping-pong/SK-iM880A/main.c @@ -85,7 +85,7 @@ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * \brief Function executed on Radio Tx Timeout event @@ -130,24 +130,24 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, FSK_DATARATE, 0, FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, - true, 0, 3000000 ); + true, 0, 0, 0, 3000000 ); Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0,false, true ); #else #error "Please define a frequency band in the compiler options." @@ -187,6 +187,11 @@ int main( void ) isMaster = false; GpioWrite( &Led3, 1 ); // Set LED off Radio.Rx( RX_TIMEOUT_VALUE ); + } + else // valid reception but neither a PING or a PONG message + { // Set device as master ans start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); } } } @@ -212,6 +217,11 @@ int main( void ) DelayMs( 1 ); Radio.Send( Buffer, BufferSize ); } + else // valid reception but not a PING as expected + { // Set device as master and start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } } } State = LOWPOWER; @@ -262,10 +272,11 @@ int main( void ) void OnTxDone( void ) { + Radio.Sleep( ); State = TX; } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { Radio.Sleep( ); BufferSize = size; diff --git a/src/apps/ping-pong/SensorNode/main.c b/src/apps/ping-pong/SensorNode/main.c index 058a3f375..6ac57546a 100644 --- a/src/apps/ping-pong/SensorNode/main.c +++ b/src/apps/ping-pong/SensorNode/main.c @@ -104,7 +104,7 @@ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * \brief Function executed on Radio Tx Timeout event @@ -149,24 +149,24 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, FSK_DATARATE, 0, FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, - true, 0, 3000000 ); + true, 0, 0, 0, 3000000 ); Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0,false, true ); #else #error "Please define a frequency band in the compiler options." @@ -206,6 +206,11 @@ int main( void ) isMaster = false; GpioWrite( &Led2, 1 ); // Set LED off Radio.Rx( RX_TIMEOUT_VALUE ); + } + else // valid reception but neither a PING or a PONG message + { // Set device as master ans start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); } } } @@ -231,6 +236,11 @@ int main( void ) DelayMs( 1 ); Radio.Send( Buffer, BufferSize ); } + else // valid reception but not a PING as expected + { // Set device as master and start again + isMaster = true; + Radio.Rx( RX_TIMEOUT_VALUE ); + } } } State = LOWPOWER; @@ -281,10 +291,11 @@ int main( void ) void OnTxDone( void ) { + Radio.Sleep( ); State = TX; } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { Radio.Sleep( ); BufferSize = size; diff --git a/src/apps/rx-sensi/Bleeper-72/main.c b/src/apps/rx-sensi/Bleeper-72/main.c index 2ad5c93a4..610ef90a8 100644 --- a/src/apps/rx-sensi/Bleeper-72/main.c +++ b/src/apps/rx-sensi/Bleeper-72/main.c @@ -58,7 +58,7 @@ static RadioEvents_t RadioEvents; /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * Main application entry point. @@ -81,14 +81,14 @@ int main( void ) Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0, false, true ); #else #error "Please define a frequency band in the compiler options." @@ -102,7 +102,7 @@ int main( void ) } } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { static uint8_t ledState = 1; // Toggle LED 1 diff --git a/src/apps/rx-sensi/Bleeper-76/main.c b/src/apps/rx-sensi/Bleeper-76/main.c index 70769e599..108be1e74 100644 --- a/src/apps/rx-sensi/Bleeper-76/main.c +++ b/src/apps/rx-sensi/Bleeper-76/main.c @@ -76,7 +76,7 @@ static RadioEvents_t RadioEvents; /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * Main application entry point. @@ -99,14 +99,14 @@ int main( void ) Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0, false, true ); #else #error "Please define a frequency band in the compiler options." @@ -120,7 +120,7 @@ int main( void ) } } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { static uint8_t ledState = 1; // Toggle LED 1 diff --git a/src/apps/rx-sensi/LoRaMote/main.c b/src/apps/rx-sensi/LoRaMote/main.c index 5f0116e53..32fb28f78 100644 --- a/src/apps/rx-sensi/LoRaMote/main.c +++ b/src/apps/rx-sensi/LoRaMote/main.c @@ -68,7 +68,7 @@ static RadioEvents_t RadioEvents; /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * Main application entry point. @@ -91,14 +91,14 @@ int main( void ) Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0, false, true ); #else #error "Please define a frequency band in the compiler options." @@ -112,7 +112,7 @@ int main( void ) } } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { static uint8_t ledState = 1; // Toggle LED 1 diff --git a/src/apps/rx-sensi/SK-iM880A/main.c b/src/apps/rx-sensi/SK-iM880A/main.c index 50fa99caf..1a1139a56 100644 --- a/src/apps/rx-sensi/SK-iM880A/main.c +++ b/src/apps/rx-sensi/SK-iM880A/main.c @@ -58,7 +58,7 @@ static RadioEvents_t RadioEvents; /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * Main application entry point. @@ -81,14 +81,14 @@ int main( void ) Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0, false, true ); #else #error "Please define a frequency band in the compiler options." @@ -102,7 +102,7 @@ int main( void ) } } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { static uint8_t ledState = 1; // Toggle LED 4 diff --git a/src/apps/rx-sensi/SensorNode/main.c b/src/apps/rx-sensi/SensorNode/main.c index 70769e599..108be1e74 100644 --- a/src/apps/rx-sensi/SensorNode/main.c +++ b/src/apps/rx-sensi/SensorNode/main.c @@ -76,7 +76,7 @@ static RadioEvents_t RadioEvents; /*! * \brief Function to be executed on Radio Rx Done event */ -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * Main application entry point. @@ -99,14 +99,14 @@ int main( void ) Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, true ); + 0, true, 0, 0, LORA_IQ_INVERSION_ON, true ); #elif defined( USE_MODEM_FSK ) Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, true, - false, true ); + 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, true, + 0, 0, false, true ); #else #error "Please define a frequency band in the compiler options." @@ -120,7 +120,7 @@ int main( void ) } } -void OnRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { static uint8_t ledState = 1; // Toggle LED 1 diff --git a/src/apps/tx-cw/Bleeper-72/main.c b/src/apps/tx-cw/Bleeper-72/main.c index 6947bd8f8..4eaecaabc 100644 --- a/src/apps/tx-cw/Bleeper-72/main.c +++ b/src/apps/tx-cw/Bleeper-72/main.c @@ -82,7 +82,7 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); /**********************************************/ /* WARNING */ diff --git a/src/apps/tx-cw/Bleeper-76/main.c b/src/apps/tx-cw/Bleeper-76/main.c index 0e3c8a548..d8cf24b6e 100644 --- a/src/apps/tx-cw/Bleeper-76/main.c +++ b/src/apps/tx-cw/Bleeper-76/main.c @@ -130,7 +130,7 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); TimerInit( &Led1Timer, OnLed1TimerEvent ); TimerSetValue( &Led1Timer, 90000 ); diff --git a/src/apps/tx-cw/LoRaMote/main.c b/src/apps/tx-cw/LoRaMote/main.c index dc16df275..7a7273d6f 100644 --- a/src/apps/tx-cw/LoRaMote/main.c +++ b/src/apps/tx-cw/LoRaMote/main.c @@ -95,7 +95,7 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); /**********************************************/ /* WARNING */ diff --git a/src/apps/tx-cw/SK-iM880A/main.c b/src/apps/tx-cw/SK-iM880A/main.c index dbb57462b..b8b00c088 100644 --- a/src/apps/tx-cw/SK-iM880A/main.c +++ b/src/apps/tx-cw/SK-iM880A/main.c @@ -82,7 +82,7 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); /**********************************************/ /* WARNING */ diff --git a/src/apps/tx-cw/SensorNode/main.c b/src/apps/tx-cw/SensorNode/main.c index ce1b8591c..cafd4d8bd 100644 --- a/src/apps/tx-cw/SensorNode/main.c +++ b/src/apps/tx-cw/SensorNode/main.c @@ -130,7 +130,7 @@ int main( void ) Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, LORA_CODINGRATE, LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - true, LORA_IQ_INVERSION_ON, 3000000 ); + true, 0, 0, LORA_IQ_INVERSION_ON, 3000000 ); TimerInit( &Led1Timer, OnLed1TimerEvent ); TimerSetValue( &Led1Timer, 90000 ); diff --git a/src/boards/Bleeper-72/board.c b/src/boards/Bleeper-72/board.c index 2473c8913..545325640 100644 --- a/src/boards/Bleeper-72/board.c +++ b/src/boards/Bleeper-72/board.c @@ -89,13 +89,22 @@ void BoardInitMcu( void ) GpioInit( &DbgPin4, J5_4, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif BoardInitPeriph( ); - BoardUnusedIoInit( ); -#ifdef LOW_POWER_MODE_ENABLE - RtcInit( ); +#if( LOW_POWER_MODE_ENABLE ) + TimerSetLowPowerEnable( true ); #else - TimerHwInit( ); + TimerSetLowPowerEnable( false ); #endif + BoardUnusedIoInit( ); + + if( TimerGetLowPowerEnable( ) == true ) + { + RtcInit( ); + } + else + { + TimerHwInit( ); + } McuInitialized = true; } } @@ -127,12 +136,13 @@ void BoardDeInitMcu( void ) GpioInit( &DbgPin3, J5_3, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &DbgPin4, J5_4, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif - + GpioInit( &ioPin, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); GpioInit( &ioPin, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &ioPin, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); GpioInit( &ioPin, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); - + McuInitialized = false; } @@ -236,8 +246,10 @@ static void BoardUnusedIoInit( void ) GpioInit( &ioPin, SD_CMD, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); /* USB */ +#if !defined( USE_USB_CDC ) GpioInit( &ioPin, USB_DM, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); +#endif /* BOOT1 pin */ GpioInit( &ioPin, BOOT_1, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); diff --git a/src/boards/Bleeper-72/cmsis/arm-gcc/stm32l1xx_hd_flash.ld b/src/boards/Bleeper-72/cmsis/arm-gcc/stm32l1xx_hd_flash.ld index 228fc0598..c9382e2b5 100644 --- a/src/boards/Bleeper-72/cmsis/arm-gcc/stm32l1xx_hd_flash.ld +++ b/src/boards/Bleeper-72/cmsis/arm-gcc/stm32l1xx_hd_flash.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_hd Device with -** 384KByte FLASH, 48KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 48K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x2000C000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 48K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/Bleeper-72/gpio-board.c b/src/boards/Bleeper-72/gpio-board.c index 72802a517..f4739e11f 100644 --- a/src/boards/Bleeper-72/gpio-board.c +++ b/src/boards/Bleeper-72/gpio-board.c @@ -200,9 +200,10 @@ uint32_t GpioMcuRead( Gpio_t *obj ) void EXTI0_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line0 ) != RESET ) { if( GpioIrq[0] != NULL ) @@ -215,9 +216,10 @@ void EXTI0_IRQHandler( void ) void EXTI1_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line1 ) != RESET ) { if( GpioIrq[1] != NULL ) @@ -230,9 +232,10 @@ void EXTI1_IRQHandler( void ) void EXTI2_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line2 ) != RESET ) { if( GpioIrq[2] != NULL ) @@ -245,9 +248,10 @@ void EXTI2_IRQHandler( void ) void EXTI3_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line3 ) != RESET ) { if( GpioIrq[3] != NULL ) @@ -260,9 +264,10 @@ void EXTI3_IRQHandler( void ) void EXTI4_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line4 ) != RESET ) { if( GpioIrq[4] != NULL ) @@ -275,9 +280,10 @@ void EXTI4_IRQHandler( void ) void EXTI9_5_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line5 ) != RESET ) { if( GpioIrq[5] != NULL ) @@ -326,9 +332,10 @@ void EXTI9_5_IRQHandler( void ) void EXTI15_10_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line10 ) != RESET ) { if( GpioIrq[10] != NULL ) diff --git a/src/boards/Bleeper-72/i2c-board.c b/src/boards/Bleeper-72/i2c-board.c index 678db7dec..304259386 100644 --- a/src/boards/Bleeper-72/i2c-board.c +++ b/src/boards/Bleeper-72/i2c-board.c @@ -20,6 +20,8 @@ Maintainer: Miguel Luis and Gregory Cristian */ #define TIMEOUT_MAX 0x8000 +I2cAddrSize I2cInternalAddrSize = I2C_ADDR_SIZE_8; + /*! * MCU I2C peripherals enumeration */ @@ -110,6 +112,11 @@ void I2cMcuDeInit( I2c_t *obj ) GpioInit( &obj->Sda, obj->Sda.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ) +{ + I2cInternalAddrSize = addrSize; +} + uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { uint32_t timeOut; @@ -161,7 +168,7 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -291,7 +298,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -377,7 +384,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_AcknowledgeConfig( obj->I2c, DISABLE ); /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ - (void)obj->I2c->SR2; + ( void )obj->I2c->SR2; /* Send STOP Condition */ I2C_GenerateSTOP( obj->I2c, ENABLE ); @@ -403,21 +410,20 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } else { - while( size ) + timeOut = TIMEOUT_MAX; + while( I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR ) { - /* Wait for the byte to be received */ - timeOut = TIMEOUT_MAX; - while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + if( ( timeOut-- ) == 0 ) { - if( ( timeOut-- ) == 0 ) - { - I2cResetBus( obj ); + I2cResetBus( obj ); - __enable_irq( ); - return( FAIL ); - } - } + __enable_irq( ); + return( FAIL ); + } + } + while( size ) + { if( size == 1 ) { /* Disable Acknowledgement */ @@ -427,6 +433,18 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_GenerateSTOP( obj->I2c, ENABLE ); } + timeOut = TIMEOUT_MAX; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + /* Read a byte from the device */ *buffer = I2C_ReceiveData( obj->I2c ); @@ -439,7 +457,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t /* Wait to make sure that STOP control bit has been cleared */ timeOut = TIMEOUT_MAX; - while(obj->I2c->CR1 & I2C_CR1_STOP) + while( obj->I2c->CR1 & I2C_CR1_STOP ) { if( ( timeOut-- ) == 0 ) { @@ -449,10 +467,116 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t return( FAIL ); } } - /*!< Re-Enable Acknowledgement to be ready for another reception */ - I2C_AcknowledgeConfig( obj->I2c, ENABLE ); } + /*!< Re-Enable Acknowledgement to be ready for another reception */ + I2C_AcknowledgeConfig( obj->I2c, ENABLE ); + __enable_irq( ); return( SUCCESS ); } + +/* Maximum Timeout values for flags and events waiting loops. These timeouts are + not based on accurate values, they just guarantee that the application will + not remain stuck if the I2C communication is corrupted. + You may modify these timeout values depending on CPU frequency and application + conditions (interrupts routines ...). */ +#define EE_FLAG_TIMEOUT ( ( uint32_t )0x1000 ) +#define EE_LONG_TIMEOUT ( ( uint32_t )( 10 * EE_FLAG_TIMEOUT ) ) + +/* Maximum number of trials for I2cMcuWaitStandbyState( ) function */ +#define EE_MAX_TRIALS_NUMBER 300 + +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ) +{ + uint32_t timeOut; + __IO uint16_t tmpSR1 = 0; + __IO uint32_t trials = 0; + + __disable_irq( ); + + /*!< While the bus is busy */ + timeOut = EE_LONG_TIMEOUT; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_BUSY ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + + /* Keep looping till the slave acknowledge his address or maximum number + of trials is reached (this number is defined by EE_MAX_TRIALS_NUMBER define + in eeProm.h file) */ + while( 1 ) + { + /*!< Send START condition */ + I2C_GenerateSTART( obj->I2c, ENABLE ); + + /*!< Test on EV5 and clear it */ + timeOut = EE_FLAG_TIMEOUT; + while( !I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_MODE_SELECT ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + + /*!< Send device address for write */ + I2C_Send7bitAddress( obj->I2c, deviceAddr, I2C_Direction_Transmitter ); + + /* Wait for ADDR flag to be set (Slave acknowledged his address) */ + timeOut = EE_LONG_TIMEOUT; + do + { + /* Get the current value of the SR1 register */ + tmpSR1 = obj->I2c->SR1; + + /* Update the timeout value and exit if it reach 0 */ + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + /* Keep looping till the Address is acknowledged or the AF flag is + set (address not acknowledged at time) */ + while( ( tmpSR1 & ( I2C_SR1_ADDR | I2C_SR1_AF ) ) == 0 ); + + /* Check if the ADDR flag has been set */ + if ( tmpSR1 & I2C_SR1_ADDR ) + { + /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already + been read) */ + ( void )obj->I2c->SR2; + + /*!< STOP condition */ + I2C_GenerateSTOP( obj->I2c, ENABLE ); + + /* Exit the function */ + __enable_irq( ); + return ( SUCCESS ); + } + else + { + /*!< Clear AF flag */ + I2C_ClearFlag( obj->I2c, I2C_FLAG_AF ); + } + + /* Check if the maximum allowed number of trials has bee reached */ + if ( trials++ == EE_MAX_TRIALS_NUMBER ) + { + I2cResetBus( obj ); + /* If the maximum number of trials has been reached, exit the function */ + __enable_irq( ); + return( FAIL ); + } + } +} diff --git a/src/boards/Bleeper-72/i2c-board.h b/src/boards/Bleeper-72/i2c-board.h index f09d3529e..72aae12bb 100644 --- a/src/boards/Bleeper-72/i2c-board.h +++ b/src/boards/Bleeper-72/i2c-board.h @@ -43,6 +43,15 @@ typedef enum I2C_ACK_ADD_10_BIT }I2cAckAddrMode; +/*! + * Internal device address size + */ +typedef enum +{ + I2C_ADDR_SIZE_8 = 0, + I2C_ADDR_SIZE_16, +}I2cAddrSize; + /*! * \brief Initializes the I2C object and MCU peripheral * @@ -93,4 +102,20 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ */ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); +/*! + * \brief Waits until the given device is in standby mode + * + * \param [IN] obj I2C object + * \param [IN] deviceAddr device address + */ +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ); + +/*! + * \brief Sets the internal device address size + * + * \param [IN] obj I2C object + * \param [IN] addrSize Internal address size + */ +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ); + #endif // __I2C_MCU_H__ diff --git a/src/boards/Bleeper-72/rtc-board.c b/src/boards/Bleeper-72/rtc-board.c index 938f507f5..b37da4cd0 100644 --- a/src/boards/Bleeper-72/rtc-board.c +++ b/src/boards/Bleeper-72/rtc-board.c @@ -315,28 +315,53 @@ static void RtcStartWakeUpAlarm( uint32_t timeoutValue ) timeoutValue = timeoutValue / RTC_ALARM_TIME_BASE; - rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; - rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; - rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; - rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; - - rtcAlarmSeconds = ( rtcSeconds ) % 60; - rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; - rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; - rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; - - if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) - { - if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + if( timeoutValue > 2160000 ) // 25 "days" in tick + { // drastically reduce the computation time + rtcAlarmSeconds = RTC_TimeStruct.RTC_Seconds; + rtcAlarmMinutes = RTC_TimeStruct.RTC_Minutes; + rtcAlarmHours = RTC_TimeStruct.RTC_Hours; + rtcAlarmDays = 25 + RTC_DateStruct.RTC_Date; // simply add 25 days to current date and time + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1]; + } } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1]; + } + } } else { - if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; + rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; + rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; + rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; + + rtcAlarmSeconds = ( rtcSeconds ) % 60; + rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; + rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; + rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + } + } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + } } } @@ -386,45 +411,46 @@ void RtcEnterLowPowerStopMode( void ) void RtcRecoverMcuStatus( void ) { -#ifdef LOW_POWER_MODE_ENABLE - if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) - { - // Disable IRQ while the MCU is not running on HSE - __disable_irq( ); - - /* After wake-up from STOP reconfigure the system clock */ - /* Enable HSE */ - RCC_HSEConfig( RCC_HSE_ON ); - - /* Wait till HSE is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) - {} - - /* Enable PLL */ - RCC_PLLCmd( ENABLE ); - - /* Wait till PLL is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) - {} - - /* Select PLL as system clock source */ - RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); - - /* Wait till PLL is used as system clock source */ - while( RCC_GetSYSCLKSource( ) != 0x0C ) - {} - - /* Set MCU in ULP (Ultra Low Power) */ - PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time - - /* Enable the Power Voltage Detector */ - PWR_PVDCmd( ENABLE ); + if( TimerGetLowPowerEnable( ) == true ) + { + if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) + { + // Disable IRQ while the MCU is not running on HSE + __disable_irq( ); + + /* After wake-up from STOP reconfigure the system clock */ + /* Enable HSE */ + RCC_HSEConfig( RCC_HSE_ON ); - BoardInitMcu( ); - - __enable_irq( ); + /* Wait till HSE is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) + {} + + /* Enable PLL */ + RCC_PLLCmd( ENABLE ); + + /* Wait till PLL is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) + {} + + /* Select PLL as system clock source */ + RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); + + /* Wait till PLL is used as system clock source */ + while( RCC_GetSYSCLKSource( ) != 0x0C ) + {} + + /* Set MCU in ULP (Ultra Low Power) */ + PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time + + /* Enable the Power Voltage Detector */ + PWR_PVDCmd( ENABLE ); + + BoardInitMcu( ); + + __enable_irq( ); + } } -#endif } /*! diff --git a/src/boards/Bleeper-72/sx1272-board.c b/src/boards/Bleeper-72/sx1272-board.c index 1d5ed48ac..1981fd9e9 100644 --- a/src/boards/Bleeper-72/sx1272-board.c +++ b/src/boards/Bleeper-72/sx1272-board.c @@ -41,6 +41,7 @@ const struct Radio_s Radio = SX1272SetSleep, SX1272SetStby, SX1272SetRx, + SX1272StartCad, SX1272ReadRssi, SX1272Write, SX1272Read, diff --git a/src/boards/Bleeper-72/timer-board.c b/src/boards/Bleeper-72/timer-board.c index 61ecdc804..49dba7e87 100644 --- a/src/boards/Bleeper-72/timer-board.c +++ b/src/boards/Bleeper-72/timer-board.c @@ -36,8 +36,26 @@ static uint64_t TimerTickCounterContext = 0; */ volatile uint64_t TimeoutCntValue = 0; +/*! + * Increment the Hardware Timer tick counter + */ void TimerIncrementTickCounter( void ); +/*! + * Counter used for the Delay operations + */ +volatile uint32_t TimerDelayCounter = 0; + +/*! + * Retunr the value of the counter used for a Delay + */ +uint32_t TimerHwGetDelayValue( void ); + +/*! + * Increment the value of TimerDelayCounter + */ +void TimerIncrementDelayCounter( void ); + void TimerHwInit( void ) { @@ -50,8 +68,8 @@ void TimerHwInit( void ) /* --------------------------NVIC Configuration -------------------------------*/ /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); @@ -65,10 +83,39 @@ void TimerHwInit( void ) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure ); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); + TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); /* TIM2 disable counter */ TIM_Cmd( TIM2, ENABLE ); + + /* TIM3 clock enable */ + RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); + + /* --------------------------NVIC Configuration -------------------------------*/ + /* Enable the TIM3 gloabal Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init( &NVIC_InitStructure ); + + /* Time base configuration */ + TIM_TimeBaseStructure.TIM_Period = 3199; + TIM_TimeBaseStructure.TIM_Prescaler = 10; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + + /* TIM3 disable counter */ + TIM_Cmd( TIM3, DISABLE ); + + + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + } void TimerHwDeInit( void ) @@ -104,16 +151,21 @@ void TimerHwStop( void ) void TimerHwDelayMs( uint32_t delay ) { - uint64_t delayValue = 0; - uint64_t timeout = 0; + uint32_t delayValue = 0; - delayValue = delay * 1000; + delayValue = delay; - timeout = TimerHwGetTimerValue( ); + TimerDelayCounter = 0; - while( ( ( TimerHwGetTimerValue( ) - timeout ) * HW_TIMER_TIME_BASE ) < delayValue ) + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + + while( TimerHwGetDelayValue( ) < delayValue ) { } + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + TIM_Cmd( TIM3, DISABLE ); } uint64_t TimerHwGetElapsedTime( void ) @@ -134,6 +186,19 @@ uint64_t TimerHwGetTimerValue( void ) return( val ); } +uint32_t TimerHwGetDelayValue( void ) +{ + uint32_t val = 0; + + __disable_irq( ); + + val = TimerDelayCounter; + + __enable_irq( ); + + return( val ); +} + void TimerIncrementTickCounter( void ) { __disable_irq( ); @@ -143,6 +208,15 @@ void TimerIncrementTickCounter( void ) __enable_irq( ); } +void TimerIncrementDelayCounter( void ) +{ + __disable_irq( ); + + TimerDelayCounter++; + + __enable_irq( ); +} + /*! * Timer IRQ handler */ @@ -151,13 +225,24 @@ void TIM2_IRQHandler( void ) if( TIM_GetITStatus( TIM2, TIM_IT_Update ) != RESET ) { TimerIncrementTickCounter( ); + TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); if( TimerTickCounter == TimeoutCntValue ) { TimerIrqHandler( ); } - - TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); + } +} + +/*! + * Timer IRQ handler + */ +void TIM3_IRQHandler( void ) +{ + if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET ) + { + TimerIncrementDelayCounter( ); + TIM_ClearITPendingBit( TIM3, TIM_IT_Update ); } } diff --git a/src/boards/Bleeper-76/board.c b/src/boards/Bleeper-76/board.c index f8b1085bc..c42cb1e88 100644 --- a/src/boards/Bleeper-76/board.c +++ b/src/boards/Bleeper-76/board.c @@ -89,13 +89,21 @@ void BoardInitMcu( void ) GpioInit( &DbgPin4, J1_4, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif BoardInitPeriph( ); - BoardUnusedIoInit( ); - -#ifdef LOW_POWER_MODE_ENABLE - RtcInit( ); +#if( LOW_POWER_MODE_ENABLE ) + TimerSetLowPowerEnable( true ); #else - TimerHwInit( ); + TimerSetLowPowerEnable( false ); #endif + BoardUnusedIoInit( ); + + if( TimerGetLowPowerEnable( ) == true ) + { + RtcInit( ); + } + else + { + TimerHwInit( ); + } McuInitialized = true; } } @@ -127,12 +135,13 @@ void BoardDeInitMcu( void ) GpioInit( &DbgPin3, J1_3, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &DbgPin4, J1_4, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif - + GpioInit( &ioPin, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); GpioInit( &ioPin, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &ioPin, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); GpioInit( &ioPin, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); - + McuInitialized = false; } @@ -236,8 +245,10 @@ static void BoardUnusedIoInit( void ) GpioInit( &ioPin, NC_13, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); /* USB */ +#if !defined( USE_USB_CDC ) GpioInit( &ioPin, USB_DM, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); +#endif /* BOOT1 pin */ GpioInit( &ioPin, BOOT_1, PIN_ANALOGIC, PIN_OPEN_DRAIN, PIN_NO_PULL, 0 ); diff --git a/src/boards/Bleeper-76/cmsis/arm-gcc/stm32l1xx_hd_flash.ld b/src/boards/Bleeper-76/cmsis/arm-gcc/stm32l1xx_hd_flash.ld index 228fc0598..c9382e2b5 100644 --- a/src/boards/Bleeper-76/cmsis/arm-gcc/stm32l1xx_hd_flash.ld +++ b/src/boards/Bleeper-76/cmsis/arm-gcc/stm32l1xx_hd_flash.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_hd Device with -** 384KByte FLASH, 48KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 48K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x2000C000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 384K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 48K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/Bleeper-76/gpio-board.c b/src/boards/Bleeper-76/gpio-board.c index 72802a517..f4739e11f 100644 --- a/src/boards/Bleeper-76/gpio-board.c +++ b/src/boards/Bleeper-76/gpio-board.c @@ -200,9 +200,10 @@ uint32_t GpioMcuRead( Gpio_t *obj ) void EXTI0_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line0 ) != RESET ) { if( GpioIrq[0] != NULL ) @@ -215,9 +216,10 @@ void EXTI0_IRQHandler( void ) void EXTI1_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line1 ) != RESET ) { if( GpioIrq[1] != NULL ) @@ -230,9 +232,10 @@ void EXTI1_IRQHandler( void ) void EXTI2_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line2 ) != RESET ) { if( GpioIrq[2] != NULL ) @@ -245,9 +248,10 @@ void EXTI2_IRQHandler( void ) void EXTI3_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line3 ) != RESET ) { if( GpioIrq[3] != NULL ) @@ -260,9 +264,10 @@ void EXTI3_IRQHandler( void ) void EXTI4_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line4 ) != RESET ) { if( GpioIrq[4] != NULL ) @@ -275,9 +280,10 @@ void EXTI4_IRQHandler( void ) void EXTI9_5_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line5 ) != RESET ) { if( GpioIrq[5] != NULL ) @@ -326,9 +332,10 @@ void EXTI9_5_IRQHandler( void ) void EXTI15_10_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line10 ) != RESET ) { if( GpioIrq[10] != NULL ) diff --git a/src/boards/Bleeper-76/i2c-board.c b/src/boards/Bleeper-76/i2c-board.c index 678db7dec..304259386 100644 --- a/src/boards/Bleeper-76/i2c-board.c +++ b/src/boards/Bleeper-76/i2c-board.c @@ -20,6 +20,8 @@ Maintainer: Miguel Luis and Gregory Cristian */ #define TIMEOUT_MAX 0x8000 +I2cAddrSize I2cInternalAddrSize = I2C_ADDR_SIZE_8; + /*! * MCU I2C peripherals enumeration */ @@ -110,6 +112,11 @@ void I2cMcuDeInit( I2c_t *obj ) GpioInit( &obj->Sda, obj->Sda.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ) +{ + I2cInternalAddrSize = addrSize; +} + uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { uint32_t timeOut; @@ -161,7 +168,7 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -291,7 +298,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -377,7 +384,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_AcknowledgeConfig( obj->I2c, DISABLE ); /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ - (void)obj->I2c->SR2; + ( void )obj->I2c->SR2; /* Send STOP Condition */ I2C_GenerateSTOP( obj->I2c, ENABLE ); @@ -403,21 +410,20 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } else { - while( size ) + timeOut = TIMEOUT_MAX; + while( I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR ) { - /* Wait for the byte to be received */ - timeOut = TIMEOUT_MAX; - while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + if( ( timeOut-- ) == 0 ) { - if( ( timeOut-- ) == 0 ) - { - I2cResetBus( obj ); + I2cResetBus( obj ); - __enable_irq( ); - return( FAIL ); - } - } + __enable_irq( ); + return( FAIL ); + } + } + while( size ) + { if( size == 1 ) { /* Disable Acknowledgement */ @@ -427,6 +433,18 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_GenerateSTOP( obj->I2c, ENABLE ); } + timeOut = TIMEOUT_MAX; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + /* Read a byte from the device */ *buffer = I2C_ReceiveData( obj->I2c ); @@ -439,7 +457,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t /* Wait to make sure that STOP control bit has been cleared */ timeOut = TIMEOUT_MAX; - while(obj->I2c->CR1 & I2C_CR1_STOP) + while( obj->I2c->CR1 & I2C_CR1_STOP ) { if( ( timeOut-- ) == 0 ) { @@ -449,10 +467,116 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t return( FAIL ); } } - /*!< Re-Enable Acknowledgement to be ready for another reception */ - I2C_AcknowledgeConfig( obj->I2c, ENABLE ); } + /*!< Re-Enable Acknowledgement to be ready for another reception */ + I2C_AcknowledgeConfig( obj->I2c, ENABLE ); + __enable_irq( ); return( SUCCESS ); } + +/* Maximum Timeout values for flags and events waiting loops. These timeouts are + not based on accurate values, they just guarantee that the application will + not remain stuck if the I2C communication is corrupted. + You may modify these timeout values depending on CPU frequency and application + conditions (interrupts routines ...). */ +#define EE_FLAG_TIMEOUT ( ( uint32_t )0x1000 ) +#define EE_LONG_TIMEOUT ( ( uint32_t )( 10 * EE_FLAG_TIMEOUT ) ) + +/* Maximum number of trials for I2cMcuWaitStandbyState( ) function */ +#define EE_MAX_TRIALS_NUMBER 300 + +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ) +{ + uint32_t timeOut; + __IO uint16_t tmpSR1 = 0; + __IO uint32_t trials = 0; + + __disable_irq( ); + + /*!< While the bus is busy */ + timeOut = EE_LONG_TIMEOUT; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_BUSY ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + + /* Keep looping till the slave acknowledge his address or maximum number + of trials is reached (this number is defined by EE_MAX_TRIALS_NUMBER define + in eeProm.h file) */ + while( 1 ) + { + /*!< Send START condition */ + I2C_GenerateSTART( obj->I2c, ENABLE ); + + /*!< Test on EV5 and clear it */ + timeOut = EE_FLAG_TIMEOUT; + while( !I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_MODE_SELECT ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + + /*!< Send device address for write */ + I2C_Send7bitAddress( obj->I2c, deviceAddr, I2C_Direction_Transmitter ); + + /* Wait for ADDR flag to be set (Slave acknowledged his address) */ + timeOut = EE_LONG_TIMEOUT; + do + { + /* Get the current value of the SR1 register */ + tmpSR1 = obj->I2c->SR1; + + /* Update the timeout value and exit if it reach 0 */ + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + /* Keep looping till the Address is acknowledged or the AF flag is + set (address not acknowledged at time) */ + while( ( tmpSR1 & ( I2C_SR1_ADDR | I2C_SR1_AF ) ) == 0 ); + + /* Check if the ADDR flag has been set */ + if ( tmpSR1 & I2C_SR1_ADDR ) + { + /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already + been read) */ + ( void )obj->I2c->SR2; + + /*!< STOP condition */ + I2C_GenerateSTOP( obj->I2c, ENABLE ); + + /* Exit the function */ + __enable_irq( ); + return ( SUCCESS ); + } + else + { + /*!< Clear AF flag */ + I2C_ClearFlag( obj->I2c, I2C_FLAG_AF ); + } + + /* Check if the maximum allowed number of trials has bee reached */ + if ( trials++ == EE_MAX_TRIALS_NUMBER ) + { + I2cResetBus( obj ); + /* If the maximum number of trials has been reached, exit the function */ + __enable_irq( ); + return( FAIL ); + } + } +} diff --git a/src/boards/Bleeper-76/i2c-board.h b/src/boards/Bleeper-76/i2c-board.h index f09d3529e..72aae12bb 100644 --- a/src/boards/Bleeper-76/i2c-board.h +++ b/src/boards/Bleeper-76/i2c-board.h @@ -43,6 +43,15 @@ typedef enum I2C_ACK_ADD_10_BIT }I2cAckAddrMode; +/*! + * Internal device address size + */ +typedef enum +{ + I2C_ADDR_SIZE_8 = 0, + I2C_ADDR_SIZE_16, +}I2cAddrSize; + /*! * \brief Initializes the I2C object and MCU peripheral * @@ -93,4 +102,20 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ */ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); +/*! + * \brief Waits until the given device is in standby mode + * + * \param [IN] obj I2C object + * \param [IN] deviceAddr device address + */ +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ); + +/*! + * \brief Sets the internal device address size + * + * \param [IN] obj I2C object + * \param [IN] addrSize Internal address size + */ +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ); + #endif // __I2C_MCU_H__ diff --git a/src/boards/Bleeper-76/rtc-board.c b/src/boards/Bleeper-76/rtc-board.c index 938f507f5..b37da4cd0 100644 --- a/src/boards/Bleeper-76/rtc-board.c +++ b/src/boards/Bleeper-76/rtc-board.c @@ -315,28 +315,53 @@ static void RtcStartWakeUpAlarm( uint32_t timeoutValue ) timeoutValue = timeoutValue / RTC_ALARM_TIME_BASE; - rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; - rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; - rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; - rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; - - rtcAlarmSeconds = ( rtcSeconds ) % 60; - rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; - rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; - rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; - - if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) - { - if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + if( timeoutValue > 2160000 ) // 25 "days" in tick + { // drastically reduce the computation time + rtcAlarmSeconds = RTC_TimeStruct.RTC_Seconds; + rtcAlarmMinutes = RTC_TimeStruct.RTC_Minutes; + rtcAlarmHours = RTC_TimeStruct.RTC_Hours; + rtcAlarmDays = 25 + RTC_DateStruct.RTC_Date; // simply add 25 days to current date and time + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1]; + } } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1]; + } + } } else { - if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; + rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; + rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; + rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; + + rtcAlarmSeconds = ( rtcSeconds ) % 60; + rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; + rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; + rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + } + } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + } } } @@ -386,45 +411,46 @@ void RtcEnterLowPowerStopMode( void ) void RtcRecoverMcuStatus( void ) { -#ifdef LOW_POWER_MODE_ENABLE - if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) - { - // Disable IRQ while the MCU is not running on HSE - __disable_irq( ); - - /* After wake-up from STOP reconfigure the system clock */ - /* Enable HSE */ - RCC_HSEConfig( RCC_HSE_ON ); - - /* Wait till HSE is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) - {} - - /* Enable PLL */ - RCC_PLLCmd( ENABLE ); - - /* Wait till PLL is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) - {} - - /* Select PLL as system clock source */ - RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); - - /* Wait till PLL is used as system clock source */ - while( RCC_GetSYSCLKSource( ) != 0x0C ) - {} - - /* Set MCU in ULP (Ultra Low Power) */ - PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time - - /* Enable the Power Voltage Detector */ - PWR_PVDCmd( ENABLE ); + if( TimerGetLowPowerEnable( ) == true ) + { + if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) + { + // Disable IRQ while the MCU is not running on HSE + __disable_irq( ); + + /* After wake-up from STOP reconfigure the system clock */ + /* Enable HSE */ + RCC_HSEConfig( RCC_HSE_ON ); - BoardInitMcu( ); - - __enable_irq( ); + /* Wait till HSE is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) + {} + + /* Enable PLL */ + RCC_PLLCmd( ENABLE ); + + /* Wait till PLL is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) + {} + + /* Select PLL as system clock source */ + RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); + + /* Wait till PLL is used as system clock source */ + while( RCC_GetSYSCLKSource( ) != 0x0C ) + {} + + /* Set MCU in ULP (Ultra Low Power) */ + PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time + + /* Enable the Power Voltage Detector */ + PWR_PVDCmd( ENABLE ); + + BoardInitMcu( ); + + __enable_irq( ); + } } -#endif } /*! diff --git a/src/boards/Bleeper-76/sx1276-board.c b/src/boards/Bleeper-76/sx1276-board.c index 1787d074b..9129aad39 100644 --- a/src/boards/Bleeper-76/sx1276-board.c +++ b/src/boards/Bleeper-76/sx1276-board.c @@ -41,6 +41,7 @@ const struct Radio_s Radio = SX1276SetSleep, SX1276SetStby, SX1276SetRx, + SX1276StartCad, SX1276ReadRssi, SX1276Write, SX1276Read, diff --git a/src/boards/Bleeper-76/timer-board.c b/src/boards/Bleeper-76/timer-board.c index 61ecdc804..49dba7e87 100644 --- a/src/boards/Bleeper-76/timer-board.c +++ b/src/boards/Bleeper-76/timer-board.c @@ -36,8 +36,26 @@ static uint64_t TimerTickCounterContext = 0; */ volatile uint64_t TimeoutCntValue = 0; +/*! + * Increment the Hardware Timer tick counter + */ void TimerIncrementTickCounter( void ); +/*! + * Counter used for the Delay operations + */ +volatile uint32_t TimerDelayCounter = 0; + +/*! + * Retunr the value of the counter used for a Delay + */ +uint32_t TimerHwGetDelayValue( void ); + +/*! + * Increment the value of TimerDelayCounter + */ +void TimerIncrementDelayCounter( void ); + void TimerHwInit( void ) { @@ -50,8 +68,8 @@ void TimerHwInit( void ) /* --------------------------NVIC Configuration -------------------------------*/ /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); @@ -65,10 +83,39 @@ void TimerHwInit( void ) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure ); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); + TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); /* TIM2 disable counter */ TIM_Cmd( TIM2, ENABLE ); + + /* TIM3 clock enable */ + RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); + + /* --------------------------NVIC Configuration -------------------------------*/ + /* Enable the TIM3 gloabal Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init( &NVIC_InitStructure ); + + /* Time base configuration */ + TIM_TimeBaseStructure.TIM_Period = 3199; + TIM_TimeBaseStructure.TIM_Prescaler = 10; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + + /* TIM3 disable counter */ + TIM_Cmd( TIM3, DISABLE ); + + + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + } void TimerHwDeInit( void ) @@ -104,16 +151,21 @@ void TimerHwStop( void ) void TimerHwDelayMs( uint32_t delay ) { - uint64_t delayValue = 0; - uint64_t timeout = 0; + uint32_t delayValue = 0; - delayValue = delay * 1000; + delayValue = delay; - timeout = TimerHwGetTimerValue( ); + TimerDelayCounter = 0; - while( ( ( TimerHwGetTimerValue( ) - timeout ) * HW_TIMER_TIME_BASE ) < delayValue ) + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + + while( TimerHwGetDelayValue( ) < delayValue ) { } + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + TIM_Cmd( TIM3, DISABLE ); } uint64_t TimerHwGetElapsedTime( void ) @@ -134,6 +186,19 @@ uint64_t TimerHwGetTimerValue( void ) return( val ); } +uint32_t TimerHwGetDelayValue( void ) +{ + uint32_t val = 0; + + __disable_irq( ); + + val = TimerDelayCounter; + + __enable_irq( ); + + return( val ); +} + void TimerIncrementTickCounter( void ) { __disable_irq( ); @@ -143,6 +208,15 @@ void TimerIncrementTickCounter( void ) __enable_irq( ); } +void TimerIncrementDelayCounter( void ) +{ + __disable_irq( ); + + TimerDelayCounter++; + + __enable_irq( ); +} + /*! * Timer IRQ handler */ @@ -151,13 +225,24 @@ void TIM2_IRQHandler( void ) if( TIM_GetITStatus( TIM2, TIM_IT_Update ) != RESET ) { TimerIncrementTickCounter( ); + TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); if( TimerTickCounter == TimeoutCntValue ) { TimerIrqHandler( ); } - - TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); + } +} + +/*! + * Timer IRQ handler + */ +void TIM3_IRQHandler( void ) +{ + if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET ) + { + TimerIncrementDelayCounter( ); + TIM_ClearITPendingBit( TIM3, TIM_IT_Update ); } } diff --git a/src/boards/LoRaMote/board.c b/src/boards/LoRaMote/board.c index 36fd05e0f..41e8e82d8 100644 --- a/src/boards/LoRaMote/board.c +++ b/src/boards/LoRaMote/board.c @@ -83,13 +83,13 @@ void BoardInitPeriph( void ) GpioInit( &Led2, LED_2, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &Led3, LED_3, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - // Init Temperature, pressure and altitude sensor + // Init temperature, pressure and altitude sensor MPL3115Init( ); - // Init Accelerometer + // Init accelerometer MMA8451Init( ); - // Init Magnetometer + // Init magnetometer MAG3110Init( ); // Init SAR @@ -133,46 +133,64 @@ void BoardInitMcu( void ) GpioInit( &DbgPin4, CON_EXT_9, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif - BoardUnusedIoInit( ); - #if defined( USE_USB_CDC ) - UsbMcuInit( ); - UartInit( &UartUsb, UART_USB_CDC, NC, NC ); - UartConfig( &UartUsb, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL ); -#endif - -#ifdef LOW_POWER_MODE_ENABLE - RtcInit( ); + { + Gpio_t usbDM; + + GpioInit( &usbDM, USB_DM, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); + + if( GpioRead( &usbDM ) == 0 ) + { + TimerSetLowPowerEnable( false ); + UsbMcuInit( ); + UartInit( &UartUsb, UART_USB_CDC, NC, NC ); + UartConfig( &UartUsb, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL ); + } + else + { + TimerSetLowPowerEnable( true ); + GpioInit( &usbDM, USB_DM, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + } + } +#elif( LOW_POWER_MODE_ENABLE ) + TimerSetLowPowerEnable( true ); #else - TimerHwInit( ); + TimerSetLowPowerEnable( false ); #endif + BoardUnusedIoInit( ); + + if( TimerGetLowPowerEnable( ) == true ) + { + RtcInit( ); + } + else + { + TimerHwInit( ); + } McuInitialized = true; } } void BoardDeInitMcu( void ) { - Gpio_t oscHseIn; - Gpio_t oscHseOut; - Gpio_t oscLseIn; - Gpio_t oscLseOut; + Gpio_t ioPin; I2cDeInit( &I2c ); SpiDeInit( &SX1272.Spi ); SX1272IoDeInit( ); -#if defined( USE_DEBUG_PINS ) +#if ( defined( USE_DEBUG_PINS ) && !defined( LOW_POWER_MODE_ENABLE ) ) GpioInit( &DbgPin1, CON_EXT_1, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &DbgPin2, CON_EXT_3, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &DbgPin3, CON_EXT_7, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &DbgPin4, CON_EXT_9, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif - GpioInit( &oscHseIn, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); - GpioInit( &oscHseOut, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &ioPin, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &ioPin, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); - GpioInit( &oscLseIn, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); - GpioInit( &oscLseOut, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); + GpioInit( &ioPin, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); + GpioInit( &ioPin, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); McuInitialized = false; } @@ -222,7 +240,7 @@ static void BoardUnusedIoInit( void ) /* USB */ #if !defined( USE_USB_CDC ) GpioInit( &ioPin, USB_DM, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif GpioInit( &ioPin, BOOT_1, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); diff --git a/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash.ld b/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash.ld index 1be62d5b0..0992cefc3 100644 --- a/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash.ld +++ b/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld b/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld index f8fc2a20f..8e7d712a7 100644 --- a/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld +++ b/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 12K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 12K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld b/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld index 865fc0291..9dfc28485 100644 --- a/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld +++ b/src/boards/LoRaMote/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08003000, LENGTH = 128K - 0x3000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08003000, LENGTH = 128K - 0x3000 - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/LoRaMote/gpio-board.c b/src/boards/LoRaMote/gpio-board.c index 72802a517..324429404 100644 --- a/src/boards/LoRaMote/gpio-board.c +++ b/src/boards/LoRaMote/gpio-board.c @@ -200,8 +200,11 @@ uint32_t GpioMcuRead( Gpio_t *obj ) void EXTI0_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line0 ) != RESET ) { @@ -215,8 +218,11 @@ void EXTI0_IRQHandler( void ) void EXTI1_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line1 ) != RESET ) { @@ -230,8 +236,11 @@ void EXTI1_IRQHandler( void ) void EXTI2_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line2 ) != RESET ) { @@ -245,8 +254,11 @@ void EXTI2_IRQHandler( void ) void EXTI3_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line3 ) != RESET ) { @@ -260,8 +272,11 @@ void EXTI3_IRQHandler( void ) void EXTI4_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line4 ) != RESET ) { @@ -275,8 +290,11 @@ void EXTI4_IRQHandler( void ) void EXTI9_5_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line5 ) != RESET ) { @@ -326,8 +344,11 @@ void EXTI9_5_IRQHandler( void ) void EXTI15_10_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line10 ) != RESET ) { diff --git a/src/boards/LoRaMote/i2c-board.c b/src/boards/LoRaMote/i2c-board.c index de1bdf280..cffc401da 100644 --- a/src/boards/LoRaMote/i2c-board.c +++ b/src/boards/LoRaMote/i2c-board.c @@ -20,6 +20,8 @@ Maintainer: Miguel Luis and Gregory Cristian */ #define TIMEOUT_MAX 0x8000 +I2cAddrSize I2cInternalAddrSize = I2C_ADDR_SIZE_8; + /*! * MCU I2C peripherals enumeration */ @@ -110,6 +112,11 @@ void I2cMcuDeInit( I2c_t *obj ) GpioInit( &obj->Sda, obj->Sda.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ) +{ + I2cInternalAddrSize = addrSize; +} + uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { uint32_t timeOut; @@ -161,7 +168,7 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -291,7 +298,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -377,7 +384,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_AcknowledgeConfig( obj->I2c, DISABLE ); /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ - (void)obj->I2c->SR2; + ( void )obj->I2c->SR2; /* Send STOP Condition */ I2C_GenerateSTOP( obj->I2c, ENABLE ); @@ -403,21 +410,20 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } else { - while( size ) + timeOut = TIMEOUT_MAX; + while( I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR ) { - /* Wait for the byte to be received */ - timeOut = TIMEOUT_MAX; - while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + if( ( timeOut-- ) == 0 ) { - if( ( timeOut-- ) == 0 ) - { - I2cResetBus( obj ); + I2cResetBus( obj ); - __enable_irq( ); - return( FAIL ); - } - } + __enable_irq( ); + return( FAIL ); + } + } + while( size ) + { if( size == 1 ) { /* Disable Acknowledgement */ @@ -427,6 +433,18 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_GenerateSTOP( obj->I2c, ENABLE ); } + timeOut = TIMEOUT_MAX; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + /* Read a byte from the device */ *buffer = I2C_ReceiveData( obj->I2c ); @@ -439,7 +457,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t /* Wait to make sure that STOP control bit has been cleared */ timeOut = TIMEOUT_MAX; - while(obj->I2c->CR1 & I2C_CR1_STOP) + while( obj->I2c->CR1 & I2C_CR1_STOP ) { if( ( timeOut-- ) == 0 ) { @@ -449,10 +467,116 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t return( FAIL ); } } - /*!< Re-Enable Acknowledgement to be ready for another reception */ - I2C_AcknowledgeConfig( obj->I2c, ENABLE ); } + /*!< Re-Enable Acknowledgement to be ready for another reception */ + I2C_AcknowledgeConfig( obj->I2c, ENABLE ); + __enable_irq( ); return( SUCCESS ); } + +/* Maximum Timeout values for flags and events waiting loops. These timeouts are + not based on accurate values, they just guarantee that the application will + not remain stuck if the I2C communication is corrupted. + You may modify these timeout values depending on CPU frequency and application + conditions (interrupts routines ...). */ +#define EE_FLAG_TIMEOUT ( ( uint32_t )0x1000 ) +#define EE_LONG_TIMEOUT ( ( uint32_t )( 10 * EE_FLAG_TIMEOUT ) ) + +/* Maximum number of trials for I2cMcuWaitStandbyState( ) function */ +#define EE_MAX_TRIALS_NUMBER 300 + +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ) +{ + uint32_t timeOut; + __IO uint16_t tmpSR1 = 0; + __IO uint32_t trials = 0; + + __disable_irq( ); + + /*!< While the bus is busy */ + timeOut = EE_LONG_TIMEOUT; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_BUSY ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + + /* Keep looping till the slave acknowledge his address or maximum number + of trials is reached (this number is defined by EE_MAX_TRIALS_NUMBER define + in eeProm.h file) */ + while( 1 ) + { + /*!< Send START condition */ + I2C_GenerateSTART( obj->I2c, ENABLE ); + + /*!< Test on EV5 and clear it */ + timeOut = EE_FLAG_TIMEOUT; + while( !I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_MODE_SELECT ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + + /*!< Send device address for write */ + I2C_Send7bitAddress( obj->I2c, deviceAddr, I2C_Direction_Transmitter ); + + /* Wait for ADDR flag to be set (Slave acknowledged his address) */ + timeOut = EE_LONG_TIMEOUT; + do + { + /* Get the current value of the SR1 register */ + tmpSR1 = obj->I2c->SR1; + + /* Update the timeout value and exit if it reach 0 */ + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + /* Keep looping till the Address is acknowledged or the AF flag is + set (address not acknowledged at time) */ + while( ( tmpSR1 & ( I2C_SR1_ADDR | I2C_SR1_AF ) ) == 0 ); + + /* Check if the ADDR flag has been set */ + if ( tmpSR1 & I2C_SR1_ADDR ) + { + /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already + been read) */ + ( void )obj->I2c->SR2; + + /*!< STOP condition */ + I2C_GenerateSTOP( obj->I2c, ENABLE ); + + /* Exit the function */ + __enable_irq( ); + return ( SUCCESS ); + } + else + { + /*!< Clear AF flag */ + I2C_ClearFlag( obj->I2c, I2C_FLAG_AF ); + } + + /* Check if the maximum allowed number of trials has bee reached */ + if ( trials++ == EE_MAX_TRIALS_NUMBER ) + { + I2cResetBus( obj ); + /* If the maximum number of trials has been reached, exit the function */ + __enable_irq( ); + return( FAIL ); + } + } +} diff --git a/src/boards/LoRaMote/i2c-board.h b/src/boards/LoRaMote/i2c-board.h index f09d3529e..72aae12bb 100644 --- a/src/boards/LoRaMote/i2c-board.h +++ b/src/boards/LoRaMote/i2c-board.h @@ -43,6 +43,15 @@ typedef enum I2C_ACK_ADD_10_BIT }I2cAckAddrMode; +/*! + * Internal device address size + */ +typedef enum +{ + I2C_ADDR_SIZE_8 = 0, + I2C_ADDR_SIZE_16, +}I2cAddrSize; + /*! * \brief Initializes the I2C object and MCU peripheral * @@ -93,4 +102,20 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ */ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); +/*! + * \brief Waits until the given device is in standby mode + * + * \param [IN] obj I2C object + * \param [IN] deviceAddr device address + */ +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ); + +/*! + * \brief Sets the internal device address size + * + * \param [IN] obj I2C object + * \param [IN] addrSize Internal address size + */ +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ); + #endif // __I2C_MCU_H__ diff --git a/src/boards/LoRaMote/rtc-board.c b/src/boards/LoRaMote/rtc-board.c index 938f507f5..b37da4cd0 100644 --- a/src/boards/LoRaMote/rtc-board.c +++ b/src/boards/LoRaMote/rtc-board.c @@ -315,28 +315,53 @@ static void RtcStartWakeUpAlarm( uint32_t timeoutValue ) timeoutValue = timeoutValue / RTC_ALARM_TIME_BASE; - rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; - rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; - rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; - rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; - - rtcAlarmSeconds = ( rtcSeconds ) % 60; - rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; - rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; - rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; - - if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) - { - if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + if( timeoutValue > 2160000 ) // 25 "days" in tick + { // drastically reduce the computation time + rtcAlarmSeconds = RTC_TimeStruct.RTC_Seconds; + rtcAlarmMinutes = RTC_TimeStruct.RTC_Minutes; + rtcAlarmHours = RTC_TimeStruct.RTC_Hours; + rtcAlarmDays = 25 + RTC_DateStruct.RTC_Date; // simply add 25 days to current date and time + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1]; + } } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1]; + } + } } else { - if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; + rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; + rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; + rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; + + rtcAlarmSeconds = ( rtcSeconds ) % 60; + rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; + rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; + rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + } + } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + } } } @@ -386,45 +411,46 @@ void RtcEnterLowPowerStopMode( void ) void RtcRecoverMcuStatus( void ) { -#ifdef LOW_POWER_MODE_ENABLE - if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) - { - // Disable IRQ while the MCU is not running on HSE - __disable_irq( ); - - /* After wake-up from STOP reconfigure the system clock */ - /* Enable HSE */ - RCC_HSEConfig( RCC_HSE_ON ); - - /* Wait till HSE is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) - {} - - /* Enable PLL */ - RCC_PLLCmd( ENABLE ); - - /* Wait till PLL is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) - {} - - /* Select PLL as system clock source */ - RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); - - /* Wait till PLL is used as system clock source */ - while( RCC_GetSYSCLKSource( ) != 0x0C ) - {} - - /* Set MCU in ULP (Ultra Low Power) */ - PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time - - /* Enable the Power Voltage Detector */ - PWR_PVDCmd( ENABLE ); + if( TimerGetLowPowerEnable( ) == true ) + { + if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) + { + // Disable IRQ while the MCU is not running on HSE + __disable_irq( ); + + /* After wake-up from STOP reconfigure the system clock */ + /* Enable HSE */ + RCC_HSEConfig( RCC_HSE_ON ); - BoardInitMcu( ); - - __enable_irq( ); + /* Wait till HSE is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) + {} + + /* Enable PLL */ + RCC_PLLCmd( ENABLE ); + + /* Wait till PLL is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) + {} + + /* Select PLL as system clock source */ + RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); + + /* Wait till PLL is used as system clock source */ + while( RCC_GetSYSCLKSource( ) != 0x0C ) + {} + + /* Set MCU in ULP (Ultra Low Power) */ + PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time + + /* Enable the Power Voltage Detector */ + PWR_PVDCmd( ENABLE ); + + BoardInitMcu( ); + + __enable_irq( ); + } } -#endif } /*! diff --git a/src/boards/LoRaMote/sx1272-board.c b/src/boards/LoRaMote/sx1272-board.c index edb6e2024..a49ac33a5 100644 --- a/src/boards/LoRaMote/sx1272-board.c +++ b/src/boards/LoRaMote/sx1272-board.c @@ -41,6 +41,7 @@ const struct Radio_s Radio = SX1272SetSleep, SX1272SetStby, SX1272SetRx, + SX1272StartCad, SX1272ReadRssi, SX1272Write, SX1272Read, diff --git a/src/boards/LoRaMote/timer-board.c b/src/boards/LoRaMote/timer-board.c index 61ecdc804..49dba7e87 100644 --- a/src/boards/LoRaMote/timer-board.c +++ b/src/boards/LoRaMote/timer-board.c @@ -36,8 +36,26 @@ static uint64_t TimerTickCounterContext = 0; */ volatile uint64_t TimeoutCntValue = 0; +/*! + * Increment the Hardware Timer tick counter + */ void TimerIncrementTickCounter( void ); +/*! + * Counter used for the Delay operations + */ +volatile uint32_t TimerDelayCounter = 0; + +/*! + * Retunr the value of the counter used for a Delay + */ +uint32_t TimerHwGetDelayValue( void ); + +/*! + * Increment the value of TimerDelayCounter + */ +void TimerIncrementDelayCounter( void ); + void TimerHwInit( void ) { @@ -50,8 +68,8 @@ void TimerHwInit( void ) /* --------------------------NVIC Configuration -------------------------------*/ /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); @@ -65,10 +83,39 @@ void TimerHwInit( void ) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure ); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); + TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); /* TIM2 disable counter */ TIM_Cmd( TIM2, ENABLE ); + + /* TIM3 clock enable */ + RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); + + /* --------------------------NVIC Configuration -------------------------------*/ + /* Enable the TIM3 gloabal Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init( &NVIC_InitStructure ); + + /* Time base configuration */ + TIM_TimeBaseStructure.TIM_Period = 3199; + TIM_TimeBaseStructure.TIM_Prescaler = 10; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + + /* TIM3 disable counter */ + TIM_Cmd( TIM3, DISABLE ); + + + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + } void TimerHwDeInit( void ) @@ -104,16 +151,21 @@ void TimerHwStop( void ) void TimerHwDelayMs( uint32_t delay ) { - uint64_t delayValue = 0; - uint64_t timeout = 0; + uint32_t delayValue = 0; - delayValue = delay * 1000; + delayValue = delay; - timeout = TimerHwGetTimerValue( ); + TimerDelayCounter = 0; - while( ( ( TimerHwGetTimerValue( ) - timeout ) * HW_TIMER_TIME_BASE ) < delayValue ) + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + + while( TimerHwGetDelayValue( ) < delayValue ) { } + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + TIM_Cmd( TIM3, DISABLE ); } uint64_t TimerHwGetElapsedTime( void ) @@ -134,6 +186,19 @@ uint64_t TimerHwGetTimerValue( void ) return( val ); } +uint32_t TimerHwGetDelayValue( void ) +{ + uint32_t val = 0; + + __disable_irq( ); + + val = TimerDelayCounter; + + __enable_irq( ); + + return( val ); +} + void TimerIncrementTickCounter( void ) { __disable_irq( ); @@ -143,6 +208,15 @@ void TimerIncrementTickCounter( void ) __enable_irq( ); } +void TimerIncrementDelayCounter( void ) +{ + __disable_irq( ); + + TimerDelayCounter++; + + __enable_irq( ); +} + /*! * Timer IRQ handler */ @@ -151,13 +225,24 @@ void TIM2_IRQHandler( void ) if( TIM_GetITStatus( TIM2, TIM_IT_Update ) != RESET ) { TimerIncrementTickCounter( ); + TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); if( TimerTickCounter == TimeoutCntValue ) { TimerIrqHandler( ); } - - TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); + } +} + +/*! + * Timer IRQ handler + */ +void TIM3_IRQHandler( void ) +{ + if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET ) + { + TimerIncrementDelayCounter( ); + TIM_ClearITPendingBit( TIM3, TIM_IT_Update ); } } diff --git a/src/boards/LoRaMote/uart-usb-board.c b/src/boards/LoRaMote/uart-usb-board.c index 2bb68ec92..d7ff7a35c 100644 --- a/src/boards/LoRaMote/uart-usb-board.c +++ b/src/boards/LoRaMote/uart-usb-board.c @@ -26,18 +26,14 @@ Maintainer: Miguel Luis and Gregory Cristian /*! * FIFO buffers size */ -#define FIFO_TX_SIZE 64 -#define FIFO_RX_SIZE 64 +#define FIFO_RX_SIZE 256 -uint8_t CdcTxBuffer[FIFO_TX_SIZE]; uint8_t CdcRxBuffer[FIFO_RX_SIZE]; __IO uint32_t UsbPacketTx = 1; -__IO uint8_t UsbTxBuffer[64]; -__IO uint32_t UsbTxLength; +__IO uint8_t UsbTxBuffer[VIRTUAL_COM_PORT_DATA_SIZE]; -__IO uint8_t UsbRxBuffer[64]; -__IO uint32_t UsbRxLength; +__IO uint8_t UsbRxBuffer[VIRTUAL_COM_PORT_DATA_SIZE]; void UartUsbInit( Uart_t *obj, uint8_t uartId, PinNames tx, PinNames rx ) { @@ -46,7 +42,6 @@ void UartUsbInit( Uart_t *obj, uint8_t uartId, PinNames tx, PinNames rx ) void UartUsbConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_t wordLength, StopBits_t stopBits, Parity_t parity, FlowCtrl_t flowCtrl ) { - FifoInit( &obj->FifoTx, CdcTxBuffer, FIFO_RX_SIZE ); FifoInit( &obj->FifoRx, CdcRxBuffer, FIFO_RX_SIZE ); } @@ -55,50 +50,47 @@ void UartUsbDeInit( Uart_t *obj ) } -uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data ) +uint8_t UartUsbPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size ) { - if( UsbMcuIsDeviceConfigured( ) == false ) + uint16_t idx = 0; + uint16_t usbBufferSize = VIRTUAL_COM_PORT_DATA_SIZE - 1; + + if( UsbPacketTx == 0 ) { - return 2; + return 1; // Busy } - if( IsFifoFull( &obj->FifoTx ) == false ) + while( size > usbBufferSize ) { - __disable_irq( ); - FifoPush( &obj->FifoTx, data ); - __enable_irq( ); - if( UsbPacketTx == 1 ) { - /*Sent flag*/ UsbPacketTx = 0; - SetEPTxCount( ENDP1, 0 ); + + UserToPMABufferCopy( buffer + idx, ENDP1_TXADDR, usbBufferSize ); + size -= usbBufferSize; + idx += usbBufferSize; + + SetEPTxCount( ENDP1, usbBufferSize ); SetEPTxValid( ENDP1 ); } - return 0; // OK } - return 1; // Busy -// if( UsbPacketTx == 1 ) -// { -// /*Sent flag*/ -// UsbPacketTx = 0; -// /* send packet to PMA*/ -// UserToPMABufferCopy( ( unsigned char* )&data, ENDP1_TXADDR, 1 ); -// SetEPTxCount( ENDP1, 1 ); -// SetEPTxValid( ENDP1 ); -// return 0; // OK -// } -// else -// { -// if( IsFifoFull( &obj->FifoTx ) == false ) -// { -// __disable_irq( ); -// FifoPush( &obj->FifoTx, data ); -// __enable_irq( ); -// return 0; // OK -// } -// } -// return 1; // Busy + + if( size != 0 ) + { + // Wait for previous transmission finalization + while( UsbPacketTx != 1 ); + + UsbPacketTx = 0; + UserToPMABufferCopy( buffer + idx, ENDP1_TXADDR, size ); + SetEPTxCount( ENDP1, size ); + SetEPTxValid( ENDP1 ); + } + return 0; // OK +} + +uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data ) +{ + return UartUsbPutBuffer( obj, &data, 1 ); } uint8_t UartUsbGetChar( Uart_t *obj, uint8_t *data ) @@ -121,33 +113,17 @@ uint8_t UartUsbGetChar( Uart_t *obj, uint8_t *data ) void EP1_IN_Callback (void) { UsbPacketTx = 1; - - UsbTxLength = 0; - - while( IsFifoEmpty( &UartUsb.FifoTx ) == false ) - { - UsbTxBuffer[UsbTxLength] = FifoPop( &UartUsb.FifoTx ); - UsbTxLength++; - } - - if( UsbTxLength > 0 ) - { - UsbPacketTx = 0; - UserToPMABufferCopy( ( unsigned char* )UsbTxBuffer, ENDP1_TXADDR, UsbTxLength ); - SetEPTxCount( ENDP1, UsbTxLength ); - SetEPTxValid( ENDP1 ); - - } } void EP3_OUT_Callback(void) { uint8_t i; + uint32_t size; - UsbRxLength = GetEPRxCount( ENDP3 ); - PMAToUserBufferCopy( ( unsigned char* )UsbRxBuffer, ENDP3_RXADDR, UsbRxLength ); + size = GetEPRxCount( ENDP3 ); + PMAToUserBufferCopy( ( unsigned char* )UsbRxBuffer, ENDP3_RXADDR, size ); - for( i = 0; i < UsbRxLength; i++ ) + for( i = 0; i < size; i++ ) { if( IsFifoFull( &UartUsb.FifoRx ) == false ) { diff --git a/src/boards/LoRaMote/uart-usb-board.h b/src/boards/LoRaMote/uart-usb-board.h index 9c9c28b45..d3cc961c4 100644 --- a/src/boards/LoRaMote/uart-usb-board.h +++ b/src/boards/LoRaMote/uart-usb-board.h @@ -53,6 +53,16 @@ void UartUsbDeInit( Uart_t *obj ); */ uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data ); +/*! + * \brief Sends a buffer to the UART + * + * \param [IN] obj UART object + * \param [IN] buffer Buffer to be sent + * \param [IN] size Buffer size + * \retval status [0: OK, 1: Busy, 2: Not configured] + */ +uint8_t UartUsbPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size ); + /*! * \brief Gets a character from the UART * diff --git a/src/boards/LoRaMote/usb-cdc-board.c b/src/boards/LoRaMote/usb-cdc-board.c index a68e681d9..cf4efbc5c 100644 --- a/src/boards/LoRaMote/usb-cdc-board.c +++ b/src/boards/LoRaMote/usb-cdc-board.c @@ -69,8 +69,6 @@ void UsbMcuLeaveLowPowerMode( void ) { bDeviceState = ATTACHED; } - /*Enable SystemCoreClock*/ - SystemInit( ); } void UsbMcuCableConfig( FunctionalState newState ) @@ -125,7 +123,7 @@ static void IntToUnicode( uint32_t value , uint8_t *pbuf , uint8_t len ) bool UsbMcuIsDeviceConfigured( void ) { - return bDeviceState == CONFIGURED; + return Virtual_ComPort_IsOpen( ); } void USB_LP_IRQHandler(void) diff --git a/src/boards/LoRaMote/usb/cdc/inc/usb_prop.h b/src/boards/LoRaMote/usb/cdc/inc/usb_prop.h index bd8170263..bcd1f1a2b 100644 --- a/src/boards/LoRaMote/usb/cdc/inc/usb_prop.h +++ b/src/boards/LoRaMote/usb/cdc/inc/usb_prop.h @@ -69,6 +69,7 @@ void Virtual_Com_Port_init(void); void Virtual_Com_Port_Reset(void); void Virtual_Com_Port_SetConfiguration(void); void Virtual_Com_Port_SetDeviceAddress (void); +bool Virtual_ComPort_IsOpen( void ); void Virtual_Com_Port_Status_In (void); void Virtual_Com_Port_Status_Out (void); RESULT Virtual_Com_Port_Data_Setup(uint8_t); diff --git a/src/boards/LoRaMote/usb/cdc/src/usb_prop.c b/src/boards/LoRaMote/usb/cdc/src/usb_prop.c index 25f15055b..d1a11e5b4 100644 --- a/src/boards/LoRaMote/usb/cdc/src/usb_prop.c +++ b/src/boards/LoRaMote/usb/cdc/src/usb_prop.c @@ -107,6 +107,8 @@ ONE_DESCRIPTOR String_Descriptor[4] = {(uint8_t*)Virtual_Com_Port_StringSerial, VIRTUAL_COM_PORT_SIZ_STRING_SERIAL} }; +static bool IsOpen = false; + /* Extern variables ----------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Extern function prototypes ------------------------------------------------*/ @@ -220,6 +222,18 @@ void Virtual_Com_Port_SetDeviceAddress (void) bDeviceState = ADDRESSED; } +/******************************************************************************* +* Function Name : Virtual_ComPort_IsOpen. +* Description : Indicates if the serial port is opened by the host. +* Input : None. +* Output : None. +* Return : serial port status. +*******************************************************************************/ +bool Virtual_ComPort_IsOpen( void ) +{ + return ( bDeviceState == CONFIGURED ) && ( IsOpen == true ); +} + /******************************************************************************* * Function Name : Virtual_Com_Port_Status_In. * Description : Virtual COM Port Status In Routine. @@ -303,6 +317,15 @@ RESULT Virtual_Com_Port_NoData_Setup(uint8_t RequestNo) } else if (RequestNo == SET_CONTROL_LINE_STATE) { + // Checks DTR state + if( ( pInformation->USBwValues.bw.bb0 & 0x01 ) != 0 ) + { + IsOpen = true; + } + else + { + IsOpen = false; + } return USB_SUCCESS; } } diff --git a/src/boards/LoRaMote/usb/cdc/src/usb_pwr.c b/src/boards/LoRaMote/usb/cdc/src/usb_pwr.c index 9a7c466b8..a6fa3face 100644 --- a/src/boards/LoRaMote/usb/cdc/src/usb_pwr.c +++ b/src/boards/LoRaMote/usb/cdc/src/usb_pwr.c @@ -116,100 +116,27 @@ RESULT PowerOff() *******************************************************************************/ void Suspend(void) { - uint32_t i =0; uint16_t wCNTR; - uint32_t tmpreg = 0; - __IO uint32_t savePWR_CR=0; /* suspend preparation */ /* ... */ - - /*Store CNTR value */ - wCNTR = _GetCNTR(); - /* This a sequence to apply a force RESET to handle a robustness case */ - - /*Store endpoints registers status */ - for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); - - /* unmask RESET flag */ - wCNTR|=CNTR_RESETM; - _SetCNTR(wCNTR); - - /*apply FRES */ - wCNTR|=CNTR_FRES; - _SetCNTR(wCNTR); - - /*clear FRES*/ - wCNTR&=~CNTR_FRES; - _SetCNTR(wCNTR); - - /*poll for RESET flag in ISTR*/ - while((_GetISTR()&ISTR_RESET) == 0); - - /* clear RESET flag in ISTR */ - _SetISTR((uint16_t)CLR_RESET); - - /*restore Enpoints*/ - for (i=0;i<8;i++) - _SetENDPOINT(i, EP[i]); - - /* Now it is safe to enter macrocell in suspend mode */ + /* macrocell enters suspend mode */ + wCNTR = _GetCNTR(); wCNTR |= CNTR_FSUSP; _SetCNTR(wCNTR); - + + /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ + /* power reduction */ + /* ... on connected devices */ + /* force low-power mode in the macrocell */ wCNTR = _GetCNTR(); wCNTR |= CNTR_LPMODE; _SetCNTR(wCNTR); - - /*prepare entry in low power mode (STOP mode)*/ - /* Select the regulator state in STOP mode*/ - savePWR_CR = PWR->CR; - tmpreg = PWR->CR; - /* Clear PDDS and LPDS bits */ - tmpreg &= ((uint32_t)0xFFFFFFFC); - /* Set LPDS bit according to PWR_Regulator value */ - tmpreg |= PWR_Regulator_LowPower; - /* Store the new value */ - PWR->CR = tmpreg; - /* Set SLEEPDEEP bit of Cortex System Control Register */ -#if defined (STM32F30X) || defined (STM32F37X) - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; -#else - SCB->SCR |= SCB_SCR_SLEEPDEEP; -#endif - - /* enter system in STOP mode, only when wakeup flag in not set */ - if((_GetISTR()&ISTR_WKUP)==0) - { - __WFI(); - /* Reset SLEEPDEEP bit of Cortex System Control Register */ -#if defined (STM32F30X) || defined (STM32F37X) - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); -#else - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); -#endif - } - else - { - /* Clear Wakeup flag */ - _SetISTR(CLR_WKUP); - /* clear FSUSP to abort entry in suspend mode */ - wCNTR = _GetCNTR(); - wCNTR&=~CNTR_FSUSP; - _SetCNTR(wCNTR); - - /*restore sleep mode configuration */ - /* restore Power regulator config in sleep mode*/ - PWR->CR = savePWR_CR; - - /* Reset SLEEPDEEP bit of Cortex System Control Register */ -#if defined (STM32F30X) || defined (STM32F37X) - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); -#else - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); -#endif - } + + /* switch-off the clocks */ + /* ... */ + Enter_LowPowerMode(); } /******************************************************************************* diff --git a/src/boards/SK-iM880A/board.c b/src/boards/SK-iM880A/board.c index e41352a98..25376fd0f 100644 --- a/src/boards/SK-iM880A/board.c +++ b/src/boards/SK-iM880A/board.c @@ -88,32 +88,37 @@ void BoardInitMcu( void ) SpiInit( &SX1272.Spi, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC ); SX1272IoInit( ); - BoardUnusedIoInit( ); - -#ifdef LOW_POWER_MODE_ENABLE - RtcInit( ); +#if( LOW_POWER_MODE_ENABLE ) + TimerSetLowPowerEnable( true ); #else - TimerHwInit( ); + TimerSetLowPowerEnable( false ); #endif + BoardUnusedIoInit( ); + + if( TimerGetLowPowerEnable( ) == true ) + { + RtcInit( ); + } + else + { + TimerHwInit( ); + } McuInitialized = true; } } void BoardDeInitMcu( void ) { - Gpio_t oscHseIn; - Gpio_t oscHseOut; - Gpio_t oscLseIn; - Gpio_t oscLseOut; + Gpio_t ioPin; SpiDeInit( &SX1272.Spi ); SX1272IoDeInit( ); - GpioInit( &oscHseIn, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); - GpioInit( &oscHseOut, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &ioPin, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); + GpioInit( &ioPin, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 1 ); - GpioInit( &oscLseIn, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); - GpioInit( &oscLseOut, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); + GpioInit( &ioPin, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); + GpioInit( &ioPin, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_DOWN, 1 ); McuInitialized = false; } @@ -195,14 +200,15 @@ uint8_t BoardMeasureBatterieLevel( void ) static void BoardUnusedIoInit( void ) { -#if !defined( USE_DEBUGGER ) - Gpio_t jtagTms; - Gpio_t jtagTck; - Gpio_t jtagTdi; - Gpio_t jtagTdo; - Gpio_t jtagNrst; +#if !defined( USE_USB_CDC ) || !defined( USE_DEBUGGER ) + Gpio_t ioPin; #endif + /* USB */ +#if !defined( USE_USB_CDC ) + GpioInit( &ioPin, USB_DM, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); +#endif #if defined( USE_DEBUGGER ) DBGMCU_Config( DBGMCU_SLEEP, ENABLE ); DBGMCU_Config( DBGMCU_STOP, ENABLE); @@ -212,10 +218,10 @@ static void BoardUnusedIoInit( void ) DBGMCU_Config( DBGMCU_STOP, DISABLE ); DBGMCU_Config( DBGMCU_STANDBY, DISABLE ); - GpioInit( &jtagTms, JTAG_TMS, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &jtagTck, JTAG_TCK, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &jtagTdi, JTAG_TDI, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &jtagTdo, JTAG_TDO, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &jtagNrst, JTAG_NRST, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, JTAG_TMS, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, JTAG_TCK, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, JTAG_TDI, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, JTAG_TDO, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, JTAG_NRST, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif } diff --git a/src/boards/SK-iM880A/cmsis/arm-gcc/stm32l1xx_md_flash.ld b/src/boards/SK-iM880A/cmsis/arm-gcc/stm32l1xx_md_flash.ld index 1be62d5b0..0992cefc3 100644 --- a/src/boards/SK-iM880A/cmsis/arm-gcc/stm32l1xx_md_flash.ld +++ b/src/boards/SK-iM880A/cmsis/arm-gcc/stm32l1xx_md_flash.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/SK-iM880A/gpio-board.c b/src/boards/SK-iM880A/gpio-board.c index 72802a517..f4739e11f 100644 --- a/src/boards/SK-iM880A/gpio-board.c +++ b/src/boards/SK-iM880A/gpio-board.c @@ -200,9 +200,10 @@ uint32_t GpioMcuRead( Gpio_t *obj ) void EXTI0_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line0 ) != RESET ) { if( GpioIrq[0] != NULL ) @@ -215,9 +216,10 @@ void EXTI0_IRQHandler( void ) void EXTI1_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line1 ) != RESET ) { if( GpioIrq[1] != NULL ) @@ -230,9 +232,10 @@ void EXTI1_IRQHandler( void ) void EXTI2_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line2 ) != RESET ) { if( GpioIrq[2] != NULL ) @@ -245,9 +248,10 @@ void EXTI2_IRQHandler( void ) void EXTI3_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line3 ) != RESET ) { if( GpioIrq[3] != NULL ) @@ -260,9 +264,10 @@ void EXTI3_IRQHandler( void ) void EXTI4_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line4 ) != RESET ) { if( GpioIrq[4] != NULL ) @@ -275,9 +280,10 @@ void EXTI4_IRQHandler( void ) void EXTI9_5_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line5 ) != RESET ) { if( GpioIrq[5] != NULL ) @@ -326,9 +332,10 @@ void EXTI9_5_IRQHandler( void ) void EXTI15_10_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } if( EXTI_GetITStatus( EXTI_Line10 ) != RESET ) { if( GpioIrq[10] != NULL ) diff --git a/src/boards/SK-iM880A/i2c-board.c b/src/boards/SK-iM880A/i2c-board.c index de1bdf280..cffc401da 100644 --- a/src/boards/SK-iM880A/i2c-board.c +++ b/src/boards/SK-iM880A/i2c-board.c @@ -20,6 +20,8 @@ Maintainer: Miguel Luis and Gregory Cristian */ #define TIMEOUT_MAX 0x8000 +I2cAddrSize I2cInternalAddrSize = I2C_ADDR_SIZE_8; + /*! * MCU I2C peripherals enumeration */ @@ -110,6 +112,11 @@ void I2cMcuDeInit( I2c_t *obj ) GpioInit( &obj->Sda, obj->Sda.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ) +{ + I2cInternalAddrSize = addrSize; +} + uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { uint32_t timeOut; @@ -161,7 +168,7 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -291,7 +298,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -377,7 +384,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_AcknowledgeConfig( obj->I2c, DISABLE ); /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ - (void)obj->I2c->SR2; + ( void )obj->I2c->SR2; /* Send STOP Condition */ I2C_GenerateSTOP( obj->I2c, ENABLE ); @@ -403,21 +410,20 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } else { - while( size ) + timeOut = TIMEOUT_MAX; + while( I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR ) { - /* Wait for the byte to be received */ - timeOut = TIMEOUT_MAX; - while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + if( ( timeOut-- ) == 0 ) { - if( ( timeOut-- ) == 0 ) - { - I2cResetBus( obj ); + I2cResetBus( obj ); - __enable_irq( ); - return( FAIL ); - } - } + __enable_irq( ); + return( FAIL ); + } + } + while( size ) + { if( size == 1 ) { /* Disable Acknowledgement */ @@ -427,6 +433,18 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_GenerateSTOP( obj->I2c, ENABLE ); } + timeOut = TIMEOUT_MAX; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + /* Read a byte from the device */ *buffer = I2C_ReceiveData( obj->I2c ); @@ -439,7 +457,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t /* Wait to make sure that STOP control bit has been cleared */ timeOut = TIMEOUT_MAX; - while(obj->I2c->CR1 & I2C_CR1_STOP) + while( obj->I2c->CR1 & I2C_CR1_STOP ) { if( ( timeOut-- ) == 0 ) { @@ -449,10 +467,116 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t return( FAIL ); } } - /*!< Re-Enable Acknowledgement to be ready for another reception */ - I2C_AcknowledgeConfig( obj->I2c, ENABLE ); } + /*!< Re-Enable Acknowledgement to be ready for another reception */ + I2C_AcknowledgeConfig( obj->I2c, ENABLE ); + __enable_irq( ); return( SUCCESS ); } + +/* Maximum Timeout values for flags and events waiting loops. These timeouts are + not based on accurate values, they just guarantee that the application will + not remain stuck if the I2C communication is corrupted. + You may modify these timeout values depending on CPU frequency and application + conditions (interrupts routines ...). */ +#define EE_FLAG_TIMEOUT ( ( uint32_t )0x1000 ) +#define EE_LONG_TIMEOUT ( ( uint32_t )( 10 * EE_FLAG_TIMEOUT ) ) + +/* Maximum number of trials for I2cMcuWaitStandbyState( ) function */ +#define EE_MAX_TRIALS_NUMBER 300 + +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ) +{ + uint32_t timeOut; + __IO uint16_t tmpSR1 = 0; + __IO uint32_t trials = 0; + + __disable_irq( ); + + /*!< While the bus is busy */ + timeOut = EE_LONG_TIMEOUT; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_BUSY ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + + /* Keep looping till the slave acknowledge his address or maximum number + of trials is reached (this number is defined by EE_MAX_TRIALS_NUMBER define + in eeProm.h file) */ + while( 1 ) + { + /*!< Send START condition */ + I2C_GenerateSTART( obj->I2c, ENABLE ); + + /*!< Test on EV5 and clear it */ + timeOut = EE_FLAG_TIMEOUT; + while( !I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_MODE_SELECT ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + + /*!< Send device address for write */ + I2C_Send7bitAddress( obj->I2c, deviceAddr, I2C_Direction_Transmitter ); + + /* Wait for ADDR flag to be set (Slave acknowledged his address) */ + timeOut = EE_LONG_TIMEOUT; + do + { + /* Get the current value of the SR1 register */ + tmpSR1 = obj->I2c->SR1; + + /* Update the timeout value and exit if it reach 0 */ + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + /* Keep looping till the Address is acknowledged or the AF flag is + set (address not acknowledged at time) */ + while( ( tmpSR1 & ( I2C_SR1_ADDR | I2C_SR1_AF ) ) == 0 ); + + /* Check if the ADDR flag has been set */ + if ( tmpSR1 & I2C_SR1_ADDR ) + { + /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already + been read) */ + ( void )obj->I2c->SR2; + + /*!< STOP condition */ + I2C_GenerateSTOP( obj->I2c, ENABLE ); + + /* Exit the function */ + __enable_irq( ); + return ( SUCCESS ); + } + else + { + /*!< Clear AF flag */ + I2C_ClearFlag( obj->I2c, I2C_FLAG_AF ); + } + + /* Check if the maximum allowed number of trials has bee reached */ + if ( trials++ == EE_MAX_TRIALS_NUMBER ) + { + I2cResetBus( obj ); + /* If the maximum number of trials has been reached, exit the function */ + __enable_irq( ); + return( FAIL ); + } + } +} diff --git a/src/boards/SK-iM880A/i2c-board.h b/src/boards/SK-iM880A/i2c-board.h index f09d3529e..72aae12bb 100644 --- a/src/boards/SK-iM880A/i2c-board.h +++ b/src/boards/SK-iM880A/i2c-board.h @@ -43,6 +43,15 @@ typedef enum I2C_ACK_ADD_10_BIT }I2cAckAddrMode; +/*! + * Internal device address size + */ +typedef enum +{ + I2C_ADDR_SIZE_8 = 0, + I2C_ADDR_SIZE_16, +}I2cAddrSize; + /*! * \brief Initializes the I2C object and MCU peripheral * @@ -93,4 +102,20 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ */ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); +/*! + * \brief Waits until the given device is in standby mode + * + * \param [IN] obj I2C object + * \param [IN] deviceAddr device address + */ +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ); + +/*! + * \brief Sets the internal device address size + * + * \param [IN] obj I2C object + * \param [IN] addrSize Internal address size + */ +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ); + #endif // __I2C_MCU_H__ diff --git a/src/boards/SK-iM880A/rtc-board.c b/src/boards/SK-iM880A/rtc-board.c index 938f507f5..b37da4cd0 100644 --- a/src/boards/SK-iM880A/rtc-board.c +++ b/src/boards/SK-iM880A/rtc-board.c @@ -315,28 +315,53 @@ static void RtcStartWakeUpAlarm( uint32_t timeoutValue ) timeoutValue = timeoutValue / RTC_ALARM_TIME_BASE; - rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; - rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; - rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; - rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; - - rtcAlarmSeconds = ( rtcSeconds ) % 60; - rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; - rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; - rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; - - if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) - { - if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + if( timeoutValue > 2160000 ) // 25 "days" in tick + { // drastically reduce the computation time + rtcAlarmSeconds = RTC_TimeStruct.RTC_Seconds; + rtcAlarmMinutes = RTC_TimeStruct.RTC_Minutes; + rtcAlarmHours = RTC_TimeStruct.RTC_Hours; + rtcAlarmDays = 25 + RTC_DateStruct.RTC_Date; // simply add 25 days to current date and time + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1]; + } } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1]; + } + } } else { - if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; + rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; + rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; + rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; + + rtcAlarmSeconds = ( rtcSeconds ) % 60; + rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; + rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; + rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + } + } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + } } } @@ -386,45 +411,46 @@ void RtcEnterLowPowerStopMode( void ) void RtcRecoverMcuStatus( void ) { -#ifdef LOW_POWER_MODE_ENABLE - if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) - { - // Disable IRQ while the MCU is not running on HSE - __disable_irq( ); - - /* After wake-up from STOP reconfigure the system clock */ - /* Enable HSE */ - RCC_HSEConfig( RCC_HSE_ON ); - - /* Wait till HSE is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) - {} - - /* Enable PLL */ - RCC_PLLCmd( ENABLE ); - - /* Wait till PLL is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) - {} - - /* Select PLL as system clock source */ - RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); - - /* Wait till PLL is used as system clock source */ - while( RCC_GetSYSCLKSource( ) != 0x0C ) - {} - - /* Set MCU in ULP (Ultra Low Power) */ - PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time - - /* Enable the Power Voltage Detector */ - PWR_PVDCmd( ENABLE ); + if( TimerGetLowPowerEnable( ) == true ) + { + if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) + { + // Disable IRQ while the MCU is not running on HSE + __disable_irq( ); + + /* After wake-up from STOP reconfigure the system clock */ + /* Enable HSE */ + RCC_HSEConfig( RCC_HSE_ON ); - BoardInitMcu( ); - - __enable_irq( ); + /* Wait till HSE is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) + {} + + /* Enable PLL */ + RCC_PLLCmd( ENABLE ); + + /* Wait till PLL is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) + {} + + /* Select PLL as system clock source */ + RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); + + /* Wait till PLL is used as system clock source */ + while( RCC_GetSYSCLKSource( ) != 0x0C ) + {} + + /* Set MCU in ULP (Ultra Low Power) */ + PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time + + /* Enable the Power Voltage Detector */ + PWR_PVDCmd( ENABLE ); + + BoardInitMcu( ); + + __enable_irq( ); + } } -#endif } /*! diff --git a/src/boards/SK-iM880A/sx1272-board.c b/src/boards/SK-iM880A/sx1272-board.c index edb6e2024..a49ac33a5 100644 --- a/src/boards/SK-iM880A/sx1272-board.c +++ b/src/boards/SK-iM880A/sx1272-board.c @@ -41,6 +41,7 @@ const struct Radio_s Radio = SX1272SetSleep, SX1272SetStby, SX1272SetRx, + SX1272StartCad, SX1272ReadRssi, SX1272Write, SX1272Read, diff --git a/src/boards/SK-iM880A/timer-board.c b/src/boards/SK-iM880A/timer-board.c index 61ecdc804..49dba7e87 100644 --- a/src/boards/SK-iM880A/timer-board.c +++ b/src/boards/SK-iM880A/timer-board.c @@ -36,8 +36,26 @@ static uint64_t TimerTickCounterContext = 0; */ volatile uint64_t TimeoutCntValue = 0; +/*! + * Increment the Hardware Timer tick counter + */ void TimerIncrementTickCounter( void ); +/*! + * Counter used for the Delay operations + */ +volatile uint32_t TimerDelayCounter = 0; + +/*! + * Retunr the value of the counter used for a Delay + */ +uint32_t TimerHwGetDelayValue( void ); + +/*! + * Increment the value of TimerDelayCounter + */ +void TimerIncrementDelayCounter( void ); + void TimerHwInit( void ) { @@ -50,8 +68,8 @@ void TimerHwInit( void ) /* --------------------------NVIC Configuration -------------------------------*/ /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); @@ -65,10 +83,39 @@ void TimerHwInit( void ) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure ); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); + TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); /* TIM2 disable counter */ TIM_Cmd( TIM2, ENABLE ); + + /* TIM3 clock enable */ + RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); + + /* --------------------------NVIC Configuration -------------------------------*/ + /* Enable the TIM3 gloabal Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init( &NVIC_InitStructure ); + + /* Time base configuration */ + TIM_TimeBaseStructure.TIM_Period = 3199; + TIM_TimeBaseStructure.TIM_Prescaler = 10; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + + /* TIM3 disable counter */ + TIM_Cmd( TIM3, DISABLE ); + + + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + } void TimerHwDeInit( void ) @@ -104,16 +151,21 @@ void TimerHwStop( void ) void TimerHwDelayMs( uint32_t delay ) { - uint64_t delayValue = 0; - uint64_t timeout = 0; + uint32_t delayValue = 0; - delayValue = delay * 1000; + delayValue = delay; - timeout = TimerHwGetTimerValue( ); + TimerDelayCounter = 0; - while( ( ( TimerHwGetTimerValue( ) - timeout ) * HW_TIMER_TIME_BASE ) < delayValue ) + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + + while( TimerHwGetDelayValue( ) < delayValue ) { } + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + TIM_Cmd( TIM3, DISABLE ); } uint64_t TimerHwGetElapsedTime( void ) @@ -134,6 +186,19 @@ uint64_t TimerHwGetTimerValue( void ) return( val ); } +uint32_t TimerHwGetDelayValue( void ) +{ + uint32_t val = 0; + + __disable_irq( ); + + val = TimerDelayCounter; + + __enable_irq( ); + + return( val ); +} + void TimerIncrementTickCounter( void ) { __disable_irq( ); @@ -143,6 +208,15 @@ void TimerIncrementTickCounter( void ) __enable_irq( ); } +void TimerIncrementDelayCounter( void ) +{ + __disable_irq( ); + + TimerDelayCounter++; + + __enable_irq( ); +} + /*! * Timer IRQ handler */ @@ -151,13 +225,24 @@ void TIM2_IRQHandler( void ) if( TIM_GetITStatus( TIM2, TIM_IT_Update ) != RESET ) { TimerIncrementTickCounter( ); + TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); if( TimerTickCounter == TimeoutCntValue ) { TimerIrqHandler( ); } - - TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); + } +} + +/*! + * Timer IRQ handler + */ +void TIM3_IRQHandler( void ) +{ + if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET ) + { + TimerIncrementDelayCounter( ); + TIM_ClearITPendingBit( TIM3, TIM_IT_Update ); } } diff --git a/src/boards/SensorNode/board.c b/src/boards/SensorNode/board.c index 53e8d88dc..0b529f14b 100644 --- a/src/boards/SensorNode/board.c +++ b/src/boards/SensorNode/board.c @@ -87,13 +87,13 @@ void BoardInitPeriph( void ) GpioInit( &Led3, LED_3, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &Led4, LED_4, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - // Init Temperature, pressure and altitude sensor + // Init temperature, pressure and altitude sensor MPL3115Init( ); - // Init Accelerometer + // Init accelerometer MMA8451Init( ); - // Init Magnetometer + // Init magnetometer MAG3110Init( ); // Init SAR @@ -124,48 +124,67 @@ void BoardInitMcu( void ) // Disable Systick SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; // Systick IRQ off SCB->ICSR |= SCB_ICSR_PENDSTCLR_Msk; // Clear SysTick Exception pending flag - + I2cInit( &I2c, I2C_SCL, I2C_SDA ); - + SpiInit( &SX1276.Spi, RADIO_MOSI, RADIO_MISO, RADIO_SCLK, NC ); SX1276IoInit( ); - BoardUnusedIoInit( ); #if defined( USE_USB_CDC ) - UsbMcuInit( ); - UartInit( &UartUsb, UART_USB_CDC, NC, NC ); - UartConfig( &UartUsb, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL ); + { + Gpio_t usbDM; + + GpioInit( &usbDM, USB_DM, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); + + if( GpioRead( &usbDM ) == 0 ) + { + TimerSetLowPowerEnable( false ); + UsbMcuInit( ); + UartInit( &UartUsb, UART_USB_CDC, NC, NC ); + UartConfig( &UartUsb, RX_TX, 115200, UART_8_BIT, UART_1_STOP_BIT, NO_PARITY, NO_FLOW_CTRL ); + } + else + { + TimerSetLowPowerEnable( true ); + GpioInit( &usbDM, USB_DM, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + } + } +#elif( LOW_POWER_MODE_ENABLE ) + TimerSetLowPowerEnable( true ); +#else + TimerSetLowPowerEnable( false ); #endif + BoardUnusedIoInit( ); GpioInit( &UsbDetect, USB_ON, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &BatVal, BAT_LEVEL, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); -#ifdef LOW_POWER_MODE_ENABLE - RtcInit( ); -#else - TimerHwInit( ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcInit( ); + } + else + { + TimerHwInit( ); + } McuInitialized = true; } } void BoardDeInitMcu( void ) { - Gpio_t oscHseIn; - Gpio_t oscHseOut; - Gpio_t oscLseIn; - Gpio_t oscLseOut; + Gpio_t ioPin; I2cDeInit( &I2c ); SpiDeInit( &SX1276.Spi ); SX1276IoDeInit( ); - GpioInit( &oscHseIn, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &oscHseOut, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, OSC_HSE_IN, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, OSC_HSE_OUT, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &oscLseIn, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &oscLseOut, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, OSC_LSE_IN, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, OSC_LSE_OUT, PIN_INPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); GpioInit( &UsbDetect, USB_ON, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); @@ -268,7 +287,7 @@ static void BoardUnusedIoInit( void ) /* USB */ #if !defined( USE_USB_CDC ) GpioInit( &ioPin, USB_DM, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); - GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); + GpioInit( &ioPin, USB_DP, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); #endif GpioInit( &ioPin, TEST_POINT1, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); diff --git a/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash.ld b/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash.ld index 1be62d5b0..0992cefc3 100644 --- a/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash.ld +++ b/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld b/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld index f8fc2a20f..8e7d712a7 100644 --- a/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld +++ b/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_bootloader.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 12K + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 12K - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld b/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld index 865fc0291..9dfc28485 100644 --- a/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld +++ b/src/boards/SensorNode/cmsis/arm-gcc/stm32l1xx_md_flash_offset.ld @@ -1,171 +1,131 @@ -/* -***************************************************************************** -** -** File : stm32_flash.ld -** -** Abstract : Linker script for stm32l1xx_md Device with -** 128KByte FLASH, 16KByte RAM -** -** Set heap size, stack size and stack location according -** to application requirements. -** -** Set memory bank area and size if external memory is used. -** -** Target : STMicroelectronics STM32 -** -** Environment : Atollic TrueSTUDIO(R) -** -** Distribution: The file is distributed “as is,” without any warranty -** of any kind. -** -** (c)Copyright Atollic AB. -** You may use this file as-is or modify it according to the needs of your -** project. Distribution of this file (unmodified or modified) is not -** permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the -** rights to distribute the assembled, compiled & linked contents of this -** file as part of an application binary file, provided that it is built -** using the Atollic TrueSTUDIO(R) toolchain. -** -***************************************************************************** -*/ +/* Memory regions.*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08003000, LENGTH = 128K - 0x3000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} /* Entry Point */ ENTRY(Reset_Handler) -/* Highest address of the user mode stack */ -_estack = 0x20004000; /* end of 16K RAM */ - -/* Generate a link error if heap and stack don't fit into RAM */ -_Min_Heap_Size = 0; /* required amount of heap */ -_Min_Stack_Size = 0x80; /* required amount of stack */ - -/* Specify the memory areas */ -MEMORY -{ - FLASH (rx) : ORIGIN = 0x08003000, LENGTH = 128K - 0x3000 - RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K - MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K -} +_estack = 0x20000000 + 16K; /* Define output sections */ SECTIONS { - /* The startup code goes first into FLASH */ - .isr_vector : - { - . = ALIGN(4); - KEEP(*(.isr_vector)) /* Startup code */ - . = ALIGN(4); - } >FLASH - - /* The program code and other data goes into FLASH */ - .text : - { - . = ALIGN(4); - *(.text) /* .text sections (code) */ - *(.text*) /* .text* sections (code) */ - *(.rodata) /* .rodata sections (constants, strings, etc.) */ - *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ - *(.glue_7) /* glue arm to thumb code */ - *(.glue_7t) /* glue thumb to arm code */ - *(.eh_frame) - - KEEP (*(.init)) - KEEP (*(.fini)) - - . = ALIGN(4); - _etext = .; /* define a global symbols at end of code */ - } >FLASH - - - .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH - .ARM : { - __exidx_start = .; - *(.ARM.exidx*) - __exidx_end = .; - } >FLASH - - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array*)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } >FLASH - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT(.init_array.*))) - KEEP (*(.init_array*)) - PROVIDE_HIDDEN (__init_array_end = .); - } >FLASH - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(.fini_array*)) - KEEP (*(SORT(.fini_array.*))) - PROVIDE_HIDDEN (__fini_array_end = .); - } >FLASH - - /* used by the startup to initialize data */ - _sidata = .; - - /* Initialized data sections goes into RAM, load LMA copy after code */ - .data : AT ( _sidata ) - { - . = ALIGN(4); - _sdata = .; /* create a global symbol at data start */ - *(.data) /* .data sections */ - *(.data*) /* .data* sections */ - - . = ALIGN(4); - _edata = .; /* define a global symbol at data end */ - } >RAM - - /* Uninitialized data section */ - . = ALIGN(4); - .bss : - { - /* This is used by the startup in order to initialize the .bss secion */ - _sbss = .; /* define a global symbol at bss start */ - __bss_start__ = _sbss; - *(.bss) - *(.bss*) - *(COMMON) - - . = ALIGN(4); - _ebss = .; /* define a global symbol at bss end */ - __bss_end__ = _ebss; - } >RAM - - PROVIDE ( end = _ebss ); - PROVIDE ( _end = _ebss ); - - /* User_heap_stack section, used to check that there is enough RAM left */ - ._user_heap_stack : - { - . = ALIGN(4); - . = . + _Min_Heap_Size; - . = . + _Min_Stack_Size; - . = ALIGN(4); - } >RAM - - /* MEMORY_bank1 section, code must be located here explicitly */ - /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ - .memory_b1_text : - { - *(.mb1text) /* .mb1text sections (code) */ - *(.mb1text*) /* .mb1text* sections (code) */ - *(.mb1rodata) /* read-only data (constants) */ - *(.mb1rodata*) - } >MEMORY_B1 - - /* Remove information from the standard libraries */ - /DISCARD/ : - { - libc.a ( * ) - libm.a ( * ) - libgcc.a ( * ) - } - - .ARM.attributes 0 : { *(.ARM.attributes) } + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + __etext = .; + + /* used by the startup to initialize data */ + _sidata = __etext; + + .data : AT (__etext) + { + __data_start__ = .; + _sdata = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + _edata = .; + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + _sbss = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + _ebss = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(_end = .); + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") } diff --git a/src/boards/SensorNode/gpio-board.c b/src/boards/SensorNode/gpio-board.c index 72802a517..324429404 100644 --- a/src/boards/SensorNode/gpio-board.c +++ b/src/boards/SensorNode/gpio-board.c @@ -200,8 +200,11 @@ uint32_t GpioMcuRead( Gpio_t *obj ) void EXTI0_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line0 ) != RESET ) { @@ -215,8 +218,11 @@ void EXTI0_IRQHandler( void ) void EXTI1_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line1 ) != RESET ) { @@ -230,8 +236,11 @@ void EXTI1_IRQHandler( void ) void EXTI2_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line2 ) != RESET ) { @@ -245,8 +254,11 @@ void EXTI2_IRQHandler( void ) void EXTI3_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line3 ) != RESET ) { @@ -260,8 +272,11 @@ void EXTI3_IRQHandler( void ) void EXTI4_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line4 ) != RESET ) { @@ -275,8 +290,11 @@ void EXTI4_IRQHandler( void ) void EXTI9_5_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line5 ) != RESET ) { @@ -326,8 +344,11 @@ void EXTI9_5_IRQHandler( void ) void EXTI15_10_IRQHandler( void ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcRecoverMcuStatus( ); +#if !defined( USE_NO_TIMER ) + if( TimerGetLowPowerEnable( ) == true ) + { + RtcRecoverMcuStatus( ); + } #endif if( EXTI_GetITStatus( EXTI_Line10 ) != RESET ) { diff --git a/src/boards/SensorNode/i2c-board.c b/src/boards/SensorNode/i2c-board.c index de1bdf280..cffc401da 100644 --- a/src/boards/SensorNode/i2c-board.c +++ b/src/boards/SensorNode/i2c-board.c @@ -20,6 +20,8 @@ Maintainer: Miguel Luis and Gregory Cristian */ #define TIMEOUT_MAX 0x8000 +I2cAddrSize I2cInternalAddrSize = I2C_ADDR_SIZE_8; + /*! * MCU I2C peripherals enumeration */ @@ -110,6 +112,11 @@ void I2cMcuDeInit( I2c_t *obj ) GpioInit( &obj->Sda, obj->Sda.pin, PIN_ANALOGIC, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); } +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ) +{ + I2cInternalAddrSize = addrSize; +} + uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { uint32_t timeOut; @@ -161,7 +168,7 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -291,7 +298,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } } - if( ( addr & 0xFF00 ) != 0x0000 ) + if( I2cInternalAddrSize == I2C_ADDR_SIZE_16 ) { /* Send the device's internal address MSB to write to */ I2C_SendData( obj->I2c, ( uint8_t )( ( addr & 0xFF00 ) >> 8 ) ); @@ -377,7 +384,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_AcknowledgeConfig( obj->I2c, DISABLE ); /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */ - (void)obj->I2c->SR2; + ( void )obj->I2c->SR2; /* Send STOP Condition */ I2C_GenerateSTOP( obj->I2c, ENABLE ); @@ -403,21 +410,20 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t } else { - while( size ) + timeOut = TIMEOUT_MAX; + while( I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ) == ERROR ) { - /* Wait for the byte to be received */ - timeOut = TIMEOUT_MAX; - while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + if( ( timeOut-- ) == 0 ) { - if( ( timeOut-- ) == 0 ) - { - I2cResetBus( obj ); + I2cResetBus( obj ); - __enable_irq( ); - return( FAIL ); - } - } + __enable_irq( ); + return( FAIL ); + } + } + while( size ) + { if( size == 1 ) { /* Disable Acknowledgement */ @@ -427,6 +433,18 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t I2C_GenerateSTOP( obj->I2c, ENABLE ); } + timeOut = TIMEOUT_MAX; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_RXNE ) == RESET ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + /* Read a byte from the device */ *buffer = I2C_ReceiveData( obj->I2c ); @@ -439,7 +457,7 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t /* Wait to make sure that STOP control bit has been cleared */ timeOut = TIMEOUT_MAX; - while(obj->I2c->CR1 & I2C_CR1_STOP) + while( obj->I2c->CR1 & I2C_CR1_STOP ) { if( ( timeOut-- ) == 0 ) { @@ -449,10 +467,116 @@ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t return( FAIL ); } } - /*!< Re-Enable Acknowledgement to be ready for another reception */ - I2C_AcknowledgeConfig( obj->I2c, ENABLE ); } + /*!< Re-Enable Acknowledgement to be ready for another reception */ + I2C_AcknowledgeConfig( obj->I2c, ENABLE ); + __enable_irq( ); return( SUCCESS ); } + +/* Maximum Timeout values for flags and events waiting loops. These timeouts are + not based on accurate values, they just guarantee that the application will + not remain stuck if the I2C communication is corrupted. + You may modify these timeout values depending on CPU frequency and application + conditions (interrupts routines ...). */ +#define EE_FLAG_TIMEOUT ( ( uint32_t )0x1000 ) +#define EE_LONG_TIMEOUT ( ( uint32_t )( 10 * EE_FLAG_TIMEOUT ) ) + +/* Maximum number of trials for I2cMcuWaitStandbyState( ) function */ +#define EE_MAX_TRIALS_NUMBER 300 + +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ) +{ + uint32_t timeOut; + __IO uint16_t tmpSR1 = 0; + __IO uint32_t trials = 0; + + __disable_irq( ); + + /*!< While the bus is busy */ + timeOut = EE_LONG_TIMEOUT; + while( I2C_GetFlagStatus( obj->I2c, I2C_FLAG_BUSY ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + + /* Keep looping till the slave acknowledge his address or maximum number + of trials is reached (this number is defined by EE_MAX_TRIALS_NUMBER define + in eeProm.h file) */ + while( 1 ) + { + /*!< Send START condition */ + I2C_GenerateSTART( obj->I2c, ENABLE ); + + /*!< Test on EV5 and clear it */ + timeOut = EE_FLAG_TIMEOUT; + while( !I2C_CheckEvent( obj->I2c, I2C_EVENT_MASTER_MODE_SELECT ) ) + { + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + + __enable_irq( ); + return( FAIL ); + } + } + + /*!< Send device address for write */ + I2C_Send7bitAddress( obj->I2c, deviceAddr, I2C_Direction_Transmitter ); + + /* Wait for ADDR flag to be set (Slave acknowledged his address) */ + timeOut = EE_LONG_TIMEOUT; + do + { + /* Get the current value of the SR1 register */ + tmpSR1 = obj->I2c->SR1; + + /* Update the timeout value and exit if it reach 0 */ + if( ( timeOut-- ) == 0 ) + { + I2cResetBus( obj ); + __enable_irq( ); + return( FAIL ); + } + } + /* Keep looping till the Address is acknowledged or the AF flag is + set (address not acknowledged at time) */ + while( ( tmpSR1 & ( I2C_SR1_ADDR | I2C_SR1_AF ) ) == 0 ); + + /* Check if the ADDR flag has been set */ + if ( tmpSR1 & I2C_SR1_ADDR ) + { + /* Clear ADDR Flag by reading SR1 then SR2 registers (SR1 have already + been read) */ + ( void )obj->I2c->SR2; + + /*!< STOP condition */ + I2C_GenerateSTOP( obj->I2c, ENABLE ); + + /* Exit the function */ + __enable_irq( ); + return ( SUCCESS ); + } + else + { + /*!< Clear AF flag */ + I2C_ClearFlag( obj->I2c, I2C_FLAG_AF ); + } + + /* Check if the maximum allowed number of trials has bee reached */ + if ( trials++ == EE_MAX_TRIALS_NUMBER ) + { + I2cResetBus( obj ); + /* If the maximum number of trials has been reached, exit the function */ + __enable_irq( ); + return( FAIL ); + } + } +} diff --git a/src/boards/SensorNode/i2c-board.h b/src/boards/SensorNode/i2c-board.h index f09d3529e..72aae12bb 100644 --- a/src/boards/SensorNode/i2c-board.h +++ b/src/boards/SensorNode/i2c-board.h @@ -43,6 +43,15 @@ typedef enum I2C_ACK_ADD_10_BIT }I2cAckAddrMode; +/*! + * Internal device address size + */ +typedef enum +{ + I2C_ADDR_SIZE_8 = 0, + I2C_ADDR_SIZE_16, +}I2cAddrSize; + /*! * \brief Initializes the I2C object and MCU peripheral * @@ -93,4 +102,20 @@ uint8_t I2cMcuWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_ */ uint8_t I2cMcuReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); +/*! + * \brief Waits until the given device is in standby mode + * + * \param [IN] obj I2C object + * \param [IN] deviceAddr device address + */ +uint8_t I2cMcuWaitStandbyState( I2c_t *obj, uint8_t deviceAddr ); + +/*! + * \brief Sets the internal device address size + * + * \param [IN] obj I2C object + * \param [IN] addrSize Internal address size + */ +void I2cSetAddrSize( I2c_t *obj, I2cAddrSize addrSize ); + #endif // __I2C_MCU_H__ diff --git a/src/boards/SensorNode/rtc-board.c b/src/boards/SensorNode/rtc-board.c index 938f507f5..b37da4cd0 100644 --- a/src/boards/SensorNode/rtc-board.c +++ b/src/boards/SensorNode/rtc-board.c @@ -315,28 +315,53 @@ static void RtcStartWakeUpAlarm( uint32_t timeoutValue ) timeoutValue = timeoutValue / RTC_ALARM_TIME_BASE; - rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; - rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; - rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; - rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; - - rtcAlarmSeconds = ( rtcSeconds ) % 60; - rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; - rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; - rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; - - if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) - { - if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + if( timeoutValue > 2160000 ) // 25 "days" in tick + { // drastically reduce the computation time + rtcAlarmSeconds = RTC_TimeStruct.RTC_Seconds; + rtcAlarmMinutes = RTC_TimeStruct.RTC_Minutes; + rtcAlarmHours = RTC_TimeStruct.RTC_Hours; + rtcAlarmDays = 25 + RTC_DateStruct.RTC_Date; // simply add 25 days to current date and time + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1]; + } } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1]; + } + } } else { - if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) - { - rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + rtcSeconds = ( timeoutValue % SecondsInMinute ) + RTC_TimeStruct.RTC_Seconds; + rtcMinutes = ( ( timeoutValue / SecondsInMinute ) % SecondsInMinute ) + RTC_TimeStruct.RTC_Minutes; + rtcHours = ( ( timeoutValue / SecondsInHour ) % HoursInDay ) + RTC_TimeStruct.RTC_Hours; + rtcDays = ( timeoutValue / SecondsInDay ) + RTC_DateStruct.RTC_Date; + + rtcAlarmSeconds = ( rtcSeconds ) % 60; + rtcAlarmMinutes = ( ( rtcSeconds / 60 ) + rtcMinutes ) % 60; + rtcAlarmHours = ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) % 24; + rtcAlarmDays = ( ( ( ( ( rtcSeconds / 60 ) + rtcMinutes ) / 60 ) + rtcHours ) / 24 ) + rtcDays; + + if( ( RTC_DateStruct.RTC_Year == 0 ) || ( RTC_DateStruct.RTC_Year % 4 == 0 ) ) + { + if( rtcAlarmDays > DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonthLeapYear[ RTC_DateStruct.RTC_Month - 1 ]; + } + } + else + { + if( rtcAlarmDays > DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ] ) + { + rtcAlarmDays = rtcAlarmDays % DaysInMonth[ RTC_DateStruct.RTC_Month - 1 ]; + } } } @@ -386,45 +411,46 @@ void RtcEnterLowPowerStopMode( void ) void RtcRecoverMcuStatus( void ) { -#ifdef LOW_POWER_MODE_ENABLE - if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) - { - // Disable IRQ while the MCU is not running on HSE - __disable_irq( ); - - /* After wake-up from STOP reconfigure the system clock */ - /* Enable HSE */ - RCC_HSEConfig( RCC_HSE_ON ); - - /* Wait till HSE is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) - {} - - /* Enable PLL */ - RCC_PLLCmd( ENABLE ); - - /* Wait till PLL is ready */ - while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) - {} - - /* Select PLL as system clock source */ - RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); - - /* Wait till PLL is used as system clock source */ - while( RCC_GetSYSCLKSource( ) != 0x0C ) - {} - - /* Set MCU in ULP (Ultra Low Power) */ - PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time - - /* Enable the Power Voltage Detector */ - PWR_PVDCmd( ENABLE ); + if( TimerGetLowPowerEnable( ) == true ) + { + if( ( LowPowerDisableDuringTask == false ) && ( RtcTimerEventAllowsLowPower == true ) ) + { + // Disable IRQ while the MCU is not running on HSE + __disable_irq( ); + + /* After wake-up from STOP reconfigure the system clock */ + /* Enable HSE */ + RCC_HSEConfig( RCC_HSE_ON ); - BoardInitMcu( ); - - __enable_irq( ); + /* Wait till HSE is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_HSERDY ) == RESET ) + {} + + /* Enable PLL */ + RCC_PLLCmd( ENABLE ); + + /* Wait till PLL is ready */ + while( RCC_GetFlagStatus( RCC_FLAG_PLLRDY ) == RESET ) + {} + + /* Select PLL as system clock source */ + RCC_SYSCLKConfig( RCC_SYSCLKSource_PLLCLK ); + + /* Wait till PLL is used as system clock source */ + while( RCC_GetSYSCLKSource( ) != 0x0C ) + {} + + /* Set MCU in ULP (Ultra Low Power) */ + PWR_UltraLowPowerCmd( DISABLE ); // add up to 3ms wakeup time + + /* Enable the Power Voltage Detector */ + PWR_PVDCmd( ENABLE ); + + BoardInitMcu( ); + + __enable_irq( ); + } } -#endif } /*! diff --git a/src/boards/SensorNode/sx1276-board.c b/src/boards/SensorNode/sx1276-board.c index 63de934de..112e37819 100644 --- a/src/boards/SensorNode/sx1276-board.c +++ b/src/boards/SensorNode/sx1276-board.c @@ -41,6 +41,7 @@ const struct Radio_s Radio = SX1276SetSleep, SX1276SetStby, SX1276SetRx, + SX1276StartCad, SX1276ReadRssi, SX1276Write, SX1276Read, diff --git a/src/boards/SensorNode/timer-board.c b/src/boards/SensorNode/timer-board.c index 61ecdc804..49dba7e87 100644 --- a/src/boards/SensorNode/timer-board.c +++ b/src/boards/SensorNode/timer-board.c @@ -36,8 +36,26 @@ static uint64_t TimerTickCounterContext = 0; */ volatile uint64_t TimeoutCntValue = 0; +/*! + * Increment the Hardware Timer tick counter + */ void TimerIncrementTickCounter( void ); +/*! + * Counter used for the Delay operations + */ +volatile uint32_t TimerDelayCounter = 0; + +/*! + * Retunr the value of the counter used for a Delay + */ +uint32_t TimerHwGetDelayValue( void ); + +/*! + * Increment the value of TimerDelayCounter + */ +void TimerIncrementDelayCounter( void ); + void TimerHwInit( void ) { @@ -50,8 +68,8 @@ void TimerHwInit( void ) /* --------------------------NVIC Configuration -------------------------------*/ /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; - NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; - NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init( &NVIC_InitStructure ); @@ -65,10 +83,39 @@ void TimerHwInit( void ) TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit( TIM2, &TIM_TimeBaseStructure ); - TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE ); + TIM_ITConfig( TIM2, TIM_IT_Update, ENABLE ); /* TIM2 disable counter */ TIM_Cmd( TIM2, ENABLE ); + + /* TIM3 clock enable */ + RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); + + /* --------------------------NVIC Configuration -------------------------------*/ + /* Enable the TIM3 gloabal Interrupt */ + NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + + NVIC_Init( &NVIC_InitStructure ); + + /* Time base configuration */ + TIM_TimeBaseStructure.TIM_Period = 3199; + TIM_TimeBaseStructure.TIM_Prescaler = 10; + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseInit( TIM3, &TIM_TimeBaseStructure ); + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + + /* TIM3 disable counter */ + TIM_Cmd( TIM3, DISABLE ); + + + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + } void TimerHwDeInit( void ) @@ -104,16 +151,21 @@ void TimerHwStop( void ) void TimerHwDelayMs( uint32_t delay ) { - uint64_t delayValue = 0; - uint64_t timeout = 0; + uint32_t delayValue = 0; - delayValue = delay * 1000; + delayValue = delay; - timeout = TimerHwGetTimerValue( ); + TimerDelayCounter = 0; - while( ( ( TimerHwGetTimerValue( ) - timeout ) * HW_TIMER_TIME_BASE ) < delayValue ) + TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE ); + TIM_Cmd( TIM3, ENABLE ); + + while( TimerHwGetDelayValue( ) < delayValue ) { } + + TIM_ITConfig( TIM3, TIM_IT_Update, DISABLE ); + TIM_Cmd( TIM3, DISABLE ); } uint64_t TimerHwGetElapsedTime( void ) @@ -134,6 +186,19 @@ uint64_t TimerHwGetTimerValue( void ) return( val ); } +uint32_t TimerHwGetDelayValue( void ) +{ + uint32_t val = 0; + + __disable_irq( ); + + val = TimerDelayCounter; + + __enable_irq( ); + + return( val ); +} + void TimerIncrementTickCounter( void ) { __disable_irq( ); @@ -143,6 +208,15 @@ void TimerIncrementTickCounter( void ) __enable_irq( ); } +void TimerIncrementDelayCounter( void ) +{ + __disable_irq( ); + + TimerDelayCounter++; + + __enable_irq( ); +} + /*! * Timer IRQ handler */ @@ -151,13 +225,24 @@ void TIM2_IRQHandler( void ) if( TIM_GetITStatus( TIM2, TIM_IT_Update ) != RESET ) { TimerIncrementTickCounter( ); + TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); if( TimerTickCounter == TimeoutCntValue ) { TimerIrqHandler( ); } - - TIM_ClearITPendingBit( TIM2, TIM_IT_Update ); + } +} + +/*! + * Timer IRQ handler + */ +void TIM3_IRQHandler( void ) +{ + if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET ) + { + TimerIncrementDelayCounter( ); + TIM_ClearITPendingBit( TIM3, TIM_IT_Update ); } } diff --git a/src/boards/SensorNode/uart-usb-board.c b/src/boards/SensorNode/uart-usb-board.c index 2bb68ec92..d7ff7a35c 100644 --- a/src/boards/SensorNode/uart-usb-board.c +++ b/src/boards/SensorNode/uart-usb-board.c @@ -26,18 +26,14 @@ Maintainer: Miguel Luis and Gregory Cristian /*! * FIFO buffers size */ -#define FIFO_TX_SIZE 64 -#define FIFO_RX_SIZE 64 +#define FIFO_RX_SIZE 256 -uint8_t CdcTxBuffer[FIFO_TX_SIZE]; uint8_t CdcRxBuffer[FIFO_RX_SIZE]; __IO uint32_t UsbPacketTx = 1; -__IO uint8_t UsbTxBuffer[64]; -__IO uint32_t UsbTxLength; +__IO uint8_t UsbTxBuffer[VIRTUAL_COM_PORT_DATA_SIZE]; -__IO uint8_t UsbRxBuffer[64]; -__IO uint32_t UsbRxLength; +__IO uint8_t UsbRxBuffer[VIRTUAL_COM_PORT_DATA_SIZE]; void UartUsbInit( Uart_t *obj, uint8_t uartId, PinNames tx, PinNames rx ) { @@ -46,7 +42,6 @@ void UartUsbInit( Uart_t *obj, uint8_t uartId, PinNames tx, PinNames rx ) void UartUsbConfig( Uart_t *obj, UartMode_t mode, uint32_t baudrate, WordLength_t wordLength, StopBits_t stopBits, Parity_t parity, FlowCtrl_t flowCtrl ) { - FifoInit( &obj->FifoTx, CdcTxBuffer, FIFO_RX_SIZE ); FifoInit( &obj->FifoRx, CdcRxBuffer, FIFO_RX_SIZE ); } @@ -55,50 +50,47 @@ void UartUsbDeInit( Uart_t *obj ) } -uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data ) +uint8_t UartUsbPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size ) { - if( UsbMcuIsDeviceConfigured( ) == false ) + uint16_t idx = 0; + uint16_t usbBufferSize = VIRTUAL_COM_PORT_DATA_SIZE - 1; + + if( UsbPacketTx == 0 ) { - return 2; + return 1; // Busy } - if( IsFifoFull( &obj->FifoTx ) == false ) + while( size > usbBufferSize ) { - __disable_irq( ); - FifoPush( &obj->FifoTx, data ); - __enable_irq( ); - if( UsbPacketTx == 1 ) { - /*Sent flag*/ UsbPacketTx = 0; - SetEPTxCount( ENDP1, 0 ); + + UserToPMABufferCopy( buffer + idx, ENDP1_TXADDR, usbBufferSize ); + size -= usbBufferSize; + idx += usbBufferSize; + + SetEPTxCount( ENDP1, usbBufferSize ); SetEPTxValid( ENDP1 ); } - return 0; // OK } - return 1; // Busy -// if( UsbPacketTx == 1 ) -// { -// /*Sent flag*/ -// UsbPacketTx = 0; -// /* send packet to PMA*/ -// UserToPMABufferCopy( ( unsigned char* )&data, ENDP1_TXADDR, 1 ); -// SetEPTxCount( ENDP1, 1 ); -// SetEPTxValid( ENDP1 ); -// return 0; // OK -// } -// else -// { -// if( IsFifoFull( &obj->FifoTx ) == false ) -// { -// __disable_irq( ); -// FifoPush( &obj->FifoTx, data ); -// __enable_irq( ); -// return 0; // OK -// } -// } -// return 1; // Busy + + if( size != 0 ) + { + // Wait for previous transmission finalization + while( UsbPacketTx != 1 ); + + UsbPacketTx = 0; + UserToPMABufferCopy( buffer + idx, ENDP1_TXADDR, size ); + SetEPTxCount( ENDP1, size ); + SetEPTxValid( ENDP1 ); + } + return 0; // OK +} + +uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data ) +{ + return UartUsbPutBuffer( obj, &data, 1 ); } uint8_t UartUsbGetChar( Uart_t *obj, uint8_t *data ) @@ -121,33 +113,17 @@ uint8_t UartUsbGetChar( Uart_t *obj, uint8_t *data ) void EP1_IN_Callback (void) { UsbPacketTx = 1; - - UsbTxLength = 0; - - while( IsFifoEmpty( &UartUsb.FifoTx ) == false ) - { - UsbTxBuffer[UsbTxLength] = FifoPop( &UartUsb.FifoTx ); - UsbTxLength++; - } - - if( UsbTxLength > 0 ) - { - UsbPacketTx = 0; - UserToPMABufferCopy( ( unsigned char* )UsbTxBuffer, ENDP1_TXADDR, UsbTxLength ); - SetEPTxCount( ENDP1, UsbTxLength ); - SetEPTxValid( ENDP1 ); - - } } void EP3_OUT_Callback(void) { uint8_t i; + uint32_t size; - UsbRxLength = GetEPRxCount( ENDP3 ); - PMAToUserBufferCopy( ( unsigned char* )UsbRxBuffer, ENDP3_RXADDR, UsbRxLength ); + size = GetEPRxCount( ENDP3 ); + PMAToUserBufferCopy( ( unsigned char* )UsbRxBuffer, ENDP3_RXADDR, size ); - for( i = 0; i < UsbRxLength; i++ ) + for( i = 0; i < size; i++ ) { if( IsFifoFull( &UartUsb.FifoRx ) == false ) { diff --git a/src/boards/SensorNode/uart-usb-board.h b/src/boards/SensorNode/uart-usb-board.h index 9c9c28b45..d3cc961c4 100644 --- a/src/boards/SensorNode/uart-usb-board.h +++ b/src/boards/SensorNode/uart-usb-board.h @@ -53,6 +53,16 @@ void UartUsbDeInit( Uart_t *obj ); */ uint8_t UartUsbPutChar( Uart_t *obj, uint8_t data ); +/*! + * \brief Sends a buffer to the UART + * + * \param [IN] obj UART object + * \param [IN] buffer Buffer to be sent + * \param [IN] size Buffer size + * \retval status [0: OK, 1: Busy, 2: Not configured] + */ +uint8_t UartUsbPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size ); + /*! * \brief Gets a character from the UART * diff --git a/src/boards/SensorNode/usb-cdc-board.c b/src/boards/SensorNode/usb-cdc-board.c index a68e681d9..cf4efbc5c 100644 --- a/src/boards/SensorNode/usb-cdc-board.c +++ b/src/boards/SensorNode/usb-cdc-board.c @@ -69,8 +69,6 @@ void UsbMcuLeaveLowPowerMode( void ) { bDeviceState = ATTACHED; } - /*Enable SystemCoreClock*/ - SystemInit( ); } void UsbMcuCableConfig( FunctionalState newState ) @@ -125,7 +123,7 @@ static void IntToUnicode( uint32_t value , uint8_t *pbuf , uint8_t len ) bool UsbMcuIsDeviceConfigured( void ) { - return bDeviceState == CONFIGURED; + return Virtual_ComPort_IsOpen( ); } void USB_LP_IRQHandler(void) diff --git a/src/boards/SensorNode/usb/cdc/inc/usb_prop.h b/src/boards/SensorNode/usb/cdc/inc/usb_prop.h index bd8170263..bcd1f1a2b 100644 --- a/src/boards/SensorNode/usb/cdc/inc/usb_prop.h +++ b/src/boards/SensorNode/usb/cdc/inc/usb_prop.h @@ -69,6 +69,7 @@ void Virtual_Com_Port_init(void); void Virtual_Com_Port_Reset(void); void Virtual_Com_Port_SetConfiguration(void); void Virtual_Com_Port_SetDeviceAddress (void); +bool Virtual_ComPort_IsOpen( void ); void Virtual_Com_Port_Status_In (void); void Virtual_Com_Port_Status_Out (void); RESULT Virtual_Com_Port_Data_Setup(uint8_t); diff --git a/src/boards/SensorNode/usb/cdc/src/usb_prop.c b/src/boards/SensorNode/usb/cdc/src/usb_prop.c index 25f15055b..d1a11e5b4 100644 --- a/src/boards/SensorNode/usb/cdc/src/usb_prop.c +++ b/src/boards/SensorNode/usb/cdc/src/usb_prop.c @@ -107,6 +107,8 @@ ONE_DESCRIPTOR String_Descriptor[4] = {(uint8_t*)Virtual_Com_Port_StringSerial, VIRTUAL_COM_PORT_SIZ_STRING_SERIAL} }; +static bool IsOpen = false; + /* Extern variables ----------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ /* Extern function prototypes ------------------------------------------------*/ @@ -220,6 +222,18 @@ void Virtual_Com_Port_SetDeviceAddress (void) bDeviceState = ADDRESSED; } +/******************************************************************************* +* Function Name : Virtual_ComPort_IsOpen. +* Description : Indicates if the serial port is opened by the host. +* Input : None. +* Output : None. +* Return : serial port status. +*******************************************************************************/ +bool Virtual_ComPort_IsOpen( void ) +{ + return ( bDeviceState == CONFIGURED ) && ( IsOpen == true ); +} + /******************************************************************************* * Function Name : Virtual_Com_Port_Status_In. * Description : Virtual COM Port Status In Routine. @@ -303,6 +317,15 @@ RESULT Virtual_Com_Port_NoData_Setup(uint8_t RequestNo) } else if (RequestNo == SET_CONTROL_LINE_STATE) { + // Checks DTR state + if( ( pInformation->USBwValues.bw.bb0 & 0x01 ) != 0 ) + { + IsOpen = true; + } + else + { + IsOpen = false; + } return USB_SUCCESS; } } diff --git a/src/boards/SensorNode/usb/cdc/src/usb_pwr.c b/src/boards/SensorNode/usb/cdc/src/usb_pwr.c index 9a7c466b8..a6fa3face 100644 --- a/src/boards/SensorNode/usb/cdc/src/usb_pwr.c +++ b/src/boards/SensorNode/usb/cdc/src/usb_pwr.c @@ -116,100 +116,27 @@ RESULT PowerOff() *******************************************************************************/ void Suspend(void) { - uint32_t i =0; uint16_t wCNTR; - uint32_t tmpreg = 0; - __IO uint32_t savePWR_CR=0; /* suspend preparation */ /* ... */ - - /*Store CNTR value */ - wCNTR = _GetCNTR(); - /* This a sequence to apply a force RESET to handle a robustness case */ - - /*Store endpoints registers status */ - for (i=0;i<8;i++) EP[i] = _GetENDPOINT(i); - - /* unmask RESET flag */ - wCNTR|=CNTR_RESETM; - _SetCNTR(wCNTR); - - /*apply FRES */ - wCNTR|=CNTR_FRES; - _SetCNTR(wCNTR); - - /*clear FRES*/ - wCNTR&=~CNTR_FRES; - _SetCNTR(wCNTR); - - /*poll for RESET flag in ISTR*/ - while((_GetISTR()&ISTR_RESET) == 0); - - /* clear RESET flag in ISTR */ - _SetISTR((uint16_t)CLR_RESET); - - /*restore Enpoints*/ - for (i=0;i<8;i++) - _SetENDPOINT(i, EP[i]); - - /* Now it is safe to enter macrocell in suspend mode */ + /* macrocell enters suspend mode */ + wCNTR = _GetCNTR(); wCNTR |= CNTR_FSUSP; _SetCNTR(wCNTR); - + + /* ------------------ ONLY WITH BUS-POWERED DEVICES ---------------------- */ + /* power reduction */ + /* ... on connected devices */ + /* force low-power mode in the macrocell */ wCNTR = _GetCNTR(); wCNTR |= CNTR_LPMODE; _SetCNTR(wCNTR); - - /*prepare entry in low power mode (STOP mode)*/ - /* Select the regulator state in STOP mode*/ - savePWR_CR = PWR->CR; - tmpreg = PWR->CR; - /* Clear PDDS and LPDS bits */ - tmpreg &= ((uint32_t)0xFFFFFFFC); - /* Set LPDS bit according to PWR_Regulator value */ - tmpreg |= PWR_Regulator_LowPower; - /* Store the new value */ - PWR->CR = tmpreg; - /* Set SLEEPDEEP bit of Cortex System Control Register */ -#if defined (STM32F30X) || defined (STM32F37X) - SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; -#else - SCB->SCR |= SCB_SCR_SLEEPDEEP; -#endif - - /* enter system in STOP mode, only when wakeup flag in not set */ - if((_GetISTR()&ISTR_WKUP)==0) - { - __WFI(); - /* Reset SLEEPDEEP bit of Cortex System Control Register */ -#if defined (STM32F30X) || defined (STM32F37X) - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); -#else - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); -#endif - } - else - { - /* Clear Wakeup flag */ - _SetISTR(CLR_WKUP); - /* clear FSUSP to abort entry in suspend mode */ - wCNTR = _GetCNTR(); - wCNTR&=~CNTR_FSUSP; - _SetCNTR(wCNTR); - - /*restore sleep mode configuration */ - /* restore Power regulator config in sleep mode*/ - PWR->CR = savePWR_CR; - - /* Reset SLEEPDEEP bit of Cortex System Control Register */ -#if defined (STM32F30X) || defined (STM32F37X) - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP_Msk); -#else - SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); -#endif - } + + /* switch-off the clocks */ + /* ... */ + Enter_LowPowerMode(); } /******************************************************************************* diff --git a/src/boards/mcu/stm32/sysIrqHandlers.c b/src/boards/mcu/stm32/sysIrqHandlers.c index 9be22bf45..5fd399272 100644 --- a/src/boards/mcu/stm32/sysIrqHandlers.c +++ b/src/boards/mcu/stm32/sysIrqHandlers.c @@ -28,13 +28,73 @@ void NMI_Handler( void ) * \param None * \retval None */ -void HardFault_Handler( void ) +#if defined( HARD_FAULT_HANDLER_ENABLED ) +void HardFault_Handler_C( unsigned int *args ) { - /* Go to infinite loop when Hard Fault exception occurs */ - while( 1 ) - { - } + __IO unsigned int stacked_r0; + __IO unsigned int stacked_r1; + __IO unsigned int stacked_r2; + __IO unsigned int stacked_r3; + __IO unsigned int stacked_r12; + __IO unsigned int stacked_lr; + __IO unsigned int stacked_pc; + __IO unsigned int stacked_psr; + + stacked_r0 = ( ( unsigned long) args[0] ); + stacked_r1 = ( ( unsigned long) args[1] ); + stacked_r2 = ( ( unsigned long) args[2] ); + stacked_r3 = ( ( unsigned long) args[3] ); + + stacked_r12 = ( ( unsigned long) args[4] ); + stacked_lr = ( ( unsigned long) args[5] ); + stacked_pc = ( ( unsigned long) args[6] ); + stacked_psr = ( ( unsigned long) args[7] ); + + ( void )stacked_r0; + ( void )stacked_r1; + ( void )stacked_r2; + ( void )stacked_r3; + + ( void )stacked_r12; + ( void )stacked_lr ; + ( void )stacked_pc ; + ( void )stacked_psr; + + while( 1 ); +} + +#if defined(__CC_ARM) +__asm void HardFault_Handler(void) +{ + TST LR, #4 + ITE EQ + MRSEQ r0, MSP + MRSNE r0, PSP + B __cpp(HardFault_Handler_C) +} +#elif defined(__ICCARM__) +void HardFault_Handler(void) +{ + __asm("TST LR, #4"); + __asm("ITE EQ"); + __asm("MRSEQ r0, MSP"); + __asm("MRSNE r0, PSP"); + __asm("B HardFault_Handler_C"); } +#elif defined(__GNUC__) +void HardFault_Handler(void) +{ + __asm volatile( "TST LR, #4" ); + __asm volatile( "ITE EQ" ); + __asm volatile( "MRSEQ R0, MSP" ); + __asm volatile( "MRSNE R0, PSP" ); + __asm volatile( "B HardFault_Handler_C" ); +} +#else + #warning Not supported compiler type +#endif + +#endif /*! * \brief This function handles Memory Manage exception. diff --git a/src/mac/LoRaMac.c b/src/mac/LoRaMac.c index 8b134b8b2..953a0cd30 100644 --- a/src/mac/LoRaMac.c +++ b/src/mac/LoRaMac.c @@ -262,6 +262,12 @@ static TimerEvent_t RxWindowTimer2; static uint32_t RxWindow1Delay; static uint32_t RxWindow2Delay; +static uint32_t MaxRxWindow; +static uint32_t ReceiveDelay1; +static uint32_t ReceiveDelay2; +static uint32_t JoinAcceptDelay1; +static uint32_t JoinAcceptDelay2; + /*! * Acknowledge timeout timer. Used for packet retransmissions. */ @@ -270,12 +276,12 @@ static TimerEvent_t AckTimeoutTimer; /*! * Number of trials to get a frame acknowledged */ -static uint8_t AckTimeoutRetries = 4; +static uint8_t AckTimeoutRetries = 1; /*! * Number of trials to get a frame acknowledged */ -static uint8_t AckTimeoutRetriesCounter = 0; +static uint8_t AckTimeoutRetriesCounter = 1; /*! * Function to be executed on Radio Tx Done event @@ -285,7 +291,7 @@ static void OnRadioTxDone( void ); /*! * Function to be executed on Radio Rx Done event */ -static void OnRadioRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); +static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * Function executed on Radio Tx Timeout event @@ -340,6 +346,11 @@ static uint8_t LoRaMacSetNextChannel( void ) { if( ( ( 1 << i ) & ChannelsMask ) != 0 ) { + if( ( ( Channels[i].DrRange.Fields.Min <= ChannelsDatarate ) && + ( ChannelsDatarate <= Channels[i].DrRange.Fields.Max ) ) == false ) + { // Check if the current channel selection supports the given datarate + continue; + } enabledChannels[nbEnabledChannels++] = i; } } @@ -349,11 +360,6 @@ static uint8_t LoRaMacSetNextChannel( void ) channelNext = enabledChannels[j]; j = ( j + 1 ) % nbEnabledChannels; - if( ( ( Channels[channelNext].DrRange.Fields.Min <= ChannelsDatarate ) && - ( ChannelsDatarate <= Channels[channelNext].DrRange.Fields.Max ) ) == false ) - { // Check if the current channel selection supports the given datarate - continue; - } if( Radio.IsChannelFree( MODEM_LORA, Channels[channelNext].Frequency, RSSI_FREE_TH ) == true ) { // Free channel found @@ -467,6 +473,12 @@ void LoRaMacInit( LoRaMacEvent_t *events ) ChannelsNbRepCounter = 0; AggregatedDCycle = 1.0; + MaxRxWindow = MAX_RX_WINDOW; + ReceiveDelay1 = RECEIVE_DELAY1; + ReceiveDelay2 = RECEIVE_DELAY2; + JoinAcceptDelay1 = JOIN_ACCEPT_DELAY1; + JoinAcceptDelay2 = JOIN_ACCEPT_DELAY2; + TimerInit( &RxWindowTimer1, OnRxWindow1TimerEvent ); TimerInit( &RxWindowTimer2, OnRxWindow2TimerEvent ); TimerInit( &AckTimeoutTimer, OnAckTimeoutTimerEvent ); @@ -548,7 +560,7 @@ uint8_t LoRaMacSendConfirmedFrame( uint8_t fPort, void *fBuffer, uint16_t fBuffe LoRaMacHeader_t macHdr; AckTimeoutRetries = retries; - AckTimeoutRetriesCounter = 0; + AckTimeoutRetriesCounter = 1; macHdr.Value = 0; @@ -604,8 +616,8 @@ uint8_t LoRaMacPrepareFrame( ChannelParams_t channel, LoRaMacHeader_t *macHdr, L switch( macHdr->Bits.MType ) { case FRAME_TYPE_JOIN_REQ: - RxWindow1Delay = JOIN_ACEPT_DELAY1; - RxWindow2Delay = JOIN_ACEPT_DELAY2; + RxWindow1Delay = JoinAcceptDelay1 - RADIO_WAKEUP_TIME; + RxWindow2Delay = JoinAcceptDelay2 - RADIO_WAKEUP_TIME; LoRaMacBufferPktLen = pktHeaderLen; @@ -644,8 +656,8 @@ uint8_t LoRaMacPrepareFrame( ChannelParams_t channel, LoRaMacHeader_t *macHdr, L return 2; // No network has been joined yet } - RxWindow1Delay = CLS2_RECEIVE_DELAY1; - RxWindow2Delay = CLS2_RECEIVE_DELAY2; + RxWindow1Delay = ReceiveDelay1 - RADIO_WAKEUP_TIME; + RxWindow2Delay = ReceiveDelay2 - RADIO_WAKEUP_TIME; if( fOpts == NULL ) { @@ -654,6 +666,7 @@ uint8_t LoRaMacPrepareFrame( ChannelParams_t channel, LoRaMacHeader_t *macHdr, L if( SrvAckRequested == true ) { + SrvAckRequested = false; fCtrl->Bits.Ack = 1; } @@ -773,15 +786,15 @@ uint8_t LoRaMacSendFrameOnChannel( ChannelParams_t channel ) if( ChannelsDatarate == DR_FSK ) { // High Speed FSK channel - Radio.SetTxConfig( MODEM_FSK, TxPowers[ChannelsTxPower], 25e3, 0, Datarates[ChannelsDatarate] * 1e3, 0, 5, false, true, false, 3e6 ); + Radio.SetTxConfig( MODEM_FSK, TxPowers[ChannelsTxPower], 25e3, 0, Datarates[ChannelsDatarate] * 1e3, 0, 5, false, true, 0, 0, false, 3e6 ); } else if( ChannelsDatarate == DR_SF7H ) { // High speed LoRa channel - Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 1, Datarates[ChannelsDatarate], 1, 8, false, true, false, 3e6 ); + Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 1, Datarates[ChannelsDatarate], 1, 8, false, true, 0, 0, false, 3e6 ); } else { // Normal LoRa channel - Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 0, Datarates[ChannelsDatarate], 1, 8, false, true, false, 3e6 ); + Radio.SetTxConfig( MODEM_LORA, TxPowers[ChannelsTxPower], 0, 0, Datarates[ChannelsDatarate], 1, 8, false, true, 0, 0, false, 3e6 ); } IsLoRaMacTransmitting = true; @@ -845,12 +858,10 @@ static void LoRaMacProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8 { nbRep = 1; } - if( mask == 0 ) { status &= 0xFE; // Channel mask KO } - for( i = 0; i < LORA_MAX_NB_CHANNELS; i++ ) { if( ( ( ( 1 << i ) & mask ) != 0 ) && @@ -906,6 +917,7 @@ static void LoRaMacProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8 freq = payload[macIndex++]; freq |= payload[macIndex++] << 8; freq |= payload[macIndex++] << 16; + freq *= 100; if( Radio.CheckRfFrequency( freq ) == false ) { @@ -935,16 +947,14 @@ static void LoRaMacProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8 int8_t channelIndex = 0; uint32_t freq = 0; DrRange_t drRange = { 0 }; - uint8_t dutyCycle = 0; - + channelIndex = payload[macIndex++]; freq = payload[macIndex++]; freq |= payload[macIndex++] << 8; freq |= payload[macIndex++] << 16; freq *= 100; drRange.Value = payload[macIndex++]; - dutyCycle = payload[macIndex++]; - + if( ( channelIndex < 3 ) && ( channelIndex > LORA_MAX_NB_CHANNELS ) ) { status &= 0xFE; // Channel frequency KO @@ -967,9 +977,11 @@ static void LoRaMacProcessMacCommands( uint8_t *payload, uint8_t macIndex, uint8 { Channels[channelIndex].Frequency = freq; Channels[channelIndex].DrRange = drRange; - Channels[channelIndex].DutyCycle = dutyCycle; + Channels[channelIndex].DutyCycle = 0; + // Activate the newly created channel + ChannelsMask |= 1 << channelIndex; } - AddMacCommand( MOTE_MAC_RX2_SETUP_ANS, status, 0 ); + AddMacCommand( MOTE_MAC_NEW_CHANNEL_ANS, status, 0 ); } break; default: @@ -1015,8 +1027,7 @@ static void OnRadioTxDone( void ) } else { - TimerSetValue( &NbRepTimeoutTimer, RxWindow1Delay + - RxWindow2Delay + + TimerSetValue( &NbRepTimeoutTimer, RxWindow2Delay + ACK_TIMEOUT + randr( -ACK_TIMEOUT_RND, ACK_TIMEOUT_RND ) ); TimerStart( &NbRepTimeoutTimer ); } @@ -1026,7 +1037,7 @@ static void OnRadioTxDone( void ) /*! * Function to be executed on Rx Done event */ -static void OnRadioRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ) +static void OnRadioRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) { LoRaMacHeader_t macHdr; LoRaMacFrameCtrl_t fCtrl; @@ -1256,7 +1267,7 @@ static void OnRadioRxDone( uint8_t *payload, uint16_t size, int8_t rssi, int8_t if( port == 0 ) { // Decode frame payload MAC commands - LoRaMacProcessMacCommands( payload, appPayloadStartIndex, frameLen ); + LoRaMacProcessMacCommands( LoRaMacPayload, appPayloadStartIndex, frameLen ); } } LoRaMacEventInfo.Status = LORAMAC_EVENT_INFO_STATUS_OK; @@ -1343,12 +1354,12 @@ static void OnRxWindow1TimerEvent( void ) if( ChannelsDatarate == DR_FSK ) { - Radio.SetRxConfig( MODEM_FSK, 50e3, Datarates[ChannelsDatarate] * 1e3, 0, 83.333e3, 5, 0, false, true, false, false ); + Radio.SetRxConfig( MODEM_FSK, 50e3, Datarates[ChannelsDatarate] * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, false ); } else if( ChannelsDatarate == DR_SF7H ) { symbTimeout = 8; - Radio.SetRxConfig( MODEM_LORA, 1, Datarates[ChannelsDatarate], 1, 0, 8, symbTimeout, false, false, true, false ); + Radio.SetRxConfig( MODEM_LORA, 1, Datarates[ChannelsDatarate], 1, 0, 8, symbTimeout, false, 0, false, 0, 0, true, false ); } else { @@ -1361,9 +1372,9 @@ static void OnRxWindow1TimerEvent( void ) { // DR_SF7 = 5, DR_SF8 = 4, DR_SF9 = 3 symbTimeout = 8; } - Radio.SetRxConfig( MODEM_LORA, 0, Datarates[ChannelsDatarate], 1, 0, 8, symbTimeout, false, false, true, false ); + Radio.SetRxConfig( MODEM_LORA, 0, Datarates[ChannelsDatarate], 1, 0, 8, symbTimeout, false, 0, false, 0, 0, true, false ); } - Radio.Rx( CLS2_MAX_RX_WINDOW ); + Radio.Rx( MaxRxWindow ); } } @@ -1385,14 +1396,14 @@ static void OnRxWindow2TimerEvent( void ) // RX2 Defaults to SF9/125kHz - 869.525MHz Radio.SetChannel( Rx2Channel.Frequency ); - if( ChannelsDatarate == DR_FSK ) + if( Rx2Channel.Datarate == DR_FSK ) { - Radio.SetRxConfig( MODEM_FSK, 50e3, Datarates[Rx2Channel.Datarate] * 1e3, 0, 83.333e3, 5, 0, false, true, false, false ); + Radio.SetRxConfig( MODEM_FSK, 50e3, Datarates[Rx2Channel.Datarate] * 1e3, 0, 83.333e3, 5, 0, false, 0, true, 0, 0, false, false ); } - else if( ChannelsDatarate == DR_SF7H ) + else if( Rx2Channel.Datarate == DR_SF7H ) { symbTimeout = 8; - Radio.SetRxConfig( MODEM_LORA, 1, Datarates[Rx2Channel.Datarate], 1, 0, 8, symbTimeout, false, false, true, false ); + Radio.SetRxConfig( MODEM_LORA, 1, Datarates[Rx2Channel.Datarate], 1, 0, 8, symbTimeout, false, 0, false, 0, 0, true, false ); } else { @@ -1405,9 +1416,9 @@ static void OnRxWindow2TimerEvent( void ) { // DR_SF7 = 5, DR_SF8 = 4, DR_SF9 = 3 symbTimeout = 8; } - Radio.SetRxConfig( MODEM_LORA, 0, Datarates[Rx2Channel.Datarate], 1, 0, 8, symbTimeout, false, false, true, false ); + Radio.SetRxConfig( MODEM_LORA, 0, Datarates[Rx2Channel.Datarate], 1, 0, 8, symbTimeout, false, 0, false, 0, 0, true, false ); } - Radio.Rx( CLS2_MAX_RX_WINDOW ); + Radio.Rx( MaxRxWindow ); } } @@ -1435,11 +1446,11 @@ static void OnNbRepTimeoutTimerEvent( void ) */ static void OnAckTimeoutTimerEvent( void ) { - if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter < MAX_ACK_RETRIES ) ) + if( ( AckTimeoutRetriesCounter < AckTimeoutRetries ) && ( AckTimeoutRetriesCounter <= MAX_ACK_RETRIES ) ) { AckTimeoutRetriesCounter++; - if( ( AckTimeoutRetriesCounter % 2 ) == 0 ) + if( ( AckTimeoutRetriesCounter % 2 ) == 1 ) { ChannelsDatarate = MAX( ChannelsDatarate - 1, LORAMAC_MIN_DATARATE ); } @@ -1479,9 +1490,14 @@ static void OnAckTimeoutTimerEvent( void ) * ============================================================================ */ -void LoRaMacSetChannelsDatarate( int8_t datrate ) +void LoRaMacSetChannel( uint8_t id, ChannelParams_t params ) { - ChannelsDatarate = datrate; + Channels[id] = params; +} + +void LoRaMacSetRx2Channel( Rx2ChannelParams_t param ) +{ + Rx2Channel = param; } void LoRaMacSetChannelsTxPower( int8_t txPower ) @@ -1489,11 +1505,69 @@ void LoRaMacSetChannelsTxPower( int8_t txPower ) ChannelsTxPower = txPower; } +void LoRaMacSetChannelsDatarate( int8_t datrate ) +{ + ChannelsDatarate = datrate; +} + +void LoRaMacSetChannelsMask( uint16_t mask ) +{ + ChannelsMask = mask; +} + +void LoRaMacSetChannelsNbRep( uint8_t nbRep ) +{ + if( nbRep < 1 ) + { + nbRep = 1; + } + if( nbRep > 15 ) + { + nbRep = 15; + } + ChannelsNbRep = nbRep; +} + +void LoRaMacSetMaxRxWindow( uint32_t delay ) +{ + MaxRxWindow = delay; +} + +void LoRaMacSetReceiveDelay1( uint32_t delay ) +{ + ReceiveDelay1 = delay; +} + +void LoRaMacSetReceiveDelay2( uint32_t delay ) +{ + ReceiveDelay2 = delay; +} + +void LoRaMacSetJoinAcceptDelay1( uint32_t delay ) +{ + JoinAcceptDelay1 = delay; +} + +void LoRaMacSetJoinAcceptDelay2( uint32_t delay ) +{ + JoinAcceptDelay2 = delay; +} + void LoRaMacTestRxWindowsOn( bool enable ) { IsRxWindowsEnabled = enable; } +uint32_t LoRaMacGetUpLinkCounter( void ) +{ + return UpLinkCounter; +} + +uint32_t LoRaMacGetDownLinkCounter( void ) +{ + return DownLinkCounter; +} + void LoRaMacSetMicTest( uint16_t upLinkCounter ) { UpLinkCounter = upLinkCounter; diff --git a/src/mac/LoRaMac.h b/src/mac/LoRaMac.h index c26d13216..193b7c0d2 100644 --- a/src/mac/LoRaMac.h +++ b/src/mac/LoRaMac.h @@ -26,24 +26,24 @@ Maintainer: Miguel Luis and Gregory Cristian /*! * Class A&B receive delay in ms */ -#define CLS2_RECEIVE_DELAY1 1000000 - RADIO_WAKEUP_TIME -#define CLS2_RECEIVE_DELAY2 2000000 - RADIO_WAKEUP_TIME +#define RECEIVE_DELAY1 1000000 +#define RECEIVE_DELAY2 2000000 /*! * Join accept receive delay in ms */ #if defined( LORAMAC_R3 ) -#define JOIN_ACEPT_DELAY1 5000000 - RADIO_WAKEUP_TIME -#define JOIN_ACEPT_DELAY2 6000000 - RADIO_WAKEUP_TIME +#define JOIN_ACCEPT_DELAY1 5000000 +#define JOIN_ACCEPT_DELAY2 6000000 #else -#define JOIN_ACEPT_DELAY1 1000000 - RADIO_WAKEUP_TIME -#define JOIN_ACEPT_DELAY2 2000000 - RADIO_WAKEUP_TIME +#define JOIN_ACCEPT_DELAY1 1000000 +#define JOIN_ACCEPT_DELAY2 2000000 #endif /*! * Class A&B maximum receive window delay in ms */ -#define CLS2_MAX_RX_WINDOW 3000000 +#define MAX_RX_WINDOW 3000000 /*! * Maximum allowed gap for the FCNT field @@ -106,8 +106,8 @@ typedef union { int8_t Min : 4; int8_t Max : 4; - }Fields; -}DrRange_t; + }__attribute__((__packed__)) Fields; +}__attribute__((__packed__)) DrRange_t; typedef struct { @@ -115,13 +115,13 @@ typedef struct DrRange_t DrRange; // Max datarate [0: SF12, 1: SF11, 2: SF10, 3: SF9, 4: SF8, 5: SF7, 6: SF7, 7: FSK] // Min datarate [0: SF12, 1: SF11, 2: SF10, 3: SF9, 4: SF8, 5: SF7, 6: SF7, 7: FSK] int8_t DutyCycle; // 0 = 100% .. 15 = 0.003% -}ChannelParams_t; +}__attribute__((__packed__)) ChannelParams_t; typedef struct { uint32_t Frequency; // Hz uint8_t Datarate; // [0: SF12, 1: SF11, 2: SF10, 3: SF9, 4: SF8, 5: SF7, 6: SF7, 7: FSK] -}Rx2ChannelParams_t; +}__attribute__((__packed__)) Rx2ChannelParams_t; /*! * LoRaMAC frame types @@ -137,7 +137,7 @@ typedef enum FRAME_TYPE_DATA_CONFIRMED_DOWN = 0x05, FRAME_TYPE_RFU = 0x06, FRAME_TYPE_PROPRIETARY = 0x07, -}LoRaMacFrameType_t; +}__attribute__((__packed__)) LoRaMacFrameType_t; #else typedef enum { @@ -146,7 +146,7 @@ typedef enum FRAME_TYPE_DATA_UNCONFIRMED = 0x02, FRAME_TYPE_DATA_CONFIRMED = 0x03, FRAME_TYPE_PROPRIETARY = 0x07, -}LoRaMacFrameType_t; +}__attribute__((__packed__)) LoRaMacFrameType_t; #endif /*! @@ -160,7 +160,7 @@ typedef enum MOTE_MAC_RX2_SETUP_ANS = 0x05, MOTE_MAC_DEV_STATUS_ANS = 0x06, MOTE_MAC_NEW_CHANNEL_ANS = 0x07, -}LoRaMacMoteCmd_t; +}__attribute__((__packed__)) LoRaMacMoteCmd_t; /*! * LoRaMAC server MAC commands @@ -173,7 +173,7 @@ typedef enum SRV_MAC_RX2_SETUP_REQ = 0x05, SRV_MAC_DEV_STATUS_REQ = 0x06, SRV_MAC_NEW_CHANNEL_REQ = 0x07, -}LoRaMacSrvCmd_t; +}__attribute__((__packed__)) LoRaMacSrvCmd_t; /*! * LoRaMAC Battery level indicator @@ -184,7 +184,7 @@ typedef enum BAT_LEVEL_EMPTY = 0x01, BAT_LEVEL_FULL = 0xFE, BAT_LEVEL_NO_MEASURE = 0xFF, -}LoRaMacBatteryLevel_t; +}__attribute__((__packed__)) LoRaMacBatteryLevel_t; /*! * LoRaMAC header field definition @@ -197,8 +197,8 @@ typedef union uint8_t Major : 2; uint8_t RFU : 3; uint8_t MType : 3; - }Bits; -}LoRaMacHeader_t; + }__attribute__((__packed__)) Bits; +}__attribute__((__packed__)) LoRaMacHeader_t; /*! * LoRaMAC frame header field definition @@ -213,8 +213,8 @@ typedef union uint8_t Ack : 1; uint8_t AdrAckReq : 1; uint8_t Adr : 1; - }Bits; -}LoRaMacFrameCtrl_t; + }__attribute__((__packed__)) Bits; +}__attribute__((__packed__)) LoRaMacFrameCtrl_t; /*! * LoRaMAC event flags @@ -229,14 +229,14 @@ typedef union uint8_t LinkCheck : 1; uint8_t : 4; uint8_t JoinAccept : 1; - }Bits; -}LoRaMacEventFlags_t; + }__attribute__((__packed__)) Bits; +}__attribute__((__packed__)) LoRaMacEventFlags_t; typedef enum { LORAMAC_EVENT_INFO_STATUS_OK = 0, LORAMAC_EVENT_INFO_STATUS_ERROR, -}LoRaMacEventInfoStatus_t; +}__attribute__((__packed__)) LoRaMacEventInfoStatus_t; /*! * LoRaMAC event information @@ -250,12 +250,12 @@ typedef struct uint8_t RxPort; uint8_t *RxBuffer; uint8_t RxBufferSize; - int8_t RxRssi; + int16_t RxRssi; uint8_t RxSnr; uint16_t Energy; uint8_t DemodMargin; uint8_t NbGateways; -}LoRaMacEventInfo_t; +}__attribute__((__packed__)) LoRaMacEventInfo_t; /*! * LoRaMAC events structure @@ -270,7 +270,7 @@ typedef struct sLoRaMacEvent * \param [IN] info Details about MAC events occurred */ void ( *MacEvent )( LoRaMacEventFlags_t *flags, LoRaMacEventInfo_t *info ); -}LoRaMacEvent_t; +}__attribute__((__packed__)) LoRaMacEvent_t; /*! * LoRaMAC layer initialization @@ -414,6 +414,51 @@ uint8_t LoRaMacSendFrameOnChannel( ChannelParams_t channel ); */ uint8_t LoRaMacSendOnChannel( ChannelParams_t channel, LoRaMacHeader_t *macHdr, LoRaMacFrameCtrl_t *fCtrl, uint8_t *fOpts, uint8_t fPort, void *fBuffer, uint16_t fBufferSize ); +/* + * TODO: Add documentations + */ +void LoRaMacSetChannel( uint8_t id, ChannelParams_t params ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetRx2Channel( Rx2ChannelParams_t param ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetChannelsMask( uint16_t mask ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetChannelsNbRep( uint8_t nbRep ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetMaxRxWindow( uint32_t delay ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetReceiveDelay1( uint32_t delay ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetReceiveDelay2( uint32_t delay ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetJoinAcceptDelay1( uint32_t delay ); + +/* + * TODO: Add documentations + */ +void LoRaMacSetJoinAcceptDelay2( uint32_t delay ); + /*! * Sets channels datarate * @@ -438,6 +483,16 @@ void LoRaMacSetChannelsTxPower( int8_t txPower ); */ void LoRaMacTestRxWindowsOn( bool enable ); +/* + * TODO: Add documentations + */ +uint32_t LoRaMacGetUpLinkCounter( void ); + +/* + * TODO: Add documentations + */ +uint32_t LoRaMacGetDownLinkCounter( void ); + /*! * Enables the MIC field test * diff --git a/src/peripherals/sx9500.h b/src/peripherals/sx9500.h index 283d0caab..63275c211 100644 --- a/src/peripherals/sx9500.h +++ b/src/peripherals/sx9500.h @@ -54,8 +54,8 @@ uint8_t SX9500Reset( void ); /*! * \brief Writes a byte at specified address in the device * - * \param [IN]: addr - * \param [IN]: data + * \param [IN]: addr + * \param [IN]: data * \retval status [OK, ERROR, UNSUPPORTED] */ uint8_t SX9500Write( uint8_t addr, uint8_t data ); diff --git a/src/radio/radio.h b/src/radio/radio.h index b908d2140..0f253099f 100644 --- a/src/radio/radio.h +++ b/src/radio/radio.h @@ -32,6 +32,7 @@ typedef enum RF_IDLE = 0, RF_RX_RUNNING, RF_TX_RUNNING, + RF_CAD, }RadioState_t; /*! @@ -57,7 +58,7 @@ typedef struct * FSK : N/A ( set to 0 ) * LoRa: SNR value in dB */ - void ( *RxDone )( uint8_t *payload, uint16_t size, int8_t rssi, int8_t snr ); + void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); /*! * \brief Rx Timeout callback prototype. */ @@ -66,6 +67,19 @@ typedef struct * \brief Rx Error callback prototype. */ void ( *RxError )( void ); + /*! + * \brief FHSS Change Channel callback prototype. + * + * \param [IN] currentChannel Index number of the current channel + */ + void ( *FhssChangeChannel )( uint8_t currentChannel ); + + /*! + * \brief CAD Done callback prototype. + * + * \param [IN] channelDetected Channel Activity detected during the CAD + */ + void ( *CadDone ) ( bool channelActivityDetected ); }RadioEvents_t; /*! @@ -106,7 +120,7 @@ struct Radio_s * * \retval isFree [true: Channel is free, false: Channel is not free] */ - bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int8_t rssiThresh ); + bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); /*! * \brief Generates a 32 bits random value based on the RSSI readings * @@ -143,7 +157,14 @@ struct Radio_s * FSK : N/A ( set to 0 ) * LoRa: timeout in symbols * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed lenght is used * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols * \param [IN] iqInverted Inverts IQ signals (LoRa only) * FSK : N/A ( set to 0 ) * LoRa: [0: not inverted, 1: inverted] @@ -154,7 +175,9 @@ struct Radio_s uint32_t datarate, uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, uint16_t symbTimeout, bool fixLen, - bool crcOn, bool iqInverted, bool rxContinuous ); + uint8_t payloadLen, + bool crcOn, bool FreqHopOn, uint8_t HopPeriod, + bool iqInverted, bool rxContinuous ); /*! * \brief Sets the transmission parameters * @@ -179,6 +202,12 @@ struct Radio_s * LoRa: Length in symbols (the hardware adds 4 more symbols) * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols * \param [IN] iqInverted Inverts IQ signals (LoRa only) * FSK : N/A ( set to 0 ) * LoRa: [0: not inverted, 1: inverted] @@ -187,8 +216,8 @@ struct Radio_s void ( *SetTxConfig )( RadioModems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preambleLen, - bool fixLen, bool crcOn, - bool iqInverted, uint32_t timeout ); + bool fixLen, bool crcOn, bool FreqHopOn, + uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); /*! * \brief Checks if the given RF frequency is supported by the hardware * @@ -229,12 +258,16 @@ struct Radio_s * [0: continuous, others timeout] */ void ( *Rx )( uint32_t timeout ); + /*! + * \brief Start a Channel Activity Detection + */ + void ( *StartCad )( void ); /*! * \brief Reads the current RSSI value * * \retval rssiValue Current RSSI value in [dBm] */ - int8_t ( *Rssi )( RadioModems_t modem ); + int16_t ( *Rssi )( RadioModems_t modem ); /*! * \brief Writes the radio register at the specified address * diff --git a/src/radio/sx1272/sx1272.c b/src/radio/sx1272/sx1272.c index 200a01a52..6a76b24fd 100644 --- a/src/radio/sx1272/sx1272.c +++ b/src/radio/sx1272/sx1272.c @@ -135,9 +135,7 @@ const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE; /*! * Constant values need to compute the RSSI value */ -#define NOISE_ABSOLUTE_ZERO -174.0 -#define NOISE_FIGURE 6.0 -#define RSSI_OFFSET -139.0 +#define RSSI_OFFSET -139 /*! * Precomputed FSK bandwidth registers values @@ -164,7 +162,8 @@ const FskBandwidth_t FskBandwidths[] = { 125000, 0x02 }, { 166700, 0x11 }, { 200000, 0x09 }, - { 250000, 0x01 } + { 250000, 0x01 }, + { 0, 0x00 }, // Invalid Badwidth }; /* @@ -250,9 +249,9 @@ void SX1272SetChannel( uint32_t freq ) SX1272Write( REG_FRFLSB, ( uint8_t )( freq & 0xFF ) ); } -bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int8_t rssiThresh ) +bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ) { - int8_t rssi = 0; + int16_t rssi = 0; SX1272SetModem( modem ); @@ -334,7 +333,9 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, uint16_t symbTimeout, bool fixLen, - bool crcOn, bool iqInverted, bool rxContinuous ) + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) { SX1272SetModem( modem ); @@ -346,6 +347,7 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1272.Settings.Fsk.Datarate = datarate; SX1272.Settings.Fsk.BandwidthAfc = bandwidthAfc; SX1272.Settings.Fsk.FixLen = fixLen; + SX1272.Settings.Fsk.PayloadLen = payloadLen; SX1272.Settings.Fsk.CrcOn = crcOn; SX1272.Settings.Fsk.IqInverted = iqInverted; SX1272.Settings.Fsk.RxContinuous = rxContinuous; @@ -358,8 +360,8 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1272Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) ); SX1272Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) ); - SX1272Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); - SX1272Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + SX1272Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); + SX1272Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); SX1272Write( REG_PACKETCONFIG1, ( SX1272Read( REG_PACKETCONFIG1 ) & @@ -375,7 +377,10 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1272.Settings.LoRa.Datarate = datarate; SX1272.Settings.LoRa.Coderate = coderate; SX1272.Settings.LoRa.FixLen = fixLen; + SX1272.Settings.LoRa.PayloadLen = payloadLen; SX1272.Settings.LoRa.CrcOn = crcOn; + SX1272.Settings.LoRa.FreqHopOn = freqHopOn; + SX1272.Settings.LoRa.HopPeriod = hopPeriod; SX1272.Settings.LoRa.IqInverted = iqInverted; SX1272.Settings.LoRa.RxContinuous = rxContinuous; @@ -421,6 +426,17 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1272Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); SX1272Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + if( fixLen == 1 ) + { + SX1272Write( REG_LR_PAYLOADLENGTH, payloadLen ); + } + + if( SX1272.Settings.LoRa.FreqHopOn == true ) + { + SX1272Write( REG_LR_PLLHOP, ( SX1272Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + SX1272Write( REG_LR_HOPPERIOD, SX1272.Settings.LoRa.HopPeriod ); + } + if( datarate == 6 ) { SX1272Write( REG_LR_DETECTOPTIMIZE, @@ -439,11 +455,6 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1272Write( REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); } - - SX1272Write( REG_LR_INVERTIQ, - ( SX1272Read( REG_LR_INVERTIQ ) & - RFLR_INVERTIQ_MASK ) | - ( iqInverted << 6 ) ); } break; } @@ -452,8 +463,8 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preambleLen, - bool fixLen, bool crcOn, - bool iqInverted, uint32_t timeout ) + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) { uint8_t paConfig = 0; uint8_t paDac = 0; @@ -557,6 +568,8 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, SX1272.Settings.LoRa.Coderate = coderate; SX1272.Settings.LoRa.PreambleLen = preambleLen; SX1272.Settings.LoRa.FixLen = fixLen; + SX1272.Settings.LoRa.FreqHopOn = freqHopOn; + SX1272.Settings.LoRa.HopPeriod = hopPeriod; SX1272.Settings.LoRa.CrcOn = crcOn; SX1272.Settings.LoRa.IqInverted = iqInverted; SX1272.Settings.LoRa.TxTimeout = timeout; @@ -579,6 +592,12 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, SX1272.Settings.LoRa.LowDatarateOptimize = 0x00; } + if( SX1272.Settings.LoRa.FreqHopOn == true ) + { + SX1272Write( REG_LR_PLLHOP, ( SX1272Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + SX1272Write( REG_LR_HOPPERIOD, SX1272.Settings.LoRa.HopPeriod ); + } + SX1272Write( REG_LR_MODEMCONFIG1, ( SX1272Read( REG_LR_MODEMCONFIG1 ) & RFLR_MODEMCONFIG1_BW_MASK & @@ -617,11 +636,6 @@ void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, SX1272Write( REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); } - - SX1272Write( REG_LR_INVERTIQ, - ( SX1272Read( REG_LR_INVERTIQ ) & - RFLR_INVERTIQ_MASK ) | - ( iqInverted << 6 ) ); } break; } @@ -721,6 +735,15 @@ void SX1272Send( uint8_t *buffer, uint8_t size ) break; case MODEM_LORA: { + if( SX1272.Settings.LoRa.IqInverted == true ) + { + SX1272Write( REG_LR_INVERTIQ, ( ( SX1272Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) ); + } + else + { + SX1272Write( REG_LR_INVERTIQ, ( ( SX1272Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + } + SX1272.Settings.LoRaPacketHandler.Size = size; // Initializes the payload size @@ -750,14 +773,18 @@ void SX1272SetSleep( void ) { TimerStop( &RxTimeoutTimer ); TimerStop( &TxTimeoutTimer ); + SX1272SetOpMode( RF_OPMODE_SLEEP ); + SX1272.Settings.State = RF_IDLE; } void SX1272SetStby( void ) { TimerStop( &RxTimeoutTimer ); TimerStop( &TxTimeoutTimer ); + SX1272SetOpMode( RF_OPMODE_STANDBY ); + SX1272.Settings.State = RF_IDLE; } void SX1272SetRx( uint32_t timeout ) @@ -780,7 +807,7 @@ void SX1272SetRx( uint32_t timeout ) RF_DIOMAPPING1_DIO2_MASK ) | RF_DIOMAPPING1_DIO0_00 | RF_DIOMAPPING1_DIO2_11 ); - + SX1272Write( REG_DIOMAPPING2, ( SX1272Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK & RF_DIOMAPPING2_MAP_MASK ) | RF_DIOMAPPING2_DIO4_11 | @@ -796,19 +823,45 @@ void SX1272SetRx( uint32_t timeout ) break; case MODEM_LORA: { + if( SX1272.Settings.LoRa.IqInverted == true ) + { + SX1272Write( REG_LR_INVERTIQ, ( ( SX1272Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) ); + } + else + { + SX1272Write( REG_LR_INVERTIQ, ( ( SX1272Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + } + rxContinuous = SX1272.Settings.LoRa.RxContinuous; - SX1272Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | - //RFLR_IRQFLAGS_RXDONE | - //RFLR_IRQFLAGS_PAYLOADCRCERROR | - RFLR_IRQFLAGS_VALIDHEADER | - RFLR_IRQFLAGS_TXDONE | - RFLR_IRQFLAGS_CADDONE | - RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | - RFLR_IRQFLAGS_CADDETECTED ); - - // DIO0=RxDone - SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + if( SX1272.Settings.LoRa.FreqHopOn == true ) + { + SX1272Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone, DIO2=FhssChangeChannel + SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + SX1272Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone + SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + } SX1272Write( REG_LR_FIFORXBASEADDR, 0 ); SX1272Write( REG_LR_FIFOADDRPTR, 0 ); } @@ -875,17 +928,34 @@ void SX1272SetTx( uint32_t timeout ) break; case MODEM_LORA: { - SX1272Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | - RFLR_IRQFLAGS_RXDONE | - RFLR_IRQFLAGS_PAYLOADCRCERROR | - RFLR_IRQFLAGS_VALIDHEADER | - //RFLR_IRQFLAGS_TXDONE | - RFLR_IRQFLAGS_CADDONE | - RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | - RFLR_IRQFLAGS_CADDETECTED ); - - // DIO0=TxDone - SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 ); + if( SX1272.Settings.LoRa.FreqHopOn == true ) + { + SX1272Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone, DIO2=FhssChangeChannel + SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + SX1272Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone + SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 ); + } } break; } @@ -895,9 +965,42 @@ void SX1272SetTx( uint32_t timeout ) SX1272SetOpMode( RF_OPMODE_TRANSMITTER ); } -int8_t SX1272ReadRssi( RadioModems_t modem ) +void SX1272StartCad( void ) { - int8_t rssi = 0; + switch( SX1272.Settings.Modem ) + { + case MODEM_FSK: + { + + } + break; + case MODEM_LORA: + { + SX1272Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + //RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL // | + //RFLR_IRQFLAGS_CADDETECTED + ); + + // DIO3=CADDone + SX1272Write( REG_DIOMAPPING1, ( SX1272Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + + SX1272.Settings.State = RF_CAD; + SX1272SetOpMode( RFLR_OPMODE_CAD ); + } + break; + default: + break; + } +} + +int16_t SX1272ReadRssi( RadioModems_t modem ) +{ + int16_t rssi = 0; switch( modem ) { @@ -1047,7 +1150,6 @@ void SX1272ReadFifo( uint8_t *buffer, uint8_t size ) void SX1272OnTimeoutIrq( void ) { - RadioState_t state = RF_IDLE; switch( SX1272.Settings.State ) { case RF_RX_RUNNING: @@ -1066,13 +1168,13 @@ void SX1272OnTimeoutIrq( void ) if( SX1272.Settings.Fsk.RxContinuous == true ) { - state = SX1272.Settings.State; // Continuous mode restart Rx chain SX1272Write( REG_RXCONFIG, SX1272Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); } else { - TimerStart( &RxTimeoutSyncWord ); + SX1272.Settings.State = RF_IDLE; + TimerStop( &RxTimeoutSyncWord ); } } if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) ) @@ -1081,6 +1183,7 @@ void SX1272OnTimeoutIrq( void ) } break; case RF_TX_RUNNING: + SX1272.Settings.State = RF_IDLE; if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) ) { RadioEvents->TxTimeout( ); @@ -1089,7 +1192,6 @@ void SX1272OnTimeoutIrq( void ) default: break; } - SX1272.Settings.State = state; } void SX1272OnDio0Irq( void ) @@ -1179,7 +1281,7 @@ void SX1272OnDio0Irq( void ) break; case MODEM_LORA: { - uint8_t snr = 0; + int8_t snr = 0; // Clear Irq SX1272Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE ); @@ -1216,8 +1318,8 @@ void SX1272OnDio0Irq( void ) snr = ( SX1272.Settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2; } - int8_t rssi = SX1272Read( REG_LR_PKTRSSIVALUE ); - if( SX1272.Settings.LoRaPacketHandler.SnrValue < 0 ) + int16_t rssi = SX1272Read( REG_LR_PKTRSSIVALUE ); + if( snr < 0 ) { SX1272.Settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET + rssi + ( rssi >> 4 ) + snr; @@ -1367,6 +1469,16 @@ void SX1272OnDio2Irq( void ) } break; case MODEM_LORA: + if( SX1272.Settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + SX1272Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if( ( RadioEvents != NULL ) && ( RadioEvents->FhssChangeChannel != NULL ) ) + { + RadioEvents->FhssChangeChannel( ( SX1272Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } break; default: break; @@ -1378,6 +1490,16 @@ void SX1272OnDio2Irq( void ) case MODEM_FSK: break; case MODEM_LORA: + if( SX1272.Settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + SX1272Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if( ( RadioEvents != NULL ) && ( RadioEvents->FhssChangeChannel != NULL ) ) + { + RadioEvents->FhssChangeChannel( ( SX1272Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } break; default: break; @@ -1395,6 +1517,24 @@ void SX1272OnDio3Irq( void ) case MODEM_FSK: break; case MODEM_LORA: + if( ( SX1272Read( REG_LR_IRQFLAGS ) & RFLR_IRQFLAGS_CADDETECTED ) == RFLR_IRQFLAGS_CADDETECTED ) + { + // Clear Irq + SX1272Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE ); + if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) ) + { + RadioEvents->CadDone( true ); + } + } + else + { + // Clear Irq + SX1272Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE ); + if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) ) + { + RadioEvents->CadDone( false ); + } + } break; default: break; diff --git a/src/radio/sx1272/sx1272.h b/src/radio/sx1272/sx1272.h index 7be2f0b99..943ef670c 100644 --- a/src/radio/sx1272/sx1272.h +++ b/src/radio/sx1272/sx1272.h @@ -35,6 +35,7 @@ typedef struct uint32_t Datarate; uint16_t PreambleLen; bool FixLen; + uint8_t PayloadLen; bool CrcOn; bool IqInverted; bool RxContinuous; @@ -69,7 +70,10 @@ typedef struct uint8_t Coderate; uint16_t PreambleLen; bool FixLen; + uint8_t PayloadLen; bool CrcOn; + bool FreqHopOn; + uint8_t HopPeriod; bool IqInverted; bool RxContinuous; uint32_t TxTimeout; @@ -81,7 +85,7 @@ typedef struct typedef struct { int8_t SnrValue; - int8_t RssiValue; + int16_t RssiValue; uint8_t Size; }RadioLoRaPacketHandler_t; @@ -172,7 +176,7 @@ void SX1272SetChannel( uint32_t freq ); * * \retval isFree [true: Channel is free, false: Channel is not free] */ -bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int8_t rssiThresh ); +bool SX1272IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); /*! * \brief Generates a 32 bits random value based on the RSSI readings @@ -211,18 +215,27 @@ uint32_t SX1272Random( void ); * FSK : N/A ( set to 0 ) * LoRa: timeout in symbols * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed lenght is used * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols * \param [IN] iqInverted Inverts IQ signals (LoRa only) * FSK : N/A ( set to 0 ) * LoRa: [0: not inverted, 1: inverted] * \param [IN] rxContinuous Sets the reception in continuous mode * [false: single mode, true: continuous mode] */ -void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, +void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, uint16_t symbTimeout, bool fixLen, - bool crcOn, bool iqInverted, bool rxContinuous ); + uint8_t payloadLen, + bool crcOn, bool FreqHopOn, uint8_t HopPeriod, + bool iqInverted, bool rxContinuous ); /*! * \brief Sets the transmission parameters @@ -248,6 +261,12 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, * LoRa: Length in symbols (the hardware adds 4 more symbols) * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols * \param [IN] iqInverted Inverts IQ signals (LoRa only) * FSK : N/A ( set to 0 ) * LoRa: [0: not inverted, 1: inverted] @@ -256,8 +275,8 @@ void SX1272SetRxConfig( RadioModems_t modem, uint32_t bandwidth, void SX1272SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preambleLen, - bool fixLen, bool crcOn, - bool iqInverted, uint32_t timeout ); + bool fixLen, bool crcOn, bool FreqHopOn, + uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); /*! * \brief Computes the packet time on air for the given payload @@ -296,12 +315,17 @@ void SX1272SetStby( void ); */ void SX1272SetRx( uint32_t timeout ); +/*! + * \brief Start a Channel Activity Detection + */ +void SX1272StartCad( void ); + /*! * \brief Reads the current RSSI value * * \retval rssiValue Current RSSI value in [dBm] */ -int8_t SX1272ReadRssi( RadioModems_t modem ); +int16_t SX1272ReadRssi( RadioModems_t modem ); /*! * \brief Writes the radio register at the specified address diff --git a/src/radio/sx1272/sx1272Regs-LoRa.h b/src/radio/sx1272/sx1272Regs-LoRa.h index 4554ff51d..1f1faf87a 100644 --- a/src/radio/sx1272/sx1272Regs-LoRa.h +++ b/src/radio/sx1272/sx1272Regs-LoRa.h @@ -65,6 +65,7 @@ Maintainer: Miguel Luis and Gregory Cristian #define REG_LR_DETECTOPTIMIZE 0x31 #define REG_LR_INVERTIQ 0x33 #define REG_LR_DETECTIONTHRESHOLD 0x37 +#define REG_LR_SYNCWORD 0x39 // end of documented register in datasheet // I/O settings @@ -412,9 +413,12 @@ Maintainer: Miguel Luis and Gregory Cristian /*! * RegInvertIQ */ -#define RFLR_INVERTIQ_MASK 0xBF -#define RFLR_INVERTIQ_OFF 0x00 -#define RFLR_INVERTIQ_ON 0x40 +#define RFLR_INVERTIQ_RX_MASK 0xBF +#define RFLR_INVERTIQ_RX_OFF 0x00 +#define RFLR_INVERTIQ_RX_ON 0x40 +#define RFLR_INVERTIQ_TX_MASK 0xFE +#define RFLR_INVERTIQ_TX_OFF 0x01 +#define RFLR_INVERTIQ_TX_ON 0x00 /*! * RegDetectionThreshold diff --git a/src/radio/sx1276/sx1276.c b/src/radio/sx1276/sx1276.c index 91411b18a..f5e1910cc 100644 --- a/src/radio/sx1276/sx1276.c +++ b/src/radio/sx1276/sx1276.c @@ -141,11 +141,8 @@ const RadioRegisters_t RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE; /*! * Constant values need to compute the RSSI value */ -#define NOISE_ABSOLUTE_ZERO -174.0 -#define NOISE_FIGURE_LF 4.0 -#define NOISE_FIGURE_HF 6.0 -#define RSSI_OFFSET_LF -164.0 -#define RSSI_OFFSET_HF -157.0 +#define RSSI_OFFSET_LF -164 +#define RSSI_OFFSET_HF -157 /*! * Precomputed FSK bandwidth registers values @@ -172,7 +169,8 @@ const FskBandwidth_t FskBandwidths[] = { 125000, 0x02 }, { 166700, 0x11 }, { 200000, 0x09 }, - { 250000, 0x01 } + { 250000, 0x01 }, + { 0, 0x00 }, // Invalid Badwidth }; /* @@ -260,9 +258,9 @@ void SX1276SetChannel( uint32_t freq ) SX1276Write( REG_FRFLSB, ( uint8_t )( freq & 0xFF ) ); } -bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int8_t rssiThresh ) +bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ) { - int8_t rssi = 0; + int16_t rssi = 0; SX1276SetModem( modem ); @@ -383,7 +381,9 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, uint16_t symbTimeout, bool fixLen, - bool crcOn, bool iqInverted, bool rxContinuous ) + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) { SX1276SetModem( modem ); @@ -395,6 +395,7 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1276.Settings.Fsk.Datarate = datarate; SX1276.Settings.Fsk.BandwidthAfc = bandwidthAfc; SX1276.Settings.Fsk.FixLen = fixLen; + SX1276.Settings.Fsk.PayloadLen = payloadLen; SX1276.Settings.Fsk.CrcOn = crcOn; SX1276.Settings.Fsk.IqInverted = iqInverted; SX1276.Settings.Fsk.RxContinuous = rxContinuous; @@ -407,8 +408,8 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1276Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) ); SX1276Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) ); - SX1276Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); - SX1276Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + SX1276Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); + SX1276Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); SX1276Write( REG_PACKETCONFIG1, ( SX1276Read( REG_PACKETCONFIG1 ) & @@ -430,7 +431,10 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1276.Settings.LoRa.Datarate = datarate; SX1276.Settings.LoRa.Coderate = coderate; SX1276.Settings.LoRa.FixLen = fixLen; + SX1276.Settings.LoRa.PayloadLen = payloadLen; SX1276.Settings.LoRa.CrcOn = crcOn; + SX1276.Settings.LoRa.FreqHopOn = freqHopOn; + SX1276.Settings.LoRa.HopPeriod = hopPeriod; SX1276.Settings.LoRa.IqInverted = iqInverted; SX1276.Settings.LoRa.RxContinuous = rxContinuous; @@ -479,6 +483,17 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1276Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); SX1276Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + if( fixLen == 1 ) + { + SX1276Write( REG_LR_PAYLOADLENGTH, payloadLen ); + } + + if( SX1276.Settings.LoRa.FreqHopOn == true ) + { + SX1276Write( REG_LR_PLLHOP, ( SX1276Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + SX1276Write( REG_LR_HOPPERIOD, SX1276.Settings.LoRa.HopPeriod ); + } + if( datarate == 6 ) { SX1276Write( REG_LR_DETECTOPTIMIZE, @@ -497,11 +512,6 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, SX1276Write( REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); } - - SX1276Write( REG_LR_INVERTIQ, - ( SX1276Read( REG_LR_INVERTIQ ) & - RFLR_INVERTIQ_MASK ) | - ( iqInverted << 6 ) ); } break; } @@ -510,8 +520,8 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preambleLen, - bool fixLen, bool crcOn, - bool iqInverted, uint32_t timeout ) + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) { uint8_t paConfig = 0; uint8_t paDac = 0; @@ -622,6 +632,8 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, SX1276.Settings.LoRa.Coderate = coderate; SX1276.Settings.LoRa.PreambleLen = preambleLen; SX1276.Settings.LoRa.FixLen = fixLen; + SX1276.Settings.LoRa.FreqHopOn = freqHopOn; + SX1276.Settings.LoRa.HopPeriod = hopPeriod; SX1276.Settings.LoRa.CrcOn = crcOn; SX1276.Settings.LoRa.IqInverted = iqInverted; SX1276.Settings.LoRa.TxTimeout = timeout; @@ -644,6 +656,12 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, SX1276.Settings.LoRa.LowDatarateOptimize = 0x00; } + if( SX1276.Settings.LoRa.FreqHopOn == true ) + { + SX1276Write( REG_LR_PLLHOP, ( SX1276Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + SX1276Write( REG_LR_HOPPERIOD, SX1276.Settings.LoRa.HopPeriod ); + } + SX1276Write( REG_LR_MODEMCONFIG1, ( SX1276Read( REG_LR_MODEMCONFIG1 ) & RFLR_MODEMCONFIG1_BW_MASK & @@ -684,11 +702,6 @@ void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, SX1276Write( REG_LR_DETECTIONTHRESHOLD, RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); } - - SX1276Write( REG_LR_INVERTIQ, - ( SX1276Read( REG_LR_INVERTIQ ) & - RFLR_INVERTIQ_MASK ) | - ( iqInverted << 6 ) ); } break; } @@ -810,6 +823,15 @@ void SX1276Send( uint8_t *buffer, uint8_t size ) break; case MODEM_LORA: { + if( SX1276.Settings.LoRa.IqInverted == true ) + { + SX1276Write( REG_LR_INVERTIQ, ( ( SX1276Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) ); + } + else + { + SX1276Write( REG_LR_INVERTIQ, ( ( SX1276Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + } + SX1276.Settings.LoRaPacketHandler.Size = size; // Initializes the payload size @@ -839,14 +861,18 @@ void SX1276SetSleep( void ) { TimerStop( &RxTimeoutTimer ); TimerStop( &TxTimeoutTimer ); + SX1276SetOpMode( RF_OPMODE_SLEEP ); + SX1276.Settings.State = RF_IDLE; } void SX1276SetStby( void ) { TimerStop( &RxTimeoutTimer ); TimerStop( &TxTimeoutTimer ); + SX1276SetOpMode( RF_OPMODE_STANDBY ); + SX1276.Settings.State = RF_IDLE; } void SX1276SetRx( uint32_t timeout ) @@ -885,19 +911,45 @@ void SX1276SetRx( uint32_t timeout ) break; case MODEM_LORA: { + if( SX1276.Settings.LoRa.IqInverted == true ) + { + SX1276Write( REG_LR_INVERTIQ, ( ( SX1276Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) ); + } + else + { + SX1276Write( REG_LR_INVERTIQ, ( ( SX1276Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + } + rxContinuous = SX1276.Settings.LoRa.RxContinuous; - SX1276Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | - //RFLR_IRQFLAGS_RXDONE | - //RFLR_IRQFLAGS_PAYLOADCRCERROR | - RFLR_IRQFLAGS_VALIDHEADER | - RFLR_IRQFLAGS_TXDONE | - RFLR_IRQFLAGS_CADDONE | - RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | - RFLR_IRQFLAGS_CADDETECTED ); - - // DIO0=RxDone - SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + if( SX1276.Settings.LoRa.FreqHopOn == true ) + { + SX1276Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone, DIO2=FhssChangeChannel + SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + SX1276Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone + SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + } SX1276Write( REG_LR_FIFORXBASEADDR, 0 ); SX1276Write( REG_LR_FIFOADDRPTR, 0 ); } @@ -964,17 +1016,34 @@ void SX1276SetTx( uint32_t timeout ) break; case MODEM_LORA: { - SX1276Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | - RFLR_IRQFLAGS_RXDONE | - RFLR_IRQFLAGS_PAYLOADCRCERROR | - RFLR_IRQFLAGS_VALIDHEADER | - //RFLR_IRQFLAGS_TXDONE | - RFLR_IRQFLAGS_CADDONE | - RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | - RFLR_IRQFLAGS_CADDETECTED ); - - // DIO0=TxDone - SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 ); + if( SX1276.Settings.LoRa.FreqHopOn == true ) + { + SX1276Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone, DIO2=FhssChangeChannel + SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + SX1276Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone + SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 ); + } } break; } @@ -984,9 +1053,42 @@ void SX1276SetTx( uint32_t timeout ) SX1276SetOpMode( RF_OPMODE_TRANSMITTER ); } -int8_t SX1276ReadRssi( RadioModems_t modem ) +void SX1276StartCad( void ) { - int8_t rssi = 0; + switch( SX1276.Settings.Modem ) + { + case MODEM_FSK: + { + + } + break; + case MODEM_LORA: + { + SX1276Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + //RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL // | + //RFLR_IRQFLAGS_CADDETECTED + ); + + // DIO3=CADDone + SX1276Write( REG_DIOMAPPING1, ( SX1276Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + + SX1276.Settings.State = RF_CAD; + SX1276SetOpMode( RFLR_OPMODE_CAD ); + } + break; + default: + break; + } +} + +int16_t SX1276ReadRssi( RadioModems_t modem ) +{ + int16_t rssi = 0; switch( modem ) { @@ -1143,7 +1245,6 @@ void SX1276ReadFifo( uint8_t *buffer, uint8_t size ) void SX1276OnTimeoutIrq( void ) { - RadioState_t state = RF_IDLE; switch( SX1276.Settings.State ) { case RF_RX_RUNNING: @@ -1162,13 +1263,13 @@ void SX1276OnTimeoutIrq( void ) if( SX1276.Settings.Fsk.RxContinuous == true ) { - state = SX1276.Settings.State; // Continuous mode restart Rx chain SX1276Write( REG_RXCONFIG, SX1276Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); } else { - TimerStart( &RxTimeoutSyncWord ); + SX1276.Settings.State = RF_IDLE; + TimerStop( &RxTimeoutSyncWord ); } } if( ( RadioEvents != NULL ) && ( RadioEvents->RxTimeout != NULL ) ) @@ -1177,6 +1278,7 @@ void SX1276OnTimeoutIrq( void ) } break; case RF_TX_RUNNING: + SX1276.Settings.State = RF_IDLE; if( ( RadioEvents != NULL ) && ( RadioEvents->TxTimeout != NULL ) ) { RadioEvents->TxTimeout( ); @@ -1185,7 +1287,6 @@ void SX1276OnTimeoutIrq( void ) default: break; } - SX1276.Settings.State = state; } void SX1276OnDio0Irq( void ) @@ -1275,7 +1376,7 @@ void SX1276OnDio0Irq( void ) break; case MODEM_LORA: { - uint8_t snr = 0; + int8_t snr = 0; // Clear Irq SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE ); @@ -1312,8 +1413,8 @@ void SX1276OnDio0Irq( void ) snr = ( SX1276.Settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2; } - int8_t rssi = SX1276Read( REG_LR_PKTRSSIVALUE ); - if( SX1276.Settings.LoRaPacketHandler.SnrValue < 0 ) + int16_t rssi = SX1276Read( REG_LR_PKTRSSIVALUE ); + if( snr < 0 ) { if( SX1276.Settings.Channel > RF_MID_BAND_THRESH ) { @@ -1478,6 +1579,16 @@ void SX1276OnDio2Irq( void ) } break; case MODEM_LORA: + if( SX1276.Settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if( ( RadioEvents != NULL ) && ( RadioEvents->FhssChangeChannel != NULL ) ) + { + RadioEvents->FhssChangeChannel( ( SX1276Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } break; default: break; @@ -1489,6 +1600,16 @@ void SX1276OnDio2Irq( void ) case MODEM_FSK: break; case MODEM_LORA: + if( SX1276.Settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if( ( RadioEvents != NULL ) && ( RadioEvents->FhssChangeChannel != NULL ) ) + { + RadioEvents->FhssChangeChannel( ( SX1276Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } break; default: break; @@ -1506,6 +1627,24 @@ void SX1276OnDio3Irq( void ) case MODEM_FSK: break; case MODEM_LORA: + if( ( SX1276Read( REG_LR_IRQFLAGS ) & RFLR_IRQFLAGS_CADDETECTED ) == RFLR_IRQFLAGS_CADDETECTED ) + { + // Clear Irq + SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE ); + if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) ) + { + RadioEvents->CadDone( true ); + } + } + else + { + // Clear Irq + SX1276Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE ); + if( ( RadioEvents != NULL ) && ( RadioEvents->CadDone != NULL ) ) + { + RadioEvents->CadDone( false ); + } + } break; default: break; diff --git a/src/radio/sx1276/sx1276.h b/src/radio/sx1276/sx1276.h index ccbeb2be5..6c06e17b5 100644 --- a/src/radio/sx1276/sx1276.h +++ b/src/radio/sx1276/sx1276.h @@ -35,6 +35,7 @@ typedef struct uint32_t Datarate; uint16_t PreambleLen; bool FixLen; + uint8_t PayloadLen; bool CrcOn; bool IqInverted; bool RxContinuous; @@ -69,7 +70,10 @@ typedef struct uint8_t Coderate; uint16_t PreambleLen; bool FixLen; + uint8_t PayloadLen; bool CrcOn; + bool FreqHopOn; + uint8_t HopPeriod; bool IqInverted; bool RxContinuous; uint32_t TxTimeout; @@ -81,7 +85,7 @@ typedef struct typedef struct { int8_t SnrValue; - int8_t RssiValue; + int16_t RssiValue; uint8_t Size; }RadioLoRaPacketHandler_t; @@ -172,7 +176,7 @@ void SX1276SetChannel( uint32_t freq ); * * \retval isFree [true: Channel is free, false: Channel is not free] */ -bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int8_t rssiThresh ); +bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); /*! * \brief Generates a 32 bits random value based on the RSSI readings @@ -213,7 +217,14 @@ uint32_t SX1276Random( void ); * FSK : N/A ( set to 0 ) * LoRa: timeout in symbols * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * \param [IN] payloadLen Sets payload length when fixed lenght is used * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols * \param [IN] iqInverted Inverts IQ signals (LoRa only) * FSK : N/A ( set to 0 ) * LoRa: [0: not inverted, 1: inverted] @@ -224,7 +235,9 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint32_t bandwidthAfc, uint16_t preambleLen, uint16_t symbTimeout, bool fixLen, - bool crcOn, bool iqInverted, bool rxContinuous ); + uint8_t payloadLen, + bool crcOn, bool FreqHopOn, uint8_t HopPeriod, + bool iqInverted, bool rxContinuous ); /*! * \brief Sets the transmission parameters @@ -252,6 +265,12 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, * LoRa: Length in symbols (the hardware adds 4 more symbols) * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping + * FSK : N/A ( set to 0 ) + * LoRa: [0: OFF, 1: ON] + * \param [IN] HopPeriod Number of symbols bewteen each hop + * FSK : N/A ( set to 0 ) + * LoRa: Number of symbols * \param [IN] iqInverted Inverts IQ signals (LoRa only) * FSK : N/A ( set to 0 ) * LoRa: [0: not inverted, 1: inverted] @@ -260,8 +279,8 @@ void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, uint32_t bandwidth, uint32_t datarate, uint8_t coderate, uint16_t preambleLen, - bool fixLen, bool crcOn, - bool iqInverted, uint32_t timeout ); + bool fixLen, bool crcOn, bool FreqHopOn, + uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); /*! * \brief Computes the packet time on air for the given payload @@ -300,12 +319,17 @@ void SX1276SetStby( void ); */ void SX1276SetRx( uint32_t timeout ); +/*! + * \brief Start a Channel Activity Detection + */ +void SX1276StartCad( void ); + /*! * \brief Reads the current RSSI value * * \retval rssiValue Current RSSI value in [dBm] */ -int8_t SX1276ReadRssi( RadioModems_t modem ); +int16_t SX1276ReadRssi( RadioModems_t modem ); /*! * \brief Writes the radio register at the specified address diff --git a/src/radio/sx1276/sx1276Regs-LoRa.h b/src/radio/sx1276/sx1276Regs-LoRa.h index eafcdd9b5..d37c640bf 100644 --- a/src/radio/sx1276/sx1276Regs-LoRa.h +++ b/src/radio/sx1276/sx1276Regs-LoRa.h @@ -66,6 +66,8 @@ Maintainer: Miguel Luis and Gregory Cristian #define REG_LR_DETECTOPTIMIZE 0x31 #define REG_LR_INVERTIQ 0x33 #define REG_LR_DETECTIONTHRESHOLD 0x37 +#define REG_LR_SYNCWORD 0x39 + // end of documented register in datasheet // I/O settings #define REG_LR_DIOMAPPING1 0x40 @@ -436,9 +438,12 @@ Maintainer: Miguel Luis and Gregory Cristian /*! * RegInvertIQ */ -#define RFLR_INVERTIQ_MASK 0xBF -#define RFLR_INVERTIQ_OFF 0x00 -#define RFLR_INVERTIQ_ON 0x40 +#define RFLR_INVERTIQ_RX_MASK 0xBF +#define RFLR_INVERTIQ_RX_OFF 0x00 +#define RFLR_INVERTIQ_RX_ON 0x40 +#define RFLR_INVERTIQ_TX_MASK 0xFE +#define RFLR_INVERTIQ_TX_OFF 0x01 +#define RFLR_INVERTIQ_TX_ON 0x00 /*! * RegDetectionThreshold diff --git a/src/system/delay.c b/src/system/delay.c index 29404b579..f0b239f6a 100644 --- a/src/system/delay.c +++ b/src/system/delay.c @@ -21,9 +21,12 @@ void Delay( float s ) void DelayMs( uint32_t ms ) { -#ifdef LOW_POWER_MODE_ENABLE - RtcDelayMs( ms ); -#else - TimerHwDelayMs( ms ); -#endif + if( TimerGetLowPowerEnable( ) == true ) + { + RtcDelayMs( ms ); + } + else + { + TimerHwDelayMs( ms ); + } } diff --git a/src/system/eeprom.c b/src/system/eeprom.c new file mode 100644 index 000000000..b2e47adcb --- /dev/null +++ b/src/system/eeprom.c @@ -0,0 +1,218 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Timer objects and scheduling management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#include "board.h" + +#include "i2c-board.h" +#include "i2c.h" + +#include "eeprom.h" + +#define DEVICE_I2C_ADDRESS 0xA8 + +static uint8_t I2cDeviceAddr = DEVICE_I2C_ADDRESS; + +#define EE_PAGE_SIZE 64 + +uint8_t EepromWriteBuffer( uint16_t addr, uint8_t *buffer, uint16_t size ) +{ + uint8_t nbPage = 0; + uint8_t nbBytes = 0; + uint8_t nbBytesRemaining = 0; + uint16_t lAddr = 0; + + lAddr = addr % EE_PAGE_SIZE; + nbBytesRemaining = EE_PAGE_SIZE - lAddr; + nbPage = size / EE_PAGE_SIZE; + nbBytes = size % EE_PAGE_SIZE; + + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_16 ); + /*!< If lAddr is EE_PAGE_SIZE aligned */ + if( lAddr == 0 ) + { + /*!< If size < EE_PAGE_SIZE */ + if( nbPage == 0 ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, size ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + } + /*!< If size > EE_PAGE_SIZE */ + else + { + while( nbPage-- ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, EE_PAGE_SIZE ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + addr += EE_PAGE_SIZE; + buffer += EE_PAGE_SIZE; + } + + if( nbBytes != 0 ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, nbBytes ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + } + } + } + /*!< If addr is not EE_PAGE_SIZE aligned */ + else + { + /*!< If size < EE_PAGE_SIZE */ + if( nbPage== 0 ) + { + /*!< If the number of data to be written is more than the remaining space + in the current page: */ + if ( size > nbBytesRemaining ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, nbBytesRemaining ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, ( addr + nbBytesRemaining ), + ( uint8_t* )( buffer + nbBytesRemaining ), + ( size - nbBytesRemaining ) ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + } + else + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, nbBytes ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + } + } + /*!< If size > EE_PAGE_SIZE */ + else + { + size -= nbBytesRemaining; + nbPage = size / EE_PAGE_SIZE; + nbBytes = size % EE_PAGE_SIZE; + + if( nbBytesRemaining != 0 ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, nbBytesRemaining ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + addr += nbBytesRemaining; + buffer += nbBytesRemaining; + } + + while( nbPage-- ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, EE_PAGE_SIZE ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + addr += EE_PAGE_SIZE; + buffer += EE_PAGE_SIZE; + } + if( nbBytes != 0 ) + { + if( I2cWriteBuffer( &I2c, I2cDeviceAddr, addr, buffer, nbBytes ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + if( I2cMcuWaitStandbyState( &I2c, I2cDeviceAddr ) == FAIL ) + { + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return FAIL; + } + } + } + } + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + return SUCCESS; +} + +uint8_t EepromReadBuffer( uint16_t addr, uint8_t *buffer, uint16_t size ) +{ + uint8_t status = FAIL; + + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_16 ); + + status = I2cReadBuffer( &I2c, I2cDeviceAddr, addr, buffer, size ); + + I2cSetAddrSize( &I2c, I2C_ADDR_SIZE_8 ); + + return status; +} + +void EepromSetDeviceAddr( uint8_t addr ) +{ + I2cDeviceAddr = addr; +} + +uint8_t EepromGetDeviceAddr( void ) +{ + return I2cDeviceAddr; +} diff --git a/src/system/eeprom.h b/src/system/eeprom.h new file mode 100644 index 000000000..d1bf83d28 --- /dev/null +++ b/src/system/eeprom.h @@ -0,0 +1,25 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C)2013 Semtech + +Description: Timer objects and scheduling management + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __EEPROM_H__ +#define __EEPROM_H__ + +uint8_t EepromWriteBuffer( uint16_t addr, uint8_t *buffer, uint16_t size ); +uint8_t EepromReadBuffer( uint16_t addr, uint8_t *buffer, uint16_t size ); +void EepromSetDeviceAddr( uint8_t addr ); +uint8_t EepromGetDeviceAddr( void ); + + +#endif // __EEPROM_H__ + diff --git a/src/system/i2c.c b/src/system/i2c.c index 7d32dd849..e7cfdf61b 100644 --- a/src/system/i2c.c +++ b/src/system/i2c.c @@ -43,14 +43,14 @@ void I2cResetBus( I2c_t *obj ) I2cInit( obj, I2C_SCL, I2C_SDA ); } -uint8_t I2cWrite( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data ) +uint8_t I2cWrite( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t data ) { if( I2cInitialized == true ) { - if( I2cMcuWriteBuffer( obj, deviceAddress, registerAddress, data, 1 ) == FAIL ) + if( I2cMcuWriteBuffer( obj, deviceAddr, addr, &data, 1 ) == FAIL ) { // if first attempt fails due to an IRQ, try a second time - if( I2cMcuWriteBuffer( obj, deviceAddress, registerAddress, data, 1 ) == FAIL ) + if( I2cMcuWriteBuffer( obj, deviceAddr, addr, &data, 1 ) == FAIL ) { return FAIL; } @@ -70,14 +70,14 @@ uint8_t I2cWrite( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, ui } } -uint8_t I2cWriteBuffer( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, uint8_t size ) +uint8_t I2cWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { if( I2cInitialized == true ) { - if( I2cMcuWriteBuffer( obj, deviceAddress, registerAddress, data, size ) == FAIL ) + if( I2cMcuWriteBuffer( obj, deviceAddr, addr, buffer, size ) == FAIL ) { // if first attempt fails due to an IRQ, try a second time - if( I2cMcuWriteBuffer( obj, deviceAddress, registerAddress, data, size ) == FAIL ) + if( I2cMcuWriteBuffer( obj, deviceAddr, addr, buffer, size ) == FAIL ) { return FAIL; } @@ -97,11 +97,11 @@ uint8_t I2cWriteBuffer( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddre } } -uint8_t I2cRead( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data ) +uint8_t I2cRead( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *data ) { if( I2cInitialized == true ) { - return( I2cMcuReadBuffer( obj, deviceAddress, registerAddress, data, 1 ) ); + return( I2cMcuReadBuffer( obj, deviceAddr, addr, data, 1 ) ); } else { @@ -109,11 +109,11 @@ uint8_t I2cRead( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uin } } -uint8_t I2cReadBuffer( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, uint8_t size ) +uint8_t I2cReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ) { if( I2cInitialized == true ) { - return( I2cMcuReadBuffer( obj, deviceAddress, registerAddress, data, size ) ); + return( I2cMcuReadBuffer( obj, deviceAddr, addr, buffer, size ) ); } else { diff --git a/src/system/i2c.h b/src/system/i2c.h index 617e0ef53..eca1ab3a9 100644 --- a/src/system/i2c.h +++ b/src/system/i2c.h @@ -52,42 +52,42 @@ void I2cResetBus( I2c_t *obj ); * \brief Write data to the I2C device * * \param [IN] obj I2C object - * \param [IN] deviceAddress device address - * \param [IN] registerAddress register address + * \param [IN] deviceAddr device address + * \param [IN] addr data address * \param [IN] data data to write */ -uint8_t I2cWrite( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data ); +uint8_t I2cWrite( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t data ); /*! * \brief Write several data to the I2C device * * \param [IN] obj I2C object - * \param [IN] deviceAddress device address - * \param [IN] registerAddress register address - * \param [IN] data data buffer to write - * \param [IN] size number of data byte to write + * \param [IN] deviceAddr device address + * \param [IN] addr data address + * \param [IN] buffer data buffer to write + * \param [IN] size number of bytes to write */ -uint8_t I2cWriteBuffer( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, uint8_t size ); +uint8_t I2cWriteBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); /*! * \brief Read data from the I2C device * * \param [IN] obj I2C object - * \param [IN] deviceAddress device address - * \param [IN] registerAddress register address - * \param [IN] data data buffer used to store the data read + * \param [IN] deviceAddr device address + * \param [IN] addr data address + * \param [OUT] data variable used to store the data read */ -uint8_t I2cRead( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data ); +uint8_t I2cRead( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *data ); /*! * \brief Read several data byte from the I2C device * * \param [IN] obj I2C object - * \param [IN] deviceAddress device address - * \param [IN] registerAddress register address - * \param [IN] data data buffer used to store the data read + * \param [IN] deviceAddr device address + * \param [IN] addr data address + * \param [OUT] buffer data buffer used to store the data read * \param [IN] size number of data byte to read */ -uint8_t I2cReadBuffer( I2c_t *obj, uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, uint8_t size ); +uint8_t I2cReadBuffer( I2c_t *obj, uint8_t deviceAddr, uint16_t addr, uint8_t *buffer, uint16_t size ); #endif // __I2C_H__ diff --git a/src/system/timer.c b/src/system/timer.c index 604b04e30..636d8b8b5 100644 --- a/src/system/timer.c +++ b/src/system/timer.c @@ -13,11 +13,10 @@ License: Revised BSD License, see LICENSE.TXT file include in the project Maintainer: Miguel Luis and Gregory Cristian */ #include "board.h" -#ifdef LOW_POWER_MODE_ENABLE #include "rtc-board.h" -#else #include "timer-board.h" -#endif + +static bool LowPowerModeEnable = true; /*! * This flag is used to make sure we have looped through the main several time to avoid race issues @@ -71,6 +70,15 @@ static bool TimerExists( TimerEvent_t *obj ); */ uint32_t TimerGetValue( void ); +void TimerSetLowPowerEnable( bool enable ) +{ + LowPowerModeEnable = enable; +} + +bool TimerGetLowPowerEnable( void ) +{ + return LowPowerModeEnable; +} void TimerInit( TimerEvent_t *obj, void ( *callback )( void ) ) { @@ -203,12 +211,13 @@ void TimerIrqHandler( void ) { uint32_t elapsedTime = 0; -#ifndef LOW_POWER_MODE_ENABLE - if( TimerListHead == NULL ) + if( LowPowerModeEnable == false ) { - return; // Only necessary when the standard timer is used as a time base + if( TimerListHead == NULL ) + { + return; // Only necessary when the standard timer is used as a time base + } } -#endif elapsedTime = TimerGetValue( ); @@ -372,11 +381,14 @@ void TimerSetValue( TimerEvent_t *obj, uint32_t value ) TimerStop( obj ); -#ifdef LOW_POWER_MODE_ENABLE - minValue = RtcGetMinimumTimeout( ); -#else - minValue = TimerHwGetMinimumTimeout( ); -#endif + if( LowPowerModeEnable == true ) + { + minValue = RtcGetMinimumTimeout( ); + } + else + { + minValue = TimerHwGetMinimumTimeout( ); + } if( value < minValue ) { @@ -391,11 +403,14 @@ uint32_t TimerGetValue( void ) { uint32_t valTimer = 0; -#ifdef LOW_POWER_MODE_ENABLE - valTimer = RtcGetTimerElapsedTime( ); -#else - valTimer = TimerHwGetElapsedTime( ); -#endif + if( LowPowerModeEnable == true ) + { + valTimer = RtcGetTimerElapsedTime( ); + } + else + { + valTimer = TimerHwGetElapsedTime( ); + } return valTimer; } @@ -404,11 +419,14 @@ static void TimerSetTimeout( TimerEvent_t *obj ) { HasLoopedThroughMain = 0; -#ifdef LOW_POWER_MODE_ENABLE - RtcSetTimeout( obj->Timestamp ); -#else - TimerHwStart( obj->Timestamp ); -#endif + if( LowPowerModeEnable == true ) + { + RtcSetTimeout( obj->Timestamp ); + } + else + { + TimerHwStart( obj->Timestamp ); + } } void TimerLowPowerHandler( void ) @@ -423,11 +441,14 @@ void TimerLowPowerHandler( void ) { HasLoopedThroughMain = 0; -#ifdef LOW_POWER_MODE_ENABLE - RtcEnterLowPowerStopMode( ); -#else - TimerHwEnterLowPowerStopMode( ); -#endif + if( LowPowerModeEnable == true ) + { + RtcEnterLowPowerStopMode( ); + } + else + { + TimerHwEnterLowPowerStopMode( ); + } } } } diff --git a/src/system/timer.h b/src/system/timer.h index 2936ea31b..d6a47423c 100644 --- a/src/system/timer.h +++ b/src/system/timer.h @@ -27,6 +27,20 @@ typedef struct TimerEvent_s struct TimerEvent_s *Next; //! Pointer to the next Timer object. }TimerEvent_t; +/*! + * \brief Enables/Disables low power timers usage + * + * \param [IN] enable [true]RTC timer used, [false]Normal timer used + */ +void TimerSetLowPowerEnable( bool enable ); + +/*! + * \brief Initializes the timer object + * + * \retval enable [true]RTC timer used, [false]Normal timer used + */ +bool TimerGetLowPowerEnable( void ); + /*! * \brief Initializes the timer object * diff --git a/src/system/uart.c b/src/system/uart.c index ecf83d9f6..41217d6f9 100644 --- a/src/system/uart.c +++ b/src/system/uart.c @@ -113,24 +113,35 @@ uint8_t UartGetChar( Uart_t *obj, uint8_t *data ) uint8_t UartPutBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size ) { - uint8_t retryCount; - uint16_t i; - - for( i = 0; i < size; i++ ) + if( obj->UartId == UART_USB_CDC ) { - retryCount = 0; - while( UartPutChar( obj, buffer[i] ) != 0 ) - { - retryCount++; +#if defined( USE_USB_CDC ) + return UartUsbPutBuffer( obj, buffer, size ); +#else + return 255; // Not supported +#endif + } + else + { + uint8_t retryCount; + uint16_t i; - // Exit if something goes terribly wrong - if( retryCount > TX_BUFFER_RETRY_COUNT ) + for( i = 0; i < size; i++ ) + { + retryCount = 0; + while( UartPutChar( obj, buffer[i] ) != 0 ) { - return 1; // Error + retryCount++; + + // Exit if something goes terribly wrong + if( retryCount > TX_BUFFER_RETRY_COUNT ) + { + return 1; // Error + } } } + return 0; // OK } - return 0; // OK } uint8_t UartGetBuffer( Uart_t *obj, uint8_t *buffer, uint16_t size, uint16_t *nbReadBytes )