Merge pull request #3510 from ARMmbed/release-candidate

Release candidate for mbed-os-5.3.2
mbed-os-5.3 mbed_lib_rev133
Martin Kojtal 2017-01-04 13:11:51 +01:00 committed by GitHub
commit 2885c1b41e
1312 changed files with 20912 additions and 17074 deletions

View File

@ -40,7 +40,7 @@ void queue_isr() {
myled = !myled;
}
void queue_thread(void const *argument) {
void queue_thread() {
while (true) {
queue.put((uint32_t*)QUEUE_PUT_THREAD_VALUE);
Thread::wait(THREAD_DELAY);
@ -50,7 +50,8 @@ void queue_thread(void const *argument) {
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(queue_thread, NULL, osPriorityNormal, STACK_SIZE);
Thread thread(osPriorityNormal, STACK_SIZE);
thread.start(queue_thread);
Ticker ticker;
ticker.attach(queue_isr, 1.0);
int isr_puts_counter = 0;

View File

@ -38,7 +38,7 @@ typedef struct {
Mail<mail_t, QUEUE_SIZE> mail_box;
void send_thread (void const *argument) {
void send_thread () {
static uint32_t i = 10;
while (true) {
i++; // fake data update
@ -54,7 +54,8 @@ void send_thread (void const *argument) {
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(send_thread, NULL, osPriorityNormal, STACK_SIZE);
Thread thread(osPriorityNormal, STACK_SIZE);
thread.start(send_thread);
bool result = true;
int result_counter = 0;

View File

@ -77,10 +77,9 @@ bool manipulate_protected_zone(const int thread_delay) {
return result;
}
void test_thread(void const *args) {
const int thread_delay = int(args);
void test_thread(int const *thread_delay) {
while (true) {
manipulate_protected_zone(thread_delay);
manipulate_protected_zone(*thread_delay);
}
}
@ -90,8 +89,11 @@ int main() {
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);
Thread t2(osPriorityNormal, STACK_SIZE);
Thread t3(osPriorityNormal, STACK_SIZE);
t2.start(callback(test_thread, &t2_delay));
t3.start(callback(test_thread, &t3_delay));
while (true) {
// Thread 1 action

View File

@ -40,7 +40,7 @@ MemoryPool<message_t, QUEUE_SIZE> mpool;
Queue<message_t, QUEUE_SIZE> queue;
/* Send Thread */
void send_thread (void const *argument) {
void send_thread () {
static uint32_t i = 10;
while (true) {
i++; // Fake data update
@ -56,7 +56,8 @@ void send_thread (void const *argument) {
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(send_thread, NULL, osPriorityNormal, STACK_SIZE);
Thread thread(osPriorityNormal, STACK_SIZE);
thread.start(send_thread);
bool result = true;
int result_counter = 0;

View File

@ -56,8 +56,8 @@ volatile int change_counter = 0;
volatile int sem_counter = 0;
volatile bool sem_defect = false;
void test_thread(void const *delay) {
const int thread_delay = int(delay);
void test_thread(int const *delay) {
const int thread_delay = *delay;
while (true) {
two_slots.wait();
sem_counter++;
@ -81,9 +81,13 @@ int main (void) {
const int t1_delay = THREAD_DELAY * 1;
const int t2_delay = THREAD_DELAY * 2;
const int t3_delay = THREAD_DELAY * 3;
Thread t1(test_thread, (void *)t1_delay, osPriorityNormal, STACK_SIZE);
Thread t2(test_thread, (void *)t2_delay, osPriorityNormal, STACK_SIZE);
Thread t3(test_thread, (void *)t3_delay, osPriorityNormal, STACK_SIZE);
Thread t1(osPriorityNormal, STACK_SIZE);
Thread t2(osPriorityNormal, STACK_SIZE);
Thread t3(osPriorityNormal, STACK_SIZE);
t1.start(callback(test_thread, &t1_delay));
t2.start(callback(test_thread, &t2_delay));
t3.start(callback(test_thread, &t3_delay));
while (true) {
if (change_counter >= SEM_CHANGES or sem_defect == true) {

View File

@ -32,7 +32,7 @@ const int SIGNAL_HANDLE_DELEY = 25;
DigitalOut led(LED1);
int signal_counter = 0;
void led_thread(void const *argument) {
void led_thread() {
while (true) {
// Signal flags that are reported as event are automatically cleared.
Thread::signal_wait(SIGNAL_SET_VALUE);
@ -44,7 +44,8 @@ void led_thread(void const *argument) {
int main (void) {
GREENTEA_SETUP(20, "default_auto");
Thread thread(led_thread, NULL, osPriorityNormal, STACK_SIZE);
Thread thread(osPriorityNormal, STACK_SIZE);
thread.start(led_thread);
bool result = false;
printf("Handling %d signals...\r\n", SIGNALS_TO_EMIT);

View File

@ -15,23 +15,7 @@
* the C standard library. For GCC, ARM_STD and IAR it is defined with a size of 2048 bytes
* and for ARM_MICRO 512. Because of reduce RAM size some targets need a reduced stacksize.
*/
#if defined(TARGET_MCU_NRF51822) || defined(TARGET_MCU_NRF52832)
#define STACK_SIZE 512
#elif defined(TARGET_STM32F070RB) || defined(TARGET_STM32F072RB) || defined(TARGET_STM32F103RB) || defined(TARGET_STM32F091RC)
#define STACK_SIZE 512
#elif defined(TARGET_STM32F410RB)
#define STACK_SIZE 512
#elif defined(TARGET_STM32L073RZ)
#define STACK_SIZE 512
#elif defined(TARGET_XDOT_L151CC)
#define STACK_SIZE 1024
#elif defined(TARGET_HI2110)
#define STACK_SIZE 512
#elif defined(TARGET_EFR32)
#define STACK_SIZE 512
#else
#define STACK_SIZE DEFAULT_STACK_SIZE
#endif
#define PARALLEL_STACK_SIZE 512
using namespace utest::v1;
@ -55,7 +39,8 @@ void increment_with_wait(counter_t* counter) {
}
void increment_with_child(counter_t* counter) {
Thread child(counter, increment, osPriorityNormal, STACK_SIZE);
Thread child;
child.start(callback(increment, counter));
child.join();
}
@ -64,7 +49,8 @@ void increment_with_murder(counter_t* counter) {
// take ownership of the counter mutex so it prevent the child to
// modify counter.
LockGuard lock(counter->internal_mutex());
Thread child(counter, increment, osPriorityNormal, STACK_SIZE);
Thread child;
child.start(callback(increment, counter));
child.terminate();
}
@ -81,7 +67,8 @@ void self_terminate(Thread *self) {
template <void (*F)(counter_t *)>
void test_single_thread() {
counter_t counter(0);
Thread thread(&counter, F, osPriorityNormal, STACK_SIZE);
Thread thread;
thread.start(callback(F, &counter));
thread.join();
TEST_ASSERT_EQUAL(counter, 1);
}
@ -92,7 +79,8 @@ void test_parallel_threads() {
Thread *threads[N];
for (int i = 0; i < N; i++) {
threads[i] = new Thread(&counter, F, osPriorityNormal, STACK_SIZE);
threads[i] = new Thread(osPriorityNormal, PARALLEL_STACK_SIZE);
threads[i]->start(callback(F, &counter));
}
for (int i = 0; i < N; i++) {
@ -108,7 +96,8 @@ void test_serial_threads() {
counter_t counter(0);
for (int i = 0; i < N; i++) {
Thread thread(&counter, F, osPriorityNormal, STACK_SIZE);
Thread thread;
thread.start(callback(F, &counter));
thread.join();
}
@ -116,8 +105,8 @@ void test_serial_threads() {
}
void test_self_terminate() {
Thread *thread = new Thread(osPriorityNormal, STACK_SIZE);
thread->start(thread, self_terminate);
Thread *thread = new Thread();
thread->start(callback(self_terminate, thread));
thread->join();
delete thread;
}

View File

@ -1,600 +0,0 @@
# Mbed SDK build script environment
## Introduction
Mbed test framework allows users to test their mbed devices applications, build mbed SDK library, re-run tests, run mbed SDK regression, add new tests and get all this results automatically. Everything is done on your machine so you have a full control over compilation, and tests you run.
It's is using Python 2.7 programming language to drive all tests so make sure Python 2.7 is installed on your system and included in your system PATH. To compile mbed SDK and tests you will need one or more supported compilers installed on your system.
To follow this short introduction you should already:
* Know what mbed SDK is in general.
* Know how to install Python 2.7, ARM target cross compilers.
* You have C/C++ programming experience and at least willingness to learn a bit about Python.
## Test automation
Currently our simple test framework allows users to run tests on their machines (hosts) in a fully automated manner. All you need to do is to prepare two configuration files.
## Test automation limitations
Note that for tests which require connected external peripherals, for example Ethernet, SD flash cards, external EEPROM tests, loops etc. you need to:
* Modify test source code to match components' pin names to actual mbed board pins where peripheral is connected or
* Wire your board the same way test defines it.
## Prerequisites
mbed test suite and build scripts are Python 2.7 applications and require Python 2.7 runtime environment and [setuptools](https://pythonhosted.org/an_example_pypi_project/setuptools.html) to install dependencies.
What we need:
* Installed [Python 2.7](https://www.python.org/download/releases/2.7) programming language.
* Installed [setuptools](https://pythonhosted.org/an_example_pypi_project/setuptools.html#installing-setuptools-and-easy-install)
* Optionally you can install [pip](https://pip.pypa.io/en/latest/installing.html) which is the PyPA recommended tool for installing Python packages from command line.
mbed SDK in its repo root directory specifies ```setup.py``` file which holds information about all packages which are dependencies for it. Bear in mind only few simple steps are required to install all dependencies.
First, clone mbed SDK repo and go to mbed SDk repo's directory:
```
$ git clone https://github.com/mbedmicro/mbed.git
$ cd mbed
```
Second, invoke ```setup.py``` so ```setuptools``` can install mbed SDK's dependencies (external Python modules required by mbed SDK):
```
$ python setup.py install
```
or
```
$ sudo python setup.py install
```
when your system requires administrator rights to install new Python packages.
### Manual Python package dependency installation
In case you do not want to install whole mbed package using ```setuptools```, you can use ```requirements.txt``` file and with help of ```pip`` package manager install only mbed's Python package dependencies:
```
$ pip install -r requirements.txt
```
## Prerequisites (manual Python package dependency installation)
**Please only read this chapter if you had problems installing mbed SDK dependencies to Python packages**.
Below you can find the list of mbed SDK dependencies to Python modules with instructions how to install them manually.
You can skip this part if you've already install [Python 2.7](https://www.python.org/download/releases/2.7) and [setuptools](https://pythonhosted.org/an_example_pypi_project/setuptools.html) and successfully [installed all dependencies](#prerequisites).
* Please make sure you've installed [pip](https://pip.pypa.io/en/latest/installing.html) or [easy_install](https://pythonhosted.org/setuptools/easy_install.html#installing-easy-install)
Note: Easy Install is a python module (easy_install) bundled with [setuptools](https://pythonhosted.org/an_example_pypi_project/setuptools.html#installing-setuptools-and-easy-install) that lets you automatically download, build, install, and manage Python packages.
* Installed [pySerial](https://pypi.python.org/pypi/pyserial) module for Python 2.7.
pySerial can be installed from PyPI, either manually downloading the files and installing as described below or using:
```
$ pip install pyserial
```
or:
```
easy_install -U pyserial
```
* Installed [prettytable](https://code.google.com/p/prettytable/wiki/Installation) module for Python 2.7.
prettytable can be installed from PyPI, either manually downloading the files and installing as described below or using:
```
$ pip install prettytable
```
* Installed [IntelHex](https://pypi.python.org/pypi/IntelHex) module.
IntelHex may be downloaded from https://launchpad.net/intelhex/+download or http://www.bialix.com/intelhex/.
Assuming Python is properly installed on your platform, installation should just require running the following command from the root directory of the archive:
```
sudo python setup.py install
```
This will install the intelhex package into your systems site-packages directory. After that is done, any other Python scripts or modules should be able to import the package using:
```
$ python
Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from intelhex import IntelHex
>>>
```
* You can check if you have correctly installed the above modules (or you already have them) by starting Python and importing both modules.
```
$ python
Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import serial
>>> import prettytable
>>> from intelhex import IntelHex
>>>
```
* Installed Git open source distributed version control system.
* Installed at least one of the supported by Mbed SDK workspace tools compilers:
Compiler | Mbed SDK Abbreviation | Example Version
-----------------------|-----------------------|-----------
Keil ARM Compiler | ARM, uARM | ARM C/C++ Compiler, 5.03 [Build 117]
GCC ARM | GCC_ARM | gcc version 4.8.3 20131129 (release)
GCC CodeRed | GCC_CR | gcc version 4.6.2 20121016 (release)
IAR Embedded Workbench | IAR | IAR ANSI C/C++ Compiler V6.70.1.5641/W32 for ARM
* Mbed board. You can find list of supported platforms [here](https://mbed.org/platforms/).
### Getting Mbed SDK sources with test suite
So you have already installed Python (with required modules) together with at least one supported compiler you will use with your mbed board. Great!
Now let's go further and try to get Mbed SDK with test suite together. So let's clone latest Mbed SDK source code and configure path to our compiler(s) in next few steps.
* Open console and run command below to clone Mbed SDK repository hosted on [Github](https://github.com/mbedmicro/mbed).
```
$ git clone https://github.com/mbedmicro/mbed.git
Cloning into 'mbed'...
remote: Counting objects: 37221, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 37221 (delta 0), reused 0 (delta 0), pack-reused 37218
Receiving objects: 100% (37221/37221), 20.38 MiB | 511.00 KiB/s, done.
Resolving deltas: 100% (24455/24455), done.
Checking connectivity... done.
Checking out files: 100% (3994/3994), done.
```
* Now you can go to mbed directory you've just cloned and you can see root directory structure of our Mbed SDK library sources. Just type following commands:
```
$ cd mbed
$ ls
LICENSE MANIFEST.in README.md libraries setup.py travis tools
```
Directory structure we are interested in:
```
mbed/tools/ - test suite scripts, build scripts etc.
mbed/libraries/tests/ - mbed SDK tests,
mbed/libraries/tests/mbed/ - tests for mbed SDK and peripherals tests,
mbed/libraries/tests/net/echo/ - tests for Ethernet interface,
mbed/libraries/tests/rtos/mbed/ - tests for RTOS.
```
### Workspace tools
Workspace tools are set of Python scripts used off-line by Mbed SDK team to:
* Compile and build mbed SDK,
* Compile and build libraries included in mbed SDK repo like e.g. ETH (Ethernet), USB, RTOS or CMSIS,
* Compile, build and run mbed SDK tests,
* Run test regression locally and in CI server,
* Get library, target, test configuration (paths, parameters, names etc.).
### Configure workspace tools to work with your compilers
Before we can run our first test we need to configure our test environment a little!
Now we need to tell workspace tools where our compilers are.
* Please to go ```mbed``` directory and create empty file called ```mbed_settings.py```.
```
$ touch mbed_settings.py
```
* Populate this file the Python code below:
```python
from os.path import join
# ARMCC
ARM_PATH = "C:/Work/toolchains/ARMCompiler_5.03_117_Windows"
ARM_BIN = join(ARM_PATH, "bin")
ARM_INC = join(ARM_PATH, "include")
ARM_LIB = join(ARM_PATH, "lib")
ARM_CPPLIB = join(ARM_LIB, "cpplib")
MY_ARM_CLIB = join(ARM_PATH, "lib", "microlib")
# GCC ARM
GCC_ARM_PATH = "C:/Work/toolchains/gcc_arm_4_8/4_8_2013q4/bin"
# GCC CodeRed
GCC_CR_PATH = "C:/Work/toolchains/LPCXpresso_6.1.4_194/lpcxpresso/tools/bin"
# IAR
IAR_PATH = "C:/Work/toolchains/iar_6_5/arm"
SERVER_ADDRESS = "127.0.0.1"
LOCALHOST = "127.0.0.1"
# This is moved to separate JSON configuration file used by singletest.py
MUTs = {
}
```
Note: You need to provide the absolute path to your compiler(s) installed on your host machine. Replace corresponding variable values with paths to compilers installed in your system:
* ```ARM_PATH``` for armcc compiler.
* ```GCC_ARM_PATH``` for GCC ARM compiler.
* ```GCC_CR_PATH``` for GCC CodeRed compiler.
* ```IAR_PATH``` for IAR compiler.
If for example you do not use ```IAR``` compiler you do not have to modify anything. Workspace tools will use ```IAR_PATH`` variable only if you explicit ask for it from command line. So do not worry and replace only paths for your installed compilers.
Note: Because this is a Python script and ```ARM_PATH```, ```GCC_ARM_PATH```, ```GCC_CR_PATH```, ```IAR_PATH``` are Python string variables please use double backlash or single slash as path's directories delimiter to avoid incorrect path format. For example:
```python
ARM_PATH = "C:/Work/toolchains/ARMCompiler_5.03_117_Windows"
GCC_ARM_PATH = "C:/Work/toolchains/gcc_arm_4_8/4_8_2013q4/bin"
GCC_CR_PATH = "C:/Work/toolchains/LPCXpresso_6.1.4_194/lpcxpresso/tools/bin"
IAR_PATH = "C:/Work/toolchains/iar_6_5/arm"
```
Note: Settings in ```mbed_settings.py``` will overwrite variables with default values in ```mbed/default_settings.py``` file.
## Build Mbed SDK library from sources
Let's build mbed SDK library off-line from sources using your compiler. We've already cloned mbed SDK sources, we've also installed compilers and added their paths to ```mbed_settings.py```.
We now should be ready to use workspace tools script ```build.py``` to compile and build mbed SDK from sources.
We are still using console. You should be already in ```mbed/tools/``` directory if not go to ```mbed/tools/``` and type below command:
```
$ python build.py -m LPC1768 -t ARM
```
or if you want to take advantage from multi-threaded compilation please use option ```-j X``` where ```X``` is number of cores you want to use to compile mbed SDK. See below:
```
$ python build.py -m LPC1768 -t ARM -j 4
Building library CMSIS (LPC1768, ARM)
Copy: core_ca9.h
Copy: core_caFunc.h
...
Compile: us_ticker_api.c
Compile: wait_api.c
Library: mbed.ar
Creating archive 'C:\temp\x\mbed\build\mbed\TARGET_LPC1768\TOOLCHAIN_ARM_STD\mbed.ar'
Copy: board.o
Copy: retarget.o
Completed in: (42.58)s
Build successes:
* ARM::LPC1768
```
Above command will build mbed SDK for [LPC1768](http://developer.mbed.org/platforms/mbed-LPC1768/) platform using ARM compiler.
Let's have a look at directory structure under ```mbed/build/```. We can see for ```LPC1768``` new directory ```TARGET_LPC1768``` was created. This directory contains all build primitives.
Directory ```mbed/TARGET_LPC1768/TOOLCHAIN_ARM_STD/``` contains mbed SDK library ```mbed.ar```. This directory structure also stores all needed headers which you should use with ```mbed.ar``` when building your own software.
```
$ tree ./mbed/build/
Folder PATH listing
Volume serial number is 006C006F 6243:3EA9
./MBED/BUILD
+---mbed
+---.temp
¦ +---TARGET_LPC1768
¦ +---TOOLCHAIN_ARM_STD
¦ +---TARGET_NXP
¦ +---TARGET_LPC176X
¦ +---TOOLCHAIN_ARM_STD
+---TARGET_LPC1768
+---TARGET_NXP
¦ +---TARGET_LPC176X
¦ +---TARGET_MBED_LPC1768
+---TOOLCHAIN_ARM_STD
```
Note: Why ```LCP1768```? For this example we are using ```LPC1768``` because this platform supports all compilers so you are sure you only need to specify proper compiler.
If you are not using ARM Compiler replace ```ARM``` with your compiler nickname: ```GCC_ARM```, ```GCC_CR``` or ```IAR```. For example if you are using IAR type command:
```
$ python build.py -m LPC1768 -t IAR
```
Note: Workspace tools track changes in source code. So if for example mbed SDK or test source code changes ```build.py``` script will recompile project with all dependencies. If there are no changes in code consecutive mbed SDK re-builds using build.py will not rebuild project if this is not necessary. Try to run last command once again, we can see script ```build.py``` will not recompile project (there are no changes):
```
$ python build.py -m LPC1768 -t ARM
Building library CMSIS (LPC1768, ARM)
Building library MBED (LPC1768, ARM)
Completed in: (0.15)s
Build successes:
* ARM::LPC1768
```
### build.py script
Build script located in mbed/tools/ is our core script solution to drive compilation, linking and building process for:
* mbed SDK (with libs like Ethernet, RTOS, USB, USB host).
* Tests which also can be linked with libraries like RTOS or Ethernet.
Note: Test suite also uses the same build script, inheriting the same properties like auto dependency tracking and project rebuild in case of source code changes.
Build.py script is a powerful tool to build mbed SDK for all available platforms using all supported by mbed cross-compilers. Script is using our workspace tools build API to create desired platform-compiler builds. Use script option ```--h``` (help) to check all script parameters.
```
$ python build.py --help
```
* The command line parameter ```-m``` specifies the MCUs/platforms for which you want to build the mbed SDK. More than one MCU(s)/platform(s) may be specified with this parameter using comma as delimiter.
Example for one platform build:
```
$ python build.py -m LPC1768 -t ARM
```
or for many platforms:
```
$ python build.py -m LPC1768,NUCLEO_L152RE -t ARM
```
* Parameter ```-t``` defined which toolchain should be used for mbed SDK build. You can build Mbed SDK for multiple toolchains using one command.
Below example (note there is no space after commas) will compile mbed SDK for Freescale Freedom KL25Z platform using ARM and GCC_ARM compilers:
```
$ python build.py -m KL25Z -t ARM,GCC_ARM
```
* You can combine this technique to compile multiple targets with multiple compilers.
Below example will compile mbed SDK for Freescale's KL25Z and KL46Z platforms using ARM and GCC_ARM compilers:
```
$ python build.py -m KL25Z,KL46Z -t ARM,GCC_ARM
```
* Building libraries included in mbed SDK's source code. Parameters ```-r```, ```-e```, ```-u```, ```-U```, ```-d```, ```-b``` will add ```RTOS```, ```Ethernet```, ```USB```, ```USB Host```, ```DSP```, ```U-Blox``` libraries respectively.
Below example will build Mbed SDK library for for NXP LPC1768 platform together with RTOS (```-r``` switch) and Ethernet (```-e``` switch) libraries.
```
$ python build.py -m LPC1768 -t ARM -r -e
Building library CMSIS (LPC1768, ARM)
Building library MBED (LPC1768, ARM)
Building library RTX (LPC1768, ARM)
Building library RTOS (LPC1768, ARM)
Building library ETH (LPC1768, ARM)
Completed in: (0.48)s
Build successes:
* ARM::LPC1768
```
* If youre unsure which platforms and toolchains are supported please use switch ```-S``` to print simple matrix of platform to compiler dependencies.
```
$ python build.py -S
+-------------------------+-----------+-----------+-----------+-----------+-----------+
| Platform | ARM | uARM | GCC_ARM | IAR | GCC_CR |
+-------------------------+-----------+-----------+-----------+-----------+-----------+
| APPNEARME_MICRONFCBOARD | Supported | Default | Supported | - | - |
| ARCH_BLE | Default | - | Supported | Supported | - |
| ARCH_GPRS | Supported | Default | Supported | Supported | Supported |
...
| UBLOX_EVK_ODIN_W2 | Supported | Default | Supported | Supported | - |
| WALLBOT_BLE | Default | - | Supported | Supported | - |
| XADOW_M0 | Supported | Default | Supported | Supported | Supported |
+-------------------------+-----------+-----------+-----------+-----------+-----------+
*Default - default on-line compiler
*Supported - supported off-line compiler
Total platforms: 90
Total permutations: 297
```
Above list can be overwhelming so please do not hesitate to use switch ```-f``` to filter ```Platform``` column.
```
$ python build.py -S -f ^K
+--------------+-----------+---------+-----------+-----------+--------+
| Platform | ARM | uARM | GCC_ARM | IAR | GCC_CR |
+--------------+-----------+---------+-----------+-----------+--------+
| K20D50M | Default | - | Supported | Supported | - |
| K22F | Default | - | Supported | Supported | - |
| K64F | Default | - | Supported | Supported | - |
| KL05Z | Supported | Default | Supported | Supported | - |
| KL25Z | Default | - | Supported | Supported | - |
| KL43Z | Default | - | Supported | - | - |
| KL46Z | Default | - | Supported | Supported | - |
| NRF51_DK | Default | - | Supported | Supported | - |
| NRF51_DK_OTA | Default | - | Supported | - | - |
+--------------+-----------+---------+-----------+-----------+--------+
*Default - default on-line compiler
*Supported - supported off-line compiler
Total platforms: 9
Total permutations: 28
```
or just give platform name:
```
$ python build.py -S -f LPC1768
+----------+---------+-----------+-----------+-----------+-----------+
| Platform | ARM | uARM | GCC_ARM | IAR | GCC_CR |
+----------+---------+-----------+-----------+-----------+-----------+
| LPC1768 | Default | Supported | Supported | Supported | Supported |
+----------+---------+-----------+-----------+-----------+-----------+
*Default - default on-line compiler
*Supported - supported off-line compiler
Total platforms: 1
Total permutations: 6
```
* You can be more verbose ```-v``` especially if you want to see each compilation / linking command build.py is executing:
```
$ python build.py -t GCC_ARM -m LPC1768 -j 8 -v
Building library CMSIS (LPC1768, GCC_ARM)
Copy: LPC1768.ld
Compile: startup_LPC17xx.s
[DEBUG] Command: C:/Work/toolchains/gcc_arm_4_8/4_8_2013q4/bin\arm-none-eabi-gcc
-x assembler-with-cpp -c -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers
-fmessage-length=0 -fno-exceptions -fno-builtin -ffunction-sections -fdata-sections -MMD
-fno-delete-null-pointer-checks -fomit-frame-pointer -mcpu=cortex-m3 -mthumb -O2
-DTARGET_LPC1768 -DTARGET_M3 -DTARGET_CORTEX_M -DTARGET_NXP -DTARGET_LPC176X
-DTARGET_MBED_LPC1768 -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -D__CORTEX_M3 -DARM_MATH_CM3
-DMBED_BUILD_TIMESTAMP=1424903604.77 -D__MBED__=1 -IC:\Work\mbed\libraries\mbed\targets\cmsis
-IC:\Work\mbed\libraries\mbed\targets\cmsis\TARGET_NXP
-IC:\Work\mbed\libraries\mbed\targets\cmsis\TARGET_NXP\TARGET_LPC176X -IC:\Work\mbed\libraries\mbed\targets\cmsis\TARGET_NXP\TARGET_LPC176X\TOOLCHAIN_GCC_ARM
-o C:\Work\mbed\build\mbed\.temp\TARGET_LPC1768\TOOLCHAIN_GCC_ARM\TARGET_NXP\TARGET_LPC176X\TOOLCHAIN_GCC_ARM\startup_LPC17xx.o
C:\Work\mbed\libraries\mbed\targets\cmsis\TARGET_NXP\TARGET_LPC176X\TOOLCHAIN_GCC_ARM\startup_LPC17xx.s
[DEBUG] Return: 0
...
```
## CppCheck analysis
[Cppcheck](http://cppcheck.sourceforge.net/) is a static analysis tool for C/C++ code. Unlike C/C++ compilers and many other analysis tools it does not detect syntax errors in the code. Cppcheck primarily detects the types of bugs that the compilers normally do not detect. The goal is to detect only real errors in the code (i.e. have zero false positives).
Prerequisites:
* Please install ```CppCheck``` on your system before you want to use it with build scripts.
* You should also add Cppcheck to your system path.
```build.py``` script supports switching between compilation, building and just static code analysis testing. You can use switch ```--cppcheck``` to perform CppCheck static code analysis.
* When you are using --cppcheck switch all macros, toolchain dependencies etc. are preserved so you are sure you are checking exactly the same code you would compile for your application.
* Cppcheck analysis can take up to few minutes on slower machines.
* Usually you will use switches ```-t``` and ```-m``` to define toolchain and MCU (platform) respectively. You should do the same in case of CppCheck analysis. Please note that build script can also compile and build RTOS, Ethernet library etc. If you want to check those just use corresponding build script switches (e.g. ```-r```, ```-e```, ...).
Example:
```
$ python build.py -t uARM -m NUCLEO_F334R8 --cppcheck
```
# make.py script
```make.py``` is a ```mbed/tools/``` script used to build tests (we call them sometimes 'programs') one by one manually. This script allows you to flash board, execute and test it. However, this script is deprecated and will not be described here. Instead please use ```singletest.py``` file to build mbed SDK, tests and run automation for test cases included in ```mbedmicro/mbed```.
Note: ```make.py``` script depends on existing already built mbed SDK and library sources so you need to pre-build mbed SDK and other libraries (such as RTOS library) to link 'program' (test) with mbed SDK and RTOS library. To pre-build mbed SDK please use ```build.py``` script.
Just for sake of example please see few ways to use ```make.py``` together with Freedom K64F board.
* We need to build mbed SDK (in directory ```mbed/build/```:
```
$ python build.py -t GCC_ARM -m K64F -j 8
Building library CMSIS (K64F, GCC_ARM)
Building library MBED (K64F, GCC_ARM)
Completed in: (0.59)s
Build successes:
* GCC_ARM::K64F
```
* We can print all 'programs' (test cases) ```make.py``` can build for us:
```
$ python make.py -L
.
[ 0] MBED_A1: Basic
[ 1] MBED_A2: Semihost file system
[ 2] MBED_A3: C++ STL
[ 3] MBED_A4: I2C TMP102
.
```
For example 'program' under index ```2``` is ```MBED_A3``` test case we can build and flash onto K64F board.
* Building test with ```make.py``` by specifying test case name with ```-n``` option:
```
$ python make.py -t GCC_ARM -m K64F -n MBED_A3
Building project STL (K64F, GCC_ARM)
Compile: main.cpp
[Warning] main.cpp@76: In function 'int main()': deprecated conversion from string constant to 'char*' [-Wwrite-strings]
.
.
.
[Warning] main.cpp@76: In function 'int main()': deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Compile: test_env.cpp
Link: stl
Elf2Bin: stl
Image: C:\Work\mbed\build\test\K64F\GCC_ARM\MBED_A3\stl.bin
```
Because we previously have built mbed SDK we are now able to drive test case compilation and linking with mbed SDK and produce ```MBED_A3``` test case binary in build directory:
```
C:\Work\mbed\build\test\K64F\GCC_ARM\MBED_A3\stl.bin
```
For more help type ```$ python make.py --help``` in your command line.
# project.py script
```project.py``` script is used to export test cases ('programs') from test case portfolio to off-line IDE. This is a easy way to export test project to IDEs such as:
* codesourcery.
* coide.
* ds5_5.
* emblocks.
* gcc_arm.
* iar.
* kds.
* lpcxpresso.
* uvision.
You can export project using command line. All you need to do is to specify mbed platform name (option ```-m```), your IDE (option ```-i```) and project name you want to export (option ```-n``` or (option ```-p```).
In below example we export our project so we can work on it using GCC ARM cross-compiler. Building mechanism used to drive exported build will be ```Make```.
```
$ python project.py -m K64F -n MBED_A3 -i gcc_arm
Copy: test_env.h
Copy: AnalogIn.h
Copy: AnalogOut.h
.
.
.
Copy: K64FN1M0xxx12.ld
Copy: main.cpp
Successful exports:
* K64F::gcc_arm C:\Work\mbed\build\export\MBED_A3_gcc_arm_K64F.zip
```
You can see exporter placed compressed project export in ```zip``` file in ```mbed/build/export/``` directory.
Example export file ```MBED_A3_gcc_arm_K64F.zip``` structure:
```
MBED_A3
├───env
└───mbed
├───api
├───common
├───hal
└───targets
├───cmsis
│ └───TARGET_Freescale
│ └───TARGET_MCU_K64F
│ └───TOOLCHAIN_GCC_ARM
└───hal
└───TARGET_Freescale
└───TARGET_KPSDK_MCUS
├───TARGET_KPSDK_CODE
│ ├───common
│ │ └───phyksz8081
│ ├───drivers
│ │ ├───clock
│ │ ├───enet
│ │ │ └───src
│ │ ├───interrupt
│ │ └───pit
│ │ ├───common
│ │ └───src
│ ├───hal
│ │ ├───adc
│ │ ├───can
│ │ ├───dac
│ │ ├───dmamux
│ │ ├───dspi
│ │ ├───edma
│ │ ├───enet
│ │ ├───flextimer
│ │ ├───gpio
│ │ ├───i2c
│ │ ├───llwu
│ │ ├───lptmr
│ │ ├───lpuart
│ │ ├───mcg
│ │ ├───mpu
│ │ ├───osc
│ │ ├───pdb
│ │ ├───pit
│ │ ├───pmc
│ │ ├───port
│ │ ├───rcm
│ │ ├───rtc
│ │ ├───sai
│ │ ├───sdhc
│ │ ├───sim
│ │ ├───smc
│ │ ├───uart
│ │ └───wdog
│ └───utilities
│ └───src
└───TARGET_MCU_K64F
├───device
│ ├───device
│ │ └───MK64F12
│ └───MK64F12
├───MK64F12
└───TARGET_FRDM
```
After unpacking exporter ```zip``` file we can go to directory and see files inside MBED_A3 directory:
```
$ ls
GettingStarted.htm Makefile env main.cpp mbed
```
Exporter generated for us ```Makefile``` so now we can build our software:
```
$ make -j 8
.
.
.
text data bss dec hex filename
29336 184 336 29856 74a0 MBED_A3.elf
```
We can see root directory of exporter project is now populated with binary files:
* MBED_A3.bin.
* MBED_A3.elf .
* MBED_A3.hex.
You have also map file ```MBED_A3.map``` for your disposal.
```
$ ls
GettingStarted.htm MBED_A3.bin MBED_A3.elf MBED_A3.hex MBED_A3.map Makefile env main.cpp main.d main.o mbed
```

View File

@ -1,270 +0,0 @@
# Committing changes to mbedmicro/mbed
* Our current branching model is very simple. We are using ```master``` branch to merge all pull requests.
* Based on stable ```SHA``` version of ```master``` branch we decide to release and at the same time ```tag``` our build release.
* Our current release versioning follows simple integer version: ```94```, ```95```, ```96``` etc.
# Committer Guide
## How to decide what release(s) should be patched
This section provides a guide to help a committer decide the specific base branch that a change set should be merged into.
Currently our default branch is ```master``` branch. All pull requests should be created against ```master``` branch.
mbed SDK is released currently on master branch under certain tag name (see [Git tagging basics]( http://git-scm.com/book/en/v2/Git-Basics-Tagging)). You can see mbed SDK tags and switch between them to for example go back to previous mbed SDK release.
```
$ git tag
```
Please note: mebd SDK ```master``` branch's ```HEAD``` is our latest code and may not be as stable as you expect. We are putting our best effort to run regression testing (in-house) against pull requests and latest code.
Each commit to ```master``` will trigger [GitHub's Travis Continuous Integration](https://travis-ci.org/mbedmicro/mbed/builds).
### Pull request
Please send pull requests with changes which are:
* Complete (your code will compile and perform as expected).
* Tested on hardware.
* You can use included mbed SDK test suite to perform testing. See TESTING.md.
* If your change, feature do not have a test case included please add one (or more) to cover new functionality.
* If you can't test your functionality describe why.
* Documented source code:
* New, modified functions have descriptive comments.
* You follow coding rules and styles provided by mbed SDK project.
* Documented pull request description:
* Description of changes is added - explain your change / enhancement.
* References to existing issues, other pull requests or forum discussions are included.
* Test results are added.
After you send us your pull request our Gate Keeper will change the state of pull request to:
• ``` enhancement``` or ```bug``` when pull request creates new improvement or fixed issue.
Than we will set for you labels:
• ```review``` to let you know your pull request is under review and you can expect review related comments from us.
• ```in progress``` when you pull request requires some additional change which will for now block this pull request from merging.
At the end we will remove ```review``` label and merge your change if everything goes well.
## C++ coding rules & coding guidelines
### Rules
* The mbed SDK code follows K&R style (Reference: [K&R style](http://en.wikipedia.org/wiki/Indent_style#K.26R_style)) with at least 2 exceptions which can be found in the list below the code snippet:
```c++
static const PinMap PinMap_ADC[] = {
{PTC2, ADC0_SE4b, 0},
{NC , NC , 0}
};
uint32_t adc_function(analogin_t *obj, uint32_t options)
{
uint32_t instance = obj->adc >> ADC_INSTANCE_SHIFT;
switch (options) {
case 1:
timeout = 6;
break;
default:
timeout = 10;
break;
}
while (!adc_hal_is_conversion_completed(instance, 0)) {
if (timeout == 0) {
break;
} else {
timeout--;
}
}
if (obj->adc == ADC_CHANNEL0) {
adc_measure_channel(instance);
adc_stop_channel(instance);
} else {
error("channel not available");
}
#if DEBUG
for (uint32_t i = 0; i < 10; i++) {
printf("Loop : %d", i);
}
#endif
return adc_hal_get_conversion_value(instance, 0);
}
```
* Indentation - 4 spaces. Please do not use tabs!
* Braces - K&R, except for functions where the opening brace is on the new line.
* 1 TBS - use braces for statements ```if```, ```else```, ```while```, ```for``` (exception from K&R) Reference: [1TBS](http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS)).
* One line per statement.
* Preprocessor macro starts at the beginning of a new line, the code inside is indented accordingly the code above it.
* Cases within switch are indented (exception from K&R).
* Space after statements if, while, for, switch, same applies to binary and ternary operators.
* Each line has preferably at most 120 characters.
* For pointers, ```*``` is adjacent to a name (analogin_t *obj).
* Don't leave trailing spaces at the end of lines.
* Empty lines should have no trailing spaces.
* Unix line endings are default option for files.
* Use capital letters for macros.
* A file should have an empty line at the end.
and:
* We are not using C++11 yet so do not write code compliant to this standard.
* We are not using libraries like ```BOOST``` so please so not include any ```BOOST``` headers to your code.
* C++ & templates: please take under consideration templates are not fully supported by cross-compilers. You may have difficulties compiling template code few cross-compilers so make sure your template code compilers for more than one compiler.
### Naming conventions
Classes:
* Begins with a capital letter, and each word in it begins also with a capital letter (```AnalogIn```, ```BusInOut```).
* Methods contain small letters, distinct words separated by underscore.
* Private members starts with an underscore.
User defined types (typedef):
* Structures - suffix ```_t``` - to denote it is user defined type
* Enumeration - the type name and values name - same naming convention as classes (e.g ```MyNewEnum```)
Functions:
* Contain lower case letters (as methods within classes)
* Distinct words separated by underscore (```wait_ms```, ```read_u16```)
* Please make sure that in your module all functions have unique prefix so when your module is compiled with other modules function names (and e.g. extern global variable names) are not in naming conflict.
Example code look&feel:
```c++
#define ADC_INSTANCE_SHIFT 8
class AnalogIn {
public:
/** Create an AnalogIn, connected to the specified pin
*
* @param pin AnalogIn pin to connect to
* @param name (optional) A string to identify the object
*/
AnalogIn(PinName pin) {
analogin_init(&_adc, pin);
}
/** Read the input voltage, represented as a float in the range [0.0, 1.0]
*
* @returns
* A floating-point value representing the current input voltage, measured as a percentage
*/
uint32_t read() {
return analogin_read(&_adc, operation);
}
protected:
analogin_t _adc;
};
typedef enum {
ADC0_SE0 = (0 << ADC_INSTANCE_SHIFT) | 0,
} ADCName;
struct analogin_s {
ADCName adc;
};
typedef struct analogin_s analogin_t;
```
### Doxygen documentation
All functions / methods should contain a documentation using doxygen javadoc in a header file. More information regarding writing API Documentation, follow [this](https://mbed.org/handbook/API-Documentation) link.
Example of well documentet code:
```c++
#ifndef ADC_H
#define ADC_H
#ifdef __cplusplus
extern "C" {
#endif
/** ADC Measurement method
*
* @param obj Pointer to the analogin object.
* @param options Options to be enabled by ADC peripheral.
*
* @returns
* Measurement value on defined ADC channel.
*/
uint32_t adc_function(analogin_t *obj, uint32_t options)
#ifdef __cplusplus
}
#endif
#endif
```
### C/C++ Source code indenter
In Mbed project you can use AStyle (Reference: [Artistic Style](http://astyle.sourceforge.net/)) source code indenter to help you auto format your source code. It will for sure not correct all your coding styles but for sure will eliminate most of them. You can download AStyle from this location.
Official Mbed SDK styles include below AStyle styles (defined by command line switched):
```
--style=kr --indent=spaces=4 --indent-switches
```
To format your file you can execute below command. Just replace ```$(FULL_CURRENT_PATH)``` with path to your source file.
```
$ astyle.exe --style=kr --indent=spaces=4 --indent-switches $(FULL_CURRENT_PATH)
```
## Python coding rules & coding guidelines
Some of our tools in tools are written in ```Python 2.7```. In case of developing tools for python we prefer to keep similar code styles across all Python source code. Please note that not all rules must be enforced. For example we do not limit you to 80 characters per line, just be sure your code can fit to widescreen display.
Please stay compatible with ```Python 2.7``` but nothing stops you to write your code so in the future it will by Python 3 friendly.
Please check our Python source code (especially ```test_api.py``` and ```singletest.py```) to get notion of how your new code should look like). We know our code is not perfect but please try to fit the same coding style to existing code so source looks consistent and is not series of different flavors.
Some general guidelines:
* Use Python idioms, please refer to one of many on-line guidelines how to write Pythonic code: [Code Like a Pythonista: Idiomatic Python](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html).
* Please do not use TABs. Please use 4 spaces instead for indentations.
* Please put space character between operators, after comma etc.
* Please document your code, write comments and ```doc``` sections for each function or class you implement.
### Static Code Analizers for Python
If you are old-school developer for sure you remember tools like lint. "lint was the name originally given to a particular program that flagged some suspicious and non-portable constructs (likely to be bugs) in C language source code." Now lint-like programs are used to check similar code issues for multiple languages, also for Python. Please do use them if you want to commit new code to tools and other mbed SDK Python tooling.
Below is the list Python lint tools you may want to use:
* [pyflakes](https://pypi.python.org/pypi/pyflakes) - Please scan your code with pyflakes and remove all issues reported by it. If you are unsure if something should be modified or not you can skip lint report related fix and report this issue as possible additional commit in your pull request description.
* [pylint](http://www.pylint.org/) - Please scan your code with pylint and check if there are any issues which can be resolved and are obvious "to fix" bugs. For example you may forgot to add 'self' as first parameter in class method parameter list or you are calling unknown functions / functions from not imported modules.
* [pychecker](http://pychecker.sourceforge.net/) - optional, but more the merrier ;)
Example Python look&feel:
```python
class HostRegistry:
""" Class stores registry with host tests and objects representing them
"""
HOST_TESTS = {} # host_test_name -> host_test_ojbect
def register_host_test(self, ht_name, ht_object):
""" Registers (removes) host test by name from HOST_TESTS registry
if host test is not already registered (check by name).
"""
if ht_name not in self.HOST_TESTS:
self.HOST_TESTS[ht_name] = ht_object
def unregister_host_test(self):
""" Unregisters (removes) host test by name from HOST_TESTS registry.
"""
if ht_name in HOST_TESTS:
self.HOST_TESTS[ht_name] = None
def get_host_test(self, ht_name):
""" Returns HOST_TEST if host name is valid.
In case no host test is available return None
"""
return self.HOST_TESTS[ht_name] if ht_name in self.HOST_TESTS else None
def is_host_test(self, ht_name):
""" Function returns True if host name is valid (is in HOST_TESTS)
"""
return ht_name in self.HOST_TESTS
```
## Testing
Please refer to TESTING.md document for detais regarding mbed SDK test suite and build scripts included in ```mbed/tools/```.
## Before pull request checklist
* Your pull request description section contains:
* Rationale tell us why you submitted this pull request. This is your change to write us summary of your change.
* Description describe changes youve made and tell us which new features / functionalities were implemented.
* Manual / Cookbook / Handbook you can put here manual, cookbook or handbook related to your change / enhancement. Your documentation can stay with pull request.
* Test results (if applicable).
* Make sure you followed project's coding rules and styles.
* No dependencies are created to external C/C++ libraries which are not included already in our repository.
* Please make sure that in your module all functions have unique prefix (no name space collisions).
* You reused existing functionality, please do not add or rewrite existing code. E.g. use mbeds ```FunctionPointer``` if possible to store your function pointers. Do not write another wrapper for it. We already got one. If some functionality is missing, just add it! Extend our APIs wisely!
* Were you consistent? Please continue using style / code formatting, variables naming etc. in file they are modifying.
* Your code compiles and links. Also doesnt generate additional compilation warnings.

View File

@ -1,830 +0,0 @@
# Mbed SDK automated test suite
## Introduction
Test suit allows users to run locally on their machines Mbed SDKs tests included in Mbed SDK repository. It also allows users to create their own tests and for example add new tests to test set as they progress with their project. If test is generic enough it could be included into official Mbed SDK test pool just do it via normal pull request!
Each test is supervised by python script called “host test” which will at least Test suite is using build script API to compile and build test source together with required by test libraries like CMSIS, Mbed, Ethernet, USB etc.
## What is host test?
Test suite supports test supervisor concept. This concept is realized by separate Python script called ```host test```. Host tests can be found in ```mbed/tools/host_tests/``` directory. Note: In newer mbed versions (mbed OS) host tests will be separate library.
Host test script is executed in parallel with test runner to monitor test execution. Basic host test just monitors device's default serial port for test results returned by test runner. Simple tests will print test result on serial port. In other cases host tests can for example judge by test results returned by test runner if test passed or failed. It all depends on test itself.
In some cases host test can be TCP server echoing packets from test runner and judging packet loss. In other cases it can just check if values returned from accelerometer are actually valid (sane).
## Test suite core: singletest.py script
```singletest.py``` script located in ```mbed/tools/``` is a test suite script which allows users to compile, build tests and test runners (also supports CppUTest unit test library). Script also is responsible for test execution on devices selected by configuration files.
### Parameters of singletest.py
Test execution script ```singletest.py``` is a fairly powerful tool to run tests for mbed SDK platform. It is flexible and allows users to configure test execution process and define which mbed platforms will be tested.
By specifying external configuration files (in JSON format) you can gain flexibility and prepare many different test scenarios. Just pass configuration file names to your script and run it.
#### MUTs Specification
You can easily configure your MUTs (Mbed Under Test) by creating configuration file with MUTs description.
Note: This configuration file must be in [JSON format](http://www.w3schools.com/json/).
Note: Unfortunately JSON format is not allowing you to have comments inside JSON code.
Lets see some example and let's try to configure small "test farm" with three devices connected to your host computer. In this example no peripherals (like SD card or EEPROM) are connected to our Mbed boards. We will use three platforms in this example:
* [NXP LPC1768](https://mbed.org/platforms/mbed-LPC1768) board.
* \[Freescale KL25Z](https://mbed.org/platforms/KL25Z) board and
* [STMicro Nucleo F103RB](https://mbed.org/platforms/ST-Nucleo-F103RB) board.
After connecting boards to our host machine (PC) we can check which serial ports and disks they occupy. For our example let's assume that:
* ```LPC1768``` serial port is on ```COM4``` and disk drive is ```J:```.
* ```KL25Z``` serial port is on ```COM39``` and disk drive is ```E:```.
* ```NUCLEO_F103RB``` serial port is on ```COM11``` and disk drive is ```I:```.
If you are working under Linux your port and disk could look like /dev/ttyACM5 and /media/usb5.
This information is needed to create ```muts_all.json``` configuration file. You can create it in ```mbed/tools/``` directory:
```
$ touch muts_all.json
```
Its name will be passed to ```singletest.py``` script after ```-M``` (MUTs specification) switch. Lets see how this file's content would look like in our example below:
```json
{
"1" : {"mcu": "LPC1768",
"port":"COM4",
"disk":"J:\\",
"peripherals": []
},
"2" : {"mcu": "KL25Z",
"port":"COM39",
"disk":"E:\\",
"peripherals": []
},
"3" : {"mcu": "NUCLEO_F103RB",
"port":"COM11",
"disk":"I:\\",
"peripherals": []
}
}
```
Note: We will leave field ```peripherals``` empty for the sake of this example. We will explain it later. All you need to do now is to properly fill fields ```mcu```, ```port``` and ```disk```.
Note: Please make sure files muts_all.json and test_spec.json are in tools/ directory. We will assume in this example they are.
Where to find ```mcu``` names? You can use option ```-S``` of ```build.py``` script (in ```mbed/tools/``` directory) to check all supported off-line MCUs names.
Note: If you update mbed device firmware or even disconnect / reconnect mbed device you may find that serial port / disk configuration changed. You need to update configuration file accordingly or you will face connection problems and obviously tests will not run.
#### Peripherals testing
When using MUTs configuration file (switch ```-M```) you can define in MUTs JSON file peripherals connected to your device:
```json
{
"1" : {"mcu" : "KL25Z",
"port" : "COM39",
"disk" : "E:\\",
"peripherals" : ["SD", "24LC256"]}
}
```
You can force test suite to run only common tests (switch ```-C```) or only peripheral tests (switch ```-P```).
```
$ python singletest.py -i test_spec.json -M muts_all.json -C
```
will not include tests for SD card and EEPROM 24LC256.
```
$ python singletest.py -i test_spec.json -M muts_all.json -P
```
will only run tests bind to SD card and EEPROM 24LC256.
Note: option ```-P``` is useful for example in cases when you have same platform and different shields you want to test. No need to test common part all the time (timers, RTC, RTOS etc.). You can force to test peripherals only on some devices and for example only common tests on other devices.
#### Additional MUTs configuration file settings
You can add extra information to each MUT configuration. In particular you can specify which flashing (binary copy method) should be used, how to reset target and for example set reset timeout (used to delay test execution just after reset).
muts_all.json:
```json
{
"1" : {"mcu" : "LPC1768",
"port" : "COM77",
"disk" : "G:\\",
"peripherals" : ["TMP102", "digital_loop", "port_loop", "analog_loop", "SD"]},
"2" : {"mcu" : "KL25Z",
"port" : "COM89",
"disk" : "F:\\",
"peripherals" : ["SD", "24LC256", "KL25Z"],
"copy_method" : "copy",
"reset_type" : "default",
"reset_tout" : "2"},
"3" : {"mcu" : "LPC11U24",
"port" : "COM76",
"disk" : "E:\\",
"peripherals" : []}
}
```
Please note that for MUT no. 2 few extra parameters were defined: ```copy_method```, ```reset_type``` and ```reset_tout```. Using this extra options you can tell test suite more about MUT you are using. This will allow you to be more flexible in terms of how you configure and use your MUTs.
* ```copy_method``` - STRING - tells test suite which binary copy method should be used.
You may notice that ```singletest.py``` command line help contains description about:
* Option ```-c``` (in MUTs file called ```copy_method```) with available copy methods supported by test suite plugin system.
* Option ```-r``` (in MUTs file called reset_type) with available reset methods supported by test suite plugin system.
* ```reset_type``` - STRING - some boards may require special reset handling, for example vendor specific command must be executed to reset device.
* ```reset_tout``` - INTEGER - extra timeout just after device is reseted. May be used to wait for few seconds so device may finish booting, flashing data internally etc.
Part of help listing for singletest.py:
```
-c COPY_METHOD, --copy-method=COPY_METHOD
Select binary copy (flash) method. Default is Python's
shutil.copy() method. Plugin support: copy, cp,
default, eACommander, eACommander-usb, xcopy
-r MUT_RESET_TYPE, --reset-type=MUT_RESET_TYPE
Extra reset method used to reset MUT by host test
script. Plugin support: default, eACommander,
eACommander-usb
```
----
Now we've already defined how our devices are connected to our host PC. We can continue and define which of this MUTs will be tested and which compilers we will use to compile and build Mbed SDK and tests. To do so we need to create test specification file (let's call it ```test_spec.json```) and put inside our configuration file information about which MUTs we actually want to test. We will pass this file's name to ```singletest.py``` script using ```-i``` switch.
Below we can see how sample ```test_spec.json``` file content could look like. (I've included all possible toolchains, we will change it in a moment):
```json
{
"targets": {
"LPC1768" : ["ARM", "uARM", "GCC_ARM", "GCC_CR", "IAR"],
"KL25Z" : ["ARM", "GCC_ARM"],
"NUCLEO_F103RB" : ["ARM", "uARM"]
}
}
```
Above example configuration will force tests for LPC1768, KL25Z, NUCLEO_F103RB platforms and:
* Compilers: ```ARM```, ```uARM```, ```GCC_ARM```, ```GCC_CR``` and ```IAR``` will be used to compile tests for NXP's ```LPC1768```.
* Compilers: ```ARM``` and ```GCC_ARM``` will be used for Freescales' ```KL25Z``` platform.
* Compilers: ```ARM``` and ```uARM``` will be used for STMicro's ```NUCLEO_F103RB``` platform.
For our example purposes let's assume we only have Keil ARM compiler, so let's change configuration in ```test_spec.json``` file and reduce number of compiler to those we actually have:
```json
{
"targets": {
"LPC1768" : ["ARM", "uARM"],
"KL25Z" : ["ARM"],
"NUCLEO_F103RB" : ["ARM", "uARM"]
}
}
```
#### Run your tests
After you configure all your MUTs and compilers you are ready to run tests. Make sure your devices are connected and your configuration files reflect your current configuration (serial ports, devices). Go to tools directory in your mbed location.
```
$ cd tools/
```
and execute test suite script.
```
$ python singletest.py -i test_spec.json -M muts_all.json
```
To check your configuration before test execution please use ```--config``` switch:
```
$ python singletest.py -i test_spec.json -M muts_all.json --config
MUTs configuration in m.json:
+-------+-------------+---------------+------+-------+
| index | peripherals | mcu | disk | port |
+-------+-------------+---------------+------+-------+
| 1 | | LPC1768 | J:\ | COM4 |
| 3 | | NUCLEO_F103RB | I:\ | COM11 |
| 2 | | KL25Z | E:\ | COM39 |
+-------+-------------+---------------+------+-------+
Test specification in t.json:
+---------------+-----+------+
| mcu | ARM | uARM |
+---------------+-----+------+
| NUCLEO_F103RB | Yes | Yes |
| KL25Z | Yes | - |
| LPC1768 | Yes | Yes |
+---------------+-----+------+
```
It should help you localize basic problems with configuration files and toolchain configuration.
Note: Configurations with issues will be marked with ```*``` sign.
Having multiple configuration files allows you to manage your test scenarios in more flexible manner. You can:
* Set up all platforms and toolchains used during testing.
* Define (using script's ```-n``` switch) which tests you want to run during testing.
* Just run regression (all tests). Regression is default setting for test script.
You can also force ```singletest.py``` script to:
* Run only peripherals' tests (switch ```-P```) or
* Just skip peripherals' tests (switch ```-C```).
* Build mbed SDK, libraries and corresponding tests with multiple cores, just use ```-j X``` option where ```X``` is number of cores you want to use for compilation.
```
$ python singletest.py -i test_spec.json -M muts_all.json -j 8
```
* Print test cases console output using ```-V``` option.
* Only build mbed SDK, tests and dependant libraries with switch ```-O```:
```
$ python singletest.py -i test_spec.json -M muts_all.json -j 8 -O
```
* Execute each test case multiple times with ```--global-loops X``` option, where ```X``` number of repeats. Additionally use option ```-W``` to continue repeating test cases execution only if they continue to fail.
```
$ python singletest.py -i test_spec.json -M muts_all.json --global-loops 3 -W
```
* Option ```--loops``` can be used to overwrite global loop count and redefine loop count for particular tests. Define test loops as ```TEST_ID=X``` where ```X``` is integer and separate loops count definitions by comma if necessary. E.g. ```TEST_1=5,TEST_2=20,TEST_3=2```.
```
$ python singletest.py -i test_spec.json -M muts_all.json RTOS_1=10,RTOS_2=5
```
This will execute test ```RTOS_1``` ten (10) times and test ```RTOS_2``` five (5) times.
* Force non default copy method. Note that mbed platforms can be flashed with just binary drag&drop. We simply copy file onto mbed's disk and interface chip flashes target MCU with given binary. Force non standard (Python specific) copy method by using option ```-c COPY_METHOD``` where ```COPY_METHOD``` can be shell, command line copy command like: ```cp```, ```copy````, ```xcopy``` etc. Make sure those commands are available from command line!
```
$ python singletest.py -i test_spec.json -M muts_all.json -c cp
```
* Run only selected tests. You can select which tests should be executed when you run test suite. Use ```-n``` switch to define tests by their ids you want to execute. Use comma to separate test ids:
```
$ python singletest.py -i test_spec.json -M muts_all.json -n RTOS_1,RTOS_2,RTOS_3,MBED_10,MBED_16,MBED_11
```
* Set common output binary name for all tests. In some cases you would like to have the same name for all tests. You can use switch ```--firmware-name``` to specify (without extension) build script output binary name.
In below example we would like to have all test binaries called ```firmware.bin`` (or with other extension like .elf, .hex depending on target accepted format).
```
$ python singletest.py -i test_spec.json -M muts_all.json --firmware-name firmware
```
* Where to find test list? Tests are defined in file ```tests.py``` in ```mbed/tools/``` directory. ```singletest.py``` uses test metadata in ```tests.py``` to resolve libraries dependencies and build tests for proper platforms and peripherals. Option ```-R``` can be used to get test names and direct path and test configuration.
```
$ python singletest.py -R
+-------------+-----------+---------------------------------------+--------------+-------------------+----------+--------------------------------------------------------+
| id | automated | description | peripherals | host_test | duration | source_dir |
+-------------+-----------+---------------------------------------+--------------+-------------------+----------+--------------------------------------------------------+
| MBED_1 | False | I2C SRF08 | SRF08 | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\i2c_SRF08 |
| MBED_10 | True | Hello World | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\hello |
| MBED_11 | True | Ticker Int | - | host_test | 20 | C:\Work\mbed\libraries\tests\mbed\ticker |
| MBED_12 | True | C++ | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\cpp |
| MBED_13 | False | Heap & Stack | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\heap_and_stack |
| MBED_14 | False | Serial Interrupt | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\serial_interrupt |
| MBED_15 | False | RPC | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\rpc |
| MBED_16 | True | RTC | - | host_test | 15 | C:\Work\mbed\libraries\tests\mbed\rtc |
| MBED_17 | False | Serial Interrupt 2 | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\serial_interrupt_2 |
| MBED_18 | False | Local FS Directory | - | host_test | 10 | C:\Work\mbed\libraries\tests\mbed\dir |
...
```
Note: you can filter tests by ```id``` column, just use ```-f``` option and give test name or regular expression:
```
$ python singletest.py -R -f RTOS
+--------------+-----------+-------------------------+-------------+-----------+----------+---------------------------------------------------+
| id | automated | description | peripherals | host_test | duration | source_dir |
+--------------+-----------+-------------------------+-------------+-----------+----------+---------------------------------------------------+
| CMSIS_RTOS_1 | False | Basic | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\cmsis\basic |
| CMSIS_RTOS_2 | False | Mutex | - | host_test | 20 | C:\Work\mbed\libraries\tests\rtos\cmsis\mutex |
| CMSIS_RTOS_3 | False | Semaphore | - | host_test | 20 | C:\Work\mbed\libraries\tests\rtos\cmsis\semaphore |
| CMSIS_RTOS_4 | False | Signals | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\cmsis\signals |
| CMSIS_RTOS_5 | False | Queue | - | host_test | 20 | C:\Work\mbed\libraries\tests\rtos\cmsis\queue |
| CMSIS_RTOS_6 | False | Mail | - | host_test | 20 | C:\Work\mbed\libraries\tests\rtos\cmsis\mail |
| CMSIS_RTOS_7 | False | Timer | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\cmsis\timer |
| CMSIS_RTOS_8 | False | ISR | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\cmsis\isr |
| RTOS_1 | True | Basic thread | - | host_test | 15 | C:\Work\mbed\libraries\tests\rtos\mbed\basic |
| RTOS_2 | True | Mutex resource lock | - | host_test | 20 | C:\Work\mbed\libraries\tests\rtos\mbed\mutex |
| RTOS_3 | True | Semaphore resource lock | - | host_test | 20 | C:\Work\mbed\libraries\tests\rtos\mbed\semaphore |
| RTOS_4 | True | Signals messaging | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\mbed\signals |
| RTOS_5 | True | Queue messaging | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\mbed\queue |
| RTOS_6 | True | Mail messaging | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\mbed\mail |
| RTOS_7 | True | Timer | - | host_test | 15 | C:\Work\mbed\libraries\tests\rtos\mbed\timer |
| RTOS_8 | True | ISR (Queue) | - | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\mbed\isr |
| RTOS_9 | True | SD File write-read | SD | host_test | 10 | C:\Work\mbed\libraries\tests\rtos\mbed\file |
+--------------+-----------+-------------------------+-------------+-----------+----------+---------------------------------------------------+
```
* Shuffle your tests. We strongly encourage you to shuffle your test order each time you execute test suite script.
Rationale: It is probable that tests executed in one particular order will pass and in other will fail. To shuffle your tests order please use option ```-u``` (or ```--shuffle```):
```
$ python singletest.py -i test_spec.json -M muts_all.json --shuffle
```
Above command will force test script to randomly generate shuffle seed and shuffle test order execution. Note: Shuffle seed is float in ```[0.0, 1.0)```.
You can always recreate particular test order by forcing shuffle (```-u``` or ```--shuffle``` switch) and passing shuffle seed back to test suite using ```--shuffle-seed``` switch:
```
$ python singletest.py -i test_spec.json -M muts_all.json --shuffle --shuffle-seed 0.4041028336
```
Note: You can also supply your own randomly generated shuffle seed to drive particular test execution order scenarios. Just make sure shuffle seed is float in ```[0.0, 1.0)```.
You can find test shuffle seed in test summary:
```
...
| OK | LPC1768 | ARM | MBED_A9 | Serial Echo at 115200 | 2.84 | 10 | 1/1 |
+--------+---------+-----------+-----------+-----------------------------+--------------------+---------------+-------+
Result: 1 FAIL / 22 OK
Shuffle Seed: 0.4041028336
Completed in 234.85 sec
```
### Example of device configuration (one device connected to host computer)
This example will show you how to configure single device, run general tests or only peripheral tests. We will also show some real test result examples.
1. We will test only one board STMIcro Nucleo ```F334R8``` board connected to our PC (port ```COM46``` and disk is ```E:```).
2. We will also connect EEPROM ```24LC256``` to SDA, SCL pins of our Nucleo board and define 24LC256 peripheral to make sure our test suite will run all available tests for ```24LC256```.
Let's configure our one MUT and set uARM as the only compiler we will use to compiler Mbed SDK and tests.
We also need to create two configuration files ```muts_all.json``` and ```test_spec.json``` to pass our small testbed configuration to test script.
muts_all.json:
```json
{
"1" : {
"mcu": "NUCLEO_F334R8",
"port":"COM46",
"disk":"E:\\",
"peripherals": ["24LC256"]
}
}
```
Note: By defining ```"peripherals": ["24LC256"]``` we are passing to test suite information that this particular board has EEPROM 24LC256 connected to our board.
test_spec.json:
```json
{
"targets": {
"NUCLEO_F334R8" : ["uARM"]
}
}
```
Note:
* Please make sure device is connected before we will start running tests.
* Please make sure files ```muts_all.json``` and ```test_spec.json``` are in ```mbed/tools/``` directory.
Now you can call test suite and execute tests:
```
$ python singletest.py -i test_spec.json -M muts_all.json
...
Test summary:
+--------+---------------+-----------+-----------+---------------------------------+--------------------+---------------+
| Result | Target | Toolchain | Test ID | Test Description | Elapsed Time (sec) | Timeout (sec) |
+--------+---------------+-----------+-----------+---------------------------------+--------------------+---------------+
| OK | NUCLEO_F334R8 | uARM | MBED_A25 | I2C EEPROM line read/write test | 12.41 | 15 |
| OK | NUCLEO_F334R8 | uARM | MBED_A1 | Basic | 3.42 | 10 |
| OK | NUCLEO_F334R8 | uARM | EXAMPLE_1 | /dev/null | 3.42 | 10 |
| OK | NUCLEO_F334R8 | uARM | MBED_24 | Timeout Int us | 11.47 | 15 |
| OK | NUCLEO_F334R8 | uARM | MBED_25 | Time us | 11.43 | 15 |
| OK | NUCLEO_F334R8 | uARM | MBED_26 | Integer constant division | 3.37 | 10 |
| OK | NUCLEO_F334R8 | uARM | MBED_23 | Ticker Int us | 12.43 | 15 |
| OK | NUCLEO_F334R8 | uARM | MBED_A19 | I2C EEPROM read/write test | 11.42 | 15 |
| OK | NUCLEO_F334R8 | uARM | MBED_11 | Ticker Int | 12.43 | 20 |
| OK | NUCLEO_F334R8 | uARM | MBED_10 | Hello World | 2.42 | 10 |
| OK | NUCLEO_F334R8 | uARM | MBED_12 | C++ | 3.42 | 10 |
| OK | NUCLEO_F334R8 | uARM | MBED_16 | RTC | 4.76 | 15 |
| UNDEF | NUCLEO_F334R8 | uARM | MBED_2 | stdio | 20.42 | 20 |
| UNDEF | NUCLEO_F334R8 | uARM | MBED_A9 | Serial Echo at 115200 | 10.37 | 10 |
+--------+---------------+-----------+-----------+---------------------------------+--------------------+---------------+
Result: 2 UNDEF / 12 OK
Completed in 160 sec
```
If we want to get additional test summary with results in separate columns please use option ```-t```.
```
$ python singletest.py -i test_spec.json -M muts_all.json -t
...
Test summary:
+---------------+-----------+---------------------------------+-------+
| Target | Test ID | Test Description | uARM |
+---------------+-----------+---------------------------------+-------+
| NUCLEO_F334R8 | EXAMPLE_1 | /dev/null | OK |
| NUCLEO_F334R8 | MBED_10 | Hello World | OK |
| NUCLEO_F334R8 | MBED_11 | Ticker Int | OK |
| NUCLEO_F334R8 | MBED_12 | C++ | OK |
| NUCLEO_F334R8 | MBED_16 | RTC | OK |
| NUCLEO_F334R8 | MBED_2 | stdio | UNDEF |
| NUCLEO_F334R8 | MBED_23 | Ticker Int us | OK |
| NUCLEO_F334R8 | MBED_24 | Timeout Int us | OK |
| NUCLEO_F334R8 | MBED_25 | Time us | OK |
| NUCLEO_F334R8 | MBED_26 | Integer constant division | OK |
| NUCLEO_F334R8 | MBED_A1 | Basic | OK |
| NUCLEO_F334R8 | MBED_A19 | I2C EEPROM read/write test | OK |
| NUCLEO_F334R8 | MBED_A25 | I2C EEPROM line read/write test | OK |
| NUCLEO_F334R8 | MBED_A9 | Serial Echo at 115200 | UNDEF |
+---------------+-----------+---------------------------------+-------+
```
----
Please do not forget you can combine few options together to get result you want. For example you want to repeat few tests multiple number of times, shuffle test ids execution order and select only tests which are critical for you at this point. You can do it using switch -n, --global-loops with --loops and --shuffle:
Execute above command to:
* Run only tests: ```RTOS_1```, ```RTOS_2```, ```RTOS_3```, ```MBED_10```, ```MBED_16```, ```MBED_11```.
* Shuffle test execution order. Note tests in loops will not be shuffled.
* Set global loop count to 3 - each test will repeated 3 times.
* Overwrite global loop count (set above to 3) and:
* Force to loop test RTOS_1 to execute 3 times.
* Force to loop test RTOS_2 to execute 4 times.
* Force to loop test RTOS_3 to execute 5 times.
* Force to loop test MBED_11 to execute 5 times.
```
$ python singletest.py -i test_spec.json -M muts_all.json -n RTOS_1,RTOS_2,RTOS_3,MBED_10,MBED_16,MBED_11 --shuffle --global-loops 3 --loops RTOS_1=3,RTOS_2=4,RTOS_3=5,MBED_11=5
```
# CppUTest unit test library support
## CppUTest in Mbed SDK testing introduction
[CppUTest](http://cpputest.github.io/) is a C / C++ based unit xUnit test framework for unit testing and for test-driving your code. It is written in C++ but is used in C and C++ projects and frequently used in embedded systems but it works for any C / C++ project.
Mbed SDK test suite supports writing tests using CppUTest. All you need to do it to provide CppUTest sources and includes with Mbed SDK port. This is already done for you so all you need to do it to get proper sources in your project directory.
CppUTests core design principles are:
* Simple in design and simple in use.
* Portable to old and new platforms.
* Build with Test-driven Development in mind.
## From where you can get more help about CppUTest library and unit testing
• You can read [CppUTest manual](http://cpputest.github.io/manual.html)
* [CppUTest forum](https://groups.google.com/forum/?fromgroups#!forum/cpputest)
* [CppUTest on GitHub](https://github.com/cpputest/cpputest)
* Finally, if you think unit testing is new concept for you, you can have a grasp of it on Wikipedia pages about [unit testing](http://en.wikipedia.org/wiki/Unit_testing) and continue from there.
## How to add CppUTest to your current Mbed SDK installation
### Do I need CppUTest port for Mbed SDK?
Yes, you do. If you want to use CppUTest with Mbed SDK you need to have CppUTest version with ARMCC compiler (only ARM flavor for now) port and Mbed SDK console port (if you want to have output on serial port). All is already prepared by Mbed engineers and you can get it for example here: http://mbed.org/users/rgrover1/code/CppUTest/
### Prerequisites
* Installed [git client](http://git-scm.com/downloads/).
* Installed [Mercurial client](http://mercurial.selenic.com/).
### How / where to install
We want to create directory structure similar to one below:
```
\your_project_directory
├───cpputest
│ ├───include
│ └───src
└───mbed
├───libraries
├───travis
└───tools
```
Please go to directory with your project. For example it could be c:\Projects\Project.
```
$ cd c:\Projects\Project
```
If your project directory already has your mbed SDK repository included just execute below command (Mercurial console client). It should download CppUTest with Mbed SDK port.
```
$ hg clone https://mbed.org/users/rgrover1/code/cpputest/
```
You should see something like this after you execute Mercurial clone command:
```
$ hg clone https://mbed.org/users/rgrover1/code/cpputest/
destination directory: cpputest
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 69 changes to 42 files
updating to branch default
41 files updated, 0 files merged, 0 files removed, 0 files unresolved
```
Confirm your project structure. It should look more or less like this:
```
$ ls
cpputest mbed
```
From now on CppUTest is in correct path. Each time you want to compile unit tests for CppUTest build script will always look for CppUTest library in the same directory where mbed library is.
## New off-line mbed SDK project with CppUTest support
If you are creating new mbed SDK project and you want to use CppUTest with it you need to download both mbed SDK and CppUTest with mbed port to the same directory. You can do it like this:
```
$ cd c:\Projects\Project
$ git clone https://github.com/mbedmicro/mbed.git
$ hg clone https://mbed.org/users/rgrover1/code/cpputest/
```
After above three steps you should have proper directory structure. All you need to do now is to configure your ```mbed_settings.py``` in ```mbed``` directory. Please refer to mbed SDK build script documentation for details.
## CppUTest with mbed port
To make sure you actualy have CppUTest library with mbed SDK port you can go to CppUTest ```armcc``` platform directory:
```
$ cd c:/Projects/Project/cpputest/src/Platforms/armcc/
```
And open file ```UtestPlatform.cpp```.
You should find part of code responsible for porting console on default serial port of the mbed device:
```c++
#include "Serial.h"
using namespace mbed;
int PlatformSpecificPutchar(int c)
{
/* Please modify this block for test results to be reported as
* console output. The following is a sample implementation using a
* Serial object connected to the console. */
#define NEED_TEST_REPORT_AS_CONSOLE_OUTPUT 1
#if NEED_TEST_REPORT_AS_CONSOLE_OUTPUT
extern Serial console;
#define NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE 1
#if NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE
/* CppUTest emits \n line terminators in its reports; some terminals
* need the linefeed (\r) in addition. */
if (c == '\n') {
console.putc('\r');
}
#endif /* #if NEED_LINE_FEED_IN_ADDITION_TO_NEWLINE */
return (console.putc(c));
#else /* NEED_TEST_REPORT_AS_CONSOLE_OUTPUT */
return (0);
#endif /* NEED_TEST_REPORT_AS_CONSOLE_OUTPUT */
}
```
You can find cpputest UT test runner main function in mbed sources: ```c:/Projects/Project/mbed/libraries/tests/utest/testrunner/testrunner.cpp```. Test runner code (in ```testrunner.cpp```) only defined console object and executes all unit tests:
```c++
#include "CommandLineTestRunner.h"
#include <stdio.h>
#include "mbed.h"
#include "testrunner.h"
#include "test_env.h"
/**
Object 'mbed_cpputest_console' is used to show prints on console.
It is declared in \cpputest\src\Platforms\armcc\UtestPlatform.cpp
*/
Serial mbed_cpputest_console(STDIO_UART_TX, STDIO_UART_RX);
int main(int ac, char** av) {
MBED_HOSTTEST_TIMEOUT(20);
MBED_HOSTTEST_SELECT(default_auto);
MBED_HOSTTEST_DESCRIPTION(Unit test);
MBED_HOSTTEST_START("UT");
unsigned failureCount = 0;
{
// Some compilers may not pass ac, av so we need to supply them ourselves
int ac = 2;
char* av[] = {__FILE__, "-v"};
failureCount = CommandLineTestRunner::RunAllTests(ac, av);
}
MBED_HOSTTEST_RESULT(failureCount == 0);
return failureCount;
}
```
## Unit test location
Unit tests source code is located in below directory: ```c:/Projects/Project/mbed/libraries/tests/utest/```
Each sub directory except testrunner contains compilable unit test source files with test groups and test cases. You can see utest structure below. Please note this is just example and in the future this directory will contain many sub directories with unit tests.
```
$ c:\Projects\Project\mbed\libraries\tests\utest> tree
utest
├───basic
├───semihost_fs
└───testrunner
```
## Define unit tests in mbed SDK test suite structure
All tests defined in test suite are described in ```mbed/tools/tests.py``` file. This file stores data structure ```TESTS``` which is a list of simple structures describing each test. Below you can find example of ```TESTS``` structure which is configuring one of the unit tests.
```
.
.
.
{
"id": "UT_2", "description": "Semihost file system",
"source_dir": join(TEST_DIR, "utest", "file"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
"automated": False,
"mcu": ["LPC1768", "LPC2368", "LPC11U24"]
},
.
.
.
```
Note: In dependency section we've added library ```CPPUTEST_LIBRARY``` which is pointing build script to CppUTest library with mbed port. This is a must for unit tests to be compiled with CppUTest library.
### Tests are now divided into two types:
#### 'Hello world' tests
First type of test cases we call 'hello world' tests. They do not dependent on CppUTest library and are monolithic programs usually composed of one main function. You can find this tests in below example directories:
* ```mbed/libraries/tests/mbed/```
* ```mbed/libraries/tests/net/```
* ```mbed/libraries/tests/rtos/```
* ```mbed/libraries/tests/usb/```
Usually hello world test cases are using ```test_env.cpp``` and ```test_env.h``` files which implement simple test framework used to communicate with host test and help test framework instrument your tests.
Below you can see listing of ```test_env.h``` file which contains simple macro definitions used to communicate (via serial port printouts) between test case (on hardware) and host test script (on host computer).
Each use case should print on console basic information like:
* Default test case timeout.
* Which host test should be used to supervise test case execution.
* Test description and test case ID (short identifier).
```c++
.
.
.
// Test result related notification functions
void notify_start();
void notify_completion(bool success);
bool notify_completion_str(bool success, char* buffer);
void notify_performance_coefficient(const char* measurement_name, const int value);
void notify_performance_coefficient(const char* measurement_name, const unsigned int value);
void notify_performance_coefficient(const char* measurement_name, const double value);
// Host test auto-detection API
void notify_host_test_name(const char *host_test);
void notify_timeout(int timeout);
void notify_test_id(const char *test_id);
void notify_test_description(const char *description);
// Host test auto-detection API
#define MBED_HOSTTEST_START(TESTID) notify_test_id(TESTID); notify_start()
#define MBED_HOSTTEST_SELECT(NAME) notify_host_test_name(#NAME)
#define MBED_HOSTTEST_TIMEOUT(SECONDS) notify_timeout(SECONDS)
#define MBED_HOSTTEST_DESCRIPTION(DESC) notify_test_description(#DESC)
#define MBED_HOSTTEST_RESULT(RESULT) notify_completion(RESULT)
/**
Test auto-detection preamble example:
main() {
MBED_HOSTTEST_TIMEOUT(10);
MBED_HOSTTEST_SELECT( host_test );
MBED_HOSTTEST_DESCRIPTION(Hello World);
MBED_HOSTTEST_START("MBED_10");
// Proper 'host_test.py' should take over supervising of this test
// Test code
bool result = ...;
MBED_HOSTTEST_RESULT(result);
}
*/
.
.
.
```
Example of 'hello world' test:
```c++
#include "mbed.h"
#include "test_env.h"
#define CUSTOM_TIME 1256729737
int main() {
MBED_HOSTTEST_TIMEOUT(20);
MBED_HOSTTEST_SELECT(rtc_auto);
MBED_HOSTTEST_DESCRIPTION(RTC);
MBED_HOSTTEST_START("MBED_16");
char buffer[32] = {0};
set_time(CUSTOM_TIME); // Set RTC time to Wed, 28 Oct 2009 11:35:37
while(1) {
time_t seconds = time(NULL);
strftime(buffer, 32, "%Y-%m-%d %H:%M:%S %p", localtime(&seconds));
printf("MBED: [%ld] [%s]\r\n", seconds, buffer);
wait(1);
}
}
```
#### 'Unit test' test cases
Second group of tests are unit tests. They are using CppUTest library and require you to write ```TEST_GROUP```s and ```TEST```s in your test files. Test suite will add test runner sources to your test automatically so you can concentrate on writing tests.
Example of unit test:
```c++
#include "TestHarness.h"
#include <utility>
#include "mbed.h"
TEST_GROUP(BusOut_mask)
{
};
TEST(BusOut_mask, led_1_2_3)
{
BusOut bus_data(LED1, LED2, LED3);
CHECK_EQUAL(0x07, bus_data.mask());
}
TEST(BusOut_mask, led_nc_nc_nc_nc)
{
BusOut bus_data(NC, NC, NC, NC);
CHECK_EQUAL(0x00, bus_data.mask());
}
TEST(BusOut_mask, led_1_2_3_nc_nc)
{
BusOut bus_data(LED1, LED2, LED3, NC, NC);
CHECK_EQUAL(0x07, bus_data.mask());
}
TEST(BusOut_mask, led_1_nc_2_nc_nc_3)
{
BusOut bus_data(LED1, NC, LED2, NC, NC, LED3);
CHECK_EQUAL(0x25, bus_data.mask());
}
```
## Example
In below example we will run two example unit tests that are now available. tests ```UT_1``` and ```UT_2``` are unit tests used for now only to check if mbed SDK works with CppUTest library and if tests are being executed. In future number of unit tests will increase, nothing is also stopping you from writing and executing your own unit tests!
### Example configuration
By default unit tests ```UT_1``` and ```UT_2``` are not automated - simply test suite will ignore them. Also we do not want to create dependency to CppUTest library each time someone executes automation.
Note: To compile ```UT_1``` and ```UT_2``` tests CppUTest library described above, installation is needed and not all users wish to add UT libs to their project. Also new to mbed users may find it difficult. This is why unit testing is an extra feature active only after you deliberately install and enable needed components.
Bellow snippet shows how to modify 'automated' flag so test suite will consider unit tests ```UT_1``` and ```UT_2``` as part of "automated test portfolio". Just change flag 'automated' from ```False``` to ```True```.
```tests.py``` listing related to ```UT_1``` and ```UT_2```:
```python
.
.
.
# CPPUTEST Library provides Unit testing Framework
#
# To write TESTs and TEST_GROUPs please add CPPUTEST_LIBRARY to 'dependencies'
#
# This will also include:
# 1. test runner - main function with call to CommandLineTestRunner::RunAllTests(ac, av)
# 2. Serial console object to print test result on serial port console
#
# Unit testing with cpputest library
{
"id": "UT_1", "description": "Basic",
"source_dir": join(TEST_DIR, "utest", "basic"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
"automated": True,
},
{
"id": "UT_2", "description": "Semihost file system",
"source_dir": join(TEST_DIR, "utest", "semihost_fs"),
"dependencies": [MBED_LIBRARIES, TEST_MBED_LIB, CPPUTEST_LIBRARY],
"automated": True,
"mcu": ["LPC1768", "LPC2368", "LPC11U24"]
},
.
.
.
```
### Execute tests
In my test I will use common [LPC1768](http://developer.mbed.org/platforms/mbed-LPC1768/) mbed-enabled board because unit test ```UT_2``` is checking semi-host functionality which is available on this board and handful of others.
Configure your ```test_spec.json``` and ```muts_all.json``` files (refer to test suite build script and automation description) and set mbed disk and serial port.
```
$ singletest.py -i test_spec.json -M muts_all.json -n UT_1,UT_2 -V
Building library CMSIS (LPC1768, ARM)
Building library MBED (LPC1768, ARM)
Building library CPPUTEST (LPC1768, ARM)
Building project BASIC (LPC1768, ARM)
Executing 'python host_test.py -p COM77 -d E:\ -t 10'
Test::Output::Start
Host test instrumentation on port: "COM77" and disk: "E:\"
TEST(FirstTestGroup, FirstTest) - 0 ms
OK (1 tests, 1 ran, 3 checks, 0 ignored, 0 filtered out, 3 ms)
{{success}}
{{end}}
Test::Output::Finish
TargetTest::LPC1768::ARM::UT_1::Basic [OK] in 2.43 of 10 sec
Building library CPPUTEST (LPC1768, ARM)
Building project SEMIHOST_FS (LPC1768, ARM)
Executing 'python host_test.py -p COM77 -d E:\ -t 10'
Test::Output::Start
Host test instrumentation on port: "COM77" and disk: "E:\"
TEST(FirstTestGroup, FirstTest) - 9 ms
OK (1 tests, 1 ran, 10 checks, 0 ignored, 0 filtered out, 10 ms)
{{success}}
{{end}}
Test::Output::Finish
TargetTest::LPC1768::ARM::UT_2::Semihost file system [OK] in 2.43 of 10 sec
Test summary:
+--------+---------+-----------+---------+----------------------+--------------------+---------------+-------+
| Result | Target | Toolchain | Test ID | Test Description | Elapsed Time (sec) | Timeout (sec) | Loops |
+--------+---------+-----------+---------+----------------------+--------------------+---------------+-------+
| OK | LPC1768 | ARM | UT_1 | Basic | 2.43 | 10 | 1/1 |
| OK | LPC1768 | ARM | UT_2 | Semihost file system | 2.43 | 10 | 1/1 |
+--------+---------+-----------+---------+----------------------+--------------------+---------------+-------+
Result: 2 OK
Completed in 12.02 sec
```
You can compile unit tests using various number of supported compilers, below just few examples with working solutions:
```
Test summary:
+--------+---------+-----------+---------+----------------------+--------------------+---------------+-------+
| Result | Target | Toolchain | Test ID | Test Description | Elapsed Time (sec) | Timeout (sec) | Loops |
+--------+---------+-----------+---------+----------------------+--------------------+---------------+-------+
| OK | LPC1768 | ARM | UT_1 | Basic | 2.43 | 10 | 1/1 |
| OK | LPC1768 | ARM | UT_2 | Semihost file system | 2.43 | 10 | 1/1 |
| OK | LPC1768 | uARM | UT_1 | Basic | 2.43 | 10 | 1/1 |
| OK | LPC1768 | uARM | UT_2 | Semihost file system | 2.43 | 10 | 1/1 |
| OK | LPC1768 | GCC_ARM | UT_1 | Basic | 2.43 | 10 | 1/1 |
| OK | LPC1768 | GCC_ARM | UT_2 | Semihost file system | 2.43 | 10 | 1/1 |
| OK | LPC1768 | GCC_CR | UT_1 | Basic | 3.44 | 10 | 1/1 |
| OK | LPC1768 | GCC_CR | UT_2 | Semihost file system | 3.43 | 10 | 1/1 |
+--------+---------+-----------+---------+----------------------+--------------------+---------------+-------+
Result: 8 OK
Completed in 55.85 sec
```

View File

@ -1,72 +0,0 @@
# Toolchain Profiles User Perspective
A Toolchain or build system Profile is a set of flags that is garenteed to be passed to the underlieing compiler suite.
These flags are stored in a JSON file that may be merged with other JSON files of the same structure.
## JSON Toolchain Profile Format
The JSON object that represents a Toolchain Profile is a dict mapping from Toolchains, like `GCC_ARM`, to their flags, like `-O3`.
The structure is as follows: Each toolchain supported by a Toolchain Profile has an dict in the root dict.
This dict contains a mapping from a flag type to a list of flags that should be passed the corresponding part of the compiler suite.
The required flag types are:
| Key | Description |
|:---------|:--------------------------------------|
| `c` | Flags for the C Compiler |
| `cxx` | Flags for the C++ Compiler |
| `common` | Flags for both the C and C++ Compilers|
| `asm` | Flags for the Assembler |
## Example
An example of a Toolchain Profile is given below:
```json
{
"GCC_ARM": {
"common": ["-c", "-Wall", "-Wextra",
"-Wno-unused-parameter", "-Wno-missing-field-initializers",
"-fmessage-length=0", "-fno-exceptions", "-fno-builtin",
"-ffunction-sections", "-fdata-sections", "-funsigned-char",
"-MMD", "-fno-delete-null-pointer-checks",
"-fomit-frame-pointer", "-Os"],
"asm": ["-x", "assembler-with-cpp"],
"c": ["-std=gnu99"],
"cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"],
"ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r",
"-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r",
"-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit"]
},
"ARM": {
"common": ["-c", "--gnu", "-Otime", "--split_sections",
"--apcs=interwork", "--brief_diagnostics", "--restrict",
"--multibyte_chars", "-O3"],
"asm": [],
"c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"],
"cxx": ["--cpp", "--no_rtti", "--no_vla"],
"ld": []
},
"IAR": {
"common": [
"--no_wrap_diagnostics", "non-native end of line sequence", "-e",
"--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Oh"],
"asm": [],
"c": ["--vla"],
"cxx": ["--guard_calls", "--no_static_destruction"],
"ld": ["--skip_dynamic_initialization", "--threaded_lib"]
}
}
```
From this Toolchain profile, we can tell that:
- `GCC_ARM`, `ARM`, and `IAR` compiler suites are supported.
- The `ARM` C and C++ Compilers will be using optimization level `-O3`
- The `IAR` linker will skip dynamic initialization
- etc.
# Toolchain Profile API Perspective
The Toolchains no longer take in an optional argument, `build_profile`, that will contain a map from flag types to lists of flags.
This looks exactly the same in python as it does in the JSON format above.
The meaning of the flags, and which ones are required is the same as the User Perspective
A developer using the API must parse the User provided files themselves and extract the appropriate sub-dict from the file afterwards.
A convienence function that does this for a developer is `tools.options.extract_profile` and will call args_error when a Toolchain Profile JSON file does not provide flags for the selected Toolchain.

View File

@ -1,298 +0,0 @@
# About the configuration system
The mbed configuration system can be used to customize the compile time configuration of various mbed components (targets, libraries and applications). Each such component can define a number of *configuration parameters*. The values of these configuration parameters can then be *overridden* in various ways. Configuration is defined using [JSON](http://www.json.org/). Some examples of configuration parameters:
- the sampling period for a data acquisition application.
- the default stack size for a newly created OS thread.
- the receive buffer size of a serial communication library.
- the flash and RAM memory size of a mbed target.
The configuration system gathers and interprets all the configuration defined in the source tree. The output of the configuration system is a list of macros that are automatically defined when compiling the code.
# Defining configuration parameters
The configuration system understands configuration data defined in targets, libraries and applications. While there are some slight differences in the way the configuration system works in these cases, the configuration parameters are always defined in a JSON object called "config". An example is given below:
```
{
"config": {
"param1": {
"help": "The first configuration parameter",
"macro_name": "CUSTOM_MACRO_NAME",
"value": 0
},
"param2": {
"help": "The second configuration parameter",
"required": true
},
"param3": 10
}
}
```
The JSON fragment above defines 3 configuration parameters named `param1`, `param2` and `param3`. There are two ways to define a configuration parameter:
- the short way: by name and value. `param3` above is an example of a short definition for a parameter named `param3` with value `10`.
- the long way: by name and description (another JSON object), like `param1` and `param2` above. The JSON description object can have the following keys:
- `help`: an optional help message that describes the purpose of the parameter.
- `value`: an optional field that defines the value of the parameter.
- `required`: an optional key that specifies if the parameter **must** be given a value before compiling the code (`false` by default). It's not possible to compile a source tree with one or more required parameters that don't have a value. Generally, it makes sense to define a required parameter only when it doesn't have a `value` key.
- `macro_name`: an optional name for the macro defined at compile time for this configuration parameter. The configuration system will automatically figure out the corresponding macro name for a configuration parameter, but the user can override this automatically computed name by specifying `macro_name`.
Note that the name of a parameter in `config` can't contain a dot (`.`) character.
The configuration system automatically appends an *implicit prefix* to the name of each parameter, so you don't have to worry about a name clash if you define a parameter with the same name in a library and a target, for example. The implicit prefix is:
- **target.** if the parameter is defined in a target.
- **app.** if the parameter is defined in the application.
- the name of the library followed by a dot (.) if the parameter is defined in a library.
# Configuration data in libraries
Each mbed library can have an optional `mbed_lib.json` file located in the root folder of the library that defines its configuration. For a library called `mylib`, the configuration file could look like this:
```
{
"name": "mylib",
"config": {
"buffer_size": 1024,
"timer_period": {
"help": "The timer period (in us)",
"macro_name": "INTERNAL_GPTMR_PERIOD",
"required": true
},
"queue_size": {
"help": "Size of event queue (entries)",
"value": 10
}
},
"macros": ["MYMOD_MACRO1", "MYMOD_MACRO2=\"TEST\""],
"target_overrides": {
"K64F": {
"timer_period": 100,
"queue_size": 40
},
"NXP": {
"queue_size": 20,
"buffer_size": 128
}
}
}
```
In this JSON file:
- `name` is the name of the library. **This is a required field.**
- `config` defines the configuration parameters of the library, as explained [here](#defining-configuration-parameters).
- `macros` is a list of extra macros that will be defined when compiling a project that includes this library. A macro can be defined without a value (like `MYMOD_MACRO1` above) or with a value (like `MYMOD_MACRO2` above).
- `target_overrides` is a dictionary with target-specific values for the configuration parameters.
`target_overrides` is used to override the values of the parameters depending on the current compilation target. The keys in `target_overrides` are matched against toolchain *labels* (a description of mbed targets can be found [here](mbed_targets.md)). If a key inside `target_overrides` matches one of the target labels, the parameter values are changed according to the value of the key. In the example above:
- `config` is always processed first, independent of the target. `config` might define values for some of the parameters. In this case, `buffer_size` will be set to 1024, `queue_size` will be set to 10 and `timer_period` will not have a value.
- if the library is compiled for the `K64F` target, `timer_period` will be set to 100 and `queue_size` will be set to 40, since they are overridden by the `K64F` key in `target_overrides`. `buffer_size` will be set to 1024, as defined in `config`.
- assuming that `NXP` is a label defined by **all** NXP based targets, if the library is compiled for **any** `NXP` target (like `LPC1768` or `LPC11U24`), `buffer_size` will be set to 128 and `queue_size` will be set to 20, while `timer_period` will not have a value (since it doesn't get one neither in `config`, nor in the `NXP` override).
- the keys in `target_overrides` are processed in order: if a hypothetical target defines both `K64F` and `NXP` as labels, `timer_period` will be set to 100, `queue_size` will be set to 20 and `buffer_size` will be set to 128.
- if the library is compiled for a target that doesn't have `K64F` or `NXP` as labels, the values of the parameters will be the ones set in `config`.
Except `name`, all the above keys in the JSON file are optional, but if `target_overrides` is defined, `config` must also be defined.
As explained [here](#defining-configuration-parameters), the parameters have an implicit `mylib.` prefix. Outside `mylib`, `buffer_size` is accessible using the name `mylib.buffer_size`. An application will be able to override the value of this parameter, as described in [this section](#configuration-data-in-applications).
If the source tree has code for more than one library, each library needs its own `mbed_lib.json` file in its root folder.
# Configuration data in targets
Like libraries, targets can define their own configuration data. Additionally, tables can override the configuration of the target(s) they inherit from (for more details about how do define a target and target inheritance, check [this link](mbed_targets.md)). Target configuration data is defined in `targets.json` using `config`, as described [here](#defining-configuration-parameters). An example for a hypothetical `Base` target is given below:
```
"Base": {
"core": "Cortex-M0",
"extra_labels": ["BASE_LABEL"],
"config": {
"serial_console_speed": {
"help": "Baud rate of the serial console",
"value": 115200,
"macro_name": "MBED_SERIAL_UART_SPEED"
},
"stack_size": {
"help": "Initial stack size of the application",
"value": 128
}
}
}
```
Similar to libraries, the target defined parameters have an implicit prefix. For a target, the prefix is always called `target` (no matter what the actual target name is), so the above configuration parameters will be accessible outside the definition in `Base` (and any other target) as `target.serial_console_speed` and `target.stack_size`.
Targets can inherit from other targets, and their configuration data is also inherited. A target that inherits from one or more other targets can add new parameters in its own `config` section and can also override the configuration parameters defined by its parent(s) in a `overrides` section. For example:
```
"Derived": {
"inherits": ["Base"],
"extra_labels_add": ["NXP"],
"config": {
"my_own_config": {
"help": "My very own configuration parameter",
"value": 0
}
},
"overrides": {
"stack_size": 256
}
}
```
`Derived` above defines its own configuration parameter called `my_own_config` and inherits the configuration parameters from `Base`, so its configuration parameters are `serial_console_speed`, `stack_size` and `my_own_config`. It also overrides the value of the `stack_size` parameter defined in `Base`. This means that:
- when compiling for `Base`, the target will define two configuration parameters: `serial_console_speed` with the value 115200 and `stack_size` with the value 128.
- when compiling for `Derived`, the target will define three configuration parameters: `serial_console_speed` with the value 115200, `stack_size` with the value 256 and `my_own_config` with the value 0.
It is an error for a derived target to re-define a configuration parameter already defined by its parent(s) in its `config` section. It is also an error for a derived target to override a configuration parameter that was not defined by its parent(s) in its `overrides` section.
# Configuration data in applications
Like the configuration for targets and libraries, application configuration is optional; if it exists, it must be defined in a `mbed_app.json` file. Unlike library configuration, there can be a single `mbed_app.json` file in the source tree.
There are quite a few similarities between configuration data in applications and libraries:
- applications define their configuration parameters in the `config` section of `mbed_app.json`, as explained [here](#defining-configuration-parameters).
- applications can specify target-dependent values in their `target_overrides` section, as described in the [library configuration paragraph][#configuration-data-in-libraries) (but see below for differences).
- applications can define macros that will be define at compile time by declaring them in `macros`.
There are also a few differences:
- applications **can't** have a `name` key in `mbed_app.json`. The prefix for the configuration parameters defined in an application is always `app.`.
- applications can also override configuration of libraries and targets in addition to its own configuration in its `target_overrides` section.
The last point above is important. The application can freely override the configuration of any of the libraries it depends on, as well as the configuration data in targets, so it has complete control over the configuration of the whole build. For an application called myapp that depends on mylib above, the configuration can look like this:
```
{
"config": {
"welcome_string": {
"help": "The string printed on the display on start-up",
"value": "\"Hello!\""
}
},
"target_overrides": {
"*": {
"target.serial_console_speed": 2400,
"mylib.timer_period": 100
},
"Base": {
"target.serial_console_speed": 9600
}
}
}
```
`target_overrides` works a lot like it does in libraries, but there are a few differences:
- since the application can override any configuration parameter, it must specify them using their prefix (like `mylib.timer_period`). If an overridden parameter doesn't have a prefix, it is assumed that it is one of the parameters defined by the application in its own `config` section.
- the `*` key in `target_overrides` will match *any* target. It is possible to use the `*` key in a library's `target_overrides` too, but it'd make little sense to do so, since it will always override the values defined in the library's `config` section. In an application it might make sense to use the `*` key, since it can be used to override the configuration defined by the target or the dependent libraries, no matter which target is used for building.
Other than this, `target_overrides` works exactly like it does for libraries. Keys in `target_overrides` are still processed in the order they are defined, so for the example above, the `*` override is always processed first (since it matches all targets) and then `Base` is only processed for the `Base` target.
`myapp` above defines its own configuration parameter (`welcome_string`) and overrides the configuration in both the target (`target.serial_console_speed`) and its `mylib` dependency (`mylib.timer_period`):
- when compiling for `Base`, `app.welcome_string` will be set to `"Hello!"`, `target.serial_console_speed` will be set to 9600 (from the `Base` override) and `mylib.timer_period` will be set to 100 (from the `*` override).
- when compiling for `Derived`, `app.welcome_string` will be set to `"Hello!"`, `target.serial_console_speed` will be set to 2400 (from the `*` override) and `mylib.timer_period` will be set to 100 (also from the `*` override).
It is an error for the application configuration to override configuration parameters that were not defined.
## Overriding cumulative target attributes
Target configurations contain a set of cumulative attributes that can be manipulated in the application configuration. These attributes can be overriden as a normal configuration parameter, or manipulated with the special `attribute_add` and `attribute_remove` meta-attributes.
Cumulative attributes:
- features: List of features which will be compiled into the resulting binary and available at runtime. Determines the FEATURE directories included during compilation. These are also emitted as FEATURE macros.
- device_has: List of hardware components available on the target. These are emitted as DEVICE_HAS macros.
- extra_labels: List of target labels which determine the TARGET directories included during compilation. These are also emitted as TARGET macros.
- macros: List of target-specific macros that are defined during compilation.
For example, an application may want to remove features with extra space or runtime cost. This `mbed_app.json` will disable the IPV4 network stack. Attempting to use this network stack will result in a compilation error:
```
{
"target_overrides": {
"K64F": {
"target.features_remove": ["IPV4"]
}
}
}
```
# Configuration data precedence
The order in which the various bits of configurations are considered is this:
- the configuration defined by an inherited target overrides the configuration defined by its parent(s), as described [above](#configuration-data-in-targets).
- the configuration of the top level application overrides the configuration defined by the target and any of the libraries on which it depends.
For `myapp` above:
- the value of `target.serial_console_speed` will be 9600 when compiling for `Base` because of the `Base` override in myapp's `target_overrides`.
- the value of `target.serial_console_speed` will be 2400 when compiling for any other target because of the `*` override in myapp's `target_overrides`.
- the value of `target.stack_size` will be 256 when compiling for `Derived` and 128 when compiling for `Base` or any other target that derives from `Base` (assuming of course that `Derived` is the only target that redefines `stack_size`).
- the value of `mylib.timer_period` will be 100, since that's overridden by the application and thus takes precedence over the values defined in `mylib`.
- when compiling for `Base`, the values of `mylib.buffer_size` and `mylib.queue_size` will be 1024 and 10 respectively, as defined in the `config` section of `mylib`.
- when compiling for `Derived`, the values of `mylib.buffer_size `and `mylib.queue_size` will be 128 and 20 respectively, since `Derived` defines the `NXP` label and `mylib` defines a specific configuration for this label. Also, since `Derived` has its own `my_own_config` configuration parameter, `target.my_own_config` will also be defined in this case.
# Using configuration data in the code
When compiling, the configuration system will automatically generate macro definitions for the configuration parameters and all the macros defined in libraries and the application in their `macros` keys. These definitions will be written in a file named `mbed_config.h` located in the build directory. When compiling `myapp` for target `Base`, the `mbed_config.h` file will look like this (note that the order of the definitions might be different):
```
// Automatically generated configuration file.
// DO NOT EDIT, content will be overwritten.
#ifndef __MBED_CONFIG_DATA__
#define __MBED_CONFIG_DATA__
// Configuration parameters
#define MBED_CONF_MYAPP_WELCOME_STRING "Hello!" // set by application
#define MBED_SERIAL_UART_SPEED 9600 // set by application[Base]
#define MBED_CONF_TARGET_STACK_SIZE 128 // set by target
#define INTERNAL_GPTMR_PERIOD 100 // set by application[*]
#define MBED_CONF_MYLIB_BUFFER_SIZE 1024 // set by library:mylib
#define MBED_CONF_MYLIB_QUEUE_SIZE 10 // set by library:mylib
// Macros
#define MYMOD_MACRO1 // defined by library:mylib
#define MYMOD_MACRO2 "TEST" // defined by library:mylib
#endif
```
When compiling for `Derived`, `mbed_config.h` will look like this:
```
// Automatically generated configuration file.
// DO NOT EDIT, content will be overwritten.
#ifndef __MBED_CONFIG_DATA__
#define __MBED_CONFIG_DATA__
// Configuration parameters
#define MBED_CONF_MYAPP_WELCOME_STRING "Hello!" // set by application
#define MBED_SERIAL_UART_SPEED 2400 // set by application[*]
#define MBED_CONF_TARGET_STACK_SIZE 256 // set by target
#define MBED_CONF_TARGET_MY_OWN_CONFIG 0 // set by target
#define INTERNAL_GPTMR_PERIOD 100 // set by application[*]
#define MBED_CONF_MYLIB_BUFFER_SIZE 128 // set by library:mylib[NXP]
#define MBED_CONF_MYLIB_QUEUE_SIZE 20 // set by library:mylib[NXP]
// Macros
#define MYMOD_MACRO1 // defined by library:mylib
#define MYMOD_MACRO2 "TEST" // defined by library:mylib
#endif
```
Note that a macro definition will *not* be generated for a parameter that doesn't have a value.
The names of the macros for the configuration parameter (unless explicitly specified by `macro_name`) are prefixed by **MBED_CONF_**, followed by the full (prefixed) name of the parameter, capitalized and converted to a valid C macro name (if needed).
`mbed_config.h` will be included automatically by the toolchain in all compiled sources, so you'll have access to the configuration data without having to include `mbed_config.h` manually.
*Do not edit mbed_config.h manually*. It will be overwritten the next time you compile or export your project and all your changes will be lost.

View File

@ -1,139 +0,0 @@
# About the mbed OS event loop
One of the optional mbed OS features is an event loop mechanism that can be used to defer the execution of code in a different context. In particular, a common uses of an event loop is to postpone the execution of a code sequence from an interrupt handler to an user context. This is useful because of the specific constraints of code that runs in an interrupt handler:
- the execution of certain functions (notably some functions in the C library) is not safe.
- various RTOS objects and functions can't be used from an interrupt context.
- as a general rule, the code needs to finish as fast as possible, to allow other interrupts to be handled.
The event loop offers a solution to these issues in the form of an API that can be used to defer execution of code from the interrupt context to the user context. More generally, the event loop can be used anywhere in a program (not necessarily in an interrupt handler) to defer code execution to a different context.
# Overview of the mbed OS event loop
An event loop has two main components:
1. an **event queue**, used to store events. In mbed OS, *events* are pointers to functions (and optionally function arguments).
2. an **event loop** that extracts events from the queue and executes them.
The mbed OS event queue is implemented by the [mbed-events library](http://github.com/ARMmbed/mbed-os/tree/master/events). It's a good idea to go through the [README of mbed-events](https://github.com/ARMmbed/mbed-os/blob/master/events/README.md), as it shows how to use the event queue.
The event loop must be created and started manually. The simplest way to achieve that is to create a `Thread` and run the event queue's `dispatch` method in the thread:
```
#include "mbed.h"
#include "mbed_events.h"
// Create a queue that can hold a maximum of 32 events
Queue queue(32 * EVENTS_EVENT_SIZE);
// Create a thread that'll run the event queue's dispatch function
Thread t;
int main () {
// Start the event queue's dispatch thread
t.start(callback(&queue, &EventQueue::dispatch_forever));
...
}
```
Note that although this document assumes the presence of a single event loop in the system, there's nothing preventing the programmer to run more than one event loop, simply by following the create/start pattern above for each of them.
## Using the event loop
Once the event loop is created, it can be used for posting events. Let's consider a very simple example of a program that attaches two interrupt handlers for an InterruptIn object, using the InterruptIn `rise` and `fall` functions. The `rise` handler will run in interrupt context, while the `fall` handler will run in user context (more specifically, in the context of the event loop's thread). The full code for the example can be found below:
```
#include "mbed.h"
#include "mbed_events.h"
DigitalOut led1(LED1);
InterruptIn sw(SW2);
EventQueue queue(32 * EVENTS_EVENT_SIZE);
Thread t;
void rise_handler(void) {
printf("rise_handler in context %p\r\n", Thread::gettid());
// Toggle LED
led1 = !led1;
}
void fall_handler(void) {
printf("fall_handler in context %p\r\n", Thread::gettid());
// Toggle LED
led1 = !led1;
}
int main() {
// Start the event queue
t.start(callback(&queue, &EventQueue::dispatch_forever));
printf("Starting in context %p\r\n", Thread::gettid());
// The 'rise' handler will execute in IRQ context
sw.rise(rise_handler);
// The 'fall' handler will execute in the context of thread 't'
sw.fall(queue.event(fall_handler));
}
```
The above code executes two handler functions (`rise_handler` and `fall_handler`) in two different contexts:
1. in interrupt context when a rising edge is detected on `SW2` (`rise_handler`).
2. in the context of the event loop's thread function when a falling edge is detected on `SW2` (`fall_handler`). `queue.event()` is called with `fall_handler` as an argument to specify that `fall_handler` will run in user context instead of interrupt context.
This is the output of the above program on a FRDM-K64F board after resetting the board and pressing the SW2 button twice:
```
Starting in context 0x20002c50
fall_handler in context 0x20002c90
rise_handler in context 0x0
fall_handler in context 0x20002c90
rise_handler in context 0x0
```
The program starts in the context of the thread that runs the `main` function (`0x29992c5`). When the uses presses SW2, `fall_handler` is automatically queued in the event queue, and it runs later in the context of thread `t` (`0x20002c90`). When the user releases the button, `rise_handler` is executed immediately, and it displays `0x0`, indicating that the code runs in interrupt context.
The code for `rise_handler` is problematic, since it calls `printf` in interrupt context, which is a potentially unsafe operation. Fortunately, this is exactly the kind of problem that event queues can solve. We can make the code safe by running `rise_handler` in user context (like we already do with `fall_handler`) by replacing this line:
```
sw.rise(rise_handler);
```
with this line:
```
sw.rise(queue.event(rise_handler));
```
The code is safe now, but we might've introduced another problem: latency. After the change above, the call to `rise_handler` will be queued, which means that it doesn't run immediately after the interrupt is raised anymore. For this example code, this isn't a problem, but some applications might require the code to respond as fast as possible to an interrupt. Let's assume that `rise_handler` must toggle the LED as quickly as possible in response to the user's action on SW2. To do that, in must run in interrupt context. However, `rise_handler` still needs to print a message indicating that the handler was called, but that's problematic since it's not safe to call `printf` from an interrupt context. The solution is to split `rise_handler` in two parts: the time critical part will run in interrupt context, while the non-critical part (displaying the message) will run in user context. This is easily doable using `queue.call`:
```
void rise_handler_user_context(void) {
printf("rise_handler_user_context in context %p\r\n", Thread::gettid());
}
void rise_handler(void) {
// Execute the time critical part first
led1 = !led1;
// The rest can execute later in user context (and can contain code that's not interrupt safe).
// We use the 'queue.call' function to add an event (the call to 'rise_handler_user_context') to the queue.
queue.call(rise_handler_user_context);
}
```
After replacing the code for `rise_handler` as above, the output of our example becomes:
```
Starting in context 0x20002c50
fall_handler in context 0x20002c90
rise_handler_user_context in context 0x20002c90
fall_handler in context 0x20002c90
rise_handler_user_context in context 0x20002c90
```
The scenario above (splitting an interrupt handler's code into time critical code and non-time critical code) is another common pattern that's easily implemented with event queues. Another thing to learn from this example is that queuing code that's not interrupt safe is not the only thing that event queues can be used for. Any kind of code can be queued and deferred for later execution.
We used `InterruptIn` for the example above, but the same kind of code can be used with any `attach()`-like functions in the SDK. Example include `Serial::attach()`, `Ticker::attach()`, `Ticker::attach_us()`, `Timeout::attach()`.
## Where to go from here
We just scratched the surface of how event queues work in mbed OS. The `EventQueue` and `Event` classes in the `mbed-events` library offer a lot of features that are not covered in this document, including calling functions with arguments, queueing functions to be called after a delay, or queueing functions to be called periodically. The [README of the mbed-events library](https://github.com/ARMmbed/mbed-os/blob/master/events/README.md) shows more ways to use events and event queues. For more details about how the events library is implemented, check [this file](https://github.com/ARMmbed/mbed-os/blob/master/events/equeue/README.md).

View File

@ -1,49 +0,0 @@
# Ignoring files from mbed build
The `.mbedignore` file allows you to ignore files and directories from being processed by `mbed build` command.
## Usage
You can place the `.mbedignore` file in any directory where `mbed build` command is going to search for source files.
The most convenient place is the root directory of the library or application. However, this is not a requirement.
Avoid defining rules that would cross the library boundaries as those would lead to side effects or build problems that are hard to find.
## Syntax
Each line in the `.mbedignore` file is a file pattern used for matching files. Each matched file or directory is ignored from build.
The following wildcards are accepted:
|Pattern | Meaning|
|--------|--------|
| `*` | Matches everything. |
| `?` | Matches any single character. |
| `[seq]` | Matches any character in seq. |
| `[!seq]` | Matches any character not in seq. |
File is parsed with Python's [fnmatch](https://docs.python.org/2/library/fnmatch.html) functionality so the syntax follows basic shell patterns with the following exceptions:
1. Each line is internally prefixed with the path of the `.mbedignore` file.
2. Line cannot start with `.` or `/` (because of rule 1)
Globbing functionality is not used, so you cannot recursively match specific file pattern. You need to define rule per directory in that case.
Relative paths can be used, so you can match files deeper in the build tree. However, avoid crossing library boundaries.
### Example
A file located in `source/obsolete/.mbedignore` with following content:
```
*.c
*.h
second_level/*.c
```
After applying the rule 1, actual patterns used internally for matching the source files are:
```
source/obsolete/*.c
source/obsolete/*.h
source/obsolete/second_level/*.c
```

View File

@ -1,90 +0,0 @@
# memap - Static Memory Map Analysis
## Introduction
*memap* is a simple utility that displays static memory information required by [mbed](https://github.com/mbedmicro/mbed) applications. This information is produced by analysing the memory map file previously generated by your toolchain.
**Note**: this tool shows static RAM usage and the total size of allocated heap and stack space defined at compile time, not the actual heap and stack usage (which may be different depending on your application).
## Table of contents
1. [Using memap](#using-memap)
1. [Information on memory sections](#info-mem-sections)
1. [Current support](#current-support)
1. [Known problems](#known-problems)
## Using memap
*memap* is automatically invoked after an mbed build finishes successfully. It's also possible to manually run the program with different command line options, for example:
```
$> python memap.py
usage: memap.py [-h] -t TOOLCHAIN [-o OUTPUT] [-e EXPORT] [-v] file
Memory Map File Analyser for ARM mbed version 0.3.11
positional arguments:
file memory map file
optional arguments:
-h, --help show this help message and exit
-t TOOLCHAIN, --toolchain TOOLCHAIN
select a toolchain used to build the memory map file
(ARM, GCC_ARM, IAR)
-o OUTPUT, --output OUTPUT
output file name
-e EXPORT, --export EXPORT
export format (examples: 'json', 'csv-ci', 'table':
default)
-v, --version show program's version number and exit
```
Result example:
```
$> python memap.py GCC_ARM\myprog3.map -t GCC_ARM
+----------------------------+-------+-------+------+
| Module | .text | .data | .bss |
+----------------------------+-------+-------+------+
| Fill | 170 | 0 | 2294 |
| Misc | 36282 | 2220 | 2152 |
| core/hal | 15396 | 16 | 568 |
| core/rtos | 6751 | 24 | 2662 |
| features/FEATURE_IPV4 | 96 | 0 | 48 |
| frameworks/greentea-client | 912 | 28 | 44 |
| frameworks/utest | 3079 | 0 | 732 |
| Subtotals | 62686 | 2288 | 8500 |
+----------------------------+-------+-------+------+
Allocated Heap: 65540 bytes
Allocated Stack: 32768 bytes
Total Static RAM memory (data + bss): 10788 bytes
Total RAM memory (data + bss + heap + stack): 109096 bytes
Total Flash memory (text + data + misc): 66014 bytes
```
## Information on memory sections
The table above showed multiple memory sections.
- ``.text``: is where the code application and constants are located in Flash.
- ``.data``: non-zero initialized variables; allocated in both RAM and Flash memory (variables are copied from Flash to RAM at run time)
- ``.bss``: uninitialized data allocated in RAM, or variables initialized to zero.
- ``Heap``: dynamic allocations in the Heap area in RAM (for example, used by ``malloc``). The maximum size value may be defined at build time.
- ``Stack``: dynamic allocations in the Stack area in RAM (for example, used to store local data, temporary data when branching to a subroutine or context switch information). The maximum size value may be defined at build time.
There are other entries that require a bit of clarification:
- Fill: represents the bytes in multiple sections (RAM and Flash) that the toolchain has filled with zeros because it requires subsequent data or code to be aligned appropriately in memory.
- Misc: usually represents helper libraries introduced by the toolchain (like ``libc``), but can also represent modules that are not part of mbed.
## Current support
*memap* has been tested on Windows 7, Linux and Mac OS X and works with memory map files are generated by the GCC_ARM, ARM (ARM Compiler 5) and IAR toochains.
## Known issues and new features
This utility is considered 'alpha' quality at the moment. The information generated by this utility may not be fully accurate and may vary from one toolchain to another.
If you are experiencing problems, or would like additional features, please raise a ticket on [GitHub](https://github.com/mbedmicro/mbed/issues) and use ```[memap] ``` in the title.

View File

@ -1,5 +1,293 @@
# Change Log
## [v3.0.4](https://github.com/ARMmbed/mbed-client-c/releases/tag/v3.0.4) (23-dec-2016)
[Full Changelog](https://github.com/ARMmbed/mbed-client-c/compare/v3.0.2...v3.0.4)
**New feature**
- CoAP message ID randomization
- Initial memory optimized API added behind compile time flag
**Closed issues:**
- IOTCLT-1207 - sn_coap_builder_options_build_add_uint_option function produce wrong option value
- IOTCLT-828 / ARMmbed/mbed-client-c#59 - Random CoAP message ID
**Merged pull requests:**
commit 8d247d6baf16d7171dbc1d0e61383aeae59f9f20 (HEAD -> release-3.0.4, tag: v3.0.4, origin/release-3.0.4)
Author: Jaakko Kukkohovi <jaakko.kukkohovi@arm.com>
Date: Fri Dec 23 13:48:23 2016 +0200
version v3.0.4
commit 6f6d604dc9984dbae4bd183c4151be986de81a1b (origin/mem_opt_part_2, mem_opt_part_2)
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Thu Dec 22 20:12:48 2016 +0200
Make the code compile two different versions of the API
If one defines MBED_CLIENT_C_NEW_API, the new versions of
sn_grs and sn_nsdl are selected and old code will continue to work
as is if the define is not there.
commit 947bec9fd2a997a1f29633fa83f67fde40c16e0f
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Thu Dec 22 19:12:30 2016 +0200
Copy the changed files from memory_optimizations -branch to new name
commit a3de842af0b19c8760482cc451b7a2e8520547fb
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Thu Dec 22 18:46:13 2016 +0200
Copy the sn_nsdl and sn_grs files to fork the API via define
commit d6a4ece6c305a14030a97e340566893560c00496 (origin/master, origin/HEAD, master)
Author: Jaakko Kukkohovi <jaakko.kukkohovi@arm.com>
Date: Fri Dec 9 17:55:17 2016 +0200
Add application definable context to nsdl handle (#96)
Added application definable context field to nsdl handle. This is useful for example when interfacing with c++ objects where a pointer to object is set as the context, and in the callback functions the context pointer can be used to call methods for the correct instance of the c++ object.
commit e502b67a90ff96e52b98828e1e0c93d40071f171
Author: simosillankorva <simo.sillankorva@arm.com>
Date: Mon Nov 21 12:02:23 2016 +0200
Changed sn_coap_protocol.c to use randLIB for random message ID. (#91)
* Changed sn_coap_protocol.c to use randLIB for random message ID. randLIB now needed to build the coap library.
* Added randLIB dependency to module.json
* Added check for message_id==0 when randomizing, as we dont want to change the api for sn_nsdl.c, that uses it for error cases when sending some messages.
* Added randLiIB include path to unit tests.
* Added randLIB_stub for sn_coap_protocol unit test.
commit 4cdc3570f3a4dad1cef9787755718fec6917f8f2
Merge: cfe1e4e 2f7e733
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Nov 16 10:46:52 2016 +0200
Merge pull request #95 from ARMmbed/anttiylitokola-patch-1
Disable message duplication
commit 2f7e7333799082b59346173c8c12fc71fb93ccde
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Nov 16 09:45:38 2016 +0200
Disable message duplication
Message duplication is currently missing some features and it doesn't work reliable yet. Can be enabled again once "IOTCLT-1038
CoAP duplicate message detection missing features" is implemented.
commit cfe1e4e8c464a828eb6dfd4550b2f82831b0f489 (origin/memory_optimizations_base)
Author: Antti Kauppila <antti.kauppila@arm.com>
Date: Thu Nov 10 15:20:47 2016 +0200
Update sn_coap_builder.c
1 compilation warning fixed
commit e9c5e25492914bcd583e74ae14f71c9c8465398c
Merge: fc1f9eb c0bb893
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Nov 9 09:41:00 2016 +0200
Merge pull request #92 from ARMmbed/iotclt_1207
Fix CoAP option building
commit c0bb8936b9d44cda49611bfee9ae55969b717811
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Wed Nov 9 08:20:29 2016 +0200
Replace unnecessary started flag with len variable.
commit 1deac48ddb51a9e9d85ecb682b9b82c4072b5c44
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Tue Nov 8 14:20:34 2016 +0200
Fix CoAP option building
commit fc1f9eb790d08306ee435dd3a8452cfc82d7d740
Merge: 59be2f1 316a9db
Author: Yogesh Pande <yogpan01@users.noreply.github.com>
Date: Thu Nov 3 16:35:47 2016 +0200
Merge pull request #90 from ARMmbed/valgrind_unittest_fixes
Valgrind unittest fixes
commit 316a9dbb11cf2b842255655501c30a5d0d040ca7
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Tue Oct 25 19:24:57 2016 +0300
sn_coap_builder_unit_tests: fix 1976 valgrind errors
Fix 1976 valgrind errors for uninitialized memory accesses by
initializing the buffers before trying to parse them.
One example of error being fixed:
---8<---8<---8<---
==8405==
==8405== Conditional jump or move depends on uninitialised value(s)
==8405== at 0x40EA6E: sn_coap_builder_options_get_option_part_count (sn_coap_builder.c:926)
==8405== by 0x40E7CF: sn_coap_builder_options_calc_option_size (sn_coap_builder.c:834)
==8405== by 0x40CDA2: sn_coap_builder_calc_needed_packet_data_size_2 (sn_coap_builder.c:238)
==8405== by 0x40C8C5: sn_coap_builder_calc_needed_packet_data_size (sn_coap_builder.c:147)
==8405== by 0x404609: TEST_libCoap_builder_sn_coap_builder_calc_needed_packet_data_size_Test::testBody() (libCoap_builder_test.cpp:339)
==8405== by 0x418660: PlatformSpecificSetJmp (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
==8405== by 0x416C24: Utest::run() (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
==8405== by 0x4172DE: UtestShell::runOneTest(TestPlugin*, TestResult&) (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
==8405== by 0x418660: PlatformSpecificSetJmp (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
==8405== by 0x416B3B: UtestShell::runOneTestWithPlugins(TestPlugin*, TestResult&) (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
==8405== by 0x419F9D: TestRegistry::runAllTests(TestResult&) (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
==8405== by 0x4107D7: CommandLineTestRunner::runAllTests() (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_builder/sn_coap_builder_unit_tests)
commit 7fe1b032d117aec24bacf929bff72aee2d4b1000
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Tue Oct 25 17:32:26 2016 +0300
sn_nsdl_unit_tests: fix 23 valgrind errors
Fix 23 valgrind error for uninitialized memory accesses.
One example of warning being fixed:
---8<---8<---
==3916==
==3916== Conditional jump or move depends on uninitialised value(s)
==3916== at 0x418976: sn_coap_parser_release_allocated_coap_msg_mem (sn_coap_parser_stub.c:42)
==3916== by 0x420E3A: sn_nsdl_release_allocated_coap_msg_mem (sn_nsdl.c:2535)
==3916== by 0x417A92: test_sn_nsdl_release_allocated_coap_msg_mem (test_sn_nsdl.c:2885)
==3916== by 0x402E85: TEST_sn_nsdl_test_sn_nsdl_release_allocated_coap_msg_mem_Test::testBody() (sn_nsdltest.cpp:166)
==3916== by 0x42A8B0: PlatformSpecificSetJmp (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x428E74: Utest::run() (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x42952E: UtestShell::runOneTest(TestPlugin*, TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x42A8B0: PlatformSpecificSetJmp (in mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x428D8B: UtestShell::runOneTestWithPlugins(TestPlugin*, TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x42C1ED: TestRegistry::runAllTests(TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x422A27: CommandLineTestRunner::runAllTests() (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
==3916== by 0x422ACC: CommandLineTestRunner::runAllTestsMain() (in mbed-client-c/test/nsdl-c/unittest/sn_nsdl/sn_nsdl_unit_tests)
commit 36933741993f71dbd3e02521de5cf69876106030
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Tue Oct 25 16:38:02 2016 +0300
sn_grs_unit_tests: fix 4 valgrind errors
Fix 4 valgrind findings of uninitialized memory usage.
One example of error being fixed:
---8<----8<---
==30551==
==30551== Conditional jump or move depends on uninitialised value(s)
==30551== at 0x40F01B: sn_grs_convert_uri (sn_grs.c:949)
==30551== by 0x40E7E7: sn_grs_search_resource (sn_grs.c:769)
==30551== by 0x40D42F: sn_grs_process_coap (sn_grs.c:413)
==30551== by 0x40869C: test_sn_grs_process_coap (test_sn_grs.c:654)
==30551== by 0x401E7D: TEST_sn_grs_test_sn_grs_process_coap_Test::testBody() (sn_grstest.cpp:31)
==30551== by 0x418C20: PlatformSpecificSetJmp (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
==30551== by 0x4171E4: Utest::run() (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
==30551== by 0x41789E: UtestShell::runOneTest(TestPlugin*, TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
==30551== by 0x418C20: PlatformSpecificSetJmp (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
==30551== by 0x4170FB: UtestShell::runOneTestWithPlugins(TestPlugin*, TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
==30551== by 0x41A55D: TestRegistry::runAllTests(TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
==30551== by 0x410D97: CommandLineTestRunner::runAllTests() (in mbed-client-c/test/nsdl-c/unittest/sn_grs/sn_grs_unit_tests)
commit 1eebc512fe157227702b81684b36cb9bad179af2
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Tue Oct 25 16:13:35 2016 +0300
sn_coap_protocol_unit_tests: Fix 297 valgrind errors for unint. memory.
Fix 297 valgrind errors for uses of uninitialized memory. Most cases
were caused by same copy-pasted piece which allocated 3 bytes for a
buffer but used it as it was much, much larger.
One sample of the fixed error:
---8<---8<---
==22740== Invalid read of size 8
==22740== at 0x4C2F79E: memcpy@@GLIBC_2.14 (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22740== by 0x419329: sn_coap_protocol_build (sn_coap_protocol.c:492)
==22740== by 0x41268E: TEST_libCoap_protocol_sn_coap_protocol_exec_Test::testBody() (libCoap_protocol_test.cpp:2076)
==22740== by 0x427DE0: PlatformSpecificSetJmp (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x4263A4: Utest::run() (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x426A5E: UtestShell::runOneTest(TestPlugin*, TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x427DE0: PlatformSpecificSetJmp (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x4262BB: UtestShell::runOneTestWithPlugins(TestPlugin*, TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x42971D: TestRegistry::runAllTests(TestResult&) (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x41FF57: CommandLineTestRunner::runAllTests() (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x41FFFC: CommandLineTestRunner::runAllTestsMain() (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
==22740== by 0x42011E: CommandLineTestRunner::RunAllTests(int, char const**) (in mbed-client-c/test/nsdl-c/unittest/sn_coap_protocol/sn_coap_protocol_unit_tests)
commit 1393616579ff888dc23384cc5a50a8be3b7f9935
Author: Tero Jääskö <tero.jaasko@arm.com>
Date: Tue Oct 25 15:21:48 2016 +0300
sn_coap_parser_unit_tests: Fix uses of uninitialized memory.
Fix 10 valgrind erros for uses of uninitialized memory. All the errors
are caused by same root cause, where code allocated memory for test buffer
and assumed it contains something useful or predictable.
One error beind fixed:
--8<---8<---
==21841== Conditional jump or move depends on uninitialised value(s)
==21841== at 0x4093CA: sn_coap_parser_options_parse (sn_coap_parser.c:262)
==21841== by 0x408E5C: sn_coap_parser (sn_coap_parser.c:133)
==21841== by 0x403FBC: test_sn_coap_parser (test_sn_coap_parser.c:61)
==21841== by 0x401CFD: TEST_sn_coap_parser_test_sn_coap_parser_Test::testBody() (sn_coap_parsertest.cpp:20)
==21841== by 0x414350: PlatformSpecificSetJmp (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x412914: Utest::run() (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x412FCE: UtestShell::runOneTest(TestPlugin*, TestResult&) (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x414350: PlatformSpecificSetJmp (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x41282B: UtestShell::runOneTestWithPlugins(TestPlugin*, TestResult&) (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x415C8D: TestRegistry::runAllTests(TestResult&) (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x40C4C7: CommandLineTestRunner::runAllTests() (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
==21841== by 0x40C56C: CommandLineTestRunner::runAllTestsMain() (in /home/tero/work/mbed-github/mbed-client-c/test/nsdl-c/unittest/sn_coap_parser/sn_coap_parser_unit_tests)
commit 59be2f154af9b8388ae3e3e6a763cd5b0d2700f1 (tag: v3.0.3)
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Thu Sep 29 10:52:54 2016 +0300
version v3.0.3
commit 3b89e2a465c3876cc184c92c72bdbe66193502c7
Merge: 58f712b 4369a46
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Thu Sep 29 10:50:20 2016 +0300
Merge pull request #81 from ARMmbed/duplicate_fix
Fix for message duplication handling
commit 4369a4656e4a1ef5e81adf6316513d7a06e9a488
Author: Antti Yli-Tokola <antti.yli-tokola@arm.com>
Date: Thu Sep 29 09:19:36 2016 +0300
Fix one failing unit test
commit 72bfc3e7199d040b8bfa637e1840a0869f786231
Author: Tero Heinonen <tero.heinonen@arm.com>
Date: Wed Sep 28 13:54:56 2016 +0300
Enable duplicate message detection
commit 852c1f642afe7eb342016c76807d8b10a0fe7504
Author: Tero Heinonen <tero.heinonen@arm.com>
Date: Thu Sep 22 14:12:15 2016 +0300
Fix for message duplication handling
RFC 7252 chapter 4.5 talks only duplication of Confirmable- and
Non-confirmable messages. Adding check for message type before
processing duplication store and check.
## [v3.0.2](https://github.com/ARMmbed/mbed-client-c/releases/tag/v3.0.2) (24-Sep-2016)
[Full Changelog](https://github.com/ARMmbed/mbed-client-c/compare/v3.0.1...v3.0.2)

View File

@ -0,0 +1,45 @@
#
# Makefile for combined NSDL+COAP library
#
# Define compiler toolchain with CC or PLATFORM variables
# Example (GCC toolchains, default $CC and $AR are used)
# make
#
# OR (Cross-compile GCC toolchain)
# make PLATFORM=arm-linux-gnueabi-
#
# OR (armcc/Keil)
# make CC=armcc AR=ArmAR
#
# OR (IAR-ARM)
# make CC=iccarm
LIB = libnsdl.a
SRCS := \
source/libNsdl/src/sn_grs.c \
source/libNsdl/src/sn_nsdl.c \
source/libCoap/src/sn_coap_protocol.c \
source/libCoap/src/sn_coap_parser.c \
source/libCoap/src/sn_coap_header_check.c \
source/libCoap/src/sn_coap_builder.c \
override CFLAGS += -DVERSION='"$(VERSION)"'
override CFLAGS += -Isource/libNsdl/src/include/
override CFLAGS += -Isource/libCoap/src/include/
SERVLIB_DIR := ../libService
override CFLAGS += -I$(SERVLIB_DIR)/libService
override CFLAGS += -Insdl-c/
include ../libService/toolchain_rules.mk
$(eval $(call generate_rules,$(LIB),$(SRCS)))
.PHONY: release
release:
7z a nsdl-c_$(VERSION).zip *.a *.lib include
.PHONY: deploy_to
deploy_to: all
tar --transform 's,^,nsdl-c/,' --append -f $(TO) *.a nsdl-c

View File

@ -1,6 +1,6 @@
{
"name": "mbed-client-c",
"version": "3.0.2",
"version": "3.0.4",
"description": "Nanostack NSDL and COAP library",
"keywords": [
"coap",
@ -14,7 +14,8 @@
],
"dependencies": {
"nanostack-libservice": "^3.0.0",
"mbed-trace": ">=0.2.0,<2.0.0"
"mbed-trace": ">=0.2.0,<2.0.0",
"nanostack-randlib": "^1.2.0"
},
"targetDependencies": {}
}

View File

@ -25,6 +25,12 @@
#ifndef SN_NSDL_LIB_H_
#define SN_NSDL_LIB_H_
#ifdef MBED_CLIENT_C_NEW_API
#include "nsdl-c/sn_nsdl_lib2.h"
#else
#include "ns_list.h"
#ifdef __cplusplus
@ -723,8 +729,40 @@ extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size)
*/
extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count);
/**
* \fn void *sn_nsdl_set_context(const struct nsdl_s *handle, void *context)
*
* \brief Set the application defined context parameter for given handle.
* This is useful for example when interfacing with c++ objects where a
* pointer to object is set as the context, and in the callback functions
* the context pointer can be used to call methods for the correct instance
* of the c++ object.
*
* \param *handle Pointer to library handle
* \param *context Pointer to the application defined context
* \return 0 = success, -1 = failure
*/
extern int8_t sn_nsdl_set_context(struct nsdl_s * const handle, void * const context);
/**
* \fn void *sn_nsdl_get_context(const struct nsdl_s *handle)
*
* \brief Get the application defined context parameter for given handle.
* This is useful for example when interfacing with c++ objects where a
* pointer to object is set as the context, and in the callback functions
* the context pointer can be used to call methods for the correct instance
* of the c++ object.
*
* \param *handle Pointer to library handle
* \return Pointer to the application defined context
*/
extern void *sn_nsdl_get_context(const struct nsdl_s * const handle);
#ifdef __cplusplus
}
#endif
#endif /* MBED_CLIENT_C_NEW_API */
#endif /* SN_NSDL_LIB_H_ */

View File

@ -0,0 +1,666 @@
/*
* Copyright (c) 2011-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* \file sn_nsdl_lib.h
*
* \brief NanoService Devices Library header file
*
*
*/
#ifndef SN_NSDL_LIB_2_H_
#define SN_NSDL_LIB_2_H_
#ifdef MBED_CLIENT_C_NEW_API
#include "mbed-client-libservice/ns_list.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SN_NSDL_ENDPOINT_NOT_REGISTERED 0
#define SN_NSDL_ENDPOINT_IS_REGISTERED 1
/* Handle structure */
struct nsdl_s;
/**
* \brief Received device server security
*/
typedef enum omalw_server_security_ {
SEC_NOT_SET = -1,
PSK = 0,
RPK = 1,
CERTIFICATE = 2,
NO_SEC = 3
} omalw_server_security_t;
/**
* \brief Endpoint binding and mode
*/
typedef enum sn_nsdl_oma_binding_and_mode_ {
BINDING_MODE_NOT_SET = 0,
BINDING_MODE_U = 0x01,
BINDING_MODE_Q = 0x02,
BINDING_MODE_S = 0x04
} sn_nsdl_oma_binding_and_mode_t;
/**
* \brief Endpoint registration mode.
* If REGISTER_WITH_RESOURCES, endpoint sends list of all resources during registration.
* If REGISTER_WITH_TEMPLATE, endpoint sends registration without resource list. Device server must have
* correctly configured template.
*/
typedef enum sn_nsdl_registration_mode_ {
REGISTER_WITH_RESOURCES = 0,
REGISTER_WITH_TEMPLATE
} sn_nsdl_registration_mode_t;
/**
* \brief Endpoint registration parameters
*/
typedef struct sn_nsdl_ep_parameters_ {
uint8_t endpoint_name_len;
uint8_t domain_name_len;
uint8_t type_len;
uint8_t lifetime_len;
uint8_t location_len;
sn_nsdl_registration_mode_t ds_register_mode; /**< Defines registration mode */
sn_nsdl_oma_binding_and_mode_t binding_and_mode; /**< Defines endpoints binding and mode */
uint8_t *endpoint_name_ptr; /**< Endpoint name */
uint8_t *domain_name_ptr; /**< Domain to register. If null, NSP uses default domain */
uint8_t *type_ptr; /**< Endpoint type */
uint8_t *lifetime_ptr; /**< Endpoint lifetime in seconds. eg. "1200" = 1200 seconds */
uint8_t *location_ptr; /**< Endpoint location in server, optional parameter,default is NULL */
} sn_nsdl_ep_parameters_s;
/**
* \brief For internal use
*/
typedef struct sn_nsdl_sent_messages_ {
uint8_t message_type;
uint16_t msg_id_number;
ns_list_link_t link;
} sn_nsdl_sent_messages_s;
/**
* \brief Includes resource path
*/
typedef struct sn_grs_resource_ {
uint8_t pathlen;
uint8_t *path;
} sn_grs_resource_s;
/**
* \brief Table of created resources
*/
typedef struct sn_grs_resource_list_ {
uint8_t res_count; /**< Number of resources */
sn_grs_resource_s *res;
} sn_grs_resource_list_s;
/**
* \brief Resource access rights
*/
typedef enum sn_grs_resource_acl_ {
SN_GRS_GET_ALLOWED = 0x01 ,
SN_GRS_PUT_ALLOWED = 0x02,
SN_GRS_POST_ALLOWED = 0x04,
SN_GRS_DELETE_ALLOWED = 0x08
} sn_grs_resource_acl_e;
/**
* \brief Defines the resource mode
*/
typedef enum sn_nsdl_resource_mode_ {
SN_GRS_STATIC = 0, /**< Static resources have some value that doesn't change */
SN_GRS_DYNAMIC, /**< Dynamic resources are handled in application. Therefore one must give function callback pointer to them */
SN_GRS_DIRECTORY /**< Directory resources are unused and unsupported */
} sn_nsdl_resource_mode_e;
/**
* \brief Defines static parameters for the resource.
*/
typedef struct sn_nsdl_static_resource_parameters_ {
char *resource_type_ptr; //
char *interface_description_ptr; //
uint8_t *path; // convert to char*?
uint8_t *resource; /**< NULL if dynamic resource */
int16_t pathlen; /**< Address */ // Check type
uint16_t resourcelen; /**< 0 if dynamic resource, resource information in static resource */
bool external_memory_block:1; /**< 0 means block messages are handled inside this library,
otherwise block messages are passed to application */
unsigned mode:2; /**< STATIC etc.. */
bool free_on_delete:1; /**< 1 if struct is dynamic allocted --> to be freed */
} sn_nsdl_static_resource_parameters_s;
/**
* \brief Defines dynamic parameters for the resource.
*/
typedef struct sn_nsdl_resource_parameters_ {
uint8_t (*sn_grs_dyn_res_callback)(struct nsdl_s *,
sn_coap_hdr_s *,
sn_nsdl_addr_s *,
sn_nsdl_capab_e);
#ifdef MEMORY_OPTIMIZED_API
const sn_nsdl_static_resource_parameters_s *static_resource_parameters;
#else
sn_nsdl_static_resource_parameters_s *static_resource_parameters;
#endif
ns_list_link_t link;
uint16_t coap_content_type; /**< CoAP content type */
unsigned access:4; /**< Allowed operation mode, GET, PUT, etc,
TODO! This should be in static struct but current
mbed-client implementation requires this to be changed at runtime */
unsigned registered:2; /**< Is resource registered or not */
bool publish_uri:1; /**< 1 if resource to be published to server */
bool free_on_delete:1; /**< 1 if struct is dynamic allocted --> to be freed */
bool observable:1; /**< Is resource observable or not */
} sn_nsdl_dynamic_resource_parameters_s;
/**
* \brief Defines OMAlw server information
*/
typedef struct sn_nsdl_oma_server_info_ {
sn_nsdl_addr_s *omalw_address_ptr;
omalw_server_security_t omalw_server_security;
} sn_nsdl_oma_server_info_t;
/**
* \brief Defines endpoint parameters to OMA bootstrap.
*/
typedef struct sn_nsdl_bs_ep_info_ {
void (*oma_bs_status_cb)(sn_nsdl_oma_server_info_t *); /**< Callback for OMA bootstrap status */
void (*oma_bs_status_cb_handle)(sn_nsdl_oma_server_info_t *,
struct nsdl_s *); /**< Callback for OMA bootstrap status with nsdl handle */
} sn_nsdl_bs_ep_info_t;
/**
* \fn struct nsdl_s *sn_nsdl_init (uint8_t (*sn_nsdl_tx_cb)(sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
* uint8_t (*sn_nsdl_rx_cb)(sn_coap_hdr_s *, sn_nsdl_addr_s *),
* sn_nsdl_mem_s *sn_memory)
*
* \brief Initialization function for NSDL library. Initializes NSDL, GRS, HTTP and CoAP.
*
* \param *sn_nsdl_tx_callback A callback function for sending messages.
*
* \param *sn_nsdl_rx_callback A callback function for parsed messages. If received message is not CoAP protocol message (eg. ACK), message for GRS (GET, PUT, POST, DELETE) or
* reply for some DS messages (register message etc.), rx callback will be called.
*
* \param *sn_memory Memory structure which includes function pointers to the allocation and free functions.
*
* \return pointer to created handle structure. NULL if failed
*/
struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *),
uint8_t (*sn_nsdl_rx_cb)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
void *(*sn_nsdl_alloc)(uint16_t), void (*sn_nsdl_free)(void *));
/**
* \fn extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr);
*
* \brief Registers endpoint to mbed Device Server.
* \param *handle Pointer to nsdl-library handle
* \param *endpoint_info_ptr Contains endpoint information.
*
* \return registration message ID, 0 if failed
*/
extern uint16_t sn_nsdl_register_endpoint(struct nsdl_s *handle, sn_nsdl_ep_parameters_s *endpoint_info_ptr);
/**
* \fn extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle)
*
* \brief Sends unregister-message to mbed Device Server.
*
* \param *handle Pointer to nsdl-library handle
*
* \return unregistration message ID, 0 if failed
*/
extern uint16_t sn_nsdl_unregister_endpoint(struct nsdl_s *handle);
/**
* \fn extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len);
*
* \brief Update the registration with mbed Device Server.
*
* \param *handle Pointer to nsdl-library handle
* \param *lt_ptr Pointer to lifetime value string in ascii form, eg. "1200"
* \param lt_len Length of the lifetime string
*
* \return registration update message ID, 0 if failed
*/
extern uint16_t sn_nsdl_update_registration(struct nsdl_s *handle, uint8_t *lt_ptr, uint8_t lt_len);
/**
* \fn extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len);
*
* \brief Sets the location receievd from Device Server.
*
* \param *handle Pointer to nsdl-library handle
* \param *lt_ptr Pointer to location value string , eg. "s322j4k"
* \param lt_len Length of the location string
*
* \return success, 0 if failed -1
*/
extern int8_t sn_nsdl_set_endpoint_location(struct nsdl_s *handle, uint8_t *location_ptr, uint8_t location_len);
/**
* \fn extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle)
*
* \brief Checks if endpoint is registered.
*
* \param *handle Pointer to nsdl-library handle
*
* \return 1 Endpoint registration is done successfully
* \return 0 Endpoint is not registered
*/
extern int8_t sn_nsdl_is_ep_registered(struct nsdl_s *handle);
/**
* \fn extern void sn_nsdl_nsp_lost(struct nsdl_s *handle);
*
* \brief A function to inform mbed Device C client library if application detects a fault in mbed Device Server registration.
*
* \param *handle Pointer to nsdl-library handle
*
* After calling this function sn_nsdl_is_ep_registered() will return "not registered".
*/
extern void sn_nsdl_nsp_lost(struct nsdl_s *handle);
/**
* \fn extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len,
* uint8_t *payload_ptr, uint16_t payload_len,
* sn_coap_observe_e observe,
* sn_coap_msg_type_e message_type, sn_coap_content_format_e content_format)
*
*
* \brief Sends observation message to mbed Device Server
*
* \param *handle Pointer to nsdl-library handle
* \param *token_ptr Pointer to token to be used
* \param token_len Token length
* \param *payload_ptr Pointer to payload to be sent
* \param payload_len Payload length
* \param observe Observe option value to be sent
* \param message_type Observation message type (confirmable or non-confirmable)
* \param content_format Observation message payload content format
*
* \return !0 Success, observation messages message ID
* \return 0 Failure
*/
extern uint16_t sn_nsdl_send_observation_notification(struct nsdl_s *handle, uint8_t *token_ptr, uint8_t token_len,
uint8_t *payload_ptr, uint16_t payload_len,
sn_coap_observe_e observe,
sn_coap_msg_type_e message_type,
sn_coap_content_format_e content_format);
/**
* \fn extern uint32_t sn_nsdl_get_version(void)
*
* \brief Version query function.
*
* Used to retrieve the version information from the mbed Device C Client library.
*
* \return Pointer to library version string
*/
extern char *sn_nsdl_get_version(void);
/**
* \fn extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src)
*
* \brief To push CoAP packet to mbed Device C Client library
*
* Used to push an CoAP packet to mbed Device C Client library for processing.
*
* \param *handle Pointer to nsdl-library handle
*
* \param *packet Pointer to a uint8_t array containing the packet (including the CoAP headers).
* After successful execution this array may contain the response packet.
*
* \param *packet_len Pointer to length of the packet. After successful execution this array may contain the length
* of the response packet.
*
* \param *src Pointer to packet source address information. After successful execution this array may contain
* the destination address of the response packet.
*
* \return 0 Success
* \return -1 Failure
*/
extern int8_t sn_nsdl_process_coap(struct nsdl_s *handle, uint8_t *packet, uint16_t packet_len, sn_nsdl_addr_s *src);
/**
* \fn extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time);
*
* \brief CoAP retransmission function.
*
* Used to give execution time for the mbed Device C Client library for retransmissions.
*
* \param *handle Pointer to nsdl-library handle
*
* \param time Time in seconds.
*
* \return 0 Success
* \return -1 Failure
*/
extern int8_t sn_nsdl_exec(struct nsdl_s *handle, uint32_t time);
#ifndef MEMORY_OPTIMIZED_API
/**
* \fn extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, const sn_nsdl_resource_parameters_s *res);
*
* \brief Resource creating function.
*
* Used to create a static or dynamic CoAP resource.
*
* \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information
* about the resource.
*
* \return 0 Success
* \return -1 Failure
* \return -2 Resource already exists
* \return -3 Invalid path
* \return -4 List adding failure
*/
extern int8_t sn_nsdl_create_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
/**
* \fn extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_resource_parameters_s *res)
*
* \brief Resource updating function.
*
* Used to update the direct value of a static resource, the callback function pointer of a dynamic resource
* and access rights of the recource.
*
* \param *handle Pointer to nsdl-library handle
* \param *res Pointer to a structure of type sn_nsdl_resource_info_t that contains the information
* about the resource. Only the pathlen and path elements are evaluated along with
* either resourcelen and resource or the function pointer.
*
* \return 0 Success
* \return -1 Failure
*/
extern int8_t sn_nsdl_update_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
#endif
/**
* \fn extern int8_t sn_nsdl_put_resource(struct nsdl_s *handle, const sn_nsdl_dynamic_resource_parameters_s *res);
*
* \brief Resource putting function.
*
* Used to put a static or dynamic CoAP resource without creating copy of it.
* NOTE: Remember that only resource will be owned, not data that it contains
* NOTE: The resource may be removed from list by sn_nsdl_pop_resource().
*
* \param *res Pointer to a structure of type sn_nsdl_dynamic_resource_parameters_s that contains the information
* about the resource.
*
* \return 0 Success
* \return -1 Failure
* \return -2 Resource already exists
* \return -3 Invalid path
* \return -4 List adding failure
*/
extern int8_t sn_nsdl_put_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
/**
* \fn extern int8_t sn_nsdl_pop_resource(struct nsdl_s *handle, const sn_nsdl_dynamic_resource_parameters_s *res);
*
* \brief Resource popping function.
*
* Used to remove a static or dynamic CoAP resource from lists without deleting it.
* NOTE: This function is a counterpart of sn_nsdl_put_resource().
*
* \param *res Pointer to a structure of type sn_nsdl_dynamic_resource_parameters_s that contains the information
* about the resource.
*
* \return 0 Success
* \return -1 Failure
* \return -3 Invalid path
*/
extern int8_t sn_nsdl_pop_resource(struct nsdl_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
/**
* \fn extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint8_t pathlen, uint8_t *path)
*
* \brief Resource delete function.
*
* Used to delete a resource. If resource has a subresources, these all must also be removed.
*
* \param *handle Pointer to nsdl-library handle
* \param pathlen Contains the length of the path that is to be deleted (excluding possible trailing "\0").
* \param *path_ptr A pointer to an array containing the path.
*
* \return 0 Success
* \return -1 Failure (No such resource)
*/
extern int8_t sn_nsdl_delete_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path);
/**
* \fn extern sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path)
*
* \brief Resource get function.
*
* Used to get a resource.
*
* \param *handle Pointer to nsdl-library handle
* \param pathlen Contains the length of the path that is to be returned (excluding possible trailing '\0').
* \param *path A pointer to an array containing the path.
*
* \return !NULL Success, pointer to a sn_nsdl_dynamic_resource_parameters_s that contains the resource information\n
* \return NULL Failure
*/
extern sn_nsdl_dynamic_resource_parameters_s *sn_nsdl_get_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path);
/**
* \fn extern sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path)
*
* \brief Resource list function.
*
* \param *handle Pointer to nsdl-library handle
* \param pathlen Contains the length of the target path (excluding possible trailing '\0').
* The length value is not examined if the path itself is a NULL pointer.
* \param *path A pointer to an array containing the path or a NULL pointer.
*
* \return !NULL A pointer to a sn_grs_resource_list_s structure containing the resource listing.
* \return NULL Failure with an unspecified error
*/
sn_grs_resource_list_s *sn_nsdl_list_resource(struct nsdl_s *handle, uint16_t pathlen, uint8_t *path);
/**
* \fn extern void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list)
*
* \brief Free a resource list obtained from sn_nsdl_list_resource()
*
* \param list The list to free, or NULL.
*/
void sn_nsdl_free_resource_list(struct nsdl_s *handle, sn_grs_resource_list_s *list);
/**
* \fn extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
*
* \brief Send an outgoing CoAP request.
*
* \param *handle Pointer to nsdl-library handle
* \param *address_ptr Pointer to source address struct
* \param *coap_hdr_ptr Pointer to CoAP message to be sent
*
* \return 0 Success
* \return -1 Failure
*/
extern int8_t sn_nsdl_send_coap_message(struct nsdl_s *handle, sn_nsdl_addr_s *address_ptr, sn_coap_hdr_s *coap_hdr_ptr);
/**
* \fn extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type);
*
* \brief This function is used to set the mbed Device Server address given by an application.
*
* \param *handle Pointer to nsdl-library handle
* \return 0 Success
* \return -1 Failed to indicate that internal address pointer is not allocated (call nsdl_init() first).
*/
extern int8_t set_NSP_address(struct nsdl_s *handle, uint8_t *NSP_address, uint8_t address_length, uint16_t port, sn_nsdl_addr_type_e address_type);
/**
* \fn extern int8_t sn_nsdl_destroy(struct nsdl_s *handle);
*
* \param *handle Pointer to nsdl-library handle
* \brief This function releases all allocated memory in mbed Device C Client library.
*/
extern int8_t sn_nsdl_destroy(struct nsdl_s *handle);
/**
* \fn extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr);
*
* \brief Starts OMA bootstrap process
*
* \param *handle Pointer to nsdl-library handle
*
* \return bootstrap message ID, 0 if failed
*/
extern uint16_t sn_nsdl_oma_bootstrap(struct nsdl_s *handle, sn_nsdl_addr_s *bootstrap_address_ptr, sn_nsdl_ep_parameters_s *endpoint_info_ptr, sn_nsdl_bs_ep_info_t *bootstrap_endpoint_info_ptr);
/**
* \fn sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code)
*
* \brief Prepares generic response packet from a request packet. This function allocates memory for the resulting sn_coap_hdr_s
*
* \param *handle Pointer to library handle
* \param *coap_packet_ptr The request packet pointer
* \param msg_code response messages code
*
* \return *coap_packet_ptr The allocated and pre-filled response packet pointer
* NULL Error in parsing the request
*
*/
extern sn_coap_hdr_s *sn_nsdl_build_response(struct nsdl_s *handle, sn_coap_hdr_s *coap_packet_ptr, uint8_t msg_code);
/**
* \brief Allocates and initializes options list structure
*
* \param *handle Pointer to library handle
* \param *coap_msg_ptr is pointer to CoAP message that will contain the options
*
* If the message already has a pointer to an option structure, that pointer
* is returned, rather than a new structure being allocated.
*
* \return Return value is pointer to the CoAP options structure.\n
* In following failure cases NULL is returned:\n
* -Failure in given pointer (= NULL)\n
* -Failure in memory allocation (malloc() returns NULL)
*/
extern sn_coap_options_list_s *sn_nsdl_alloc_options_list(struct nsdl_s *handle, sn_coap_hdr_s *coap_msg_ptr);
/**
* \fn void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr)
*
* \brief Releases memory of given CoAP message
*
* Note!!! Does not release Payload part
*
* \param *handle Pointer to library handle
*
* \param *freed_coap_msg_ptr is pointer to released CoAP message
*/
extern void sn_nsdl_release_allocated_coap_msg_mem(struct nsdl_s *handle, sn_coap_hdr_s *freed_coap_msg_ptr);
/**
* \fn int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_intervall)
*
* \brief If re-transmissions are enabled, this function changes resending count and interval.
*
* \param *handle Pointer to library handle
* \param uint8_t resending_count max number of resendings for message
* \param uint8_t resending_intervall message resending intervall in seconds
* \return 0 = success, -1 = failure
*/
extern int8_t sn_nsdl_set_retransmission_parameters(struct nsdl_s *handle, uint8_t resending_count, uint8_t resending_interval);
/**
* \fn int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle, uint8_t buffer_size_messages, uint16_t buffer_size_bytes)
*
* \brief If re-transmissions are enabled, this function changes message retransmission queue size.
* Set size to '0' to disable feature. If both are set to '0', then re-sendings are disabled.
*
* \param *handle Pointer to library handle
* \param uint8_t buffer_size_messages queue size - maximum number of messages to be saved to queue
* \param uint8_t buffer_size_bytes queue size - maximum size of messages saved to queue
* \return 0 = success, -1 = failure
*/
extern int8_t sn_nsdl_set_retransmission_buffer(struct nsdl_s *handle,
uint8_t buffer_size_messages, uint16_t buffer_size_bytes);
/**
* \fn int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size)
*
* \brief If block transfer is enabled, this function changes the block size.
*
* \param *handle Pointer to library handle
* \param uint16_t block_size maximum size of CoAP payload. Valid sizes are 16, 32, 64, 128, 256, 512 and 1024 bytes
* \return 0 = success, -1 = failure
*/
extern int8_t sn_nsdl_set_block_size(struct nsdl_s *handle, uint16_t block_size);
/**
* \fn int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle,uint8_t message_count)
*
* \brief If dublicate message detection is enabled, this function changes buffer size.
*
* \param *handle Pointer to library handle
* \param uint8_t message_count max number of messages saved for duplicate control
* \return 0 = success, -1 = failure
*/
extern int8_t sn_nsdl_set_duplicate_buffer_size(struct nsdl_s *handle, uint8_t message_count);
/**
* \fn void *sn_nsdl_set_context(const struct nsdl_s *handle, void *context)
*
* \brief Set the application defined context parameter for given handle.
* This is useful for example when interfacing with c++ objects where a
* pointer to object is set as the context, and in the callback functions
* the context pointer can be used to call methods for the correct instance
* of the c++ object.
*
* \param *handle Pointer to library handle
* \param *context Pointer to the application defined context
* \return 0 = success, -1 = failure
*/
extern int8_t sn_nsdl_set_context(struct nsdl_s * const handle, void * const context);
/**
* \fn void *sn_nsdl_get_context(const struct nsdl_s *handle)
*
* \brief Get the application defined context parameter for given handle.
* This is useful for example when interfacing with c++ objects where a
* pointer to object is set as the context, and in the callback functions
* the context pointer can be used to call methods for the correct instance
* of the c++ object.
*
* \param *handle Pointer to library handle
* \return Pointer to the application defined context
*/
extern void *sn_nsdl_get_context(const struct nsdl_s * const handle);
#ifdef __cplusplus
}
#endif
#endif /* MBED_CLIENT_C_NEW_API */
#endif /* SN_NSDL_LIB_2_H_ */

View File

@ -149,6 +149,7 @@ uint16_t sn_coap_builder_calc_needed_packet_data_size(sn_coap_hdr_s *src_coap_ms
uint16_t sn_coap_builder_calc_needed_packet_data_size_2(sn_coap_hdr_s *src_coap_msg_ptr, uint16_t blockwise_payload_size)
{
(void)blockwise_payload_size;
tr_debug("sn_coap_builder_calc_needed_packet_data_size_2");
uint16_t returned_byte_count = 0;
@ -750,13 +751,11 @@ static uint8_t sn_coap_builder_options_build_add_uint_option(uint8_t **dst_packe
{
uint8_t payload[4];
uint8_t len = 0;
/* Construct the variable-length payload representing the value */
while (option_value) {
if (option_value & 0xff000000) {
for (uint8_t i = 0; i < 4; i++) {
if (len > 0 || (option_value & 0xff000000)) {
payload[len++] = option_value >> 24;
}
option_value <<= 8;
}

View File

@ -40,7 +40,9 @@
#include "sn_coap_protocol.h"
#include "sn_coap_header_internal.h"
#include "sn_coap_protocol_internal.h"
#include "randLIB.h"
#include "mbed-trace/mbed_trace.h"
#define TRACE_GROUP "coap"
/* * * * * * * * * * * * * * * * * * * * */
/* * * * LOCAL FUNCTION PROTOTYPES * * * */
@ -198,12 +200,12 @@ struct coap_s *sn_coap_protocol_init(void *(*used_malloc_func_ptr)(uint16_t), vo
#endif /* ENABLE_RESENDINGS */
/* Randomize global message ID */
#if defined __linux__ || defined TARGET_LIKE_MBED
srand(rand()^time(NULL));
message_id = rand() % 400 + 100;
#else
message_id = 100;
#endif
randLIB_seed_random();
message_id = randLIB_get_16bit();
if (message_id == 0) {
message_id = 1;
}
tr_debug("Coap random msg ID: %d", message_id);
return handle;
}
@ -610,29 +612,33 @@ sn_coap_hdr_s *sn_coap_protocol_parse(struct coap_s *handle, sn_nsdl_addr_s *src
/* * * * Manage received CoAP message duplicate detection * * * */
/* If no message duplication detected */
if (sn_coap_protocol_linked_list_duplication_info_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id) == -1) {
/* * * No Message duplication: Store received message for detecting later duplication * * */
if (returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_CONFIRMABLE ||
returned_dst_coap_msg_ptr->msg_type == COAP_MSG_TYPE_NON_CONFIRMABLE) {
/* Get count of stored duplication messages */
uint16_t stored_duplication_msgs_count = handle->count_duplication_msgs;
if (sn_coap_protocol_linked_list_duplication_info_search(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id) == -1) {
/* * * No Message duplication: Store received message for detecting later duplication * * */
/* Check if there is no room to store message for duplication detection purposes */
if (stored_duplication_msgs_count >= handle->sn_coap_duplication_buffer_size) {
/* Get oldest stored duplication message */
coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&handle->linked_list_duplication_msgs);
/* Get count of stored duplication messages */
uint16_t stored_duplication_msgs_count = handle->count_duplication_msgs;
/* Remove oldest stored duplication message for getting room for new duplication message */
sn_coap_protocol_linked_list_duplication_info_remove(handle, stored_duplication_info_ptr->addr_ptr, stored_duplication_info_ptr->port, stored_duplication_info_ptr->msg_id);
/* Check if there is no room to store message for duplication detection purposes */
if (stored_duplication_msgs_count >= handle->sn_coap_duplication_buffer_size) {
/* Get oldest stored duplication message */
coap_duplication_info_s *stored_duplication_info_ptr = ns_list_get_first(&handle->linked_list_duplication_msgs);
/* Remove oldest stored duplication message for getting room for new duplication message */
sn_coap_protocol_linked_list_duplication_info_remove(handle, stored_duplication_info_ptr->addr_ptr, stored_duplication_info_ptr->port, stored_duplication_info_ptr->msg_id);
}
/* Store Duplication info to Linked list */
sn_coap_protocol_linked_list_duplication_info_store(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id);
} else { /* * * Message duplication detected * * */
/* Set returned status to User */
returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG;
// todo: send ACK to confirmable messages
/* Because duplicate message, return with coap_status set */
return returned_dst_coap_msg_ptr;
}
/* Store Duplication info to Linked list */
sn_coap_protocol_linked_list_duplication_info_store(handle, src_addr_ptr, returned_dst_coap_msg_ptr->msg_id);
} else { /* * * Message duplication detected * * */
/* Set returned status to User */
returned_dst_coap_msg_ptr->coap_status = COAP_STATUS_PARSER_DUPLICATED_MSG;
/* Because duplicate message, return with coap_status set */
return returned_dst_coap_msg_ptr;
}
#endif

View File

@ -16,6 +16,11 @@
#ifndef GRS_H_
#define GRS_H_
#ifdef MBED_CLIENT_C_NEW_API
#include "sn_grs2.h"
#else
#ifdef __cplusplus
extern "C" {
@ -79,6 +84,9 @@ struct nsdl_s {
uint8_t *oma_bs_address_ptr; /* Bootstrap address pointer. If null, no bootstrap in use */
sn_nsdl_ep_parameters_s *ep_information_ptr; // Endpoint parameters, Name, Domain etc..
sn_nsdl_oma_server_info_t *nsp_address_ptr; // NSP server address information
/* Application definable context. This is useful for example when interfacing with c++ objects where a pointer to object is set as the
* context, and in the callback functions the context pointer can be used to call methods for the correct instance of the c++ object. */
void *context;
void (*sn_nsdl_oma_bs_done_cb)(sn_nsdl_oma_server_info_t *server_info_ptr); /* Callback to inform application when bootstrap is done */
void *(*sn_nsdl_alloc)(uint16_t);
@ -128,7 +136,7 @@ extern void sn_grs_mark_resources_as_registered(stru
}
#endif
#endif /* MBED_CLIENT_C_NEW_API */
#endif /* GRS_H_ */

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2011-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef GRS_2_H_
#define GRS_2_H_
#ifdef MBED_CLIENT_C_NEW_API
#ifdef __cplusplus
extern "C" {
#endif
#define SN_GRS_RESOURCE_ALREADY_EXISTS -2
#define SN_GRS_INVALID_PATH -3
#define SN_GRS_LIST_ADDING_FAILURE -4
#define SN_GRS_RESOURCE_UPDATED -5
#define ACCESS_DENIED -6
#define SN_GRS_DELETE_METHOD 0
#define SN_GRS_SEARCH_METHOD 1
#define SN_GRS_DEFAULT_ACCESS 0x0F
#define SN_NDSL_RESOURCE_NOT_REGISTERED 0
#define SN_NDSL_RESOURCE_REGISTERING 1
#define SN_NDSL_RESOURCE_REGISTERED 2
/***** Structs *****/
typedef struct sn_grs_version_ {
uint8_t major_version;
uint8_t minor_version;
uint8_t build;
} sn_grs_version_s;
typedef NS_LIST_HEAD(sn_nsdl_dynamic_resource_parameters_s, link) resource_list_t;
struct grs_s {
struct coap_s *coap;
void *(*sn_grs_alloc)(uint16_t);
void (*sn_grs_free)(void *);
uint8_t (*sn_grs_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *);
int8_t (*sn_grs_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *);
uint16_t resource_root_count;
resource_list_t resource_root_list;
};
struct nsdl_s {
uint16_t update_register_msg_id;
uint16_t register_msg_len;
uint16_t update_register_msg_len;
uint16_t register_msg_id;
uint16_t unregister_msg_id;
uint16_t bootstrap_msg_id;
uint16_t oma_bs_port; /* Bootstrap port */
uint8_t oma_bs_address_len; /* Bootstrap address length */
unsigned int sn_nsdl_endpoint_registered:1;
struct grs_s *grs;
uint8_t *oma_bs_address_ptr; /* Bootstrap address pointer. If null, no bootstrap in use */
sn_nsdl_ep_parameters_s *ep_information_ptr; // Endpoint parameters, Name, Domain etc..
sn_nsdl_oma_server_info_t *nsp_address_ptr; // NSP server address information
/* Application definable context. This is useful for example when interfacing with c++ objects where a pointer to object is set as the
* context, and in the callback functions the context pointer can be used to call methods for the correct instance of the c++ object. */
void *context;
void (*sn_nsdl_oma_bs_done_cb)(sn_nsdl_oma_server_info_t *server_info_ptr); /* Callback to inform application when bootstrap is done */
void *(*sn_nsdl_alloc)(uint16_t);
void (*sn_nsdl_free)(void *);
uint8_t (*sn_nsdl_tx_callback)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t, sn_nsdl_addr_s *);
uint8_t (*sn_nsdl_rx_callback)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *);
void (*sn_nsdl_oma_bs_done_cb_handle)(sn_nsdl_oma_server_info_t *server_info_ptr,
struct nsdl_s *handle); /* Callback to inform application when bootstrap is done with nsdl handle */
};
/***** Function prototypes *****/
/**
* \fn extern grs_s *sn_grs_init (uint8_t (*sn_grs_tx_callback_ptr)(sn_nsdl_capab_e , uint8_t *, uint16_t,
* sn_nsdl_addr_s *), uint8_t (*sn_grs_rx_callback_ptr)(sn_coap_hdr_s *, sn_nsdl_addr_s *),
* sn_grs_mem_s *sn_memory)
*
* \brief GRS library initialize function.
*
* This function initializes GRS and CoAP.
*
* \param sn_grs_tx_callback A function pointer to a transmit callback function. Should return 1 when succeed, 0 when failed
* \param *sn_grs_rx_callback_ptr A function pointer to a receiving callback function. If received packet is not for GRS, it will be passed to
* upper level (NSDL) to be proceed.
* \param sn_memory A pointer to a structure containing the platform specific functions for memory allocation and free.
*
* \return success pointer to handle, failure = NULL
*
*/
extern struct grs_s *sn_grs_init(uint8_t (*sn_grs_tx_callback_ptr)(struct nsdl_s *, sn_nsdl_capab_e , uint8_t *, uint16_t,
sn_nsdl_addr_s *),
int8_t (*sn_grs_rx_callback_ptr)(struct nsdl_s *, sn_coap_hdr_s *, sn_nsdl_addr_s *),
void *(*sn_grs_alloc)(uint16_t),
void (*sn_grs_free)(void *));
extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_first_resource(struct grs_s *handle);
extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_get_next_resource(struct grs_s *handle,
const sn_nsdl_dynamic_resource_parameters_s *sn_grs_current_resource);
extern int8_t sn_grs_process_coap(struct nsdl_s *handle,
sn_coap_hdr_s *coap_packet_ptr,
sn_nsdl_addr_s *src);
extern sn_nsdl_dynamic_resource_parameters_s *sn_grs_search_resource(struct grs_s *handle,
uint16_t pathlen,
uint8_t *path,
uint8_t search_method);
extern int8_t sn_grs_destroy(struct grs_s *handle);
extern sn_grs_resource_list_s *sn_grs_list_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path);
extern void sn_grs_free_resource_list(struct grs_s *handle, sn_grs_resource_list_s *list);
extern int8_t sn_grs_send_coap_message(struct nsdl_s *handle,
sn_nsdl_addr_s *address_ptr,
sn_coap_hdr_s *coap_hdr_ptr);
extern int8_t sn_grs_put_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
extern int8_t sn_grs_pop_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
extern int8_t sn_grs_delete_resource(struct grs_s *handle, uint16_t pathlen, uint8_t *path);
extern void sn_grs_mark_resources_as_registered(struct nsdl_s *handle);
#ifndef MEMORY_OPTIMIZED_API
extern int8_t sn_grs_create_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
extern int8_t sn_grs_update_resource(struct grs_s *handle, sn_nsdl_dynamic_resource_parameters_s *res);
#endif
#ifdef __cplusplus
}
#endif
#endif /* MBED_CLIENT_C_NEW_API */
#endif /* GRS_H_ */

View File

@ -21,6 +21,9 @@
* \brief General resource server.
*
*/
#ifndef MBED_CLIENT_C_NEW_API
#include <string.h>
#include <stdlib.h>
@ -1035,3 +1038,5 @@ void sn_grs_mark_resources_as_registered(struct nsdl_s *handle)
temp_resource = sn_grs_get_next_resource(handle->grs, temp_resource);
}
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,8 @@
*
*/
#ifndef MBED_CLIENT_C_NEW_API
#include <string.h>
#include "ns_types.h"
@ -223,6 +225,8 @@ struct nsdl_s *sn_nsdl_init(uint8_t (*sn_nsdl_tx_cb)(struct nsdl_s *, sn_nsdl_ca
handle->sn_nsdl_endpoint_registered = SN_NSDL_ENDPOINT_NOT_REGISTERED;
// By default bootstrap msgs are handled in nsdl
handle->handle_bootstrap_msg = true;
handle->context = NULL;
return handle;
}
@ -2585,3 +2589,23 @@ bool sn_nsdl_check_uint_overflow(uint16_t resource_size, uint16_t param_a, uint1
}
}
}
extern int8_t sn_nsdl_set_context(struct nsdl_s * const handle, void * const context)
{
if (handle == NULL) {
return SN_NSDL_FAILURE;
}
handle->context = context;
return SN_NSDL_SUCCESS;
}
extern void *sn_nsdl_get_context(const struct nsdl_s * const handle)
{
if (handle == NULL) {
return NULL;
}
return handle->context;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,19 @@
#scan for folders having "Makefile" in them and remove 'this' to prevent loop
DIRS := $(filter-out ./, $(sort $(dir $(shell find . -name 'Makefile'))))
all:
for dir in $(DIRS); do \
cd $$dir; make gcov; cd ..;\
done
clean:
for dir in $(DIRS); do \
cd $$dir; make clean; cd ..;\
done
rm -rf ../source/*gcov ../source/*gcda ../source/*o
rm -rf stubs/*gcov stubs/*gcda stubs/*o
rm -rf results/*
rm -rf coverages/*
rm -rf results
rm -rf coverages

View File

@ -13,6 +13,7 @@ INCLUDE_DIRS =\
../../../../nsdl-c\
../../../../yotta_modules/nanostack-libservice/mbed-client-libservice\
../../../../yotta_modules/mbed-trace\
../../../../yotta_modules/nanostack-randlib/mbed-client-randlib\
../../../../../libService/libService\
../../../../source/libCoap/src/include\
../../../../source/libNsdl/src/include\

View File

@ -0,0 +1,16 @@
include ../makefile_defines.txt
COMPONENT_NAME = sn_coap_builder_unit
SRC_FILES = \
../../../../source/libCoap/src/sn_coap_builder.c
TEST_SRC_FILES = \
main.cpp \
libCoap_builder_test.cpp \
../stubs/sn_coap_header_check_stub.c \
../stubs/sn_coap_parser_stub.c \
include ../MakefileWorker.mk

View File

@ -318,20 +318,23 @@ TEST(libCoap_builder, sn_coap_builder_calc_needed_packet_data_size)
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 16);
//proxy uri tests (4)
header.options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(270);
header.options_list_ptr->proxy_uri_ptr = (uint8_t*)malloc(1800);
header.options_list_ptr->proxy_uri_len = 1800;
header.options_list_ptr->max_age = COAP_OPTION_MAX_AGE_DEFAULT;
header.options_list_ptr->accept = COAP_CT_NONE;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
header.options_list_ptr->proxy_uri_len = 6;
header.options_list_ptr->etag_ptr = (uint8_t*)malloc(6);
header.options_list_ptr->etag_ptr = (uint8_t*)malloc(4);
header.options_list_ptr->etag_len = 0;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
header.options_list_ptr->proxy_uri_len = 14;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
// init now the buffer up to 4 bytes, as it will be accessed
memset(header.options_list_ptr->etag_ptr, 0, 4);
header.options_list_ptr->proxy_uri_len = 281;
header.options_list_ptr->block1 = COAP_OPTION_BLOCK_NONE;
header.options_list_ptr->block2 = COAP_OPTION_BLOCK_NONE;
@ -343,7 +346,7 @@ TEST(libCoap_builder, sn_coap_builder_calc_needed_packet_data_size)
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
header.options_list_ptr->uri_host_len = 4;
header.options_list_ptr->location_path_ptr = (uint8_t*)malloc(6);
header.options_list_ptr->location_path_ptr = (uint8_t*)calloc(270, 1);
header.options_list_ptr->location_path_len = 270;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
@ -357,7 +360,7 @@ TEST(libCoap_builder, sn_coap_builder_calc_needed_packet_data_size)
header.options_list_ptr->uri_port = 6;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 377);
header.options_list_ptr->location_query_ptr = (uint8_t*)malloc(6);
header.options_list_ptr->location_query_ptr = (uint8_t*)calloc(277, 1);
header.options_list_ptr->location_query_len = 277;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
@ -372,6 +375,8 @@ TEST(libCoap_builder, sn_coap_builder_calc_needed_packet_data_size)
header.options_list_ptr->uri_query_len = 0;
CHECK(sn_coap_builder_calc_needed_packet_data_size(&header) == 0);
// init the 4 bytes to something useful, leave rest uninitialized to let valgrind warn if builder is processing past buffer
memset(header.options_list_ptr->uri_query_ptr, 0, 4);
header.options_list_ptr->uri_query_len = 4;
header.options_list_ptr->block2 = -1;
header.options_list_ptr->observe = 0xFFFFFF22;

View File

@ -0,0 +1,14 @@
include ../makefile_defines.txt
COMPONENT_NAME = sn_coap_header_check_unit
SRC_FILES = \
../../../../source/libCoap/src/sn_coap_header_check.c
TEST_SRC_FILES = \
main.cpp \
libCoap_header_test.cpp \
include ../MakefileWorker.mk
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT

View File

@ -0,0 +1,17 @@
include ../makefile_defines.txt
COMPONENT_NAME = sn_coap_parser_unit
#This must be changed manually
SRC_FILES = \
../../../../source/libCoap/src/sn_coap_parser.c
TEST_SRC_FILES = \
main.cpp \
sn_coap_parsertest.cpp \
test_sn_coap_parser.c \
include ../MakefileWorker.mk
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT

View File

@ -8,6 +8,7 @@
#include "sn_coap_header.h"
#include "sn_coap_header_internal.h"
#include "sn_coap_protocol_internal.h"
#include <assert.h>
int retCounter = 0;
@ -37,7 +38,9 @@ bool test_sn_coap_parser()
retCounter = 0;
bool ret = true;
uint8_t* ptr = (uint8_t*)malloc(20);
// use zero-initialized buffer for tests
uint8_t* ptr = (uint8_t*)calloc(20, 1);
assert(ptr);
sn_coap_hdr_s * hdr = sn_coap_parser(NULL, 8, ptr, NULL);
if( hdr != NULL ){
free(hdr);

View File

@ -0,0 +1,23 @@
include ../makefile_defines.txt
MBED_CLIENT_USER_CONFIG_FILE ?= $(CURDIR)/test_config.h
COMPONENT_NAME = sn_coap_protocol_unit
SRC_FILES = \
../../../../source/libCoap/src/sn_coap_protocol.c
TEST_SRC_FILES = \
main.cpp \
libCoap_protocol_test.cpp \
../stubs/sn_coap_builder_stub.c \
../stubs/sn_coap_parser_stub.c \
../stubs/sn_coap_header_check_stub.c \
../stubs/ns_list_stub.c \
../stubs/randLIB_stub.cpp \
include ../MakefileWorker.mk
# the config is needed for client application compilation too
override CFLAGS += -DMBED_CLIENT_USER_CONFIG_FILE='<$(MBED_CLIENT_USER_CONFIG_FILE)>'
override CXXFLAGS += -DMBED_CLIENT_USER_CONFIG_FILE='<$(MBED_CLIENT_USER_CONFIG_FILE)>'
CPPUTESTFLAGS += -DYOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE=16 -DENABLE_RESENDINGS=1 -DSN_COAP_MAX_INCOMING_BLOCK_MESSAGE_SIZE=65535

View File

@ -384,24 +384,25 @@ TEST(libCoap_protocol, sn_coap_protocol_build)
hdr2->options_list_ptr->use_size1 = true;
hdr2->options_list_ptr->size1 = 0xFFFF01;
hdr2->payload_ptr = (uint8_t*)malloc(3);
int buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
hdr2->payload_ptr = (uint8_t*)malloc(buff_len);
for( int i=0; i < 8; i++ ){
retCounter = 1 + i;
sn_coap_builder_stub.expectedInt16 = 1;
hdr2->payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
hdr2->payload_len = buff_len;
int8_t rett = sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, hdr2, NULL);
CHECK( -2 == rett );
}
retCounter = 11;
sn_coap_builder_stub.expectedInt16 = 1;
hdr2->payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
hdr2->payload_len = buff_len;
CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, hdr2, NULL));
retCounter = 19;
sn_coap_builder_stub.expectedInt16 = 1;
hdr2->payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
hdr2->payload_len = buff_len;
CHECK( 1 == sn_coap_protocol_build(handle, &addr, dst_packet_data_ptr, hdr2, NULL));
free(hdr2->payload_ptr);
@ -450,7 +451,6 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 1;
struct coap_s * handle = sn_coap_protocol_init(myMalloc, myFree, null_tx_cb, NULL);
sn_nsdl_addr_s* addr = (sn_nsdl_addr_s*)malloc(sizeof(sn_nsdl_addr_s));
memset(addr, 0, sizeof(sn_nsdl_addr_s));
@ -582,7 +582,7 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
memset(list, 0, sizeof(sn_coap_options_list_s));
sn_coap_parser_stub.expectedHeader->options_list_ptr = list;
sn_coap_parser_stub.expectedHeader->options_list_ptr->block1 = 1;
sn_coap_parser_stub.expectedHeader->msg_id = 4;
sn_coap_parser_stub.expectedHeader->msg_id = 5;
sn_coap_parser_stub.expectedHeader->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
sn_coap_parser_stub.expectedHeader->msg_code = COAP_MSG_CODE_REQUEST_GET;
payload = (uint8_t*)malloc(17);
@ -843,12 +843,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
int buff_size = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_size);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 16;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_size;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -891,13 +892,14 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 21;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
int buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block1 = -1;
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 17;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
@ -938,7 +940,8 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = UINT16_MAX;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
// tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
// memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
// tmp_hdr.options_list_ptr->block2 = 1;
@ -1096,12 +1099,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 16;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1145,13 +1149,14 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 21;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block1 = -1;
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 17;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
@ -1197,14 +1202,15 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->use_size2 = true;
tmp_hdr.options_list_ptr->size2 = 0xFF01;
tmp_hdr.msg_id = 18;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1350,11 +1356,12 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.msg_id = 20;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1425,12 +1432,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 41;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1472,12 +1480,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 42;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1519,12 +1528,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 43;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1565,12 +1575,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 44;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1610,12 +1621,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 45;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1656,12 +1668,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 46;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1706,12 +1719,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 47;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1758,12 +1772,13 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 1;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(tmp_hdr.options_list_ptr, 0, sizeof(sn_coap_options_list_s));
tmp_hdr.options_list_ptr->block2 = 1;
tmp_hdr.msg_id = 47;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1942,10 +1957,11 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 5;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.msg_id = 18;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -1981,10 +1997,11 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 5;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.msg_id = 18;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
tmp_hdr.uri_path_ptr = (uint8_t*)malloc(7);
snprintf((char *)tmp_hdr.uri_path_ptr, 7, "13/0/1");
tmp_hdr.uri_path_len = 7;
@ -2025,10 +2042,11 @@ TEST(libCoap_protocol, sn_coap_protocol_parse)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 5;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
buff_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_len);
tmp_hdr.msg_id = 18;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_len;
tmp_hdr.uri_path_ptr = (uint8_t*)malloc(7);
snprintf((char *)tmp_hdr.uri_path_ptr, 7, "13/0/1");
tmp_hdr.uri_path_len = 7;
@ -2070,10 +2088,11 @@ TEST(libCoap_protocol, sn_coap_protocol_exec)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 5;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
int buff_size = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buff_size);
tmp_hdr.msg_id = 18;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buff_size;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);
@ -2136,10 +2155,11 @@ TEST(libCoap_protocol, sn_coap_protocol_exec2)
retCounter = 20;
sn_coap_builder_stub.expectedInt16 = 5;
tmp_hdr.payload_ptr = (uint8_t*)malloc(3);
int buf_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_ptr = (uint8_t*)malloc(buf_len);
tmp_hdr.msg_id = 18;
tmp_hdr.msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
tmp_hdr.payload_len = SN_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE + 20;
tmp_hdr.payload_len = buf_len;
sn_coap_protocol_build(handle, &tmp_addr, dst_packet_data_ptr, &tmp_hdr, NULL);
free(tmp_hdr.options_list_ptr);

View File

@ -0,0 +1,20 @@
include ../makefile_defines.txt
COMPONENT_NAME = sn_grs_unit
#This must be changed manually
SRC_FILES = \
../../../../source/libNsdl/src/sn_grs.c
TEST_SRC_FILES = \
main.cpp \
sn_grstest.cpp \
test_sn_grs.c \
../stubs/sn_coap_protocol_stub.c \
../stubs/sn_coap_parser_stub.c \
../stubs/sn_coap_builder_stub.c \
../stubs/sn_nsdl_stub.c \
../stubs/ns_list_stub.c \
include ../MakefileWorker.mk

View File

@ -646,10 +646,11 @@ bool test_sn_grs_process_coap()
memset(hdr, 0, sizeof(sn_coap_hdr_s));
hdr->msg_code = COAP_MSG_CODE_REQUEST_GET;
hdr->msg_type = COAP_MSG_TYPE_RESET;
hdr->uri_path_ptr = (uint8_t*)malloc(2);
hdr->uri_path_ptr = (uint8_t*)calloc(2, 1);
hdr->uri_path_len = 2;
hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
hdr->payload_ptr = (uint8_t*)malloc(2);
hdr->payload_ptr = (uint8_t*)calloc(2, 1);
hdr->payload_len = 2;
if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){
return false;
@ -660,10 +661,11 @@ bool test_sn_grs_process_coap()
memset(hdr, 0, sizeof(sn_coap_hdr_s));
hdr->msg_code = COAP_MSG_CODE_REQUEST_POST;
hdr->msg_type = COAP_MSG_TYPE_RESET;
hdr->uri_path_ptr = (uint8_t*)malloc(2);
hdr->uri_path_ptr = (uint8_t*)calloc(2, 1);
hdr->uri_path_len = 2;
hdr->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
hdr->payload_ptr = (uint8_t*)malloc(2);
hdr->payload_len = 2;
if( SN_NSDL_SUCCESS != sn_grs_process_coap(handle, hdr, addr) ){
return false;

View File

@ -0,0 +1,21 @@
include ../makefile_defines.txt
COMPONENT_NAME = sn_nsdl_unit
#This must be changed manually
SRC_FILES = \
../../../../source/libNsdl/src/sn_nsdl.c
TEST_SRC_FILES = \
main.cpp \
sn_nsdltest.cpp \
test_sn_nsdl.c \
../stubs/sn_coap_protocol_stub.c \
../stubs/sn_grs_stub.c \
../stubs/sn_coap_parser_stub.c \
../stubs/sn_coap_builder_stub.c \
include ../MakefileWorker.mk
CPPUTESTFLAGS += -DYOTTA_CFG_COAP_MAX_BLOCKWISE_PAYLOAD_SIZE=16

View File

@ -186,5 +186,14 @@ TEST(sn_nsdl, test_sn_nsdl_set_duplicate_buffer_size)
CHECK(test_sn_nsdl_set_duplicate_buffer_size());
}
TEST(sn_nsdl, test_sn_nsdl_get_context)
{
CHECK(test_sn_nsdl_get_context());
}
TEST(sn_nsdl, test_sn_nsdl_set_context)
{
CHECK(test_sn_nsdl_set_context());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015 ARM. All rights reserved.
* Copyright (c) 2015 ARM. All rights reserved.
*/
#include "test_sn_nsdl.h"
#include <string.h>
@ -279,6 +279,7 @@ bool test_sn_nsdl_register_endpoint()
sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0';
sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1;
sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1;
sn_grs_stub.expectedInfo->resource_parameters_ptr->coap_content_type = 0; // XXX: why was this left uninitialized? what was point of this test?
sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2);
sn_grs_stub.expectedInfo->path[0] = 'a';
@ -309,7 +310,7 @@ bool test_sn_nsdl_register_endpoint()
sn_grs_stub.infoRetCounter = 1;
sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s));
memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s));
sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s));
sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)calloc(sizeof(sn_nsdl_resource_parameters_s), 1);
sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1;
sn_grs_stub.expectedInfo->publish_uri = 1;
eptr->binding_and_mode = 0x06;
@ -351,6 +352,7 @@ bool test_sn_nsdl_register_endpoint()
sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0';
sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1;
sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1;
sn_grs_stub.expectedInfo->resource_parameters_ptr->coap_content_type = 0;
sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2);
sn_grs_stub.expectedInfo->path[0] = 'a';
@ -617,6 +619,7 @@ bool test_sn_nsdl_register_endpoint()
sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_ptr[1] = '\0';
sn_grs_stub.expectedInfo->resource_parameters_ptr->interface_description_len = 1;
sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1;
sn_grs_stub.expectedInfo->resource_parameters_ptr->coap_content_type = 0;
sn_grs_stub.expectedInfo->path = (uint8_t*)malloc(2);
sn_grs_stub.expectedInfo->path[0] = 'a';
sn_grs_stub.expectedInfo->path[1] = '\0';
@ -830,7 +833,7 @@ bool test_sn_nsdl_update_registration()
sn_grs_stub.infoRetCounter = 1;
sn_grs_stub.expectedInfo = (sn_nsdl_resource_info_s*)malloc(sizeof(sn_nsdl_resource_info_s));
memset( sn_grs_stub.expectedInfo, 0, sizeof(sn_nsdl_resource_info_s));
sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)malloc(sizeof(sn_nsdl_resource_parameters_s));
sn_grs_stub.expectedInfo->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)calloc(sizeof(sn_nsdl_resource_parameters_s), 1);
sn_grs_stub.expectedInfo->resource_parameters_ptr->observable = 1;
sn_grs_stub.expectedInfo->publish_uri = 1;
retCounter = 3;
@ -1505,7 +1508,7 @@ bool test_sn_nsdl_process_coap()
sn_coap_protocol_stub.expectedHeader->msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
sn_coap_protocol_stub.expectedHeader->options_list_ptr = (sn_coap_options_list_s*)malloc(sizeof(sn_coap_options_list_s));
memset(sn_coap_protocol_stub.expectedHeader->options_list_ptr, 0, sizeof(sn_coap_options_list_s));
sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)malloc(2);
sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_ptr = (uint8_t*)calloc(2, 1);
sn_coap_protocol_stub.expectedHeader->options_list_ptr->location_path_len = 2;
handle->register_msg_id = 5;
@ -2650,35 +2653,41 @@ bool test_set_NSP_address()
handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(2);
memset( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 2 );
uint8_t* addr = (uint8_t*)malloc(2);
memset(addr, 0, 2);
// Note: the set_NSP_address() will read 4 bytes of source address
uint8_t* addr4 = (uint8_t*)calloc(4, 1);
if( SN_NSDL_FAILURE != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){
if( SN_NSDL_FAILURE != set_NSP_address(handle, addr4, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){
return false;
}
handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL;
retCounter = 1;
if( SN_NSDL_SUCCESS != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){
if( SN_NSDL_SUCCESS != set_NSP_address(handle, addr4, 0, SN_NSDL_ADDRESS_TYPE_IPV4) ){
return false;
}
free(handle->nsp_address_ptr->omalw_address_ptr->addr_ptr);
handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL;
if( SN_NSDL_FAILURE != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV6) ){
// Note: the set_NSP_address() will read 16 bytes of source address
uint8_t* addr6 = (uint8_t*)calloc(16, 1);
if( SN_NSDL_FAILURE != set_NSP_address(handle, addr6, 0, SN_NSDL_ADDRESS_TYPE_IPV6) ){
return false;
}
handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = NULL;
handle->nsp_address_ptr->omalw_address_ptr->addr_ptr = (uint8_t*)malloc(2);
handle->nsp_address_ptr->omalw_address_ptr->addr_len = 2;
memset( handle->nsp_address_ptr->omalw_address_ptr->addr_ptr, 0, 2 );
retCounter = 1;
if( SN_NSDL_SUCCESS != set_NSP_address(handle, addr, 0, SN_NSDL_ADDRESS_TYPE_IPV6) ){
if( SN_NSDL_SUCCESS != set_NSP_address(handle, addr6, 0, SN_NSDL_ADDRESS_TYPE_IPV6) ){
return false;
}
free(addr);
free(addr4);
free(addr6);
sn_nsdl_destroy(handle);
return true;
}
@ -2880,7 +2889,7 @@ bool test_sn_nsdl_release_allocated_coap_msg_mem()
memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s));
struct nsdl_s* handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree);
sn_coap_hdr_s* list = (sn_coap_hdr_s*)malloc(sizeof(sn_coap_hdr_s));
sn_coap_hdr_s* list = (sn_coap_hdr_s*)calloc(sizeof(sn_coap_hdr_s), 1);
sn_nsdl_release_allocated_coap_msg_mem(handle, list); //mem leak or pass
@ -2963,3 +2972,51 @@ bool test_sn_nsdl_set_duplicate_buffer_size()
sn_nsdl_destroy(handle);
return true;
}
bool test_sn_nsdl_set_context()
{
struct nsdl_s* handle = NULL;
if (sn_nsdl_set_context(handle,NULL) == 0){
printf("\n\neka\n\n");
return false;
}
retCounter = 4;
sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s));
memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s));
handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree);
if (sn_nsdl_set_context(handle,NULL) != 0){
printf("\n\ntoka\n\n");
return false;
}
int somecontext = 1;
if (sn_nsdl_set_context(handle,&somecontext) != 0){
printf("\n\nkolmas\n\n");
return false;
}
sn_nsdl_destroy(handle);
return true;
}
bool test_sn_nsdl_get_context()
{
struct nsdl_s* handle = NULL;
if (sn_nsdl_get_context(handle) != NULL){
return false;
}
retCounter = 4;
sn_grs_stub.expectedGrs = (struct grs_s *)malloc(sizeof(struct grs_s));
memset(sn_grs_stub.expectedGrs,0, sizeof(struct grs_s));
handle = sn_nsdl_init(&nsdl_tx_callback, &nsdl_rx_callback, &myMalloc, &myFree);
int somecontext = 1;
sn_nsdl_set_context(handle,&somecontext);
if (sn_nsdl_get_context(handle) != &somecontext){
return false;
}
sn_nsdl_destroy(handle);
return true;
}

View File

@ -78,6 +78,10 @@ bool test_sn_nsdl_set_block_size();
bool test_sn_nsdl_set_duplicate_buffer_size();
bool test_sn_nsdl_set_context();
bool test_sn_nsdl_get_context();
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2016 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "randLIB_stub.h"
uint8_t randLIB_stub::uint8_value;
uint16_t randLIB_stub::uint16_value;
uint32_t randLIB_stub::uint32_value;
uint64_t randLIB_stub::uint64_value;
void* randLIB_stub::void_value;
extern "C"{
void randLIB_seed_random(void){}
void randLIB_add_seed(uint64_t seed){}
uint8_t randLIB_get_8bit(void)
{
return randLIB_stub::uint8_value;
}
uint16_t randLIB_get_16bit(void)
{
return randLIB_stub::uint16_value;
}
uint32_t randLIB_get_32bit(void)
{
return randLIB_stub::uint32_value;
}
uint64_t randLIB_get_64bit(void)
{
return randLIB_stub::uint64_value;
}
void *randLIB_get_n_bytes_random(void *data_ptr, uint8_t count)
{
return randLIB_stub::void_value;
}
uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max)
{
return randLIB_stub::uint16_value;
}
uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor)
{
return randLIB_stub::uint32_value;
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 2016 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef M2M_RANDLIB_STUB_H
#define M2M_RANDLIB_STUB_H
#include <stdint.h>
//some internal test related stuff
namespace randLIB_stub
{
extern uint8_t uint8_value;
extern uint16_t uint16_value;
extern uint32_t uint32_value;
extern uint64_t uint64_value;
extern void* void_value;
}
#endif // M2M_RANDLIB_STUB_H

View File

@ -7,6 +7,8 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
if (heth->Instance == ETH) {
/* Disable DCache for STM32F7 family */
SCB_DisableDCache();
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
@ -78,4 +80,4 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
/* Disable the Ethernet global Interrupt */
NVIC_DisableIRQ(ETH_IRQn);
}
}
}

View File

@ -7,6 +7,8 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
if (heth->Instance == ETH) {
/* Disable DCache for STM32F7 family */
SCB_DisableDCache();
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
@ -84,4 +86,4 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
/* Disable the Ethernet global Interrupt */
NVIC_DisableIRQ(ETH_IRQn);
}
}
}

View File

@ -7,6 +7,8 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
if (heth->Instance == ETH) {
/* Disable DCache for STM32F7 family */
SCB_DisableDCache();
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();

View File

@ -7,6 +7,8 @@ void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
{
GPIO_InitTypeDef GPIO_InitStructure;
if (heth->Instance == ETH) {
/* Disable DCache for STM32F7 family */
SCB_DisableDCache();
/* Enable GPIOs clocks */
__HAL_RCC_GPIOA_CLK_ENABLE();
@ -84,4 +86,4 @@ void HAL_ETH_MspDeInit(ETH_HandleTypeDef* heth)
/* Disable the Ethernet global Interrupt */
NVIC_DisableIRQ(ETH_IRQn);
}
}
}

View File

@ -68,28 +68,31 @@ public:
*/
virtual nsapi_error_t add_dns_server(const SocketAddress &address);
/* Set stack-specific stack options
/* Set stack options
*
* The setstackopt allow an application to pass stack-specific hints
* to the underlying stack. For unsupported options,
* NSAPI_ERROR_UNSUPPORTED is returned and the stack is unmodified.
* setstackopt allows an application to pass stack-specific options
* to the underlying stack using stack-specific level and option names,
* or to request generic options using levels from nsapi_stack_level_t.
*
* @param level Stack-specific protocol level
* @param optname Stack-specific option identifier
* For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned
* and the stack is unmodified.
*
* @param level Stack-specific protocol level or nsapi_stack_level_t
* @param optname Level-specific option name
* @param optval Option value
* @param optlen Length of the option value
* @return 0 on success, negative error code on failure
*/
virtual nsapi_error_t setstackopt(int level, int optname, const void *optval, unsigned optlen);
/* Get stack-specific stack options
/* Get stack options
*
* The getstackopt allow an application to retrieve stack-specific hints
* from the underlying stack. For unsupported options,
* NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
* getstackopt allows an application to retrieve stack-specific options
* to the underlying stack using stack-specific level and option names,
* or to request generic options using levels from nsapi_stack_level_t.
*
* @param level Stack-specific protocol level
* @param optname Stack-specific option identifier
* @param level Stack-specific protocol level or nsapi_stack_level_t
* @param optname Level-specific option name
* @param optval Destination for option value
* @param optlen Length of the option value
* @return 0 on success, negative error code on failure

View File

@ -60,6 +60,7 @@ nsapi_error_t Socket::close()
_socket = 0;
ret = _stack->socket_close(socket);
}
_stack = 0;
// Wakeup anything in a blocking operation
// on this socket

View File

@ -120,28 +120,34 @@ public:
*/
void set_timeout(int timeout);
/* Set stack-specific socket options
/* Set socket options
*
* The setsockopt allow an application to pass stack-specific hints
* to the underlying stack. For unsupported options,
* NSAPI_ERROR_UNSUPPORTED is returned and the socket is unmodified.
* setsockopt allows an application to pass stack-specific options
* to the underlying stack using stack-specific level and option names,
* or to request generic options using levels from nsapi_socket_level_t.
*
* @param level Stack-specific protocol level
* @param optname Stack-specific option identifier
* For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned
* and the socket is unmodified.
*
* @param level Stack-specific protocol level or nsapi_socket_level_t
* @param optname Level-specific option name
* @param optval Option value
* @param optlen Length of the option value
* @return 0 on success, negative error code on failure
*/
nsapi_error_t setsockopt(int level, int optname, const void *optval, unsigned optlen);
/* Get stack-specific socket options
/* Get socket options
*
* The getstackopt allow an application to retrieve stack-specific hints
* from the underlying stack. For unsupported options,
* NSAPI_ERROR_UNSUPPORTED is returned and optval is unmodified.
* getsockopt allows an application to retrieve stack-specific options
* from the underlying stack using stack-specific level and option names,
* or to request generic options using levels from nsapi_socket_level_t.
*
* @param level Stack-specific protocol level
* @param optname Stack-specific option identifier
* For unsupported options, NSAPI_ERROR_UNSUPPORTED is returned
* and the socket is unmodified.
*
* @param level Stack-specific protocol level or nsapi_socket_level_t
* @param optname Level-specific option name
* @param optval Destination for option value
* @param optlen Length of the option value
* @return 0 on success, negative error code on failure

View File

@ -39,10 +39,47 @@ nsapi_error_t TCPSocket::connect(const SocketAddress &address)
_lock.lock();
nsapi_error_t ret;
if (!_socket) {
ret = NSAPI_ERROR_NO_SOCKET;
} else {
// If this assert is hit then there are two threads
// performing a send at the same time which is undefined
// behavior
MBED_ASSERT(!_write_in_progress);
_write_in_progress = true;
bool blocking_connect_in_progress = false;
while (true) {
if (!_socket) {
ret = NSAPI_ERROR_NO_SOCKET;
break;
}
_pending = 0;
ret = _stack->socket_connect(_socket, address);
if ((_timeout == 0) || !(ret == NSAPI_ERROR_IN_PROGRESS || ret == NSAPI_ERROR_ALREADY)) {
break;
} else {
blocking_connect_in_progress = true;
int32_t count;
// Release lock before blocking so other threads
// accessing this object aren't blocked
_lock.unlock();
count = _write_sem.wait(_timeout);
_lock.lock();
if (count < 1) {
// Semaphore wait timed out so break out and return
break;
}
}
}
_write_in_progress = false;
/* Non-blocking connect gives "EISCONN" once done - convert to OK for blocking mode if we became connected during this call */
if (ret == NSAPI_ERROR_IS_CONNECTED && blocking_connect_in_progress) {
ret = NSAPI_ERROR_OK;
}
_lock.unlock();
@ -81,9 +118,8 @@ nsapi_size_or_error_t TCPSocket::send(const void *data, nsapi_size_t size)
}
_pending = 0;
nsapi_size_or_error_t sent = _stack->socket_send(_socket, data, size);
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != sent)) {
ret = sent;
ret = _stack->socket_send(_socket, data, size);
if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
break;
} else {
int32_t count;
@ -125,9 +161,8 @@ nsapi_size_or_error_t TCPSocket::recv(void *data, nsapi_size_t size)
}
_pending = 0;
nsapi_size_or_error_t recv = _stack->socket_recv(_socket, data, size);
if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK != recv)) {
ret = recv;
ret = _stack->socket_recv(_socket, data, size);
if ((_timeout == 0) || (ret != NSAPI_ERROR_WOULD_BLOCK)) {
break;
} else {
int32_t count;

View File

@ -48,6 +48,9 @@ enum nsapi_error {
NSAPI_ERROR_DHCP_FAILURE = -3010, /*!< DHCP failed to complete successfully */
NSAPI_ERROR_AUTH_FAILURE = -3011, /*!< connection to access point failed */
NSAPI_ERROR_DEVICE_ERROR = -3012, /*!< failure interfacing with the network processor */
NSAPI_ERROR_IN_PROGRESS = -3013, /*!< operation (eg connect) in progress */
NSAPI_ERROR_ALREADY = -3014, /*!< operation (eg connect) already in progress */
NSAPI_ERROR_IS_CONNECTED = -3015, /*!< socket is already connected */
};
/** Type used to represent error codes
@ -161,22 +164,45 @@ typedef enum nsapi_protocol {
} nsapi_protocol_t;
/* Enum of standardized stack option levels
* for use with NetworkStack::setstackopt and getstackopt.
*
* @enum nsapi_level_t
* @enum nsapi_stack_level_t
*/
typedef enum nsapi_level {
NSAPI_STACK, /*!< Stack option level */
NSAPI_SOCKET, /*!< Socket option level */
} nsapi_level_t;
typedef enum nsapi_stack_level {
NSAPI_STACK = 5000, /*!< Stack option level - see nsapi_stack_option_t for options */
} nsapi_stack_level_t;
/* Enum of standardized stack options
/* Enum of standardized stack option names for level NSAPI_STACK
* of NetworkStack::setstackopt and getstackopt.
*
* These options may not be supported on all stacks, in which
* case NSAPI_ERROR_UNSUPPORTED may be returned from setsockopt.
* case NSAPI_ERROR_UNSUPPORTED may be returned.
*
* @enum nsapi_option_t
* @enum nsapi_stack_option_t
*/
typedef enum nsapi_option {
typedef enum nsapi_stack_option {
NSAPI_IPV4_MRU, /*!< Sets/gets size of largest IPv4 fragmented datagram to reassemble */
NSAPI_IPV6_MRU, /*!< Sets/gets size of largest IPv6 fragmented datagram to reassemble */
} nsapi_stack_option_t;
/* Enum of standardized socket option levels
* for use with Socket::setsockopt and getsockopt.
*
* @enum nsapi_socket_level_t
*/
typedef enum nsapi_socket_level {
NSAPI_SOCKET = 7000, /*!< Socket option level - see nsapi_socket_option_t for options */
} nsapi_socket_level_t;
/* Enum of standardized socket option names for level NSAPI_SOCKET
* of Socket::setsockopt and getsockopt.
*
* These options may not be supported on all stacks, in which
* case NSAPI_ERROR_UNSUPPORTED may be returned.
*
* @enum nsapi_socket_option_t
*/
typedef enum nsapi_socket_option {
NSAPI_REUSEADDR, /*!< Allow bind to reuse local addresses */
NSAPI_KEEPALIVE, /*!< Enables sending of keepalive messages */
NSAPI_KEEPIDLE, /*!< Sets timeout value to initiate keepalive */
@ -184,7 +210,11 @@ typedef enum nsapi_option {
NSAPI_LINGER, /*!< Keeps close from returning until queues empty */
NSAPI_SNDBUF, /*!< Sets send buffer size */
NSAPI_RCVBUF, /*!< Sets recv buffer size */
} nsapi_option_t;
} nsapi_socket_option_t;
/* Backwards compatibility - previously didn't distinguish stack and socket options */
typedef nsapi_socket_level_t nsapi_level_t;
typedef nsapi_socket_option_t nsapi_option_t;
/** nsapi_wifi_ap structure
*

View File

@ -113,6 +113,17 @@ bool USBAudio::write(uint8_t * buf) {
return true;
}
void USBAudio::writeSync(uint8_t *buf)
{
USBDevice::writeNB(EP3IN, buf, PACKET_SIZE_ISO_OUT, PACKET_SIZE_ISO_OUT);
}
uint32_t USBAudio::readSync(uint8_t *buf)
{
uint32_t size = 0;
USBDevice::readEP(EP3OUT, (uint8_t *)buf, &size, PACKET_SIZE_ISO_IN);
return size;
}
float USBAudio::getVolume() {
return (mute) ? 0.0 : volume;
@ -127,6 +138,10 @@ bool USBAudio::EPISO_OUT_callback() {
available = true;
buf_stream_in = NULL;
}
else {
if (rxDone)
rxDone.call();
}
readStart(EP3OUT, PACKET_SIZE_ISO_IN);
return false;
}
@ -135,6 +150,8 @@ bool USBAudio::EPISO_OUT_callback() {
bool USBAudio::EPISO_IN_callback() {
interruptIN = true;
writeIN = true;
if (txDone)
txDone.call();
return true;
}

View File

@ -107,6 +107,14 @@ public:
*/
bool readNB(uint8_t * buf);
/**
* read last received packet if some.
* @param buf pointer on a buffer which will be filled if an audio packet is available
*
* @returns the packet length
*/
uint32_t readSync(uint8_t *buf);
/**
* Write an audio packet. During a frame, only a single writing (you can't write and read an audio packet during the same frame)can be done using this method.
*
@ -115,6 +123,12 @@ public:
*/
bool write(uint8_t * buf);
/**
* Write packet in endpoint fifo. assuming tx fifo is empty
* @param buf pointer on the audio packet which will be sent
*/
void writeSync(uint8_t *buf);
/**
* Write and read an audio packet at the same time (on the same frame)
*
@ -133,6 +147,22 @@ public:
void attach(void(*fptr)(void)) {
updateVol.attach(fptr);
}
/** attach a handler to Tx Done
*
* @param function Function to attach
*
*/
void attachTx(void(*fptr)(void)) {
txDone.attach(fptr);
}
/** attach a handler to Rx Done
*
* @param function Function to attach
*
*/
void attachRx(void(*fptr)(void)) {
rxDone.attach(fptr);
}
/** Attach a nonstatic void/void member function to update the volume
*
@ -144,6 +174,14 @@ public:
void attach(T *tptr, void(T::*mptr)(void)) {
updateVol.attach(tptr, mptr);
}
template<typename T>
void attachTx(T *tptr, void(T::*mptr)(void)) {
txDone.attach(tptr, mptr);
}
template<typename T>
void attachRx(T *tptr, void(T::*mptr)(void)) {
rxDone.attach(tptr, mptr);
}
protected:
@ -277,6 +315,11 @@ private:
// callback to update volume
Callback<void()> updateVol;
// callback transmit Done
Callback<void()> txDone;
// callback transmit Done
Callback<void()> rxDone;
// boolean showing that the SOF handler has been called. Useful for readNB.
volatile bool SOF_handler;

View File

@ -53,6 +53,10 @@ typedef enum {
#include "USBEndpoints_Maxim.h"
#elif defined(TARGET_EFM32GG_STK3700) || defined(TARGET_EFM32LG_STK3600) || defined(TARGET_EFM32WG_STK3800) || defined(TARGET_EFM32HG_STK3400)
#include "USBEndpoints_EFM32.h"
#elif defined(TARGET_NUMAKER_PFM_NUC472)
#include "USBEndpoints_NUC472.h"
#elif defined(TARGET_NUMAKER_PFM_M453)
#include "USBEndpoints_M453.h"
#else
#error "Unknown target type"
#endif

View File

@ -0,0 +1,79 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define NU_MAX_EPX_BUFSIZE 4096
#define NU_EP2EPL(ep) ((ep) >> 1)
#define NU_EP2EPH(ep) (((ep) >> 1) + 1)
#define NU_EPL2EPH(ep) ((ep) + 1)
#define NU_EPH2EPL(ep) ((ep) - 1)
#define NU_EP_DIR_Pos 0
#define NU_EP_DIR_Msk (1 << NU_EP_DIR_Pos)
#define NU_EP_DIR_OUT 0
#define NU_EP_DIR_IN 1
#define NU_EP_TYPE(ep) (((ep) & NU_EP_TYPE_Msk) >> NU_EP_TYPE_Pos)
#define NU_EP_NUM(ep) (((ep) & NU_EP_NUM_Msk) >> NU_EP_NUM_Pos)
#define NU_EP_DIR(ep) (((ep) & NU_EP_DIR_Msk) >> NU_EP_DIR_Pos)
#define NU_EP_NUM_DIR(ep) ((NU_EP_NUM(ep) << 1) | NU_EP_DIR(ep))
#define NUMBER_OF_PHYSICAL_ENDPOINTS 8
#define EP0OUT (0)
#define EP0IN (1)
#define EP1OUT (2)
#define EP1IN (3)
#define EP2OUT (4)
#define EP2IN (5)
#define EP3OUT (6)
#define EP3IN (7)
#define EP4OUT (8)
#define EP4IN (9)
#define EP5OUT (10)
#define EP5IN (11)
#define EP6OUT (12)
#define EP6IN (13)
/* Maximum Packet sizes */
#define MAX_PACKET_SIZE_EP0 64
#define MAX_PACKET_SIZE_EP1 64
#define MAX_PACKET_SIZE_EP2 64
#define MAX_PACKET_SIZE_EP3 0x60
#define MAX_PACKET_SIZE_EP4 64
#define MAX_PACKET_SIZE_EP5 64
#define MAX_PACKET_SIZE_EP6 64
#define MAX_PACKET_SIZE_EP7 64
/* Generic endpoints - intended to be portable accross devices */
/* and be suitable for simple USB devices. */
/* Bulk endpoints */
#define EPBULK_OUT EP5OUT
#define EPBULK_IN EP6IN
#define EPBULK_OUT_callback EP5_OUT_callback
#define EPBULK_IN_callback EP6_IN_callback
/* Interrupt endpoints */
#define EPINT_OUT EP1OUT
#define EPINT_IN EP2IN
#define EPINT_OUT_callback EP1_OUT_callback
#define EPINT_IN_callback EP2_IN_callback
/* Isochronous endpoints */
#define EPISO_OUT EP3OUT
#define EPISO_IN EP4IN
#define EPISO_OUT_callback EP3_OUT_callback
#define EPISO_IN_callback EP4_IN_callback
#define MAX_PACKET_SIZE_EPBULK 64
#define MAX_PACKET_SIZE_EPINT 64
#define MAX_PACKET_SIZE_EPISO 1023

View File

@ -0,0 +1,89 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define NU_MAX_EPX_BUFSIZE 4096
#define NU_EP2EPL(ep) ((ep) >> 1)
#define NU_EP2EPH(ep) (((ep) >> 1) - 1)
#define NU_EPX2EP(ep) ((ep == CEP) ? EP0OUT : ((ep) - EPA + EP1OUT))
#define NU_EPL2EPH(ep) ((ep) - 1)
#define NU_EPH2EPL(ep) ((ep) + 1)
#define NU_EP_DIR_Pos 0
#define NU_EP_DIR_Msk (1 << NU_EP_DIR_Pos)
#define NU_EP_DIR_OUT 0
#define NU_EP_DIR_IN 1
#define NU_EP_TYPE(ep) (((ep) & NU_EP_TYPE_Msk) >> NU_EP_TYPE_Pos)
#define NU_EP_NUM(ep) (((ep) & NU_EP_NUM_Msk) >> NU_EP_NUM_Pos)
#define NU_EP_DIR(ep) (((ep) & NU_EP_DIR_Msk) >> NU_EP_DIR_Pos)
#define NU_EP_NUM_DIR(ep) ((NU_EP_NUM(ep) << 1) | NU_EP_DIR(ep))
#define NUMBER_OF_PHYSICAL_ENDPOINTS 12
#define EP0OUT (0)
#define EP0IN (1)
#define EP1OUT (2)
#define EP1IN (3)
#define EP2OUT (4)
#define EP2IN (5)
#define EP3OUT (6)
#define EP3IN (7)
#define EP4OUT (8)
#define EP4IN (9)
#define EP5OUT (10)
#define EP5IN (11)
#define EP6OUT (12)
#define EP6IN (13)
/* Maximum Packet sizes */
#define MAX_PACKET_SIZE_EP0 64
#define MAX_PACKET_SIZE_EP1 64
#define MAX_PACKET_SIZE_EP2 64
#define MAX_PACKET_SIZE_EP3 0x60
#define MAX_PACKET_SIZE_EP4 64
#define MAX_PACKET_SIZE_EP5 64
#define MAX_PACKET_SIZE_EP6 64
#define MAX_PACKET_SIZE_EP7 64
#define MAX_PACKET_SIZE_EP8 64
#define MAX_PACKET_SIZE_EP9 64
#define MAX_PACKET_SIZE_EP10 64
#define MAX_PACKET_SIZE_EP11 64
/* Generic endpoints - intended to be portable accross devices */
/* and be suitable for simple USB devices. */
/* Bulk endpoints */
#define EPBULK_OUT EP5OUT
#define EPBULK_IN EP6IN
#define EPBULK_OUT_callback EP5_OUT_callback
#define EPBULK_IN_callback EP6_IN_callback
/* Interrupt endpoints */
#define EPINT_OUT EP1OUT
#define EPINT_IN EP2IN
#define EPINT_OUT_callback EP1_OUT_callback
#define EPINT_IN_callback EP2_IN_callback
/* Isochronous endpoints */
#define EPISO_OUT EP3OUT
#define EPISO_IN EP4IN
#define EPISO_OUT_callback EP3_OUT_callback
#define EPISO_IN_callback EP4_IN_callback
#define MAX_PACKET_SIZE_EPBULK 64
#define MAX_PACKET_SIZE_EPINT 64
#define MAX_PACKET_SIZE_EPISO 1023
#define USBD_GET_EP_MAX_PAYLOAD(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EPAMPS + (uint32_t)((ep)*0x28))))
#define USBD_GET_EP_DATA_COUNT(ep) ((*((__IO uint32_t *) ((uint32_t)&USBD->EPADATCNT + (uint32_t)((ep)*0x28)))) & 0xFFFFF)
#define USBD_SET_EP_SHORT_PACKET(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EPARSPCTL + (uint32_t)((ep)*0x28))) = (*((__IO uint32_t *) ((uint32_t)&USBD->EPARSPCTL + (uint32_t)((ep)*0x28)))) & 0x10 | 0x40)
#define USBD_GET_EP_INT_EN(ep) (*((__IO uint32_t *) ((uint32_t)&USBD->EPAINTEN + (uint32_t)((ep)*0x28))))

View File

@ -68,6 +68,23 @@ protected:
virtual void suspendStateChanged(unsigned int suspended){};
virtual void SOF(int frameNumber){};
#if defined(TARGET_NUMAKER_PFM_NUC472) || defined(TARGET_NUMAKER_PFM_M453)
// NUC472/M453 USB doesn't support configuration of the same EP number for IN/OUT simultaneously.
virtual bool EP1_OUT_callback(){return false;};
virtual bool EP2_IN_callback(){return false;};
virtual bool EP3_OUT_callback(){return false;};
virtual bool EP4_IN_callback(){return false;};
virtual bool EP5_OUT_callback(){return false;};
virtual bool EP6_IN_callback(){return false;};
#if ! (defined(TARGET_NUMAKER_PFM_M453))
virtual bool EP7_OUT_callback(){return false;};
virtual bool EP8_IN_callback(){return false;};
virtual bool EP9_OUT_callback(){return false;};
virtual bool EP10_IN_callback(){return false;};
virtual bool EP11_OUT_callback(){return false;};
virtual bool EP12_IN_callback(){return false;};
#endif
#else
virtual bool EP1_OUT_callback(){return false;};
virtual bool EP1_IN_callback(){return false;};
virtual bool EP2_OUT_callback(){return false;};
@ -102,6 +119,7 @@ protected:
virtual bool EP15_IN_callback(){return false;};
#endif
#endif
#endif
private:
void usbisr(void);
@ -110,10 +128,12 @@ private:
#if defined(TARGET_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
bool (USBHAL::*epCallback[10 - 2])(void);
#elif defined(TARGET_STM32F4) && !defined(USB_STM_HAL)
#elif (defined(TARGET_STM32F4) && !defined(USB_STM_HAL)) || defined(TARGET_NUMAKER_PFM_M453)
bool (USBHAL::*epCallback[8 - 2])(void);
#elif defined(TARGET_STM32F4) || defined(TARGET_STM32F3) || defined (TARGET_STM32F2)|| defined(TARGET_STM32L4) || defined(TARGET_STM32F7)
PCD_HandleTypeDef hpcd;
#elif defined(TARGET_NUMAKER_PFM_NUC472)
bool (USBHAL::*epCallback[14 - 2])(void);
#else
bool (USBHAL::*epCallback[32 - 2])(void);
#endif

View File

@ -0,0 +1,464 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined(TARGET_NUMAKER_PFM_M453)
#include "USBHAL.h"
#include "M451Series.h"
#include "pinmap.h"
/**
* EP: mbed USBD defined endpoint, e.g. EP0OUT/IN, EP1OUT/IN, EP2OUT/IN.
* EPX: BSP defined endpoint, e.g. CEP, EPA, EPB, EPC.
*/
USBHAL * USBHAL::instance;
/* Global variables for Control Pipe */
extern uint8_t g_usbd_SetupPacket[]; /*!< Setup packet buffer */
static volatile uint32_t s_ep_compl = 0;
static volatile uint32_t s_ep_buf_ind = 8;
static volatile uint8_t s_usb_addr = 0;
static volatile uint8_t s_ep_data_bit[NUMBER_OF_PHYSICAL_ENDPOINTS] = {1};
static volatile uint8_t s_ep_mxp[NUMBER_OF_PHYSICAL_ENDPOINTS] = {0};
extern volatile uint8_t *g_usbd_CtrlInPointer;
extern volatile uint32_t g_usbd_CtrlInSize;
extern volatile uint8_t *g_usbd_CtrlOutPointer;
extern volatile uint32_t g_usbd_CtrlOutSize;
extern volatile uint32_t g_usbd_CtrlOutSizeLimit;
extern volatile uint32_t g_usbd_UsbConfig;
extern volatile uint32_t g_usbd_CtrlMaxPktSize;
extern volatile uint32_t g_usbd_UsbAltInterface;
volatile uint32_t g_usbd_CepTransferLen = 0;
volatile uint32_t frame_cnt = 0;
USBHAL::USBHAL(void)
{
SYS_UnlockReg();
s_ep_buf_ind = 8;
memset(epCallback, 0x00, sizeof (epCallback));
epCallback[0] = &USBHAL::EP1_OUT_callback;
epCallback[1] = &USBHAL::EP2_IN_callback;
epCallback[2] = &USBHAL::EP3_OUT_callback;
epCallback[3] = &USBHAL::EP4_IN_callback;
epCallback[4] = &USBHAL::EP5_OUT_callback;
epCallback[5] = &USBHAL::EP6_IN_callback;
instance = this;
/* Enable USBD module clock */
CLK_EnableModuleClock(USBD_MODULE);
CLK_SetModuleClock(USBD_MODULE, 0, CLK_CLKDIV0_USB(3));
/* Enable USB LDO33 */
SYS->USBPHY = SYS_USBPHY_LDO33EN_Msk;
/* Initial USB engine */
USBD->ATTR = 0x7D0;
/* Set SE0 (disconnect) */
USBD_SET_SE0();
//NVIC_SetVector(OTG_FS_IRQn, (uint32_t) &_usbisr);
NVIC_SetVector(USBD_IRQn, (uint32_t) &_usbisr);
NVIC_EnableIRQ(USBD_IRQn);
}
USBHAL::~USBHAL(void)
{
NVIC_DisableIRQ(USBD_IRQn);
USBD_SET_SE0();
USBD_DISABLE_PHY();
}
void USBHAL::connect(void)
{
USBD->STBUFSEG = 0;
frame_cnt = 0;
/* EP0 ==> control IN endpoint, address 0 */
USBD_CONFIG_EP(EP0, USBD_CFG_CSTALL | USBD_CFG_EPMODE_IN | 0);
/* Buffer range for EP0 */
USBD_SET_EP_BUF_ADDR(EP0, s_ep_buf_ind);
/* EP1 ==> control OUT endpoint, address 0 */
USBD_CONFIG_EP(EP1, USBD_CFG_CSTALL | USBD_CFG_EPMODE_OUT | 0);
/* Buffer range for EP1 */
USBD_SET_EP_BUF_ADDR(EP1, s_ep_buf_ind);
s_ep_buf_ind += MAX_PACKET_SIZE_EP0;
/* Disable software-disconnect function */
USBD_CLR_SE0();
/* Clear USB-related interrupts before enable interrupt */
USBD_CLR_INT_FLAG(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
/* Enable USB-related interrupts. */
USBD_ENABLE_INT(USBD_INT_BUS | USBD_INT_USB | USBD_INT_FLDET | USBD_INT_WAKEUP);
}
void USBHAL::disconnect(void)
{
/* Set SE0 (disconnect) */
USBD_SET_SE0();
}
void USBHAL::configureDevice(void)
{
/**
* In USBDevice.cpp > USBDevice::requestSetConfiguration, configureDevice() is called after realiseEndpoint() (in USBCallback_setConfiguration()).
* So we have the following USB buffer management policy:
* 1. Allocate for CEP on connect().
* 2. Allocate for EPX in realiseEndpoint().
* 3. Deallocate all except for CEP in unconfigureDevice().
*/
}
void USBHAL::unconfigureDevice(void)
{
s_ep_buf_ind = 8;
}
void USBHAL::setAddress(uint8_t address)
{
// NOTE: Delay address setting; otherwise, USB controller won't ack.
s_usb_addr = address;
}
void USBHAL::remoteWakeup(void)
{
#if 0
USBD->OPER |= USBD_OPER_RESUMEEN_Msk;
#endif
}
bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
{
uint32_t ep_type = 0;
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
uint32_t ep_logic_index = NU_EP2EPL(endpoint);
uint32_t ep_dir = (NU_EP_DIR(endpoint) == NU_EP_DIR_IN) ? USBD_CFG_EPMODE_IN : USBD_CFG_EPMODE_OUT;
if(ep_logic_index == 3 || ep_logic_index == 4)
ep_type = USBD_CFG_TYPE_ISO;
USBD_CONFIG_EP(ep_hw_index, ep_dir | ep_type | ep_logic_index);
/* Buffer range */
USBD_SET_EP_BUF_ADDR(ep_hw_index, s_ep_buf_ind);
if(ep_dir == USBD_CFG_EPMODE_OUT)
USBD_SET_PAYLOAD_LEN(ep_hw_index, maxPacket);
s_ep_mxp[ep_logic_index] = maxPacket;
s_ep_buf_ind += maxPacket;
return true;
}
void USBHAL::EP0setup(uint8_t *buffer)
{
uint32_t sz;
endpointReadResult(EP0OUT, buffer, &sz);
}
void USBHAL::EP0read(void)
{
}
void USBHAL::EP0readStage(void)
{
// N/A
USBD_PrepareCtrlOut(0,0);
}
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
{
uint32_t i;
uint8_t *buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP1));
uint32_t ceprxcnt = USBD_GET_PAYLOAD_LEN(EP1);
for (i = 0; i < ceprxcnt; i ++)
buffer[i] = buf[i];
USBD_SET_PAYLOAD_LEN(EP1, MAX_PACKET_SIZE_EP0);
return ceprxcnt;
}
void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
{
if (buffer && size)
{
if(s_ep_data_bit[0] & 1)
USBD_SET_DATA1(EP0);
else
USBD_SET_DATA0(EP0);
s_ep_data_bit[0]++;
USBD_MemCopy((uint8_t *)USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(EP0), buffer, size);
USBD_SET_PAYLOAD_LEN(EP0, size);
if(size < MAX_PACKET_SIZE_EP0)
s_ep_data_bit[0] = 1;
}
else
{
if(g_usbd_SetupPacket[0] & 0x80) //Device to Host
{
// Status stage
// USBD_PrepareCtrlOut(0,0);
}else
{
USBD_SET_DATA1(EP0);
USBD_SET_PAYLOAD_LEN(EP0, 0);
}
}
}
void USBHAL::EP0getWriteResult(void)
{
// N/A
}
void USBHAL::EP0stall(void)
{
stallEndpoint(EP0OUT);
}
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
{
return EP_PENDING;
}
EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) //spcheng
{
if(endpoint == EP0OUT)
{
USBD_MemCopy(g_usbd_SetupPacket, (uint8_t *)USBD_BUF_BASE, 8);
if (buffer) {
USBD_MemCopy(buffer, g_usbd_SetupPacket, 8);
}
USBD_SET_PAYLOAD_LEN(EP1, MAX_PACKET_SIZE_EP0);
}
else
{
uint32_t i;
uint8_t *buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(NU_EP2EPH(endpoint)));
uint32_t eprxcnt = USBD_GET_PAYLOAD_LEN(NU_EP2EPH(endpoint));
for (i = 0; i < eprxcnt; i ++)
buffer[i] = buf[i];
*bytesRead = eprxcnt;
USBD_SET_PAYLOAD_LEN(NU_EP2EPH(endpoint),s_ep_mxp[NU_EPH2EPL(NU_EP2EPL(endpoint))]);
}
return EP_COMPLETED;
}
uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer)
{
return 0;
}
EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
{
uint32_t ep_logic_index = NU_EP2EPL(endpoint);
if(ep_logic_index == 0)
return EP_INVALID;
else
{
uint8_t *buf;
uint32_t i=0;
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
s_ep_compl |= (1 << ep_logic_index);
buf = (uint8_t *)(USBD_BUF_BASE + USBD_GET_EP_BUF_ADDR(ep_hw_index));
for(i=0;i<size;i++)
buf[i] = data[i];
/* Set transfer length and trigger IN transfer */
USBD_SET_PAYLOAD_LEN(ep_hw_index, size);
}
return EP_PENDING;
}
EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
{
if (!(s_ep_compl & (1 << NU_EP2EPL(endpoint))))
return EP_COMPLETED;
return EP_PENDING;
}
void USBHAL::stallEndpoint(uint8_t endpoint)
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
return;
USBD_SetStall(NU_EPH2EPL(ep_hw_index));
}
void USBHAL::unstallEndpoint(uint8_t endpoint)
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
return;
USBD_ClearStall(NU_EPH2EPL(ep_hw_index));
}
bool USBHAL::getEndpointStallState(uint8_t endpoint)
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
return false;
return USBD_GetStall(NU_EPH2EPL(ep_hw_index)) ? 1 : 0;
}
void USBHAL::_usbisr(void)
{
MBED_ASSERT(instance);
instance->usbisr();
}
void USBHAL::usbisr(void)
{
uint32_t u32IntSts = USBD_GET_INT_FLAG();
uint32_t u32State = USBD_GET_BUS_STATE();
//------------------------------------------------------------------
if(u32IntSts & USBD_INTSTS_VBDETIF_Msk)
{
// Floating detect
USBD_CLR_INT_FLAG(USBD_INTSTS_VBDETIF_Msk);
if(USBD_IS_ATTACHED())
{
/* USB Plug In */
USBD_ENABLE_USB();
}
else
{
/* USB Un-plug */
USBD_DISABLE_USB();
}
}
//------------------------------------------------------------------
if(u32IntSts & USBD_INTSTS_BUSIF_Msk)
{
/* Clear event flag */
USBD_CLR_INT_FLAG(USBD_INTSTS_BUSIF_Msk);
if(u32State & USBD_ATTR_USBRST_Msk)
{
/* Bus reset */
USBD_ENABLE_USB();
USBD_SwReset();
}
if(u32State & USBD_ATTR_SUSPEND_Msk)
{
/* Enable USB but disable PHY */
USBD_DISABLE_PHY();
}
if(u32State & USBD_ATTR_RESUME_Msk)
{
/* Enable USB and enable PHY */
USBD_ENABLE_USB();
}
}
if(u32IntSts & USBD_INTSTS_USBIF_Msk)
{
// USB event
if(u32IntSts & USBD_INTSTS_SETUP_Msk)
{
// Setup packet
/* Clear event flag */
USBD_CLR_INT_FLAG(USBD_INTSTS_SETUP_Msk);
/* Clear the data IN/OUT ready flag of control end-points */
USBD_STOP_TRANSACTION(EP0);
USBD_STOP_TRANSACTION(EP1);
EP0setupCallback();
}
// EP events
if(u32IntSts & USBD_INTSTS_EP0)
{
/* Clear event flag */
USBD_CLR_INT_FLAG(USBD_INTSTS_EP0);
// control IN
EP0in();
// In ACK for Set address
if((g_usbd_SetupPacket[0] == REQ_STANDARD) && (g_usbd_SetupPacket[1] == USBD_SET_ADDRESS))
{
if((USBD_GET_ADDR() != s_usb_addr) && (USBD_GET_ADDR() == 0))
{
USBD_SET_ADDR(s_usb_addr);
}
}
}
if(u32IntSts & USBD_INTSTS_EP1)
{
/* Clear event flag */
USBD_CLR_INT_FLAG(USBD_INTSTS_EP1);
// control OUT
EP0out();
}
uint32_t gintsts_epx = (u32IntSts >> 18) & 0x3F;
uint32_t ep_hw_index = 2;
while (gintsts_epx) {
if(gintsts_epx & 0x01)
{
uint32_t ep_status = (USBD_GET_EP_FLAG() >> (ep_hw_index * 3 + 8)) & 0x7;
/* Clear event flag */
USBD_CLR_INT_FLAG(1 << (ep_hw_index + 16));
if(ep_status == 0x02 || ep_status == 0x06 || (ep_status == 0x07 && NU_EPH2EPL(ep_hw_index) == 3)) //RX
{
if(ep_status == 0x07)
SOF(frame_cnt++);
if ((instance->*(epCallback[ep_hw_index-2]))())
{
}
USBD_SET_PAYLOAD_LEN(ep_hw_index,s_ep_mxp[NU_EPH2EPL(ep_hw_index)]);
}
else if(ep_status == 0x00 || ep_status == 0x07) //TX
{
s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index)));
if ((instance->*(epCallback[ep_hw_index-2]))())
{
}
}
}
gintsts_epx = gintsts_epx >> 1;
ep_hw_index++;
}
}
}
#endif

View File

@ -0,0 +1,729 @@
/* mbed Microcontroller Library
* Copyright (c) 2015-2016 Nuvoton
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if defined(TARGET_NUMAKER_PFM_NUC472)
#include "USBHAL.h"
#include "NUC472_442.h"
#include "pinmap.h"
/**
* EP: mbed USBD defined endpoint, e.g. EP0OUT/IN, EP1OUT/IN, EP2OUT/IN.
* EPX: BSP defined endpoint, e.g. CEP, EPA, EPB, EPC.
*/
USBHAL * USBHAL::instance;
static volatile uint32_t s_ep_compl = 0;
static volatile uint32_t s_ep_buf_ind = 0;
static volatile uint8_t s_usb_addr = 0;
static volatile S_USBD_CMD_T s_setup;
static volatile uint16_t s_ctrlin_packetsize;
static uint8_t *g_usbd_CtrlInPointer = 0;
static uint32_t g_usbd_CtrlMaxPktSize = 64;
static uint32_t g_usbd_ShortPkt = 0;
static uint32_t gEpRead = 0;
static uint32_t gEpReadCnt = 0;
void USBD_CtrlInput(void)
{
int volatile i;
uint32_t volatile count;
// Process remained data
if(g_usbd_CtrlInSize >= g_usbd_CtrlMaxPktSize)
{
// Data size > MXPLD
for (i=0; i<(g_usbd_CtrlMaxPktSize >> 2); i++, g_usbd_CtrlInPointer+=4)
USBD->CEPDAT = *(uint32_t *)g_usbd_CtrlInPointer;
USBD_START_CEP_IN(g_usbd_CtrlMaxPktSize);
g_usbd_CtrlInSize -= g_usbd_CtrlMaxPktSize;
}
else
{
// Data size <= MXPLD
for (i=0; i<(g_usbd_CtrlInSize >> 2); i++, g_usbd_CtrlInPointer+=4)
USBD->CEPDAT = *(uint32_t *)g_usbd_CtrlInPointer;
count = g_usbd_CtrlInSize % 4;
for (i=0; i<count; i++)
USBD->CEPDAT_BYTE = *(uint8_t *)(g_usbd_CtrlInPointer + i);
USBD_START_CEP_IN(g_usbd_CtrlInSize);
g_usbd_CtrlInPointer = 0;
g_usbd_CtrlInSize = 0;
}
}
USBHAL::USBHAL(void)
{
SYS_UnlockReg();
s_ep_buf_ind = 0;
memset(epCallback, 0x00, sizeof (epCallback));
epCallback[0] = &USBHAL::EP1_OUT_callback;
epCallback[1] = &USBHAL::EP2_IN_callback;
epCallback[2] = &USBHAL::EP3_OUT_callback;
epCallback[3] = &USBHAL::EP4_IN_callback;
epCallback[4] = &USBHAL::EP5_OUT_callback;
epCallback[5] = &USBHAL::EP6_IN_callback;
epCallback[6] = &USBHAL::EP7_OUT_callback;
epCallback[7] = &USBHAL::EP8_IN_callback;
epCallback[8] = &USBHAL::EP9_OUT_callback;
epCallback[9] = &USBHAL::EP10_IN_callback;
epCallback[10] = &USBHAL::EP11_OUT_callback;
epCallback[11] = &USBHAL::EP12_IN_callback;
instance = this;
/* Enable USBD module clock */
CLK_EnableModuleClock(USBD_MODULE);
/* Enable USB PHY's LDO33. Run as USB device. */
SYS->USBPHY = SYS_USBPHY_USBROLE_OTG_V33_EN | SYS_USBPHY_USBROLE_STD_USBD;
/* Enable USB PHY and wait for it ready */
USBD_ENABLE_PHY();
while (1)
{
USBD->EPAMPS = 0x20;
if (USBD->EPAMPS == 0x20)
break;
}
/* Force to full-speed */
USBD->OPER = 0;//USBD_OPER_HISPDEN_Msk;
/* Set SE0 (disconnect) */
USBD_SET_SE0();
NVIC_SetVector(USBD_IRQn, (uint32_t) &_usbisr);
NVIC_EnableIRQ(USBD_IRQn);
}
USBHAL::~USBHAL(void)
{
NVIC_DisableIRQ(USBD_IRQn);
USBD_SET_SE0();
USBD_DISABLE_PHY();
}
void USBHAL::connect(void)
{
USBD_ResetDMA();
USBD_SET_ADDR(0);
/**
* Control Transfer Packet Size Constraints
* low-speed: 8
* full-speed: 8, 16, 32, 64
* high-speed: 64
*/
/* Control endpoint */
USBD_SetEpBufAddr(CEP, s_ep_buf_ind, MAX_PACKET_SIZE_EP0);
s_ep_buf_ind = MAX_PACKET_SIZE_EP0;
/* Enable USB/CEP interrupt */
USBD_ENABLE_USB_INT(USBD_GINTEN_USBIE_Msk | USBD_GINTEN_CEPIE_Msk);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk|USBD_CEPINTEN_STSDONEIEN_Msk);
/* Enable BUS interrupt */
USBD_ENABLE_BUS_INT(
USBD_BUSINTEN_DMADONEIEN_Msk |
USBD_BUSINTEN_RESUMEIEN_Msk |
USBD_BUSINTEN_RSTIEN_Msk |
USBD_BUSINTEN_VBUSDETIEN_Msk |
USBD_BUSINTEN_SOFIEN_Msk
);
/* Clear SE0 (connect) */
USBD_CLR_SE0();
}
void USBHAL::disconnect(void)
{
/* Set SE0 (disconnect) */
USBD_SET_SE0();
}
void USBHAL::configureDevice(void)
{
/**
* In USBDevice.cpp > USBDevice::requestSetConfiguration, configureDevice() is called after realiseEndpoint() (in USBCallback_setConfiguration()).
* So we have the following USB buffer management policy:
* 1. Allocate for CEP on connect().
* 2. Allocate for EPX in realiseEndpoint().
* 3. Deallocate all except for CEP in unconfigureDevice().
*/
}
void USBHAL::unconfigureDevice(void)
{
s_ep_buf_ind = MAX_PACKET_SIZE_EP0;
}
void USBHAL::setAddress(uint8_t address)
{
// NOTE: Delay address setting; otherwise, USB controller won't ack.
s_usb_addr = address;
}
void USBHAL::remoteWakeup(void)
{
USBD->OPER |= USBD_OPER_RESUMEEN_Msk;
}
bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
{
uint32_t ep_type;
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
USBD_SetEpBufAddr(ep_hw_index, s_ep_buf_ind, maxPacket);
s_ep_buf_ind += maxPacket;
USBD_SET_MAX_PAYLOAD(ep_hw_index, maxPacket);
switch (NU_EP2EPL(endpoint))
{
case 1:case 2:
ep_type = USB_EP_CFG_TYPE_INT;
break;
case 3:case 4:
ep_type = USB_EP_CFG_TYPE_ISO;
break;
default:
ep_type = USB_EP_CFG_TYPE_BULK;
}
uint32_t ep_dir = (NU_EP_DIR(endpoint) == NU_EP_DIR_IN) ? USB_EP_CFG_DIR_IN : USB_EP_CFG_DIR_OUT;
USBD_ConfigEp(ep_hw_index, NU_EP2EPL(endpoint), ep_type, ep_dir);
/* Enable USB/EPX interrupt */
// NOTE: Require USBD_GINTEN_EPAIE_Pos, USBD_GINTEN_EPBIE_Pos, ... USBD_GINTEN_EPLIE_Pos to be consecutive.
USBD_ENABLE_USB_INT(USBD->GINTEN | USBD_GINTEN_USBIE_Msk |
USBD_GINTEN_CEPIE_Msk |
1 << (ep_hw_index + USBD_GINTEN_EPAIE_Pos)); // Added USB/EPX interrupt
if (ep_dir == 0)
USBD_ENABLE_EP_INT(ep_hw_index, USBD_EPINTEN_RXPKIEN_Msk);
else
USBD_ENABLE_EP_INT(ep_hw_index, USBD_EPINTEN_TXPKIEN_Msk);
return true;
}
void USBHAL::EP0setup(uint8_t *buffer)
{
uint32_t sz;
endpointReadResult(EP0OUT, buffer, &sz);
}
void USBHAL::EP0read(void)
{
if (s_setup.wLength && ! (s_setup.bmRequestType & 0x80))
{
// Control OUT
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk | USBD_CEPINTEN_RXPKIEN_Msk);
}
else
{
// Status stage
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk);
USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk);
}
}
void USBHAL::EP0readStage(void)
{
// N/A
}
uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
{
uint32_t i;
uint32_t ceprxcnt = USBD->CEPRXCNT;
for (i = 0; i < ceprxcnt; i ++)
*buffer ++ = USBD->CEPDAT_BYTE;
return ceprxcnt;
}
void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
{
if (buffer && size)
{
g_usbd_CtrlInPointer = buffer;
g_usbd_CtrlInSize = size;
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_INTKIEN_Msk);
}
else
{
/* Status stage */
s_ctrlin_packetsize = 0;
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk);
USBD_SET_CEP_STATE(USB_CEPCTL_NAKCLR);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk);
}
}
void USBHAL::EP0getWriteResult(void)
{
// N/A
}
void USBHAL::EP0stall(void)
{
stallEndpoint(EP0OUT);
}
EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
{
return EP_PENDING;
}
EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) //spcheng
{
if(endpoint == EP0OUT)
{
if (buffer) {
*((uint16_t *) (buffer + 0)) = (uint16_t) USBD->SETUP1_0;
*((uint16_t *) (buffer + 2)) = (uint16_t) USBD->SETUP3_2;
*((uint16_t *) (buffer + 4)) = (uint16_t) USBD->SETUP5_4;
*((uint16_t *) (buffer + 6)) = (uint16_t) USBD->SETUP7_6;
}
s_setup.bmRequestType = (uint8_t) (USBD->SETUP1_0 & 0xff);
s_setup.bRequest = (int8_t) (USBD->SETUP1_0 >> 8) & 0xff;
s_setup.wValue = (uint16_t) USBD->SETUP3_2;
s_setup.wIndex = (uint16_t) USBD->SETUP5_4;
s_setup.wLength = (uint16_t) USBD->SETUP7_6;
}
else
{
if (!(s_ep_compl & (1 << NU_EP2EPL(endpoint))))
{
while(1)
{
if (!(USBD->DMACTL & USBD_DMACTL_DMAEN_Msk))
break;
else
if (!USBD_IS_ATTACHED())
break;
}
gEpReadCnt = USBD_GET_EP_DATA_COUNT(NU_EP2EPH(endpoint));
if(gEpReadCnt == 0)
{
*bytesRead = 0;
return EP_COMPLETED;
}
s_ep_compl |= (1 << NU_EP2EPL(endpoint));
USBD_SET_DMA_LEN(gEpReadCnt);
USBD_SET_DMA_ADDR((uint32_t)buffer);
USBD_SET_DMA_WRITE(NU_EP2EPL(endpoint));
USBD_ENABLE_DMA();
return EP_PENDING;;
}
else
{
if ((USBD->DMACTL & USBD_DMACTL_DMAEN_Msk))
return EP_PENDING;;
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_DMADONEIF_Msk);
s_ep_compl &= ~(1 << NU_EP2EPL(endpoint));
*bytesRead = gEpReadCnt;
}
}
return EP_COMPLETED;
}
uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer)
{
return 0;
}
EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
{
uint32_t ep_logic_index = NU_EP2EPL(endpoint);
if(ep_logic_index == 0)
return EP_INVALID;
else
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
uint32_t mps = USBD_GET_EP_MAX_PAYLOAD(ep_hw_index);
if (size > mps) {
return EP_INVALID;
}
if(size < mps)
g_usbd_ShortPkt = 1;
if (!(s_ep_compl & (1 << NU_EP2EPL(endpoint))))
{
s_ep_compl |= (1 << ep_logic_index);
while(1)
{
if (!(USBD->DMACTL & USBD_DMACTL_DMAEN_Msk))
break;
else
if (!USBD_IS_ATTACHED())
break;
}
USBD_SET_DMA_LEN(size);
USBD_SET_DMA_ADDR((uint32_t)data);
USBD_SET_DMA_READ(ep_logic_index);
USBD_ENABLE_DMA();
}
}
return EP_PENDING;
}
EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
{
if (!(s_ep_compl & (1 << NU_EP2EPL(endpoint))))
return EP_COMPLETED;
else
{
if((USBD_GET_EP_DATA_COUNT(NU_EP2EPH(endpoint))) == 0 && !(USBD->DMACTL & USBD_DMACTL_DMAEN_Msk))
{
s_ep_compl &= ~(s_ep_compl & (1 << NU_EP2EPL(endpoint)));
return EP_COMPLETED;
}
}
return EP_PENDING;
}
void USBHAL::stallEndpoint(uint8_t endpoint)
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
return;
USBD_SetStall(ep_hw_index);
}
void USBHAL::unstallEndpoint(uint8_t endpoint)
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
return;
USBD_ClearStall(ep_hw_index);
}
bool USBHAL::getEndpointStallState(uint8_t endpoint)
{
uint32_t ep_hw_index = NU_EP2EPH(endpoint);
if (ep_hw_index >= NUMBER_OF_PHYSICAL_ENDPOINTS)
return false;
return USBD_GetStall(ep_hw_index) ? 1 : 0;
}
void USBHAL::_usbisr(void)
{
MBED_ASSERT(instance);
instance->usbisr();
}
void USBHAL::usbisr(void)
{
uint32_t gintsts = USBD->GINTSTS & USBD->GINTEN;
if (! gintsts)
return;
if (gintsts & USBD_GINTSTS_USBIF_Msk)
{
uint32_t busintsts = USBD->BUSINTSTS & USBD->BUSINTEN;
/* SOF */
if (busintsts & USBD_BUSINTSTS_SOFIF_Msk)
{
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SOFIF_Msk);
// TODO
SOF(USBD->FRAMECNT >> 3);
}
/* Reset */
if (busintsts & USBD_BUSINTSTS_RSTIF_Msk)
{
connect();
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RSTIF_Msk);
USBD_CLR_CEP_INT_FLAG(0x1ffc);
}
/* Resume */
if (busintsts & USBD_BUSINTSTS_RESUMEIF_Msk)
{
USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk|USBD_BUSINTEN_SUSPENDIEN_Msk | USBD_BUSINTEN_SOFIEN_Msk | USBD_BUSINTEN_SOFIEN_Msk);
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_RESUMEIF_Msk);
}
/* Suspend */
if (busintsts & USBD_BUSINTSTS_SUSPENDIF_Msk)
{
USBD_ENABLE_BUS_INT(USBD_BUSINTEN_RSTIEN_Msk | USBD_BUSINTEN_RESUMEIEN_Msk |USBD_BUSINTEN_SOFIEN_Msk);
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_SUSPENDIF_Msk);
}
/* High-speed */
if (busintsts & USBD_BUSINTSTS_HISPDIF_Msk)
{
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk);
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_HISPDIF_Msk);
}
/* DMA */
if (busintsts & USBD_BUSINTSTS_DMADONEIF_Msk)
{
if(USBD->DMACTL & 0x10) /* IN - Read */
{
if(g_usbd_ShortPkt)
{
uint32_t ep_hw_index = NU_EPL2EPH((USBD->DMACTL & 0xF));
USBD_SET_EP_SHORT_PACKET(ep_hw_index);
g_usbd_ShortPkt = 0;
}
}
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_DMADONEIF_Msk);
}
/* PHY clock available */
if (busintsts & USBD_BUSINTSTS_PHYCLKVLDIF_Msk)
{
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_PHYCLKVLDIF_Msk);
}
/* VBUS plug-in */
if (busintsts & USBD_BUSINTSTS_VBUSDETIF_Msk)
{
if (USBD_IS_ATTACHED())
{
// USB plug-in
USBD_ENABLE_USB();
}
else
{
// USB unplug-out
USBD_DISABLE_USB();
}
USBD_CLR_BUS_INT_FLAG(USBD_BUSINTSTS_VBUSDETIF_Msk);
}
}
/* CEP interrupts */
if (gintsts & USBD_GINTSTS_CEPIF_Msk)
{
uint32_t cepintsts = USBD->CEPINTSTS & USBD->CEPINTEN;
/* SETUP token packet */
if (cepintsts & USBD_CEPINTSTS_SETUPTKIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPTKIF_Msk);
return;
}
/* SETUP transaction */
if (cepintsts & USBD_CEPINTSTS_SETUPPKIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_SETUPPKIF_Msk);
EP0setupCallback();
return;
}
/* OUT token packet */
if (cepintsts & USBD_CEPINTSTS_OUTTKIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_OUTTKIF_Msk);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_STSDONEIEN_Msk);
return;
}
/* IN token packet */
if (cepintsts & USBD_CEPINTSTS_INTKIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_INTKIF_Msk);
if (!(cepintsts & USBD_CEPINTSTS_STSDONEIF_Msk))
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_TXPKIEN_Msk);
USBD_CtrlInput();
}
else
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_TXPKIEN_Msk|USBD_CEPINTEN_STSDONEIEN_Msk);
}
return;
}
/* PING packet */
if (cepintsts & USBD_CEPINTSTS_PINGIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_PINGIF_Msk);
return;
}
/* IN transaction */
if (cepintsts & USBD_CEPINTSTS_TXPKIF_Msk)
{
EP0in();
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_TXPKIF_Msk);
return;
}
/* OUT transaction */
if (cepintsts & USBD_CEPINTSTS_RXPKIF_Msk)
{
EP0out();
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_RXPKIF_Msk);
return;
}
/* NAK handshake packet */
if (cepintsts & USBD_CEPINTSTS_NAKIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_NAKIF_Msk);
return;
}
/* STALL handshake packet */
if (cepintsts & USBD_CEPINTSTS_STALLIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STALLIF_Msk);
return;
}
/* ERR special packet */
if (cepintsts & USBD_CEPINTSTS_ERRIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_ERRIF_Msk);
return;
}
/* Status stage transaction */
if (cepintsts & USBD_CEPINTSTS_STSDONEIF_Msk)
{
if (s_usb_addr)
{
USBD_SET_ADDR(s_usb_addr);
s_usb_addr = 0;
}
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_STSDONEIF_Msk);
USBD_ENABLE_CEP_INT(USBD_CEPINTEN_SETUPPKIEN_Msk);
return;
}
/* Buffer Full */
if (cepintsts & USBD_CEPINTSTS_BUFFULLIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFFULLIF_Msk);
return;
}
/* Buffer Empty */
if (cepintsts & USBD_CEPINTSTS_BUFEMPTYIF_Msk)
{
USBD_CLR_CEP_INT_FLAG(USBD_CEPINTSTS_BUFEMPTYIF_Msk);
return;
}
}
/* EPA, EPB, EPC, ... EPL interrupts */
uint32_t gintsts_epx = gintsts >> 2;
uint32_t ep_hw_index = 0;
while (gintsts_epx) {
if(gintsts_epx & 0x01)
{
uint32_t epxintsts = USBD_GET_EP_INT_FLAG(ep_hw_index) & USBD_GET_EP_INT_EN(ep_hw_index);
USBD_CLR_EP_INT_FLAG(ep_hw_index, epxintsts);
/* Buffer Full */
if (epxintsts & USBD_EPINTSTS_BUFFULLIF_Msk)
{
}
/* Buffer Empty */
if (epxintsts & USBD_EPINTSTS_BUFEMPTYIF_Msk)
{
}
/* Short Packet Transferred */
if (epxintsts & USBD_EPINTSTS_SHORTTXIF_Msk)
{
}
/* Data Packet Transmitted */
if (epxintsts & USBD_EPINTSTS_TXPKIF_Msk)
{
s_ep_compl &= ~(1 << (NU_EPH2EPL(ep_hw_index)));
if ((instance->*(epCallback[ep_hw_index]))())
{
}
}
/* Data Packet Received */
if (epxintsts & USBD_EPINTSTS_RXPKIF_Msk)
{
if ((instance->*(epCallback[ep_hw_index]))())
{
}
}
/* OUT token packet */
if (epxintsts & USBD_EPINTSTS_OUTTKIF_Msk)
{
}
/* IN token packet */
if (epxintsts & USBD_EPINTSTS_INTKIF_Msk)
{
}
/* PING packet */
if (epxintsts & USBD_EPINTSTS_PINGIF_Msk)
{
}
/* NAK handshake packet sent to Host */
if (epxintsts & USBD_EPINTSTS_NAKIF_Msk)
{
}
/* STALL handshake packet sent to Host */
if (epxintsts & USBD_EPINTSTS_STALLIF_Msk)
{
}
/* NYET handshake packet sent to Host */
if (epxintsts & USBD_EPINTSTS_NYETIF_Msk)
{
}
/* ERR packet sent to Host */
if (epxintsts & USBD_EPINTSTS_ERRIF_Msk)
{
}
/* Bulk Out Short Packet Received */
if (epxintsts & USBD_EPINTSTS_SHORTRXIF_Msk)
{
}
}
gintsts_epx = gintsts_epx >> 1;
ep_hw_index++;
}
}
#endif

View File

@ -20,7 +20,7 @@ CAN can1(PD_0, PD_1);
defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_F446RE) || \
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F103RB) || \
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_L476RG) || \
defined(TARGET_NUCLEO_L432KC)
defined(TARGET_NUCLEO_L432KC) || defined(TARGET_DISCO_F303VC)
CAN can1(PA_11, PA_12);
#elif defined(TARGET_DISCO_F469NI) ||defined(TARGET_DISCO_F746NG)
CAN can1(PB_8, PB_9);
@ -68,7 +68,7 @@ int main() {
!defined(TARGET_NUCLEO_F303RE) && !defined(TARGET_NUCLEO_F303K8) && \
!defined(TARGET_NUCLEO_F302R8) && !defined(TARGET_NUCLEO_F103RB) && \
!defined(TARGET_DISCO_L476VG) && !defined(TARGET_NUCLEO_L476RG) && \
!defined(TARGET_NUCLEO_L432KC))
!defined(TARGET_NUCLEO_L432KC)) && !defined(TARGET_DISCO_F303VC)
printf("loop()\n");
if(can2.read(msg)) {
printmsg("Rx message:", &msg);

View File

@ -20,7 +20,7 @@ CAN can1(PD_0, PD_1);
defined(TARGET_NUCLEO_F302R8) || defined(TARGET_NUCLEO_F446RE) || \
defined(TARGET_DISCO_F429ZI) || defined(TARGET_NUCLEO_F103RB) || \
defined(TARGET_NUCLEO_F746ZG) || defined(TARGET_NUCLEO_L476RG) || \
defined(TARGET_NUCLEO_L432KC)
defined(TARGET_NUCLEO_L432KC) || defined(TARGET_DISCO_F303VC)
CAN can1(PA_11, PA_12);
#elif defined(TARGET_DISCO_F469NI) || defined(TARGET_DISCO_F746NG)
CAN can1(PB_8, PB_9);
@ -63,7 +63,7 @@ void send() {
!defined(TARGET_NUCLEO_F303RE) && !defined(TARGET_NUCLEO_F303K8) && \
!defined(TARGET_NUCLEO_F302R8) && !defined(TARGET_NUCLEO_F103RB) && \
!defined(TARGET_DISCO_L476VG) && !defined(TARGET_NUCLEO_L476RG) && \
!defined(TARGET_NUCLEO_L432KC))
!defined(TARGET_NUCLEO_L432KC) && !defined(TARGET_DISCO_F303VC))
void read() {
CANMessage msg;
printf("rx()\n");
@ -83,7 +83,7 @@ int main() {
!defined(TARGET_NUCLEO_F303RE) && !defined(TARGET_NUCLEO_F303K8) && \
!defined(TARGET_NUCLEO_F302R8) && !defined(TARGET_NUCLEO_F103RB) && \
!defined(TARGET_DISCO_L476VG) && !defined(TARGET_NUCLEO_L476RG) && \
!defined(TARGET_NUCLEO_L432KC))
!defined(TARGET_NUCLEO_L432KC) && !defined(TARGET_DISCO_F303VC))
can2.attach(&read);
#endif
while(1) {

View File

@ -24,7 +24,8 @@ CAN can1(PA_11, PA_12);
#elif defined(TARGET_DISCO_F469NI) || defined(TARGET_DISCO_F746NG) || \
defined(TARGET_NUCLEO_F446ZE) || defined(TARGET_NUCLEO_F103RB) || \
defined(TARGET_NUCLEO_F207ZG) || defined(TARGET_NUCLEO_F303ZE) || \
defined(TARGET_DISCO_F769NI) || defined(TARGET_NUCLEO_F767ZI)
defined(TARGET_DISCO_F769NI) || defined(TARGET_NUCLEO_F767ZI) || \
defined(TARGET_DISCO_F303VC)
CAN can1(PB_8, PB_9);
#endif

View File

@ -83,6 +83,10 @@ int main()
SDFileSystem sd(D11, D12, D13, D10, "sd");
#elif defined(TARGET_LPC11U37H_401)
SDFileSystem sd(SDMOSI, SDMISO, SDSCLK, SDSSEL, "sd");
#elif defined(TARGET_NUMAKER_PFM_NUC472)
SDFileSystem sd(PF_0, PD_15, PD_14, PD_13, "sd");
#elif defined(TARGET_NUMAKER_PFM_M453)
SDFileSystem sd(PD_13, PD_14, PD_15, PD_12, "sd");
#else
SDFileSystem sd(p11, p12, p13, p14, "sd");
#endif

View File

@ -14,7 +14,7 @@
#error [NOT_SUPPORTED] I2C Async is not supported
#endif
#define ADDR (0x90)
#define ADDR (0x80)
#define FREQ 100000
#define SIZE 10

View File

@ -55,6 +55,12 @@ SDFileSystem sd(P8_5, P8_6, P8_3, P8_4, "sd");
#elif defined(TARGET_LPC11U37H_401)
SDFileSystem sd(SDMOSI, SDMISO, SDSCLK, SDSSEL, "sd");
#elif defined(TARGET_NUMAKER_PFM_NUC472)
SDFileSystem sd(PF_0, PD_15, PD_14, PD_13, "sd");
#elif defined(TARGET_NUMAKER_PFM_M453)
SDFileSystem sd(PD_13, PD_14, PD_15, PD_12, "sd");
#else
SDFileSystem sd(p11, p12, p13, p14, "sd");
#endif

View File

@ -53,6 +53,12 @@ SDFileSystem sd(D11, D12, D13, D10, "sd");
#elif defined(TARGET_LPC11U37H_401)
SDFileSystem sd(SDMOSI, SDMISO, SDSCLK, SDSSEL, "sd");
#elif defined(TARGET_NUMAKER_PFM_NUC472)
SDFileSystem sd(PF_0, PD_15, PD_14, PD_13, "sd");
#elif defined(TARGET_NUMAKER_PFM_M453)
SDFileSystem sd(PD_13, PD_14, PD_15, PD_12, "sd");
#else
SDFileSystem sd(p11, p12, p13, p14, "sd");
#endif

View File

@ -53,6 +53,12 @@ SDFileSystem sd(D11, D12, D13, D10, "sd");
#elif defined(TARGET_LPC11U37H_401)
SDFileSystem sd(SDMOSI, SDMISO, SDSCLK, SDSSEL, "sd");
#elif defined(TARGET_NUMAKER_PFM_NUC472)
SDFileSystem sd(PF_0, PD_15, PD_14, PD_13, "sd");
#elif defined(TARGET_NUMAKER_PFM_M453)
SDFileSystem sd(PD_13, PD_14, PD_15, PD_12, "sd");
#else
SDFileSystem sd(p11, p12, p13, p14, "sd");
#endif

View File

@ -53,6 +53,12 @@ SDFileSystem sd(D11, D12, D13, D10, "sd");
#elif defined(TARGET_LPC11U37H_401)
SDFileSystem sd(SDMOSI, SDMISO, SDSCLK, SDSSEL, "sd");
#elif defined(TARGET_NUMAKER_PFM_NUC472)
SDFileSystem sd(PF_0, PD_15, PD_14, PD_13, "sd");
#elif defined(TARGET_NUMAKER_PFM_M453)
SDFileSystem sd(PD_13, PD_14, PD_15, PD_12, "sd");
#else
SDFileSystem sd(p11, p12, p13, p14, "sd");
#endif

View File

@ -33,6 +33,12 @@ void sd_thread(void const *argument)
#elif defined(TARGET_RZ_A1H)
SDFileSystem sd(P8_5, P8_6, P8_3, P8_4, "sd");
#elif defined(TARGET_NUMAKER_PFM_NUC472)
SDFileSystem sd(PF_0, PD_15, PD_14, PD_13, "sd");
#elif defined(TARGET_NUMAKER_PFM_M453)
SDFileSystem sd(PD_13, PD_14, PD_15, PD_12, "sd");
#else
SDFileSystem sd(p11, p12, p13, p14, "sd");
#endif

View File

@ -0,0 +1,51 @@
// Playback example with the USBAUDIO library
#include "mbed.h"
#include "USBAudio.h"
// frequency: 48 kHz
#define FREQ_SPK 16000
#define FREQ_MIC 16000
// 2channels: stereo
#define NB_CHA_SPK 2
#define NB_CHA_MIC 2
// length computed: each ms, we receive 48 * 16bits ->48 * 2 bytes. as there are two channels, the length will be 48 * 2 * 2
#define LENGTH_AUDIO_PACKET_SPK (FREQ_SPK / 500) * NB_CHA_SPK
#define LENGTH_AUDIO_PACKET_MIC (FREQ_MIC / 500) * NB_CHA_MIC
// USBAudio object
USBAudio audio(FREQ_SPK, NB_CHA_SPK, FREQ_MIC, NB_CHA_MIC, 0xab45, 0x0378);
int filled;
int ready = 2;
/* buffer 4 packets to avoid */
int buf[4][LENGTH_AUDIO_PACKET_SPK/sizeof(int)];
void tx_audio(void)
{
/* used some buffer in advance */
ready = (filled+2)&0x3;
audio.writeSync((uint8_t *)buf[ready]);
}
void rx_audio(void)
{
int size=0;
int next = (filled + 1)&0x3;
size = audio.readSync((uint8_t *)buf[next]);
if (size ) filled = next;
if ((size) && (size!=LENGTH_AUDIO_PACKET_MIC)) printf("%d\n",size);
}
int main()
{
filled = 0;
memset(&buf[0][0], 0, sizeof (buf));
audio.attachTx(tx_audio);
audio.attachRx(rx_audio);
/* start the tx with a silent packet */
audio.write((uint8_t *)buf[2]);
while(1);
}

4
mbed.h
View File

@ -16,13 +16,13 @@
#ifndef MBED_H
#define MBED_H
#define MBED_LIBRARY_VERSION 132
#define MBED_LIBRARY_VERSION 133
#if MBED_CONF_RTOS_PRESENT
// RTOS present, this is valid only for mbed OS 5
#define MBED_MAJOR_VERSION 5
#define MBED_MINOR_VERSION 3
#define MBED_PATCH_VERSION 1
#define MBED_PATCH_VERSION 2
#else
// mbed 2

View File

@ -48,14 +48,14 @@ namespace rtos {
* void blink(DigitalOut *led) {
* while (running) {
* *led = !*led;
* Thread::wait(1000);
* wait(1);
* }
* }
*
* // Spawns a thread to run blink for 5 seconds
* int main() {
* thread.start(led1, blink);
* Thread::wait(5000);
* thread.start(callback(blink, &led1));
* wait(5);
* running = false;
* thread.join();
* }

Some files were not shown because too many files have changed in this diff Show More