added NRF52 pwm, icu, i2c, radio esb drivers

This commit is contained in:
andru 2019-01-08 11:22:01 +03:00
parent 5af099c366
commit 2168085ac7
39 changed files with 10514 additions and 109 deletions

View File

@ -0,0 +1,81 @@
/*
Copyright (C) 2016 Stéphane D'Alu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "hal.h"
#if HAL_USE_PAL || defined(__DOXYGEN__)
/**
* @brief PAL setup.
* @details Digital I/O ports static configuration as defined in @p board.h.
* This variable is used by the HAL when initializing the PAL driver.
*/
const PALConfig pal_default_config =
{
.pads = {
PAL_MODE_UNCONNECTED, /* P0.0 : XTAL (32MHz) */
PAL_MODE_UNCONNECTED, /* P0.1 : XTAL (32MHz) */
PAL_MODE_UNCONNECTED, /* P0.2 */
PAL_MODE_UNCONNECTED, /* P0.3 */
PAL_MODE_UNCONNECTED, /* P0.4 */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.5 : UART_RTS */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.6 : UART_TX */
PAL_MODE_INPUT_PULLUP, /* P0.7 : UART_CTS */
PAL_MODE_INPUT_PULLUP, /* P0.8 : UART_RX */
PAL_MODE_UNCONNECTED, /* P0.9 */
PAL_MODE_UNCONNECTED, /* P0.10 */
PAL_MODE_UNCONNECTED, /* P0.11 */
PAL_MODE_UNCONNECTED, /* P0.12 */
PAL_MODE_INPUT, /* P0.13: BTN1 */
PAL_MODE_INPUT, /* P0.14: BTN2 */
PAL_MODE_INPUT_PULLUP, /* P0.15: BTN3 */
PAL_MODE_INPUT_PULLUP, /* P0.16: BTN4 */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.17: LED1 */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.18: LED2 */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.19: LED3 */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.20: LED4 */
PAL_MODE_UNCONNECTED, /* P0.21 */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.22: SPI_SS */
PAL_MODE_INPUT_PULLUP, /* P0.23: SPI_MISO */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.24: SPI_MOSI */
PAL_MODE_OUTPUT_PUSHPULL, /* P0.25: SPI_SCK */
PAL_MODE_OUTPUT_OPENDRAIN, /* P0.26: SDA */
PAL_MODE_OUTPUT_OPENDRAIN, /* P0.27: SCL */
PAL_MODE_UNCONNECTED, /* P0.28 */
PAL_MODE_UNCONNECTED, /* P0.29 */
PAL_MODE_UNCONNECTED, /* P0.30 */
PAL_MODE_UNCONNECTED, /* P0.31 */
},
};
#endif
/**
* @brief Early initialization code.
* @details This initialization is performed just after reset before BSS and
* DATA segments initialization.
*/
void __early_init(void)
{
}
/**
* @brief Late initialization code.
* @note This initialization is performed after BSS and DATA segments
* initialization and before invoking the main() function.
*/
void boardInit(void)
{
}

View File

@ -0,0 +1,164 @@
/*
Copyright (C) 2016 Stephane D'Alu
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _BOARD_H_
#define _BOARD_H_
/* Board identifier. */
#define BOARD_NRF52_EBYTE_E73
#define BOARD_NAME "nRF52 EBYTE E73-2G4M04S"
/* Board oscillators-related settings. */
#define NRF5_XTAL_VALUE 32000000
#define NRF5_HFCLK_SOURCE NRF5_HFCLK_HFXO
#define NRF5_LFCLK_SOURCE NRF5_LFCLK_XTAL
#define NRF5_HFCLK_HFINT 0
#define NRF5_HFCLK_HFXO 1
#define NRF5_LFCLK_RC 0
#define NRF5_LFCLK_XTAL 1
#define NRF5_LFCLK_SYNTH 2
/*
* GPIO pins.
*/
/* Defined by board */
#define BTN1 13U
#define BTN2 14U
#define BTN3 15U
#define BTN4 16U
#define LED1 17U
#define LED2 18U
#define LED3 19U
#define LED4 20U
#define UART_RTS 5U
#define UART_TX 6U
#define UART_CTS 7U
#define UART_RX 8U
#define NFC1 9U
#define NFC2 10U
#define I2C_SCL 27U
#define I2C_SDA 26U
/* Our definitions */
#define SPI_SCK 25U
#define SPI_MOSI 24U
#define SPI_MISO 23U
#define SPI_SS 22U
/* Analog input */
#define AIN0 2U
#define AIN1 3U
#define AIN2 4U
#define AIN3 5U
#define AIN4 28U
#define AIN5 29U
#define AIN6 30U
#define AIN7 31U
#define AREF0 AIN0
#define AREF1 AIN1
/*
* IO pins assignments.
*/
/* Defined by board */
#define IOPORT1_BTN1 13U
#define IOPORT1_BTN2 14U
#define IOPORT1_BTN3 15U
#define IOPORT1_BTN4 16U
#define IOPORT1_LED1 17U
#define IOPORT1_LED2 18U
#define IOPORT1_LED3 19U
#define IOPORT1_LED4 20U
#define IOPORT1_UART_RTS 5U
#define IOPORT1_UART_TX 6U
#define IOPORT1_UART_CTS 7U
#define IOPORT1_UART_RX 8U
#define IOPORT1_NFC1 9U
#define IOPORT1_NFC2 10U
#define IOPORT1_I2C_SCL 27U
#define IOPORT1_I2C_SDA 26U
#define IOPORT1_RESET 21U
/* Our definitions */
#define IOPORT1_SPI_SCK 25U
#define IOPORT1_SPI_MOSI 24U
#define IOPORT1_SPI_MISO 23U
#define IOPORT1_SPI_SS 22U
/* Analog inpupt */
#define IOPORT1_AIN0 2U
#define IOPORT1_AIN1 3U
#define IOPORT1_AIN2 4U
#define IOPORT1_AIN3 5U
#define IOPORT1_AIN4 28U
#define IOPORT1_AIN5 29U
#define IOPORT1_AIN6 30U
#define IOPORT1_AIN7 31U
#define IOPORT1_AREF0 IOPORT1_AIN0
#define IOPORT1_AREF1 IOPORT1_AIN1
/*
* IO lines assignments.
*/
/* Board defined */
#define LINE_BTN1 PAL_LINE(IOPORT1, IOPORT1_BTN1)
#define LINE_BTN2 PAL_LINE(IOPORT1, IOPORT1_BTN2)
#define LINE_BTN3 PAL_LINE(IOPORT1, IOPORT1_BTN3)
#define LINE_BTN4 PAL_LINE(IOPORT1, IOPORT1_BTN4)
#define LINE_LED1 PAL_LINE(IOPORT1, IOPORT1_LED1)
#define LINE_LED2 PAL_LINE(IOPORT1, IOPORT1_LED2)
#define LINE_LED3 PAL_LINE(IOPORT1, IOPORT1_LED3)
#define LINE_LED4 PAL_LINE(IOPORT1, IOPORT1_LED4)
#define LINE_UART_RTS PAL_LINE(IOPORT1, IOPORT1_UART_RTS)
#define LINE_UART_TX PAL_LINE(IOPORT1, IOPORT1_UART_TX)
#define LINE_UART_CTS PAL_LINE(IOPORT1, IOPORT1_UART_CTS)
#define LINE_UART_RX PAL_LINE(IOPORT1, IOPORT1_UART_RX)
#define LINE_NFC1 PAL_LINE(IOPORT1, IOPORT1_NFC1)
#define LINE_NFC2 PAL_LINE(IOPORT1, IOPORT1_NFC2)
#define LINE_I2C_SCL PAL_LINE(IOPORT1, IOPORT1_I2C_SCL)
#define LINE_I2C_SDA PAL_LINE(IOPORT1, IOPORT1_I2C_SDA)
/* Our definitions */
#define LINE_SPI_SCK PAL_LINE(IOPORT1, IOPORT1_SPI_SCK)
#define LINE_SPI_MOSI PAL_LINE(IOPORT1, IOPORT1_SPI_MOSI)
#define LINE_SPI_MISO PAL_LINE(IOPORT1, IOPORT1_SPI_MISO)
#define LINE_SPI_SS PAL_LINE(IOPORT1, IOPORT1_SPI_SS)
/* Analog line */
#define LINE_AIN0 PAL_LINE(IOPORT1, IOPORT1_AIN0)
#define LINE_AIN1 PAL_LINE(IOPORT1, IOPORT1_AIN1)
#define LINE_AIN2 PAL_LINE(IOPORT1, IOPORT1_AIN2)
#define LINE_AIN3 PAL_LINE(IOPORT1, IOPORT1_AIN3)
#define LINE_AIN4 PAL_LINE(IOPORT1, IOPORT1_AIN4)
#define LINE_AIN5 PAL_LINE(IOPORT1, IOPORT1_AIN5)
#define LINE_AIN6 PAL_LINE(IOPORT1, IOPORT1_AIN6)
#define LINE_AIN7 PAL_LINE(IOPORT1, IOPORT1_AIN7)
#define LINE_AREF0 PAL_LINE(IOPORT1, IOPORT1_AREF0)
#define LINE_AREF1 PAL_LINE(IOPORT1, IOPORT1_AREF1)
#if !defined(_FROM_ASM_)
#ifdef __cplusplus
extern "C" {
#endif
void boardInit(void);
#ifdef __cplusplus
}
#endif
#endif /* _FROM_ASM_ */
#endif /* _BOARD_H_ */

View File

@ -0,0 +1,8 @@
# List of all the board related files.
BOARDSRC = ${CHIBIOS_CONTRIB}/os/hal/boards/NRF52-E73-2G4M04S/board.c
# Required include directories
BOARDINC = ${CHIBIOS_CONTRIB}/os/hal/boards/NRF52-E73-2G4M04S
ALLCSRC += $(BOARDSRC)
ALLINC += $(BOARDINC)

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_PWM TRUE,$(HALCONF)),)
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/PWMv2/hal_pwm_lld.c
endif
else
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/PWMv2/hal_pwm_lld.c
endif
PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/PWMv2

View File

@ -0,0 +1,402 @@
/*
ChibiOS/HAL - Copyright (C) 2018 Andru
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_pwm_lld.c
* @brief NRF52 PWM subsystem low level driver source.
*
* @addtogroup PWM
* @{
*/
#include "hal.h"
#if HAL_USE_PWM || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
uint16_t pwm_seq[PWM_CHANNELS];
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief PWMD1 driver identifier.
* @note The driver PWMD1 enabled.
*/
#if NRF5_PWM_USE_PWM0 || defined(__DOXYGEN__)
PWMDriver PWMD1;
#endif
/**
* @brief PWMD2 driver identifier.
* @note The driver PWMD2 enabled.
*/
#if NRF5_PWM_USE_PWM1 || defined(__DOXYGEN__)
PWMDriver PWMD2;
#endif
/**
* @brief PWMD3 driver identifier.
* @note The driver PWMD3 enabled.
*/
#if NRF5_PWM_USE_PWM2 || defined(__DOXYGEN__)
PWMDriver PWMD3;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
static void pwm_lld_serve_interrupt(PWMDriver *pwmp) {
/* Deal with PWM period
*/
if (pwmp->config->callback == NULL) {
return;
}
if ((pwmp->pwm->INTEN & PWM_INTEN_PWMPERIODEND_Msk) && (pwmp->pwm->EVENTS_PWMPERIODEND)) {
pwmp->config->callback(pwmp);
pwmp->pwm->EVENTS_PWMPERIODEND = 0;
(void)pwmp->pwm->EVENTS_PWMPERIODEND;
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if NRF5_PWM_USE_PWM0
/**
* @brief PWM0 interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(VectorB0) {
OSAL_IRQ_PROLOGUE();
pwm_lld_serve_interrupt(&PWMD1);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_PWM_USE_PWM0 */
#if NRF5_PWM_USE_PWM1
/**
* @brief PWM1 interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(VectorC4) {
OSAL_IRQ_PROLOGUE();
pwm_lld_serve_interrupt(&PWMD2);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_PWM_USE_PWM1 */
#if NRF5_PWM_USE_PWM2
/**
* @brief PWM2 interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(VectorC8) {
OSAL_IRQ_PROLOGUE();
pwm_lld_serve_interrupt(&PWMD3);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_PWM_USE_PWM2 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level PWM driver initialization.
*
* @notapi
*/
void pwm_lld_init(void) {
#if NRF5_PWM_USE_PWM0
pwmObjectInit(&PWMD1);
PWMD1.channels = PWM_CHANNELS;
PWMD1.pwm = NRF_PWM0;
#endif
#if NRF5_PWM_USE_PWM1
pwmObjectInit(&PWMD2);
PWMD2.channels = PWM_CHANNELS;
PWMD2.pwm = NRF_PWM1;
#endif
#if NRF5_PWM_USE_PWM2
pwmObjectInit(&PWMD3);
PWMD3.channels = PWM_CHANNELS;
PWMD3.pwm = NRF_PWM2;
#endif
}
/**
* @brief Configures and activates the PWM peripheral.
* @note Starting a driver that is already in the @p PWM_READY state
* disables all the active channels.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_start(PWMDriver *pwmp) {
/* Prescaler value calculation: ftimer = 16MHz / 2^PRESCALER */
/* Prescaler value as a power of 2, must be 0..7 */
uint8_t i, psc_value;
for (psc_value = 0; psc_value < 8; psc_value++)
if (pwmp->config->frequency == (uint32_t)(16000000 >> psc_value))
break;
/* Prescaler value must be between 0..7, and a power of two. */
osalDbgAssert(psc_value <= 7, "invalid frequency");
/* Set PWM output lines */
for (i=0; i<PWM_CHANNELS; i++) {
const PWMChannelConfig *cfg_channel = &pwmp->config->channels[i];
uint32_t gpio_pin = PAL_PAD(cfg_channel->ioline);
if (cfg_channel->mode == PWM_OUTPUT_DISABLED) {
gpio_pin = PAL_NOLINE;
}
pwmp->pwm->PSEL.OUT[i] = gpio_pin << PWM_PSEL_OUT_PIN_Pos;
}
/* Enable PWM */
pwmp->pwm->ENABLE = PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos;
/* Set mode */
pwmp->pwm->MODE = PWM_MODE_UPDOWN_Up & PWM_MODE_UPDOWN_Msk;
/* Set prescaler */
pwmp->pwm->PRESCALER = psc_value & PWM_PRESCALER_PRESCALER_Msk;
/* Set period */
pwmp->pwm->COUNTERTOP = pwmp->period & PWM_COUNTERTOP_COUNTERTOP_Msk;
pwmp->pwm->LOOP = PWM_LOOP_CNT_Disabled & PWM_LOOP_CNT_Msk;
pwmp->pwm->DECODER = (PWM_DECODER_LOAD_Individual << PWM_DECODER_LOAD_Pos) |
(PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);
pwmp->pwm->SEQ[0].PTR = ((uint32_t)(pwm_seq) << PWM_SEQ_PTR_PTR_Pos);
pwmp->pwm->SEQ[0].CNT = ((sizeof(pwm_seq) / sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos);
pwmp->pwm->SEQ[0].REFRESH = 0;
pwmp->pwm->SEQ[0].ENDDELAY = 0;
pwmp->pwm->SEQ[1].PTR = ((uint32_t)(pwm_seq) << PWM_SEQ_PTR_PTR_Pos);
pwmp->pwm->SEQ[1].CNT = ((sizeof(pwm_seq) / sizeof(uint16_t)) << PWM_SEQ_CNT_CNT_Pos);
pwmp->pwm->SEQ[1].REFRESH = 0;
pwmp->pwm->SEQ[1].ENDDELAY = 0;
/* With clear shortcuts for period */
pwmp->pwm->SHORTS = 0;
/* Disable and reset interrupts */
pwmp->pwm->INTEN = 0;
}
/**
* @brief Deactivates the PWM peripheral.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_stop(PWMDriver *pwmp) {
#if NRF5_PWM_USE_PWM0
if (&PWMD1 == pwmp) {
nvicDisableVector(PWM0_IRQn);
}
#endif
#if NRF5_PWM_USE_PWM1
if (&PWMD2 == pwmp) {
nvicDisableVector(PWM1_IRQn);
}
#endif
#if NRF5_PWM_USE_PWM2
if (&PWMD3 == pwmp) {
nvicDisableVector(PWM2_IRQn);
}
#endif
/* Stop PWM generation */
pwmp->pwm->TASKS_STOP = 1;
/* Disable PWM */
pwmp->pwm->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
}
/**
* @brief Enables a PWM channel.
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The channel is active using the specified configuration.
* @note The function has effect at the next cycle start.
* @note Channel notification is not enabled.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
* @param[in] width PWM pulse width as clock pulses number
*
* @notapi
*/
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width) {
const PWMChannelConfig *cfg_channel = &pwmp->config->channels[channel];
/* Deal with corner case: 0% and 100% */
if ((width <= 0) || (width >= pwmp->period)) {
pwm_seq[channel] = pwmp->period & PWM_COUNTERTOP_COUNTERTOP_Msk;
if (cfg_channel->mode == PWM_OUTPUT_ACTIVE_LOW) pwm_seq[channel] |= 0x8000;
/* Really doing PWM */
} else {
pwm_seq[channel] = width & PWM_COUNTERTOP_COUNTERTOP_Msk;
if (cfg_channel->mode == PWM_OUTPUT_ACTIVE_HIGH) pwm_seq[channel] |= 0x8000;
}
pwmp->pwm->EVENTS_STOPPED = 0;
(void)pwmp->pwm->EVENTS_STOPPED;
pwmp->pwm->TASKS_SEQSTART[0] = 1;
}
/**
* @brief Disables a PWM channel and its notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The channel is disabled and its output line returned to the
* idle state.
* @note The function has effect at the next cycle start.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel) {
const PWMChannelConfig *cfg_channel = &pwmp->config->channels[channel];
pwm_seq[channel] = pwmp->period & PWM_COUNTERTOP_COUNTERTOP_Msk;
if (cfg_channel->mode == PWM_OUTPUT_ACTIVE_LOW) pwm_seq[channel] |= 0x8000;
pwmp->pwm->EVENTS_STOPPED = 0;
(void)pwmp->pwm->EVENTS_STOPPED;
pwmp->pwm->TASKS_SEQSTART[0] = 1;
}
/**
* @brief Enables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp) {
/* Events clear */
pwmp->pwm->EVENTS_LOOPSDONE = 0;
pwmp->pwm->EVENTS_SEQEND[0] = 0;
pwmp->pwm->EVENTS_SEQEND[1] = 0;
pwmp->pwm->EVENTS_STOPPED = 0;
#if CORTEX_MODEL >= 4
(void)pwmp->pwm->EVENTS_LOOPSDONE;
(void)pwmp->pwm->EVENTS_SEQEND[0];
(void)pwmp->pwm->EVENTS_SEQEND[1];
(void)pwmp->pwm->EVENTS_STOPPED;
#endif
pwmp->pwm->INTENSET = PWM_INTENSET_PWMPERIODEND_Msk;
/* Enable interrupt */
#if NRF5_PWM_USE_PWM0
if (&PWMD1 == pwmp) {
nvicEnableVector(PWM0_IRQn, NRF5_PWM_PWM0_PRIORITY);
}
#endif
#if NRF5_PWM_USE_PWM1
if (&PWMD2 == pwmp) {
nvicEnableVector(PWM1_IRQn, NRF5_PWM_PWM1_PRIORITY);
}
#endif
#if NRF5_PWM_USE_PWM2
if (&PWMD3 == pwmp) {
nvicEnableVector(PWM2_IRQn, NRF5_PWM_PWM2_PRIORITY);
}
#endif
}
/**
* @brief Disables the periodic activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
*
* @notapi
*/
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp) {
pwmp->pwm->INTENCLR = PWM_INTENCLR_PWMPERIODEND_Msk;
}
/**
* @brief Enables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
}
/**
* @brief Disables a channel de-activation edge notification.
* @pre The PWM unit must have been activated using @p pwmStart().
* @pre The channel must have been activated using @p pwmEnableChannel().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] channel PWM channel identifier (0...channels-1)
*
* @notapi
*/
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel) {
}
#endif /* HAL_USE_PWM */
/** @} */

View File

@ -0,0 +1,243 @@
/*
ChibiOS/HAL - Copyright (C) 2018 Andru
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file hal_pwm_lld.h
* @brief NRF52 PWM subsystem low level driver header.
*
* @addtogroup PWM
* @{
*/
#ifndef HAL_PWM_LLD_H_
#define HAL_PWM_LLD_H_
#if HAL_USE_PWM || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Number of PWM channels per PWM driver.
*/
#define PWM_CHANNELS 4
typedef enum {
PWM_FREQUENCY_16MHZ = 16000000, /** @brief 16MHz */
PWM_FREQUENCY_8MHZ = 8000000, /** @brief 8MHz */
PWM_FREQUENCY_4MHZ = 4000000, /** @brief 4MHz */
PWM_FREQUENCY_2MHZ = 2000000, /** @brief 2MHz */
PWM_FREQUENCY_1MHZ = 1000000, /** @brief 1MHz */
PWM_FREQUENCY_500KHZ = 500000, /** @brief 500kHz */
PWM_FREQUENCY_250KHZ = 250000, /** @brief 250kHz */
PWM_FREQUENCY_125KHZ = 125000, /** @brief 125kHz */
} pwm_frequency_t;
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/** @} */
/*===========================================================================*/
/* Configuration checks. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Type of a PWM mode.
*/
typedef uint32_t pwmmode_t;
/**
* @brief Type of a PWM channel.
*/
typedef uint8_t pwmchannel_t;
/**
* @brief Type of a channels mask.
*/
typedef uint32_t pwmchnmsk_t;
/**
* @brief Type of a PWM counter.
*/
typedef uint16_t pwmcnt_t;
/**
* @brief Type of a PWM driver channel configuration structure.
*/
typedef struct {
/**
* @brief Channel active logic level.
*/
pwmmode_t mode;
/**
* @brief Channel callback pointer.
* @note This callback is invoked on the channel compare event. If set to
* @p NULL then the callback is disabled.
*/
pwmcallback_t callback;
/* End of the mandatory fields.*/
/**
* @brief PAL line to toggle.
* @note Only used if mode is PWM_OUTPUT_HIGH or PWM_OUTPUT_LOW.
* @note When channel enabled it wont be possible to access this PAL line using the PAL
* driver.
*/
ioline_t ioline;
} PWMChannelConfig;
/**
* @brief Type of a PWM driver configuration structure.
*/
typedef struct {
/**
* @brief Timer clock in Hz.
* @note The low level can use assertions in order to catch invalid
* frequency specifications.
*/
pwm_frequency_t frequency;
/**
* @brief PWM period in ticks.
* @note The low level can use assertions in order to catch invalid
* period specifications.
*/
pwmcnt_t period;
/**
* @brief Periodic callback pointer.
* @note This callback is invoked on PWM counter reset. If set to
* @p NULL then the callback is disabled.
*/
pwmcallback_t callback;
/**
* @brief Channels configurations.
*/
PWMChannelConfig channels[PWM_CHANNELS];
/* End of the mandatory fields.*/
} PWMConfig;
/**
* @brief Structure representing a PWM driver.
*/
struct PWMDriver {
/**
* @brief Driver state.
*/
pwmstate_t state;
/**
* @brief Current driver configuration data.
*/
const PWMConfig *config;
/**
* @brief Current PWM period in ticks.
*/
pwmcnt_t period;
/**
* @brief Mask of the enabled channels.
*/
pwmchnmsk_t enabled;
/**
* @brief Number of channels in this instance.
*/
pwmchannel_t channels;
#if defined(PWM_DRIVER_EXT_FIELDS)
PWM_DRIVER_EXT_FIELDS
#endif
/* End of the mandatory fields.*/
/**
* @brief Pointer to the PWM registers block.
*/
NRF_PWM_Type *pwm;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Changes the period the PWM peripheral.
* @details This function changes the period of a PWM unit that has already
* been activated using @p pwmStart().
* @pre The PWM unit must have been activated using @p pwmStart().
* @post The PWM unit period is changed to the new value.
* @note The function has effect at the next cycle start.
* @note If a period is specified that is shorter than the pulse width
* programmed in one of the channels then the behavior is not
* guaranteed.
*
* @param[in] pwmp pointer to a @p PWMDriver object
* @param[in] period new cycle time in ticks
*
* @notapi
*/
#define pwm_lld_change_period(pwmp, period) \
do { \
(pwmp)->pwm->COUNTERTOP = period & PWM_COUNTERTOP_COUNTERTOP_Msk; \
} while(0)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if NRF5_PWM_USE_PWM0 || defined(__DOXYGEN__)
extern PWMDriver PWMD1;
#endif
#if NRF5_PWM_USE_PWM1 || defined(__DOXYGEN__)
extern PWMDriver PWMD2;
#endif
#if NRF5_PWM_USE_PWM2 || defined(__DOXYGEN__)
extern PWMDriver PWMD3;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void pwm_lld_init(void);
void pwm_lld_start(PWMDriver *pwmp);
void pwm_lld_stop(PWMDriver *pwmp);
void pwm_lld_enable_channel(PWMDriver *pwmp,
pwmchannel_t channel,
pwmcnt_t width);
void pwm_lld_disable_channel(PWMDriver *pwmp, pwmchannel_t channel);
void pwm_lld_enable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_disable_periodic_notification(PWMDriver *pwmp);
void pwm_lld_enable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
void pwm_lld_disable_channel_notification(PWMDriver *pwmp,
pwmchannel_t channel);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_PWM */
#endif /* HAL_PWM_LLD_H_ */
/** @} */

View File

@ -2,8 +2,12 @@ ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_GPT TRUE,$(HALCONF)),)
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TIMERv1/hal_gpt_lld.c
endif
ifneq ($(findstring HAL_USE_ICU TRUE,$(HALCONF)),)
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TIMERv1/hal_icu_lld.c
endif
else
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TIMERv1/hal_gpt_lld.c
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TIMERv1/hal_icu_lld.c
endif
PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TIMERv1

View File

@ -0,0 +1,768 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* Hardware Abstraction Layer for Extended Input Capture Unit
*/
#include "hal.h"
#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
/**
* @brief Returns the compare value of the latest cycle.
*
* @param[in] chp Pointer to channel structure that fired the interrupt.
* @return The number of ticks.
*
* @notapi
*/
//#define icu_lld_get_compare(chp) (*((chp)->ccp) + 1)
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief ICUD1 driver identifier.
* @note The driver ICUD1 allocates the complex timer TIMER0 when enabled.
*/
#if NRF5_ICU_USE_TIMER0 && !defined(__DOXYGEN__)
ICUDriver ICUD1;
#endif
/**
* @brief ICUD2 driver identifier.
* @note The driver ICUD2 allocates the timer TIMER1 when enabled.
*/
#if NRF5_ICU_USE_TIMER1 && !defined(__DOXYGEN__)
ICUDriver ICUD2;
#endif
/**
* @brief ICUD3 driver identifier.
* @note The driver ICUD3 allocates the timer TIMER2 when enabled.
*/
#if NRF5_ICU_USE_TIMER2 && !defined(__DOXYGEN__)
ICUDriver ICUD3;
#endif
/**
* @brief ICUD4 driver identifier.
* @note The driver ICUD4 allocates the timer TIMER3 when enabled.
*/
#if NRF5_ICU_USE_TIMER3 && !defined(__DOXYGEN__)
ICUDriver ICUD4;
#endif
/**
* @brief ICUD5 driver identifier.
* @note The driver ICUD5 allocates the timer TIMER4 when enabled.
*/
#if NRF5_ICU_USE_TIMER4 && !defined(__DOXYGEN__)
ICUDriver ICUD5;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Returns pulse width.
* @details The time is defined as number of ticks.
*
* @param[in] icup Pointer to the ICUDriver object.
* @param[in] channel The timer channel that fired the interrupt.
* @param[in] compare Content of the CC register.
* @return The number of ticks.
*
* @notapi
*/
static icucnt_t get_time_width(const ICUDriver *icup,
uint8_t channel,
icucnt_t compare) {
const ICUChannel *chp = &icup->channel[channel];
/* Note! there is no overflow check because it handles under the hood of
unsigned subtraction math.*/
return compare - chp->last_idle;
}
/**
* @brief Returns pulse period.
* @details The time is defined as number of ticks.
*
* @param[in] icup Pointer to the ICUDriver object.
* @param[in] channel The timer channel that fired the interrupt.
* @param[in] compare Content of the CC register.
* @return The number of ticks.
*
* @notapi
*/
static icucnt_t get_time_period(const ICUDriver *icup,
uint8_t channel,
icucnt_t compare) {
const ICUChannel *chp = &icup->channel[channel];
/* Note! there is no overflow check because it handles under the hood of
unsigned subtraction math.*/
return compare - chp->last_idle;
}
/**
* @brief ICU width event.
*
* @param[in] icup Pointer to the @p ICUDriver object
* @param[in] channel The timer channel that fired the interrupt.
*
* @notapi
*/
static void _isr_invoke_width_cb(ICUDriver *icup, uint8_t channel) {
ICUChannel *chp = &icup->channel[channel];
icucnt_t compare = icup->timer->CC[channel+2];
chp->last_active = compare;
if (ICU_CH_ACTIVE == chp->state) {
icup->result.width = get_time_width(icup, channel, compare);
if ((icup->state == ICU_ACTIVE) && (icup->config->width_cb != NULL))
icup->config->width_cb(icup);
chp->state = ICU_CH_IDLE;
}
}
/**
* @brief ICU period detect event.
*
* @param[in] icup Pointer to the @p ICUDriver object
* @param[in] channel The timer channel that fired the interrupt.
*
* @notapi
*/
static void _isr_invoke_period_cb(ICUDriver *icup, uint8_t channel) {
ICUChannel *chp = &icup->channel[channel];
icucnt_t compare = (uint32_t)icup->timer->CC[channel];
icup->result.period = get_time_period(icup, channel, compare);
chp->last_idle = compare;
chp->state = ICU_CH_ACTIVE;
if ((icup->state == ICU_ACTIVE) && (icup->config->period_cb != NULL))
icup->config->period_cb(icup);
icup->state = ICU_ACTIVE;
/* Set overflow timeout */
icup->timer->CC[channel] = compare + ICU_WAIT_TIMEOUT;
}
/**
* @brief Shared IRQ handler.
*
* @param[in] icup Pointer to the @p ICUDriver object
*/
void icu_lld_serve_gpiote_interrupt(ICUDriver *icup) {
uint8_t ch;
for (ch=0; ch<ICU_CHANNELS; ch++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[ch];
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
/* Period event */
if (NRF_GPIOTE->INTENSET & (1 << gpiote_channel[0]) && NRF_GPIOTE->EVENTS_IN[gpiote_channel[0]]) {
_isr_invoke_period_cb(icup, ch);
NRF_GPIOTE->EVENTS_IN[gpiote_channel[0]] = 0;
(void) NRF_GPIOTE->EVENTS_IN[gpiote_channel[0]];
}
/* Width event */
if (NRF_GPIOTE->INTENSET & (1 << gpiote_channel[1]) && NRF_GPIOTE->EVENTS_IN[gpiote_channel[1]]) {
_isr_invoke_width_cb(icup, ch);
NRF_GPIOTE->EVENTS_IN[gpiote_channel[1]] = 0;
(void) NRF_GPIOTE->EVENTS_IN[gpiote_channel[1]];
}
}
}
/**
* @brief Overflow IRQ handler.
*
* @param[in] icup Pointer to the @p ICUDriver object
*/
void icu_lld_serve_interrupt(ICUDriver *icup) {
uint8_t ch;
for (ch=0; ch<ICU_CHANNELS; ch++) {
/* Clear overflow events */
if (icup->timer->INTENSET & (1 << (TIMER_INTENSET_COMPARE0_Pos + ch)) &&
icup->timer->EVENTS_COMPARE[ch]) {
icup->timer->EVENTS_COMPARE[ch] = 0;
(void) icup->timer->EVENTS_COMPARE[ch];
/* Set next overlow compare */
icup->timer->CC[ch] = icup->timer->CC[ch] + ICU_WAIT_TIMEOUT;
}
}
if (icup->config->overflow_cb != NULL)
icup->config->overflow_cb(icup);
icup->state = ICU_WAITING;
}
/**
* @brief Starts every channel.
*
* @param[in] icup Pointer to the @p ICUDriver object
*
* @note GPIO Line[0] -> GPIOTE channel[0] will detect start edge.
* @note GPIO Line[1] -> GPIOTE channel[1] will detect end edge.
*/
static void start_channels(ICUDriver *icup) {
/* Set each input channel that is used as: a normal input capture channel. */
#if NRF5_ICU_USE_GPIOTE_PPI
uint8_t channel;
for (channel = 0; channel<ICU_CHANNELS; channel++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[channel];
if (cfg_channel->mode == ICU_INPUT_DISABLED) continue;
const uint32_t gpio_pin0 = PAL_PAD(cfg_channel->ioline[0]);
const uint32_t gpio_pin1 = PAL_PAD(cfg_channel->ioline[1]);
osalDbgAssert((gpio_pin0 < 32) &&
(gpio_pin1 < 32) &&
(gpio_pin0 != gpio_pin1),
"invalid Line configuration");
/* NRF52832 GPIOTE channels 0..7 */
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
osalDbgAssert((gpiote_channel[0] < 8) &&
(gpiote_channel[1] < 8) &&
(gpiote_channel[0] != gpiote_channel[1]),
"invalid GPIOTE configuration");
/* NRF52832 PPI channels 0..19 */
const uint8_t *ppi_channel = cfg_channel->ppi_channel;
osalDbgAssert((gpiote_channel[0] < 20) &&
(gpiote_channel[1] < 20) &&
(gpiote_channel[0] != gpiote_channel[1]),
"invalid PPI configuration");
/* Program PPI events for period */
NRF_PPI->CH[ppi_channel[0]].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel[0]];
NRF_PPI->CH[ppi_channel[0]].TEP = (uint32_t) &icup->timer->TASKS_CAPTURE[channel];
/* Program PPI events for width */
NRF_PPI->CH[ppi_channel[1]].EEP = (uint32_t) &NRF_GPIOTE->EVENTS_IN[gpiote_channel[1]];
NRF_PPI->CH[ppi_channel[1]].TEP = (uint32_t) &icup->timer->TASKS_CAPTURE[channel+2];
/* Disable GPIOTE interrupts */
NRF_GPIOTE->INTENCLR = (GPIOTE_INTENCLR_PORT_Clear << GPIOTE_INTENCLR_PORT_Pos) |
(1 << gpiote_channel[0]) | (1 << gpiote_channel[1]);
NRF_GPIOTE->EVENTS_PORT = 1;
/* Clear GPIOTE channels */
NRF_GPIOTE->CONFIG[gpiote_channel[0]] &= ~(GPIOTE_CONFIG_PSEL_Msk | GPIOTE_CONFIG_POLARITY_Msk);
NRF_GPIOTE->CONFIG[gpiote_channel[1]] &= ~(GPIOTE_CONFIG_PSEL_Msk | GPIOTE_CONFIG_POLARITY_Msk);
/* Set GPIOTE channels */
if (cfg_channel->mode == ICU_INPUT_ACTIVE_HIGH) {
NRF_GPIOTE->CONFIG[gpiote_channel[0]] =
(GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
((gpio_pin0 << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk) |
((GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk);
NRF_GPIOTE->CONFIG[gpiote_channel[1]] =
(GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
((gpio_pin1 << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk) |
((GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk);
} else {
NRF_GPIOTE->CONFIG[gpiote_channel[0]] =
(GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
((gpio_pin0 << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk) |
((GPIOTE_CONFIG_POLARITY_HiToLo << GPIOTE_CONFIG_POLARITY_Pos)
& GPIOTE_CONFIG_POLARITY_Msk);
NRF_GPIOTE->CONFIG[gpiote_channel[1]] =
(GPIOTE_CONFIG_MODE_Event << GPIOTE_CONFIG_MODE_Pos) |
((gpio_pin1 << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk) |
((GPIOTE_CONFIG_POLARITY_LoToHi << GPIOTE_CONFIG_POLARITY_Pos)
& GPIOTE_CONFIG_POLARITY_Msk);
}
}
#endif
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if NRF5_ICU_USE_GPIOTE_PPI
/**
* @brief GPIOTE events interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector58) {
OSAL_IRQ_PROLOGUE();
icu_lld_serve_gpiote_interrupt(&ICUD1);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_ICU_USE_GPIOTE_PPI */
#if NRF5_ICU_USE_TIMER0
/**
* @brief TIMER0 compare interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector60) {
OSAL_IRQ_PROLOGUE();
icu_lld_serve_interrupt(&ICUD1);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_ICU_USE_TIMER0 */
#if NRF5_ICU_USE_TIMER1
/**
* @brief TIMER1 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector64) {
OSAL_IRQ_PROLOGUE();
icu_lld_serve_interrupt(&ICUD2);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_ICU_USE_TIMER1 */
#if NRF5_ICU_USE_TIMER2
/**
* @brief TIMER2 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(Vector68) {
OSAL_IRQ_PROLOGUE();
icu_lld_serve_interrupt(&ICUD3);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_ICU_USE_TIMER2 */
#if NRF5_ICU_USE_TIMER3
/**
* @brief TIMER3 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(VectorA8) {
OSAL_IRQ_PROLOGUE();
icu_lld_serve_interrupt(&ICUD4);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_ICU_USE_TIMER3 */
#if NRF5_ICU_USE_TIMER4
/**
* @brief TIMER4 interrupt handler.
* @note It is assumed that the various sources are only activated if the
* associated callback pointer is not equal to @p NULL in order to not
* perform an extra check in a potentially critical interrupt handler.
*
* @isr
*/
OSAL_IRQ_HANDLER(VectorAC) {
OSAL_IRQ_PROLOGUE();
icu_lld_serve_interrupt(&ICUD5);
OSAL_IRQ_EPILOGUE();
}
#endif /* NRF5_ICU_USE_TIMER4 */
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level ICU driver initialization.
*
* @notapi
*/
void icu_lld_init(void) {
#if NRF5_ICU_USE_TIMER0
/* Driver initialization.*/
icuObjectInit(&ICUD1);
ICUD1.timer = NRF_TIMER0;
#endif
#if NRF5_ICU_USE_TIMER1
/* Driver initialization.*/
icuObjectInit(&ICUD2);
ICUD2.timer = NRF_TIMER1;
#endif
#if NRF5_ICU_USE_TIMER2
/* Driver initialization.*/
icuObjectInit(&ICUD3);
ICUD3.timer = NRF_TIMER2;
#endif
#if NRF5_ICU_USE_TIMER3
/* Driver initialization.*/
icuObjectInit(&ICUD4);
ICUD4.timer = NRF_TIMER3;
#endif
#if NRF5_ICU_USE_TIMER4
/* Driver initialization.*/
icuObjectInit(&ICUD5);
ICUD5.timer = NRF_TIMER4;
#endif
}
/**
* @brief Configures and activates the ICU peripheral.
*
* @param[in] icup Pointer to the @p ICUDriver object
*
* @notapi
*/
void icu_lld_start(ICUDriver *icup) {
size_t ch;
osalDbgAssert((&icup->config->iccfgp[0] != NULL) ||
(&icup->config->iccfgp[1] != NULL),
"invalid input configuration");
/* Prescaler value calculation: ftimer = 16MHz / 2^PRESCALER */
uint16_t psc_ratio = 16000000 / icup->config->frequency;
/* Prescaler ratio must be between 1 and 512, and a power of two. */
osalDbgAssert(psc_ratio <= 512 && !(psc_ratio & (psc_ratio - 1)),
"invalid frequency");
/* Prescaler value as a power of 2, must be 0..9 */
uint32_t psc_value;
for (psc_value = 0; psc_value < 10; psc_value++)
if (psc_ratio == (unsigned)(1 << psc_value))
break;
/* Configure as 32bits timer */
icup->timer->BITMODE = TIMER_BITMODE_BITMODE_32Bit;
/* Set timer mode */
icup->timer->MODE = TIMER_MODE_MODE_Timer;
/* Set prescaler */
icup->timer->PRESCALER = psc_value;
/* With clear shortcuts. */
icup->timer->SHORTS = 0;
/* Clear Timer */
icup->timer->TASKS_CLEAR = 1;
/* Disable and reset interrupts for compare events */
icup->timer->INTENCLR = (TIMER_INTENCLR_COMPARE0_Msk |
TIMER_INTENCLR_COMPARE1_Msk |
TIMER_INTENCLR_COMPARE2_Msk |
TIMER_INTENCLR_COMPARE3_Msk );
icup->timer->EVENTS_COMPARE[0] = 0;
icup->timer->EVENTS_COMPARE[1] = 0;
icup->timer->EVENTS_COMPARE[2] = 0;
icup->timer->EVENTS_COMPARE[3] = 0;
(void) icup->timer->EVENTS_COMPARE[0];
(void) icup->timer->EVENTS_COMPARE[1];
(void) icup->timer->EVENTS_COMPARE[2];
(void) icup->timer->EVENTS_COMPARE[3];
/* Enable GPIOTE and TIMER interrupt vectors.*/
#if NRF5_ICU_USE_GPIOTE_PPI
nvicEnableVector(GPIOTE_IRQn, NRF5_ICU_GPIOTE_IRQ_PRIORITY);
#endif
#if NRF5_ICU_USE_TIMER0
if (&ICUD1 == icup) {
nvicEnableVector(TIMER0_IRQn, NRF5_ICU_TIMER0_IRQ_PRIORITY);
}
#endif
#if NRF5_ICU_USE_TIMER1
if (&ICUD2 == icup) {
nvicEnableVector(TIMER1_IRQn, NRF5_ICU_TIMER1_IRQ_PRIORITY);
}
#endif
#if NRF5_ICU_USE_TIMER2
if (&ICUD3 == icup) {
nvicEnableVector(TIMER2_IRQn, NRF5_ICU_TIMER2_IRQ_PRIORITY);
}
#endif
#if NRF5_ICU_USE_TIMER3
if (&ICUD4 == icup) {
nvicEnableVector(TIMER3_IRQn, NRF5_ICU_TIMER3_IRQ_PRIORITY);
}
#endif
#if NRF5_ICU_USE_TIMER4
if (&ICUD5 == icup) {
nvicEnableVector(TIMER4_IRQn, NRF5_ICU_TIMER4_IRQ_PRIORITY);
}
#endif
/* clean channel structures and set pointers to channel configs */
for (ch=0; ch<ICU_CHANNELS; ch++) {
icup->channel[ch].last_active = 0;
icup->channel[ch].last_idle = 0;
icup->channel[ch].state = ICU_CH_IDLE;
}
/* Set GPIOTE & PPI channels */
start_channels(icup);
}
/**
* @brief Deactivates the ICU peripheral.
*
* @param[in] icup Pointer to the @p ICUDriver object
*
* @notapi
*/
void icu_lld_stop(ICUDriver *icup) {
if (icup->state == ICU_READY) {
/* Timer stop.*/
icup->timer->TASKS_STOP = 1;
#if NRF5_ICU_USE_GPIOTE_PPI
uint8_t channel;
for (channel = 0; channel<ICU_CHANNELS; channel++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[channel];
if (cfg_channel == NULL) continue;
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
const uint8_t *ppi_channel = cfg_channel->ppi_channel;
/* Disable Timer interrupt */
icup->timer->INTENCLR = 1 << (TIMER_INTENCLR_COMPARE0_Pos + channel);
/* Disable GPIOTE interrupts */
NRF_GPIOTE->INTENCLR = (1 << gpiote_channel[0]) | (1 << gpiote_channel[1]);
/* Disable PPI channels */
NRF_PPI->CHENCLR = ((1 << ppi_channel[0]) | (1 << ppi_channel[1]));
/* Clear GPIOTE channels */
NRF_GPIOTE->CONFIG[gpiote_channel[0]] &= ~(GPIOTE_CONFIG_PSEL_Msk | GPIOTE_CONFIG_POLARITY_Msk);
NRF_GPIOTE->CONFIG[gpiote_channel[1]] &= ~(GPIOTE_CONFIG_PSEL_Msk | GPIOTE_CONFIG_POLARITY_Msk);
}
#endif
#if NRF5_ICU_USE_GPIOTE_PPI
nvicDisableVector(GPIOTE_IRQn);
#endif
#if NRF5_ICU_USE_TIMER0
if (&ICUD1 == icup) {
nvicDisableVector(TIMER0_IRQn);
}
#endif
#if NRF5_ICU_USE_TIMER1
if (&ICUD2 == icup) {
nvicDisableVector(TIMER1_IRQn);
}
#endif
#if NRF5_ICU_USE_TIMER2
if (&ICUD3 == icup) {
nvicDisableVector(TIMER2_IRQn);
}
#endif
#if NRF5_ICU_USE_TIMER3
if (&ICUD4 == icup) {
nvicDisableVector(TIMER3_IRQn);
}
#endif
#if NRF5_ICU_USE_TIMER4
if (&ICUD5 == icup) {
nvicDisableVector(TIMER4_IRQn);
}
#endif
}
}
/**
* @brief Starts the input capture.
*
* @param[in] icup pointer to the @p ICUDriver object
*
* @notapi
*/
void icu_lld_start_capture(ICUDriver *icup) {
/* Clear and start Timer */
icup->timer->TASKS_CLEAR = 1;
icup->timer->TASKS_START = 1;
#if NRF5_ICU_USE_GPIOTE_PPI
uint8_t channel;
for (channel = 0; channel<ICU_CHANNELS; channel++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[channel];
if (cfg_channel == NULL) continue;
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
const uint8_t *ppi_channel = cfg_channel->ppi_channel;
/* Enable interrupt for overflow events */
icup->timer->CC[channel] = ICU_WAIT_TIMEOUT;
icup->timer->INTENSET = 1 << (TIMER_INTENSET_COMPARE0_Pos + channel);
/* Enable PPI channels */
NRF_PPI->CHENSET = ((1 << ppi_channel[0]) | (1 << ppi_channel[1]));
/* Enable GPIOTE interrupt */
NRF_GPIOTE->INTENSET = (1 << gpiote_channel[0]) | (1 << gpiote_channel[1]);
}
#endif
}
/**
* @brief Waits for a completed capture.
* @note The operation is performed in polled mode.
* @note In order to use this function notifications must be disabled.
*
* @param[in] icup pointer to the @p ICUDriver object
* @return The capture status.
* @retval false if the capture is successful.
* @retval true if a timer overflow occurred.
*
* @notapi
*/
bool icu_lld_wait_capture(ICUDriver *icup) {
/* If the driver is still in the ICU_WAITING state then we need to wait
for the first activation edge.*/
if (icup->state == ICU_WAITING)
if (icu_lld_wait_edge(icup))
return true;
/* This edge marks the availability of a capture result.*/
return icu_lld_wait_edge(icup);
}
/**
* @brief Stops the input capture.
*
* @param[in] icup pointer to the @p ICUDriver object
*
* @notapi
*/
void icu_lld_stop_capture(ICUDriver *icup) {
/* Timer stopped.*/
icup->timer->TASKS_STOP = 1;
#if NRF5_ICU_USE_GPIOTE_PPI
uint8_t channel;
for (channel = 0; channel<ICU_CHANNELS; channel++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[channel];
if (cfg_channel == NULL) continue;
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
const uint8_t *ppi_channel = cfg_channel->ppi_channel;
/* Disable Timer interrupt for overflow events */
icup->timer->INTENCLR = 1 << (TIMER_INTENCLR_COMPARE0_Pos + channel);
/* Disable GPIOTE interrupt */
NRF_GPIOTE->INTENCLR = (1 << gpiote_channel[0]) | (1 << gpiote_channel[1]);
/* Disable PPI channels */
NRF_PPI->CHENCLR = ((1 << ppi_channel[0]) | (1 << ppi_channel[1]));
}
#endif
}
/**
* @brief Enables notifications.
* @pre The ICU unit must have been activated using @p icuStart() and the
* capture started using @p icuStartCapture().
* @note If the notification is already enabled then the call has no effect.
*
* @param[in] icup pointer to the @p ICUDriver object
*
* @notapi
*/
void icu_lld_enable_notifications(ICUDriver *icup) {
#if NRF5_ICU_USE_GPIOTE_PPI
uint8_t channel;
for (channel = 0; channel<ICU_CHANNELS; channel++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[channel];
if (cfg_channel == NULL) continue;
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
/* Enable Timer interrupt */
icup->timer->INTENSET = 1 << (TIMER_INTENSET_COMPARE0_Pos + channel);
/* Enable GPIOTE interrupt */
NRF_GPIOTE->INTENSET = (1 << gpiote_channel[0]) | (1 << gpiote_channel[1]);
}
#endif
}
/**
* @brief Disables notifications.
* @pre The ICU unit must have been activated using @p icuStart() and the
* capture started using @p icuStartCapture().
* @note If the notification is already disabled then the call has no effect.
*
* @param[in] icup pointer to the @p ICUDriver object
*
* @notapi
*/
void icu_lld_disable_notifications(ICUDriver *icup) {
/* All interrupts disabled.*/
#if NRF5_ICU_USE_GPIOTE_PPI
uint8_t channel;
for (channel = 0; channel<ICU_CHANNELS; channel++) {
const ICUChannelConfig *cfg_channel = &icup->config->iccfgp[channel];
if (cfg_channel == NULL) continue;
const uint8_t *gpiote_channel = cfg_channel->gpiote_channel;
/* Disable Timer interrupt for overflow events */
icup->timer->INTENCLR = 1 << (TIMER_INTENCLR_COMPARE0_Pos + channel);
/* Disable GPIOTE interrupt */
NRF_GPIOTE->INTENCLR = (1 << gpiote_channel[0]) | (1 << gpiote_channel[1]);
}
#endif
}
#endif /* HAL_USE_ICU */

View File

@ -0,0 +1,424 @@
/*
ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
*/
#ifndef HAL_ICU_LLD_H
#define HAL_ICU_LLD_H
#if (HAL_USE_ICU == TRUE) || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/**
* @brief Number of ICU channels per ICU driver.
*/
#define ICU_CHANNELS 2 /* max channels */
#define ICU_WAIT_TIMEOUT ( 0xFFFF ) /* first edge wait timeout */
#define ICU_FREQUENCY_16MHZ 16000000 /** @brief 16MHz */
#define ICU_FREQUENCY_8MHZ 8000000 /** @brief 8MHz */
#define ICU_FREQUENCY_4MHZ 4000000 /** @brief 4MHz */
#define ICU_FREQUENCY_2MHZ 2000000 /** @brief 2MHz */
#define ICU_FREQUENCY_1MHZ 1000000 /** @brief 1MHz */
#define ICU_FREQUENCY_500KHZ 500000 /** @brief 500kHz */
#define ICU_FREQUENCY_250KHZ 250000 /** @brief 250kHz */
#define ICU_FREQUENCY_125KHZ 125000 /** @brief 125kHz */
#define ICU_FREQUENCY_62500HZ 62500 /** @brief 62500Hz */
#define ICU_FREQUENCY_31250HZ 31250 /** @brief 31250Hz */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief ICUD1 driver enable switch.
* @details If set to @p TRUE the support for ICUD1 is included.
* @note The default is @p TRUE.
*/
#if !defined(NRF5_ICU_USE_TIMER0) || defined(__DOXYGEN__)
#define NRF5_ICU_USE_TIMER0 FALSE
#endif
/**
* @brief ICUD2 driver enable switch.
* @details If set to @p TRUE the support for ICUD2 is included.
* @note The default is @p TRUE.
*/
#if !defined(NRF5_ICU_USE_TIMER1) || defined(__DOXYGEN__)
#define NRF5_ICU_USE_TIMER1 FALSE
#endif
/**
* @brief ICUD3 driver enable switch.
* @details If set to @p TRUE the support for ICUD3 is included.
* @note The default is @p TRUE.
*/
#if !defined(NRF5_ICU_USE_TIMER2) || defined(__DOXYGEN__)
#define NRF5_ICU_USE_TIMER2 FALSE
#endif
/**
* @brief ICUD4 driver enable switch.
* @details If set to @p TRUE the support for ICUD4 is included.
* @note The default is @p TRUE.
*/
#if !defined(NRF5_ICU_USE_TIMER3) || defined(__DOXYGEN__)
#define NRF5_ICU_USE_TIMER3 FALSE
#endif
/**
* @brief ICUD5 driver enable switch.
* @details If set to @p TRUE the support for ICUD5 is included.
* @note The default is @p TRUE.
*/
#if !defined(NRF5_ICU_USE_TIMER4) || defined(__DOXYGEN__)
#define NRF5_ICU_USE_TIMER4 FALSE
#endif
/**
* @brief ICUD1 interrupt priority level setting.
*/
#if !defined(NRF5_ICU_TIMER0_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_ICU_TIMER0_IRQ_PRIORITY 3
#endif
/**
* @brief ICUD2 interrupt priority level setting.
*/
#if !defined(NRF5_ICU_TIMER1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_ICU_TIMER1_IRQ_PRIORITY 3
#endif
/**
* @brief ICUD3 interrupt priority level setting.
*/
#if !defined(NRF5_ICU_TIMER2_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_ICU_TIMER2_IRQ_PRIORITY 3
#endif
/**
* @brief ICUD4 interrupt priority level setting.
*/
#if !defined(NRF5_ICU_TIMER3_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_ICU_TIMER3_IRQ_PRIORITY 3
#endif
/**
* @brief ICUD5 interrupt priority level setting.
*/
#if !defined(NRF5_ICU_TIMER4_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_ICU_TIMER4_IRQ_PRIORITY 3
#endif
/**
* @brief Allow driver to use GPIOTE/PPI to capture PAL line
*/
#if !defined(NRF5_ICU_USE_GPIOTE_PPI)
#define NRF5_ICU_USE_GPIOTE_PPI TRUE
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if !NRF5_ICU_USE_TIMER0 && !NRF5_ICU_USE_TIMER1 && \
!NRF5_ICU_USE_TIMER2 && !NRF5_ICU_USE_TIMER3 && \
!NRF5_ICU_USE_TIMER4
#error "ICU driver activated but no TIMER peripheral assigned"
#endif
#if NRF5_ICU_USE_TIMER0 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_ICU_TIMER0_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER0"
#endif
#if NRF5_ICU_USE_TIMER1 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_ICU_TIMER1_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER1"
#endif
#if NRF5_ICU_USE_TIMER2 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_ICU_TIMER2_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER2"
#endif
#if NRF5_ICU_USE_TIMER3 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_ICU_TIMER3_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER3"
#endif
#if NRF5_ICU_USE_TIMER4 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_ICU_TIMER4_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to TIMER4"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/**
* @brief Active level selector.
*/
typedef enum {
ICU_INPUT_DISABLED, /**< Channel disabled . */
ICU_INPUT_ACTIVE_HIGH, /**< Trigger on rising edge. */
ICU_INPUT_ACTIVE_LOW, /**< Trigger on falling edge. */
} icumode_t;
/**
* @brief ICU channel state.
*/
typedef enum {
ICU_CH_IDLE = 0, /**< Not initialized. */
ICU_CH_ACTIVE = 1 /**< First front detected. */
} icuchannelstate_t;
/**
* @brief ICU frequency type.
*/
typedef uint32_t icufreq_t;
/**
* @brief ICU channel type.
*/
typedef enum {
ICU_CHANNEL_1 = 0, /**< Use TIMERx channel 0,2 */
ICU_CHANNEL_2 = 1, /**< Use TIMERx channel 1,3 */
} icuchannel_t;
/**
* @brief ICU counter type.
*/
typedef uint32_t icucnt_t;
/**
* @brief ICU captured width and (or) period.
*/
typedef struct {
/**
* @brief Pulse width.
*/
icucnt_t width;
/**
* @brief Pulse period.
*/
icucnt_t period;
} icuresult_t;
/**
* @brief ICU Capture Channel Config structure definition.
*/
typedef struct {
/**
* @brief Specifies the channel capture mode.
*/
icumode_t mode;
#if NRF5_ICU_USE_GPIOTE_PPI || defined(__DOXYGEN__)
/**
* @brief PAL line to capture.
* @note When NRF5_ICU_USE_GPIOTE_PPI is used and channel enabled,
* it wont be possible to access this PAL line using the PAL
* driver.
*/
ioline_t ioline[2];
/**
* @brief Unique GPIOTE channel to use. (2 channel)
* @note Only 8 GPIOTE channels are available on nRF52.
*/
uint8_t gpiote_channel[2];
/**
* @brief Unique PPI channels to use. (2 channels)
* @note Only 20 PPI channels are available on nRF52
* (When Softdevice is enabled, only channels 0-7 are available)
*/
uint8_t ppi_channel[2];
#endif
} ICUChannelConfig;
/**
* @brief ICU Capture Channel structure definition.
*/
typedef struct {
/**
* @brief Channel state for the internal state machine.
*/
icuchannelstate_t state;
/**
* @brief Cached value for pulse width calculation.
*/
icucnt_t last_active;
/**
* @brief Cached value for period calculation.
*/
icucnt_t last_idle;
/**
* @brief Pointer to Input Capture channel configuration.
*/
// const ICUChannelConfig *config;
} ICUChannel;
/**
* @brief ICU Config structure definition.
*/
typedef struct {
/**
* @brief Specifies the Timer clock in Hz.
*/
icufreq_t frequency;
/**
* @brief Callback for pulse width measurement.
*/
icucallback_t width_cb;
/**
* @brief Callback for cycle period measurement.
*/
icucallback_t period_cb;
/**
* @brief Callback for timer overflow.
*/
icucallback_t overflow_cb;
/**
* @brief Pointer to each Input Capture channel configuration.
* @note A NULL parameter indicates the channel as unused.
* @note In ICU mode, only Channel 1 OR Channel 2 may be used.
*/
const ICUChannelConfig iccfgp[ICU_CHANNELS];
} ICUConfig;
/**
* @brief ICU Driver structure definition
*/
struct ICUDriver {
/**
* @brief NRF52 timer peripheral for Input Capture.
*/
NRF_TIMER_Type *timer;
/**
* @brief Driver state for the internal state machine.
*/
icustate_t state;
/**
* @brief Channels' data structures.
*/
ICUChannel channel[ICU_CHANNELS];
/**
* @brief Timer base clock.
*/
uint32_t clock;
/**
* @brief Pointer to configuration for the driver.
*/
const ICUConfig *config;
/**
* @brief Period, width last value.
*/
icuresult_t result;
#if defined(ICU_DRIVER_EXT_FIELDS)
ICU_DRIVER_EXT_FIELDS
#endif
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Returns the width of the latest pulse.
* @details The pulse width is defined as number of ticks between the start
* edge and the stop edge.
*
* @param[in] icup pointer to the @p ICUDriver object
* @return The number of ticks.
*
* @notapi
*/
#define icu_lld_get_width(icup) ((uint32_t)((icup)->result.width))
/**
* @brief Returns the width of the latest cycle.
* @details The cycle width is defined as number of ticks between a start
* edge and the next start edge.
*
* @param[in] icup pointer to the @p ICUDriver object
* @return The number of ticks.
*
* @notapi
*/
#define icu_lld_get_period(icup) ((uint32_t)((icup)->result.period))
/**
* @brief Check on notifications status.
*
* @param[in] icup pointer to the @p ICUDriver object
* @return The notifications status.
* @retval false if notifications are not enabled.
* @retval true if notifications are enabled.
*
* @notapi
*/
#define icu_lld_are_notifications_enabled(icup) ( 1 )
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if NRF5_ICU_USE_TIMER0 && !defined(__DOXYGEN__)
extern ICUDriver ICUD1;
#endif
#if NRF5_ICU_USE_TIMER1 && !defined(__DOXYGEN__)
extern ICUDriver ICUD2;
#endif
#if NRF5_ICU_USE_TIMER2 && !defined(__DOXYGEN__)
extern ICUDriver ICUD3;
#endif
#if NRF5_ICU_USE_TIMER3 && !defined(__DOXYGEN__)
extern ICUDriver ICUD4;
#endif
#if NRF5_ICU_USE_TIMER4 && !defined(__DOXYGEN__)
extern ICUDriver ICUD5;
#endif
#ifdef __cplusplus
extern "C" {
#endif
void icu_lld_init(void);
void icu_lld_start(ICUDriver *icup);
void icu_lld_stop(ICUDriver *icup);
void icu_lld_start_capture(ICUDriver *icup);
bool icu_lld_wait_capture(ICUDriver *icup);
void icu_lld_stop_capture(ICUDriver *icup);
void icu_lld_enable_notifications(ICUDriver *icup);
void icu_lld_disable_notifications(ICUDriver *icup);
void icu_lld_serve_interrupt(ICUDriver *icup);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_ICU */
#endif /* HAL_ICU_LLD_H */

View File

@ -0,0 +1,9 @@
ifeq ($(USE_SMART_BUILD),yes)
ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),)
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TWIMv1/hal_i2c_lld.c
endif
else
PLATFORMSRC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TWIMv1/hal_i2c_lld.c
endif
PLATFORMINC_CONTRIB += ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TWIMv1

View File

@ -0,0 +1,420 @@
/*
Copyright (C) 2018 andru
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file NRF5/NRF52832/hal_i2c_lld.c
* @brief NRF52 I2C subsystem low level driver source.
*
* @addtogroup I2C
* @{
*/
#include "osal.h"
#include "hal.h"
#include "nrf_delay.h"
#if HAL_USE_I2C || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver local definitions. */
/*===========================================================================*/
/* These macros are needed to see if the slave is stuck and we as master send dummy clock cycles to end its wait */
#define I2C_HIGH(p) do { IOPORT1->OUTSET = (1UL << (p)); } while(0) /*!< Pulls I2C line high */
#define I2C_LOW(p) do { IOPORT1->OUTCLR = (1UL << (p)); } while(0) /*!< Pulls I2C line low */
#define I2C_INPUT(p) do { IOPORT1->DIRCLR = (1UL << (p)); } while(0) /*!< Configures I2C pin as input */
#define I2C_OUTPUT(p) do { IOPORT1->DIRSET = (1UL << (p)); } while(0) /*!< Configures I2C pin as output */
#define I2C_PIN_CNF \
((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) \
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos))
#define I2C_PIN_CNF_CLR \
((GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos) \
| (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) \
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) \
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) \
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos))
#if NRF5_I2C_USE_I2C0
#define I2C0_IRQ_NUM SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn
#define I2C0_IRQ_PRI NRF5_I2C_I2C0_IRQ_PRIORITY
#endif
#if NRF5_I2C_USE_I2C1
#define I2C1_IRQ_NUM SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn
#define I2C1_IRQ_PRI NRF5_I2C_I2C1_IRQ_PRIORITY
#endif
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
/**
* @brief I2C0 driver identifier.
*/
#if NRF5_I2C_USE_I2C0 || defined(__DOXYGEN__)
I2CDriver I2CD1;
#endif
/**
* @brief I2C1 driver identifier.
*/
#if NRF5_I2C_USE_I2C1 || defined(__DOXYGEN__)
I2CDriver I2CD2;
#endif
/*===========================================================================*/
/* Driver local variables and types. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/*===========================================================================*/
/**
* @brief Function for detecting stuck slaves (SDA = 0 and SCL = 1) and tries to clear the bus.
*
* @return
* @retval false Bus is stuck.
* @retval true Bus is clear.
*/
static void i2c_clear_bus(I2CDriver *i2cp) {
const I2CConfig *cfg = i2cp->config;
uint8_t i;
IOPORT1->PIN_CNF[cfg->scl_pad] = I2C_PIN_CNF;
IOPORT1->PIN_CNF[cfg->sda_pad] = I2C_PIN_CNF;
I2C_HIGH(cfg->sda_pad);
I2C_HIGH(cfg->scl_pad);
IOPORT1->PIN_CNF[cfg->scl_pad] = I2C_PIN_CNF_CLR;
IOPORT1->PIN_CNF[cfg->sda_pad] = I2C_PIN_CNF_CLR;
nrf_delay_us(4);
for(i = 0; i < 9; i++) {
if (palReadPad(IOPORT1, cfg->sda_pad)) {
if(i > 0)
break;
else
return;
}
I2C_LOW(cfg->scl_pad);
nrf_delay_us(4);
I2C_HIGH(cfg->scl_pad);
nrf_delay_us(4);
}
I2C_LOW(cfg->sda_pad);
nrf_delay_us(4);
I2C_HIGH(cfg->sda_pad);
}
#if defined(__GNUC__)
__attribute__((noinline))
#endif
/**
* @brief Common IRQ handler.
* @note Tries hard to clear all the pending interrupt sources, we don't
* want to go through the whole ISR and have another interrupt soon
* after.
*
* @param[in] i2cp pointer to an I2CDriver
*/
static void i2c_serve_interrupt(I2CDriver *i2cp) {
NRF_TWIM_Type *i2c = i2cp->i2c;
if (i2c->EVENTS_ERROR) {
uint32_t err = i2c->ERRORSRC;
i2c->EVENTS_ERROR = 0;
(void)i2c->EVENTS_ERROR;
if (err & 0x01) // nRF52832 Product Specification v1.3 p.314 TWIM_ERRORSRC OVERRUN bit = 0x01
i2cp->errors |= I2C_OVERRUN;
if (err & (TWIM_ERRORSRC_ANACK_Msk | TWIM_ERRORSRC_DNACK_Msk))
i2cp->errors |= I2C_ACK_FAILURE;
i2c->TASKS_STOP = 1;
_i2c_wakeup_error_isr(i2cp);
} else if(i2c->EVENTS_STOPPED) {
i2c->EVENTS_STOPPED = 0;
(void)i2c->EVENTS_STOPPED;
_i2c_wakeup_isr(i2cp);
}
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
#if NRF5_I2C_USE_I2C0 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(Vector4C) {
OSAL_IRQ_PROLOGUE();
i2c_serve_interrupt(&I2CD1);
OSAL_IRQ_EPILOGUE();
}
#endif
#if NRF5_I2C_USE_I2C1 || defined(__DOXYGEN__)
OSAL_IRQ_HANDLER(Vector50) {
OSAL_IRQ_PROLOGUE();
i2c_serve_interrupt(&I2CD2);
OSAL_IRQ_EPILOGUE();
}
#endif
/*===========================================================================*/
/* Driver exported functions. */
/*===========================================================================*/
/**
* @brief Low level I2C driver initialization.
*
* @notapi
*/
void i2c_lld_init(void) {
#if NRF5_I2C_USE_I2C0
i2cObjectInit(&I2CD1);
I2CD1.thread = NULL;
I2CD1.i2c = NRF_TWIM0;
#endif
#if NRF5_I2C_USE_I2C1
i2cObjectInit(&I2CD2);
I2CD2.thread = NULL;
I2CD2.i2c = NRF_TWIM1;
#endif
}
/**
* @brief Configures and activates the I2C peripheral.
*
* @param[in] i2cp pointer to the @p I2CDriver object
*
* @notapi
*/
void i2c_lld_start(I2CDriver *i2cp) {
NRF_TWIM_Type *i2c = i2cp->i2c;
const I2CConfig *cfg = i2cp->config;
if (i2cp->state != I2C_STOP)
return;
osalDbgAssert(i2c->ENABLE == 0, "already in use");
i2c_clear_bus(i2cp);
IOPORT1->PIN_CNF[cfg->scl_pad] = I2C_PIN_CNF;
IOPORT1->PIN_CNF[cfg->sda_pad] = I2C_PIN_CNF;
i2c->SHORTS = 0;
i2c->EVENTS_STOPPED = 0;
i2c->EVENTS_ERROR = 0;
(void)i2c->EVENTS_STOPPED;
(void)i2c->EVENTS_ERROR;
i2c->PSEL.SCL = cfg->scl_pad;
i2c->PSEL.SDA = cfg->sda_pad;
switch (cfg->clock) {
case 100000:
i2c->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100 << TWIM_FREQUENCY_FREQUENCY_Pos;
break;
case 250000:
i2c->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250 << TWIM_FREQUENCY_FREQUENCY_Pos;
break;
case 400000:
i2c->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400 << TWIM_FREQUENCY_FREQUENCY_Pos;
break;
default:
osalDbgAssert(0, "invalid I2C frequency");
break;
};
#if NRF5_I2C_USE_I2C0
nvicEnableVector(I2C0_IRQ_NUM, I2C0_IRQ_PRI);
#endif
#if NRF5_I2C_USE_I2C1
nvicEnableVector(I2C1_IRQ_NUM, I2C1_IRQ_PRI);
#endif
i2c->INTENSET = TWIM_INTENSET_STOPPED_Msk | TWIM_INTENSET_ERROR_Msk;
i2c->ENABLE = TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos;
}
/**
* @brief Deactivates the I2C peripheral.
*
* @param[in] i2cp pointer to the @p I2CDriver object
*
* @notapi
*/
void i2c_lld_stop(I2CDriver *i2cp) {
NRF_TWIM_Type *i2c = i2cp->i2c;
const I2CConfig *cfg = i2cp->config;
if (i2cp->state != I2C_STOP) {
i2c->SHORTS = 0;
i2c->INTENCLR = TWIM_INTENCLR_STOPPED_Msk | TWIM_INTENCLR_ERROR_Msk;
#if NRF5_I2C_USE_I2C0
nvicDisableVector(I2C0_IRQ_NUM);
#endif
#if NRF5_I2C_USE_I2C1
nvicDisableVector(I2C1_IRQ_NUM);
#endif
i2c->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos;
IOPORT1->PIN_CNF[cfg->scl_pad] = I2C_PIN_CNF_CLR;
IOPORT1->PIN_CNF[cfg->sda_pad] = I2C_PIN_CNF_CLR;
}
}
static inline msg_t _i2c_txrx_timeout(I2CDriver *i2cp, i2caddr_t addr,
const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
NRF_TWIM_Type *i2c = i2cp->i2c;
msg_t msg;
i2cp->errors = I2C_NO_ERROR;
i2cp->addr = addr;
uint8_t tx_bytes = txbytes;
uint8_t rx_bytes = rxbytes;
i2cp->i2c->SHORTS = 0;
i2c->ADDRESS = addr;
if (tx_bytes && rx_bytes) {
i2c->TXD.PTR = (uint32_t)txbuf;
i2c->TXD.MAXCNT = tx_bytes;
i2c->TXD.LIST = TWIM_TXD_LIST_LIST_ArrayList << TWIM_TXD_LIST_LIST_Pos;
i2c->RXD.PTR = (uint32_t)rxbuf;
i2c->RXD.MAXCNT = rx_bytes;
i2c->RXD.LIST = TWIM_RXD_LIST_LIST_ArrayList << TWIM_RXD_LIST_LIST_Pos;
i2cp->i2c->SHORTS = TWIM_SHORTS_LASTTX_STARTRX_Enabled << TWIM_SHORTS_LASTTX_STARTRX_Pos |
TWIM_SHORTS_LASTRX_STOP_Enabled << TWIM_SHORTS_LASTRX_STOP_Pos;
i2c->TASKS_STARTTX = 1;
} else if (tx_bytes && !rx_bytes) {
i2c->TXD.PTR = (uint32_t)txbuf;
i2c->TXD.MAXCNT = tx_bytes;
i2c->TXD.LIST = TWIM_TXD_LIST_LIST_ArrayList << TWIM_TXD_LIST_LIST_Pos;
i2cp->i2c->SHORTS = TWIM_SHORTS_LASTTX_STOP_Enabled << TWIM_SHORTS_LASTTX_STOP_Pos;
i2c->TASKS_STARTTX = 1;
} else if (!tx_bytes && rx_bytes) {
i2c->RXD.PTR = (uint32_t)rxbuf;
i2c->RXD.MAXCNT = rx_bytes;
i2c->RXD.LIST = TWIM_RXD_LIST_LIST_ArrayList << TWIM_RXD_LIST_LIST_Pos;
i2cp->i2c->SHORTS = TWIM_SHORTS_LASTRX_STOP_Enabled << TWIM_SHORTS_LASTRX_STOP_Pos;
i2c->TASKS_STARTRX = 1;
} else {
osalDbgAssert(0, "no bytes to transfer");
}
msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout);
if (msg == MSG_TIMEOUT)
i2c->TASKS_STOP = 1;
return msg;
}
/**
* @brief Receives data via the I2C bus as master.
*
* @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] addr slave device address
* @param[out] rxbuf pointer to the receive buffer
* @param[in] rxbytes number of bytes to be received
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if the function succeeded.
* @retval MSG_RESET if one or more I2C errors occurred, the errors can
* be retrieved using @p i2cGetErrors().
* @retval MSG_TIMEOUT if a timeout occurred before operation end. <b>After a
* timeout the driver must be stopped and restarted
* because the bus is in an uncertain state</b>.
*
* @notapi
*/
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
return _i2c_txrx_timeout(i2cp, addr, NULL, 0, rxbuf, rxbytes, timeout);
}
/**
* @brief Transmits data via the I2C bus as master.
*
* @param[in] i2cp pointer to the @p I2CDriver object
* @param[in] addr slave device address
* @param[in] txbuf pointer to the transmit buffer
* @param[in] txbytes number of bytes to be transmitted
* @param[out] rxbuf pointer to the receive buffer
* @param[in] rxbytes number of bytes to be received
* @param[in] timeout the number of ticks before the operation timeouts,
* the following special values are allowed:
* - @a TIME_INFINITE no timeout.
* .
* @return The operation status.
* @retval MSG_OK if the function succeeded.
* @retval MSG_RESET if one or more I2C errors occurred, the errors can
* be retrieved using @p i2cGetErrors().
* @retval MSG_TIMEOUT if a timeout occurred before operation end. <b>After a
* timeout the driver must be stopped and restarted
* because the bus is in an uncertain state</b>.
*
* @notapi
*/
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout) {
return _i2c_txrx_timeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, timeout);
}
#endif /* HAL_USE_I2C */
/** @} */

View File

@ -0,0 +1,210 @@
/*
Copyright (C) 2018 andru
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file NRF5/NRF52832/hal_i2c_lld.h
* @brief NRF52 I2C subsystem low level driver header.
*
* @addtogroup I2C
* @{
*/
#ifndef HAL_I2C_LLD_H
#define HAL_I2C_LLD_H
#if HAL_USE_I2C || defined(__DOXYGEN__)
/*===========================================================================*/
/* Driver constants. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @name Configuration options
* @{
*/
/**
* @brief I2C0 driver enable switch.
* @details If set to @p TRUE the support for I2C0 is included.
* @note The default is @p FALSE.
*/
#if !defined(NRF5_I2C_USE_I2C0) || defined(__DOXYGEN__)
#define NRF5_I2C_USE_I2C0 FALSE
#endif
/**
* @brief I2C1 driver enable switch.
* @details If set to @p TRUE the support for I2C1 is included.
* @note The default is @p FALSE.
*/
#if !defined(NRF5_I2C_USE_I2C1) || defined(__DOXYGEN__)
#define NRF5_I2C_USE_I2C1 FALSE
#endif
/**
* @brief I2C0 interrupt priority level setting.
*/
#if !defined(NRF5_I2C_I2C0_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_I2C_I2C0_IRQ_PRIORITY 3
#endif
/**
* @brief I2C1 interrupt priority level setting.
*/
#if !defined(NRF5_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__)
#define NRF5_I2C_I2C1_IRQ_PRIORITY 3
#endif
/** @} */
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if NRF5_I2C_USE_I2C0 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_I2C_I2C0_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to I2C0"
#endif
#if NRF5_I2C_USE_I2C1 && \
!OSAL_IRQ_IS_VALID_PRIORITY(NRF5_I2C_I2C1_IRQ_PRIORITY)
#error "Invalid IRQ priority assigned to I2C1"
#endif
/*===========================================================================*/
/* Driver data structures and types. */
/*===========================================================================*/
/* @brief Type representing I2C address. */
typedef uint8_t i2caddr_t;
/* @brief Type of I2C Driver condition flags. */
typedef uint32_t i2cflags_t;
/**
* @brief Driver configuration structure.
* @note Implementations may extend this structure to contain more,
* architecture dependent, fields.
*/
/**
* @brief Driver configuration structure.
*/
typedef struct {
/* @brief Clock to be used for the I2C bus. */
uint32_t clock;
/* @brief Pad number for SCL */
uint8_t scl_pad;
/* @brief Pad number for SDA */
uint8_t sda_pad;
} I2CConfig;
/**
* @brief Type of a structure representing an I2C driver.
*/
typedef struct I2CDriver I2CDriver;
/**
* @brief Structure representing an I2C driver.
*/
struct I2CDriver {
/**
* @brief Driver state.
*/
i2cstate_t state;
/**
* @brief Current configuration data.
*/
const I2CConfig *config;
/**
* @brief Error flags.
*/
i2cflags_t errors;
#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__)
/**
* @brief Mutex protecting the bus.
*/
mutex_t mutex;
#endif /* I2C_USE_MUTUAL_EXCLUSION */
#if defined(I2C_DRIVER_EXT_FIELDS)
I2C_DRIVER_EXT_FIELDS
#endif
/* @brief Thread waiting for I/O completion. */
thread_reference_t thread;
/* @brief Current slave address without R/W bit. */
i2caddr_t addr;
/* End of the mandatory fields.*/
/* @brief Low-level register access. */
NRF_TWIM_Type *i2c;
};
/*===========================================================================*/
/* Driver macros. */
/*===========================================================================*/
/**
* @brief Get errors from I2C driver.
*
* @param[in] i2cp pointer to the @p I2CDriver object
*
* @notapi
*/
#define i2c_lld_get_errors(i2cp) ((i2cp)->errors)
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if !defined(__DOXYGEN__)
#if NRF5_I2C_USE_I2C0
extern I2CDriver I2CD1;
#endif
#if NRF5_I2C_USE_I2C1
extern I2CDriver I2CD2;
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
void i2c_lld_init(void);
void i2c_lld_start(I2CDriver *i2cp);
void i2c_lld_stop(I2CDriver *i2cp);
msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr,
const uint8_t *txbuf, size_t txbytes,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout);
msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr,
uint8_t *rxbuf, size_t rxbytes,
systime_t timeout);
#ifdef __cplusplus
}
#endif
#endif /* HAL_USE_I2C */
#endif /* HAL_I2C_LLD_H */
/** @} */

View File

@ -55,23 +55,37 @@
*/
void hal_lld_init(void)
{
/* High frequency clock initialisation
/* High frequency clock initialization
*/
NRF_CLOCK->TASKS_HFCLKSTOP = 1;
#if !defined(NRF5_XTAL_VALUE) && (NRF5_XTAL_VALUE != 32000000)
#error "A 32Mhz crystal is mandatory on nRF52 boards."
#endif
#if (NRF5_HFCLK_SOURCE == NRF5_HFCLK_HFXO)
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
#endif
/* Low frequency clock initialisation
* Clock is only started if st driver requires it
/* Low frequency clock initialization
*/
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE)
#if (NRF5_ST_USE_RTC0 || NRF5_ST_USE_RTC1) && \
(NRF5_LFCLK_SOURCE == NRF5_LFCLK_RC)
#error "A NRF5_SYSTEM_TICKS_AS_RTC requires LFCLK clock to be started."
#endif
#endif
NRF_CLOCK->TASKS_LFCLKSTOP = 1;
#if (NRF5_LFCLK_SOURCE != NRF5_LFCLK_RC)
NRF_CLOCK->LFCLKSRC = NRF5_LFCLK_SOURCE;
#if (OSAL_ST_MODE != OSAL_ST_MODE_NONE) && \
(NRF5_SYSTEM_TICKS == NRF5_SYSTEM_TICKS_AS_RTC)
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
NRF_CLOCK->TASKS_LFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
#endif
}

View File

@ -59,23 +59,37 @@
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Select source of High Frequency Clock (HFCLK)
* @details Possible values for source are:
* 0 : 64 MHz internal oscillator (HFINT)
* 1 : 32 MHz external crystal oscillator (HFXO)
*/
#if !defined(NRF5_HFCLK_SOURCE) || defined(__DOXYGEN__)
#define NRF5_HFCLK_SOURCE NRF5_HFCLK_HFINT
#endif
/**
* @brief Select source of Low Frequency Clock (LFCLK)
* @details Possible values for source are:
* 0 : RC oscillator
* 1 : External cristal
* 2 : Synthetized clock from High Frequency Clock (HFCLK)
* When cristal is not available it's preferable to use the
* internal RC oscillator that synthezing the clock.
* 1 : External crystal
* 2 : Synthesized clock from High Frequency Clock (HFCLK)
* When crystal is not available it's preferable to use the
* internal RC oscillator that synthesizing the clock.
*/
#if !defined(NRF5_LFCLK_SOURCE) || defined(__DOXYGEN__)
#define NRF5_LFCLK_SOURCE 0
#define NRF5_LFCLK_SOURCE NRF5_LFCLK_RC
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
#if (NRF5_HFCLK_SOURCE < 0) || (NRF5_HFCLK_SOURCE > 1)
#error "Possible value for NRF5_HFCLK_SOURCE are HFINT=0, HFXO=1"
#endif
#if (NRF5_LFCLK_SOURCE < 0) || (NRF5_LFCLK_SOURCE > 2)
#error "Possible value for NRF5_LFCLK_SOURCE are 0=RC, 1=XTAL, 2=Synth"
#endif
@ -91,6 +105,14 @@
/*===========================================================================*/
/* External declarations. */
/*===========================================================================*/
#if 0 // moved to board.h
#define NRF5_HFCLK_HFINT 0
#define NRF5_HFCLK_HFXO 1
#define NRF5_LFCLK_RC 0
#define NRF5_LFCLK_XTAL 1
#define NRF5_LFCLK_SYNTH 2
#endif
#include "nvic.h"

View File

@ -1,97 +1,238 @@
/*
Copyright (C) 2015 Stephen Caudle
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file NRF5/NRF52832/nrf_delay.h
* @brief NRF5 Delay routines
*
* @{
*/
#ifndef _NRF_DELAY_H
#define _NRF_DELAY_H
inline static void nrf_delay_us(uint32_t volatile number_of_us) __attribute__((always_inline));
inline static void nrf_delay_us(uint32_t volatile number_of_us)
{
register uint32_t delay __asm ("r0") = number_of_us;
__asm volatile (
".syntax unified\n"
"1:\n"
" SUBS %0, %0, #1\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" BNE 1b\n"
".syntax divided\n"
: "+r" (delay));
}
#endif //__NRF_DELAY_H
#ifndef _NRF_DELAY_H
#define _NRF_DELAY_H
/**
* @brief Function for delaying execution for number of microseconds.
*
* @note NRF52 has instruction cache and because of that delay is not precise.
*
* @param number_of_ms
*/
/*lint --e{438, 522} "Variable not used" "Function lacks side-effects" */
#if defined ( __CC_ARM )
static __ASM void __INLINE nrf_delay_us(uint32_t volatile number_of_us)
{
loop
SUBS R0, R0, #1
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
#ifdef NRF52
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
#endif
BNE loop
BX LR
}
#elif defined ( __ICCARM__ )
static void __INLINE nrf_delay_us(uint32_t volatile number_of_us)
{
__ASM (
"loop:\n\t"
" SUBS R0, R0, #1\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
#ifdef NRF52
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
#endif
" BNE.n loop\n\t");
}
#elif defined ( _WIN32 ) || defined ( __unix ) || defined( __APPLE__ )
__STATIC_INLINE void nrf_delay_us(uint32_t volatile number_of_us);
#ifndef CUSTOM_NRF_DELAY_US
__STATIC_INLINE void nrf_delay_us(uint32_t volatile number_of_us)
{}
#endif
#elif defined ( __GNUC__ )
inline static void nrf_delay_us(uint32_t volatile number_of_us) __attribute__((always_inline));
inline static void nrf_delay_us(uint32_t volatile number_of_us)
{
register uint32_t delay __ASM ("r0") = number_of_us;
__ASM volatile (
#ifdef NRF51
".syntax unified\n"
#endif
"1:\n"
" SUBS %0, %0, #1\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
#ifdef NRF52
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
#endif
" BNE 1b\n"
#ifdef NRF51
".syntax divided\n"
#endif
: "+r" (delay));
}
#endif
#endif

View File

@ -20,7 +20,8 @@ endif
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/GPIOv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/UARTv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/SPIv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TWIv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TWIMv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/PWMv2/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/TIMERv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/WDTv1/driver.mk
include ${CHIBIOS_CONTRIB}/os/hal/ports/NRF5/LLD/RNGv1/driver.mk

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,256 @@
/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
* @brief Enhanced ShockBurst (ESB) is a basic protocol supporting two-way data
* packet communication including packet buffering, packet acknowledgment
* and automatic retransmission of lost packets.
*
* ported on: 25/10/2018, by andru
*
*/
#ifndef NRF52_RADIO_H_
#define NRF52_RADIO_H_
// Hard coded parameters - change if necessary
#ifndef NRF52_MAX_PAYLOAD_LENGTH
#define NRF52_MAX_PAYLOAD_LENGTH 32 /**< The max size of the payload. Valid values are 1 to 252 */
#endif
#define NRF52_CRC_RESET_VALUE 0xFFFF /**< CRC reset value*/
#define NRF52_TX_FIFO_SIZE 8 /**< The size of the transmission first in first out buffer. */
#define NRF52_RX_FIFO_SIZE 8 /**< The size of the reception first in first out buffer. */
#define NRF52_RADIO_USE_TIMER0 FALSE /**< TIMER0 will be used by the module. */
#define NRF52_RADIO_USE_TIMER1 TRUE /**< TIMER1 will be used by the module. */
#define NRF52_RADIO_USE_TIMER2 FALSE /**< TIMER2 will be used by the module. */
#define NRF52_RADIO_USE_TIMER3 FALSE /**< TIMER3 will be used by the module. */
#define NRF52_RADIO_USE_TIMER4 FALSE /**< TIMER4 will be used by the module. */
#define NRF52_RADIO_IRQ_PRIORITY 3 /**< RADIO interrupt priority. */
#define NRF52_RADIO_INTTHD_PRIORITY (NORMALPRIO+2) /**< Interrupts handle thread priority. */
#define NRF52_RADIO_EVTTHD_PRIORITY (NORMALPRIO+1) /**< Events handle thread priority */
#define NRF52_RADIO_PPI_TIMER_START 10 /**< The PPI channel used for timer start. */
#define NRF52_RADIO_PPI_TIMER_STOP 11 /**< The PPI channel used for timer stop. */
#define NRF52_RADIO_PPI_RX_TIMEOUT 12 /**< The PPI channel used for RX timeout. */
#define NRF52_RADIO_PPI_TX_START 13 /**< The PPI channel used for starting TX. */
typedef enum {
NRF52_SUCCESS, /* Call was successful. */
NRF52_INVALID_STATE, /* Module is not initialized. */
NRF52_ERROR_BUSY, /* Module was not in idle state. */
NRF52_ERROR_NULL, /* Required parameter was NULL. */
NRF52_ERROR_INVALID_PARAM, /* Required parameter is invalid */
NRF52_ERROR_NOT_SUPPORTED, /* p_payload->noack was false while selective ack was not enabled. */
NRF52_ERROR_INVALID_LENGTH, /* Payload length was invalid (zero or larger than max allowed). */
} nrf52_error_t;
// Internal radio module state.
typedef enum {
NRF52_STATE_UNINIT, /**< Module not initialized. */
NRF52_STATE_IDLE, /**< Module idle. */
NRF52_STATE_PTX_TX, /**< Module transmitting without ack. */
NRF52_STATE_PTX_TX_ACK, /**< Module transmitting with ack. */
NRF52_STATE_PTX_RX_ACK, /**< Module transmitting with ack and reception of payload with the ack response. */
NRF52_STATE_PRX, /**< Module receiving packets without ack. */
NRF52_STATE_PRX_SEND_ACK, /**< Module transmitting ack in RX mode. */
} nrf52_state_t;
/**@brief Events to indicate the last transmission/receiving status. */
typedef enum {
NRF52_EVENT_TX_SUCCESS = 0x01, /**< Event triggered on TX success. */
NRF52_EVENT_TX_FAILED = 0x02, /**< Event triggered on TX failed. */
NRF52_EVENT_RX_RECEIVED = 0x04, /**< Event triggered on RX Received. */
} nrf52_event_t;
// Interrupt flags
typedef enum {
NRF52_INT_TX_SUCCESS_MSK = 0x01, /**< The flag used to indicate a success since last event. */
NRF52_INT_TX_FAILED_MSK = 0x02, /**< The flag used to indicate a failiure since last event. */
NRF52_INT_RX_DR_MSK = 0x04, /**< The flag used to indicate a received packet since last event. */
} nrf52_int_flags_t;
/**Macro to create initializer for a TX data packet.
*
* @details This macro generates an initializer. It is more efficient
* than setting the individual parameters dynamically.
*
* @param[in] _pipe The pipe to use for the data packet.
* @param[in] ... Comma separated list of character data to put in the TX buffer.
* Supported values are from 1 to 63 characters.
*
* @return Initializer that sets up pipe, length and the byte array for content of the TX data.
*/
#define NRF52_CREATE_PAYLOAD(_pipe, ...) \
{.pipe = _pipe, .length = NUM_VA_ARGS(__VA_ARGS__), .data = {__VA_ARGS__}}; \
STATIC_ASSERT(NUM_VA_ARGS(__VA_ARGS__) > 0 && NUM_VA_ARGS(__VA_ARGS__) <= 63)
/**@brief Enhanced ShockBurst protocol. */
typedef enum {
NRF52_PROTOCOL_ESB, /*< Enhanced ShockBurst with fixed payload length. */
NRF52_PROTOCOL_ESB_DPL /*< Enhanced ShockBurst with dynamic payload length. */
} nrf52_protocol_t;
/**@brief Enhanced ShockBurst mode. */
typedef enum {
NRF52_MODE_PTX, /*< Primary transmitter mode. */
NRF52_MODE_PRX /*< Primary receiver mode. */
} nrf52_mode_t;
/**@brief Enhanced ShockBurst bitrate mode. */
typedef enum {
NRF52_BITRATE_2MBPS = RADIO_MODE_MODE_Nrf_2Mbit, /**< 2Mbit radio mode. */
NRF52_BITRATE_1MBPS = RADIO_MODE_MODE_Nrf_1Mbit, /**< 1Mbit radio mode. */
} nrf52_bitrate_t;
/**@brief Enhanced ShockBurst CRC modes. */
typedef enum {
NRF52_CRC_16BIT = RADIO_CRCCNF_LEN_Two, /**< Use two byte CRC. */
NRF52_CRC_8BIT = RADIO_CRCCNF_LEN_One, /**< Use one byte CRC. */
NRF52_CRC_OFF = RADIO_CRCCNF_LEN_Disabled /**< Disable CRC. */
} nrf52_crc_t;
/**@brief Enhanced ShockBurst radio transmission power modes. */
typedef enum {
NRF52_TX_POWER_4DBM = RADIO_TXPOWER_TXPOWER_Pos4dBm, /**< 4 dBm radio transmit power. */
NRF52_TX_POWER_0DBM = RADIO_TXPOWER_TXPOWER_0dBm, /**< 0 dBm radio transmit power. */
NRF52_TX_POWER_NEG4DBM = RADIO_TXPOWER_TXPOWER_Neg4dBm, /**< -4 dBm radio transmit power. */
NRF52_TX_POWER_NEG8DBM = RADIO_TXPOWER_TXPOWER_Neg8dBm, /**< -8 dBm radio transmit power. */
NRF52_TX_POWER_NEG12DBM = RADIO_TXPOWER_TXPOWER_Neg12dBm, /**< -12 dBm radio transmit power. */
NRF52_TX_POWER_NEG16DBM = RADIO_TXPOWER_TXPOWER_Neg16dBm, /**< -16 dBm radio transmit power. */
NRF52_TX_POWER_NEG20DBM = RADIO_TXPOWER_TXPOWER_Neg20dBm, /**< -20 dBm radio transmit power. */
NRF52_TX_POWER_NEG30DBM = RADIO_TXPOWER_TXPOWER_Neg30dBm /**< -30 dBm radio transmit power. */
} nrf52_tx_power_t;
/**@brief Enhanced ShockBurst transmission modes. */
typedef enum {
NRF52_TXMODE_AUTO, /*< Automatic TX mode - When the TX fifo is non-empty and the radio is idle packets will be sent automatically. */
NRF52_TXMODE_MANUAL, /*< Manual TX mode - Packets will not be sent until radio_start_tx() is called. Can be used to ensure consistent packet timing. */
NRF52_TXMODE_MANUAL_START /*< Manual start TX mode - Packets will not be sent until radio_start_tx() is called, but transmission will continue automatically until the TX fifo is empty. */
} nrf52_tx_mode_t;
/**@brief Enhanced ShockBurst addresses.
*
* @details The module is able to transmit packets with the TX address stored in tx_address.
The module can also receive packets from peers with up to eight different tx_addresses
stored in esb_addr_p0 - esb_addr_p7. esb_addr_p0 can have 5 arbitrary bytes
independent of the other addresses. esb_addr_p1 - esb_addr_p7 will share the
same four byte base address found in the last four bytes of esb_addr_p1.
They have an independent prefix byte found in esb_addr_p1[0] and esb_addr_p2 -
esb_addr_p7.
*/
typedef struct {
uint8_t base_addr_p0[4]; /**< Base address for pipe 0 encoded in big endian. */
uint8_t base_addr_p1[4]; /**< Base address for pipe 1-7 encoded in big endian. */
uint8_t pipe_prefixes[8]; /**< Address prefix for pipe P0 to P7. */
uint8_t num_pipes; /**< Number of pipes available. */
uint8_t addr_length; /**< Length of address including prefix */
uint8_t rx_pipes; /**< Bitfield for enabled RX pipes. */
uint8_t rf_channel; /**< Which channel is to be used. Must be in range 0 and 125 to be valid. */
} nrf52_address_t;
/**@brief Enhanced ShockBurst payload.
*
* @note The payload is used both for transmission and receive with ack and payload.
*/
typedef struct
{
uint8_t length; /**< Length of the packet. Should be equal or less than NRF_ESB_MAX_PAYLOAD_LENGTH. */
uint8_t pipe; /**< Pipe used for this payload. */
int8_t rssi; /**< RSSI for received packet. */
uint8_t noack; /**< Flag indicating that this packet will not be acknowledged. */
uint8_t pid; /**< PID assigned during communication. */
uint8_t data[NRF52_MAX_PAYLOAD_LENGTH]; /**< The payload data. */
} nrf52_payload_t;
/**@brief Retransmit attempts delay and counter. */
typedef struct {
uint16_t delay; /**< The delay between each retransmission of unacked packets. */
uint16_t count; /**< The number of retransmissions attempts before transmission fail. */
} nrf52_retransmit_t;
/**@brief Main nrf_esb configuration struct. */
typedef struct {
nrf52_protocol_t protocol; /**< Enhanced ShockBurst protocol. */
nrf52_mode_t mode; /**< Enhanced ShockBurst default RX or TX mode. */
// General RF parameters
nrf52_bitrate_t bitrate; /**< Enhanced ShockBurst bitrate mode. */
nrf52_crc_t crc; /**< Enhanced ShockBurst CRC mode. */
nrf52_tx_power_t tx_power; /**< Enhanced ShockBurst radio transmission power mode.*/
// Control settings
nrf52_tx_mode_t tx_mode; /**< Enhanced ShockBurst transmit mode. */
bool selective_auto_ack; /**< Enable or disable selective auto acknowledgement. */
nrf52_retransmit_t retransmit; /**< Packet retransmit parameters */
uint8_t payload_length; /**< Enhanced ShockBurst static payload length */
nrf52_address_t address; /**< Address parameters structure */
} nrf52_config_t;
typedef struct {
/**
* @brief NRF52 radio peripheral.
*/
NRF_RADIO_Type *radio;
/**
* @brief NRF52 timer peripheral.
*/
NRF_TIMER_Type *timer;
/**
* @brief Driver state.
*/
nrf52_state_t state;
/**
* @brief RF parameters.
*/
nrf52_config_t config;
/**
* @brief Interrupts flag.
*/
nrf52_int_flags_t flags;
/**
* @brief TX attempt number.
*/
uint16_t tx_attempt;
/**
* @brief TX retransmits remaining.
*/
uint16_t tx_remaining;
/**
* @brief Radio events source.
*/
event_source_t eventsrc;
} RFDriver;
extern RFDriver RFD1;
nrf52_error_t radio_init(nrf52_config_t const *config);
nrf52_error_t radio_disable(void);
nrf52_error_t radio_write_payload(nrf52_payload_t const * p_payload);
nrf52_error_t radio_read_rx_payload(nrf52_payload_t * p_payload);
nrf52_error_t radio_start_tx(void);
nrf52_error_t radio_start_rx(void);
nrf52_error_t radio_stop_rx(void);
nrf52_error_t radio_flush_tx(void);
nrf52_error_t radio_flush_rx(void);
nrf52_error_t radio_pop_tx(void);
nrf52_error_t radio_set_base_address_0(uint8_t const * p_addr);
nrf52_error_t radio_set_base_address_1(uint8_t const * p_addr);
nrf52_error_t radio_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes);
nrf52_error_t radio_set_prefix(uint8_t pipe, uint8_t prefix);
#endif /* NRF52_RADIO_H_ */

View File

@ -0,0 +1,207 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Licensing files.
include $(CHIBIOS)/os/license/license.mk
# Startup files.
include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_nrf52.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NRF5/NRF52832/platform.mk
include $(CHIBIOS_CONTRIB)/os/hal/boards/NRF52-E73-2G4M04S/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/NRF52832.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(ALLCSRC) \
$(TESTSRC) \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC = $(ALLCPPSRC)
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(ALLASMSRC)
ASMXSRC = $(ALLXASMSRC)
INCDIR = $(ALLINC) $(TESTINC) \
$(TESTHAL)
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m4
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
SREC = $(CP) -O srec
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk

View File

@ -0,0 +1,696 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef CHCONF_H
#define CHCONF_H
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_5_1_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION 32
#endif
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#if !defined(CH_CFG_ST_FREQUENCY)
#define CH_CFG_ST_FREQUENCY 1000
#endif
/**
* @brief Time intervals data size.
* @note Allowed values are 16, 32 or 64 bits.
*/
#if !defined(CH_CFG_INTERVALS_SIZE)
#define CH_CFG_INTERVALS_SIZE 32
#endif
/**
* @brief Time types data size.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_TIME_TYPES_SIZE)
#define CH_CFG_TIME_TYPES_SIZE 32
#endif
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#if !defined(CH_CFG_ST_TIMEDELTA)
#define CH_CFG_ST_TIMEDELTA 0
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#if !defined(CH_CFG_TIME_QUANTUM)
#define CH_CFG_TIME_QUANTUM 2
#endif
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#if !defined(CH_CFG_MEMCORE_SIZE)
#define CH_CFG_MEMCORE_SIZE 0
#endif
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#if !defined(CH_CFG_NO_IDLE_THREAD)
#define CH_CFG_NO_IDLE_THREAD FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_OPTIMIZE_SPEED)
#define CH_CFG_OPTIMIZE_SPEED TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_TM)
#define CH_CFG_USE_TM FALSE
#endif
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_REGISTRY)
#define CH_CFG_USE_REGISTRY TRUE
#endif
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_WAITEXIT)
#define CH_CFG_USE_WAITEXIT TRUE
#endif
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_SEMAPHORES)
#define CH_CFG_USE_SEMAPHORES TRUE
#endif
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
#endif
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MUTEXES)
#define CH_CFG_USE_MUTEXES TRUE
#endif
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
#endif
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_CONDVARS)
#define CH_CFG_USE_CONDVARS TRUE
#endif
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
#endif
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_EVENTS)
#define CH_CFG_USE_EVENTS TRUE
#endif
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
#endif
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MESSAGES)
#define CH_CFG_USE_MESSAGES TRUE
#endif
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
#endif
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_MAILBOXES)
#define CH_CFG_USE_MAILBOXES TRUE
#endif
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMCORE)
#define CH_CFG_USE_MEMCORE TRUE
#endif
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_CFG_USE_HEAP)
#define CH_CFG_USE_HEAP TRUE
#endif
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMPOOLS)
#define CH_CFG_USE_MEMPOOLS TRUE
#endif
/**
* @brief Objects FIFOs APIs.
* @details If enabled then the objects FIFOs APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_OBJ_FIFOS)
#define CH_CFG_USE_OBJ_FIFOS TRUE
#endif
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#if !defined(CH_CFG_USE_DYNAMIC)
#define CH_CFG_USE_DYNAMIC TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Objects factory options
* @{
*/
/*===========================================================================*/
/**
* @brief Objects Factory APIs.
* @details If enabled then the objects factory APIs are included in the
* kernel.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_CFG_USE_FACTORY)
#define CH_CFG_USE_FACTORY TRUE
#endif
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
#endif
/**
* @brief Enables the registry of generic objects.
*/
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#endif
/**
* @brief Enables factory for generic buffers.
*/
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#endif
/**
* @brief Enables factory for semaphores.
*/
#if !defined(CH_CFG_FACTORY_SEMAPHORES)
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#endif
/**
* @brief Enables factory for mailboxes.
*/
#if !defined(CH_CFG_FACTORY_MAILBOXES)
#define CH_CFG_FACTORY_MAILBOXES TRUE
#endif
/**
* @brief Enables factory for objects FIFOs.
*/
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_STATISTICS)
#define CH_DBG_STATISTICS FALSE
#endif
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
#endif
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS)
#define CH_DBG_ENABLE_CHECKS TRUE
#endif
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS)
#define CH_DBG_ENABLE_ASSERTS TRUE
#endif
/**
* @brief Debug option, trace buffer.
* @details If enabled then the trace buffer is activated.
*
* @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_MASK)
#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_ALL
#endif
/**
* @brief Trace buffer entries.
* @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
* different from @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
#define CH_DBG_TRACE_BUFFER_SIZE 128
#endif
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK)
#define CH_DBG_ENABLE_STACK_CHECK TRUE
#endif
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS)
#define CH_DBG_FILL_THREADS TRUE
#endif
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#if !defined(CH_DBG_THREADS_PROFILING)
#define CH_DBG_THREADS_PROFILING FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief System structure extension.
* @details User fields added to the end of the @p ch_system_t structure.
*/
#define CH_CFG_SYSTEM_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief System initialization hook.
* @details User initialization code added to the @p chSysInit() function
* just before interrupts are enabled globally.
*/
#define CH_CFG_SYSTEM_INIT_HOOK() { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p _thread_init() function.
*
* @note It is invoked from within @p _thread_init() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief ISR enter hook.
*/
#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
/* IRQ prologue code here.*/ \
}
/**
* @brief ISR exit hook.
*/
#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
/* IRQ epilogue code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
/* Idle-enter code here.*/ \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
/* Idle-leave code here.*/ \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/**
* @brief Trace hook.
* @details This hook is invoked each time a new record is written in the
* trace buffer.
*/
#define CH_CFG_TRACE_HOOK(tep) { \
/* Trace code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* CHCONF_H */
/** @} */

View File

@ -0,0 +1,327 @@
/*
Copyright (C) 2015 Stephen Caudle
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C TRUE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL FALSE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS TRUE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,173 @@
/*
ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef HALCONF_COMMUNITY_H
#define HALCONF_COMMUNITY_H
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the CRC subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the RNG subsystem.
*/
#if !defined(HAL_USE_RNG) || defined(__DOXYGEN__)
#define HAL_USE_RNG FALSE
#endif
/**
* @brief Enables the EEPROM subsystem.
*/
#if !defined(HAL_USE_EEPROM) || defined(__DOXYGEN__)
#define HAL_USE_EEPROM FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_TIMCAP) || defined(__DOXYGEN__)
#define HAL_USE_TIMCAP FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_COMP) || defined(__DOXYGEN__)
#define HAL_USE_COMP FALSE
#endif
/**
* @brief Enables the QEI subsystem.
*/
#if !defined(HAL_USE_QEI) || defined(__DOXYGEN__)
#define HAL_USE_QEI FALSE
#endif
/**
* @brief Enables the USBH subsystem.
*/
#if !defined(HAL_USE_USBH) || defined(__DOXYGEN__)
#define HAL_USE_USBH FALSE
#endif
/**
* @brief Enables the USB_MSD subsystem.
*/
#if !defined(HAL_USE_USB_MSD) || defined(__DOXYGEN__)
#define HAL_USE_USB_MSD FALSE
#endif
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM TRUE
/*===========================================================================*/
/* QEI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables discard of overlow
*/
#if !defined(QEI_USE_OVERFLOW_DISCARD) || defined(__DOXYGEN__)
#define QEI_USE_OVERFLOW_DISCARD FALSE
#endif
/**
* @brief Enables min max of overlow
*/
#if !defined(QEI_USE_OVERFLOW_MINMAX) || defined(__DOXYGEN__)
#define QEI_USE_OVERFLOW_MINMAX FALSE
#endif
/*===========================================================================*/
/* EEProm driver related settings. */
/*===========================================================================*/
/**
* @brief Enables 24xx series I2C eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE24XX FALSE
/**
* @brief Enables 25xx series SPI eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE25XX FALSE
#endif /* HALCONF_COMMUNITY_H */
/** @} */

View File

@ -0,0 +1,165 @@
/*
Copyright (C) 2015 Stephen Caudle
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This demo:
1) Writes bytes to the EEPROM
2) Reads the same bytes back
3) Inverts the byte values
4) Writes them
5) Reads them back
*/
#include <stdlib.h>
#include "ch.h"
#include "hal.h"
#define I2C_ADDR 0x50
#define I2C_FAKE_ADDR 0x4C
#define EEPROM_START_ADDR 0x00
/*
* EEPROM thread.
*/
static THD_WORKING_AREA(PollEepromThreadWA, 1024);
static THD_FUNCTION(PollEepromThread, arg) {
unsigned i;
uint8_t tx_data[6];
uint8_t rx_data[4];
msg_t status;
(void)arg;
chRegSetThreadName("PollEeprom");
/* set initial data to write */
tx_data[0] = EEPROM_START_ADDR;
tx_data[1] = EEPROM_START_ADDR;
tx_data[2] = 0xA0;
tx_data[3] = 0xA1;
tx_data[4] = 0xA2;
tx_data[5] = 0xA3;
while (true) {
/* write out initial data */
i2cAcquireBus(&I2CD1);
status = i2cMasterTransmitTimeout(&I2CD1, I2C_ADDR, tx_data, sizeof(tx_data), NULL, 0, TIME_INFINITE);
i2cReleaseBus(&I2CD1);
osalDbgCheck(MSG_OK == status);
/* read back inital data */
osalThreadSleepMilliseconds(2);
i2cAcquireBus(&I2CD1);
status = i2cMasterTransmitTimeout(&I2CD1, I2C_ADDR, tx_data, 2, rx_data, sizeof(rx_data), TIME_INFINITE);
i2cReleaseBus(&I2CD1);
osalDbgCheck(MSG_OK == status);
/* invert the data */
for (i = 2; i < sizeof(tx_data); i++)
tx_data[i] ^= 0xff;
/* write out inverted data */
osalThreadSleepMilliseconds(2);
i2cAcquireBus(&I2CD1);
status = i2cMasterTransmitTimeout(&I2CD1, I2C_ADDR, tx_data, sizeof(tx_data), NULL, 0, TIME_INFINITE);
i2cReleaseBus(&I2CD1);
osalDbgCheck(MSG_OK == status);
/* read back inverted data */
osalThreadSleepMilliseconds(2);
i2cAcquireBus(&I2CD1);
status = i2cMasterTransmitTimeout(&I2CD1, I2C_ADDR, tx_data, 2, rx_data, sizeof(rx_data), TIME_INFINITE);
i2cReleaseBus(&I2CD1);
osalDbgCheck(MSG_OK == status);
osalThreadSleepMilliseconds(TIME_INFINITE);
}
}
/*
* Fake polling thread.
*/
static THD_WORKING_AREA(PollFakeThreadWA, 256);
static THD_FUNCTION(PollFakeThread, arg) {
(void)arg;
chRegSetThreadName("PollFake");
while (true) {
msg_t status;
uint8_t rx_data[2];
i2cflags_t errors;
i2cAcquireBus(&I2CD1);
status = i2cMasterReceiveTimeout(&I2CD1, I2C_FAKE_ADDR, rx_data, 2, TIME_MS2I(4));
i2cReleaseBus(&I2CD1);
if (status == MSG_RESET){
errors = i2cGetErrors(&I2CD1);
osalDbgCheck(I2C_ACK_FAILURE == errors);
}
palTogglePad(IOPORT1, LED1); /* on */
osalThreadSleepMilliseconds(1000);
}
}
/*
* I2C1 config.
*/
static const I2CConfig i2cfg = {
100000,
I2C_SCL,
I2C_SDA,
};
/*
* Entry point, note, the main() function is already a thread in the system
* on entry.
*/
int main(void) {
halInit();
chSysInit();
i2cStart(&I2CD1, &i2cfg);
/* Create EEPROM thread. */
chThdCreateStatic(PollEepromThreadWA,
sizeof(PollEepromThreadWA),
NORMALPRIO,
PollEepromThread,
NULL);
/* Create not responding thread. */
chThdCreateStatic(PollFakeThreadWA,
sizeof(PollFakeThreadWA),
NORMALPRIO,
PollFakeThread,
NULL);
/* main loop handles LED */
while (true) {
palTogglePad(IOPORT1, LED2); /* on */
osalThreadSleepMilliseconds(500);
}
return 0;
}

View File

@ -0,0 +1,25 @@
/*
Copyright (C) 2015 Stephen Caudle
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* HAL driver system settings.
*/
#define NRF5_I2C_USE_I2C0 TRUE
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,21 @@
*****************************************************************************
** ChibiOS/HAL - I2C driver demo for NRF52832. **
*****************************************************************************
** TARGET **
The demo runs on an EByte E73-2G4M04S board.
** The Demo **
The application demonstrates the use of the NRF52832 I2C driver.
** Board Setup **
- Connect AT24CXX EEPROM board to I2C port on E73-2G4M04S board
** Build Procedure **
The demo has been tested using the free Codesourcery GCC-based toolchain
and YAGARTO.
Just modify the TRGT line in the makefile in order to use different GCC ports.

View File

@ -0,0 +1,228 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
# If enabled, this option makes the build process faster by not compiling
# modules not used in the current configuration.
ifeq ($(USE_SMART_BUILD),)
USE_SMART_BUILD = yes
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Startup files.
include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_nrf52.mk
# Licensing files.
include $(CHIBIOS)/os/license/license.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NRF5/NRF52832/platform.mk
include $(CHIBIOS_CONTRIB)/os/hal/boards/NRF52-E73-2G4M04S/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/NRF52832.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(ALLCSRC) \
$(TESTSRC) \
$(CHIBIOS)/os/hal/lib/streams/memstreams.c \
$(CHIBIOS)/os/hal/lib/streams/chprintf.c \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC = $(ALLCPPSRC)
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(ALLASMSRC)
ASMXSRC = $(ALLXASMSRC)
INCDIR = $(ALLINC) $(TESTINC) \
$(CHIBIOS)/os/hal/lib/streams \
$(TESTHAL)
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m4
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
SREC = $(CP) -O srec
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk
include $(CHIBIOS_CONTRIB)/os/various/jlink.mk
JLINK_DEVICE = nrf51422
JLINK_PRE_FLASH = w4 4001e504 1
JLINK_ERASE_ALL = w4 4001e504 2\nw4 4001e50c 1\nsleep 100
flash: all jlink-flash

View File

@ -0,0 +1,696 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef CHCONF_H
#define CHCONF_H
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_5_1_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION 32
#endif
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#if !defined(CH_CFG_ST_FREQUENCY)
#define CH_CFG_ST_FREQUENCY 1000
#endif
/**
* @brief Time intervals data size.
* @note Allowed values are 16, 32 or 64 bits.
*/
#if !defined(CH_CFG_INTERVALS_SIZE)
#define CH_CFG_INTERVALS_SIZE 32
#endif
/**
* @brief Time types data size.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_TIME_TYPES_SIZE)
#define CH_CFG_TIME_TYPES_SIZE 32
#endif
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#if !defined(CH_CFG_ST_TIMEDELTA)
#define CH_CFG_ST_TIMEDELTA 0
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#if !defined(CH_CFG_TIME_QUANTUM)
#define CH_CFG_TIME_QUANTUM 2
#endif
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#if !defined(CH_CFG_MEMCORE_SIZE)
#define CH_CFG_MEMCORE_SIZE 0
#endif
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#if !defined(CH_CFG_NO_IDLE_THREAD)
#define CH_CFG_NO_IDLE_THREAD FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_OPTIMIZE_SPEED)
#define CH_CFG_OPTIMIZE_SPEED TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_TM)
#define CH_CFG_USE_TM FALSE
#endif
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_REGISTRY)
#define CH_CFG_USE_REGISTRY TRUE
#endif
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_WAITEXIT)
#define CH_CFG_USE_WAITEXIT TRUE
#endif
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_SEMAPHORES)
#define CH_CFG_USE_SEMAPHORES TRUE
#endif
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
#endif
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MUTEXES)
#define CH_CFG_USE_MUTEXES TRUE
#endif
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
#endif
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_CONDVARS)
#define CH_CFG_USE_CONDVARS TRUE
#endif
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
#endif
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_EVENTS)
#define CH_CFG_USE_EVENTS TRUE
#endif
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
#endif
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MESSAGES)
#define CH_CFG_USE_MESSAGES TRUE
#endif
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
#endif
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_MAILBOXES)
#define CH_CFG_USE_MAILBOXES TRUE
#endif
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMCORE)
#define CH_CFG_USE_MEMCORE TRUE
#endif
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_CFG_USE_HEAP)
#define CH_CFG_USE_HEAP TRUE
#endif
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMPOOLS)
#define CH_CFG_USE_MEMPOOLS TRUE
#endif
/**
* @brief Objects FIFOs APIs.
* @details If enabled then the objects FIFOs APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_OBJ_FIFOS)
#define CH_CFG_USE_OBJ_FIFOS TRUE
#endif
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#if !defined(CH_CFG_USE_DYNAMIC)
#define CH_CFG_USE_DYNAMIC TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Objects factory options
* @{
*/
/*===========================================================================*/
/**
* @brief Objects Factory APIs.
* @details If enabled then the objects factory APIs are included in the
* kernel.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_CFG_USE_FACTORY)
#define CH_CFG_USE_FACTORY TRUE
#endif
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
#endif
/**
* @brief Enables the registry of generic objects.
*/
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#endif
/**
* @brief Enables factory for generic buffers.
*/
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#endif
/**
* @brief Enables factory for semaphores.
*/
#if !defined(CH_CFG_FACTORY_SEMAPHORES)
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#endif
/**
* @brief Enables factory for mailboxes.
*/
#if !defined(CH_CFG_FACTORY_MAILBOXES)
#define CH_CFG_FACTORY_MAILBOXES TRUE
#endif
/**
* @brief Enables factory for objects FIFOs.
*/
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_STATISTICS)
#define CH_DBG_STATISTICS FALSE
#endif
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
#endif
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS)
#define CH_DBG_ENABLE_CHECKS TRUE
#endif
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS)
#define CH_DBG_ENABLE_ASSERTS TRUE
#endif
/**
* @brief Debug option, trace buffer.
* @details If enabled then the trace buffer is activated.
*
* @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_MASK)
#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_ALL
#endif
/**
* @brief Trace buffer entries.
* @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
* different from @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
#define CH_DBG_TRACE_BUFFER_SIZE 128
#endif
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK)
#define CH_DBG_ENABLE_STACK_CHECK TRUE
#endif
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS)
#define CH_DBG_FILL_THREADS TRUE
#endif
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#if !defined(CH_DBG_THREADS_PROFILING)
#define CH_DBG_THREADS_PROFILING FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief System structure extension.
* @details User fields added to the end of the @p ch_system_t structure.
*/
#define CH_CFG_SYSTEM_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief System initialization hook.
* @details User initialization code added to the @p chSysInit() function
* just before interrupts are enabled globally.
*/
#define CH_CFG_SYSTEM_INIT_HOOK() { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p _thread_init() function.
*
* @note It is invoked from within @p _thread_init() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief ISR enter hook.
*/
#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
/* IRQ prologue code here.*/ \
}
/**
* @brief ISR exit hook.
*/
#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
/* IRQ epilogue code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
/* Idle-enter code here.*/ \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
/* Idle-leave code here.*/ \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/**
* @brief Trace hook.
* @details This hook is invoked each time a new record is written in the
* trace buffer.
*/
#define CH_CFG_TRACE_HOOK(tep) { \
/* Trace code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* CHCONF_H */
/** @} */

View File

@ -0,0 +1,327 @@
/*
Copyright (C) 2015 Fabio Utzig
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU TRUE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM TRUE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL TRUE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS TRUE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,173 @@
/*
ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef HALCONF_COMMUNITY_H
#define HALCONF_COMMUNITY_H
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the CRC subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the RNG subsystem.
*/
#if !defined(HAL_USE_RNG) || defined(__DOXYGEN__)
#define HAL_USE_RNG FALSE
#endif
/**
* @brief Enables the EEPROM subsystem.
*/
#if !defined(HAL_USE_EEPROM) || defined(__DOXYGEN__)
#define HAL_USE_EEPROM FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_TIMCAP) || defined(__DOXYGEN__)
#define HAL_USE_TIMCAP FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_COMP) || defined(__DOXYGEN__)
#define HAL_USE_COMP FALSE
#endif
/**
* @brief Enables the QEI subsystem.
*/
#if !defined(HAL_USE_QEI) || defined(__DOXYGEN__)
#define HAL_USE_QEI FALSE
#endif
/**
* @brief Enables the USBH subsystem.
*/
#if !defined(HAL_USE_USBH) || defined(__DOXYGEN__)
#define HAL_USE_USBH FALSE
#endif
/**
* @brief Enables the USB_MSD subsystem.
*/
#if !defined(HAL_USE_USB_MSD) || defined(__DOXYGEN__)
#define HAL_USE_USB_MSD FALSE
#endif
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM TRUE
/*===========================================================================*/
/* QEI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables discard of overlow
*/
#if !defined(QEI_USE_OVERFLOW_DISCARD) || defined(__DOXYGEN__)
#define QEI_USE_OVERFLOW_DISCARD FALSE
#endif
/**
* @brief Enables min max of overlow
*/
#if !defined(QEI_USE_OVERFLOW_MINMAX) || defined(__DOXYGEN__)
#define QEI_USE_OVERFLOW_MINMAX FALSE
#endif
/*===========================================================================*/
/* EEProm driver related settings. */
/*===========================================================================*/
/**
* @brief Enables 24xx series I2C eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE24XX FALSE
/**
* @brief Enables 25xx series SPI eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE25XX FALSE
#endif /* HALCONF_COMMUNITY_H */
/** @} */

View File

@ -0,0 +1,122 @@
/*
Copyright (C) 2018 andru
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
static icucnt_t last_width, last_period;
static SerialConfig serial_config = {
.speed = 38400,
.tx_pad = UART_TX,
.rx_pad = UART_RX,
#if NRF5_SERIAL_USE_HWFLOWCTRL == TRUE
.rts_pad = UART_RTS,
.cts_pad = UART_CTS,
#endif
};
static void pwm_cb_period(PWMDriver *pwmp) {
(void)pwmp;
palTogglePad(IOPORT1, LED1);
}
void icu_width_cb(ICUDriver *icup) {
last_width = icuGetWidthX(icup);
}
void icu_period_cb(ICUDriver *icup) {
last_period = icuGetPeriodX(icup);
}
ICUConfig icucfg = {
.frequency = ICU_FREQUENCY_250KHZ,
.width_cb = icu_width_cb,
.period_cb = icu_period_cb,
NULL,
.iccfgp = {
{
.ioline = { BTN1, BTN2 },
.mode = ICU_INPUT_ACTIVE_HIGH,
.gpiote_channel = { 0, 1 },
.ppi_channel = { 0, 1 },
},
},
};
PWMConfig pwmcfg = {
.frequency = PWM_FREQUENCY_125KHZ,
.period = 12500,
.callback = pwm_cb_period,
{
{ .mode = PWM_OUTPUT_DISABLED,
},
{ .mode = PWM_OUTPUT_ACTIVE_HIGH,
.ioline = LINE_LED2,
},
},
};
/*
* Application entry point.
*/
int main(void) {
/*
* System initializations.
* - HAL initialization, this also initializes the configured device drivers
* and performs the board-specific initializations.
* - Kernel initialization, the main() function becomes a thread and the
* RTOS is active.
*/
halInit();
chSysInit();
sdStart(&SD1, &serial_config);
/*
*
*/
pwmStart(&PWMD1, &pwmcfg);
pwmEnablePeriodicNotification(&PWMD1);
icuStart(&ICUD1, &icucfg);
icuStartCapture(&ICUD1);
pwmEnableChannel(&PWMD1, 1, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 2500)); // 25%
chThdSleepMilliseconds(5000);
chprintf((BaseSequentialStream *) &SD1, "period=%d, width=%d\r\n", last_period, last_width);
pwmEnableChannel(&PWMD1, 1, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 5000)); // 50%
chThdSleepMilliseconds(5000);
chprintf((BaseSequentialStream *) &SD1, "period=%d, width=%d\r\n", last_period, last_width);
pwmEnableChannel(&PWMD1, 1, PWM_PERCENTAGE_TO_WIDTH(&PWMD1, 7500)); // 75%
chThdSleepMilliseconds(5000);
chprintf((BaseSequentialStream *) &SD1, "period=%d, width=%d\r\n", last_period, last_width);
pwmChangePeriod(&PWMD1, 5000);
chThdSleepMilliseconds(5000);
pwmDisableChannel(&PWMD1, 1);
pwmStop(&PWMD1);
icuStopCapture(&ICUD1);
icuStop(&ICUD1);
while (true) {
chThdSleepMilliseconds(500);
}
}

View File

@ -0,0 +1,33 @@
/*
Copyright (C) 2015 Fabio Utzig
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* HAL driver system settings.
*/
#define NRF5_SERIAL_USE_UART0 TRUE
#define NRF5_ST_USE_RTC0 TRUE
#define NRF5_ST_USE_RTC1 FALSE
#define NRF5_ST_USE_TIMER0 FALSE
#define NRF5_PWM_USE_PWM0 TRUE
#define NRF5_PWM_PWM0_PRIORITY 6
#define NRF5_ICU_USE_TIMER0 TRUE
#define NRF5_ICU_GPIOTE_IRQ_PRIORITY 4
#define NRF5_ICU_TIMER0_IRQ_PRIORITY 4
#endif /* _MCUCONF_H_ */

View File

@ -0,0 +1,212 @@
##############################################################################
# Build global options
# NOTE: Can be overridden externally.
#
# Compiler options here.
ifeq ($(USE_OPT),)
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
endif
# C specific options here (added to USE_OPT).
ifeq ($(USE_COPT),)
USE_COPT =
endif
# C++ specific options here (added to USE_OPT).
ifeq ($(USE_CPPOPT),)
USE_CPPOPT = -fno-rtti
endif
# Enable this if you want the linker to remove unused code and data
ifeq ($(USE_LINK_GC),)
USE_LINK_GC = yes
endif
# Linker extra options here.
ifeq ($(USE_LDOPT),)
USE_LDOPT =
endif
# Enable this if you want link time optimizations (LTO)
ifeq ($(USE_LTO),)
USE_LTO = yes
endif
# If enabled, this option allows to compile the application in THUMB mode.
ifeq ($(USE_THUMB),)
USE_THUMB = yes
endif
# Enable this if you want to see the full log while compiling.
ifeq ($(USE_VERBOSE_COMPILE),)
USE_VERBOSE_COMPILE = no
endif
#
# Build global options
##############################################################################
##############################################################################
# Architecture or project specific options
#
# Stack size to be allocated to the Cortex-M process stack. This stack is
# the stack used by the main() thread.
ifeq ($(USE_PROCESS_STACKSIZE),)
USE_PROCESS_STACKSIZE = 0x400
endif
# Stack size to the allocated to the Cortex-M main/exceptions stack. This
# stack is used for processing interrupts and exceptions.
ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
USE_EXCEPTIONS_STACKSIZE = 0x400
endif
# Enables the use of FPU on Cortex-M4 (no, softfp, hard).
ifeq ($(USE_FPU),)
USE_FPU = no
endif
#
# Architecture or project specific options
##############################################################################
##############################################################################
# Project, sources and paths
#
# Define project name here
PROJECT = ch
# Imported source files and paths
CHIBIOS = ../../../../../ChibiOS-RT
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Licensing files.
include $(CHIBIOS)/os/license/license.mk
# Startup files.
include $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_nrf52.mk
# HAL-OSAL files (optional).
include $(CHIBIOS)/os/hal/hal.mk
include $(CHIBIOS_CONTRIB)/os/hal/ports/NRF5/NRF52832/platform.mk
include $(CHIBIOS_CONTRIB)/os/hal/boards/NRF52-E73-2G4M04S/board.mk
include $(CHIBIOS)/os/hal/osal/rt/osal.mk
# RTOS files (optional).
include $(CHIBIOS)/os/rt/rt.mk
include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
# Other files (optional).
#include $(CHIBIOS)/test/rt/test.mk
# Define linker script file here
LDSCRIPT= $(STARTUPLD)/NRF52832.ld
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC = $(ALLCSRC) \
$(TESTSRC) \
$(CHIBIOS)/os/various/syscalls.c \
$(CHIBIOS)/os/hal/lib/streams/memstreams.c \
$(CHIBIOS)/os/hal/lib/streams/chprintf.c \
nrf52_radio.c \
main.c
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CPPSRC = $(ALLCPPSRC)
# C sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACSRC =
# C++ sources to be compiled in ARM mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
ACPPSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCSRC =
# C sources to be compiled in THUMB mode regardless of the global setting.
# NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler
# option that results in lower performance and larger code size.
TCPPSRC =
# List ASM source files here
ASMSRC = $(ALLASMSRC)
ASMXSRC = $(ALLXASMSRC)
INCDIR = $(ALLINC) $(TESTINC) \
$(CHIBIOS)/os/hal/lib/streams \
$(TESTHAL)
#
# Project, sources and paths
##############################################################################
##############################################################################
# Compiler settings
#
MCU = cortex-m4
TRGT = arm-none-eabi-
CC = $(TRGT)gcc
CPPC = $(TRGT)g++
# Enable loading with g++ only if you need C++ runtime support.
# NOTE: You can use C++ even without C++ support if you are careful. C++
# runtime support makes code size explode.
LD = $(TRGT)gcc
#LD = $(TRGT)g++
CP = $(TRGT)objcopy
AS = $(TRGT)gcc -x assembler-with-cpp
AR = $(TRGT)ar
OD = $(TRGT)objdump
SZ = $(TRGT)size
HEX = $(CP) -O ihex
BIN = $(CP) -O binary
SREC = $(CP) -O srec
# ARM-specific options here
AOPT =
# THUMB-specific options here
TOPT = -mthumb -DTHUMB
# Define C warning options here
CWARN = -Wall -Wextra -Wstrict-prototypes
# Define C++ warning options here
CPPWARN = -Wall -Wextra
#
# Compiler settings
##############################################################################
##############################################################################
# Start of user section
#
# List all user C define here, like -D_DEBUG=1
UDEFS =
# Define ASM defines here
UADEFS =
# List all user directories here
UINCDIR =
# List the user directory to look for the libraries here
ULIBDIR =
# List all user libraries here
ULIBS =
#
# End of user defines
##############################################################################
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
include $(RULESPATH)/rules.mk

View File

@ -0,0 +1,696 @@
/*
ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/chconf.h
* @brief Configuration file template.
* @details A copy of this file must be placed in each project directory, it
* contains the application specific kernel settings.
*
* @addtogroup config
* @details Kernel related settings and hooks.
* @{
*/
#ifndef CHCONF_H
#define CHCONF_H
#define _CHIBIOS_RT_CONF_
#define _CHIBIOS_RT_CONF_VER_5_1_
/*===========================================================================*/
/**
* @name System timers settings
* @{
*/
/*===========================================================================*/
/**
* @brief System time counter resolution.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_ST_RESOLUTION)
#define CH_CFG_ST_RESOLUTION 32
#endif
/**
* @brief System tick frequency.
* @details Frequency of the system timer that drives the system ticks. This
* setting also defines the system tick time unit.
*/
#if !defined(CH_CFG_ST_FREQUENCY)
#define CH_CFG_ST_FREQUENCY 1000
#endif
/**
* @brief Time intervals data size.
* @note Allowed values are 16, 32 or 64 bits.
*/
#if !defined(CH_CFG_INTERVALS_SIZE)
#define CH_CFG_INTERVALS_SIZE 32
#endif
/**
* @brief Time types data size.
* @note Allowed values are 16 or 32 bits.
*/
#if !defined(CH_CFG_TIME_TYPES_SIZE)
#define CH_CFG_TIME_TYPES_SIZE 32
#endif
/**
* @brief Time delta constant for the tick-less mode.
* @note If this value is zero then the system uses the classic
* periodic tick. This value represents the minimum number
* of ticks that is safe to specify in a timeout directive.
* The value one is not valid, timeouts are rounded up to
* this value.
*/
#if !defined(CH_CFG_ST_TIMEDELTA)
#define CH_CFG_ST_TIMEDELTA 0
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel parameters and options
* @{
*/
/*===========================================================================*/
/**
* @brief Round robin interval.
* @details This constant is the number of system ticks allowed for the
* threads before preemption occurs. Setting this value to zero
* disables the preemption for threads with equal priority and the
* round robin becomes cooperative. Note that higher priority
* threads can still preempt, the kernel is always preemptive.
* @note Disabling the round robin preemption makes the kernel more compact
* and generally faster.
* @note The round robin preemption is not supported in tickless mode and
* must be set to zero in that case.
*/
#if !defined(CH_CFG_TIME_QUANTUM)
#define CH_CFG_TIME_QUANTUM 2
#endif
/**
* @brief Managed RAM size.
* @details Size of the RAM area to be managed by the OS. If set to zero
* then the whole available RAM is used. The core memory is made
* available to the heap allocator and/or can be used directly through
* the simplified core memory allocator.
*
* @note In order to let the OS manage the whole RAM the linker script must
* provide the @p __heap_base__ and @p __heap_end__ symbols.
* @note Requires @p CH_CFG_USE_MEMCORE.
*/
#if !defined(CH_CFG_MEMCORE_SIZE)
#define CH_CFG_MEMCORE_SIZE 0
#endif
/**
* @brief Idle thread automatic spawn suppression.
* @details When this option is activated the function @p chSysInit()
* does not spawn the idle thread. The application @p main()
* function becomes the idle thread and must implement an
* infinite loop.
*/
#if !defined(CH_CFG_NO_IDLE_THREAD)
#define CH_CFG_NO_IDLE_THREAD FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Performance options
* @{
*/
/*===========================================================================*/
/**
* @brief OS optimization.
* @details If enabled then time efficient rather than space efficient code
* is used when two possible implementations exist.
*
* @note This is not related to the compiler optimization options.
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_OPTIMIZE_SPEED)
#define CH_CFG_OPTIMIZE_SPEED TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Subsystem options
* @{
*/
/*===========================================================================*/
/**
* @brief Time Measurement APIs.
* @details If enabled then the time measurement APIs are included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_TM)
#define CH_CFG_USE_TM FALSE
#endif
/**
* @brief Threads registry APIs.
* @details If enabled then the registry APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_REGISTRY)
#define CH_CFG_USE_REGISTRY TRUE
#endif
/**
* @brief Threads synchronization APIs.
* @details If enabled then the @p chThdWait() function is included in
* the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_WAITEXIT)
#define CH_CFG_USE_WAITEXIT TRUE
#endif
/**
* @brief Semaphores APIs.
* @details If enabled then the Semaphores APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_SEMAPHORES)
#define CH_CFG_USE_SEMAPHORES TRUE
#endif
/**
* @brief Semaphores queuing mode.
* @details If enabled then the threads are enqueued on semaphores by
* priority rather than in FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_SEMAPHORES_PRIORITY)
#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
#endif
/**
* @brief Mutexes APIs.
* @details If enabled then the mutexes APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MUTEXES)
#define CH_CFG_USE_MUTEXES TRUE
#endif
/**
* @brief Enables recursive behavior on mutexes.
* @note Recursive mutexes are heavier and have an increased
* memory footprint.
*
* @note The default is @p FALSE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_MUTEXES_RECURSIVE)
#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
#endif
/**
* @brief Conditional Variables APIs.
* @details If enabled then the conditional variables APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MUTEXES.
*/
#if !defined(CH_CFG_USE_CONDVARS)
#define CH_CFG_USE_CONDVARS TRUE
#endif
/**
* @brief Conditional Variables APIs with timeout.
* @details If enabled then the conditional variables APIs with timeout
* specification are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_CONDVARS.
*/
#if !defined(CH_CFG_USE_CONDVARS_TIMEOUT)
#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
#endif
/**
* @brief Events Flags APIs.
* @details If enabled then the event flags APIs are included in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_EVENTS)
#define CH_CFG_USE_EVENTS TRUE
#endif
/**
* @brief Events Flags APIs with timeout.
* @details If enabled then the events APIs with timeout specification
* are included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_EVENTS.
*/
#if !defined(CH_CFG_USE_EVENTS_TIMEOUT)
#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
#endif
/**
* @brief Synchronous Messages APIs.
* @details If enabled then the synchronous messages APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MESSAGES)
#define CH_CFG_USE_MESSAGES TRUE
#endif
/**
* @brief Synchronous Messages queuing mode.
* @details If enabled then messages are served by priority rather than in
* FIFO order.
*
* @note The default is @p FALSE. Enable this if you have special
* requirements.
* @note Requires @p CH_CFG_USE_MESSAGES.
*/
#if !defined(CH_CFG_USE_MESSAGES_PRIORITY)
#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
#endif
/**
* @brief Mailboxes APIs.
* @details If enabled then the asynchronous messages (mailboxes) APIs are
* included in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_SEMAPHORES.
*/
#if !defined(CH_CFG_USE_MAILBOXES)
#define CH_CFG_USE_MAILBOXES TRUE
#endif
/**
* @brief Core Memory Manager APIs.
* @details If enabled then the core memory manager APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMCORE)
#define CH_CFG_USE_MEMCORE TRUE
#endif
/**
* @brief Heap Allocator APIs.
* @details If enabled then the memory heap allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
* @p CH_CFG_USE_SEMAPHORES.
* @note Mutexes are recommended.
*/
#if !defined(CH_CFG_USE_HEAP)
#define CH_CFG_USE_HEAP TRUE
#endif
/**
* @brief Memory Pools Allocator APIs.
* @details If enabled then the memory pools allocator APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_MEMPOOLS)
#define CH_CFG_USE_MEMPOOLS TRUE
#endif
/**
* @brief Objects FIFOs APIs.
* @details If enabled then the objects FIFOs APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
*/
#if !defined(CH_CFG_USE_OBJ_FIFOS)
#define CH_CFG_USE_OBJ_FIFOS TRUE
#endif
/**
* @brief Dynamic Threads APIs.
* @details If enabled then the dynamic threads creation APIs are included
* in the kernel.
*
* @note The default is @p TRUE.
* @note Requires @p CH_CFG_USE_WAITEXIT.
* @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
*/
#if !defined(CH_CFG_USE_DYNAMIC)
#define CH_CFG_USE_DYNAMIC TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Objects factory options
* @{
*/
/*===========================================================================*/
/**
* @brief Objects Factory APIs.
* @details If enabled then the objects factory APIs are included in the
* kernel.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_CFG_USE_FACTORY)
#define CH_CFG_USE_FACTORY TRUE
#endif
/**
* @brief Maximum length for object names.
* @details If the specified length is zero then the name is stored by
* pointer but this could have unintended side effects.
*/
#if !defined(CH_CFG_FACTORY_MAX_NAMES_LENGTH)
#define CH_CFG_FACTORY_MAX_NAMES_LENGTH 8
#endif
/**
* @brief Enables the registry of generic objects.
*/
#if !defined(CH_CFG_FACTORY_OBJECTS_REGISTRY)
#define CH_CFG_FACTORY_OBJECTS_REGISTRY TRUE
#endif
/**
* @brief Enables factory for generic buffers.
*/
#if !defined(CH_CFG_FACTORY_GENERIC_BUFFERS)
#define CH_CFG_FACTORY_GENERIC_BUFFERS TRUE
#endif
/**
* @brief Enables factory for semaphores.
*/
#if !defined(CH_CFG_FACTORY_SEMAPHORES)
#define CH_CFG_FACTORY_SEMAPHORES TRUE
#endif
/**
* @brief Enables factory for mailboxes.
*/
#if !defined(CH_CFG_FACTORY_MAILBOXES)
#define CH_CFG_FACTORY_MAILBOXES TRUE
#endif
/**
* @brief Enables factory for objects FIFOs.
*/
#if !defined(CH_CFG_FACTORY_OBJ_FIFOS)
#define CH_CFG_FACTORY_OBJ_FIFOS TRUE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Debug options
* @{
*/
/*===========================================================================*/
/**
* @brief Debug option, kernel statistics.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_STATISTICS)
#define CH_DBG_STATISTICS FALSE
#endif
/**
* @brief Debug option, system state check.
* @details If enabled the correct call protocol for system APIs is checked
* at runtime.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_SYSTEM_STATE_CHECK)
#define CH_DBG_SYSTEM_STATE_CHECK TRUE
#endif
/**
* @brief Debug option, parameters checks.
* @details If enabled then the checks on the API functions input
* parameters are activated.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_CHECKS)
#define CH_DBG_ENABLE_CHECKS TRUE
#endif
/**
* @brief Debug option, consistency checks.
* @details If enabled then all the assertions in the kernel code are
* activated. This includes consistency checks inside the kernel,
* runtime anomalies and port-defined checks.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_ENABLE_ASSERTS)
#define CH_DBG_ENABLE_ASSERTS TRUE
#endif
/**
* @brief Debug option, trace buffer.
* @details If enabled then the trace buffer is activated.
*
* @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_MASK)
#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_ALL
#endif
/**
* @brief Trace buffer entries.
* @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
* different from @p CH_DBG_TRACE_MASK_DISABLED.
*/
#if !defined(CH_DBG_TRACE_BUFFER_SIZE)
#define CH_DBG_TRACE_BUFFER_SIZE 128
#endif
/**
* @brief Debug option, stack checks.
* @details If enabled then a runtime stack check is performed.
*
* @note The default is @p FALSE.
* @note The stack check is performed in a architecture/port dependent way.
* It may not be implemented or some ports.
* @note The default failure mode is to halt the system with the global
* @p panic_msg variable set to @p NULL.
*/
#if !defined(CH_DBG_ENABLE_STACK_CHECK)
#define CH_DBG_ENABLE_STACK_CHECK TRUE
#endif
/**
* @brief Debug option, stacks initialization.
* @details If enabled then the threads working area is filled with a byte
* value when a thread is created. This can be useful for the
* runtime measurement of the used stack.
*
* @note The default is @p FALSE.
*/
#if !defined(CH_DBG_FILL_THREADS)
#define CH_DBG_FILL_THREADS TRUE
#endif
/**
* @brief Debug option, threads profiling.
* @details If enabled then a field is added to the @p thread_t structure that
* counts the system ticks occurred while executing the thread.
*
* @note The default is @p FALSE.
* @note This debug option is not currently compatible with the
* tickless mode.
*/
#if !defined(CH_DBG_THREADS_PROFILING)
#define CH_DBG_THREADS_PROFILING FALSE
#endif
/** @} */
/*===========================================================================*/
/**
* @name Kernel hooks
* @{
*/
/*===========================================================================*/
/**
* @brief System structure extension.
* @details User fields added to the end of the @p ch_system_t structure.
*/
#define CH_CFG_SYSTEM_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief System initialization hook.
* @details User initialization code added to the @p chSysInit() function
* just before interrupts are enabled globally.
*/
#define CH_CFG_SYSTEM_INIT_HOOK() { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads descriptor structure extension.
* @details User fields added to the end of the @p thread_t structure.
*/
#define CH_CFG_THREAD_EXTRA_FIELDS \
/* Add threads custom fields here.*/
/**
* @brief Threads initialization hook.
* @details User initialization code added to the @p _thread_init() function.
*
* @note It is invoked from within @p _thread_init() and implicitly from all
* the threads creation APIs.
*/
#define CH_CFG_THREAD_INIT_HOOK(tp) { \
/* Add threads initialization code here.*/ \
}
/**
* @brief Threads finalization hook.
* @details User finalization code added to the @p chThdExit() API.
*/
#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
/* Add threads finalization code here.*/ \
}
/**
* @brief Context switch hook.
* @details This hook is invoked just before switching between threads.
*/
#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
/* Context switch code here.*/ \
}
/**
* @brief ISR enter hook.
*/
#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
/* IRQ prologue code here.*/ \
}
/**
* @brief ISR exit hook.
*/
#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
/* IRQ epilogue code here.*/ \
}
/**
* @brief Idle thread enter hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
/* Idle-enter code here.*/ \
}
/**
* @brief Idle thread leave hook.
* @note This hook is invoked within a critical zone, no OS functions
* should be invoked from here.
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
/* Idle-leave code here.*/ \
}
/**
* @brief Idle Loop hook.
* @details This hook is continuously invoked by the idle thread loop.
*/
#define CH_CFG_IDLE_LOOP_HOOK() { \
/* Idle loop code here.*/ \
}
/**
* @brief System tick event hook.
* @details This hook is invoked in the system tick handler immediately
* after processing the virtual timers queue.
*/
#define CH_CFG_SYSTEM_TICK_HOOK() { \
/* System tick event code here.*/ \
}
/**
* @brief System halt hook.
* @details This hook is invoked in case to a system halting error before
* the system is halted.
*/
#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
/* System halt code here.*/ \
}
/**
* @brief Trace hook.
* @details This hook is invoked each time a new record is written in the
* trace buffer.
*/
#define CH_CFG_TRACE_HOOK(tep) { \
/* Trace code here.*/ \
}
/** @} */
/*===========================================================================*/
/* Port-specific settings (override port settings defaulted in chcore.h). */
/*===========================================================================*/
#endif /* CHCONF_H */
/** @} */

View File

@ -0,0 +1,327 @@
/*
Copyright (C) 2015 Stephen Caudle
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/**
* @file templates/halconf.h
* @brief HAL configuration header.
* @details HAL configuration file, this file allows to enable or disable the
* various device drivers from your application. You may also use
* this file in order to override the device drivers default settings.
*
* @addtogroup HAL_CONF
* @{
*/
#ifndef _HALCONF_H_
#define _HALCONF_H_
#include "mcuconf.h"
/**
* @brief Enables the PAL subsystem.
*/
#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
#define HAL_USE_PAL TRUE
#endif
/**
* @brief Enables the ADC subsystem.
*/
#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
#define HAL_USE_ADC FALSE
#endif
/**
* @brief Enables the CAN subsystem.
*/
#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
#define HAL_USE_CAN FALSE
#endif
/**
* @brief Enables the EXT subsystem.
*/
#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
#define HAL_USE_EXT FALSE
#endif
/**
* @brief Enables the GPT subsystem.
*/
#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
#define HAL_USE_GPT FALSE
#endif
/**
* @brief Enables the I2C subsystem.
*/
#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
#define HAL_USE_I2C FALSE
#endif
/**
* @brief Enables the I2S subsystem.
*/
#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
#define HAL_USE_I2S FALSE
#endif
/**
* @brief Enables the ICU subsystem.
*/
#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
#define HAL_USE_ICU FALSE
#endif
/**
* @brief Enables the MAC subsystem.
*/
#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
#define HAL_USE_MAC FALSE
#endif
/**
* @brief Enables the MMC_SPI subsystem.
*/
#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
#define HAL_USE_MMC_SPI FALSE
#endif
/**
* @brief Enables the PWM subsystem.
*/
#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
#define HAL_USE_PWM FALSE
#endif
/**
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE
#endif
/**
* @brief Enables the SDC subsystem.
*/
#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
#define HAL_USE_SDC FALSE
#endif
/**
* @brief Enables the SERIAL subsystem.
*/
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL TRUE
#endif
/**
* @brief Enables the SERIAL over USB subsystem.
*/
#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
#define HAL_USE_SERIAL_USB FALSE
#endif
/**
* @brief Enables the SPI subsystem.
*/
#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
#define HAL_USE_SPI FALSE
#endif
/**
* @brief Enables the UART subsystem.
*/
#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
#define HAL_USE_UART FALSE
#endif
/**
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#endif
/*===========================================================================*/
/* ADC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
#define ADC_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define ADC_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* CAN driver related settings. */
/*===========================================================================*/
/**
* @brief Sleep mode related APIs inclusion switch.
*/
#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
#define CAN_USE_SLEEP_MODE TRUE
#endif
/*===========================================================================*/
/* I2C driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the mutual exclusion APIs on the I2C bus.
*/
#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define I2C_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* MAC driver related settings. */
/*===========================================================================*/
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
#define MAC_USE_ZERO_COPY FALSE
#endif
/**
* @brief Enables an event sources for incoming packets.
*/
#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
#define MAC_USE_EVENTS TRUE
#endif
/*===========================================================================*/
/* MMC_SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
* This option is recommended also if the SPI driver does not
* use a DMA channel and heavily loads the CPU.
*/
#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
#define MMC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SDC driver related settings. */
/*===========================================================================*/
/**
* @brief Number of initialization attempts before rejecting the card.
* @note Attempts are performed at 10mS intervals.
*/
#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
#define SDC_INIT_RETRY 100
#endif
/**
* @brief Include support for MMC cards.
* @note MMC support is not yet implemented so this option must be kept
* at @p FALSE.
*/
#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
#define SDC_MMC_SUPPORT FALSE
#endif
/**
* @brief Delays insertions.
* @details If enabled this options inserts delays into the MMC waiting
* routines releasing some extra CPU time for the threads with
* lower priority, this may slow down the driver a bit however.
*/
#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
#define SDC_NICE_WAITING TRUE
#endif
/*===========================================================================*/
/* SERIAL driver related settings. */
/*===========================================================================*/
/**
* @brief Default bit rate.
* @details Configuration parameter, this is the baud rate selected for the
* default configuration.
*/
#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
#define SERIAL_DEFAULT_BITRATE 38400
#endif
/**
* @brief Serial buffers size.
* @details Configuration parameter, you can change the depth of the queue
* buffers depending on the requirements of your application.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#endif
/*===========================================================================*/
/* SERIAL_USB driver related setting. */
/*===========================================================================*/
/**
* @brief Serial over USB buffers size.
* @details Configuration parameter, the buffer size must be a multiple of
* the USB data endpoint maximum packet size.
* @note The default is 64 bytes for both the transmission and receive
* buffers.
*/
#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_USB_BUFFERS_SIZE 256
#endif
/*===========================================================================*/
/* SPI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
#define SPI_USE_WAIT TRUE
#endif
/**
* @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define SPI_USE_MUTUAL_EXCLUSION TRUE
#endif
#endif /* _HALCONF_H_ */
/** @} */

View File

@ -0,0 +1,173 @@
/*
ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef HALCONF_COMMUNITY_H
#define HALCONF_COMMUNITY_H
/**
* @brief Enables the community overlay.
*/
#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
#define HAL_USE_COMMUNITY TRUE
#endif
/**
* @brief Enables the FSMC subsystem.
*/
#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
#define HAL_USE_FSMC FALSE
#endif
/**
* @brief Enables the NAND subsystem.
*/
#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
#define HAL_USE_NAND FALSE
#endif
/**
* @brief Enables the 1-wire subsystem.
*/
#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
#define HAL_USE_ONEWIRE FALSE
#endif
/**
* @brief Enables the EICU subsystem.
*/
#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
#define HAL_USE_EICU FALSE
#endif
/**
* @brief Enables the CRC subsystem.
*/
#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
#define HAL_USE_CRC FALSE
#endif
/**
* @brief Enables the RNG subsystem.
*/
#if !defined(HAL_USE_RNG) || defined(__DOXYGEN__)
#define HAL_USE_RNG FALSE
#endif
/**
* @brief Enables the EEPROM subsystem.
*/
#if !defined(HAL_USE_EEPROM) || defined(__DOXYGEN__)
#define HAL_USE_EEPROM FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_TIMCAP) || defined(__DOXYGEN__)
#define HAL_USE_TIMCAP FALSE
#endif
/**
* @brief Enables the TIMCAP subsystem.
*/
#if !defined(HAL_USE_COMP) || defined(__DOXYGEN__)
#define HAL_USE_COMP FALSE
#endif
/**
* @brief Enables the QEI subsystem.
*/
#if !defined(HAL_USE_QEI) || defined(__DOXYGEN__)
#define HAL_USE_QEI FALSE
#endif
/**
* @brief Enables the USBH subsystem.
*/
#if !defined(HAL_USE_USBH) || defined(__DOXYGEN__)
#define HAL_USE_USBH FALSE
#endif
/**
* @brief Enables the USB_MSD subsystem.
*/
#if !defined(HAL_USE_USB_MSD) || defined(__DOXYGEN__)
#define HAL_USE_USB_MSD FALSE
#endif
/*===========================================================================*/
/* FSMCNAND driver related settings. */
/*===========================================================================*/
/**
* @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
#define NAND_USE_MUTUAL_EXCLUSION TRUE
#endif
/*===========================================================================*/
/* 1-wire driver related settings. */
/*===========================================================================*/
/**
* @brief Enables strong pull up feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_STRONG_PULLUP FALSE
/**
* @brief Enables search ROM feature.
* @note Disabling this option saves both code and data space.
*/
#define ONEWIRE_USE_SEARCH_ROM TRUE
/*===========================================================================*/
/* QEI driver related settings. */
/*===========================================================================*/
/**
* @brief Enables discard of overlow
*/
#if !defined(QEI_USE_OVERFLOW_DISCARD) || defined(__DOXYGEN__)
#define QEI_USE_OVERFLOW_DISCARD FALSE
#endif
/**
* @brief Enables min max of overlow
*/
#if !defined(QEI_USE_OVERFLOW_MINMAX) || defined(__DOXYGEN__)
#define QEI_USE_OVERFLOW_MINMAX FALSE
#endif
/*===========================================================================*/
/* EEProm driver related settings. */
/*===========================================================================*/
/**
* @brief Enables 24xx series I2C eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE24XX FALSE
/**
* @brief Enables 25xx series SPI eeprom device driver.
* @note Disabling this option saves both code and data space.
*/
#define EEPROM_USE_EE25XX FALSE
#endif /* HALCONF_COMMUNITY_H */
/** @} */

View File

@ -0,0 +1,122 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#include "nrf52_radio.h"
static SerialConfig serial_config = {
.speed = 38400,
.tx_pad = UART_TX,
.rx_pad = UART_RX,
#if NRF5_SERIAL_USE_HWFLOWCTRL == TRUE
.rts_pad = UART_RTS,
.cts_pad = UART_CTS,
#endif
};
static THD_WORKING_AREA(waLEDThread, 64);
static THD_FUNCTION(LEDThread, arg) {
(void)arg;
chRegSetThreadName("blinker");
palSetPadMode(IOPORT1, LED1, PAL_MODE_OUTPUT_PUSHPULL);
while (1) {
palTogglePad(IOPORT1, LED1);
chThdSleepMilliseconds(500);
}
}
static nrf52_config_t radiocfg = {
.protocol = NRF52_PROTOCOL_ESB_DPL,
.mode = NRF52_MODE_PRX,
.bitrate = NRF52_BITRATE_1MBPS,
.crc = NRF52_CRC_8BIT,
.tx_power = NRF52_TX_POWER_0DBM,
.tx_mode = NRF52_TXMODE_MANUAL_START,
.selective_auto_ack = false,
.retransmit = { 1000, 3 },
.payload_length = 0,
.address = {
.base_addr_p0 = { 0xF3, 0xF3, 0xF3, 0x01 },
.base_addr_p1 = { 0x3F, 0x3F, 0x3F, 0x01 },
.pipe_prefixes = { 0xF3, 0x3F, },
.num_pipes = 2,
.addr_length = 5,
.rx_pipes = 1 << 0,
.rf_channel = 1,
},
};
static uint16_t cnt, fail_pkt, good_pkt;
static nrf52_payload_t tx_payload = {
.pipe = 1,
};
static nrf52_payload_t rx_payload;
static THD_WORKING_AREA(waRadioThread, 256);
static THD_FUNCTION(RadioThread, arg) {
(void)arg;
event_listener_t el;
chEvtRegisterMask(&RFD1.eventsrc, &el, EVENT_MASK(0));
chRegSetThreadName("radio");
while (1) {
chEvtWaitAny(EVENT_MASK(0));
eventflags_t flags = chEvtGetAndClearFlags(&el);
if (flags & NRF52_EVENT_TX_SUCCESS) {
radio_start_rx();
good_pkt++;
}
if (flags & NRF52_EVENT_TX_FAILED) {
radio_start_rx();
fail_pkt++;
}
if (flags & NRF52_EVENT_RX_RECEIVED) {
memset(rx_payload.data, 0, 32);
radio_read_rx_payload(&rx_payload);
}
}
}
/**@brief Function for application main entry.
*/
int main(void) {
halInit();
chSysInit();
sdStart(&SD1, &serial_config);
chThdCreateStatic(waLEDThread, sizeof(waLEDThread), NORMALPRIO, LEDThread, NULL);
chThdCreateStatic(waRadioThread, sizeof(waRadioThread), NORMALPRIO, RadioThread, NULL);
radio_init(&radiocfg);
radio_flush_tx();
radio_flush_rx();
radio_start_rx();
cnt = good_pkt = fail_pkt = 0;
while (true) {
memset(tx_payload.data, 0, 32);
sprintf((char*)tx_payload.data, "counter value=%d" , cnt++);
tx_payload.length = strlen((char *)tx_payload.data);
radio_stop_rx();
radio_write_payload(&tx_payload);
radio_start_tx();
chprintf((BaseSequentialStream *)&SD1, "packets: good=%d, fail=%d, sent=%s\r\n", good_pkt, fail_pkt, tx_payload.data);
chThdSleepMilliseconds(500);
if (strlen((char*) rx_payload.data)) {
chprintf((BaseSequentialStream *)&SD1, "rssi=%d, received=%s\r\n", rx_payload.rssi, rx_payload.data);
rx_payload.data[0] = 0;
}
}
}

View File

@ -0,0 +1,28 @@
/*
Copyright (C) 2015 Stephen Caudle
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef _MCUCONF_H_
#define _MCUCONF_H_
/*
* HAL driver system settings.
*/
#define NRF5_SERIAL_USE_UART0 TRUE
#define NRF5_ST_USE_RTC0 TRUE
#define NRF5_ST_USE_RTC1 FALSE
#define NRF5_ST_USE_TIMER0 FALSE
#endif /* _MCUCONF_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,256 @@
/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
* @brief Enhanced ShockBurst (ESB) is a basic protocol supporting two-way data
* packet communication including packet buffering, packet acknowledgment
* and automatic retransmission of lost packets.
*
* ported on: 25/10/2018, by andru
*
*/
#ifndef NRF52_RADIO_H_
#define NRF52_RADIO_H_
// Hard coded parameters - change if necessary
#ifndef NRF52_MAX_PAYLOAD_LENGTH
#define NRF52_MAX_PAYLOAD_LENGTH 32 /**< The max size of the payload. Valid values are 1 to 252 */
#endif
#define NRF52_CRC_RESET_VALUE 0xFFFF /**< CRC reset value*/
#define NRF52_TX_FIFO_SIZE 8 /**< The size of the transmission first in first out buffer. */
#define NRF52_RX_FIFO_SIZE 8 /**< The size of the reception first in first out buffer. */
#define NRF52_RADIO_USE_TIMER0 FALSE /**< TIMER0 will be used by the module. */
#define NRF52_RADIO_USE_TIMER1 TRUE /**< TIMER1 will be used by the module. */
#define NRF52_RADIO_USE_TIMER2 FALSE /**< TIMER2 will be used by the module. */
#define NRF52_RADIO_USE_TIMER3 FALSE /**< TIMER3 will be used by the module. */
#define NRF52_RADIO_USE_TIMER4 FALSE /**< TIMER4 will be used by the module. */
#define NRF52_RADIO_IRQ_PRIORITY 3 /**< RADIO interrupt priority. */
#define NRF52_RADIO_INTTHD_PRIORITY (NORMALPRIO+2) /**< Interrupts handle thread priority. */
#define NRF52_RADIO_EVTTHD_PRIORITY (NORMALPRIO+1) /**< Events handle thread priority */
#define NRF52_RADIO_PPI_TIMER_START 10 /**< The PPI channel used for timer start. */
#define NRF52_RADIO_PPI_TIMER_STOP 11 /**< The PPI channel used for timer stop. */
#define NRF52_RADIO_PPI_RX_TIMEOUT 12 /**< The PPI channel used for RX timeout. */
#define NRF52_RADIO_PPI_TX_START 13 /**< The PPI channel used for starting TX. */
typedef enum {
NRF52_SUCCESS, /* Call was successful. */
NRF52_INVALID_STATE, /* Module is not initialized. */
NRF52_ERROR_BUSY, /* Module was not in idle state. */
NRF52_ERROR_NULL, /* Required parameter was NULL. */
NRF52_ERROR_INVALID_PARAM, /* Required parameter is invalid */
NRF52_ERROR_NOT_SUPPORTED, /* p_payload->noack was false while selective ack was not enabled. */
NRF52_ERROR_INVALID_LENGTH, /* Payload length was invalid (zero or larger than max allowed). */
} nrf52_error_t;
// Internal radio module state.
typedef enum {
NRF52_STATE_UNINIT, /**< Module not initialized. */
NRF52_STATE_IDLE, /**< Module idle. */
NRF52_STATE_PTX_TX, /**< Module transmitting without ack. */
NRF52_STATE_PTX_TX_ACK, /**< Module transmitting with ack. */
NRF52_STATE_PTX_RX_ACK, /**< Module transmitting with ack and reception of payload with the ack response. */
NRF52_STATE_PRX, /**< Module receiving packets without ack. */
NRF52_STATE_PRX_SEND_ACK, /**< Module transmitting ack in RX mode. */
} nrf52_state_t;
/**@brief Events to indicate the last transmission/receiving status. */
typedef enum {
NRF52_EVENT_TX_SUCCESS = 0x01, /**< Event triggered on TX success. */
NRF52_EVENT_TX_FAILED = 0x02, /**< Event triggered on TX failed. */
NRF52_EVENT_RX_RECEIVED = 0x04, /**< Event triggered on RX Received. */
} nrf52_event_t;
// Interrupt flags
typedef enum {
NRF52_INT_TX_SUCCESS_MSK = 0x01, /**< The flag used to indicate a success since last event. */
NRF52_INT_TX_FAILED_MSK = 0x02, /**< The flag used to indicate a failiure since last event. */
NRF52_INT_RX_DR_MSK = 0x04, /**< The flag used to indicate a received packet since last event. */
} nrf52_int_flags_t;
/**Macro to create initializer for a TX data packet.
*
* @details This macro generates an initializer. It is more efficient
* than setting the individual parameters dynamically.
*
* @param[in] _pipe The pipe to use for the data packet.
* @param[in] ... Comma separated list of character data to put in the TX buffer.
* Supported values are from 1 to 63 characters.
*
* @return Initializer that sets up pipe, length and the byte array for content of the TX data.
*/
#define NRF52_CREATE_PAYLOAD(_pipe, ...) \
{.pipe = _pipe, .length = NUM_VA_ARGS(__VA_ARGS__), .data = {__VA_ARGS__}}; \
STATIC_ASSERT(NUM_VA_ARGS(__VA_ARGS__) > 0 && NUM_VA_ARGS(__VA_ARGS__) <= 63)
/**@brief Enhanced ShockBurst protocol. */
typedef enum {
NRF52_PROTOCOL_ESB, /*< Enhanced ShockBurst with fixed payload length. */
NRF52_PROTOCOL_ESB_DPL /*< Enhanced ShockBurst with dynamic payload length. */
} nrf52_protocol_t;
/**@brief Enhanced ShockBurst mode. */
typedef enum {
NRF52_MODE_PTX, /*< Primary transmitter mode. */
NRF52_MODE_PRX /*< Primary receiver mode. */
} nrf52_mode_t;
/**@brief Enhanced ShockBurst bitrate mode. */
typedef enum {
NRF52_BITRATE_2MBPS = RADIO_MODE_MODE_Nrf_2Mbit, /**< 2Mbit radio mode. */
NRF52_BITRATE_1MBPS = RADIO_MODE_MODE_Nrf_1Mbit, /**< 1Mbit radio mode. */
} nrf52_bitrate_t;
/**@brief Enhanced ShockBurst CRC modes. */
typedef enum {
NRF52_CRC_16BIT = RADIO_CRCCNF_LEN_Two, /**< Use two byte CRC. */
NRF52_CRC_8BIT = RADIO_CRCCNF_LEN_One, /**< Use one byte CRC. */
NRF52_CRC_OFF = RADIO_CRCCNF_LEN_Disabled /**< Disable CRC. */
} nrf52_crc_t;
/**@brief Enhanced ShockBurst radio transmission power modes. */
typedef enum {
NRF52_TX_POWER_4DBM = RADIO_TXPOWER_TXPOWER_Pos4dBm, /**< 4 dBm radio transmit power. */
NRF52_TX_POWER_0DBM = RADIO_TXPOWER_TXPOWER_0dBm, /**< 0 dBm radio transmit power. */
NRF52_TX_POWER_NEG4DBM = RADIO_TXPOWER_TXPOWER_Neg4dBm, /**< -4 dBm radio transmit power. */
NRF52_TX_POWER_NEG8DBM = RADIO_TXPOWER_TXPOWER_Neg8dBm, /**< -8 dBm radio transmit power. */
NRF52_TX_POWER_NEG12DBM = RADIO_TXPOWER_TXPOWER_Neg12dBm, /**< -12 dBm radio transmit power. */
NRF52_TX_POWER_NEG16DBM = RADIO_TXPOWER_TXPOWER_Neg16dBm, /**< -16 dBm radio transmit power. */
NRF52_TX_POWER_NEG20DBM = RADIO_TXPOWER_TXPOWER_Neg20dBm, /**< -20 dBm radio transmit power. */
NRF52_TX_POWER_NEG30DBM = RADIO_TXPOWER_TXPOWER_Neg30dBm /**< -30 dBm radio transmit power. */
} nrf52_tx_power_t;
/**@brief Enhanced ShockBurst transmission modes. */
typedef enum {
NRF52_TXMODE_AUTO, /*< Automatic TX mode - When the TX fifo is non-empty and the radio is idle packets will be sent automatically. */
NRF52_TXMODE_MANUAL, /*< Manual TX mode - Packets will not be sent until radio_start_tx() is called. Can be used to ensure consistent packet timing. */
NRF52_TXMODE_MANUAL_START /*< Manual start TX mode - Packets will not be sent until radio_start_tx() is called, but transmission will continue automatically until the TX fifo is empty. */
} nrf52_tx_mode_t;
/**@brief Enhanced ShockBurst addresses.
*
* @details The module is able to transmit packets with the TX address stored in tx_address.
The module can also receive packets from peers with up to eight different tx_addresses
stored in esb_addr_p0 - esb_addr_p7. esb_addr_p0 can have 5 arbitrary bytes
independent of the other addresses. esb_addr_p1 - esb_addr_p7 will share the
same four byte base address found in the last four bytes of esb_addr_p1.
They have an independent prefix byte found in esb_addr_p1[0] and esb_addr_p2 -
esb_addr_p7.
*/
typedef struct {
uint8_t base_addr_p0[4]; /**< Base address for pipe 0 encoded in big endian. */
uint8_t base_addr_p1[4]; /**< Base address for pipe 1-7 encoded in big endian. */
uint8_t pipe_prefixes[8]; /**< Address prefix for pipe P0 to P7. */
uint8_t num_pipes; /**< Number of pipes available. */
uint8_t addr_length; /**< Length of address including prefix */
uint8_t rx_pipes; /**< Bitfield for enabled RX pipes. */
uint8_t rf_channel; /**< Which channel is to be used. Must be in range 0 and 125 to be valid. */
} nrf52_address_t;
/**@brief Enhanced ShockBurst payload.
*
* @note The payload is used both for transmission and receive with ack and payload.
*/
typedef struct
{
uint8_t length; /**< Length of the packet. Should be equal or less than NRF_ESB_MAX_PAYLOAD_LENGTH. */
uint8_t pipe; /**< Pipe used for this payload. */
int8_t rssi; /**< RSSI for received packet. */
uint8_t noack; /**< Flag indicating that this packet will not be acknowledged. */
uint8_t pid; /**< PID assigned during communication. */
uint8_t data[NRF52_MAX_PAYLOAD_LENGTH]; /**< The payload data. */
} nrf52_payload_t;
/**@brief Retransmit attempts delay and counter. */
typedef struct {
uint16_t delay; /**< The delay between each retransmission of unacked packets. */
uint16_t count; /**< The number of retransmissions attempts before transmission fail. */
} nrf52_retransmit_t;
/**@brief Main nrf_esb configuration struct. */
typedef struct {
nrf52_protocol_t protocol; /**< Enhanced ShockBurst protocol. */
nrf52_mode_t mode; /**< Enhanced ShockBurst default RX or TX mode. */
// General RF parameters
nrf52_bitrate_t bitrate; /**< Enhanced ShockBurst bitrate mode. */
nrf52_crc_t crc; /**< Enhanced ShockBurst CRC mode. */
nrf52_tx_power_t tx_power; /**< Enhanced ShockBurst radio transmission power mode.*/
// Control settings
nrf52_tx_mode_t tx_mode; /**< Enhanced ShockBurst transmit mode. */
bool selective_auto_ack; /**< Enable or disable selective auto acknowledgement. */
nrf52_retransmit_t retransmit; /**< Packet retransmit parameters */
uint8_t payload_length; /**< Enhanced ShockBurst static payload length */
nrf52_address_t address; /**< Address parameters structure */
} nrf52_config_t;
typedef struct {
/**
* @brief NRF52 radio peripheral.
*/
NRF_RADIO_Type *radio;
/**
* @brief NRF52 timer peripheral.
*/
NRF_TIMER_Type *timer;
/**
* @brief Driver state.
*/
nrf52_state_t state;
/**
* @brief RF parameters.
*/
nrf52_config_t config;
/**
* @brief Interrupts flag.
*/
nrf52_int_flags_t flags;
/**
* @brief TX attempt number.
*/
uint16_t tx_attempt;
/**
* @brief TX retransmits remaining.
*/
uint16_t tx_remaining;
/**
* @brief Radio events source.
*/
event_source_t eventsrc;
} RFDriver;
extern RFDriver RFD1;
nrf52_error_t radio_init(nrf52_config_t const *config);
nrf52_error_t radio_disable(void);
nrf52_error_t radio_write_payload(nrf52_payload_t const * p_payload);
nrf52_error_t radio_read_rx_payload(nrf52_payload_t * p_payload);
nrf52_error_t radio_start_tx(void);
nrf52_error_t radio_start_rx(void);
nrf52_error_t radio_stop_rx(void);
nrf52_error_t radio_flush_tx(void);
nrf52_error_t radio_flush_rx(void);
nrf52_error_t radio_pop_tx(void);
nrf52_error_t radio_set_base_address_0(uint8_t const * p_addr);
nrf52_error_t radio_set_base_address_1(uint8_t const * p_addr);
nrf52_error_t radio_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes);
nrf52_error_t radio_set_prefix(uint8_t pipe, uint8_t prefix);
#endif /* NRF52_RADIO_H_ */