From d8392f72c362288b594f5c34b05f6bfee33a1411 Mon Sep 17 00:00:00 2001 From: Andreas Anderberg Date: Thu, 8 Feb 2024 14:01:07 +0100 Subject: [PATCH] Add more documentation --- README.md | 44 +++++++++++++++++++++++----- examples/README.md | 63 ++++++++++++++++++++++++++++++++++++++++ examples/http_example.c | 2 +- examples/port/README.md | 22 ++++++++++++++ images/cmake-gui.png | Bin 0 -> 44077 bytes zephyr/README.md | 56 +++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 examples/README.md create mode 100644 examples/port/README.md create mode 100644 images/cmake-gui.png create mode 100644 zephyr/README.md diff --git a/README.md b/README.md index 6a944d8..4c6e165 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,23 @@ # ucxclient + This repo contains a small footprint AT command client for talking to the following u-blox u-connectXpress short-range modules: + * NORA-W36. -There are two levels of APIs included in this repo; the lower [uAtClient API](#uatclient-api) and the upper [u-connectXpress API](#u-connectXpress-api) +The client can run on both bare-metal and OS systems using a tiny porting layer (see [Porting and Configuration](#porting-and-configuration)) + +There are two levels of APIs included in this repo; the lower [uAtClient API](#uatclient-api) and the upper [u-connectXpress API](#u-connectxpress-api). + +If you need even more features you can checkout [ubxlib](https://github.com/u-blox/ubxlib) which uses the ucxclient for communicating with the new u-connectXpress modules. **Please note: The code in this repo is in experimental status and changes to the APIs are to be expected.** ## uAtClient API + This API contains an AT client implementation that handles transmission of AT commands, reception and parsing of AT responses and URCs. You will find the uAtClient API in the [inc/](inc) directory. ### Example + ```c #include "u_cx_at_client.h" @@ -34,8 +42,8 @@ void main(void) .pUrcBuffer = &urcBuf[0], .urcBufferLen = sizeof(urcBuf), .pStreamHandle = NULL, - .write = uCxAtWrite, - .read = uCxAtRead + .write = myWriteFunction, + .read = myReadFunction }; uCxAtClient_t client; @@ -72,11 +80,13 @@ void main(void) ``` ## u-connectXpress API + This API is a higher level API that that simplifies communication with new u-connectXpress u-blox modules (only NORA-W36 at the moment). Using this API eliminates the need of manually sending AT commands to the module. You will find the u-connectXpress API in the [ucx_api/](ucx_api) directory. ### Example + ```c #include "u_cx_at_client.h" #include "u_cx.h" @@ -107,20 +117,40 @@ void main(void) ``` ## Porting and Configuration + All configuration and porting config is located in [inc/u_cx_at_config.h](inc/u_cx_at_config.h). Make a copy of this file and place it in your code base where you can modify each config to your likings. When compiling you can specify the name of this local file with `U_CX_AT_CONFIG_FILE` (for GCC you could pass `-DU_CX_AT_CONFIG_FILE=\"my_u_cx_at_config.h\"`). ### Minimum Porting -Some things are not required for successfully running the AT client (such as U_CX_PORT_PRINTF for logging, U_CX_AT_PORT_ASSERT), but the following is required: + +Some things are not required for successfully running the AT client (such as U_CX_PORT_PRINTF for logging, U_CX_AT_PORT_ASSERT), but the following are required: | Function | Description | | -------- | ----------- | | U_CX_PORT_GET_TIME_MS | Must return a 32 bit timestamp in milliseconds.| -| read() | Passed as argument to uCxAtClientInit(). Should read data from UART with a timeout in millisec. Must return the number of bytes received, 0 if there is no data available within the timeout or negative value on error. | -| write() | Passed as argument to uCxAtClientInit(). Should write data to the UART. Must return the number of actual bytes written or negative number on error. | +| read() | Passed as argument to uCxAtClientInit(). Should read data from UART with a timeout in millisec. Must return the number of bytes received, 0 if there are no data available within the timeout or negative value on error. | +| write() | Passed as argument to uCxAtClientInit(). Should write data to the UART. Must return the number of actual bytes written or negative number on error. | + +For systems running RTOS you will also need to port the mutex API below - for bare-metal systems you can use [examples/port/u_port_no_os.h](examples/port/u_port_no_os.h): + +| Define | Example (Posix) | Description | +| -------- | --------------- | ----------- | +| U_CX_MUTEX_HANDLE | `pthread_mutex_t` | Define this to the mutex type of your system. | +| U_CX_MUTEX_CREATE(mutex) | `pthread_mutex_init(&mutex, NULL)` | If your system need to call a function before the mutex can be used, then define it here. | +| U_CX_MUTEX_DELETE(mutex) | `pthread_mutex_destroy(&mutex)` | If your system has a function to de-allocate a mutex, then define it here. | +| U_CX_MUTEX_LOCK(mutex) | `pthread_mutex_lock(&mutex)` | Define this to corresponding "lock"/"take" function of your system. No return value is expected (any return value will be ignored). | +| U_CX_MUTEX_TRY_LOCK(mutex, timeoutMs) | `uPortMutexTryLock(&mutex, timeoutMs)`1 | Define this to a function that tries to lock/take the mutex but with a timeout `timeoutMs` in millisec. Must return 0 if the mutex is successfully taken/locked and can return any negative value on timeout. | +| U_CX_MUTEX_UNLOCK(mutex) | `pthread_mutex_unlock(&mutex)` | Define this to corresponding "unlock"/"give" function of your system. No return value is expected (any return value will be ignored). | + +1 See [examples/port/u_port_posix.c](examples/port/u_port_posix.c) + +### Example Ports + +You will find some example ports in [examples/port](examples/port). These ports are used by the [example code](examples/README.md) and you will find more information in [examples/port/README.md](examples/port/README.md) + +## Disclaimer -# Disclaimer Copyright © u-blox u-blox reserves all rights in this deliverable (documentation, software, etc., diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..3af38c7 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,63 @@ +# Examples + +This directory contains application examples of how to use ucxclient. The examples make use of the [example ports](port/README.md). + +| Files | Description | +| -------------------- | ----------- | +| http_example.c | Example of doing a HTTP GET request using the uCx API. | +| http_example_no_os.c | Same example as http_example.c but illustrating how it could be done on a bare-metal system with no OS. | + +## Building + +To build all the examples on a Linux based system, just execute the following in repo root if you prefer Makefile: + +```sh +> cmake -S . -B build -G "Unix Makefiles" +> make -C build +``` + +or if you prefer Ninja: + +```sh +> cmake -S . -B build -G "Ninja" +> ninja -C build +``` + +## Running + +### http_example + +If you have built http_example using the steps above it will be built for Linux and located in `build/http_example`. +To start it you will need to pass some arguments: + +``` +http_example + device: the UART device that is connected to a u-connectXpress module + SSID: the Wi-Fi SSID to connect to + WPA_PSK: the Wi-Fi WPA PSK +``` + +Example: + +```sh +> build/http_example /dev/ttyUSB0 MySSID MyWiFiPasswd +``` + +### http_example_no_os + +Just like http_example this example will also be compiled for Linux, but in this case the UART device, Wi-Fi SSID and PSK are configured using defines. +To set these defines using CMake you can either use `cmake-gui`: + +![cmake-gui](/images/cmake-gui.png) + +or from command line: + +```sh +> cmake -S . -B build -D U_EXAMPLE_UART="/dev/ttyUSB0" -D U_EXAMPLE_SSID="MySSID" -D U_EXAMPLE_WPA_PSK="MyWiFiPasswd" +``` + +Now you should be able to start the example using: + +```sh +> build/http_example_no_os +``` diff --git a/examples/http_example.c b/examples/http_example.c index 766adf5..ee2caa1 100644 --- a/examples/http_example.c +++ b/examples/http_example.c @@ -15,7 +15,7 @@ */ /** @file - * @brief Linux example for doing HTTP GET request using NORA-W36 + * @brief Example of how to do a HTTP GET request using the uCx API * * This example will: * - Setup WiFi diff --git a/examples/port/README.md b/examples/port/README.md new file mode 100644 index 0000000..a73561a --- /dev/null +++ b/examples/port/README.md @@ -0,0 +1,22 @@ +# Port Examples + +This directory contains example ports that you can either use out-of-box or use as inspiration. + +| Files | Description | +| ------------- | ----------- | +| u_port.h | A common API mainly for being able to run the [example code](/examples/README.md) using any of the ports. | +| u_port_posix | A Linux port example using Posix threads. | +| u_port_no_os | A "no OS" port example to illustrate how ucxclient could be ported to a bare-metal system. The UART and time porting layer is using Linux API for this example so you will need to adjust it for your specific target. | +| u_port_zephyr | A Zephyr port example. You will find details on how to use it in [/zephyr/README.md](/zephyr/README.md). | + +## Using an Example Port + +You can tell ucxclient which port to use by using the following defines during build: + +| Port | Define | +| ------------- | -------------- | +| u_port_posix | `U_PORT_POSIX` | +| u_port_no_os | `U_PORT_NO_OS` | +| u_port_zephyr | No define needed; it will be selected automatically if you use ucxclient as a Zephyr module (see [/zephyr/README.md](/zephyr/README.md)). | + +You will also need to add corresponding .c file to your build (not needed for Zephyr). diff --git a/images/cmake-gui.png b/images/cmake-gui.png new file mode 100644 index 0000000000000000000000000000000000000000..00aaa09a4da52d2bf4d39924d6b9286c55400849 GIT binary patch literal 44077 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�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
y?sUAmu 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 CyKa5} literal 0 HcmV?d00001 diff --git a/zephyr/README.md b/zephyr/README.md new file mode 100644 index 0000000..2387aba --- /dev/null +++ b/zephyr/README.md @@ -0,0 +1,56 @@ +# Zephyr Module + +ucxclient can be used as a Zephyr module for easy integration to your Zephyr application. + +## Adding ucxclient to Your Zephyr App + +There are several ways of including ucxclient to your Zephyr application. + +### Using `west.yml` manifest + +If you use a `west.yml` manifest for your application then you can add ucxclient as to the list of projects like this: + +```yml +manifest: + remotes: + - name: zephyrproject-rtos + url-base: https://github.com/zephyrproject-rtos + - name: u-blox + url-base: https://github.com/u-blox + + projects: + - name: zephyr + remote: zephyrproject-rtos + revision: main + + - name: ucxclient + remote: u-blox + repo-path: ucxclient.git + revision: master +``` + +There is a very useful Zephyr example app illustrating how to create folder structure etc for a Zephyr application using a `west.yml` manifest file available here: +[https://github.com/zephyrproject-rtos/example-application](https://github.com/zephyrproject-rtos/example-application) + +### Using `ZEPHYR_MODULES` CMake Variable + +With this method you need to clone ucxclient manually or use git submodule or similar. +After that you need to add the path of ucxclient to the `ZEPHYR_MODULES` CMake variable. +This can be done in several ways as described here: +[https://docs.zephyrproject.org/latest/develop/modules.html#without-west](https://docs.zephyrproject.org/latest/develop/modules.html#without-west) + +## Config + +To build ucxclient with your Zephyr application you must add the following to your `prj.conf`: + +```ini +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_RING_BUFFER=y +CONFIG_UCXCLIENT=y +``` + +The current Zephyr port only support the interrupt driven UART API. + +Further configuration of ucxclient are also possible. +Use [menuconfig](https://docs.zephyrproject.org/latest/build/kconfig/menuconfig.html) to view and configure these.