Skip to content

AN03: Using S3P to communicate between TapNLink and target application

Introduction

This application note describes how to use S3P protocol to communicate between the TapNLink and the target application.

S3P (Serial Secure Software protocol) is a propriatory protocol which extends portability and security between applications, at the cost of minor modifications in the target application.

It can be considered as a derivative of the SPI protocol in half-duplex mode. But it used only two signals (SWD like) : data and clock and can be managed by software at the target side (yours).

Why use S3P?

  • SWD is generally considered as unsecure. It cannot selectively restrict data access. It provides read and write access to ALL resources (RAM, Flash, CPU registers, peripheral registers, etc.).
  • Many microcontrollers use debug protocols (JTAG, SWIM, etc.) that are not supported natively by IoTize.
  • Many microcontrollers debug facility is disabled once they are in production (mostly for confidentiality or security issues), so they do not respond to debug requests. This debug deactivation is usually called ‟Read-Out Protection". (ROP or RDP).
  • SWD is not encrypted: any third party who can read the SWD signals can understand and analyze the transmitted data.

The S3P protocol works around these issues:

  • S3P can be managed by the target's software - after the S3P files have been included in the target firmware and modified for configuration, and the target project has been recompiled and reprogrammed.
  • S3P requires only 2 GPIOs. These IOs are generally available on the standard debug connector (SWD or other). Reusing this connector is the simplest way to use S3P and it provides higher protection than native debug protocols:
  • Customized control of memory access: addresses can be filtered easily
  • Optional secure authentication
  • Optional data encryption

Note : You do not need to use S3P if you have a Cortex-M microcontroller and the confidentiality of your embedded firmware is not critical (if you don't need to protect binary code or IoTized data from attacks that require physical access to the device). SWD will suffice and TapNLink will manage login and user authentication, you just have to configure the TapNLink module with IoTize Studio.

Features summary and current status

This table presents the available modes for S3P:

Feature Description Remark
SWD emulation mode SWD-like target memory access (CSW / TAR / DRW) Not available for Arduino
Indexed indirect mode Address-table-based target memory access. Faster, uses less target CPU time, but uses more target CPU memory, longer and more complex to implement.

How to proceed?

Step 1: Start with the sensor demo board

  • Use SWD on the sensor demo board (see getting started section)

  • Use S3P on the sensor demo board (described in detail hereafter)

Step 2: Use S3P with your application

  • If you have a Cortex-M target board with SWD access enabled, it is preferable to start with SWD mode

  • Use S3P in SWD emulation mode (as an intermediate, optional, solution)

    • Configure the Tap and your target application to use S3P.
    • Add S3P files.
    • Adapt application specific files, recompile your application and reprogram your board.

Step 3: Optimize with Indexed mode (recommended mode)

  • The security and performance of the S3P protocol can be improved by changing from SWD emulation mode to indexed mode.
  • IoTize Studio can generate the source files to integrate in your application.
  • The procedure is the same as for S3P emulation mode (Step 2)

Getting started with the sensor demo board

Use SWD on the demo board

Refer to the getting started section.

Use S3P on the demo board

Change the communication protocol from SWD to S3P:

  1. In IoTize Studio, open the Sensor Demo example project and set IoTized Application Target Protocol to S3P.

Image

  1. Configure your Tap with this new configuration.
  2. On the target board, change the yellow jumpers as shown below, to instruct the firmware to activate S3P:

Image

  1. Unplug and replug the power supply so that the firmware uses S3P instead of SWD.

Now when you connect your smartphone to the IoTize module, the same demo runs using S3P instead of SWD!

Use S3P on your target application

Use SWD with your application

If possible, start by using SWD on your application as explained in the other IoTize docs.

Use S3P with your application

Configure TapNLink and the target application to support S3P:

  1. Check that your target's S3P pins can be configured as GPIOs (see Hardware setup).
  2. Configure the TapNLink module:
  3. Select S3P protocol in IoTize Studio (IoTized Application | Target Protocol).
  4. Select S3P mode (SWD emulation by default).
  5. Write the configuration to the TapNLink (command "Configure").
  6. Add the S3P files in the embedded firmware (see S3P files).
  7. Enable S3P: call S3P_Enable() function from your ‟main()" subroutine.
  8. Disable SWD (if your S3P implementation uses the SWD IOs, and if SWD is not disabled by some other means such as Option Bytes).
  9. Define the interrupt vectorfor the external interrupt corresponding to the S3PCK pin (this depends on your target CPU and firmware library).
  10. If applicable, modify the target board hardware to connect the S3P signals to the TapNLink target connector. It is usually possible to avoid this by reusing original debug signals (SWD, JTAG …) and the S3P connector.

Hardware Setup

Image

You can use S3P with:

  • Standard SWD debug connector (option 1) of ARM® Cortex® devices. See Cortex manuals for details.
  • Any other pair of I/Os (option 2)

S3P uses 2 signals to communicate:

  • Clock signal: S3PCK (that matches SWDCK used by SWD)
  • Data signal: S3PIO (that matches SWDIO used by SWD)

The S3P pins must be configurable as standard GPIOs.

  • S3PCK must be configured as an external interrupt, and must not have a pull-up resistor between it and GND.
  • The other pins are used for the power supply (GND and Vcc), and the Reset signal.

In most cases, the standard SWDCK and SWDIO pins can be used by S3P because the SWD pins are generally multiplexed with standard GPIOs, so either S3P or SWD can be used (not at the same time).

  • This is always the case for the STM32 family from STMicroelectronics, but there are a few exceptions
  • For example, the XMC4000 series from Infineon have dedicated pins for SWD that cannot be configured as GPIOs, in this case, the S3P protocol could still be used but the signals must be redirected to other ports.

Note

S3P is very similar to SPI but we don't recommend to use a hardware SPI port:

  • transactions are short and do not require to be hardware optimized,
  • S3P multiplexes the synchronization signal (trig pulse) with the clock signal. This solution allows to reduce the number of pins used, but it makes more complex the management of a hardware peripheral.

Configuration file generation

The S3P source files are configured by a file called S3P_conf.h. This file is automatically generated by IoTize-Studio, in the project directory when the project (.iotz) file is saved. You must make sure your application code and project know where to find it. (#include …) It contains:

  • A couple of macro-definitions to specify the selected mode.
  • A list of variables to initialize the array of pointers when indexed mode is in use.

S3P files

The following S3P files must be added, compiled and linked into your project:

Filename Contents Actions
S3P_handler.c General routines (interrupt handler, …) for the S3P protocol. We recommend NOT to change this file that can be configured by S3P_conf.h.
S3P_handler.h General declarations for the S3P protocol. We recommend NOT to change this file that can be configured by S3P_conf.h.
S3P_hw_specific.c IO functions specific to the device (microcontroller). Must be modified with characteristics of the target MCU / board. It's important to optimize low level functions such as I/O_Read and I/O_Write.
S3P_hw_specific.h IO functions specific to the device (microcontroller). Must be modified with characteristics of the target MCU/ board.
S3P_check.c Manages security features. May be modified to customize data access control and restrictions.
S3P_check.h Declaration of security features.
S3P_conf.h General settings. Generated automatically by IoTize Studio.
S3P_def.h Common declarations.
S3P_IndexedMode.c Indexed mode implementation We recommend NOT to change this file that is configured by S3P_conf.h.
S3P_IndexedMode.h Indexed mode declarations We recommend NOT to change this file that is configured by S3P_conf.h.

S3P modes

There are multiple ways to implement S3P:

S3P mode Description
SWD emulation The physical addresses of the variables are used. Without filtering, the whole 4GB area could be accessed (for 32 bits µC). However, this mode can be secured by customizing the check.c file to filter accessed addresses.
Combuf (Future feature) Provides UART-like communication using two protocol registers (S3P_CSW and S3P_COMBUF).
Indirect-indexed access TapNLink addresses a list of registers that are referenced by pointers to the application variables. The list of variables is strictly defined and a simple 8-bit index gives fast access to them.

SWD emulation mode

It is the most powerful since it is similar to the SWD protocol. But it is also almost as unsecure as SWD...

This mode enables an SWD-like direct memory access mechanism that uses 3 control registers: S3P_TAR, S3P_DRW, and S3P_CSW.

It can be secured by:

  • Implementing some control functions in S3P_check.c : each request to access memory can be analyzed (and potentially rejected) by the developer.
  • Enabling data encryption and/or authentication f the user.

A memory access is much slower than a register access. One memory access requires typically 3 word-register accesses.

The SWD protocol uses 3 predefined registers to access your applications variables configured in the TapNLink module:

  • TAR: address of the data to access,
  • CSW: configuration / status register to set the access size (8, 16 or 32 bits), and other controls (auto-increment…),
  • DRW: data register where the variable value is read or written.

Indexed mode

Up to 1024 user registers are accessible by both S3P (using an extended request) and the target application:

  • Indirect-Indexed access mode mechanism Image

  • There is an address list of variables to be accessed.

  • Your Tap refers to variables by their index in the table
  • The target S3P program reads the corresponding address from the table and accesses the application variable
  • Indexed mode advantages:
    • Secure, more efficient, and less intrusive:
    • The list of variables to be accessed is predefined in the target application.
    • Only one S3P frame is necessary to read or write one application variable.
    • Less information is disclosed in the S3P frames (variables addresses…). Compared with SWD emulation mode it also reduces the number of S3P frames for each target memory access, therefore improving performance and reducing S3P CPU load.

Appendix A: S3P Protocol implementation details

Introduction

The S3P protocol is based on SPI inter-processor protocol, where the target processor is the master, and TapNLink is the slave. However, TapNLink is a client for communications and it always initiates the requests.

When TapNLink wants to read or write a target variable, it generates an external interrupt that triggers a sequence of short elementary requests.

Typically, each request is completed within 10-100µs (depending on target processor speed).

The interrupt duration has been optimized to make the communication as transparent as possible for the target application.

The generic handler's source files are provided with examples of implementation for some standard Cortex-based microcontrollers.

8 x S3P protocol registers and 1024 x S3P user registers are independently addressable.

Low level protocol

S3P is very similar to SPI:

  • it works with a single data signal (half duplex mode with a common signal for MISO and MOSI).
  • the Master (clock generator) is the target (your firmware). TapNLink module behaves as a slave.
  • the clock is configured for "SPI-mode 1": CPOL=0 and CPHA=1.
  • the LSB is sent first.
  • there is no CS signal and the synchronisation is done by a preliminary pulse on the clock signal (interrupt input for the target)
  • every low level transaction starts with a trig pulse,
  • for the first part of the request (command), TapLink is always transmitter and the target receiver. Depending on the type of the command (PUT/GET), the second part of the request could see either one or the other as transmitter.

S3P requests

Requests can be either basic or extended.

  • Basic requests

S3P provides 2 methods to access registers: Read and Write.

Each request is preceded by a pulse sent by the TapNLink module that generates an interrupt in the target application (on the falling edge). When the interrupt is triggered, the S3P handler receives, checks and serves the request.

The following diagram shows the 6 stages of a write request (pulse / command / data / check sum / pulse / acknowledge):

Image

The following diagram shows the 6 stages of a read request (pulse / command / pulse / acknowledge / data / check sum):

Image

Both S3PCK and S3PIO are bidirectional:

  • The pulse at S3PCK is generated by TapNLink, but the clock is made by the target (TapNLink is configured as an SPI slave for data transmission in both directions).
  • The command byte (CMD) is always sent by TapNLink on S3PIO, but the data is sent or received by the target.

  • Extended requests (Indexed mode)

Image

In Indexed mode, S3P needs to specify more register addresses, so the CMD EXT bit is set to indicate an additional command will be sent ( CMD2 in these figures).

Image

Requests detailed contents

  • Command (CMD)
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
DIR SZ2 SZ1 EXT PAR ADDR3 ADDR2 ADDR1
  • DIR defines the action: 1: the register is written with the data sent by TapNLink. 0: the object is read and the data transmitted to TapNLink.
  • SZ1-2: Data size: 0: 1 byte 1: 2 bytes 2: 4 bytes
  • EXT: If set, indicates a second command is being sent: Used in indexed mode.
  • PAR: Parity bit.
  • ADDR1-ADDR3: S3P register addresses.

  • Command EXTension (CMD2)

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
PAR ADDR10 ADDR9 ADDR8 ADDR7 ADDR6 ADDR5 ADDR4
  • PAR: Parity bit.
  • ADDR4-ADDR10: S3P addresses.

  • Write Checksum (CS1)

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
CS1.7 CS1.6 CS1.5 CS1.4 CS1.3 CS1.2 CS1.1 CS1.0

This checksum byte is used during a write request by the target to verify the command and data sent by the TapNLink.

CS1 = 0 – ( CMD [+ CMD2] + WDATA.B0 [+ WDATA.B1] [+ WDATA.B2] [+ WDATA.B3] )

The check is performed by testing that:

CS1 + CMD [+ CMD2] + WDATA.B0 [+ WDATA.B1] [+ WDATA.B2] [+ WDATA.B3] == 0

  • Acknowledge
Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
PAR ERR7 ERR6 ERR5 ERR4 ERR3 ERR2 ERR1

An ACK with no errors will be 0x80.

  • PAR: Parity bit.
  • ERR1-ERR7: Error codes 0: OK 1: Error

  • Read Checksum (CS2)

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
CS1.7 CS1.6 CS1.5 CS1.4 CS1.3 CS1.2 CS1.1 CS1.0

This checksum byte is used during a read request by the TapNLink to verify the ACK and data sent by the target, and also the command received by the target.

CS2 = 0 – ( CMD [+ CMD2] + ACK + RDATA.B0 [+ RDATA.B1] [+ RDATA.B2] [+ RDATA.B3] )

The check is performed by testing that:

CS2 + CMD [+ CMD2] + ACK + RDATA.B0 [+ RDATA.B1] [+ RDATA.B2] [+ RDATA.B3] == 0

Timing consideration

The S3P protocol is managed by software on the target processor (Master) and by hardware (SPI + DMA) on the TapNLink (Slave), which makes it tolerant of timing issues. If your CPU is very fast, you should check whether the clock speed is not greater than 10MHz and the duty cycle is not too unbalanced. If necessary, you can slow down the frequency by uncommenting the macro definition for TYPICAL_DELAYSOFT into the source file 'S3P_specific.c'. Tuning the speed is possible by adapting the TYPICAL_DELAYSOFT value.

S3P Interrupt

The target application is served requests by an external interrupt (initiated by the falling edge of the pulse). The interrupt request priority is defined by the developer, and it is recommended to set the S3P interrupt as a high priority for the following reasons:

  • The interrupt duration depends on the MCU characteristics (core frequency…) but is quite short: typically 20-100 µs for a 32-bit request.
  • A very long delay before a response may be incompatible with the protocol used between TapNLink and the smartphone.

  • S3P Interrupt time. The S3P mechanism requires the target CPU to execute some code to communicate with the TapNLink, so you must make sure that the time required is small enough so that the (original) application continues to operate properly. As an example, we measured the time the CPU spends in interrupts on the DemoClock example (which is provided with the Primer Kit). It uses an STM32F1 (Cortex-M3) CPU clocked at 64MHz. The pictures below show the measurements:

  • S3PCK: C1, Yellow

  • S3PIO: C2, pink
  • S3P interrupt in/out: C3, blue

Image

Above: A simple 32-bit read access takes about 50µs, split in two interrupts, one of 10 µs and the other of 40µs.

Image

Above: A simple 16-bit write access takes about 40µs (=30+10).

The time used for S3P interrupt handling depends on many factors, including:

  • The time spent in interrupt handling is basically proportional to the speed of the target CPU.
  • Read and write accesses (of the same size and type) take roughly the same time: only the distribution of time between the two interrupts of the frame changes between read and write access.
  • The size of the accessed data (8/16/32 bits): in the example above, a 32-bit access takes 50µs, a 16-bit access takes 40µs, and a 8-bit access time should be around 35µs.
  • Extended accesses take longer than simple accesses: double the command time, in the example above that would mean about 60 µs for an extended 32-bit access.
  • The mode (SWD emulation, indexed, etc.): reading some data in SWD emulation takes between 1 to 3 simple S3P frames (which means 2 to 6 interrupts) while indexed accesses are 1 extended frame (2 interrupts) per access.
  • Of course the frequency of accesses also impacts the overall time spent in S3P interrupts.

Because of the number of factors, we recommend you perform similar measurements on your own system.

Note that the measurements above have been performed with a modified S3P code that uses a third IO (in blue) to indicate when the CPU is in the S3P interrupt. This shows the target CPU is in interrupt from the falling edge of S3PCK to the last rising edge of S3PIO. You can perform the same measurements without this code modification and third IO (but with a slightly lower precision): just measure the time between these two edges.

Appendix B: S3P mode implementation details

8 + 1024 registers are independently addressable by S3P protocol:

  • The 8 word registers accessible by simple requests are "protocol registers" reserved for the communication protocol. The SWD emulation mode, Combuf and other features are performed using these registers. The user should not manipulate them directly. He does not have to.
  • The other 1024 registers are accessible by extended requests.
  • The last one is reserved for S3P communication control, and the others are available to the application.
  • These "user registers" can be considered as shared data between the target application and you Tap (like a dual-port RAM).
  • The S3P software can associate any application-accessible data (variables, peripheral registers, virtual constructs, etc.) to these indexed objects.

Configuration of S3P features

In the S3P target source code, the following values must be defined in S3P_conf.h (generated by IoTize Studio, at least initially) to enable the corresponding features:

  • S3P_ENABLE_MEMORY_ACCESS: to enable SWD emulation
  • S3P_ENABLE_COMBUF: to enable communication buffer
  • S3P_ENABLE_PTR_TO_BYTE: to enable indexed pointed access to byte variables
  • S3P_ENABLE_PTR_TO_WORD: to enable indexed pointed access to word variables

These definitions are not exclusive and can be mixed.

Protocol registers (8 words: x00 to x07)

These virtual registers provide debug-like features, for example mimicking SWD memory access. Each of these features can be disabled.

The following table describes the registers:

Register Address Description
S3P_CSW 0x0 Control Status Word.for S3P control, SWD emulation (mimics SWD-CSW – see SWD spec), Combuf control and other features
S3P_TAR 0x1 Transfer Address Register.for SWD emulation, current address when reading/writing MCU memory (when allowed and enabled). Optionally auto-incremented after each access.
S3P_DRW 0x2 Data Read/Write.For SWD emulation, c_urrent data when reading/writing MCU memory (when allowed and enabled in the S3P code)._
S3P_COMBUF 0x3 Communication Buffer.For Combuf mode, data buffer for communication between firmware and app.Generic communication buffer (same address for both reception/transmission). The management of this bidirectional buffer is done by semaphores contained in S3P_CSW_.__Note that there are two different buffers for transmit/receive._
0x4-0x6 3 words reserved for future use
S3P_ID 0x7 Unique ID dedicated to the application.

S3P_CSW

  • Bit0-bit1: Access size. For SWD emulation, this specifies the element size of the accesses performed by the target CPU to the target memory for executing the memory accesses. It need not match the size specified in the S3P frame (for example, a 32-bit S3P read with a 8-bit CSW size will result in 4 byte accesses, which may be needed when accessing some peripheral registers).
    • 00: 8-bit
    • 01: 16-bit
    • 10: 32-bit
    • 11: reserved
  • Bit2-bit3: Auto-increment. For SWD emulation, this specifies if the S3P_TAR register must be increased after a S3P_DRW register access. The value of the increment depends on both Access Size and the Size parameter in the S3P frame.
    • 00: auto increment off
    • 01: auto increment on
    • Other values are reserved
  • Bit4: Combuf TR: Transmit Ready
  • Bit5: Combuf RF: Receive Full
    • Bits 4 and 5 are not writeable by the TapNLink/S3P. They are modified by the S3P part of the target application when S3P_COMBUF is accessed. (either by TapNLink/S3P or by target application)
  • Bit 29: 1: Indexed mode in use (and extended frames support). read-only.
  • Bit 30: 1: Combuf feature in use. read-only.
  • Bit 31: 1: SWD emulation in use. read-only.
  • All other bits are read as 0 and are reserved for future use._

SWD emulation mode implementation

SWD emulation mode was inspired by the original SWD protocol. It uses similar CSW/TAR/DRW registers in pretty much the same way:

  • CSW for control and status (note that CSW is also used by the S3P protocol itself, the Combuf mode, etc.).
  • TAR for address of accessed data.
  • DRW for data.

Combuf mode implementation

This mode uses the two protocol registers S3P_CSW and S3P_COMBUF to provide UART-like communication between target application and TapNLink.

TapNLink accesses S3P_CSW to know if there is data to read from the target (TR) and if the target is ready to receive data (RF).

TapNLink accesses S3P_COMBUF to send and get data.

This mode is currently in development.

Indexed mode implementation

The registers are referenced by a pointer to a memory address, usually an application variable.

IoTize Studio generates all necessary information to allow these redirections in the form of the S3P_conf.h file that contains tables of pointers.

In this mode, IoTize Studio automatically generates arrays of pointers to perform these redirections:

u8\* (S3P\_AddressArrayBYTE[S3P\_MAXBREG]) ;

u32\* (S3P\_AddressArrayWORD[S3P\_MAXWREG]) ;

For example, if the user has two 32-bit variables to access, he can declare:

extern u32 var1\_temperature, var2\_pressure ;

u32\* (S3P\_AddressArrayWORD[S3P\_MAXWREG])=
                            {&var1\_temperature, &var2\_pressure,NULL };

In the virtual user registers space, the tables appear in this order:

  • 32-bit word registers,
  • 16-bit half-word registers,
  • 8-bit byte registers.

The S3P program implicitly associates index ranges and types of variable.

The generated table only contains the necessary configured variables pointers.

In this example, 26 variables are declared, so 26 * 4 = 104 bytes are used:

Index Address Type (*) Name (*)
0x20 0x2000 1000 Word Configuration
0x21 0x2000 0000 Half Word Temperature 1
0x22 0x2000 0032 Half Word Temperature 2
0x31 0x2000 007E Half Word Pressure
0x32 0x2000 0100 Byte Alarm 1
0x2000 0101 Byte Alarm 2
0x3A 0x2000 0109 Byte Alarm 9

(*) these columns are not generated nor saved in the table.

It is possible for the application developer to modify the S3P code, including the S3P_conf.h file, for optimization (speed or size), safety (write lock/unlock), security (custom encryption) or other purpose (example: access to an external memory area; which is not mapped as a variable).

If you do this, keep in mind that IoTize Studio re-generates the S3P_conf.h file every time you save the project. So you should use a copy of S3P_conf.h file with a different name or location.