Hi, I'm delevoping an appilcation which can generate one sample per 20 us (accomplished with timer0) and transmit one ESB packet when 20 samples are collected. Below is the C code for my applciation (modified from esb_ptx example in nRF5 SDK 16.0):
/**
* Copyright (c) 2014 - 2019, 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.
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "sdk_common.h"
#include "nrf.h"
#include "nrf_error.h"
#include "app_util.h"
#include "app_error.h"
#include "nrf_esb.h"
#include "nrf_esb_error_codes.h"
#include "nrf_drv_ppi.h"
#include "nrf_drv_timer.h"
#include "nrf_drv_gpiote.h"
#include "boards.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
//// Pin definitions
#define PIN_CLKS 11 // Use P0.11 (Arduino D0 on nRF52 DK)
#define PIN_BUT1 BUTTON_1
#define PIN_SAMPEN LED_1
//// Parameters
#define CLKS_PERIOD 20 // Timer0 interval in microseconds
#define NUM_BYTE_SLAV_PKT_DATA 20
#define NUM_BYTE_SLAV_PKT_ID 2
#define NUM_TX_PKT 10
//// Global Variables
uint8_t saadc_count = 0;
uint16_t pid = 0;
uint16_t dummy=1;
//// Instance declarations
static nrf_esb_payload_t slav_tx_payload;
static nrf_esb_payload_t slav_rx_payload;
static const nrf_drv_timer_t m_timer0 = NRF_DRV_TIMER_INSTANCE(0);
static nrf_ppi_channel_t m_ppi_channel1;
static nrf_ppi_channel_t m_ppi_channel2;
static nrf_ppi_channel_t m_ppi_channel3;
static nrf_ppi_channel_t m_ppi_channel4;
//// Function declarations
void pin_but1_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
nrf_drv_gpiote_out_toggle(PIN_SAMPEN);
}
static void timer0_event_handler(nrf_timer_event_t event_type, void * p_context)
{
uint16_t pid_tmp;
uint32_t idx_pid;
switch (event_type)
{
case NRF_TIMER_EVENT_COMPARE0:
slav_tx_payload.data[NUM_BYTE_SLAV_PKT_ID+saadc_count] = dummy++;
if (saadc_count == NUM_BYTE_SLAV_PKT_DATA-1){
pid_tmp = pid;
for (idx_pid=0; idx_pid<NUM_BYTE_SLAV_PKT_ID; idx_pid++)
{
slav_tx_payload.data[NUM_BYTE_SLAV_PKT_ID-1-idx_pid] = (uint8_t) pid_tmp&0xFF;
pid_tmp = pid_tmp>>8;
}
saadc_count = 0;
pid++;
// Send packet
slav_tx_payload.noack = false;
nrf_esb_write_payload(&slav_tx_payload);
NRF_LOG_HEXDUMP_DEBUG(slav_tx_payload.data, NUM_BYTE_SLAV_PKT_ID+NUM_BYTE_SLAV_PKT_DATA);
}
else {
saadc_count++;
}
if (pid==NUM_TX_PKT) { // [Note] Timer0 cleared w/ NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK
NRF_LOG_INFO("Stop timer0");
nrf_drv_timer_disable(&m_timer0);
nrf_drv_gpiote_out_toggle(PIN_SAMPEN);
pid = 0;
dummy = 0;
}
default:
//Do nothing.
break;
}
}
void nrf_esb_event_handler(nrf_esb_evt_t const * p_event)
{
switch (p_event->evt_id)
{
// case NRF_ESB_EVENT_TX_SUCCESS:
// NRF_LOG_DEBUG("TX SUCCESS EVENT");
// break;
case NRF_ESB_EVENT_TX_FAILED:
NRF_LOG_DEBUG("TX FAILED EVENT");
(void) nrf_esb_flush_tx();
(void) nrf_esb_start_tx();
break;
case NRF_ESB_EVENT_RX_RECEIVED:
// NRF_LOG_DEBUG("RX RECEIVED EVENT");
while (nrf_esb_read_rx_payload(&slav_rx_payload) == NRF_SUCCESS)
{
if (slav_rx_payload.length > 0)
{
NRF_LOG_DEBUG("RX RECEIVED PAYLOAD");
}
}
break;
}
}
static void log_init(void)
{
ret_code_t err_code = NRF_LOG_INIT(NULL);
APP_ERROR_CHECK(err_code);
NRF_LOG_DEFAULT_BACKENDS_INIT();
}
void clocks_start( void )
{
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
}
static void gpio_init(void)
{
ret_code_t err_code;
err_code = nrf_drv_gpiote_init();
APP_ERROR_CHECK(err_code);
// PIN_CLKS setting
nrf_drv_gpiote_out_config_t pin_clks_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); // init_high=false
err_code = nrf_drv_gpiote_out_init(PIN_CLKS, &pin_clks_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(PIN_CLKS);
// PIN_BUT1 setting
nrf_drv_gpiote_in_config_t pin_but1_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false); // hi_accu=false (no use IN_EVENT)
pin_but1_config.pull = NRF_GPIO_PIN_PULLUP;
err_code = nrf_drv_gpiote_in_init(PIN_BUT1, &pin_but1_config, pin_but1_handler); // IN_EVENT = pin_but1_handler
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_in_event_enable(PIN_BUT1, true);
// PIN_SAMPEN setting
nrf_drv_gpiote_out_config_t pin_sampen_config = GPIOTE_CONFIG_OUT_SIMPLE(true); // configuring PIN_SAMPEN as output, where GPIOTE is not used; init_high=true
// nrf_drv_gpiote_out_config_t pin_sampen_config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true); // init_high=true
err_code = nrf_drv_gpiote_out_init(PIN_SAMPEN, &pin_sampen_config);
APP_ERROR_CHECK(err_code);
nrf_drv_gpiote_out_task_enable(PIN_SAMPEN);
}
static void timer0_init(void)
{
// Check TIMER0 configuration for details.
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
timer_cfg.frequency = NRF_TIMER_FREQ_1MHz;
timer_cfg.mode = NRF_TIMER_MODE_TIMER;
timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
ret_code_t err_code = nrf_drv_timer_init(&m_timer0, &timer_cfg, timer0_event_handler);
APP_ERROR_CHECK(err_code);
nrf_drv_timer_extended_compare(&m_timer0,
NRF_TIMER_CC_CHANNEL0,
nrf_drv_timer_us_to_ticks(&m_timer0, CLKS_PERIOD),
NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
true); // enable_int = true
nrf_drv_timer_compare (&m_timer0,
NRF_TIMER_CC_CHANNEL1,
nrf_drv_timer_us_to_ticks(&m_timer0, CLKS_PERIOD>>1),
false); // enable_int = false
}
static void ppi_init(void)
{
uint32_t err_code = NRF_SUCCESS;
err_code = nrf_drv_ppi_init();
APP_ERROR_CHECK(err_code);
/* Configure & enable available PPI channel to start TIMER0 on SENSE_HITOLO of PIN_BUT1 */
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,
nrf_drv_gpiote_in_event_addr_get(PIN_BUT1),
nrf_drv_timer_task_address_get(&m_timer0, NRF_TIMER_TASK_START) );
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
APP_ERROR_CHECK(err_code);
/* Configure & enable available PPI channel to set PIN_CLKS to high on TIMER0 COMPARE[1] match */
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel2);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel2,
nrf_drv_timer_event_address_get(&m_timer0, NRF_TIMER_EVENT_COMPARE1),
nrf_drv_gpiote_set_task_addr_get(PIN_CLKS) );
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel2);
APP_ERROR_CHECK(err_code);
/* Configure & enable available PPI channel to set PIN_CLKS to low on TIMER0 COMPARE[0] match */
err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel3);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(m_ppi_channel3,
nrf_drv_timer_event_address_get(&m_timer0, NRF_TIMER_EVENT_COMPARE0),
nrf_drv_gpiote_clr_task_addr_get(PIN_CLKS) );
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(m_ppi_channel3);
APP_ERROR_CHECK(err_code);
// /* Configure & enable 4th available PPI channel to set PIN_SAMPEN to low on SENSE_HITOLO of PIN_BUT1 */
// err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel4);
// APP_ERROR_CHECK(err_code);
// err_code = nrf_drv_ppi_channel_assign(m_ppi_channel4,
// nrf_drv_gpiote_in_event_addr_get(PIN_BUT1),
// nrf_drv_gpiote_clr_task_addr_get(PIN_SAMPEN) );
// APP_ERROR_CHECK(err_code);
// err_code = nrf_drv_ppi_channel_enable(m_ppi_channel4);
// APP_ERROR_CHECK(err_code);
}
uint32_t esb_init( void )
{
uint32_t err_code;
uint8_t base_addr_0[4] = {0xE7, 0xE7, 0xE7, 0xE7};
uint8_t base_addr_1[4] = {0xC2, 0xC2, 0xC2, 0xC2};
uint8_t addr_prefix[8] = {0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 };
nrf_esb_config_t nrf_esb_config = NRF_ESB_DEFAULT_CONFIG;
nrf_esb_config.protocol = NRF_ESB_PROTOCOL_ESB_DPL;
nrf_esb_config.retransmit_delay = 600;
nrf_esb_config.bitrate = NRF_ESB_BITRATE_2MBPS;
nrf_esb_config.event_handler = nrf_esb_event_handler;
nrf_esb_config.mode = NRF_ESB_MODE_PTX;
nrf_esb_config.selective_auto_ack = false;
err_code = nrf_esb_init(&nrf_esb_config);
VERIFY_SUCCESS(err_code);
err_code = nrf_esb_set_base_address_0(base_addr_0);
VERIFY_SUCCESS(err_code);
err_code = nrf_esb_set_base_address_1(base_addr_1);
VERIFY_SUCCESS(err_code);
err_code = nrf_esb_set_prefixes(addr_prefix, NRF_ESB_PIPE_COUNT);
VERIFY_SUCCESS(err_code);
return err_code;
}
int main(void)
{
ret_code_t err_code;
log_init();
clocks_start();
gpio_init();
timer0_init();
ppi_init();
err_code = esb_init();
APP_ERROR_CHECK(err_code);
// TX payload init
slav_tx_payload.pipe = 0;
slav_tx_payload.length = NUM_BYTE_SLAV_PKT_ID + NUM_BYTE_SLAV_PKT_DATA;
NRF_LOG_INFO("ANC raw data transmitter started.");
while (true)
{
__WFE();
}
}
Here're my questions:
1. Why a question mark appears at the breakpoint inserted at the beginning of the following for-loop below?

2. It seems the program didn't perform the loop operation as expected (i.e., only perform 1 tiem loop rather than that specified by NUM_BYTE_SLAV_PKT_ID). Why?
for (idx_pid=0; idx_pid<NUM_BYTE_SLAV_PKT_ID; idx_pid++)
{
slav_tx_payload.data[NUM_BYTE_SLAV_PKT_ID-1-idx_pid] = (uint8_t) pid_tmp&0xFF;
pid_tmp = pid_tmp>>8;
}
Thank you in advance for your help.
Best regards,
Johnson



