xSemaphoreTake() . Program gets stuck . need help debugging

asantos wrote on Wednesday, February 06, 2019:

Hi,

I am using the nordic NRF52832 on a custom board.
My program implements a binary semaphore, which is given in the RTC interrupt handler.
My send_data task (this is the only task) waits for this semaphore in the beginning of the loop.

I have been trying to debug it but I have not found the problem.
The portYIELD_WITHIN_API(); line inside xQueueSemaphoreTake() is reached and then my program seems to hang. The code inside void vApplicationIdleHook( void ) is not run though, which should be the code run after the context switch.

I attach the part of the code relative to this issue. Please let me know how to debug this.

Thanks

Code in main.c

void vApplicationIdleHook( void )
{
    while(1)
    {   
        NRF_LOG_DEBUG("Idle task");
        delay_ms(1000);
     }
 /* Create task for send_data blinking with priority set to 2 */
    UNUSED_VARIABLE(xTaskCreate(send_data, "send_data", configMINIMAL_STACK_SIZE + 200, NULL, 2, &send_data_handle));

Code in task.c

// RTC timer
APP_TIMER_DEF(m_led_a_timer_id);
/**
 * @brief RTC instance number 
 *
 */
#define PERIODIC_RTC 2

/**
 * @brief RTC compare channel used
 *
 */
#define PERIODIC_RTC_CC 0
/**
 * @brief Number of RTC ticks between interrupts
 */
#define PERIODIC_TIMER_US   5000000ULL
#define PERIODIC_RTC_TICKS   (RTC_US_TO_TICKS(PERIODIC_TIMER_US, RTC_DEFAULT_CONFIG_FREQUENCY))
/**
 * @brief Semaphore set in RTC event
 */
static SemaphoreHandle_t send_data_semaphore = NULL;
/**
 * @brief RTC configuration
 */
static nrf_drv_rtc_config_t const m_rtc_config = NRF_DRV_RTC_DEFAULT_CONFIG;
/**
 * @brief RTC instance
 *
 * Instance of the RTC used for led blinking
 */
static nrf_drv_rtc_t const m_rtc = NRF_DRV_RTC_INSTANCE(PERIODIC_RTC);

static void periodic_rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    	NRF_LOG_DEBUG("Send data RTC handler");
    BaseType_t yield_req = pdFALSE;
	BaseType_t ret_val;
    ret_code_t err_code;
    err_code = nrf_drv_rtc_cc_set(
        &m_rtc,
        PERIODIC_RTC_CC,
        (nrf_rtc_cc_get(m_rtc.p_reg, PERIODIC_RTC_CC) + PERIODIC_RTC_TICKS) & RTC_COUNTER_COUNTER_Msk,
        true);
    APP_ERROR_CHECK(err_code);

   /* The returned value may be safely ignored, if error is returned it only means that
    * the semaphore is already given (raised). */
   UNUSED_VARIABLE(xSemaphoreGiveFromISR(send_data_semaphore, &yield_req));
   // Request a context switch (switch to other task). Interrupt safe verison of taskYIELD()
   portYIELD_FROM_ISR(yield_req);
}
/**
 * @brief send_data task entry function.
 *
 * @param[in] pvParameter   Pointer that will be used as the parameter for the task.
 */
void send_data(void * pvParameter)
{	
	NRF_LOG_INFO("---------- SEND DATA TASK ----------");
	
	// Create rtc instance and compare channel
	NRF_LOG_DEBUG("Init RTC");
	ret_code_t err_code;
    err_code = nrf_drv_rtc_init(&m_rtc, &m_rtc_config, periodic_rtc_handler);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_rtc_cc_set(&m_rtc, PERIODIC_RTC_CC, PERIODIC_RTC_TICKS, true);
    APP_ERROR_CHECK(err_code);
	// Enable RTC instance
	nrf_drv_rtc_enable(&m_rtc);

	// Create semaphore
	
	send_data_semaphore = xSemaphoreCreateBinary();
	UNUSED_PARAMETER(pvParameter);
	// Begin task loop
	while(1)
	{	
			NRF_LOG_DEBUG("Waiting for semaphore to begin task");
		UNUSED_VARIABLE(xSemaphoreTake(send_data_semaphore, portMAX_DELAY));
			NRF_LOG_INFO("++++++++++++++++task begin++++++++++++++++\r\n");

richarddamon wrote on Wednesday, February 06, 2019:

Idle task, and thus Idle hook MUST NOT BLOCK, as there must always be a task ready to run.

Your vApplicationIdleHook() is broken.

asantos wrote on Thursday, February 07, 2019:

Hi,
Thanks for your support
I have changed my idle task hook to this, but I still have an issue

void vApplicationIdleHook( void )
{
    while(1)
    {   
        NRF_LOG_DEBUG("Idle task");
     }
 }

asantos wrote on Thursday, February 07, 2019:

Hi,
Thanks for your support
I have changed my idle task hook to this, but I still have an issue

void vApplicationIdleHook( void )
{
    while(1)
    {   
        NRF_LOG_DEBUG("Idle task");
     }
 }

asantos wrote on Thursday, February 07, 2019:

Hi Richard,

I have already fixed it. It turns out that my task usStackDepth was too small.

Thanks for everything

richarddamon wrote on Thursday, February 07, 2019:

Just as a comment, I would not put an infinte loop like you have in the idle hook, as that says that the rest of the Idle task won’t run, so if any task deletes itself, its resources won’t be cleared up.

Also, I would be careful that NRF_LOG_DEBUG doesn’t block (it likely doesn’t, but just spin-waits for the debug port to be ready, but should be checked).