Part Number: CC2340R5
Other Parts Discussed in Thread: SYSCONFIG
Dear E2Ers,
following the CC2340 threads from the early preview days, I have noticed that some users are requesting an example of a simple BLE <<>> UART bridge. Given the very innovative, efficient and elegant nature of this new single-core BLE platform (hardware and software-wise), there might be some confusion (including in myself!) on how to fully leverage its architecture and work around its limitations. As you probably know, previous-generations TI devices like the CC254X and the CC265X have been utilized in the very popular BLE <<>> UART bridge modules/breakouts, usually with a firmware that also includes an AT-command parser for configuration (which is out of this example's scope and that is up to you to implement). These bridges are useful also because they may be tested and used by anyone, with some freely-available BLE terminal apps for smartphones - like the excellent Serial Bluetooth Terminal from Kai Morich, which also supports earlier BT versions - that support by default the custom (unlike the standard Serial Port Profile in pre BT4.0) BLE <<>> UART profiles of the most popular bridges on the market. These are also based on devices from other vendors (the app I just mentioned supports TI, Nordic, Microchip and Telit and you can also customize your own). This way, you don't need to develop (and maintain) a custom app or understand BLE at all as a user, if you just need basic functionality.
INTRODUCTION
Like all examples, this serves as a starting point and, in order to maximize its usefulness not just intrinsically, but also comparatively, I wanted to implement it by modifying as litle as possible the official TI Data Stream example, so that you can easily figure out the differences. This has been done by commenting out with a "//+++" the unnecessary code and by adding a "//+++ comment" to the modified or added lines, so that you can easily spot the differences. All of the Data Stream Menu Module calls have been commented out, in order to produce the simplest and cleanest possible in/out terminal output, but you can uncomment the logging messages (I have left the Menu Module header includes uncommented for this reason) if you need to troubleshoot your connection (EDIT: I'm used to devices with multiple UARTs, the CC2340R5 only has one and it is grabbed by the Menu Module through the Display driver, so you can't have both).The way it works is very simple: just connect to the Data Stream device in the phone BLE terminal, open up another terminal on your desktop and connect to the virtual serial port (115200 8N1, the same way that you would do with the official Data Stream example, the CCS terminal is fine, only remember to toggle the command input field to send data) and exchange data between the two. Just for the sake of output elegance, I have added a \n to the pure UART data stream, since The CCS terminal is responsible for the \r after the sent string. Remember, if it's not already by default in the phone app, to set Newline CR+LF for Receive and Auto (same as receive) for Send (and disconnect/connect, otherwise the changes aren't applied), so that the intended clean terminal output is achieved both ways.
OUTLINE OF THE MODIFICATIONS, IN NO PARTICULAR ORDER:
1) commented out all the Menu Module (EDIT: initialization and) outputs (and conditions) which are mainly logs, except for the actual echoed capitalized/decapitalized output (which is obviously also commented out and should be left that way);
2) commented out all the LED activity and its conditions;
3) suppressed/changed the characteristics and their attributes. Unlike the original Data Stream profile/service, which is based on two characteristica (DataIn and DataOut), this modified version only uses one, that, for comparison purposes is kept as DataIn. This is because that's the way the original custom profile for the TI devices was implemented in the first place (not by TI, I suspect). This is not necessarily the way it should be done, it might seem like it restricts operation to a half-duplex UART emulation, but I suspect that a strict full-duplex implementation over a single BLE radio connection might not even be theoretically possible (but I might be wrong). In any case, this is the way the custom profile was implemented and how it can work out-of-the-box. This, of course, includes modyfing the characteristic declaration, the attribute table and the permissions (so that they match the said custom profile);
4) the individual client characteristic configuration check mechanism is kept in place - only now it is related to the dataIn characteristic and not to the dataOut one - but it's kind of pointless if using the phone terminal app, which, by default, turns the notifications on and doesn't allow you to switch them off. Strangely, the original Data Stream example, unlike this one, limits itself to one single BLE connection in the Sysconfig settings;
5) in Sysconfig, increased the maximum number of connections from one to two. By the way, I want to make it clear that this example can (and perhaps should, for educational purposes) be used also with a BLE generic scanning app such as BLE Scanner, which is often recommended in TI's BLE documentation. If you have two smartphones you can enable/disable notifications on the characteristic an see that the value of dataIn is not updated in the latter case. To figure out how it works, place a breakpoint anywhere inside the for cycle in data_server.c >> line 414 and disable notifications and you will see that it skips it altogether (while if they are enabled the apple will stop and the connection will time out);
6) utilized a callback for the non-blocking UART reads (an initial one and then repeatedly in its own callback). Remember (and this is crucial), that this function, which has a BLE stack call nested in it, would be called from an interrupt context (and not from within a task) and this is not allowed by the stack - presumably for priority and timing reasons - which would then make the application abort and crash. That's why the call is invoked in a "sendDataOverBLE()" wrapper function as the argument of the BLEAppUtil_invokeFunctionNoData() function, so that it is called from a task context. The UART utilizes a global buffer, together with a global length variable, for simplicity, without allocating anything on the heap (through the BLEapp malloc APIs, which, if I understand correctly, automatically free that memory). I think that further clarification of exactly what can be done and how with interrupts - given the complexity of the SDK/FreeRTOS/ICall/BLEStack real-time interactions in the single core - would be very welcome and I will soon be posting a few questions related to this topic and specifically to the BLEAppUtil_invokeFunction() both in its NoData and plain version;
7) the UART write on BLE data reception is obviously carried out plain-vanilla, without using the Menu Module APIs;
8) also remember that the TI base UUID must be changed, it's mandatory in the code and optional for the full UUID (since the service and characteristics would be discovered anyway during service discovery) in Sysconfig (RF Stacks >> BLE >> Broadcaster Configuration >> Advertisement Set 1 >> Advertisement Data 1 >> UUID 0 (128-bit More) and set to 0xFB349B5F80000080001000000EFF0000 (byte order must be reversed);
9) in the original example, the /common/Profiles/data_stream/data_stream_profile.c/h and the /common/Services/data_stream/data_stream_server.c/h files are linked to the SDK folders and the links must be deleted, so that local copies have been made in order to keep the original files unchanged and the Include paths have also been modified.
The declarations, definitions and some other code chunks are intentionally not organized in an optimal way and certain blocks might seeem redundant, but again, I wanted to preserve as much of the original Data Stream example structure and code as possible, for clarity. I recommend that, when studying this example, you also go through the SimpleLink Academy Data Stream exercise again - this also helps you to understand how to operate with the new BLEapp framework - and make your own modifications - a BLE/UART port configuration change parser could be a good idea, or a way to control your application (perhaps using the GPIOs/LEDs alternatively both by UART and BLE - it's available here:
dev.ti.com/.../node
LINKS
Below you will find the download links to the two different versions of this modified Data Stream example, the first one based on the earlier 7.10.00.35 SDK and the second on the latest 7.20.00.29. Please take notice that, when building the example (even the original one) with this latest release, there will be a warning about an invalid path (a directory that is in the project template is missing in the latest SDK) but just ignore it, it will build successfully and won't have any operational impact, certainly not for its educational purposes. TI is already aware of this glitch and it will be corrected in the future. It's a good idea that you use the handy CCS "select the two projects (original and modified) >> right-click them in Project Explorer >> Compare >> With Each Other" feature to figure out the differences in the files:
DISCLAIMER
The modified code is provided as is and should only be used for its intended educational purposes, since it hasn't been tested properly. Licenses, warnings and disclaimers from the original TI example are left untouched and I take no responsibility whatsoever for any IP breach or damage inadvertently and unintentionally caused by it. TI is free to modify, amend, move and take down the code and links from the forum or ask me to do it and I will comply promptly.
Please take all of the above with a grain of salt as I too am new to this platform, I suggest that an expert TIer double checks everything and/or suggests/makes the proper modifications. I hope this is welcome and useful.
Kudos TIers for bringing on this new groundbraking connected MCU HW & SW platform and thanks for your great support.
Ciao from Rome, Italy
Stefano
PS this has been built and quickly tested on a preview Rev.A CC2340 LaunchPad - my Rev.B one is currently in testing and I can't touch it -, which hosts an experimental CC2340R5 part, using the latest CCS v. 12.4.0.00007 and Sysconfig 1.17.0. I know it shouldn't be used with the new SLLPF3 SDKs but they still build and load unmodified for this purpose and I don't see why the examples shouldn't on the new public LaunchPad, but please double check.
7.10.00.35 SL LP F3 SDK Version:
data_stream_LP_EM_CC2340R5_freertos_ticlang_UART_TO_BLE_07_10_00_35.zip
7.20.00.29 SL LP F3 SDK Version:
data_stream_LP_EM_CC2340R5_freertos_ticlang_UART_TO_BLE_07_20_00_29.zip