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