BLE-NRF51822 tutorial 3-SDK framework profiling. BLE-NRF51822 tutorial 3-SDK program framework profiling nordicBLE technology exchange group 498676838 this lecture introduces the framework and won't involve too much code details. 51822 of the official SDK is actually no framework according to the BLE-NRF51822 tutorial 3-sdk program framework analysis
NordicBLE technology exchange group 498676838
This section describes the framework and does not involve too much code details.
51822 of the official SDKs are actually not framework-resistant. What is a framework? for example, TI's ble sdk has an operating system abstraction layer (OSAL) which is a round training scheduling. You need to create tasks according to their methods.
In essence, SDK 51822 only provides various calling interfaces, such as enabling the initialization protocol stack, initializing some hardware functional modules, starting broadcasting, and initiating links. It is up to you to use these interfaces. However, firmware development generally initializes various resources in a similar process, and 51822 is no exception. The main function in the sdk as a slave is similar to the following steps:
Take the official serial port BLE as an example:
Int main (void)
{
Leds_init (); // not required, but it is used in this example.
Timers_init (); // not required, but it is used in this example.
Buttons_init (); // not required, but is used in this example
Uart_init (); // not required, but the serial port is used in this example.
Ble_stack_init (); // required
Gap_params_init (); // required
Services_init (); // related to the self-created service. different service details are different, but generally
// The process is basically the same. you can directly use the official example to modify some parameters.
Advertising_init (); // broadcast data initialization, required
Conn_params_init (); // It depends on the situation. if you do not need to negotiate the connection parameters after the connection, the initialization is also // optional
Sec_params_init (); // security parameter initialization. If this parameter is not used for pairing binding, it can not be initialized.
Advertising_start (); // enable broadcast, required
// Enter main loop
For (;;)
{
Power_manage (); // enter sleep
}
}
We can see that only these five functions are necessary at the core. You can remove all the other code, as long as the five function devices can run the same way, the mobile phone can also find the device and communicate with the device.
This initialization method can be said to be no different from our general single-chip microcomputer development.
After initialization. In the past, we developed bare-board single-chip microcomputer and started to execute some recurring tasks in a while loop. later, in order to reduce power consumption, we started) add a sleep code in the loop to make the chips sleep when they are not working, and wake up with interruptions to process the coming things.
The above 51822 main function is also a for {} loop, power_manage (); internal code is actually a sleep command. The Main function is gone by now, and it is actually a cyclic sleep. You cannot see any tasks here, but only sleep. As you can imagine, 51822 of the protocol stack implementation should be based on "event wake up", that is, sleeping when there is nothing, waking up work when there is something, and then continuing to sleep. So where are the codes used to process events?
How does the protocol stack work?
Where can I add a service?
Where is the data sent by the mobile phone?
How can I send data to my mobile phone?
The following explains these questions one by one:
How does the protocol stack work?
To understand how the protocol stack works, we must first understand that 51822 of the protocol stack is event-driven based on 100%. That is to say, any data sent from the protocol stack to the app is event-based.
For example, a device receives a connection request from a mobile phone or data sent from a mobile phone. The protocol stack first receives the data and then processes it. then, it packs the data (such as link requests or common data) into a struct and attaches the event ID, for example, BLE_GAP_EVT_CONNECTED or BLE_GATTS_EVT_WRITE respectively tell the upper-layer app that the event struct represents.
For example, BLE_GAP_EVT_CONNECTED indicates a link event. The data contained in this event struct is data such as connection parameters.
BLE_GATTS_EVT_WRITE indicates the write event. The data in the structure is the data written to the board by the peer device (such as a mobile phone.
For example, the dispatch dispatching function in the uart demo
Static void ble_evt_dispatch (ble_evt_t * p_ble_evt)
{
Ble_conn_params_on_ble_evt (p_ble_evt );
Ble_nus_on_ble_evt (& m_nus, p_ble_evt );
On_ble_evt (p_ble_evt );
}
Ble_evt_dispatch is called when any BLE-related event is thrown to the app on the protocol stack. In this way, the event is thrown to each service function or processing module. here, the event is thrown
Connection parameter management handler ble_conn_params_on_ble_evt
Event Processing function of Uart service ble_nus_on_ble_evt (nus is Nordicuart server)
General Event Processing function on_ble_evt
Different events are distinguished by IDs in the event structure ble_evt_t. The difference is that the event processing function usually only processes the events of their own feelings. let's take a look at the internal functions of the ble_nus_on_ble_evt event processing function.
Voidble_nus_on_ble_evt (ble_nus_t * p_nus, ble_evt_t * p_ble_evt)
{
If (p_nus = NULL) | (p_ble_evt = NULL ))
{
Return;
}
Switch (p_ble_evt-> header. evt_id)
{
CaseBLE_GAP_EVT_CONNECTED:
On_connect (p_nus, p_ble_evt );
Break;
CaseBLE_GAP_EVT_DISCONNECTED:
On_disconnect (p_nus, p_ble_evt );
Break;
CaseBLE_GATTS_EVT_WRITE:
On_write (p_nus, p_ble_evt );
Break;
Default:
// No implementation needed.
Break;
}
}
We can see that the uart service event processing function only cares about three events, link events, disconnection events, and write events (send data to the peer device ), different events are implemented by developers. For example, for connection events, the connection handle in the event structure should be recorded, because subsequent BLE operations are basically based on the connection handle (which can be seen as the channel ID for communication between two devices, is actually the concept of data access address in the link layer ).
PS: Events are sent to dispatch for distribution to various services and modules. for details about how to deliver underlying events to the dispatch function, refer to the 51822 tutorial-protocol stack overview tutorial in the group announcement.
Solve the so-called event-driven problem: if you want to create a service, where can I add it?
In the initialization process of the main function, there is a services_init (); the internal function is to add services, add feature values and other code.
The function registers the callback function nus_data_handler (which prints data from the computer serial port when the mobile phone sends data to the board) and then executes the real initialization function ble_nus_init.
The function calls the api interface of the protocol stack sd_ble_gatts_service_add to add services.
You will also call the sd_ble_gatts_characteristic_add api interface of the protocol stack to add feature values.
The hierarchies are as follows:
That is to say, to complete a complete service build function, as long as sd_ble_gatts_service_add () and sd_ble_gatts_characteristic_add () are two core functions.
Generally, you do not need to write services from the beginning. Instead, assign a value to the official services_init () function and make some minor changes. For example, you can modify the uuid, read/write attributes, and add more feature values. Few changes are required.
The last two problems are solved: where is the data sent by the mobile phone? How can I send data to my mobile phone?
To clarify these two questions, let's take a look at some of the frequently asked questions in the group:
Q:
In which function is the data sent from the mobile phone to 51822 devices,
A:
No function
The protocol stack throws an event struct.
The received data is in the Struct.
Q:
Is the Bluetooth Upload function the same as the send function? Are all service API functions?
A:
Only the upload function is used by the server to send data to the client.
Sending data is a data event structure on the protocol stack after the Bluetooth chip receives the data. For details, see the data of various event handlers in the dispatch dispatcher in the sample code.
Q:
Sd_ble_gatts_hvx () is the Bluetooth sending function. do you know the Bluetooth receiving function?
A:
There is no receiving function for Bluetooth, and Bluetooth data is received at the underlying layer. after receiving the function, an event is returned to the ble_evt_dispatch distribution function at the upper layer, which distributes the event to various services or event processing functions. The server or handler will capture whether the write event caseBLE_GATTS_EVT_WRITE exists and then process it accordingly. All received data is in the returned event structure.
In fact, the above three problems have been basically solved. As a slave device, BLE has an API interface for sending data to mobile phones, that is, sd_ble_gatts_hvx (), you can use parameters to set whether to send the notification in the form of notification or indication (the notification does not need to be replied to for confirmation, and the indication is required ). However, the data sent by the mobile phone does not receive the function. why? Because the protocol stack is event-driven! Therefore, after receiving the data, the protocol stack will send a write event to the upper-layer app (indicating that the peer device has written data), and the written data is in this event structure. We just need to extract it. Therefore, no function API is received.
On the other hand, it can also explain why data functions are not received. This is because "synchronous" is actively called when sending data. However, when receiving data, "asynchronous" means that the data may come at any time. instead of calling a function all the time, wait for the data to arrive. if the data doesn't come, nothing can be done. Therefore, receiving is event-driven. Data can be transferred for processing.
Use a diagram to explain:
If you still think it is a bit abstract, go back to the front and check the protocol stack operation explanation section. We should better understand the so-called event-driven
Mongonordicble technology exchange group 498676838 introduces the framework and does not involve too much code details. 51822 of the official SDK actually has no framework...