CSR (Cambridge Silicon Radio) produces special chips for
BlueTooth devices. The chips appear to be fairly inexpensive, because the Chinese gentlemen offer miniature (somewhat larger than a sim card) Bluetooth
HC-04 handkerchiefs based on the
BC417143B chip (
BlueCore4 family, see [1]), which in Russia can be bought for only 6.6 dollars ( through dealextreme.com, see [2] and [3]).

By default, the FLASH memory of HC-04 contains software that allows you to connect any handheld (or phone, laptop, etc.) with a built-in microcontroller-based system (robot, Arduino board, any device on the microcontroller that has a TTL). port UART RS-232). Using the
CSR CASIRA BLUELAB SDK package (which contains working examples of Bluetooth programs), you can reprogram the HC-04 module yourself and create your own Bluetooth devices. The programmer and full-fledged hardware debugger for the module can be easily made by yourself; it is connected to the computer via the LPT port (see [4]). This article presents a brief description of the development tools for the CSR BlueCore chip family, which can be used to quickly begin writing your own programs for the HC-04 module.
')
I will not describe in detail the technical characteristics of the HC-04 module, since everything can be found out at the links from the dealextreme website [2]. I will write only about the most interesting. On board, the module has a 1 megabyte memory chip. It contains the control firmware and all settings (more on). The external 34 module contacts are displayed:
- hardware
UART , TXD, RXD, CTS and RTS signals.
-
PCM serial port (for digital audio input / output).
- two analog inputs / outputs
AIO .
-
RESET reset leg (it can not be connected anywhere).
- input voltage supply +3.3 volts, current consumption maximum 35 mA.
-
USB interface.
-
SPI interface, through which firmware is flashed and debugging takes place.
- 12
PIO digital input / output ports.
After powering the module (3.3 volts, maximum 35 mA), it can be detected as a wireless Bluetooth device with a serial COM port profile. That is, a serial port will appear on your PDA (phone, laptop, etc.) through which you can directly exchange data via TTL signals TX and RX of the standard
RS-232 port . Firmware HC-04 allows AT commands to change the data transfer rate over a wide range (from
1200 to
1382400 baud), and the speed setting changes are non-volatile, and are saved between power off. Thus, due to its small size and low price (in Russia you can buy for $ 6.6), the HC-04 module is already interesting as a convenient ready-made device for wireless communication.
However, as it turned out, for the HC-04 module, you can write programs yourself and write them to the chip’s memory. The review of these features is devoted to the main part of the article.
Development Toolkit
The programmer will have to do it yourself, because in Russia it is impossible to buy it, no one sells it. Glad that the scheme is quite simple, no problem to assemble yourself. The programmer is the simplest
LPT SPI interface .

Through this simple programmer, you can merge all the FLASH memory of the HC-04 module into binary files (using the
BlueFlash utility), view and edit the module and program settings (using the
PSTool utility). You can write firmware and debug programs (using the same LPT SPI) in the
xIDE development
environment . There are numerous examples of the source code of various Bluetooth devices, the necessary documentation in English. All these features are opened on the Windows operating system, if you install the CSR CASIRA BLUELAB SDK (the installation package takes about 55 megabytes, after installation it takes 310 megabytes).
The examples allow you to create Bluetooth devices of role A (something like Bluetooth wizards who themselves find Bluetooth devices and connect to them. It is impossible to find the role of role A by searching for wireless devices) and the role of B (Bluetooth device that can be found by searching for wireless devices). Using examples from the CSR CASIRA BLUELAB SDK, it is possible to organize data exchange between two HC-04 modules, in this case, one must realize the role A, and the other role B (the standard firmware that is recorded in the HC-04 at the factory, does not allow only role B is implemented in it.
Settings Store, Persistent Store
The memory of the HC-04 module, along with the firmware, contains many different parameters (such as the Bluetooth address, device name, transmitter output power, etc.), the so-called keys. This is not just a feature of the HC-04 module, as is the custom in the BlueCore architecture when programming applications. All keys can be viewed with the PSTool utility, modified if necessary (if you, of course, understand what you are doing) and saved to a
* .psr file that has a convenient text format. The key dump is done for quite a long time (my process took about 2 minutes), while the firmware does not stop working. All keys stored in the chip are divided by storage level. The levels are tied to the location of the settings (FLASH, RAM, ROM), as well as the time of creation (Implementation, Factory). The keys of which levels to display, choose in the menu Store (All (TIFR), Implementation Only (I), ROM Only ®, RAM Only (T), Factory Only (F), Not RAM (IFR)). If the same key is simultaneously defined at different levels and with different values, and it is selected to show all levels (All (TIFR)), then the value of the key stored at the highest level will be shown. Default key values are stored in ROM, the lowest level. Runtime keys are kept at the highest level, Transient (RAM). Several levels are immediately indicated by the abbreviations of the first letters of the levels, for example, IFR, TIFR. Read more about the levels of the Persistent Store in the document
blab-ug-008Pb_PSTool_User_Guide.pdf .
CSR BlueCore and SDK Libraries
In projects of examples xIDE, all subtleties are hidden far from the user's eyes in libraries. Libraries are divided into 3 classes:
- Foundation Libraries
- Support Libraries
- Profile Libraries
Foundation Libraries - the main functionality, low-level work with equipment. Supplied in binary form only, without source code. The header file for using the Foundation functions of the library is csr.h.
Support Libraries - provide connectivity support (RFCOMM, L2CAP and SCO). Header files and source code files are located in the folder
C: \ BlueLab \ src \ lib .
Profile Libraries - refer to BlueTooth profiles. Profiles are something like the purpose of a Bluetooth device (for example, a serial port, an audio device, a source and receiver of files, a USB interface, etc.). Header files and source code files are located in the folder C: \ BlueLab \ src \ lib.
The BlueCore chip has many different interfaces, data sources and receivers (Kalimba, PCM, SCO, RFCOMM, L2CAP, UART, Host, USB, HID, Region, File, Audio Notes), which with the help of libraries can be simply connected to each other and exchange data through streams. Some data sources and sinks (Kalimba) are related to BlueCore cores that have DSP on board. The BC417143B chip, mounted on the HC-04, belongs to the BlueCore4 family and has no DSP. See
CS-110275-UGP1_Implementing_Streams_in_BlueLab.pdf for details .
To start using the library, you need to include the necessary .h file with the #include directive and add the name of the required library to the project settings Project Properties -> Configuration Properties -> Build System -> Libraries - the names of the required libraries are specified in the input field, separated by a comma (without file extensions). Libraries can be rebuilt (the process is rather long!) By launching the BlueLab 41 shortcuts -> Rebuild -> VM libraries and DSP libraries.
Brief description of xIDE and the simplest application
BlueTooth device projects that a host can find through a search have _b suffix (for example, spp_dev_b). Projects that themselves work as a host, that is, they can connect other BlueTooth devices to themselves, have the suffix _a (for example, spp_dev_a). Devices with the suffix _a cannot be found by a host through a BlueTooth search for devices.
To run the project through xIDE, you need to go to the project folder (all the projects of the demo examples are in the
C: \ BlueLab41 \ apps \ examples folder) and double-click on the
* .xiw file (the Workspace settings are stored here, the project settings are stored in the
* .xip file ). The xIDE development environment will automatically start, where you can view the source code of the project and run the code for compilation and debugging. When you start debugging via LPT SPI, the chip type is automatically read, and the project is compiled for it. After compilation, the program is automatically poured into an external FLASH memory connected to the CSR processor (recall that for BlueTooth HC-04 modules, this is the BC417143B-IQN-E4 processor (BlueCore4-External device)), and the program is launched for execution. After stopping debugging, if you turn off and turn on the power again, the chip will be overwritten by a new compiled program that starts and starts working. The normal project is loaded, and the chip's memory is about a minute (and what did you want from the LPT port?).
You can write from scratch for HC-04 the simplest application, flashing LED. To do this, run xIDE, select Project -> New ..., specify the project type Bluelab -> Blank VM Project, enter any project name (for example, MyFirstBluelab), select the folder for the project location (everything is done by analogy, as in Visual Studio) and click OK. Then you need to create the main.c module file, and enter the text there:
#include <message.h><br>#include <pio.h><br><br> #define LED_1 (1<<1)<br><br>typedef struct <br>{<br> TaskData task;<br> uint16 change;<br>} ToggleTask;<br><br> static void MyHandler (Task t, MessageId id, Message payload)<br>{<br> uint16 change = ((ToggleTask *) t)-> change;<br> PioSet(change, PioGet() ^ change);<br> MessageSendLater (t, 0, 0, 500);<br>}<br><br> static ToggleTask toggle = { { MyHandler }, LED_1 };<br><br> int main ( void )<br>{<br> PioSetDir (LED_1, ~0);<br> MessageSend(&toggle.task, 0, 0);<br> MessageLoop();<br> return 0;<br>}
A brief description of the listing (see
CS-110344-UGP2_WritingBlueCoreApplication.pdf for details ):
- in the include block headers are included to support messages and I / O ports.
- the define operator sets the LED foot to be controlled.
- The ToggleTask structure sets the type for the toggle application task data store.
- subroutine MyHandler is a message handler that performs control of the LED. The algorithm is very simple. From the transferred structure of the task t, the value of the change parameter is read. There is the LED_1 LED mask, and the change parameter is used here simply as a demonstration of the storage and transmission of the running task. Calls to the PioSet and PioGet procedures ensure that the LED is set in the opposite state (if it was turned off, it turns on, and vice versa), the value of the change variable is used as a mask. The MessageSendLater procedure sends a new message to the task t after 500 ms.
- the declaration of a static variable toggle allocates memory for a variable of the ToggleTask structure and assigns values to its task and change fields.
- in the procedure code main PioSetDir configures PIO1 (LED_1) as an output.
- MessageSend sends the original message that the MyHandler handler receives.
- call procedure MessageLoop starts the delivery of messages between tasks. In MessageLoop, execution loops, and control never reaches operator Return 0.
Now, if you press
F7 , the project will compile. If you press
F5 , the program will automatically fill in the chip's memory and start execution (provided that you have the LPT SPI module connected and the HC-04 module is connected to it), and the LED on the PIO1 pin flashes at 1 Hz. At the same time, full-fledged debugging is available - in steps, with breakpoints, with viewing of variables, memory and processor registers. Breakpoints are set in the code as usual, by clicking the mouse to the left of the code text (a brown circle appears opposite the line where the breakpoint is set) - just like in Visual Studio. Read more about debugging in
CS-101500-UGP5_BlueLab xIDEuser guide.pdf .

The overall structure of the BlueLab application
The firmware application is based on tasks. Each task performs a specific function assigned to it. All tasks are performed as separate logical streams that do not block each other. The task scheduler is not preemptive, so it is important that all message handlers are executed to completion and not looped forever, otherwise the work of other tasks will be disrupted. Tasks exchange information with each other through messages. All tasks that an application creates are also included in a special top-level task, the so-called
application task (
application task ). This task responds to messages and controls the overall behavior of the application. Complex applications may contain several application tasks.
Messages (messages) are created and transmitted in the following form:
Task t, MessageId id, Message payload
Task t points to the recipient of the message; it is a pointer to the receiving task, for example & AppTask.
MessageId id identifies the message. The following message numbering system was adopted:
- the message that the task sends to itself begins with 0x00.
- System messages start at 0x8000.
- Messages sent to the task by a separate profile library begin with the base 0x7000, and the SPP library messages begin with 0x6f00.
Message payload - payload (data) transmitted in the message. Sometimes there is no payload in the message when only the message identifier is sufficient. In this case, the Message payload is NULL.
There is a set of functions to simplify the sending of messages, see
message.h and the corresponding documentation. The message handler for each task must process all messages addressed to it. The usual developer practice is to develop a code for handling messages that an application task accepts (application task). No need to write handlers for profile tasks and support tasks initialized from BlueLab or SDK libraries. Handlers for these tasks are already built into libraries and are selected after calling the appropriate Init function. The application task application must process messages from the libraries it initializes. The system message table is listed in file
CS-110344-UGP2_WritingBlueCoreApplication.pdf ,
Appendix A System Messages . The database table (the first byte of the message ID value) of the library messages is given in the same file,
Appendix B Library Message Bases . During debugging via debugger (LPT SPI or USB SPI) messages appear in the Output window, the Messages tab.
Tasks and messages allow the application developer to break all the necessary functionality into separate modules that work as different tasks, while you need to ensure the exchange of messages between tasks. All messages are queued and processed (transmitted) in the order received. The scheduler looks at the first message in the queue and, if necessary, sends this message as parameters to the corresponding task handler. After the message is passed to the handler, the MessageLoop function releases the payload of the transmitted message and proceeds to process the next message in the queue, or wait for a new message to appear in the queue.
You can display debug messages from the program code with the
printf statement. In this case, the Print Channel 0 tab opens in the Output window, and the printf output is printed there. The printf output works in real time while the firmware is running via a debugger on LPT SPI. In a real application, all printf statements must be removed, otherwise the application without a debugger will hang and not work (due to stack overflow). To remove the debug output, use the special DEBUG_PRINT_ENABLED compile time token and the #ifdef conditional compilation statements.
#define DEBUG_PRINT_ENABLED 1 // output resolution printf
DEBUG_PRINT_ENABLED can also be defined in the project properties, Build System -> Define symbols. An example of using DEBUG_PRINT_ENABLED is found in the sample application projects C: \ BlueLab41 \ apps \ examples \.
There are several problems encountered when experimenting with xIDE. If the program is flushed to the chip, but does not want to start debugging with the error “The app reads from disk appears to be invalid.”, Then this can happen when the project folder has a complex path that includes spaces and / or Russian letters. For example, your project is located in the
c: \ Documents and Settings \ User \ Admin \ My Documents \ LEDFlashing \ folder . Change the placement of the project to a simpler one, for example
c: \ temp \ LEDFlashing , and the debugger will start normally. With russification, xIDE has certain problems - the text stored in the code in Russian, when re-opened is displayed with krakozyabrami, so write comments in Russian in the code will not work. Sometimes it is strongly hampered by the compilation of Kaspersky anti-virus (the process is very slow). It is advisable to configure an exception scan of objects on the path
C: \ BlueLab41 \ tools \ *. Exe . The settings will take effect for some reason only after restarting Windows.

Dictionary
HCI Host Controller Interface
LC Link Controller
xIDE programming environment for BlueCore CSR processors
VM Virtual Machine - as I understand it, it is the execution of the functions of a host processor on an embedded RISC microprocessor. There are Classic VMs, and there are Native VMs that differ in architecture and execution speed. See
CS-122636-AN-1classicvsNative.pdf .
VM API is a non-DSP application programming interface.
BlueCore is the name of the CSR Bluetooth chip line. The HC-04 uses a BlueCore4 chip.
payload payload. In the context of message passing, the data transmitted in the message.
application task application task - a required element of any BlueCore firmware program.
preemptive ,
pre-emptive in this context, crowding out multitasking. For each task, a limited time interval of execution is allocated, which guarantees that it is impossible to block the execution of all tasks if one of the tasks is blocked (for example, it enters an infinite loop).
not preemptive in this context means multi-tasking, when tasks are performed one after another, and each task is performed in order from beginning to end. In this case, locking in one task can stop the execution of all tasks. This is exactly the scenario for performing tasks that is used in the CSR BlueCore and SDK libraries.
L2CAP Logical Link Control and Adaptation Protocol
Persistent Store data storage of installations in the form of records (keys)
TIFR Transient (RAM), Implementation, Factory, ROM - Persistent Store locations, meaning all possible placement options. The keys installed during the production of the product are located in the Factory and Implementation areas, the keys that are formed during the operation of the product are placed in Transient (RAM).
IFR Implementation, Factory, ROM - Persistent Store locations that do not use RAM.
BCSP BlueCore Serial Protocol is a protocol through which all debugging tools communicate with the BlueCore chip (at the physical level this happens via the BlueCore SPI interface).
Kalimba DSP - Some BlueCore chips (BlueCore3 and BlueCore5) have DSP. Unfortunately, there is no DSP in the BC417143B processor of the HC-04 module. There is a special API and corresponding library for working with Kalimba DSP.
Links
1 .
General description of the BlueCore4-External device chip on the CSR company website .
2 Bluetooth module HC-04 on the Dealextreme website .
3 How to buy at dealextreme .
4 Description of LPT SPI programmer and debugger, documentation links, CSR CASIRA BLUELAB SDK, firmware of the module HC-04 .
5 The source code of the project xIDE for the module HC-04, flashing LED on the port PIO1 .