This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

FDS, UART, BLE can not work together

Hello all,

I am using the example \ examples \ ble_peripheral \ ble_app_uart
Right now I'm having a problem that I cannot use FDS. My fds_event_handler I never see case "FDS_EVT_WRITE".

It my function main()

int main(void)
{
    ret_code_t err_code;
    bool erase_bonds;
    uart_init();
    log_init();  
    CLOCK_INIT();
    timers_init();
    
    GPIO_INIT();
    SPI_INIT();
    printf("fdsT_find_record New Record\r\n");
    ret_code_t ret = fdsT_find_record();
    if(ret == FDS_ERR_NOT_FOUND)		// No record, so create a new one		
    {
            NRF_LOG_INFO("Creating New Record\r\n");
            // Create a new record
            ret = fdsT_write();	
            if (ret != FDS_SUCCESS)
            {
               NRF_LOG_INFO("Write fail!\r\n");
            }				
    }
    else
    {
            fdsT_read();
            //NRF_LOG_INFO("Variable 5: %d\r\n", saveData2.var5);	
    }
    NRF_LOG_INFO("\r\nDelete Previous Record:\r\n");
    fdsT_find_and_delete();
    
    NRF_LOG_INFO("Writing New Record:\r\n");
    ret = fdsT_write();	
    
    NRF_LOG_INFO("\r\nReading New Record:\r\n");
    printf("\r\nReading New Record:\r\n");
    fdsT_read();	
    NRF_LOG_INFO("Program Start!\r\n");

    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init(); 
    gap_params_init();
    gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
    peer_manager_init();
 
//    nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
//    spi_config.ss_pin   = SPI_SS_PIN;
//    spi_config.miso_pin = SPI_MISO_PIN;
//    spi_config.mosi_pin = SPI_MOSI_PIN;
//    spi_config.sck_pin  = SPI_SCK_PIN;
//    APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));

//    if (pdPASS != xTaskCreate(spi_thread, "SPI", TASK_STACK, NULL, 1, &m_spi_thread))
//    {
//      APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
//    }
    
    if (pdPASS != xTaskCreate(shiftregisterTaskmain, "shiftregisterTaskmain", TASK_STACK, NULL, 5, &m_shiftregister))
    {
      APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
    }
    
    if (pdPASS != xTaskCreate(bzctrTtaskmain, "bz_ctrl_taskmain", TASK_STACK, NULL, 4, &m_bzctrlTask))
    {
      APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
    }
    if (pdPASS != xTaskCreate(sendinformationTaskmain, "sendinformation_taskmain", TASK_STACK, NULL, 3, &m_sendinformation))
    {
      APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
    }
    if (pdPASS != xTaskCreate(ledctrlTaskstart, "ledctrlTaskstart", TASK_STACK, NULL, 2, &m_ledctrltaskstart))
    {
      APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
    }
    if(pdPASS != xTaskCreate(usermainloop, "MAIN", TASK_STACK, NULL, 1, &m_usermainloop)) {
      APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
    }

    // Activate deep sleep mode.
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    while(1){

      nrf_delay_ms(10000);
    }

    printf("SPI example starter\r\n");

    // Start execution.
    printf("\r\nUART started.\r\n");
    NRF_LOG_INFO("Debug logging for UART over RTT started.");
    nrf_delay_ms(1000);
    erase_bonds = true;
    nrf_sdh_freertos_init(advertising_start, &erase_bonds);
    vTaskStartScheduler();
    
    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
        APP_ERROR_HANDLER(NRF_ERROR_FORBIDDEN);
    }
}

It function fds test write flash

/////////////////////////TEST//////////////////////
static float					var1[7] = {5.00, 5.10, 5.20, 5.30, 5.40, 5.50, 5.60};
static float					var2 = 10.00;				
static float					var3 = 5.00;
static uint8_t					var4[7] = {17,07,06,05,04,03,02};
static uint8_t					var5 = 99;

struct
{
    float     	var1[7];
    float     	var2;
    float       var3;
    uint8_t     var4[7];
    uint8_t	var5;
} saveData;

struct
{
    float     	var1[7];
    float     	var2;
    float	var3;
    uint8_t     var4[7];
    uint8_t	var5;
} saveData2;

static uint16_t fileID = 0x1000;
static uint16_t recordKey = 0x2000;
static fds_record_t        record;
static fds_record_desc_t   record_desc;
static fds_flash_record_t  flash_record;
static fds_find_token_t    ftok;
ret_code_t fdsT_write(void)
{
      saveData2.var5 = 0;
	
      uint8_t x = 0;
      for(x = 0; x<7; x++)
      {
          saveData.var1[x] = var1[x];
          saveData.var4[x] = var4[x];
      }
      saveData.var2 = var2;
      saveData.var3 = var3;
      saveData.var5 = var5;

      record.data.p_data         = &saveData;
      record.data.length_words   = sizeof(saveData)/4;
      record.file_id             = fileID;
      record.key                 = recordKey;
      NRF_LOG_INFO("fds_record_write:\r\n");
      ret_code_t ret = fds_record_write(&record_desc, &record);
      if (ret != FDS_SUCCESS)
      {
         return ret;
      }
      NRF_LOG_INFO("1111111:\r\n");
      uint32_t evt_id;
      while (write_flag==0){
        sd_evt_get(&evt_id);
        //printf("fds_record_write evt_id: %d\r\n",evt_id);
      }
      
      NRF_LOG_INFO("Writing Record ID = %d \r\n",record_desc.record_id);
      return NRF_SUCCESS;
}

ret_code_t fdsT_update(void)
{
      record.data.p_data         = &saveData;
      record.data.length_words   = sizeof(saveData)/4;
      record.file_id             = fileID;
      record.key                 = recordKey;

      ret_code_t ret = fds_record_update(&record_desc, &record);
      if (ret != FDS_SUCCESS)
      {
         return ret;
      }
                      
      NRF_LOG_INFO("Updating Record ID = %d \r\n",record_desc.record_id);
      return NRF_SUCCESS;
}

ret_code_t fdsT_read(void)
{
        fds_find_token_t    ftok ={0};//Important, make sure you zero init the ftok token
        
        uint8_t *data;
        uint32_t err_code;
        
        NRF_LOG_INFO("Start Reading... \r\n");
        printf("Start Reading... \r\n");
        // Loop until all records with the given key and file ID have been found.
        while (fds_record_find(fileID, recordKey, &record_desc, &ftok) == FDS_SUCCESS)
        {
              err_code = fds_record_open(&record_desc, &flash_record);
              if ( err_code != FDS_SUCCESS)
              {
                      return err_code;		
              }
              
              NRF_LOG_INFO("Found Record ID = %d\r\n",record_desc.record_id);
              data = (uint8_t *) flash_record.p_data;		
              memcpy(saveData2.var1,data,28);
              memcpy(&saveData2.var2,data+28,4);
              memcpy(&saveData2.var3,data+32,4);
              memcpy(saveData2.var4,data+36,7);
              memcpy(&saveData2.var5,data+43,1);
                                                                      
              // Access the record through the flash_record structure.
              // Close the record when done.
              err_code = fds_record_close(&record_desc);
              if (err_code != FDS_SUCCESS)
              {
                      return err_code;	
              }
        }

        printf("Variable 5: %d\r\n", saveData2.var5);	
        return NRF_SUCCESS;	
}

ret_code_t fdsT_find_and_delete (void)
{
      fds_find_token_t    ftok;
      ftok.page=0;
      ftok.p_addr=NULL;
      // Loop and find records with same ID and rec key and mark them as deleted. 
      while (fds_record_find(fileID, recordKey, &record_desc, &ftok) == FDS_SUCCESS)
      {
              fds_record_delete(&record_desc);
              NRF_LOG_INFO("Deleted record ID: %d \r\n",record_desc.record_id);
      }
      // call the garbage collector to empty them, don't need to do this all the time, this is just for demonstration
      ret_code_t ret = fds_gc();
      if (ret != FDS_SUCCESS)
      {
              return ret;
      }
      return NRF_SUCCESS;
}

ret_code_t fdsT_find_record (void)
{
    fds_find_token_t    ftok;
    bool recordFound = false;
    ftok.page=0;
    ftok.p_addr=NULL;
    // Loop and find records with same ID and rec key
    while (fds_record_find(fileID, recordKey, &record_desc, &ftok) == FDS_SUCCESS)
    {
            NRF_LOG_INFO("Found Record : ID %d \r\n",record_desc.record_id);
            recordFound = true;
    }
    if(!recordFound)
    {
            NRF_LOG_INFO("No Record Found!\r\n");
            return FDS_ERR_NOT_FOUND;
    }
    // call the garbage collector to empty them, don't need to do this all the time, this is just for demonstration
    
    return NRF_SUCCESS;
}
#endif // NRF_MODULE_ENABLED(PEER_MANAGER)

Do you have any suggestions for me, thanks

Parents
  • Hi Terji

    --> I see that in the fdsT_write() function you fetch SoftDevice events until write_flag is set to a non-zero value ?

    it function fs_event_hander(), write_flag = 1 when p_fds_evt->id = FDS_EVT_WRITE and p_fds_evt->result == FDS_SUCCESS

    static volatile uint8_t write_flag = 0;
    static void fds_evt_handler(fds_evt_t const * const p_fds_evt)
    {
        pm_evt_t pds_evt =
        {
            .peer_id = file_id_to_peer_id(p_fds_evt->write.file_id)
        };
        printf("p_fds_evt->id %d!\r\n",p_fds_evt->id);
        switch (p_fds_evt->id)
        {
            case FDS_EVT_WRITE:
                if (p_fds_evt->result == FDS_SUCCESS)
                {
                    write_flag = 1;
                }
            case FDS_EVT_UPDATE:
            case FDS_EVT_DEL_RECORD:
                if (   file_id_within_pm_range(p_fds_evt->write.file_id)
                    || record_key_within_pm_range(p_fds_evt->write.record_key))
                {
                    pds_evt.params.peer_data_update_succeeded.data_id
                                    = record_key_to_peer_data_id(p_fds_evt->write.record_key);
                    pds_evt.params.peer_data_update_succeeded.action
                                    = (p_fds_evt->id == FDS_EVT_DEL_RECORD) ? PM_PEER_DATA_OP_DELETE
                                                                            : PM_PEER_DATA_OP_UPDATE;
                    pds_evt.params.peer_data_update_succeeded.token = p_fds_evt->write.record_id;
    
                    if (p_fds_evt->result == FDS_SUCCESS)
                    {
                        pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_SUCCEEDED;
                        pds_evt.params.peer_data_update_succeeded.flash_changed = true;
                    }
                    else
                    {
                        pds_evt.evt_id = PM_EVT_PEER_DATA_UPDATE_FAILED;
                        pds_evt.params.peer_data_update_failed.error     = p_fds_evt->result;
                        pds_evt.params.peer_data_update_failed.fds_error = true;
                    }
    
                    pds_evt_send(&pds_evt);
                }
                break;
    
            case FDS_EVT_DEL_FILE:
                if (    file_id_within_pm_range(p_fds_evt->del.file_id)
                    && (p_fds_evt->del.record_key == FDS_RECORD_KEY_DIRTY))
                {
                    if (p_fds_evt->result == FDS_SUCCESS)
                    {
                        pds_evt.evt_id = PM_EVT_PEER_DELETE_SUCCEEDED;
                        peer_id_free(pds_evt.peer_id);
                    }
                    else
                    {
                        pds_evt.evt_id = PM_EVT_PEER_DELETE_FAILED;
                        pds_evt.params.peer_delete_failed.error     = p_fds_evt->result;
                        pds_evt.params.peer_delete_failed.fds_error = true;
                    }
    
                    m_peer_delete_deferred = true; // Trigger remaining deletes.
    
                    pds_evt_send(&pds_evt);
                }
                break;
    
            case FDS_EVT_GC:
                if (p_fds_evt->result == FDS_SUCCESS)
                {
                    pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTED;
                }
                else
                {
                    pds_evt.evt_id = PM_EVT_FLASH_GARBAGE_COLLECTION_FAILED;
                    pds_evt.params.garbage_collection_failed.error     = p_fds_evt->result;
                    pds_evt.params.garbage_collection_failed.fds_error = true;
                }
                pds_evt.peer_id = PM_PEER_ID_INVALID;
                pds_evt_send(&pds_evt);
                break;
    
            default:
                // No action.
                break;
        }
    
        if (m_peer_delete_deferred)
        {
            peer_data_delete_process();
        }
    }
    

    --> Also, it looks like you are using freertos. Is this built on a freertos example, or have you adapted the ble_app_uart example to use freertos?

    Yes,I have added freeRtos to ble_app_uart example

  • Hi,

    I found two possible issues in your fds_evt_handler():

    1) In the case FDS_EVT_DEL_RECORD, you handle the p_fds_evt as if it is a WRITE or UPDATE event, when you read the p_fds_evt->write field. This may work with the current implementation, but there is no guarantee that the write and del structs have fields at the same memory locations in the future, or depending on compiler and compiler settings.

    2) There is no break after the FDS_EVT_WRITE nor FDS_EVT_UPDATE cases, is this on purpose? If it is on purpose, then it is common to add a comment stating this. For instance, where the "break;" would normally be placed, use a comment "// fall through". Maybe the issue is that the code under FDS_EVT_DEL_RECORD is executed on FDS_EVT_WRITE, and that makes it look like the write never happened?

    Regards,
    Terje

Reply
  • Hi,

    I found two possible issues in your fds_evt_handler():

    1) In the case FDS_EVT_DEL_RECORD, you handle the p_fds_evt as if it is a WRITE or UPDATE event, when you read the p_fds_evt->write field. This may work with the current implementation, but there is no guarantee that the write and del structs have fields at the same memory locations in the future, or depending on compiler and compiler settings.

    2) There is no break after the FDS_EVT_WRITE nor FDS_EVT_UPDATE cases, is this on purpose? If it is on purpose, then it is common to add a comment stating this. For instance, where the "break;" would normally be placed, use a comment "// fall through". Maybe the issue is that the code under FDS_EVT_DEL_RECORD is executed on FDS_EVT_WRITE, and that makes it look like the write never happened?

    Regards,
    Terje

Children
No Data
Related