softdevice+freertos+radio

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);
        }
    }
}

Parents Reply
  • "Also, I want to know if my approach is correct. I want my program, based on FreeRTOS, to have two functions: one is BLE scanning and advertising, and the other is Radio transmission and reception. These two functions are mutually exclusive. Is this feasible? How should I modify the code based on nrf5_sdk_17.1.0_ddde560\examples\ble_peripheral\ble_app_hrs_freertos? And what issues should I be aware of?"

Children
No Data
Related