Hi Dialog,
I am trying to write a firmware that makes the development kit board (basic) a dongle.
I have written a desktop software that will communicate with the board via serial port.
I hope that when the software sends commands to the board, the board could response accordingly. e.g. scan peer devices, connected to peer devices , etc. The firmware installed in the board could also discover the services and attributions of the peer device it connects to, and report these to the software on PC via serial port. It could also receive the notify data from the connected peer device and , again, report to the PC software.
I have read the DSPS examples, but it discovers peer devices and connected to the given device by Device Name (pre-given in code!!!!).So would you do me a favour and write a guide line for me? Thanks!
And I tried to modify the code in user_sps_host.c, the user_on_adv_report_ind function is modified as follows, and I also modified the user_on_scanning_completed function, in the purpose to stop scanning when obtained 5 devices.
void user_on_adv_report_ind(struct gapm_adv_report_ind const * param)
{
// get device name
uint8 i=0, j=0;
uint8 len = sizeof(param->report.data);
char dn[20] = "";
for(i=0;ireport.data[i]>=0x20 && param->report.data[i]<=0x7E)
{
dn[j++] = param->report.data[i];
}
}
// get device address
len = sizeof(param->report.adv_addr.addr);
char add_buffer[13]="";
j = 0;
for(i= 0; ireport.adv_addr.addr[len - i - 1]);
add_buffer[j] = buffer[0];
add_buffer[j+1] = buffer[1];
j = j+2;
}
// get RSSI
char rssi[3];
sprintf(rssi,"%d", param->report.rssi);
// form the packet that will send to the PC via UART2
char packet[44];
j = 0;
packet[j++] = '*';
packet[j++] = 'D';
packet[j++] = 'N';
packet[j++] = ':';
for(i=0; i<20; i++)
{
if(dn[i] != 0x00)
{
packet[j++] = dn[i];
}
}
packet[j++] = ',';
for(i=0; i<13; i++)
{
if(add_buffer[i] != 0x00)
{
packet[j++] = add_buffer[i];
}
}
packet[j++] = ',';
for(i=0; i<3; i++)
{
if(add_buffer[i] != 0x00)
{
packet[j++] = add_buffer[i];
}
}
packet[j++] = '\r';
packet[j++] = '\n';
// send the packet to the PC
printf_string(packet);
}
void user_on_scanning_completed (uint8_t status)
{
device_count++;
if(device_count<=5)
{
user_scan_start();
}
else
{
user_wait_for_cmd();
}
return;
}
Here, I added a function called user_wait_for_cmd(), which is used to read the command, and is implemented as follows, and the uart2 read completed callback is used to recall the user_wait_for_cmd() . However, the program come up with an JLINK Error, that says Can not read registers ## while CPU is running. what is the problem for this implementation?
void user_wait_for_cmd(void)
{
uint8_t read_length = 25;
while(!read_success)
{
uart2_read((uint8_t *)buffer, read_length, uart2_read_completion_cb);
}
}
bool read_success ;
void uart2_read_completion_cb(uint8_t status)
{
if(buffer[0]=='C' && buffer[1]=='M' && buffer[2]=='D')
{
read_success = true;
printf_string(buffer);
}
else
{
read_success = false;
user_wait_for_cmd();
}
}
By the way, where can I buy a dongle for DA14580?
Hi wenkangl,
As far as i know it goes along with the pro-dev kit, i dont think that is sold seperately. Some comments regarding the code you ve pasted, i can see that you are counting the devices that you ve discovered when user_on_scanning_completed() is invoked, that means that you are counting the scanning cycles of your device, every scan cycle lasts a few seconds and the user_on_scanning_complete is invoked either when you cancel the scanning procedure or when the scan operation completes. The advertising messages are comming as indications to the user_on_adv_report_ind() everytime the device gets a new advertising string. So in order to count devices scanned, what you must do is to check the bd address of the current advertising string and check the entries in your log (the place that you keep the recorded devices) and count up when you are placing a new entry in your log. Regarding the error that you are getting when applying the code for reading, i dont think that your implementation is responsible for it, check the default sleep mode of the device and make sure that the sleep mode is disabled (you cant have the sleep mode enabled and debug at the same time). Also you will have to consider the fact that the 580 when it sleeps all the peripherals are powered down including the UART, the DSPS for example uses the a flow control scheme in order to signal the external MCU when its allowed to send data or not, since if the data are sent while the 580 sleeps they will be lost.
Thanks MT_dialog
Thanks MT,
I have more questions on this topic, since my aim is more than counting the devices nearby.
NO1. In the da1458x_config_basic.h The sleep mode has been configured to be active:
#undef CFG_MEM_MAP_EXT_SLEEP
#undef CFG_MEM_MAP_DEEP_SLEEP
然后我发送扫描命令(CMD_SCAN) to the DB, and the firmware did call the user_scan_start() and run the function to the end. However, after that, the user_on_adv_report_ind is NOT triggered, and moreover, when I sent a command of connection (CMD_CONNECT), the program called user_connect_to but the user_on_scanning_completed and user_on_connection are NOT triggered... so in this situation, what is wrong with my implementation.
I have modified the function uart2_read_completion_cb as follows
char buffer[25];
static uint8_t uart2_read_in_progress = 0;
void uart2_read_completion_cb(uint8_t status)
{
if(buffer[0]=='C' && buffer[1]=='M' && buffer[2]=='D')
{
uart2_read_in_progress = 0;
printf_string(buffer);
action_on_command();
}
else
{
user_wait_for_cmd();
}
}
void user_wait_for_cmd(void)
{
uint8_t read_length = 25;
uart2_read_in_progress = 1;
uart2_read((uint8_t *)buffer, read_length, uart2_read_completion_cb);
while(uart2_read_in_progress);
}
and the action on received command is as follows
void action_on_command(void)
{
char cmdid[] = {buffer[4], buffer[5]};
uint8 CMD_ID = (uint8)strtol(cmdid,NULL,16);
uint8 hexdata[16]={0};
uint8 i = 7;
while(!(buffer[i]=='\\' && buffer[i+1]=='r'))
{
hexdata[i-7]=buffer[i];
i++;
}
switch(CMD_ID)
{
case CMD_SCAN:
{
// 0x00
user_scan_start();
break;
}
case CMD_CONNECT:
{
// 0x01
uint8 peer_addr[6]={0x00};
for(i=0; i<6; i++)
{
char temp[] = { hexdata[2*i],hexdata[2*i+1] };
uint8 part_add = (uint8)strtol(temp,NULL,16);
peer_addr[5-i] = part_add;
}
user_connect_to(0x00, peer_addr);
break;
}
}
}
and the user_connect_to is as follows
void user_connect_to(uint8_t peer_addr_type, uint8_t *peer_addr)
{
app_easy_gap_start_connection_to_set(peer_addr_type, peer_addr, MS_TO_DOUBLESLOTS(USER_CON_INTV));
app_easy_gap_start_connection_to();
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NO2. Then I came up with another idea. That is, even if I solved the problem described above, it still can't be satisfying. Because I hope DA14580 could handle at least two tasks asynchronously, that is, it keeps monitoring the command sent from PC ( and the DA14580 should always be monitoring the command sent by PC) and meanwhile doing something else.
For example, it monitors the command from PC while receiving notified data sent by a connected peripheral device and send the data to the PC.
另一个考试ple: when the DB is receiving the notifying data, I send a stop notifying command to the DB. The DB should stop uploading the received notifying data and sends a stop notifying command to the connected peripheral device, and the connected peripheral device will act accordingly.
For this purpose, what should I do if I want to use the DSPS project? ps: the question is focus on the central end (dongle), the task for the peripheral end has already been done. ^_^
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NO3. Since the dongle is not sold separately, can you recommend one that works well with DA14580? connectBlue?
Thanks!
Hi wenkangl,
NO1: The definitions that you ve changed affects the memory mapping of your device and not the sleeping mode (its mentioned in the comment above "Sleep mode memory map configuration."), To change the default sleep mode you have to change the app_default_sleep_mode in the user_config.h file with ARCH_SLEEP_OFF, this is the reason for the error that JLink reports after a few seconds while you are in debug mode. Regarding the fact that the user_on_adv_report_ind is not triggered (i suppose that you are trying to catch the advertising indication by using a breakpoint), if indeed the new scanning procedure has started you wont be able to catch that advertising event via a breakpoint since your debugger is de-attached from your 580. Please check the above and if indeed you had disabled sleep and the proper functions are called when the corresponding commands are sent from UART check if the advertising device is actually advertising and can accept connections.
NO3: The dongle that is provided from dialog is not a generic dongle that you can connect to a windows machine and be recognized as a bluetooth module, its just a 580 with an ATMEL microcontroller that is used as a bridge to the USB port, and only accepts UART commands over GTL (a propriatery protocol). I suspect that a generic BLE module is what you would like, although i am not able to make a suggestion, i suppose that any BLE dongle that supports the 4.0 specification would do, however in most of our applications (testing) we are using android phones.
NO2: The DSPS example monitors the UART and serves the DSPS_TASK (send notifications and accept write commands from the central). When data are available in the UART an interrupt occurs the ISR is executed and the code takes care of the FIFO of the UART and handles the data properly, it doesn't poll the UART to consider this an additional task. You can study this implementation as an example.
Thanks MT_dialog
Thank you, MT
as for NO2, is the ISR you mentioned is UART2_Handler(void) in uart2.c and the DSPS_TASK for data received is uart2_rec_data_avail_isr? if so, where should I put the action_on_command() I defined ? do you mean that I should modify uart2_rec_data_avail_isr directly?
can you explain more on the DSPS_TASK ?
thank you very much!
当我阅读代码,我发现art2_env.rx.callback is assigned in uart2_read, and when RECEIVED_AVAILABLE the uart2_rec_data_avail_isr() is executed and the defined callback is executed. and then in uart2_rec_data_avail_isr() the callback pointer will be cleared. if my understanding is right? if so, does it mean that I need to call uart2_read to get the command received, rather than I send a command on PC and the action_on_command() is called?
Hi wenkangl,
The DSPS and the implemented debbuging mechanism are using different UARTS (there are two instances of the same UART module in the 580) therefore there are seperate ISR handlers for each UART. How to handle your interrupts and your data it depends on your application and the way you want to implement it. Regarding the DSPS_TASK (TASK_SPS_SERVER to be more exact) is the profile task of the DSPS device, you can find more info in the UM-B-038 Serial Port Service application document.
Yes your understanding is correct after the uart2 gets the data that you ve decalred the callback will be cleared, you just call the uart2_read() keep doing whatever you are doing and the interrupts will keep on comming when you ve got data in your UART, when the size of your data that you ve set is reached then your callback (the one you 've set when calling the uart read) will be called and notify you that the specified data have arrived and the UART interrupts will be disabled. That means that if your commands have a specified size you can set the size of each command when you are waiting for it, or you can specify a command format that will read the first byte as a command size (read one byte as size) and then set the callback according to that specific size command, or you can always wait for just one byte and wait for a terminal character of your command (indicate that the command is over), there are quite a few options how to implement this but as i ve mentioned above, it depends on how you want your implementation to be.
Thanks MT_dialog
Thanks MT,
so to monitor the UART, I have to call the uart2_read() frequently, and my solution to the size of the data packet is that, I use a fixed length packet (25 as indicated in the code), and the command will be pre-processed so that it is always of length of 25 (add 0 at the end of the packet, so that it is 25 of length). I am trying to get the central work.