DA14531 Name Change Service/Characteristic

I was curious if there's a characteristic to change the GAP device name.

I know there's one to see the name, but I didn't see one to change the name. Is this one I'd have to manually create or is there a simple way to do so?

Thanks!

EDIT:

For those reading this in the future, I verified 3 answers for this. 1 is for a service and characteristic. The other 2 are for AT commands to accomplish the same task, 1 with persistent data and the other without.

Parents
  • Hi There,

    Thank you for posting your question online.
    Yes, it is possible to change the Device Name. 
    I worked on the ble_app_peripheral example with SDK v6.0.18.
    I created a custom characteristic for the Custom Service 1.
    On user_custs1_impl.c file:

    void user_svc1_dev_name_wr_ind_handler (ke_msg_id_t const msgid,
                                          struct custs1_val_write_ind const *param,
                                          ke_task_id_t const dest_id,
                                          ke_task_id_t const src_id)
    {
    
    	char new_device_name[NEW_DEVICE_NAME_LENGTH] = "\0";
    
    	memcpy(&new_device_name, &param->value, param->length);
    
    	device_info.dev_name.length = (strlen(new_device_name) <= GAP_MAX_NAME_SIZE) ?strlen(new_device_name) : GAP_MAX_NAME_SIZE;
    
    	memcpy(device_info.dev_name.name, new_device_name, device_info.dev_name.length);
    
    	
    }

    On user_peripheral.c file:
    void user_catch_rest_hndl(ke_msg_id_t const msgid,
                              void const *param,
                              ke_task_id_t const dest_id,
                              ke_task_id_t const src_id)
    {
        switch(msgid)
        {
            case CUSTS1_VAL_WRITE_IND:
            {
                struct custs1_val_write_ind const *msg_param = (struct custs1_val_write_ind const *)(param);
    
                switch (msg_param->handle)
                {
                    case SVC1_IDX_CONTROL_POINT_VAL:
                        user_svc1_ctrl_wr_ind_handler(msgid, msg_param, dest_id, src_id);
                        break;
    								
                    case SVC1_IDX_DEV_NAME_VAL:
                        user_svc1_dev_name_wr_ind_handler(msgid, msg_param, dest_id, src_id);
                        break;
                        .
                        .
                        .

    With the SmartBond App I connect into my device and I can change the Device name like this:


    ble_app_peripheral_dev_name.zip

    Kind Regards,
    OV_Renesas


  • Quick follow up to this actually: what compiler is required for these changes?

  • Thanks for your time so far, I really appreciate it.

    Two more questions about your solution: 1) would your solution be applicable to the data pump firmware? 2) as far as I can tell there's two names attached to a "barebones" chip if you will: CLv2 and CodeLess. I believe your solution changes the CodeLess name. Do you know how to change the other name as well?

    Also, is there documentation that includes changing names? A quick search yielded no results.

  • Hi There,

    Thank you for the reply.
    1) Yes, a custom at command to change the Device Name can be used on the datapump firmware.
    2) No, there is only one name being used, which is the CLv2-CodeLess, the CLv2 is also the Short Device name which is being placed on the Advertising Data, while the CLv2-CodeLess is the full Device Name which is placed on the Scan Response Data and saved on the device_info struct.

    I worked on the CodeLess SDK v6.380.16.55 and followed the instructions mentioned on the CodeLess User Manual  6. Adding Custom Commands.
    The custom AT command I created is the AT+DEVNAME.
    On the user_at_commands.c file you can find the user_at_devname function:

    char new_device_name[GAP_MAX_NAME_SIZE] = "\0";
    bool flag_devname= false;
    // Custom AT command to change the Device Name
    #ifdef USE_AT_DEVNAME
    
    void user_at_devname(struct at_cmd_params_t* arg, char* reply_string)
    {
    	
    	
    	char zeroed[GAP_MAX_NAME_SIZE] = "0";
    	//Empty the new_device_name array
    	memcpy(new_device_name, &zeroed, GAP_MAX_NAME_SIZE);
    	//If AT+DEVNAME
    	if( arg->arg_count ==0)
    	{
    		//We only printed out the name, so keep flag_devname = false;
    		flag_devname = false; 
    		//Print the existing Device Name
    		arch_sprintf(reply_string, "%s", device_info.dev_name.name);
    		arg->success_flag = true;
    	}
    	else //else if AT+DEVNAME=
    	{
    		//We will change the Device Name (short and long) so change flag_devname= true
    		flag_devname= true;
    
    		//Empty the device_info struct 
    		memcpy(device_info.dev_name.name, &zeroed, GAP_MAX_NAME_SIZE);
    		//Save the New device name into the new_device_name variable
    		memcpy(&new_device_name, &arg->cmd_buffer[arg->arg_index[0]], GAP_MAX_NAME_SIZE);
    		device_info.dev_name.length = (strlen(new_device_name) <= GAP_MAX_NAME_SIZE) ?strlen(new_device_name) : GAP_MAX_NAME_SIZE;
    		//Save the New device name into the device_info struct
    		memcpy(device_info.dev_name.name, new_device_name, device_info.dev_name.length);
    		/* Set the Device Name to the codeless_env struct  */	
    	   memcpy(&codeless_env.resp_data, &device_info.dev_name.name, device_info.dev_name.length);
         codeless_env.resp_data_len = strlen(new_device_name);
    		 // Instantiate the advertising update message to be sent
        struct gapm_update_advertise_data_cmd *cmd = KE_MSG_ALLOC(GAPM_UPDATE_ADVERTISE_DATA_CMD,
                                                                  TASK_GAPM,
                                                                  TASK_APP,
                                                                  gapm_update_advertise_data_cmd);
    
        cmd->operation = GAPM_UPDATE_ADVERTISE_DATA;
    		//Set the Advertising Data as specifiec in user_app_init custom callback function
    		#ifdef USE_AT_BINARY_MODE
        const uint8_t advertisement_data[] =
        #else 
        uint8_t advertisement_data[] =
        #endif 
        { // Complete list of 128bit service UUIDs
        #ifdef USE_AT_BINARY_MODE 
            17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, SPS_SERV_ADV_UUID_REV_BYTES, 
        #else
            17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        #endif
             3, GAP_AD_TYPE_MORE_16_BIT_UUID, 0xF5, 0xFE, //SUOTA Service
          // Bluetooth Device Name
             5, GAP_AD_TYPE_SHORTENED_NAME, 
             new_device_name[0],
             new_device_name[1],
             new_device_name[2],
             new_device_name[3]
        };
        #ifndef USE_AT_BINARY_MODE
        for (uint8_t i = 0; i < 16; i++) {
                advertisement_data[2 + i] = codeless_const_env.adv_service_uuid[i]; 
        }    
        #endif   
    		 //Save the advertisemnt_data into the codeless_env struct
        memcpy(&codeless_env.adv_data, &advertisement_data, sizeof(advertisement_data));
         //Save the Advertisment  data length into the codeless_env struct
        codeless_env.adv_data_len = sizeof(advertisement_data);
    		// Update the Advertising data 
        cmd->adv_data_len = codeless_env.adv_data_len;
        memcpy(cmd->adv_data, codeless_env.adv_data, codeless_env.adv_data_len);
    
     		/* Set the Device Name to Scan response data and show it */
    	  append_device_name(&cmd->scan_rsp_data_len,
    										   codeless_env.resp_data_len,
                           &(cmd->scan_rsp_data[cmd->scan_rsp_data_len]),
                           codeless_env.resp_data);
    
        // Send the message
        ke_msg_send(cmd);
    
    		//Print the New name
    		arch_sprintf(reply_string, "%s", device_info.dev_name.name);
    		arg->success_flag = true;
    	}
    	
    
    }
    #endif

    However, when disconnected or when we use the AT+ADVSTOP and AT+ADVSTART commands we restart advertising via the user_advertise custom callback function.
    I modified the user_disconnect and the user_at_advstart functions in order to use the new device name set by the AT+DEVNAME command. 
    Please see the screenshots below on how the AT command is being used:
       
    By default the Device Name is CLv2-CodeLess and you can see on the Advertising Data the Short Name: CLv2.
    When you use the AT+DEVNAME without any arguments, then it will print out the existing Device Name. When you use the AT+DEVNAME with arguments, it will use the arguments you used as the new Device Name:

    After that I can see on the SmartBond App:

    As you can see the first 4 characters are saved on the Advertising Data on the Short Name.
    When we Connect, the Device Name is shown in the first Service (Generic Access 0x1800) on the Characteristic Device Name:

    If you use the AT+DEVNAME command while connected, it will change the Device Name as well:

    After that, you should be able to see on the SmartBond App:

    Finally, when we disconnect we will keep advertising with the last name we used on the AT+DEVNAME command.
    If you use the AT+ADVSTOP command to stop advertising, change the Device Name via the AT+DEVNAME command and start advertising with the AT+ADVSTART command, you should see the new device name.

    codeless_5xx_devname.zip

    Kind Regards,
    OV_Renesas

  • This is interesting, I see two names only: CLv2 and CodeLess, never a CLv2-CodeLess. This is on 14531 v_6.380.14.22 by the way. I'll have to investigate why that is. I wanted to figure out a way to rename both.

  • Hi There,

    Thank you for the response.
    In Codeless SDK v6.380.14.22 we had set the USER_DEVICE_NAME as CodeLess and we have not inserted the Short Name into the Advertising Data. 
    Where did you see the CLv2 name on this CodeLess version?
    Are you facing any issues with the AT+DEVNAME command on CodeLess SDK v6.380.16.55?

    Kind Regards,
    OV_Renesas

  • The library I'm using to communicate with the device has two values: name (defined as "Device name if present") and localName (defined as "User friendly name of device"). 

    name returns CLv2 and localName returns CodeLess. Ideally I was hoping to rename both.

    I admittedly haven't yet tried implementing AT+DEVNAME, I'll soon try. I just wanted to ask ahead of time to try to further my knowledge of this. 

  • Just a follow up to this since I've had time to work on it:

    For the name: You're right! v6.380.14 had CodeLess and v6.360.16 had CLv2-CodeLess.

    CLv2 shows up as the short name (I'm assuming localName is the short name for my library) on v6.380.16, which fits in perfectly with what you said earlier. Still interesting to me then that CLv2 shows up as the long name and CodeLess the short name on v6.380.14.

    For the AT+DEVNAME custom command: It works! But it's not persistent when it restarts. Do you know if that's possible without having something else read/store/write the name with the command on every reboot?

  • Hi There,

    Thank you for the reply.

    For the AT+DEVNAME custom command: It works! But it's not persistent when it restarts. Do you know if that's possible without having something else read/store/write the name with the command on every reboot?

    If you want the device name to be kept even after a Reset or Power off/on then you should save the device name on the SPI Flash and on the user_app_on_init read the specific address you have stored your name and see which name should be used in your project.

    Kind Regards,
    OV_Renesas

  • Am I correct in assuming writing to SPI Flash couldn't be done through an AT command?

    If I'm able, it seems like combining the second half of this tutorial with such an AT command could accomplish what I'm looking for.

    Edit:
    Another question, am I correct in assuming I cannot compile changes to the last file you added because it requires a paid edition of Keil-MDK? I'm unable to find the directory codeless > codeless_5xx > Keil_5 in the target_apps directory of the SDK so I've been unable to try to rebuild this on my own.

  • Hi There,

    Thanks for the reply and apologies for the delay.

    If I'm able, it seems like combining the second half of this tutorial with such an AT command could accomplish what I'm looking for.

    In order to save the new Device Name into the SPI Flash you should work with this tutorial: 
    5. DA14531 SPI Flash — DA145XX Tutorial SDK peripherals (renesas.com)

    Another question, am I correct in assuming I cannot compile changes to the last file you added because it requires a paid edition of Keil-MDK?

    Yes, due to the ARM Compiler v6 and the size of CodeLess SDK you will not be able to compile this project without a license.

    Please find the attached codeless_5xx_devname_v2.zip file.
    Each time we use the AT+DEVNAME command to change the device name, we store the Device Name into the SPI Flash on the address 0x1FFC0 (64 bytes before the end of the SPI Flash 0x20000).
    I worked with DA14531MOD, so my initializations are for the P25Q11U Flash which is integrated in the DA14531MOD.
    Main Changes:
    On user_periph_setup.h:

    #define SPI_FLASH_DEFAULT_SIZE  (128 * 1024)    // SPI Flash memory size in bytes // DevKitPro : 256* 1024

    On user_periph_setup.c:
    // Configuration struct for SPI FLASH P25Q11U (0x20000 chip size)
    const spi_flash_cfg_t spi_cfg = {
        .chip_size = SPI_FLASH_DEFAULT_SIZE,
    };
    
    //On periph_init function
    #if defined(CFG_PRF_SUOTAR) || defined(CFG_SPI_FLASH_ENABLE) 
        spi_cfg_t spi_flash_cfg = { .spi_ms = SPI_MS_MODE_MASTER,
                                    .spi_cp = SPI_CP_MODE_0,
                                    .spi_speed = SPI_SPEED_MODE_4MHz,
                                    .spi_wsz = SPI_MODE_8BIT,
                                    .spi_cs = SPI_CS_0,
                                    .cs_pad.port = SPI_EN_GPIO_PORT,
                                    .cs_pad.pin = SPI_EN_GPIO_PIN,
                            #if defined (__DA14531__)
                                    .spi_capture = SPI_MASTER_EDGE_CAPTURE
                            #endif
                                    };
    
        // Configure SPI Flash environment
    		// P25Q11U SPI Flash-DA14531MOD
         spi_flash_configure_env(&spi_cfg);
    		// Initialize the SPI driver														
        spi_initialize(&spi_flash_cfg);
    #endif // CFG_PRF_SUOTAR || CFG_SPI_FLASH_ENABLE

    On user_codeless.c:
    //Will be stored the Device Name being read from SPI Flash
    char device_name_after_reset[GAP_MAX_NAME_SIZE];
    //Counter to see if we have stored another Device name in the SPI Flash
    int counter=0;
     /* Read the Flag_devname from SPI Flash address 0x1FE00 */
    void read_flag_from_SPI(void)
    {
    	//Re-configure P0_0 for SPI Flash
    	GPIO_ConfigurePin(SPI_DO_GPIO_PORT, SPI_DO_GPIO_PIN, OUTPUT, PID_SPI_DO, false);
      int8_t ret;
    	uint8_t devname_read[GAP_MAX_NAME_SIZE];
    	//32 bytes, which is the GAP_MAX_NAME_SIZE and the MAX size of the Scan Response Data.
    	uint32_t bytes_read=0x20;
    	/* Wake-up SPI Flash */
    	spi_flash_release_from_power_down();
    
    	/*Read the data stored on address 0x1FFC0 */
    	ret = spi_flash_read_data((uint8_t *) &devname_read,0x1FFC0 , sizeof(devname_read), &bytes_read);
    	arch_printf("\n\rRead Status for 0x1FE00: %d \n\r", ret);
    	/* Print the data if the Read Status is OK 
    		Uncomment the arch_printf if you want to Print the Bytes we have read from SPI Flash*/
    	if(ret == 0)
    	{
    		//arch_printf("Bytes read:");
    		int len = sizeof(devname_read);
    		//Print all the data we read from SPI Flash
    		while(len != 0)
    		{
    			//arch_printf(" %d |", devname_read[sizeof(devname_read) -len]);
    			//Store the Device name into a new array
    			if(devname_read[sizeof(devname_read) -len] != 0x00)
    			{
    				device_name_after_reset[sizeof(devname_read) -len] = devname_read[sizeof(devname_read) -len];
    			}
    			//Check if all the data is empty
    			if(devname_read[sizeof(devname_read) -len] == 0xFF)
    			{
    				counter++;
    			}
    			
    			len--;
    		}
    		//If address 0x1FFC0 is empty, then do not change the Device Name Struct and the Scan Response Data
    		if(counter==32)
    		{
    			flag_for_name = true;
    		}
    		else// if address 0x1FFC0 is not empty, then use the stored Device Name
    		{
    			flag_for_name= false;
    		}
    	//	arch_printf("\n\r");
    	}
    	// Reduce power consumption by putting flash into sleep mode 
      spi_flash_power_down();
    	
      // Re-enable HW reset input (must be disabled if/when further operation on
      // external flash are performed) - must set as input first!
      GPIO_ConfigurePin(SPI_DO_GPIO_PORT, SPI_DO_GPIO_PIN, INPUT_PULLDOWN, PID_GPIO, false);
    
    }
    
    void user_app_on_init(void)
    {
    			
    	  
        // Create a static, random, Bluetooth Device Address
    #if defined(CFG_USE_GENERATED_BLUETOOTH_ADDRESS)
        user_injected_bd_address = generate_random_bd_addr();
    #else
        user_injected_bd_address = get_bd_addr_from_otp_or_nvds();
    #endif 
        default_app_on_init();
        // Set intial Bluetooth role
    #ifdef CODELESS_585
        codeless_env.bt_role = GAP_ROLE_NONE;
    #endif
    
        // Set the application state
        codeless_env.gap_activity = IDLE;
        codeless_env.adv_intv = user_adv_conf.intv_min;
        console_env.echo = true;
        console_env.error_report_flag = true;
        
        #ifdef USE_AT_BINARY_MODE
        codeless_env.binary_mode=false;
        codeless_env.escape_time1=MSEC_TO_ESC_TIMER1(CODELESS_DEFAULT_ESC_TIME1); //1sec
        codeless_env.escape_time2=MSEC_TO_ESC_TIMER2(CODELESS_DEFAULT_ESC_TIME2); //1sec
        codeless_env.escape_chars[0]='+';
        codeless_env.escape_chars[1]='+';
        codeless_env.escape_chars[2]='+';
        codeless_env.escape_chars_command_input=0x2B2B2B;
        #endif
        // Set the PIN to 0 (disable security)
        codeless_env.pin = 0;
        // Specify the advertise data
        
        #ifdef USE_AT_FLOWCONTROL
        codeless_env.flow_control_enabled=false;
        #endif
        
        #ifdef USE_AT_CONPAR
        struct connection_configuration_t *p_conf=&codeless_env.conn_conf;
        p_conf->dle_en=true;
        p_conf->dle_tx_pkt_len=CFG_MAX_TX_PACKET_LENGTH;
        p_conf->dle_rx_pkt_len=CFG_MAX_RX_PACKET_LENGTH;
        p_conf->max_mtu=user_gapm_conf.max_mtu;
        #endif
        
        #ifdef USE_AT_HOSTSLP
        codeless_env.hst_sleep_mode=HOSTSL_DEFAULT_SLP_MODE;
        codeless_env.hst_sleep_wakeup_byte=HOSTSL_DEFAULT_WKUP_BYTE;
        codeless_env.hst_sleep_wakeup_retry_interval=HOSTSL_DEFAULT_WKUP_INTERVAL;
        codeless_env.hst_sleep_wakeup_retry_times=HOSTSL_DEFAULT_WKUP_TRIES;
        #endif
    		//Read the address 0x1FFC0 on SPI Flash to see if we have stored a different Device Name
    		read_flag_from_SPI();
    		//Print True if we have not a New device Name, Print False if we had stored a new Device Name
    		arch_printf("We did NOT store a new Device Name: %s",flag_for_name?"true":"false");
    		if(!flag_for_name)	//if we had stored a New Device name, print it
    		{
    			arch_printf("\r\n %s", device_name_after_reset);
    		}
    		if(flag_for_name)	//Default Operation, we have not stored any alternative Device Name in the SPI Flash
    		{
    			#ifdef USE_AT_BINARY_MODE
    			const uint8_t advertisement_data[] =
    			#else 
    			uint8_t advertisement_data[] =
    			#endif 
    			{ // Complete list of 128bit service UUIDs
    			#ifdef USE_AT_BINARY_MODE 
    					17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, SPS_SERV_ADV_UUID_REV_BYTES, 
    			#else
    					17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    					 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    			#endif
    					 3, GAP_AD_TYPE_MORE_16_BIT_UUID, 0xF5, 0xFE, //SUOTA Service
    				// Bluetooth Device Name
    					 5, GAP_AD_TYPE_SHORTENED_NAME, 
    					 USER_DEVICE_NAME[0],
    					 USER_DEVICE_NAME[1],
    					 USER_DEVICE_NAME[2],
    					 USER_DEVICE_NAME[3]
    			};
    			#ifndef USE_AT_BINARY_MODE
    			for (uint8_t i = 0; i < 16; i++) {
    							advertisement_data[2 + i] = codeless_const_env.adv_service_uuid[i]; 
    			}    
    			#endif    
    			
    			//Save the advertisemnt_data into the codeless_env struct
    			memcpy(&codeless_env.adv_data, &advertisement_data, sizeof(advertisement_data));
    			//Save the Advertisment  data length into the codeless_env struct
    			codeless_env.adv_data_len = sizeof(advertisement_data);
    			
    			// Set scan response data where the full CodeLess name is shown
    			codeless_env.resp_data[0] = USER_DEVICE_NAME_LEN + 1;
    			codeless_env.resp_data[1] = GAP_AD_TYPE_COMPLETE_NAME;
    			
    			memcpy(&codeless_env.resp_data[2], USER_DEVICE_NAME, USER_DEVICE_NAME_LEN);
    			codeless_env.resp_data_len = USER_DEVICE_NAME_LEN + 2;
    	  }
    		else if(!flag_for_name)	//if we have stored a different Device Name, then use this device name on the Scan Response Data
    		{
    						//Set the Advertising Data as specifiec in user_app_init custom callback function
    					#ifdef USE_AT_BINARY_MODE
    					const uint8_t advertisement_data[] =
    					#else 
    					uint8_t advertisement_data[] =
    					#endif 
    					{ // Complete list of 128bit service UUIDs
    					#ifdef USE_AT_BINARY_MODE 
    							17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, SPS_SERV_ADV_UUID_REV_BYTES, 
    					#else
    							17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    							 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    					#endif
    							 3, GAP_AD_TYPE_MORE_16_BIT_UUID, 0xF5, 0xFE, //SUOTA Service
    						// Bluetooth Device Name
    							 5, GAP_AD_TYPE_SHORTENED_NAME, 
    							 device_name_after_reset[0],
    							 device_name_after_reset[1],
    							 device_name_after_reset[2],
    							 device_name_after_reset[3]
    					};
    					#ifndef USE_AT_BINARY_MODE
    					for (uint8_t i = 0; i < 16; i++) {
    									advertisement_data[2 + i] = codeless_const_env.adv_service_uuid[i]; 
    					}    
    					#endif   
    					 //Save the advertisemnt_data into the codeless_env struct
    					memcpy(&codeless_env.adv_data, &advertisement_data, sizeof(advertisement_data));
    					 //Save the Advertisment  data length into the codeless_env struct
    					codeless_env.adv_data_len = sizeof(advertisement_data);
    					
    					//Empty array 
    					char zeroed[GAP_MAX_NAME_SIZE] = "0";
    					//Empty the device_info struct 
    					memcpy(device_info.dev_name.name, &zeroed, GAP_MAX_NAME_SIZE);
    					device_info.dev_name.length = strlen(device_name_after_reset);
    					//Save the New device name into the device_info struct
    					memcpy(device_info.dev_name.name, device_name_after_reset, device_info.dev_name.length);
    					/* Set the Device Name to the codeless_env struct  */	
    				  memcpy(&codeless_env.resp_data, &device_info.dev_name.name, device_info.dev_name.length);
    				  codeless_env.resp_data_len = strlen(device_name_after_reset);
    				
    
    		}
        
        // set codeless to connectable.
        codeless_env.is_connectable = true;
        // Initialize input command index to zero.
        console_env.input_cmd_char_index = 0;
        // Initialize parser flag
        console_env.parser_flag = CHAR_PARSER_NOT_ACTIVE;
    		
    #if defined(USE_AT_BND) 
        #if (BLE_APP_SEC)
            // The bdb should be initialized once if the bonding commands are 
            // included. The security should be enabled as well otherwise the 
            // bond commands do not make sense.
            default_app_bdb_init();
        #else
            #warning "Bonding commands are included but security is disabled;No bonding commands will be available"
        #endif 
    #endif
    #if defined(USE_AT_HNDL)
        // The hdb should be initialized once if the handler commands are 
        // included
        app_hdb_init();
    #endif
    
    #if defined(USE_AT_CONPAR) || defined(USE_AT_MAXMTU) || defined(USE_AT_DLEEN)
        app_cpdb_init();
        app_load_cpdb_conf_from_flash(&codeless_env.conn_conf);
    #endif
    
    #if defined (USE_AT_EVENT)
        // The events database should be initialized once if the event command
        // is included
        app_evdb_init();
    #endif
    
    
    }

    On user_codeless.c for user_advertise function:
    void user_advertise(void)
    {
    	if(flag_for_name)// Default Operation, We have no Device Name stored in the SPI Flash (0x1FFC0)
    	{
    				struct gapm_start_advertise_cmd* cmd;
    
    				if (codeless_env.is_connectable)
    				{
    						cmd = app_easy_gap_undirected_advertise_get_active();
    				} 
    				else 
    				{
    						cmd = app_easy_gap_non_connectable_advertise_get_active();
    				}
    				// Specify the advertise data
    				cmd->info.host.adv_data_len = codeless_env.adv_data_len;
    				memcpy(&cmd->info.host.adv_data, &codeless_env.adv_data, codeless_env.adv_data_len);
    				// Specify scan response data (if any)
    				if (codeless_env.resp_data_len > 0 && codeless_env.is_connectable)
    				{
    						cmd->info.host.scan_rsp_data_len = codeless_env.resp_data_len;
    						memcpy(&cmd->info.host.scan_rsp_data, &codeless_env.resp_data, codeless_env.resp_data_len);
    				}
    				else
    				{
    						cmd->info.host.scan_rsp_data_len = 0;
    				}
    				// Set advertising interval
    				cmd->intv_min = codeless_env.adv_intv;
    				cmd->intv_max = codeless_env.adv_intv;
    				// Set the advertise mode
    				if (codeless_env.is_connectable)
    				{
    						cmd->info.host.mode = GAP_GEN_DISCOVERABLE;
    				}
    				else
    				{
    						cmd->info.host.mode = GAP_BROADCASTER_MODE;
    				}
    				
    
    			
    			if (codeless_env.is_connectable)
    			{
    						app_easy_gap_undirected_advertise_start();			  
    			}
    			else 
    			{
    						app_easy_gap_non_connectable_advertise_start();   			  
    			}
    
    				// Retain the current activity state
    				codeless_env.gap_activity = ADVERTISING;
    		}
    		else if(!flag_for_name) // If we have stored a new Device Name 
    		{
    				struct gapm_start_advertise_cmd* cmd;
    
    				if (codeless_env.is_connectable)
    				{
    						cmd = app_easy_gap_undirected_advertise_get_active();
    				} 
    				else 
    				{
    						cmd = app_easy_gap_non_connectable_advertise_get_active();
    				}
    
    				// Update the Advertising data 
    				cmd->info.host.adv_data_len = codeless_env.adv_data_len;
    				memcpy(cmd->info.host.adv_data, codeless_env.adv_data, codeless_env.adv_data_len);
    
    				/* Set the Device Name to Scan response data and show it */
    				append_device_name(&cmd->info.host.scan_rsp_data_len,
    													 codeless_env.resp_data_len,
    													 &(cmd->info.host.scan_rsp_data[cmd->info.host.scan_rsp_data_len]),
    													 codeless_env.resp_data);
    					
    				// Set advertising interval
    				cmd->intv_min = codeless_env.adv_intv;
    				cmd->intv_max = codeless_env.adv_intv;
    				// Set the advertise mode
    				if (codeless_env.is_connectable) {
    						cmd->info.host.mode = GAP_GEN_DISCOVERABLE;
    				} else {
    						cmd->info.host.mode = GAP_BROADCASTER_MODE;
    				}
    				//Start Advertising
    				if (codeless_env.is_connectable) {
    						app_easy_gap_undirected_advertise_start();			  
    				} else {
    						app_easy_gap_non_connectable_advertise_start();   			  
    				}
    
    				// Retain the current activity state
    				codeless_env.gap_activity = ADVERTISING;
    			}
    }

    On user_at_commands.c:
    // Custom AT command to change the Device Name
    #ifdef USE_AT_DEVNAME
    void save_flag_on_SPI(void)
    {
    
    	//Re-configure P0_0 for SPI Flash
    	GPIO_ConfigurePin(SPI_DO_GPIO_PORT, SPI_DO_GPIO_PIN, OUTPUT, PID_SPI_DO, false);
      int8_t ret;
    	/* Wake-up SPI Flash */
    	spi_flash_release_from_power_down();
    	// 32 bytes- Size of Scan Response Data and Max Device Name Length
    	uint32_t pc_bytes_written= 0x20;
    	/* Erase data on address 0x1FFC0 
    		 We must always first Erase and then Write on an Address */
    	ret = spi_flash_page_erase(0x1FFC0);	//, SPI_FLASH_OP_BE32
    	if(ret == 0)	//If erase was successful
    	{
    		arch_printf("\n\r P25Q11U Flash sector 0x1FE00 has been erased \n\r");
    	}
    
    	/* Write data on address 0x1FFC0*/
    	ret = spi_flash_write_data((uint8_t *) &new_device_name, 0x1FFC0, sizeof(new_device_name),  &pc_bytes_written);
    	arch_printf("\n\rWrite Status for 0x1FFC0: %d", ret);
    	/* Print the written data if the Write Status does not return any Error */
    //	if(ret == 0)
    //	{
    //		arch_printf("\n\r Written Success ");
    //	}
    	// Reduce power consumption by putting flash into sleep mode 
      spi_flash_power_down();
    	
      // Re-enable HW reset input (must be disabled if/when further operation on
      // external flash are performed) - must set as input first!
      GPIO_ConfigurePin(SPI_DO_GPIO_PORT, SPI_DO_GPIO_PIN, INPUT_PULLDOWN, PID_GPIO, false);
    
    }
    
    void user_at_devname(struct at_cmd_params_t* arg, char* reply_string)
    {
    	
    	
    	char zeroed[GAP_MAX_NAME_SIZE] = "0";
    	//Empty the new_device_name array
    	memcpy(new_device_name, &zeroed, GAP_MAX_NAME_SIZE);
    	//If AT+DEVNAME
    	if( arg->arg_count ==0)
    	{
    		//We only printed out the name, so keep flag_devname = false;
    		flag_devname = false; 
    		//Print the existing Device Name
    		arch_sprintf(reply_string, "%s", device_info.dev_name.name);
    		arg->success_flag = true;
    	}
    	else //else if AT+DEVNAME=
    	{
    		//We will change the Device Name (short and long) so change flag_devname= true
    		flag_devname= true;
    		changed_name = true;
    		//Empty the device_info struct 
    		memcpy(device_info.dev_name.name, &zeroed, GAP_MAX_NAME_SIZE);
    		//Save the New device name into the new_device_name variable
    		memcpy(&new_device_name, &arg->cmd_buffer[arg->arg_index[0]], GAP_MAX_NAME_SIZE);
    		device_info.dev_name.length = (strlen(new_device_name) <= GAP_MAX_NAME_SIZE) ?strlen(new_device_name) : GAP_MAX_NAME_SIZE;
    		//Save the New device name into the device_info struct
    		memcpy(device_info.dev_name.name, new_device_name, device_info.dev_name.length);
    		/* Set the Device Name to the codeless_env struct  */	
    	   memcpy(&codeless_env.resp_data, &device_info.dev_name.name, device_info.dev_name.length);
         codeless_env.resp_data_len = strlen(new_device_name);
    		 // Instantiate the advertising update message to be sent
        struct gapm_update_advertise_data_cmd *cmd = KE_MSG_ALLOC(GAPM_UPDATE_ADVERTISE_DATA_CMD,
                                                                  TASK_GAPM,
                                                                  TASK_APP,
                                                                  gapm_update_advertise_data_cmd);
    
        cmd->operation = GAPM_UPDATE_ADVERTISE_DATA;
    		//Set the Advertising Data as specifiec in user_app_init custom callback function
    		#ifdef USE_AT_BINARY_MODE
        const uint8_t advertisement_data[] =
        #else 
        uint8_t advertisement_data[] =
        #endif 
        { // Complete list of 128bit service UUIDs
        #ifdef USE_AT_BINARY_MODE 
            17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, SPS_SERV_ADV_UUID_REV_BYTES, 
        #else
            17, GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
        #endif
             3, GAP_AD_TYPE_MORE_16_BIT_UUID, 0xF5, 0xFE, //SUOTA Service
          // Bluetooth Device Name
             5, GAP_AD_TYPE_SHORTENED_NAME, 
             new_device_name[0],
             new_device_name[1],
             new_device_name[2],
             new_device_name[3]
        };
        #ifndef USE_AT_BINARY_MODE
        for (uint8_t i = 0; i < 16; i++) {
                advertisement_data[2 + i] = codeless_const_env.adv_service_uuid[i]; 
        }    
        #endif   
    		 //Save the advertisemnt_data into the codeless_env struct
        memcpy(&codeless_env.adv_data, &advertisement_data, sizeof(advertisement_data));
         //Save the Advertisment  data length into the codeless_env struct
        codeless_env.adv_data_len = sizeof(advertisement_data);
    		// Update the Advertising data 
        cmd->adv_data_len = codeless_env.adv_data_len;
        memcpy(cmd->adv_data, codeless_env.adv_data, codeless_env.adv_data_len);
    
     		/* Set the Device Name to Scan response data and show it */
    	  append_device_name(&cmd->scan_rsp_data_len,
    										   codeless_env.resp_data_len,
                           &(cmd->scan_rsp_data[cmd->scan_rsp_data_len]),
                           codeless_env.resp_data);
    
        // Send the message
        ke_msg_send(cmd);
    		
    		arch_printf("Flag_devname bool : %s",flag_devname?"true":"false");
    
    
    		//Print the New name
    		arch_sprintf(reply_string, "%s", device_info.dev_name.name);
    		arg->success_flag = true;
    		//Save the New Device Name on the SPI Flash
    		save_flag_on_SPI();
    	}
    	
    }
    #endif

    On my side it works as expected:

    Please test it in your side and share any feedback.
    6.380.16.55_devname_v2.zip

    Kind Regards,
    OV_Renesas

  • Sorry for the delay. I tested this and it works just as you described. Brilliant work. I need to spend some more time later to fully read the code vs your guide to appreciate it. Thanks for your time and effort on this, I've really learned a lot during this whole process. 

    One last question though related to compiling: am I correct in reading that SDK 5 is still accessible and can be worked on and compiled for free? 

Reply
  • Sorry for the delay. I tested this and it works just as you described. Brilliant work. I need to spend some more time later to fully read the code vs your guide to appreciate it. Thanks for your time and effort on this, I've really learned a lot during this whole process. 

    One last question though related to compiling: am I correct in reading that SDK 5 is still accessible and can be worked on and compiled for free? 

Children
  • Hi There,

    Thank you for the reply and the feedback.

    One last question though related to compiling: am I correct in reading that SDK 5 is still accessible and can be worked on and compiled for free? 

    That is not correct. The SDK5 is not available and it did not support DA14531. It supported DA14580/1/2/3/5/6,

    P.S.
    If you found any answer helpful, you can verify it so you can help others in the community with the same issue.

    Kind Regards,
    OV_Renesas

  • Drat! So is there no way for me to try my own solutions without the paid version of Keil? Reading the documentation I thought the solution was SDK5.

    Also, I've verified the 3 answers that covered changing the advertising name. 

  • Hi There,

    Thank you for the reply.

    So is there no way for me to try my own solutions without the paid version of Keil? Reading the documentation I thought the solution was SDK5.

    You could use the Keil IDE Professional License which has a Trial period. However, if you want to develop a project and go on production, you should have the Keil IDE Licensed. 
    If you have any other issue, feel free to raise a new ticket.

    Kind Regards,
    OV_Renesas