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.
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, ¶m->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); }
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; . . .
Quick follow up to this actually: what compiler is required for these changes?
Hi There,Thank you for the reply.If you are working on Codeless v6.380.16.55 you will need ARM Compiler v6.If you are working on Codeless v6.380.14.22 or any older version you will need ARM Compiler v5.Kind Regards,OV_Renesas
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
codeless_5xx_devname.zipKind 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.
Daeolt said: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.
Daeolt said: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)
Daeolt said: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
// 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
//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 }
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; } }
// 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.zipKind 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?
Hi There,Thank you for the reply and the feedback.
Daeolt said: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.
Daeolt said: 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