6. Appendix

6.1. Booting from Serial Interfaces

The DA14585/586/531 can boot from external serial devices when the OTP memory is not programmed. This is to enable the development of application code. At power-up the system enters Development Mode, where the boot code decides which interface to boot from. This section describes the boot sequence for all supported serial interfaces and provides the developer with the necessary information to realize the protocol required to establish communication between an external device and the DA14585/586/531.

Note

For more information about booting the DA14585/586/531, see the respective datasheets.

6.1.1. Introduction

The DA14585/586/531 operates in two modes: Normal mode and Development mode. The decision which mode the chip enters after power-up, is taken by the boot code that resides in the ROM. A complete flow chart of the boot code is illustrated in:

The boot ROM code reads the Application Programmed flags from the OTP header to identify whether the chip is in Development mode or Normal mode.

Note

  • DA14585/586: The OTP memory contains all zeros if not programmed.

  • DA14531: The OTP memory contains all ones if not programmed.

If the predefined value is identified, then this ensures that the OTP memory is functional and that the application code is programmed. However, if the predefined value is not identified, either the OTP memory is not programmed (blank) or is not operational (random data).

When in Development mode, the boot ROM code initializes all serial peripheral devices from which the DA14585/586/531 might download code. The options are:

  • UART

  • SPI (both master and slave)

  • I2C (only master)

The boot ROM code searches for a valid response on various combinations of I/Os one after the other. There is also the option that the user can define desired I/Os with the use of a specific OTP field for the SPI interface.

The boot pins and serial peripherals search sequence are presented in the following section.

6.1.2. Boot Pins and Serial Peripherals Search Sequence

The DA14585/586/531 boot pins and serial peripherals search sequence are presented in Table 20, Table 21 and Table 22

Table 20 DA14585/586 Development Mode Peripheral Pin Mapping

Interface

Signal

Step A

Step B

Step C

Step D

SPI Master

SCK

P0_0

P0_0

CS

P0_3

P0_1

MISO

P0_6

P0_2

MOSI

P0_5

P0_3

UART

TX

P0_0

P0_2

P0_4

P0_6

RX

P0_1

P0_3

P0_5

P0_7

Baud Rate

57600 / 8-N-1

115200 / 8-N-1

57600 / 8-N-1

9600 / 8-N-1

SPI Slave

SCK

P0_0

CS

P0_3

MOSI

P0_6

MISO

P0_5

I2C

SCL

P0_0

P0_2

P0_4

P0_6

SDA

P0_1

P0_3

P0_5

P0_7


Table 21 DA14585/586 Development Mode Peripheral Search Sequence

Sequence

Action

0

SPI Master Step A

1

SPI Master Step B

2

UART Step A

3

UART Step B

4

UART Step C

5

UART Step D

6

SPI Slave Step A

7

I2C Step A

8

I2C Step B

9

I2C Step C

10

I2C Step D


Table 22 DA14531 Boot Sequence Steps

Step 1: Boot from external SPI master

Step 2: Boot from 1-wire UART (first option)

Step 3: Boot from 1-wire UART (second option)

Step 4: Boot from 2-wire UART

Step 5: Boot from external SPI slave

Step 6: Boot from I2C

P0_0/RST

MISO

Tx

MOSI

P0_1

MOSI

Rx

SCS

P0_2

P0_3

SCS

RxTx

MISO

SDA

P0_4

SCK

SCK

SCL

P0_5

RxTx (default)

P0_6

P0_7

P0_8

P0_9

P0_10

P0_11


At each step, the boot ROM code sends a certain character to the peripheral controller and waits for an answer. If no answer is received within a certain amount of time, a timeout instructs the code to continue to the next step. If a response is detected, a specific protocol is executed and communication between the DA14585/586/531 and the external serial device is established. The code is downloaded from the external serial device to DA14585/586/531 RAM.

6.1.3. Boot Sequence

The boot sequence of DA14585 is shown in Figure 61.

../_images/booting-image1.png

Figure 61 DA14585 Boot Sequence

The boot sequence of DA14586 is shown in Figure 62.

../_images/booting-image2.png

Figure 62 DA14586 Boot Sequence

The boot sequence of DA14531 is shown in Figure 63.

../_images/booting-image3.png

Figure 63 DA14531 Boot Sequence

6.1.4. DA14585/586/531 Boot Protocols

6.1.4.1. Boot from SPI Bus - DA14585/586/531 Act as SPI Slave

The boot ROM code initially configures the DA14585/586/531 SPI controller with the following parameters:

  • 8 bit mode

  • Slave role

  • Mode 0: SPI clock is initially expected to be low and SPI phase is zero.

The protocol required to establish a successful communication and to download the SW into the RAM is given in Table 23.

Note

The master SPI device generates the SPI clock for the DA14585/586. In case of a continuous SPI clock, the frequency of this clock must not be higher than 500 kHz. For an SPI clock frequency higher than 500 kHz, the SPI clock should be paused after each byte.

Table 23 Boot Protocol - DA14585/586/531 as SPI Slave

Byte nr.

DA14585/586/531 MOSI

DA14585/586/531 MISO

0

Preamble: 0x70

1

Preamble: 0x50

2

Empty: 0x00

3

Length LS byte

Preamble ACK: 0x02

Preamble NACK:0x20

4

Length MS byte

5

CRC byte

6

Mode byte

Length ACK:0x02

Length NACK:0x20

7

Empty: 0x00

8

Data bytes

Code/Mode ACK:0x02

Code/Mode NACK:0x20

The external SPI master device starts by sending the Preamble bytes (0x70 and 0x50) followed by a zero byte. The DA14585/586/531 confirms the reception of the Preamble with 0x02 (Acknowledged) or 0x20 (Not Acknowledged) in case something went wrong. Bytes 3 and 4 define the length of the payload to follow. The least significant byte is sent first. The length is a number that represents the amount of data in 32-bit words.

Next, the SPI master must send the calculated CRC of the payload. The CRC is calculated by XORing every successive byte with the previous value. Initial CRC value is 0xFF.

Byte 6 defines the mode of operation directed by the SPI master (8, 16 or 32-bit modes) while the DA14585/586/531 SPI slave answers with ACK/NACK regarding the reception of the length bytes. The mode is encoded as follows:

  • 0x00 = 8-bit mode

  • 0x01 = 16-bit mode

  • 0x02 = 32-bit mode

  • 0x03 = Reserved

Byte 8 is the last control byte, where DA14585/586/531 replies with ACK/NACK with regard to the reception of the CRC and the mode, while the external SPI master starts to send the first byte of the payload (least significant byte of the first word).

The data section is presented in Table 24, and takes into consideration the instructed mode. The stream of data is followed by 2 extra empty slots to provide the required time to the DA14585/586/531 SPI controller to compute the CRC and answer with ACK/NACK.

Upon completion of the SPI master process, all related pads are set to input and pulled down.

Table 24 SPI Master Data Communication

Slot nr.

MOSI (8-bit mode)

MOSI (16-bit mode)

MOSI (32-bit mode)

MISO

0

byte 0

byte 1, byte 0

byte 3, byte 2, byte 1, byte 0

1

byte 1

byte 3, byte 2

byte 7, byte 6, byte 5, byte 4

4*Len-1 or

2*Len-1 or

Len-1

byte (4*Len–1)

16-bit word (2*Len-1)

32-bit word (Len-1)

all 0x00

all 0x00

all 0x00

all 0xAA

all 0x00

all 0x00

all 0x00

ACK: 0x02

NACK: 0x20

6.1.4.2. Booting from UART

The boot ROM code initially configures the DA14585/586/531 UART controller with the following parameters:

  • Bits: 8

  • No parity

  • 1 stop bit

  • Baud rate: fixed at 115.2 Kbps for DA14531, variable for DA14585/586 (see Table 20).

The protocol required to establish successful communication and to download the SW image into the RAM is shown in the next tables depending on the chip:

  • DA14585/586

    Table 25 Boot Protocol

    Byte nr.

    DA14585/586 TX

    DA14585/586 RX

    0

    STX = 0x02

    1

    SOH = 0x01

    2

    LEN_LSB byte (Basic)

    3

    LEN_MSB byte (Basic)

    4

    LEN_LSB byte (Extended)

    5

    LEN_MSB byte (Extended)

    6

    ACK = 0x06 or NACK = 0x15

    7 to N

    SW code bytes

    N+1

    CRC

    N+2

    ACK = 0x06

    1. The protocol starts with the DA14585/586 UART TX pin that transmits 0x02 (Start TX - STX).

    2. The external device is expected to answer with a 0x01 (Start of Header - SOH).

      1. If the Basic LEN_LSB and LEN_MSB bytes are both zero, then the SW image is equal to or over 64 KByte. The following two Extended LEN_LSB and LEN_MSB bytes define the additional image length over the 64 KByte boundary. In that case the length of the downloaded SW image is calculated by the following formula:

        • length = 64 KByte + additional length defined by Extended LEN_MSB and LEN_LSB bytes.

        The DA14585/586 answers with 0x06 (ACK) if the 5 bytes have been received and SOH has been identified, or answers with 0x15 (NACK) if anything went wrong.

      2. If at least one of the Basic LEN_LSB or LEN_MSB byte is NOT zero, then the SW image is lower than 64 KByte. These bytes define the length of the downloaded SW image.

        The DA14585/586 answers with 0x06 (ACK) if the 3 bytes have been received and SOH has been identified, or answers with 0x15 (NACK) if anything went wrong.

  • DA14531

    Table 26 Boot Protocol

    Byte nr.

    DA14531 TX

    DA14531 RX

    0

    STX = 0x02

    1

    SOH = 0x01

    2

    LEN_LSB byte

    3

    LEN_MSB byte

    4

    ACK = 0x06 or NACK = 0x15

    5 to N

    SW code bytes

    N+1

    CRC

    N+2

    ACK = 0x06

    The protocol starts with the DA14531 UART TX pin that transmits 0x02 (Start TX - STX). The external device is expected to answer with a 0x01 (Start of Header - SOH) byte followed by 2 more bytes (LEN_LSB, LEN_MSB), which define the length of the code to be downloaded (first byte is the least significant, second the most significant). The DA14531 answers with 0x06 (ACK) if the 3 bytes have been received and SOH has been identified, or answers with 0x15 (NACK) if anything went wrong.

At this point the connection has been successfully established and the SW code will start to be downloaded. The next N bytes are received and put into the RAM, and starts at address 0x07FC0000 as shown in Table 27.

Table 27 RAM Word Alignment

Address

Byte 3 (MSB)

Byte 2

Byte 1

Byte 0 (LSB)

0x07FC0000

Code byte 3

Code byte 2

Code byte 1

Code byte 0

0x07FC0004

Code byte 5

Code byte 4

Upon completion of the required code bytes, the boot code calculates the CRC and send it over the URX. The boot sequence ends when the value 0x06 (ACK) is read at the URX line. CRC is calculated by XORing every successive byte with the previous value. The initial CRC value is 0x00.

At the final step of the boot code, the SYS_CTRL_REG register is programmed to:

  • Remap to address zero for execution to RAM (SYS_CTRL_REG[REMAP_ADR0] = 0x2)

  • Apply a SW reset, so the system starts to execute code at the remapped address (SYS_CTRL_REG[SW_RESET] = 0x1)

6.1.4.3. Booting from SPI Bus - DA14585/586/531 acting as SPI Master

The boot code configures the SPI with the following parameters:

  • 8 bit mode

  • Master role

  • Mode 3: SPI clock is initially high and SPI phase is shifted by 90 degrees.

  • The SPI clock frequency is set by default at 2 MHz.

The protocol required to establish a successful communication and to download the SW image into the RAM is shown in the next tables, and depend on the chip:

  • DA14585/586 as SPI master

    Table 28 Boot Protocol

    Byte nr.

    DA14585/586 MOSI

    DA14585/586 MISO

    0

    Read command

    1

    Address byte 0 = 0x00

    2

    Address byte 1 = 0x00

    3 to N

    Dummy bytes = 0x00

    N+1

    ‘p’ = 0x70

    N+2

    ‘P’ = 0x50

    N+3 to N+5

    Dummy bytes

    N+6

    Length extension byte

    N+7

    LEN_MSB byte

    N+8

    LEN_LSB byte

    N+9 …

    Code bytes

    1. If Length Extension byte is equal to one, then the SW downloaded image size will be equal to or over 64 KByte. The image length is calculated based on the following formula:

      • length = 64 KByte + additional length defined by LEN_MSB and LEN_LSB bytes.

    2. If Length Extension byte is NOT equal to one, then the SW downloaded image size will be lower than 64 KByte. The image length is defined by the LEN_MSB and LEN_LSB bytes.

  • DA14531 as SPI master

    Table 29 Boot Protocol

    Byte nr.

    DA14585/586/531 MOSI

    DA14585/586/531 MISO

    0

    Read command

    1

    Address byte 0 = 0x00

    2

    Address byte 1 = 0x00

    3 to N

    Dummy bytes = 0x00

    N+1

    ‘p’ = 0x70

    N+2

    ‘P’ = 0x50

    N+3 to N+6

    Dummy bytes

    N+7

    LEN_MSB byte

    N+8

    LEN_LSB byte

    N+9 …

    Code bytes

The image length is defined by the LEN_MSB and LEN_LSB bytes.

The sequence as described in Table 28 or Table 29 is repeated for 4 different cases regarding the Read command and the Dummy byte parameters as indicated in Table 30.

Table 30 SPI Read and Dummy Byte Cases

Case nr.

Read command opcode

Number of dummy bytes

0

0x03

0

1

0x03

1

2

0x0B

2

3

0xE8

5

Note

The length of the SW image is received after the 4th Read command is issued (opcode = 0xE8).

As soon as the length has been received (2 bytes - LEN_MSB and LEN_LSB), the actual code download into RAM starts. The start address is the base address of the RAM. The byte alignment is according to Table 27.

During the final step of the boot code a SW reset is given and the system starts to execute the downloaded code.

6.1.4.4. Booting from I2C Bus - DA14585/586/531 Acting as I2C Master

The boot code initializes the I2C controller in master mode with the following parameters:

  • I2C slave address = 0x50 (7-bit address)

  • I2C speed to standard mode (100 kbit/s)

The boot code initially scans to find an I2C slave device at addresses 0x50 up to 0x57. After a successful slave address identification, a specific protocol is executed to download the SW into the RAM as shown in the next tables. There is a specfic table per chip. If unsuccessful, a timeout is programmed to expire after 20 ms to get the chip out of the I2C booting mode and into the next one.

  • DA14585/586 as I2C master

    Table 31 Boot Protocol

    Byte nr.

    DA14585/586 SDA

    Action ( DA14585/586 I2C master)

    0

    0x70

    Read command

    1

    0x50

    Read command

    2

    LEN_MSB byte (Basic)

    3

    LEN_LSB byte (Basic)

    4

    CRC over code only (image < 64KByte)

    Read command

    5

    LEN_MSB byte (Extended)

    6

    LEN_LSB byte (Extended)

    7

    CRC over code only (image >= 64KByte)

    Read command

    8 to 31

    Dummy

    Read command

    32 to Length+32

    Code data

    Read command

    1. If the Basic LEN_LSB and LEN_MSB bytes are both zero, then the SW image is equal to or over 64 KByte. The following two Extended LEN_LSB and LEN_MSB bytes define the additional image length over the 64 KByte boundary. In that case the length of the downloaded SW image is calculated by the following formula:

      • length = 64KByte + additional length defined by Extended LEN_MSB and LEN_LSB bytes.

      Byte-4 shall be 1. Byte-7 inlcudes the CRC byte (calculated over code only).

    2. If at least one of the Basic LEN_LSB or LEN_MSB byte is NOT zero, then the SW image is lower than 64 KByte. These bytes define the length of the downloaded SW image.

      Byte-4 includes the CRC byte (calculated over code only).

  • DA14531 as I2C master

    Table 32 Boot Protocol - DA14531 as I2C master

    Byte nr.

    DA14531 SDA

    Action ( DA14531 I2C master)

    0

    0x70

    Read command

    1

    0x50

    Read command

    2

    LEN_MSB byte

    Read command

    3

    LEN_LSB byte

    Read command

    4

    CRC over code only

    Read command

    5 to 31

    Dummy

    Read command

    32 to Length+32

    Code data

    Read command

The boot code will calculate the CRC by XORing every successive byte with the previous value. Initial CRC value is 0x00. The CRC is calculated on multiples of 32 bytes. Padding with zeros is required when the payload size is not a multiple of 32 bytes.

At the final step of the boot code a SW reset is given and the system starts to execute the downloaded code.

6.2. Creation of a Secondary Bootloader

This section describes the implementation steps for the development of a secondary bootloader application for the DA14585/586/531.

6.2.1. Introduction

The secondary bootloader allows the DA14585/586/531 to boot from an external SPI Flash memory, an I2C EEPROM or a UART interface. The secondary bootloader can be used to replace the ROM bootloader in case a faster boot sequence is needed. An extension of the secondary bootloader based on dual images is also presented in this section. The dual image bootloader is a building block for a Software Update Over The Air (SUOTA) enabled application. Finally the secondary bootloader code structure, the steps to test it and a methodology to measure the boot time are presented.

It is recommended to read Appendix Section 6.1, which describes the boot procedures supported by the DA14585/586/531 ROM code.

6.2.2. Application Description

6.2.2.1. File Structure

The file structure of the secondary_bootloader project is shown in Figure 64.

../_images/secondary-bootloader-file-structure.png

Figure 64 Secondary Bootloader File Structure

Initialization files and scatter-loading description files are in folder utilities/secondary_bootloader/startup:

  • bootloader_531.sct: The scatter-loading description file for DA14531

  • bootloader_585.sct: The scatter-loading description file for DA14585/586

  • sysram.ini: The Keil debugger initialization script

Application (*.c) files are in folder utilities/secondary_bootloader/src:

  • main.c: Contains the main function, the system initialization function and the main loop of the application

  • bootloader.c: Contains the functions to boot from SPI and EEPROM and the implementation of the dual image bootloader

  • uart_booter.c: Contains the functions to boot from UART

  • crc32.c: Contains the CRC32 checksum calculation algorithm

  • sw_aes.c: Contains the software implementation of the AES encryption. The encryption key and IV are hardcoded in the application code

  • decrypt Contains the software implementation of the AES decryption

Application (*.h) files are in folder utilities/secondary_bootloader/includes:

  • periph_setup.h: Contains the configuration settings for the peripherals (UART, SPI, SPI Flash) used by the secondary bootloader application.

  • bootloader.h: Contains the application configuration settings. For details see section Section 6.2.2.2.

Driver (*.c) files for the peripheral interfaces are in folder sdk/platform/driver/. Detailed information about the drivers can be found in the API documentation.

  • sdk/platform/driver/spi/spi_58x.c: Driver for the SPI interface of DA14585/586 Soc

  • sdk/platform/driver/spi/spi_531.c: Driver for the SPI interface of DA14531 Soc

  • sdk/platform/driver/i2c/i2c.c: Driver for the I2C interface

  • sdk/platform/driver/spi_flash/spi_flash.c: Driver for an external SPI Flash memory

  • sdk/platform/driver/gpio/gpio.c: Driver for the GPIO interface

  • sdk/platform/driver/dma/dma.c: Driver for the DMA interface

6.2.2.2. Compilation and Configuration Settings

The main compilation and configuration settings are included in the header files bootloader.h and user_periph_setup.h.

  • AES_ENCRYPTED_IMAGE_SUPPORTED: This setting must be defined only when the image for the dual image bootloader is encrypted. Must be disabled for the secondary bootloader.

  • UART_SUPPORTED: This setting defines whether the UART is enabled to download firmware. It is supported by both applications: secondary and dual image bootloader.

    Note

    For DA14531 P0_0 is used for UART_TX. At the end of firmware download hardware reset functionality on P0_0 is enabled. External application should drive P0_0 to low to avoid hardware reset of the device.

  • SPI_FLASH_SUPPORTED, EEPROM_FLASH_SUPPORTED: These settings define the external Flash memory type that is supported by the product. Only one must be defined.

  • SUPPORT_AN_B_001: This setting defines that the application will be compiled as secondary bootloader.

The configuration settings for the peripherals are contained in header file periph_setup.h.

// Select EEPROM characteristics
#define I2C_EEPROM_DEV_SIZE   0x20000       // EEPROM size in bytes
#define I2C_EEPROM_PAGE_SIZE   256          // EEPROM page size in bytes
#define I2C_SLAVE_ADDRESS 0x50              // Set slave device address
#define I2C_SPEED_MODE    I2C_SPEED_FAST    // Speed mode: I2C_SPEED_STANDARD (100 kbits/s), I2C_SPEED_FAST (400 kbits/s)
#define I2C_ADDRESS_MODE  I2C_ADDRESSING_7B // Addressing mode: {I2C_ADDRESSING_7B, I2C_ADDRESSING_10B}
#define I2C_ADDRESS_SIZE  I2C_2BYTES_ADDR   // Address width: {I2C_1BYTE_ADDR, I2C_2BYTES_ADDR, I2C_3BYTES_ADDR}

// SPI Flash settings
// SPI Flash Manufacturer and ID
#define W25X10CL_MANF_DEV_ID   (0xEF10)    // W25X10CL Manufacturer and ID
#define W25X20CL_MANF_DEV_ID   (0xEF11)    // W25X10CL Manufacturer and ID
#define MX25R2035F_MANF_DEV_ID (0xC212)    // MX25R2035F Manufacturer and ID

// SPI Flash options
#define W25X10CL_SIZE   131072            // SPI Flash memory size in bytes
#define W25X20CL_SIZE   262144            // SPI Flash memory size in bytes
#define MX25R2035F_SIZE 262144            // SPI Flash memory size in bytes
#define W25X10CL_PAGE   256               // SPI Flash memory page size in bytes
#define W25X20CL_PAGE   256               // SPI Flash memory page size in bytes
#define MX25R2035F_PAGE 256               // SPI Flash memory page size in bytes

#if !defined (__DA14586__)
#define SPI_FLASH_DEV_SIZE          (256 * 1024)
#endif

//SPI initialization parameters
#define SPI_WORD_MODE  SPI_8BIT_MODE
#define SPI_SMN_MODE   SPI_MASTER_MODE
#define SPI_POL_MODE   SPI_CLK_INIT_HIGH
#define SPI_PHA_MODE   SPI_PHASE_1
#define SPI_MINT_EN    SPI_NO_MINT
#if !defined (__DA14531__)
#define SPI_CLK_DIV    SPI_XTAL_DIV_2
#endif

// UART GPIOs assignment
#if defined (__DA14531__)
#define UART_GPIO_PORT       GPIO_PORT_0
#define UART_TX_PIN          GPIO_PIN_0
#define UART_RX_PIN          GPIO_PIN_1
#define UART_FRAC_BAUDRATE   UART_BAUDRATE_115200
#else
#define UART_GPIO_PORT       GPIO_PORT_0
#define UART_TX_PIN          GPIO_PIN_4
#define UART_RX_PIN          GPIO_PIN_5
#define UART_FRAC_BAUDRATE   UART_BAUDRATE_57600
#endif

// SPI GPIO assignment
#if defined (__DA14531__)
    #define SPI_EN_PORT             GPIO_PORT_0
    #define SPI_EN_PIN              GPIO_PIN_1

    #define SPI_CLK_PORT            GPIO_PORT_0
    #define SPI_CLK_PIN             GPIO_PIN_4

    #define SPI_DO_PORT             GPIO_PORT_0
    #define SPI_DO_PIN              GPIO_PIN_0

    #define SPI_DI_PORT             GPIO_PORT_0
    #define SPI_DI_PIN              GPIO_PIN_3

#elif !defined (__DA14586__)
    #define SPI_EN_PORT             GPIO_PORT_0
    #define SPI_EN_PIN              GPIO_PIN_3

    #define SPI_CLK_PORT            GPIO_PORT_0
    #define SPI_CLK_PIN             GPIO_PIN_0

    #define SPI_DO_PORT             GPIO_PORT_0
    #define SPI_DO_PIN              GPIO_PIN_6

    #define SPI_DI_PORT             GPIO_PORT_0
    #define SPI_DI_PIN              GPIO_PIN_5
#endif

// EEPROM GPIO assignment
#define I2C_SCL_PORT                GPIO_PORT_0
#define I2C_SCL_PIN                 GPIO_PIN_2

#define I2C_SDA_PORT                GPIO_PORT_0
#define I2C_SDA_PIN                 GPIO_PIN_3

W25X10CL SPI Flash memory devices are supported. The W25X10CL arrays are organized into 512 programmable pages of 256 bytes each. Up to 256 bytes can be programmed at a time. The W25X10CL has 32 erasable sectors of 4 kB, 4 erasable 32 kB blocks and 2 erasable 64 kB blocks respectively. W25X20CL SPI Flash memory devices are also supported.

Other SPI Flash memory types can be supported if the above configuration settings (SPI_FLASH_DEFAULT_SIZE, SPI_FLASH_DEFAULT_PAGE, etc.) are changed.

GPIO Port 0 is used by default as it is supported by all DA14585/586 (WLCSP34, QFN40 and QFN48) and DA14531 (WLCSP17 and FCGQFN24) packages.

6.2.3. System Initialization

The secondary bootloader application executes in the retention memory, and allows the application code to be loaded into the System RAM. The secondary bootloader does the following actions:

  1. In the main function, the secondary bootloader reloads the Watchdog timer with the max value and configures the Watchdog timer to trigger a HW reset upon expiration.

    SetBits(WATCHDOG_CTRL_REG, NMI_RST, 1);    // WDOG will generate HW reset upon expiration
    SetWord16(WATCHDOG_REG, 0xFF);             // Reset WDOG
    SetWord16(RESET_FREEZE_REG, FRZ_WDOG);     // Start WDOG
    
  2. Initializes the system.

    system_init();
    
  3. Boots from UART if the UART boot option is enabled and the UART RX pin is logic HIGH. Otherwise boots from SPI or I2C.

6.2.4. Getting Started

This section describes how to program the secondary bootloader into the OTP memory, program an application example (integrated processor Proximity Reporter) into the SPI Flash memory and measure the system’s boot time. A comparison with a normal booter (ROM booter in Development Mode) is also provided.

The SmartSnippets Toolbox provides tools for external SPI Flash and OTP memory programming.

6.2.4.1. Building the Application and Secondary Bootloader Images

Build the Proximity Reporter application image for DA14585 target to generate the executable file prox_reporter_585.hex.

Build the secondary bootloader image for the same target according to the following steps:

  1. Open the Secondary Bootloader project:

    • For Keil 5: \utilities\secondary_bootloader\secondary_bootloader.uvprojx.

  2. Configure the project according to section Section 6.2.2.2.

  3. Compile the project to generate the executable file secondary_bootloader_585.hex. This file is in directory <utilities\secondary_bootloader\out_DA14585\Objects.

6.2.4.2. Writing Application HEX File into SPI Flash Memory

The SmartSnippets SPI Flash Programmer tool is used to download an application image file to an external SPI Flash memory connected to DA14585/586/531.

The following instructions demonstrate how to do this with SmartSnippets Toolbox in UART mode when a DA14585 device is connected.

  1. Open SmartSnippets and select the chip version.

    ../_images/secondary-bootloader-Open-SmartSnippets-and-select-the-chip-version.png

    Figure 65 Select Chip Version

  2. Open the Board Setup tool and select the appropriate UART and SPI flash pin configuration as shown in Figure 66.

    ../_images/secondary-bootloader-board-setup.png

    Figure 66 Board Setup

  3. Open the SPI Flash Programmer tool, select the application image file and burn it at SPI flash memory offset 0. When asked whether to make the SPI Flash memory bootable, there are two options to consider depending on the chip version and bootloader configuration:

    • Bootable SPI Flash: SmartSnippets will automatically add an AN-B-001 header at offset 0 of the SPI flash memory. The secondary bootloader will copy only the number of bytes defined in the SPI Flash header.

    • Non-bootable SPI Flash: SmartSnippets will not add an AN-B-001 header at offset 0 of the SPI flash memory. The secondary bootloader will copy 32 KB from SPI Flash memory starting at offset 0x0. Using this setup the maximum boot time can be measured.

    ../_images/secondary-bootloader-write-SPI-flash.png

    Figure 67 SPI Flash Programmer

6.2.4.3. Writing Bootloader HEX File into OTP Memory

The SmartSnippets OTP Programmer tool enables the download of default firmware into the System RAM and to write a user-defined HEX or BIN file into the OTP memory. The tool can be used to write a secondary bootloader in the OTP memory of a DA14585/586/531.

The next steps are required to write the executable secondary_bootloader_585.hex into OTP memory with SmartSnippets in UART mode:

  1. Open SmartSnippets and select the chip version.

    ../_images/writing-hex-open-SS.png

    Figure 68 Open SS Toolbox

  2. Open the Board Setup tool and select the appropriate UART configuration.

    ../_images/writing-hex-UART-setup.png

    Figure 69 Board Setup

  3. Open the OTP Programmer tool and select the image file to download.

    ../_images/writing-hex-in-OTP-programmer.png

    Figure 70 OTP Programmer

  4. Burn the secondary_bootloader_585.hex into the OTP memory at offset 0. Enable Application Flag 1 and Application Flag 2, set DMA Length (Length = size / 4) and burn the OTP header.

    ../_images/writing-hex-in-OTP.png

    Figure 71 OTP Programmer

Note

For more info about SmartSnippets Toolbox, see the “SmartSnippets Toolbox, User manual”.

6.2.4.4. The mkimage Tool

The mkimage tool is a command line Windows application to format non-volatile memory according to the memory map specified by the dual image bootloader.

The tool supports two use cases:

  • Single image: Create a binary application image file (*.img), that contains both the application image header and the application firmware.

  • Multi-part image: Create the entire contents of the external non-volatile memory as a single multi-part binary image file (*.img), that can be written into a non-volatile memory with the SmartSnippets Toolbox.

The source code of the mkimage tool is in folder \utilities\mkimage of the SDK.

6.2.4.4.1. Creating an Application Image File

The command line syntax to create an application image file (*.img) is:

mkimage.exe single <in_file> <version_file> <out_file> [enc [<key> <iv>]]
  • single Instructs the tool to create the <out_file> application image (*.img file).

  • <infile> Specifies the raw application firmware binary file (.BIN file).

  • <version_file> C header file that contains the version, time stamp and housekeeping information for the image header. It must be formatted similar to the SDK header file sdk\platform\include\sdk_version.h. It contains definitions such as:

#define SDK_VERSION "v_6.0.12.1020"
#define SDK_VERSION_DATE "2019-10-09 14:25 "
#define SDK_VERSION_STATUS "REPOSITORY VERSION v_6.0.12.1020"

Encryption of the raw binary image (<in_file>) may be enabled if the enc option is included at the end of the command. The user may provide the encryption key (<key>) and initialisation vector (<iv>) as a string of 32 hexadecimal characters (without any prefix). When no values for <key> and <iv> are specified, the following default values are used:

Key: 06A9214036B8A15B512E03D534120006

Initialisation vector: 3DAFBA429D9EB430B422DA802C9FAC41

The default values of the key and the initialisation vector are hardcoded in the secondary bootloader firmware.

6.2.4.4.2. Creating the Entire Contents of a Non-Volatile Memory

The command line syntax to create a multi-part binary image file (*.img) with the entire contents of a non-volatile memory is:

mkimage.exe multi spi|eeprom [<bloader>] <in_img1> <off1> <in_img2> <off2> <off3> [cfg off4[,bdaddr]] <out_file>

multi Instructs the tool to create the <out_file> binary image file (*.img) with the entire contents of the SPI Flash memory (option: spi) or the I2C EEPROM (option: eeprom).

The multi-part image consists of:

  1. AN-B-001 header plus the bootloader firmware <bloader> at offset 0, if <bloader> is provided.

  2. <img1> (*.img image) at offset <off1>

  3. <img2> (*.img image) at offset <off2>

  4. Product header at offset <off3>

The cfg option configures the following product header fields:

  • The application specific ‘Configuration Offset’ is initialized from off4. If off4 is not provided, then the ‘Configuration Offset’ field shall be set to 0xFFFFFFFF.

  • The BD Address is initialized from ‘bdaddr’. If bdaddr is not provided, then the BD Address field shall be set to FF:FF:FF:FF:FF:FF. If bdaddr is provided, it is required that no space exists between off4, the comma character and the ‘bdaddr’.

The offsets can be given either as decimal or as hexadecimal numbers.

The BD address ‘bdaddr’ can be given as XX:XX:XX:XX:XX:XX where X is a hex digit. For example, 80:EA:CA:01:02:03.

6.3. Production Line Tool Reference CLI

6.3.1. Introduction

This section describes the reference command line interface (CLI) for the production test tool of DA14585/586/531.

The tool is a Microsoft Windows command line program that enables communication over UART with a DA14585/586/531 device that runs the production test firmware.

The production test firmware is a special firmware that supports:

  • The Bluetooth SIG standardized receiver and transmitter test HCI commands.

  • Additional custom test HCI commands.

All test commands are also supported by the RF Master tool of the SmartSnippets Toolbox.

Dialog has also designed a production test and programming unit “PLT” that enables you to reduce cost and increase throughput in volume test & programming of units centred around the DA145xx family.

6.3.2. Getting Started

6.3.2.1. Precompiled Binaries

Precompiled binaries are provided for both the production test firmware and tool in the following SDK paths:

Firmware

  • <sdk_root_directory>\binaries\da14585\prod_test\prod_test_585.hex for DA14585

  • <sdk_root_directory>\binaries\da14585\prod_test\prod_test_586.hex for DA14586

  • <sdk_root_directory>\binaries\da14585\prod_test\prod_test_531.hex for DA14531

Tool

  • <sdk_root_directory>\binaries\host\windows\prod_test_cmds\prod_test.exe

6.3.2.2. Building the Tool

For SDK 6.0.4 and above this is in: <sdk_root_directory>\utilities\prod_test\prod_test_cmds.

6.3.2.3. Building the Firmware

The required firmware is included in the SDK in folder: (SDK 6.0.2 and later): <sdk_root_directory>\projects\target_apps\prod_test\prod_test

Steps to build the firmware

  1. Open the folder <sdk_root_directory>\projects\target_apps\prod_test\prod_test.

  2. Open the project.

  3. Select menu Project -> Rebuild all target files to build the project.

  4. Get the generated hex file from:

  • DA14585: .\Keil_5\out_DA14585\Objects\prod_test_585.hex

  • DA14586: .\Keil_5\out_DA14586\Objects\prod_test_586.hex

  • DA14531: .\Keil_5\out_DA14531\Objects\prod_test_531.hex

6.3.3. General Description

The general syntax of the tool is:

prodtest <switches> <command> <command-arg-1> … <command-arg-2>

A command always returns a status code and optionally a list of return values. The return status code and values are written to the standard output in a simple format: <value_name> = <value>.

The return status code is also returned as an exit code.

A zero status code represents the successful execution of a command. A non-zero status code encodes the type of failure.

All other output of the tool is written to stderr (except the help message when -h option is used).

6.3.4. Command Line Switches

6.3.4.1. Switch -h

Description: print out all the commands of prodtest on a command line terminal

Syntax: prodtest -h

6.3.4.2. Switch -p

Description: select the COM port number on a PC. All commands require this switch.

Syntax: prodtest -p <COM_PORT_NUMBER> ...

6.3.4.3. Switch -v

Description: display the tool’s version

Syntax: prodtest -v

6.3.5. Commands

6.3.5.1. cont_pkt_tx

Description: this is the Bluetooth SIG standardized HCI_LE_Transmitter_Test command. It continuously transmits packets until the stoptest command is executed.

Syntax: prodtest -p <COM_PORT_NUMBER> cont_pkt_tx <FREQUENCY> <DATA_LENGTH> <PAYLOAD_TYPE>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, integer 2480 corresponds to 2.480 GHz.

  • DATA_LENGTH is the payload length in bytes (a number between 37 and 255).

  • PAYLOAD_TYPE must have one of the following values:

    0 : Pseudo-Random bit sequence 9
    1 : Pattern of alternating bits '11110000'
    2 : Pattern of alternating bits '10101010'
    3 : Pseudo-Random bit sequence 15
    4 : Pattern of All '1' bits
    5 : Pattern of All '0' bits
    6 : Pattern of alternating bits '00001111'
    7 : Pattern of alternating bits '0101'
    

Example:

prodtest -p 14 cont_pkt_tx  2402  35  6

Output example:

status = 0

6.3.5.2. pkt_tx

Description: transmit the specified number of packets.

Syntax: prodtest -p <COM_PORT_NUMBER> pkt_tx <FREQUENCY> <DATA_LENGTH> <PAYLOAD_TYPE> <NUMBER_OF_PACKETS>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, 2480 corresponds to 2.480 GHz.

  • DATA_LENGTH is the payload length in bytes (a number between 37 and 255).

  • PAYLOAD_TYPE must have one of the following values:

    0 : Pseudo-Random bit sequence 9
    1 : Pattern of alternating bits '11110000'
    2 : Pattern of alternating bits '10101010'
    3 : Pseudo-Random bit sequence 15
    4 : Pattern of All '1' bits
    5 : Pattern of All '0' bits
    6 : Pattern of alternating bits '00001111'
    7 : Pattern of alternating bits '0101'
    
  • NUMBER_OF_PACKETS is an integer between 1 and 65535.

Example: the following command sends 1000 packets:

prodtest -p 14 pkt_tx  2402  35  6 1000

Output example:

status = 0

6.3.5.3. start_pkt_rx

Description: This is the Bluetooth SIG standardized HCI_LE_Receiver_Test command. It continuously receives packets until the stoptest command is executed.

Syntax: prodtest -p <COM_PORT_NUMBER> start_pkt_rx <FREQUENCY>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, 2480 corresponds to 2.480 GHz.

Example:

prodtest -p 14 start_pkt_rx  2402

Output example:

status = 0

6.3.5.4. start_pkt_rx_stats

Description: starts packet RX with additional statistics. It continuously receives packets until the stop_pkt_rx_stats command is executed.

Syntax: prodtest -p <COM_PORT_NUMBER> start_pkt_rx_stats <FREQUENCY>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, 2480 corresponds to 2.480 GHz.

Example:

prodtest -p 14 start_pkt_rx_stats 2402

Output example:

status = 0

6.3.5.5. stop_pkt_rx_stats

Description: ends packet RX with additional statistics and reports the following statistics:

  • number of packets received correctly (nb_packets_received_correctly)

  • number of packets with sync error (nb_packets_with_syncerror)

  • number of packets with CRC error (nb_packets_received_with_crcerr)

  • RSSI in dBm (rssi)

Syntax: prodtest -p <COM_PORT_NUMBER> stop_pkt_rx_stats

Example:

prodtest -p 14 stop_pkt_rx_stats

Output example:

status = 0
nb_packets_received_correctly = 8529
nb_packets_with_syncerror = 0
nb_packets_received_with_crcerr = 1
rssi = -37.30

6.3.5.6. stoptest

Description: This is the Bluetooth SIG standardized HCI_LE_Test_End command. It is used:

  • after a cont_pkt_tx command to end the standard packet TX test mode.

  • after a start_pkt_rx command to end the standard packet RX mode and report the number of received packets.

Syntax: prodtest -p <COM_PORT_NUMBER> stoptest

Example:

prodtest -p 14 stoptest

Output example (the number of packets is always zero when executed after a cont_pkt_tx):

status = 0
number_of_packets = 0

Output example (when executed after a start_pkt_rx):

status = 0
number_of_packets = 4360

6.3.5.7. unmodulated TX

Description: starts a Continuous Wave (CW) or unmodulated TX test.

Syntax: prodtest -p <COM_PORT_NUMBER> unmodulated TX <FREQUENCY>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, 2480 corresponds to 2.480 GHz.

Example:

prodtest -p 14 unmodulated  TX 2404

Output example:

status = 0

6.3.5.8. unmodulated RX

Description: starts the unmodulated RX test.

Syntax: prodtest -p <COM_PORT_NUMBER> unmodulated RX <FREQUENCY>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, 2480 corresponds to 2.480 GHz.

Example:

prodtest  -p 14 unmodulated  RX 2404

Output example:

status = 0

6.3.5.9. unmodulated OFF

Description: stops unmodulated TX or RX test.

Syntax: prodtest -p <COM_PORT_NUMBER> unmodulated OFF

Example:

prodtest  -p 14 unmodulated  OFF

Output example:

status = 0

6.3.5.10. start_cont_tx

Description: starts the continuous TX test mode. It transmits continuously a modulated signal until the stop_cont_tx command is executed.

Syntax: prodtest -p <COM_PORT_NUMBER> start_cont_tx <FREQUENCY>  <PAYLOAD_TYPE>

Parameters:

  • FREQUENCY is an even integer between 2402 and 2480. For example, 2480 corresponds to 2.480 GHz.

  • PAYLOAD_TYPE must have one of the following values:

    0 : Pseudo-Random bit sequence 9
    1 : Pattern of alternating bits '11110000'
    2 : Pattern of alternating bits '10101010'
    3 : Pseudo-Random bit sequence 15
    4 : Pattern of All '1' bits
    5 : Pattern of All '0' bits
    6 : Pattern of alternating bits '00001111'
    7 : Pattern of alternating bits '0101'
    

Example:

prodtest -p 14 start_cont_tx 2404 4

Output example:

status = 0

6.3.5.11. stop_cont_tx

Description: stops the continuous TX test mode.

Syntax: prodtest -p <COM_PORT_NUMBER> stop_cont_tx

Example:

prodtest -p 14 stop_cont_tx

Output example:

status = 0

6.3.5.12. reset

Description: this is the Bluetooth SIG standardized HCI_Reset command.

Syntax: prodtest -p <COM_PORT_NUMBER> reset

Example:

prodtest -p 14 reset

Output example:

status = 0

6.3.5.13. xtrim rd

Description: reads the value of the XTAL16M trimming register as specified in DA14585 and DA14586 datasheets: CLK_FREQ_TRIM_REG (0x50000002).

The value is reported in decimal format.

Syntax: prodtest -p <COM port number> xtrim rd

Example:

prodtest -p 14 xtrim rd

Output example:

status = 0
trim_value = 500

6.3.5.14. xtrim wr

Description: writes a value into the XTAL16M trimming register. The new value is written immediately and is already effective when the prodtest program finishes executing this command.

Syntax: prodtest -p <COM port number> xtrim wr <trim_value>

Parameters:

  • trim_value is the unsigned 16-bit decimal value to be written into the XTAL16M trimming register.

Example:

prodtest -p 14 xtrim wr 500

Output example:

status = 0

6.3.5.15. xtrim en

Description: enables XTAL16M output on GPIO P0_5. The command takes effect immediately.

Syntax: prodtest -p <COM port number> xtrim en

Example:

prodtest -p 14 xtrim en

Output example:

status = 0

Note

This command can also be used to enable the 32 kHz clock on a GPIO 0_6. To do this, two additional registers need to be set with the write_reg16 command (see section Section 6.3.5.29). Enable the 32 kHz clock in CLK_32K_REG, set bit 0 and bit 7 to ‘1’ Set GPIO P0_6 to output mode. In P06_MODE_REG, set bit 8 and 9 to ‘1’.

Example:

prodtest -p 14 write_reg16 50000020 079D
prodtest -p 14 write_reg16 50003012 0300

Output example:

status = 0

6.3.5.16. xtrim dis

Description: disables XTAL16M output on GPIO P0_5. The command takes effect immediately.

Note

This command also disables: XTAL32K output on GPIO P0_6 RC16M output on P0_7 RC32K output on P1_0.

Syntax: prodtest -p <COM port number> xtrim dis

Example:

prodtest -p 14 xtrim dis

Output example:

status = 0

6.3.5.17. xtrim inc

Description: increments the XTAL16M trimming register. The register’s new value is already effective when the prodtest program finishes the execution of this command.

Syntax: prodtest -p <COM port number> xtrim inc <delta>

Parameters:

  • delta is the unsigned 16-bit decimal value to be added to the XTAL16M trimming register.

Example:

prodtest -p 14 xtrim inc 5

Output example:

status = 0

6.3.5.18. xtrim dec

Description: decrements the XTAL16M trimming register. The register’s new value is already effective when the prodtest program finishes executing this command.

Syntax: prodtest -p <COM port number> xtrim dec <delta>

Parameters:

  • delta is the unsigned 16-bit decimal value to be subtracted from the XTAL16M trimming register.

Example:

prodtest -p 14 xtrim dec 5

Output example:

status = 0

6.3.5.19. xtrim cal

Description: runs the XTAL16M trimming register calibration procedure, which uses an externally applied 500 ms high square pulse as a reference for trim value calibration. The procedure executes the following steps:

  1. Calibrates the XTAL16M trimming register.

  2. Programs the calibrated value in OTP (at address 0x7F8C).

  3. Enables the “XTAL16M trim value is valid” bit in OTP (at address 0x7F78).

If a square pulse has not been applied on the given GPIO then the calibration procedure will fail with a status code equal to 27.

Syntax: prodtest -p <COM port number> xtrim cal <Px_y>

Parameters:

  • Px_y is the GPIO that the external square pulse is applied on.

Example:

prodtest -p 14 xtrim cal P1_0

Output example:

status = 0

6.3.5.20. xtrim caltest

Description: behaves identically to “xtrim cal” with the exception that it does not modify the OTP.

Syntax: prodtest -p <COM port number> xtrim caltest <Px_y>

Parameters:

  • Px_y is the GPIO that the external square pulse is applied on.

Example:

prodtest -p 14 xtrim caltest P1_0

Output example:

status = 0

6.3.5.21. sleep

Description: puts the device to sleep for a specified number of minutes and seconds.

Syntax: prodtest -p <COM_PORT_NUMBER> sleep <mode> <minutes> <seconds>

Parameters:

  • mode is one of the following power modes:

    "none" for Active Mode
    "extended" for Extended Sleep Mode
    "deep" for Deep Sleep Mode
    
  • minutes is a number between 0 and 255

  • seconds is a number between 0 and 255

If both minutes and seconds are set to zero, then the device sleeps forever. The active peripherals in each sleep mode are shown in Table 33 and Table 34.

Table 33 Power Domain Manipulation for Extended and Deep Sleep Mode For the DA1585/586

Power mode

PD_SYS

PD_PER

PD_DBG

PD_RAD

PD_SRx

Analog

Extended/Deep Sleep

Auto OFF

Programmable

Auto OFF

Programmable

Programmable

Auto OFF


Table 34 Power Domain Manipulation for Extended and Deep Sleep Mode for the DA14531

Power mode

PD_SYS

PD_AON

PD_SLP

PD_RAD

PD_TIM

Extended/Deep

Sleep

Auto OFF

ON

ON

OFF

Programmable

Known limitations:

  • UART communication is lost when the device wakes up from extended sleep mode

  • The device will not wake up from Extended sleep with OTP copy mode

Example 1:

prodtest -p 14 sleep none 1 0

Example 2:

prodtest -p 14 sleep extended 0 30

Example 3:

prodtest -p 14 sleep deep 0 0

Output example:

status = 0

6.3.5.22. otp wr_xtrim

Description: writes the XTAL16M trim value into the OTP header.

Syntax: prodtest -p <COM port number> otp wr_xtrim <decimal trim value>

Parameters:

  • Decimal trim value is the unsigned 16-bit decimal XTAL16M trim value to be written into the OTP header

Example:

prodtest -p 14 otp wr_xtrim 500

Output example:

status = 0

6.3.5.23. otp rd_xtrim

Description: reads the XTAL16M trim value from the OTP header. The output value is in decimal format.

Syntax: prodtest -p <COM port number> otp rd_xtrim

Example:

prodtest -p 14 otp rd_xtrim

Output example:

status = 0
otp_xtrim_value = 500

6.3.5.24. otp wr_bdaddr

Description: writes the Bluetooth Device address into the OTP header.

Syntax: prodtest -p <COM port number> otp wr_bdaddr <BD address>

Parameters:

  • BD address is the Bluetooth Device address to be written into the OTP header. The BD address must be formatted as XX:XX:XX:XX:XX:XX where X is a hexadecimal digit

Example:

prodtest -p 14 otp wr_bdaddr 44:49:41:4c:4f:47

Output example:

status = 0

6.3.5.25. otp_read

Description: reads consecutive words from OTP memory.

Syntax: prodtest -p <COM port number> otp_read <otp address> <word count>

Parameters:

  • otp address is the start address of the OTP memory region to be read. This is a word address and must therefore be divisible by 4. It must be lower than 0x8000. It must be formatted as a 16-bit hexadecimal number

  • Word count is the number of words to be read. The accepted range is from 1 to 60. The word count must satisfy the formula: <otp address> + 4 * <word count> <= 0x8000. It must be formatted as a decimal number

Example:

prodtest -p 16 otp_read 7FDC 5

Output example:

status = 0
[7FDC] = 1234A5A5
[7FE0] = A5A51234
[7FE4] = 14121117
[7FE8] = 24222127
[7FEC] = 00000007

6.3.5.26. otp_write

Description: writes consecutive words into OTP memory.

Syntax: prodtest -p <COM port number> otp_write <otp address> <word #1> ... <word #n>

Parameters:

  • otp address is the start address of the OTP memory region to be written. This is a word address and must therefore be divisible by 4. It must be lower than 0x8000. It must be formatted as a 16 bit hexadecimal number

  • Word #i is the word value to be written in address: <otp address> + 4 * i. It must be formatted as a 32 bit hexadecimal number. The number of word value arguments must be at most 60 and must satisfy the formula: <otp address> + 4 * n <= 0x8000

Example:

prodtest -p 16 otp_write 7FDC 1234A5A5 A5A51234

Output example:

status = 0

6.3.5.27. read_reg16

Description: reads the value of a 16-bit register. The output value is printed in hex.

Syntax: prodtest -p <COM port number> read_reg16 <register address>

Parameters:

  • register address is the address of the 16-bit register to be read. The register address must be half-word aligned, and must therefore be divisible by 2. It must be formatted as a 32-bit hexadecimal number

Example: the following command reads TRIM_CTRL_REG (0x50000016).

prodtest -p 16 read_reg16 50000016

Output example:

status = 0
value = 00A2

6.3.5.28. read_reg32

Description: reads the value of a 32-bit register. The output value is printed in hex.

Syntax: prodtest -p <COM port number> read_reg32 <register address>

Parameters:

  • register address is the address of the 32-bit register to be read. The register address must be word aligned and must therefore be divisible by 4. It must be formatted as a 32-bit hexadecimal number

Example: the following command reads PATCH_VALID_REG (0x40008400).

prodtest -p 16 read_reg32 40008400

Output example:

status = 0
value = 00000001

6.3.5.29. write_reg16

Description: writes into a 16-bit register.

Syntax: prodtest -p <COM port number> write_reg16 <register address> <register value>

Parameters:

  • register address is the address of the 16-bit register to be read. The register address must be half-word aligned and must therefore be divisible by 2. It must be formatted as a 32-bit hexadecimal number

  • register value is the value to be written into the register. It must be formatted as a 16-bit hexadecimal number

Example: the following command writes 0x00B3 in TRIM_CTRL_REG (0x50000016).

prodtest -p 16 write_reg16 50000016 00B3

Output example:

status = 0

6.3.5.30. write_reg32

Description: writes into a 32-bit register.

Syntax: prodtest -p <COM port number> write_reg32 <register address> <register value>

Parameters:

  • register address is the address of the 32-bit register to be read. The register address must be word aligned and must therefore be divisible by 4. It must be formatted as a 32-bit hexadecimal number

  • register value is the value to be written into the register. It must be formatted as a 32-bit hexadecimal number

Example: the following command writes 0x0000000F in PATCH_VALID_REG (0x40008400).

prodtest -p 16 write_reg32 40008400 0000000F

Output example:

status = 0

6.3.6. Return Status Codes

Table 35 summarizes the return codes of the production’s test tool.

Table 35 Return Codes

Status code

Description

0

SC_NO_ERROR

1

SC_MISSING_COMMAND

2

SC_INVALID_COMMAND

3

SC_WRONG_NUMBER_OF_ARGUMENTS

4

SC_INVALID_COM_PORT_NUMBER

5

SC_INVALID_FREQUENCY_ARG

6

SC_INVALID_DATA_LENGTH_ARG

7

SC_INVALID_PAYLOAD_TYPE_ARG

8

SC_COM_PORT_INIT_ERROR

9

SC_RX_TIMEOUT

12

SC_INVALID_UNMODULATED_CMD_MODE_ARG

13

SC_COM_PORT_NOT_SPECIFIED

14

SC_INVALID_SLEEP_CMD_MODE_ARG

15

SC_INVALID_SLEEP_CMD_MINUTES_ARG

16

SC_INVALID_SLEEP_CMD_SECONDS_ARG

17

SC_INVALID_XTAL_TRIMMING_CMD_OPERATION_ARG

18

SC_INVALID_XTAL_TRIMMING_CMD_TRIM_VALUE_ARG

19

SC_INVALID_OTP_CMD_OPERATION_ARG

20

SC_INVALID_OTP_CMD_TRIM_VALUE_ARG

21

SC_INVALID_OTP_CMD_BDADDR_ARG

22

SC_INVALID_OTP_ADDRESS_ARG

23

SC_INVALID_NUMBER_OF_OTP_WORDS_ARG

24

SC_INVALID_WORD_VALUE_ARG

25

SC_INVALID_GPIO_ARG

26

SC_XTAL_TRIMMING_CAL_OUT_OF_RANGE_ERROR

27

SC_XTAL_TRIMMING_CAL_FREQ_NOT_CONNECTED

28

SC_INVALID_REGISTER_ADDRESS_ARG

29

SC_INVALID_REGISTER_VALUE_ARG

1000 - 1063

SC_HCI_STANDARD_ERROR_CODE_BASE (1000) + standard HCI error code

6.4. Flash Programmer

6.4.1. Overview

Flash programmer (flash_programmer) is a target side application used to upload and read back the application code that runs on platforms powered by the DA14585/586/531 series integrated circuit. After the flash programmer application is booted, the platform communicates over the UART or JTAG interface with the host application that allows it to read or write application code to the FLASH, EEPROM or OTP memory. Both sides exchange messages that contain operation codes, statuses and payload with respect to the defined protocol.

6.4.2. Communication Channel

The communication channel is selected at compile time and is limited to the following options:

6.4.2.1. UART (USE_UART Flag Defined)

In this mode, flash programmer receives messages from the host and responds back with the UART interface. It also defines an exchange buffer of size 64K- 1 bytes (0xFFFF) for DA14585/585 targets and 32K - 1 bytes (0x7FFF) for DA14531. This limits the amount of data that can be written or read in a single message. This is the implication of the 2 byte wide length indicator that (along with the CRC) is sent before the actual message frame. The frame length and the CRC code are not cached inside the buffer and holds only the actual message (including possible headers and payload).

With this knowledge it is easy to figure out, that in case of the OTP write operation, the actual firmware chunk size is limited to 0xFFF8 (0xFFFF minus the 7 bytes of header data for this particular message) for DA14585/586 and 0x7FF8 for DA14531. As communication via UART is synchronous, the defined buffer is used for both the incoming and the outgoing messages.

The flash programmer communicates by default with the host through pins P0_0, P0_1 at speed 57600 for DA14585/586 targets and at speed 115200 for DA14531. This can be changed by appending to the binary 1 byte. This byte selects pins and baud rate according to the following table.

Table 36 UART Options for DA14585/586/531

Platform

Selector

TX pin

RX pin

Baud rate

DA14585/586

0 (default)

P0_0

P0_1

57600

2

P0_2

P0_3

115200

4

P0_4

P0_5

57600

6

P0_6

P0_7

9600

DA14531

0 (default)

P0_0

P0_1

115200

3 (single wire UART)

P0_3

P0_3

115200

5 (single wire UART)

P0_5

P0_5

115200

6.4.2.2. JTAG (No Flag Defined)

Uses shared memory for message exchange. The host application reads from and writes to a certain memory region with the JTAG interface. The Flash programmer constantly polls one of these regions for new messages and responds accordingly. There are two regions defined:

  • BASE_MEMORY - in this region messages and responses are stored

  • TARGET_MEMORY - in this region the payload is stored

The available message space is limited to 64K for DA14585/586 and to 32K for DA14531 (the limitations of the actual message headers also apply here. In case of write request, the offset field is 2 bytes wide which covers the first 64K/32K memory addresses).

Note

The message exchange protocol slightly differs in both cases and is described in another section.

6.4.3. Functionality

The Flash programmer supports the following operations:

  • hardware setup required to operate the FLASH, EEPROM, OTP peripherals (this includes enabling LDO and GPIO configuration)

  • reading the currently running flash programmer version

  • reading the requested amount of data from the application memory regions

  • writing the requested amount of data to the application memory regions

  • erasing the requested amount of data from the application memory regions (not supported by all non-volatile memory types)

6.4.4. Data Exchange Protocol

Flash programmer listens for host commands in an infinite loop. The host should receive a response for each of the issued actions. Those should be issued sequentially once the previous ones were completed by the target. This message exchange sequence is done differently for each of the supported exchange channels.

6.4.4.1. UART

The host sends a command packet through UART in the following form:

Table 37 UART Command Packet

Len (16 bits)

CRC (32 bits)

Op Code

Address (32 bits)

Length (16 bits)

Data …

HEADER SECTION

MESSAGE SECTION

The first Len parameter is the total length of the message section, which starts with the Op Code (8 bits) and ends where the variable length Data buffer ends. CRC is also calculated for the message section. The message section length is limited by the 2 bytes wide Len.

The result response sent to the host varies from one message to the other. The exact request and response messages are presented later in this document but it is important to note that they do also have the header section that contain the Len and CRC fields.

Data is transferred over the wire with a network byte order (big endian).

6.4.4.2. JTAG (Memory Mapped API)

The host writes a message to the memory section to issue a command, which starts at the address that is in the BASE_MEMORY variable. The message is structured in the following form:

Table 38 Memory Layout at BASE_MEMORY Address

Memory offset

Memory content

Order

ACTION_OFFSET

Op Code

LSB

SIZE_OFFSET

Length (16 bits)

MSB

SIZE_OFFSET + 1

LSB

ADDRESS_OFFSET

Address Offset (32 bits)

ADDRESS_OFFSET + 1

ADDRESS_OFFSET + 2

MSB

ADDRESS_OFFSET + 3

RESULT_OFFSET

Result

LSB

ERROR_OFFSET

Additional error code when Result is not ACTION_OK

ERROR_OFFSET + 1

ERROR_OFFSET + 2

MSB

ERROR_OFFSET + 3

Table 39 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Memory content

0

1

Additionally the payload of Length is written into the Data buffer pointed by the TARGET_MEMORY variable when applicable.

Note

The host writes the packet sections at certain offsets relative to the starting address that is saved in the BASE_MEMORY variable. Writing the Op Code should be the last step as this triggers the action on the target platform. The Op Code value changes back to 0 once the message is processed and the response in the Result section is filled. This way the host knows when to read the results of the triggered action. Similarly to the messages exchanged via UART the response structure depends on the command sent by the host.

For the DA14585/586/531 platform, memory addresses and offsets are set according to the following table:

Table 40 Memory Addresses and Offsets

Platform

TARGET_MEMORY

BASE_MEMORY

ACTION_OFFSET

SIZE_OFFSET

ADDRESS_OFFSET

RESULT_OFFSET

DA14585/586

0x07FC8000

0x07FC7C00

0x00

0x02

0x04

0x08

DA14531

0x07FC4000

0x07FC3C00

0x00

0x02

0x04

0x08

Because of the nature of the JTAG interface, no endianness conversion is being done. Data should be written in the target platform’s endianness (little endian).

6.4.4.3. Handshake

The host application needs to receive a signal from the target to determine if the target is ready to receive requests. This is done differently for both communication channels:

UART:

Target sends the ‘’Hello’’ string over UART to report readiness.

JTAG:

Target sets the result status value to ACTION_READY at the BASE_MEMORY + RESULT_OFFSET memory address. The host application can monitor this memory address to detect flash_programmer readiness.

6.4.4.4. Messages

Note that the following list of messages do not list the header sections (Length, CRC), which is sent along every UART message that is exchanged over the protocol.

6.4.4.4.1. General
ACTION_READ_VERSION

(0x10) - Reads the flash programmer application version

UART:

Table 41 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

0x07

CRC

0x10

Table 42 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Op Code

0x0D

CRC

0x82

JTAG:

Table 43 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x10 (ACTION_READ_VERSION)

0x00 (NO_ACTION)

SIZE_OFFSET

do not care

do not care

ADDRESS_OFFSET

do not care

do not care

RESULT_OFFSET

do not care

0x82 (ACTION_CONTENTS)

Table 44 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

do not care

v

1

do not care

_

2

do not care

5

do not care

ACTION_VPP_ENABLE

(0x50) - Enable the transistor that controls high voltage (6.8v) when OTP memory is written.

UART:

Table 45 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code (8 bits)

VPP_ENABLE (8 bits)

0x02

CRC

0x50

0x00 or 0x01

Table 46 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status (8 bits)

0x01

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ACTION_READY

(0x5A) - This is used only by firmware to inform the host that the target is ready to handle host requests when running in Shared Memory Mode (JTAG).

JTAG:

Table 47 Memory Layout at BASE_MEMORY Address

Memory offset

Memory content when not ready

Memory content when ready

ACTION_OFFSET

do not care

do not care

SIZE_OFFSET

do not care

do not care

ADDRESS_OFFSET

do not care

do not care

RESULT_OFFSET

0x00

0x82 (ACTION_READY)

ACTION_UART_GPIOS

(0x31) - Configure UART data lines. Returns ACTION_ERROR if pins are incorrect.

UART:

Table 48 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

TX_PORT

TX_PIN

RX_PORT

RX_PIN

0x05

CRC

0x31

0x00

0x04

0x00

0x05

Table 49 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status (8 bits)

0x01

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

JTAG:

Unsupported

6.4.4.4.2. OTP Memory
ACTION_OTP_READ

(0x80) - Read the requested amount of data from the OTP memory at the given offset.

UART:

Table 50 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address offset (32 bits)

Length (16 bits)

Len (16 bits)

CRC (32 bits)

0x07 + length

CRC

0x80

offset

length

0x07 + length

CRC

Table 51 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status(8 bits)

Data …

0x01 + data length

CRC

0x82 (ACTION_CONTENTS)

read data

JTAG:

Table 52 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x80 (ACTION_OTP_READ)

0x00 (NO_ACTION)

SIZE_OFFSET

data length

data length

ADDRESS_OFFSET

address offset

address offset

RESULT_OFFSET

do not care

0x82 (ACTION_CONTENTS)

Table 53 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

do not care

data0

1

do not care

data1

2

do not care

data2

do not care

data3

ACTION_OTP_WRITE

(0x81) - Write the requested amount of data into the OTP memory at the given offset.

UART:

Table 54 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address offset (32 bits)

Length (16 bits)

Data (LENGTH*8 bits)

0x07 + length

CRC

0x81

memory address

length

data to write

Table 55 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status (8 bits)

Error Code (32 bits)

0x01 or 0x05

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

Additional error code - only if Status is set to ACTION_ERROR.

JTAG:

Table 56 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x81 (ACTION_OTP_WRITE)

0x00 (NO_ACTION)

SIZE_OFFSET

size

size

ADDRESS_OFFSET

address offset

address offset

RESULT_OFFSET

do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ERROR_OFFSET

do not care

Error code (32 bits) - only if result is ACTION_ERROR

Table 57 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

data0

data0

1

data1

data1

2

data2

data2

data3

data3

6.4.4.4.3. SPI FLASH
ACTION_SPI_READ

(0x90) - Read the requested amount of data from the SPI FLASH memory at given memory address.

UART:

Table 58 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address offset (32 bits)

Length (16 bits)

Data (LENGTH*8 bits)

0x07 + length

CRC

0x90

memory address

length

data to write

Table 59 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status (8 bits)

Data…

0x01 + data length

CRC

0x82 (ACTION_CONTENTS)

read data

JTAG:

Table 60 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x90 (ACTION_SPI_READ)

0x00 (NO_ACTION)

SIZE_OFFSET

data length

data length

ADDRESS_OFFSET

address

address

RESULT_OFFSET

do not care

0x82 (ACTION_CONTENTS)

Table 61 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

do not care | data0

1

do not care | data1

2

do not care | data2

do not care | data3

ACTION_SPI_WRITE

(0x91) - Write the requested amount of data into SPI FLASH memory at given offset.

UART:

Table 62 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address offset (32 bits)

Length (16 bits)

Data (LENGTH*8 bits)

0x07 + length

CRC

0x91

memory address

length

data to write

Table 63 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status (8 bits)

Error Code (32 bits)

0x01 or 0x05

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

Additional error code - only if Status is set to ACTION_ERROR.

JTAG:

Table 64 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x91 (ACTION_FLASH_WRITE)

0x00 (NO_ACTION)

SIZE_OFFSET

size

size

ADDRESS_OFFSET

memory address

memory address

RESULT_OFFSET

do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ERROR_OFFSET

do not care

Error code (32 bits) - only if result is ACTION_ERROR

Table 65 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

data0

data0

1

data1

data1

2

data2

data2

data3

data3

ACTION_SPI_ERASE

(0x92) - Erase SPI FLASH memory.

UART:

Table 66 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

0x01

CRC

0x92

Table 67 UART_RESPONSE

Status (8 bits)

Error Code (32 bits)

Status (8 bits)

Error Code (32 bits)

0x01 or 0x05

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

Additional error code - only if Status is set to ACTION_ERROR.

JTAG:

Table 68 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x92 (ACTION_SPI_ERASE)

0x00 (NO_ACTION)

SIZE_OFFSET

Do not care

Do not care

ADDRESS_OFFSET

Do not care

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ERROR_OFFSET

Do not care

Error code (32bits) - only if result is ACTION_ERROR

Note

Data buffer memory layout at TARGET_MEMORY address: Target memory is not used.

ACTION_SPI_ID

(0x93) - Read flash JEDEC ID.

UART:

Table 69 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

0x01

CRC

0x93

Table 70 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

(8 bits)

MANUFACTU RER ID (8 bits)

JEDEC ID 1 (8 bits)

0x05

CRC

0x82 (ACTION_C ONTENTS)

0

id

id

JTAG:

Table 71 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x93 (ACTION_EEPROM_READ)

0x00 (NO_ACTION)

SIZE_OFFSET

Do not care

Do not care

ADDRESS_OFFSET

Do not care

Do not care

RESULT_OFFSET

Do not care

0x82 (ACTION_CONTENTS)

Table 72 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

Do not care

Device ID byte 2

1

Do not care

Device ID byte 1

2

Do not care

Manufacturer ID

3

Do not care

0

ACTION_SPI_ERASE_BLOCK

(0x94) - Erase specified number of sectors starting from flash address.

UART:

Table 73 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address (32 bits)

Sectors (16 bits)

0x07

CRC

0x94

address

n

Table 74 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

(8 bits)

MANUFACTURER ID (8 bits)

JEDEC ID 1 (8 bits)

0x01 or 0x05

CRC

0x83 (ACTION_O K) or 0x84 (ACTION_E RROR)

Additiona l error code - only if Status is not set to ACTION_OK

0x01 or 0x05

CRC

JTAG:

Table 75 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x94 (ACTION_SPI_ERASE_BLO CK)

0x00 (NO_ACTION)

SIZE_OFFSET

sector count

Do not care

ADDRESS_OFFSET

address

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ERROR_OFFSET

Do not care

Error code - only if result is ACTION_ERROR

ACTION_SPI_GPIOS

(0x95) - Configure SPI data lines. Returns ACTION_ERROR if any pin is incorrect.

UART:

Table 76 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

CS PORT

CS PIN

CLK PORT

CLK PIN

DO PORT

DO PIN

DI PORT

DI PIN

0x09

CRC

0x95

0x00

0x03

0x00

0x00

0x00

0x06

0x00

0x05

Table 77 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

0x01

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

JTAG:

Table 78 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x95 (ACTION_SPI_GPIOS)

0x00 (NO_ACTION)

SIZE_OFFSET

Do not care

Do not care

ADDRESS_OFFSET

Do not care

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

Table 79 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

0x00 (CS PORT)

Do not care

1

0x03 (CS PIN)

Do not care

2

0x00 (SCL PORT)

Do not care

3

0x00 (SCL PIN)

Do not care

4

0x00 (DO PORT)

Do not care

5

0x06 (DO PIN)

Do not care

6

0x00 (DI PORT)

Do not care

ACTION_SPI_HEADER

(0x96) - Write image header to SPI flash.

UART:

Table 80 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Size (24 bits)

0x04

CRC

0x96

0x012345

Table 81 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

0x01

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

JTAG:

Table 82 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0x96 (ACTION_SPI_HEADER)

0x00 (NO_ACTION)

SIZE_OFFSET

Do not care

Do not care

ADDRESS_OFFSET

Do not care

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

Table 83 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

0x45 (Size LSB)

Do not care

1

0x23

Do not care

2

0x01 (Size MSB)

Do not care

3

Do not care

Do not care

6.4.4.4.4. I2C EEPROM
ACTION_EEPROM_READ

(0xA0) - Read n bytes of data from specified address in I2C EEPROM.

UART:

Table 84 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address (32 bits)

Size (16 bits)

0x07

CRC

0xA0

address

n

Table 85 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status (8 bits)

Data …

0x01 + data length

CRC

0x82 (ACTION_CONTENTS)

read data

JTAG:

Table 86 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0xA0 (ACTION_EEPROM_READ)

0x00 (NO_ACTION)

SIZE_OFFSET

n

Do not care

ADDRESS_OFFSET

address

Do not care

RESULT_OFFSET

Do not care

0x82 (ACTION_CONTENTS)

Table 87 Data buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

Do not care

data byte 1

1

Do not care

data byte 2

Do not care

n-1

Do not care

data byte n

ACTION_EEPROM_WRITE

(0xA1) - Write n bytes of data to specified address in I2C EEPROM.

UART:

Table 88 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address offset (32 bits)

Length (16 bits)

Data (LENGTH*8 bits)

0x07 + length

CRC

0xA1

memory address

length

data to write

Table 89 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

0x01

CRC

0x83 (ACTION_OK)

Or

Table 90 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

Error code (32 bits)

0x05

CRC

0x84 (ACTION_ERROR)

error code

JTAG:

Table 91 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0xA1 (ACTION_EEPROM_WRITE)

0x00 (NO_ACTION)

SIZE_OFFSET

n

Do not care

ADDRESS_OFFSET

address

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ERROR_OFFSET

Do not care

Error code

Table 92 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

data byte 1

Do not care

1

data byte 2

Do not care

Do not care

n-1

data byte n

Do not care

ACTION_I2C_GPIOS

(0xA3) - Configure I2C data lines. Returns ACTION_ERROR if pins are incorrect.

UART:

Table 93 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Address offset (32 bits)

Length (16 bits)

Data (LENGTH*8 bits)

0x07 + length

CRC

0xA3

memory address

length

data to write

Table 94 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

0x01

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

JTAG:

Table 95 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0xA3 (ACTION_I2C_GPIOS)

0x00 (NO_ACTION)

SIZE_OFFSET

Do not care

Do not care

ADDRESS_OFFSET

Do not care

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

ACTION_OFFSET

0xA3 (ACTION_I2C_GPIOS)

0x00 (NO_ACTION)

Table 96 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

0x00 (SCL PORT)

Do not care

1

0x04 (SCL_PIN)

Do not care

2

0x00 (SDA_PORT)

Do not care

3

0x05 (SDA_PIN)

Do not care

ACTION_I2C_HEADER

(0xA4) - Write image header to I2C EEPROM.

UART:

Table 97 UART_REQUEST

Len (16 bits)

CRC (32 bits)

Op Code

Size (24 bits)

0x07 + length

CRC

0xA4

memory address

Table 98 UART_RESPONSE

Len (16 bits)

CRC (32 bits)

Status

0x01

CRC

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

JTAG:

Table 99 Memory Layout at BASE_MEMORY Address

Memory offset

Request memory content

Response memory content

ACTION_OFFSET

0xA4 (ACTION_I2C_HEADER)

0x00 (NO_ACTION)

SIZE_OFFSET

Do not care

Do not care

ADDRESS_OFFSET

Do not care

Do not care

RESULT_OFFSET

Do not care

0x83 (ACTION_OK) or 0x84 (ACTION_ERROR)

Table 100 Data Buffer Memory Layout at TARGET_MEMORY Address

Memory offset

Request memory content

Response memory content

0

0x45 (Size LSB)

Do not care

1

0x23

Do not care

2

0x01 (Size MSB)

Do not care

3

Do not care

Do not care

6.4.4.4.5. Response Status

The following codes are used to communicate the result of actions triggered by the host.

ACTION_CONTENTS

(0x82) - Common status when data is returned.

ACTION_OK

(0x83) - Common success status.

ACTION_ERROR

(0x84) - Common error status.

ACTION_DATA

(0x85) - Not used.

ACTION_INVALID_COMMAND

(0x86) - Sent to the host when target receives unknown command.

ACTION_INVALID_CRC

(0x87) - Can be sent as a response to any request over UART if CRC does not match the message content.

6.5. Writing HEX File into OTP Memory

The SmartSnippets OTP Programmer tool enables to download the default firmware into the System RAM and write a user-defined HEX or BIN file into the OTP memory. The tool can be used to write a secondary bootloader in the OTP memory of a DA14585/586/531.

The following steps are required to write the executable secondary_bootloader_585.hex into OTP memory with SmartSnippets in UART mode:

  1. Open SmartSnippets and select the chip version.

../_images/writing-hex-open-SS.png

Figure 72 Open SS Toolbox

  1. Open the Board Setup tool and select the appropriate UART configuration.

../_images/writing-hex-UART-setup.png

Figure 73 Board Setup

  1. Open the OTP Programmer tool and select the image file to download.

../_images/writing-hex-in-OTP-programmer.png

Figure 74 OTP Programmer

  1. Burn the secondary_bootloader_585.hex into the OTP memory at offset 0. Enable Application Flag 1 and Application Flag 2, set DMA Length (Length = size / 4) and burn the OTP header.

../_images/writing-hex-in-OTP.png

Figure 75 OTP Programmer

Note

For more info about SmartSnippets Toolbox, see the “SmartSnippets Toolbox User manual”.

6.6. BLE Coexistence with other 2.4GHz radios

The aim of this chapter is to descibe the main steps to enable WLAN coexistence support for the DA14585/586/531.

6.6.1. Introduction

../_images/wlan_coex_setup.png

Figure 76 WLAN coexistence with BLE

The WLAN coexistence feature on DA14585/586/531 is designed to allow multiple 2.4 GHz devices to operate without signals from one radio interfering with adjacent radios. This is done by a handshaking protocol between the BLE device and the other 2.4 GHz device using the following signals:

WLAN_COEX_BLE_EIP signal

The DA14585/586/531 can communicate its radio status in advance using the abovementioned signal. WLAN_COEX_BLE_EIP is an envelop of the scheduled TX and RX radio activity of the BLE Radio and it starts before the actual radio activity so it can upfront inform the coexisting system of scheduled RF activity. The signal is de-asserted synchronously directly after radio activity is finished.

WLAN_COEX_BLE_PRIO signal

The DA14585/586/531 can enable a priority line to indicate that it can not be interrupted for a defined activity. The activity for which BLE needs priority can be defined through the API.

The WLAN_COEX_BLE_PRIO signal is controlled internally by the DA14585/586/531 firmware, following certain user configurable rules. In the following table are listed all availiable priorities.

Table 101 The commands to configure the priorities for the WLAN coexistence feature

Rule

Command

Priority Type

1

wlan_coex_prio_criteria_add(BLEMPRIO_SCAN, LLD_ADV_HDL, 0);

Active scan

2

wlan_coex_prio_criteria_add(BLEMPRIO_ADV, LLD_ADV_HDL, 0);

Advertise

3

wlan_coex_prio_criteria_add(BLEMPRIO_CONREQ, LLD_ADV_HDL, 0);

Connection request

4

wlan_coex_prio_criteria_add(BLEMPRIO_LLCP, 0, 0);

Control packet

5

wlan_coex_prio_criteria_add(BLEMPRIO_DATA, 0, 0);

Data packet

6

wlan_coex_prio_criteria_add(BLEMPRIO_MISSED, 0, 4);

Missed events (in this example, after 4 bad packets)

WLAN_COEX_24G_EIP signal

Input signal to DA14585/586/531 device. External 2.4GHz device event in progress indication.

Note

Detailed information about WLAN Coexistence driver can be found in API documentation.

6.6.2. Enabling WLAN Coexistence feature

As an example, we will proceed to outline how WLAN coexistence feature could be enabled in prox_reporter_ext project:

  • In da1458x_config_advanced.h, use the following preprocessor definitions in order to enable WLAN coexistence mode with or without debugging signals and set the prefered polarity of the BLE event in progress signal:

/****************************************************************************************************************/
/* WLAN coexistence mode: Enable/disable the mode.                                                              */
/****************************************************************************************************************/
#define CFG_COEX

/****************************************************************************************************************/
/*  WLAN coexistence mode: Enable/disable the debugging signals.                                                */
/****************************************************************************************************************/
#define CFG_WLAN_COEX_DEBUG

/****************************************************************************************************************/
/* WLAN coexistence mode: Controls the polarity of the BLE event in progress signal.                            */
/* - defined: BLE event in progress signal is active low.                                                       */
/* - undefined: BLE event in progress signal is active high.                                                    */
/****************************************************************************************************************/
#undef CFG_WLAN_COEX_BLE_EVENT_INV
  • The following source file must be added to the project:

    • wlan_coex.c comprise the WLAN coexistence feature implementation and reside in <sdk_root_directory>\sdk\platform\driver\wifi. The files can easily be added by right click on the corresponding folder and select the Add Existing files to Group… option.

  • The following include path must be added to the project. Click on the Options for Target… and then in the C/C++ tab. In the include Paths field add the wifi folder that holds the wlan_coex.h file.

../_images/wlan_coex_include_path.png

Figure 77 WLAN COEX include path

  • In user_periph_setup.h the following block of definitions should be added for WLAN coexistence pin mapping:

/****************************************************************************************/
/* WLAN COEX pin configuration                                                          */
/****************************************************************************************/

#if (WLAN_COEX_ENABLED)
#if defined (__DA14531__)

   /// Input signal to device: 2.4GHz external device event in progress indication.
   #define WLAN_COEX_24G_EIP_PORT      GPIO_PORT_0
   #define WLAN_COEX_24G_EIP_PIN       GPIO_PIN_5

   /// Output signal from device: BLE event in progress indication.
 #define WLAN_COEX_BLE_EIP_PORT      GPIO_PORT_0
 #define WLAN_COEX_BLE_EIP_PIN       GPIO_PIN_6

   /// Output signal from device: BLE priority indication.
   #define WLAN_COEX_BLE_PRIO_PORT     GPIO_PORT_0
   #define WLAN_COEX_BLE_PRIO_PIN      GPIO_PIN_7

#if defined (CFG_WLAN_COEX_DEBUG)
   /// BLE radio overruled signal pin definition.
   /// This signal goes high when the BLE radio is forced to be off due to external 2.4GHz device activity.
   #define WLAN_COEX_DEBUG_A_PORT      GPIO_PORT_0
   #define WLAN_COEX_DEBUG_A_PIN       GPIO_PIN_9

   /// External 2.4GHz device EIP handler signal pin definition.
   /// This signal indicates when an external 2.4GHz device wants to start or stop sending data.
   #define WLAN_COEX_DEBUG_B_PORT      GPIO_PORT_0
   #define WLAN_COEX_DEBUG_B_PIN       GPIO_PIN_8
#endif

#else

   /// Input signal to device: 2.4GHz external device event in progress indication.
   #define WLAN_COEX_24G_EIP_PORT      GPIO_PORT_0
   #define WLAN_COEX_24G_EIP_PIN       GPIO_PIN_0

   /// Output signal from device: BLE event in progress indication.
   #define WLAN_COEX_BLE_EIP_PORT      GPIO_PORT_0
   #define WLAN_COEX_BLE_EIP_PIN       GPIO_PIN_3

   /// Output signal from device: BLE priority indication.
   #define WLAN_COEX_BLE_PRIO_PORT     GPIO_PORT_0
   #define WLAN_COEX_BLE_PRIO_PIN      GPIO_PIN_2

#if defined (CFG_WLAN_COEX_DEBUG)
   /// BLE radio overruled signal pin definition.
   //  This signal goes high when the BLE radio is forced to be off due to external 2.4GHz device activity.
   #define WLAN_COEX_DEBUG_A_PORT      GPIO_PORT_0
   #define WLAN_COEX_DEBUG_A_PIN       GPIO_PIN_1

   /// External 2.4GHz device EIP handler signal pin definition.
   /// This signal indicates when an external 2.4GHz device wants to start or stop sending data.
   #define WLAN_COEX_DEBUG_B_PORT      GPIO_PORT_1
   #define WLAN_COEX_DEBUG_B_PIN       GPIO_PIN_3
#endif

#endif

// GPIO IRQ number. Interrupt is fired when 2.4GHz external device event in progress signal is activated.
#define WLAN_COEX_IRQ            4

#endif // WLAN_COEX_ENABLED
  • In user_periph_setup.c make the following changes in order to enable properly WLAN coexistence feature:

  • Add the required include file. Include wlan_coex.h in the Include Files section.

#if (WLAN_COEX_ENABLED)
#include "wlan_coex.h"
#endif
  • Add the following global variable definition (configuration struct for WLAN coexistence):

#if (WLAN_COEX_ENABLED)
// Configuration struct for WLAN coexistence
const wlan_coex_cfg_t wlan_coex_cfg = {
   .ext_24g_eip_port = WLAN_COEX_24G_EIP_PORT,
   .ext_24g_eip_pin = WLAN_COEX_24G_EIP_PIN,
   .ble_eip_port = WLAN_COEX_BLE_EIP_PORT,
   .ble_eip_pin = WLAN_COEX_BLE_EIP_PIN,
   .ble_prio_port = WLAN_COEX_BLE_PRIO_PORT,
   .ble_prio_pin = WLAN_COEX_BLE_PRIO_PIN,
#if defined (CFG_WLAN_COEX_DEBUG)
   .debug_a_port = WLAN_COEX_DEBUG_A_PORT,
   .debug_a_pin = WLAN_COEX_DEBUG_A_PIN,
   .debug_b_port = WLAN_COEX_DEBUG_B_PORT,
   .debug_b_pin = WLAN_COEX_DEBUG_B_PIN,
#endif
   .irq = WLAN_COEX_IRQ,
};
#endif
  • Reserve GPIOs used by the module by adding the following block of code inside GPIO_reservations() function:

#if (WLAN_COEX_ENABLED)
   RESERVE_GPIO(COEX_EIP, wlan_coex_cfg.ble_eip_port, wlan_coex_cfg.ble_eip_pin, PID_GPIO);
   RESERVE_GPIO(COEX_PRIO, wlan_coex_cfg.ble_prio_port, wlan_coex_cfg.ble_prio_pin, PID_GPIO);
   RESERVE_GPIO(COEX_REQ, wlan_coex_cfg.ext_24g_eip_port, wlan_coex_cfg.ext_24g_eip_pin, PID_GPIO);

#if defined (CFG_WLAN_COEX_DEBUG)
   RESERVE_GPIO(DEBUGPIN1, wlan_coex_cfg.debug_b_port, wlan_coex_cfg.debug_b_pin, PID_GPIO);
   RESERVE_GPIO(DEBUGPIN2, wlan_coex_cfg.debug_a_port, wlan_coex_cfg.debug_a_pin, PID_GPIO);
#endif
../_images/changes_in_GPIO_reservations_function.png

Figure 78 Changes in GPIO_reservations() function

  • Call wlan_coex_gpio_cfg() function at the end of set_pad_functions() to initialize GPIOs used by the module and to configure 2.4GHz external device event in progress signal to act as a GPIO interrupt.

#if (WLAN_COEX_ENABLED)
   wlan_coex_gpio_cfg();
#endif
../_images/changes_in_set_pad_functions.png

Figure 79 Changes in set_pad_functions()

  • Last but not least, it should be mentioned that the following changes are required in user_proxr.c in order to initialize the WLAN-BLE coexistence mode and set the BLE priority over the WLAN module.

  • Add the required include files. Include wlan_coex.h and lld.h in the Include Files section.

#if (WLAN_COEX_ENABLED)
#include "wlan_coex.h"
#include "lld.h"
#endif
  • Call inside user_on_init() the following functions:

    • wlan_coex_init() in order to initialize the WLAN-BLE coexistence mode;

    • wlan_coex_prio_criteria_add() function to configure the rules for the WLAN coexistence feature.

#if (WLAN_COEX_ENABLED)
   wlan_coex_init();

   // Adds priority case for a specific connection
   wlan_coex_prio_criteria_add(WLAN_COEX_BLE_PRIO_ADV, LLD_ADV_HDL, 0);
#endif
  • Finally call wlan_coex_going_to_sleep() function inside user_validate_sleep() in order to prepare WLAN COEX mode for going to sleep.

#if (WLAN_COEX_ENABLED)
   wlan_coex_going_to_sleep();
#endif
../_images/changes_in_user_proxr_file.png

Figure 80 Changes in user_proxr.c file