I am developing and testing in nrf5_sdk_17.1.0_ddde560examplesble_peripheralble_app_hrs_freertos. My project requires both BLE and a proprietary radio protocol, but BLE and the radio are mutually exclusive. Only one of them runs at a given time. I discovered an issue: when I removed all BLE-related code from main.c, I found that if I also removed clock_init, the radio I wrote receives a lot of data, but if I don't remove clock_init, very little data is received. Tracing specifically whether the nrfx_power_clock_irq_init function executes affects my radio reception. Below I provide the relevant files, main.c and radioconfig.c. In radioconfig.c, I deleted the commercial code. How can I implement both BLE peripheral and proprietary radio functionality in this project, given that they are mutually exclusive?
/**
* Copyright (c) 2014 - 2021, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
// Board/nrf6310/ble/ble_app_hrs_rtx/main.c
/**
*
* @brief Heart Rate Service Sample Application with RTX main file.
*
* This file contains the source code for a sample application using RTX and the
* Heart Rate service (and also Battery and Device Information services).
* This application uses the @ref srvlib_conn_params module.
*/
#include <stdint.h>
#include <string.h>
#include "nordic_common.h"
#include "nrf.h"
#include "app_error.h"
#include "ble.h"
#include "ble_hci.h"
#include "ble_srv_common.h"
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_bas.h"
#include "ble_hrs.h"
#include "ble_dis.h"
#include "ble_conn_params.h"
#include "sensorsim.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_sdh_freertos.h"
#include "app_timer.h"
#include "peer_manager.h"
#include "peer_manager_handler.h"
#include "bsp_btn_ble.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
#include "fds.h"
#include "ble_conn_state.h"
#include "nrf_drv_clock.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "TaskRunConfig.h"
#if NRF_LOG_ENABLED
static TaskHandle_t m_logger_thread; /**< Definition of Logger thread. */
#endif
/**@brief Function for initializing the nrf log module.
*/
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(xTaskGetTickCount);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
#if NRF_LOG_ENABLED
/**@brief Thread for handling the logger.
*
* @details This thread is responsible for processing log entries if logs are deferred.
* Thread flushes all log entries and suspends. It is resumed by idle task hook.
*
* @param[in] arg Pointer used for passing some arbitrary information (context) from the
* osThreadCreate() call to the thread.
*/
static void logger_thread(void * arg)
{
UNUSED_PARAMETER(arg);
while (1)
{
NRF_LOG_FLUSH();
vTaskSuspend(NULL); // Suspend myself
}
}
#endif //NRF_LOG_ENABLED
#if NRF_LOG_ENABLED && NRF_LOG_DEFERRED
void log_pending_hook( void )
{
if (m_logger_thread != NULL)
{
if (__get_IPSR() != 0)
{
BaseType_t higherPriorityTaskWoken = pdFALSE;
xTaskResumeFromISR(m_logger_thread);
portYIELD_FROM_ISR(higherPriorityTaskWoken);
}
else
{
vTaskResume(m_logger_thread);
}
}
}
#endif
/**@brief Function for initializing the clock.
*/
static void clock_init(void)
{
ret_code_t err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);
}
void radio_init(void)
/**@brief Function for application main entry.
*/
int main(void)
{
bool erase_bonds;
// Initialize modules.
log_init();
clock_init();
// Do not start any interrupt that uses system functions before system initialisation.
// The best solution is to start the OS before any other initalisation.
#if NRF_LOG_ENABLED
// Start execution.
if (pdPASS != xTaskCreate(logger_thread, "LOGGER", 256, NULL, 1, &m_logger_thread))
{
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
#endif
// Activate deep sleep mode.
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
radio_init();
// Start FreeRTOS scheduler.
vTaskStartScheduler();
for (;;)
{
APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
}
}
#include <nrf.h>
#include "nrf_radio.h"
#include "string.h"
#include "nrf_gpio.h"
#include "RadioMsg.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "nrf_drv_rtc.h"
#include "stdlib.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "nrf_drv_clock.h"
#define ADV_ACCESS_ADDRESS 0x8E89BED6
bool SetBLE_Channel(uint8_t BLE_Channel);
void SetScanFlag(bool Val);
uint8_t BLE_MAC_Buffer[6] = {0};
static uint8_t tx_packet[258]; /**< Packet to transmit. */
static uint8_t rx_packet[258]; /**< Packet to receive. */
bool get_ble_mac_address(uint8_t *mac_addr);
const nrf_drv_rtc_t rtc2 = NRF_DRV_RTC_INSTANCE(2); /**< Declaring an instance of nrf_drv_rtc for RTC0. */
// �㲥 PDU
static uint8_t adv_pdu[] = {
0x02, 0x13, // ADV_IND, Payload Length=19 (AdvA 6 + Flags 3 + Name 10)
0xCA, 0xFE, 0xBA, 0xBE, 0x01, 0x02, // AdvA (random address)
0x02, 0x01, 0x06, // Flags: LE General Discoverable, BR/EDR Not Supported
0x09, 0x09, 'n', 'R', 'F', '5', '2', '8', '4', '0' // Name: nRF52840
};
bool tx_ready_flag = false; // ��������ѯ/�ȴ��ź���
volatile bool radio_tx_complete = false;
volatile bool radio_rx_complete = false;
volatile bool is_scanning = false;
volatile bool is_get_loc_adv = false;
volatile bool need_tx = false;
// Radio ���ݰ�����
nrf_radio_packet_conf_t packet_conf = {
.lflen = 8, /**< Length on air of LENGTH field in number of bits. */
.s0len = 1, /**< Length on air of S0 field in number of bytes. */
.s1len = 0, /**< Length on air of S1 field in number of bits. */
#if defined(RADIO_PCNF0_S1INCL_Msk) || defined(__NRFX_DOXYGEN__)
.s1incl = false, /**< Include or exclude S1 field in RAM. */
#endif
#if defined(RADIO_PCNF0_CILEN_Msk) || defined(__NRFX_DOXYGEN__)
.cilen = 0, /**< Length of code indicator - long range. */
#endif
#if defined(RADIO_PCNF0_PLEN_Msk) || defined(__NRFX_DOXYGEN__)
.plen = NRF_RADIO_PREAMBLE_LENGTH_8BIT, /**< Length of preamble on air. Decision point: TASKS_START task. */
#endif
#if defined(RADIO_PCNF0_CRCINC_Msk) || defined(__NRFX_DOXYGEN__)
.crcinc = false, /**< Indicates if LENGTH field contains CRC or not. */
#endif
#if defined(RADIO_PCNF0_TERMLEN_Msk) || defined(__NRFX_DOXYGEN__)
.termlen = 0, /**< Length of TERM field in Long Range operation. */
#endif
.maxlen = 255, /**< Maximum length of packet payload. */
.statlen = 0, /**< Static length in number of bytes. */
.balen = 3, /**< Base address length in number of bytes. */
.big_endian = false, /**< On air endianness of packet. */
.whiteen = true /**< Enable or disable packet whitening. */
};
// Radio ��ʼ��
void radio_init(void)
{
// ��� HFCLK (16 MHz �ⲿ����)
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
if (get_ble_mac_address(BLE_MAC_Buffer) == true) {
memcpy(&adv_pdu[2], BLE_MAC_Buffer, 6);
}
nrf_radio_mode_set(NRF_RADIO_MODE_BLE_1MBIT);
nrf_radio_txpower_set(NRF_RADIO_TXPOWER_POS8DBM);
nrf_radio_base0_set(ADV_ACCESS_ADDRESS << 8);
nrf_radio_prefix0_set((ADV_ACCESS_ADDRESS >> 24) & 0xFF);
nrf_radio_txaddress_set(0);
nrf_radio_rxaddresses_set(RADIO_RXADDRESSES_ADDR0_Enabled);
nrf_radio_crc_configure(RADIO_CRCCNF_LEN_Three, NRF_RADIO_CRC_ADDR_SKIP, 0x100065B);
nrf_radio_crcinit_set(0x555555);
nrf_radio_packet_configure(&packet_conf);
SetBLE_Channel(37);
nrf_radio_packetptr_set(rx_packet); // ���ý��ջ�����
// SHORTS:
// 1) READY��START (RX/TX ramp-up ���Զ���ʼ��/��)
// 2) END��DISABLE (һ�������Զ��ر�)
// 3) DISABLED��RXEN (�Զ����� RX ѭ��)
nrf_radio_shorts_enable(NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK
| NRF_RADIO_SHORT_READY_START_MASK
| NRF_RADIO_SHORT_END_DISABLE_MASK);
nrf_radio_int_enable(NRF_RADIO_INT_END_MASK | NRF_RADIO_INT_DISABLED_MASK);
NVIC_SetPriority(RADIO_IRQn, 4);//freertosĿǰ�������ȼ���2
NVIC_EnableIRQ(RADIO_IRQn);
SetScanFlag(true);
// �������
nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN);
}
bool SetBLE_Channel(uint8_t BLE_Channel)
{
uint16_t freq_mhz;
// ����ŵ�����Ƿ���Ч
if (BLE_Channel > 39) {
return false;
}
// �㲥�ŵ�����ӳ��
if (BLE_Channel == 37) {
freq_mhz = 2402; // �ŵ�37: 2426 MHz
} else if (BLE_Channel == 38) {
freq_mhz = 2426; // �ŵ�38: 2478 MHz
} else if (BLE_Channel == 39) {
freq_mhz = 2480; // �ŵ�39: 2480 MHz
} else {
if (BLE_Channel <=10 ) {
freq_mhz = 2404 + 2 * BLE_Channel;
} else if (BLE_Channel > 10 && BLE_Channel < 37) {
freq_mhz = 2406 + 2 * BLE_Channel;
}
}
nrf_radio_frequency_set(freq_mhz);
nrf_radio_datawhiteiv_set(BLE_Channel);
return true;
}
bool get_ble_mac_address(uint8_t *mac_addr)
{
if (mac_addr == NULL) {
return false;
}
#if 1
// ��FICR�Ĵ�����ȡ48λ�豸��ַ
uint32_t addr_low = NRF_FICR->DEVICEADDR[0]; // ��32λ
uint32_t addr_high = NRF_FICR->DEVICEADDR[1]; // ��16λ
// ��ϳ�48λMAC��ַ��6�ֽڣ�
mac_addr[0] = (uint8_t)(addr_low); // LSB
mac_addr[1] = (uint8_t)(addr_low >> 8);
mac_addr[2] = (uint8_t)(addr_low >> 16);
mac_addr[3] = (uint8_t)(addr_low >> 24);
mac_addr[4] = (uint8_t)(addr_high);
mac_addr[5] = (uint8_t)(addr_high >> 8); // MSB
// ����Ϊ�����̬��ַ�������λΪ11��
mac_addr[5] |= 0xC0; // ���������λΪ11
#endif
return true;
}
// �ŵ��������ַ������mac��
// �㲥����
bool SendLocRequestRadio(CurrentLocParaDef LocPara)
{
uint16_t freq_mhz;
uint32_t timeout = 100000;
uint8_t BLE_Channel;
uint8_t SendBuffer[50];
BLE_Channel = LocPara.OOB_RxChannel;
memset(SendBuffer, 0x00, sizeof(SendBuffer));
// ����ŵ�����Ƿ���Ч
if (BLE_Channel > 39) {
return false;
}
// �㲥�ŵ�����ӳ��
if (BLE_Channel == 37) {
freq_mhz = 2402; // �ŵ�37: 2426 MHz
} else if (BLE_Channel == 38) {
freq_mhz = 2426; // �ŵ�38: 2478 MHz
} else if (BLE_Channel == 39) {
freq_mhz = 2480; // �ŵ�39: 2480 MHz
} else {
if (BLE_Channel <=10 ) {
freq_mhz = 2404 + 2 * BLE_Channel;
} else if (BLE_Channel > 10 && BLE_Channel < 37) {
freq_mhz = 2406 + 2 * BLE_Channel;
}
}
// ȷ������ǰtx_packet����adv_pdu
memset(tx_packet, 0x00, sizeof(tx_packet));
memcpy(tx_packet, &SendBuffer, sizeof(SendBuffer));
//ʹ���·�ʱ϶�ڵ���Ϣ��
nrf_radio_base0_set(LocPara.OOB_Address << 8);
nrf_radio_prefix0_set((LocPara.OOB_Address >> 24) & 0xFF);
nrf_radio_frequency_set(freq_mhz);
nrf_radio_datawhiteiv_set(BLE_Channel);
nrf_radio_packetptr_set(tx_packet); // ���÷��ͻ�����
radio_tx_complete = false;
is_scanning = false;
// �����л� (TXEN �� READY �� START �� ����)
nrf_radio_task_trigger(NRF_RADIO_TASK_TXEN);
while (!radio_tx_complete && timeout--) {
__WFE();
}
if (timeout == 0) {
return false;
}
// �����ָ� RX ѭ��
memset(rx_packet, 0, sizeof(rx_packet));
//����DISABLED -> RXEN ��ݼ�
nrf_radio_packetptr_set(rx_packet);
SetBLE_Channel(37);
//���ý����ַ
nrf_radio_base0_set(ADV_ACCESS_ADDRESS << 8);
nrf_radio_prefix0_set((ADV_ACCESS_ADDRESS >> 24) & 0xFF);
is_scanning = true;
need_tx = false;
nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN);
return true;
}
void SetScanFlag(bool Val)
{
is_scanning = Val;
}
void ConfigModeDeInitRadioRx(void)
{
nrf_radio_event_clear(NRF_RADIO_EVENT_END);
nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED);
nrf_radio_shorts_disable(NRF_RADIO_SHORT_DISABLED_RXEN_MASK);
// �����뷢��ǰ�������¼�
nrf_radio_event_clear(NRF_RADIO_EVENT_DISABLED);
tx_ready_flag = false;
// ���� DISABLE
nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE);
// �ȴ� flag / �ź���
while (!tx_ready_flag) { __WFE(); }
}
// �жϴ���
void RADIO_IRQHandler(void)
{
uint32_t err_code;
if (NRF_RADIO->EVENTS_END) {
NRF_RADIO->EVENTS_END = 0;
if (is_scanning) {
if (NRF_RADIO->CRCSTATUS == 1) {
need_tx = false;
} else {
need_tx = false;
}
} else {
radio_tx_complete = true;
}
}
if (NRF_RADIO->EVENTS_DISABLED) {
NRF_RADIO->EVENTS_DISABLED = 0;
// NVIC_ClearPendingIRQ(RADIO_IRQn);
tx_ready_flag = true;
if (need_tx == false && is_scanning == true)
{
nrf_radio_task_trigger(NRF_RADIO_TASK_RXEN);
}
}
}