Skip navigation
Home > All Places > WICED Studio Bluetooth > WICED Studio Bluetooth Forums > Blog > Authors RanjithK_41

CYW20719 Memory Layout

Posted by RanjithK_41 Jan 31, 2018

The memory layout for the CYW20719 is shown in Figure 1.

  • ROM
    • 2 Mbytes of ROM hosts the core firmware and various stack layers. The inclusion of core firmware, stack layers, and various libraries in the onboard ROM allow for most of the flash and RAM to be used for data and application code.
  • RAM
    • 512 Kbytes of RAM provide data storage and the ability to execute patch and application code.
  • OCF (On Chip Flash)
    • 1 Mbyte of flash provides storage for configuration data and application code. The OCF supports direct execution of application code.
  • AON (Always ON) Memory:
    • Stores Bluetooth states and connection related parameters when the device goes into its lowest power state.


Figure 1: Memory Layout of CYW20719


Typical Resource Utilization:

    The RAM requirement for application code space varies depending on the application use case and the profiles in use. For example, if the required profile stack is already part of ROM, then WICED uses it from ROM automatically.

The following table provides an approximate ballpark guidance on the available memory with a few of sample applications provided in WICED Studio.


Free RAM


~240 KB


~200 KB


~207 KB


~244 KB


~167 KB


(Freetronic 128x128 OLED Module)

~206 KB

Table 1: Typical RAM Utilization by various applications


Note: Typical MIPS utilization with the Headset sample application is 50% @48MHz.

The Analog to Digital Converter (ADC) block in CYW20719 and CYW20735 is a single-ended switched-cap sigma-delta ADC with 12 bits for Audio* measurements and 10 bits for DC measurements. The ADC has 32 DC input channels including 28 GPIO inputs.

The following pins can be programmed as ADC inputs in CYW20719 QFN40:

     P0, P1, P8–P19, P21–P23, P28–P38.

The following pins can be programmed as ADC inputs in CYW20735 QFN60:

      P0-P14, P16, P26-29, P32,P34,P38

For Audio* applications, the ADC uses a Programmable-Gain Amplifier (PGA) to control the gain.

The CYW20719 and CYW20735 supports two modes of operation: DC measurement mode and Audio mode*. Referefer to the datasheet for more details on supply voltage.


  *Note: The Audio mode (micn and micp pins) is not available in the 40 pin QFN package of the CYW20719.


1.1.  ADC Block Diagram

Figure 1: Block Diagram of CYW20719's ADC

1.2.  DC Measurement Mode

The DC Measurement mode refers to single-ended voltage measurement on an input pin referenced to ADC ground. From the ADC’s block diagram, 28 GPIO channels, VDDIO, VDDC, ADC_BGREF, and ADC_REFGND are multiplexed and fed into the switched-cap sigma-delta ADC.

The wiced_hal_adc_set_power() API allows the program to power up or power down the ADC.

The wiced_hal_adc_init() API initiates the necessary registers required for the ADC operation. The ADC needs to be initialized if the ADC has been powered down in specific low power modes.

2. ADC Output Data and Clock Timing

The ADC clock input is 24 MHz which is divided internally in the ADC hardware to operate at 12 MHz. The typical conversion rate is 100 kHz and the minimum conversion rate is 50 kHz for static measurements of the ADC. The practical time for reading DC voltages after ADC initialization is approximately 150 microseconds. Similarly, the practical time for reading DC raw samples from the ADC is approximately 50 microseconds. This conversion rate roughly translates to a range in between 16ksps and 20ksps(kilo samples per second). This reduction in conversion rate is because the firmware does filtering and averaging of sampled values for better accuracy.

3. ADC Input MUX Clocking in DC Measurement Mode

The ADC requires up to 2 microseconds to settle after switching of the DC input channels. It takes approximately 20 microseconds for the ADC REF to settle after powering up the ADC. The ADC DC input MUX should be held constant for 10 microseconds to 20 microseconds until the DC measurement is finished. This is taken care internally by the APIs. The ADC_DC_MUX_clk is the timing clock on the digital side to synchronize the DC input channel switching and measurement.

Figure 2: Timing Diagram of ADC

4. ADC Gain Calculation

The wiced_hal_adc_read_voltage() API allows the program to read the analog voltage from the ADC. The ADC must be initialized before reading the ADC voltage or else the function call will return 0. All read function calls to ADC registers are blocking. The ADC input and ADC output gain relation in the DC measurement mode can vary due to the following parameters:

  1. When the ADC input range is set to 0 to 1.8 V mode by calling wiced_hal_adc_set_input_range(ADC_RANGE_0_1P8V).
  2. When the ADC input range is set to 0 to 3.6 V mode by calling wiced_hal_adc_set_input_range(ADC_RANGE_0_3P6V).

CYW20719 supports SPI interface to communicate with other SPI devices. This block can be used to communicate with SPI-based sensors such as temperature sensors, motion sensors, and so on. The SPI blocks support the following features:

  • Three-wire (master) and four-wire (master and slave) SPI interface
  • Master and slave modes
  • Configurable SCK polarity and phase
  • Configurable LSB- or MSB-first transfer
  • 1024 byte transmit buffer and 1024 byte receive buffer (shared with HCI UART)


CYW20719 provides SPI APIs to choose between 2 SPI Hardware blocks. spi_interface_t allows the programmer to choose between SPI1 and SPI2. Each of the SPI Utility APIs will have an argument to choose between the 2 SPI blocks.


The SPI  block can be used as a generic master or a generic slave. Any LHL GPIOs can be used for the SPI interface. ModusToolbox provides a list of parameters and APIs to access the SPI 1 driver. click Help > ModusToolbox API Reference > WICED API Reference in ModusToolbox IDE and navigate to Peripheral SPI section under components > Hardware Drivers.

The SPI  block can be initialized in the required configuration using the function wiced_hal_pspi_init().


1.1.  Generic Slave Operation


TX operation

As a generic slave, data is transferred to the host when:

  1. There is data in the TxFIFO
  2. The TxFIFO is enabled
  3. The host toggles SPI_CLK and SPI_CSN is asserted

If condition (1) is false, but conditions (2) and (3) are true, a data underflow condition occurs.  The transmit APIs can place data in the TxFIFO. The wiced_hal_pspi_slave_tx_data() API can be used to transmit the data.

RX operation

As a generic slave, data is received from the host when:

  1. There is space in the RxFIFO
  2. The RxFIFO is enabled
  3. The host toggles SPI_CLK and SPI_CSN is asserted

If condition (1) is false, but conditions (2) and (3) are true, a data overflow condition occurs. Data can be retrieved from the RxFIFO using manual firmware reads. The wiced_hal_pspi_slave_rx_data() API can be used to receive the data.


1.2.  Generic Master Operation


In generic master mode, it is up to the firmware to assert the CS to various peripherals. The CS and INT pins can be used as GPIOs when in master mode. Three types of master transactions are available.


When data only needs to be sent, the SPI block is in TX-Only mode.  In this mode:

  1. TxFIFO must be enabled
  2. RxFIFO must be disabled

In this configuration, the SPI block will transmit any data placed in the TxFIFO.  Data can be placed in the TxFIFO using manual FW writes. The wiced_hal_pspi_tx_data() API can be used to transmit the data as a master.

When the TxFIFO becomes empty, SPI_CLK is paused at a byte boundary until more data is placed in the TxFIFO.  No data is stored in the RxFIFO.


When data only needs to be received, the SPI block is in RX-Only mode.  In this mode:

  • TxFIFO must be disabled
  • RxFIFO must be enabled

In this configuration, the SPI block will retrieve TransmissionLength bytes from the slave.  Data can be retrieved from the RxFIFO using manual firmware reads. The wiced_hal_pspi_rx_data() API can be used to receive the data as a master.

The data stream will be paused if the RxFIFO becomes full. The data stream will resume when there is space in the RxFIFO. No data is sent in this mode.


When data needs to be sent and received simultaneously, the SPI block is in full-duplex mode.  In this mode:

  • TxFIFO is enabled
  • RxFIFO is enabled

In this configuration, the SPI block will transfer data to both FIFOs if there is:

  1. Space in  RxFIFO
  2. Data in TxFIFO

If either of these conditions becomes false, SPI_CLK is paused until both conditions become true again. The wiced_hal_pspi_exchange_data() API can be used to send and receive data simultaneously.


Note: Since SPI and HCI UART use the same buffer, they cannot be used together.

This device has two UART blocks: PUART and HCI UART (BT_UART).

1. PUART (Peripheral UART)

CYW20719’s and CYW20735's PUART can be used to interface with peripherals. CYW20719 and CYW20735 can map the peripheral UART to any LHL GPIOs. The PUART is clocked at 24 MHz. Both PUART RX and PUART TX have a 256 byte FIFO.

PUART has the following features:

  • 8-bit transfer up to 3 Mbps
  • 9-bit transfer including stop bit up to 2.5 Mbps
  • Configurable flow control
  • Interrupt functionality on receive operation

PUART Initialization

The wiced_hal_puart_init() API in wiced_hal_puart.h is used to initialize the PUART block. The wiced_hal_puart_select_uart_pads() API can be used to select TX/RX and optional CTS/RTS pins for the PUART hardware to use.

Figure 1: Data Framing Format

PUART Baud rate

The default PUART baud rate is 115200. The wiced_hal_puart_set_baudrate() API is used to set the baud rate. Typical rates are 115200, 921600, 1500000, and 3000000 bps, although intermediate speeds are also available. For more details on the baud rate, see the datasheet.

PUART Transmit

The wiced_hal_puart_enable_tx() and wiced_hal_puart_disable_tx() APIs enable or disable transmit capability of the PUART, respectively.

The wiced_hal_puart_print() API is used to send a string of characters via the TX line.

The wiced_hal_puart_write() API is used to send one byte via the TX line.

PUART Receive

The wiced_hal_puart_enable_rx() API is used to enable receive capability.

The wiced_hal_puart_rx_fifo_not_empty() API is used to check if there are any data available in the RX FIFO.

PUART Flow control

The wiced_hal_puart_flow_on() and wiced_hal_puart_flow_off() APIs enable or disable the flow control of PUART, respectively.

PUART for RX Interrupt Operation

The wiced_hal_puart_set_watermark_level() API updates the watermark level with the specified value. The default hardware flow control watermark level is 4 which is set during PUART initialization. This value determines the number of bytes required in the RX FIFO before an interrupt is generated.

The wiced_hal_puart_register_interrupt() API is used to register the interrupt handler for the PUART RX.

The wiced_hal_puart_reset_puart_interrupt() API is used to clear and reenable the PUART RX interrupt.



This UART is used for HCI transport for the controller mode and is also used for programming the device. The HCI UART signals are fixed to specific I/O pads.

To understand the programming sequence over the HCI UART interface, see ${INSTALLDIR}libraries\bt_sdk-x.x\docs\BT-SDK\WICED-HCI-Control-Protocol.pdf.


Note: Since SPI 1 and HCI UART share the same FIFO buffer; they cannot be used together.

The CYW20719 and CYW20735 provides one I2C compatible master interface to communicate serially with I2C slave devices.

The I2C module features includes support for: 

  • 7-bit addressing mode.
  • Clock stretching as a master.
  • 100 kHz (Standard Mode), 400 kHz (Fast Mode), 800 kHz (Proprietary), and 1 MHz (Fast Mode+) SCL clock frequencies.
  • Multi-slave operation.


1.  I2C Clock

The I2C clock SCL is provided by the master on the I2C bus. When the I2C module is in master mode, the serial clock generator generates the SCL clock from the transport clock of 24 MHz. The wiced_hal_i2c_set_speed() function allows you to set the clock rate of SCL to any of the speeds listed in the introduction. The I2C block has 64 bytes of RX and TX FIFO for the transaction buffer, and thus each I2C transaction payload can be a maximum of 64 bytes.

Example frequencies for a 24-MHz system clock are given in the enum values description. The I2CM_SPEED_100KHz is set to 240 which is the dividing parameter, that is, when 24,000,000 divided by 240, it results in 100 kHz. Trying to use Multi-master will result in undefined behavior because the clocks from two or more masters will not be synchronized. Also, note that the proprietary 800 kHz mode is not expected to work on all I2C slaves. The wiced_hal_i2c_get_speed() function allows you to get the current clock frequency of the I2C block.


2.  I2C Initialization

The I2C module registers are initialized by calling wiced_hal_i2c_init() from wiced_hal_i2c.h. This function call initializes the I2C driver and its private values. It is required to call the above function before using I2C as some modules can turn this off for power saving. This function call ensures that the clock signal to this hardware block is turned on with the default SCL clock frequency of 100 kHz. Therefore, the wiced_hal_i2c_set_speed() function must be called after the wiced_hal_i2c_init() function if you want to use a speed other than 100 kHz.


3.  I2C Operations

The I2C Master module supports two modes of operations: Master write and Master Read. The modes are discussed in the following sections.

I2C Master Write

The wiced_hal_i2c_write() function writes data to the I2C hardware addressing a slave address. Although any arbitrary length of data may be written to the slave, atomic transactions greater than the hardware's capability are not possible and the data will be split into multiple transactions. This is a blocking call.  The I2C module waits until the I2C bus is free and then, it generates a START condition, transmits the 7-bit slave address followed by a 0 for write cycle's address phase. If there is an acknowledge returned, the I2C master will then start to transmit the data.

I2C Master Read

The wiced_hal_i2c_read() function reads data into the given buffer from the I2C hardware addressing a particular slave address. This is a blocking call. The I2C module waits until the I2C bus is free. When the I2C bus is free, it generates a START condition, sends the slave address, and transfers a receive direction bit. It then generates an interrupt, and the first byte is received. The I2C Master will release the SDA line for the slave device to transmit data only if it receives an acknowledge bit after it transmits the direction bit.

I2C Master Combined Write and then Read

The wiced_hal_i2c_combined_read() function executes a write transaction followed by a read transaction with a repeated start condition between the first and the second. In the first transaction, data is written to the slave address and after the repeated start, data is read from the slave in the second transaction. This operation is usually used to read a slave device's registers with the first write transaction specifying the slave's register address that needs to be read.


4.  I2C Bus Error

If the I2C master read or write operation is successful, the corresponding function will return I2CM_SUCCESS. When an attempted I2C operation fails because of no acknowledgement from the slave, I2CM_OP_FAILED is returned and the SDA and SCL lines are released (the STOP condition is not transmitted). I2CM_BUSY is returned when the I2C hardware block is busy with another transaction.

The CYW20719 and CYW20735 devices have two types of GPIOs: 40 LHL GPIOs and 8 Arm GPIOs.


The number of LHL GPIOs and Arm GPIOs available in the device depends on the package. For example, CYW20719 QFN 40 has 16 LHL GPIOs  whereas CYW20735 QFN60 has 23 LHL GPIOs.


LHL GPIOs are different from Arm GPIOs in few ways. LHL GPIOs can operate in low power modes and support mux-able peripherals, whereas Arm GPIOs can operate only in active mode with limited functionality. The functionalities that can be brought out to LHL I/Os are I2C, SPI, PUART, ACLK., and so on.


The wiced_hal_gpio_select_function() API can be used to map the functionality to specific pins.


Both LHL and ARM GPIOs are enumerated in wiced_bt_gpio_numbers_t() list in wiced_hal_gpio.h.


Though the SDK offers configuring all the I/Os, the selection of pins in an application needs to be made based on the following constraints with respect to the device:

  • Certain functionalities (for example, ADC input) are supported only on specific LHL I/Os and cannot be routed to other pins.
  • Only pins P26, P27, P28, and P29 can drive higher current compared to other pins. Refer to the datasheet for more details.
  • Some of the package pins are double or triple bonded with multiple I/O pads; therefore only one of the bonded pins can be used at a time.
  • P19, P20, and P39 are reserved for system use, and cannot be used in applications.


For using any pin as a generic GPIO, see the GPIO driver section by navigating to Hardware drivers in Components.

click Help > ModusToolbox API Reference > WICED API Reference in ModusToolbox IDE.

Using the driver, the pins can be set up as outputs, as inputs with optional pull-up, or as 16 mA or 8 mA drive-strength outputs on the device.


The WICED SDK has a SuperMUX pin selector utility to guide the pin selection for product designs.

The block diagram in Figure 1 shows the software architecture of the Bluetooth/BLE components and protocol layers, the partitioning of the components across ROM, and RAM/OCF (On-Chip Flash).


The CYW20719 ROM firmware runs on a real-time operating system and handles the programming and configuration of all on-chip hardware functions. This includes the BT/LE baseband, LM, HCI, GATT, ATT, L2CAP, and SDP layers. The ROM includes drivers for on-chip peripherals. In addition, the ROM includes on-chip power management functions including transitions between different power modes.


The application code runs in its own thread context from RAM or OCF and accesses the Bluetooth/BLE components via WICED BT APIs. The application code accesses the OS and peripheral drivers via WICED APIs. For a complete list of the supported APIs, see


For a complete list of sample applications, see the

CYW20719 implements support for building an application to execute in-place (XIP) from OCF. This XIP feature is helpful for applications with large code size and limited RAM constraints. By placing the application and the profile library code in flash, the application can save RAM to that extent. The .text (code) section and rodata (read-only data) section from the application and the profile libraries execute from the OCF. The remaining sections get loaded to SRAM. Patches will be executed from patch RAM.


Executing the code from FLASH will have an impact on the speed and power. So, time critical functionality should not be included in the XIP section.

For more details on the XIP feature, see the CYW20719 – XIP Support User Guide.

ModusToolbox provides an over-the-air firmware upgrade feature for CYW20719. For complete details see OTA Firmware Upgrade documentation



Figure 1: Software Architecture

CYW20719 and CYW20735 have multiple clock dividers and PLLs routed to several high-speed and low-speed peripherals. There are basically two types of clocks on the device: high-frequency and low-frequency clock sources.


High-frequency clock sources:

     This clock is derived from an external 24 MHz crystal oscillator  using internal PLLs to upscale the frequency.

  • HCLK: This clock powers the Resource Processing Unit (RPU). The RPU includes CM4, Floating-point Unit (FPU), and DMA Controller. This HCLK's frequency can range between 1 MHz and 48 MHz.
  • BT Core Clock: This clock powers the Bluetooth RF hardware. This BT Core's clock frequency can range between 1 MHz and 48 MHz.
  • PTU Clock: This clock powers the Peripheral Transport Unit (PTU) which includes SPI, I2C, UART, PCM, and Random Number Generator. This PTU's clock frequency can either be  24 MHz or 48 MHz. The peripherals will internally divide the clock frequency for their specific purpose. For example, the I2C master clock (SCL) can range between 100 kHz and 1 MHz.
  • The application timer (dual-input 32-bit timers) is clocked at 1 MHz.

Low frequency clock sources:

     There are three lean high land (LHL) low power oscillators (LPOs) available. They are LP-LPO (32 kHz), HP-LPO (32 kHz), and XTAL32K (32 kHz). The firmware decides which clock source to use among the available LPOs depending on the accuracy and power requirements. It is recommended to use an external 32.768 kHz crystal oscillator with low error PPM to improve the clock accuracy and lower average current consumption in Sleep, Power Down Sleep (PDS), or Shut-Down Sleep (SDS) mode. The firmware assumes the external LPO has lower (less than 250 PPM) error with little or no jitter.


1.1.  Real Time Clock (RTC)

The CYW20719 and CYW20735 supports a 48-bit RTC timer running on the 32-kHz crystal (XTAL32K) LPO. If an external LPO is not connected to CYW20719, then the firmware takes the clock input from the internal LPO for the RTC. WICED Studio provides APIs to set the current time, get the current time, or convert the current time value to a string. By default, the date and time are set to January 1, 2010 with a time of 00:00:00 denoting HH: MM: SS. It is mandatory to set the oscillator frequency to 32 kHz with the provided APIs when a 32-kHz external LPO is used. The RTC configuration structure (RTCconfig) has two member variables oscillatorFrequencykHz and rtcRefClock whose values must be set to RTC_REF_CLOCK_SRC_32KHZ.


1.2.  Watchdog

The Watchdog module in CYW20719 and CYW20735 is based on a 32-bit down counter that is used to detect and recover from malfunctions. During normal operation, the device regularly resets the watchdog timer before the count value reaches zero to prevent it from elapsing, or “timing out”. If, due to a hardware fault or program error, the device fails to reset the watchdog, the timer will elapse and generate a system reset on time out. The process of restarting the watchdog timer’s counter is referred to as “kicking or petting the dog”.

WICED Studio provides limited debugging functionalities via the watchdog timer. The default watchdog timeout is set to 2 seconds and watchdog petting is done in the idle thread. Production applications need not pet the watchdog. When the watchdog expires, the system will reset after a core-dump. The core-dump contains the following information: device firmware or hardware version, warning-flag, memory info, CPU/HW registers, SRAM, and Patch RAM image. The core dump is sent over the HCI-UART as BT-HCI vendor specific events.

  • wiced_hal_wdog_disable()
  • wiced_hal_wdog_reset_system()
  • wiced_hal_wdog_restart()

1.3.  Application Timers

CYW20719 and CYW20735 provides one general-purpose 32 bit dual-input timer. The firmware uses the 2 x 32-bit timers as a 1 x 64-bit timer. WICED Studio provides APIs to use the timer functionality. The timer supports two modes of operation:

  • Periodic Interrupt mode
  • Single-shot mode

The WICED API provides four timer types:


The two periodic timers mentioned above are triggered every time the timer count reaches zero whereas the other two timers are single-shot.

The wiced_init_timer() API initializes the timer. It allows you to specify the callback function to be invoked when the timer expires. This API also allows you to specify timer type that should be used. This API does not start the timer.

The wiced_start_timer() API is used to start the count down. The wiced_stop_timer() API can be used to stop the timer.

The wiced_is_timer_in_use() function allows you to know if the specified timer is currently in use by returning a Boolean value.

1.3.  Pulse Width Modulator(PWM)

There are six 16-bit Hardware PWM channels available in CYW20719 and CYW20735. The PWM of CYW20719 and CYW20735 is not glitch-free. The clock frequency of each PWM can be configured in one of the two ways. The LHL_CLK or PMU_CLK can be used as the clock source for the PWM. If the clock source is the LHL_CLK, then the clock frequency will be 32 kHz or 128 kHz based on the LHL clock priority. The PMU_CLK requires the auxiliary clock to be configured first. When configuring the auxiliary clock, ACLK0 is not available for use with the PWMs. Hence, ACLK1 is the only available PMU_CLK running at 24 MHz or at 1MHz using internal clock division. The wiced_hal_aclk_enable() function in wiced_hal_aclk.h enables the auxiliary clock and allows the functionality of choosing either 1 MHz or 24 MHz for routing to the PWMs.

The wiced_hal_pwm_start() function configures, enables, and starts the PWM and also routes it to a preconfigured GPIO pin. The desired GPIO pin must be configured as an output before configuring it for use with a PWM. Each PWM channel can be routed to GPIO pins using the SuperMUX. See the datasheet for more details. This function takes in 5 parameters (i.e., channel, clock source, toggle count, initial count and invert signal). The channel refers to PWM channels 0 to 5. The clock source can be either LHL_CLK or ACLK1 (PMU_CLK). The toggle count refers to the number of ticks to wait before toggling the signal. The initial count is the initial value of the register. The invert signal can be either 1 or 0. If the invert signal is 1, the PWM output starts HIGH and if the invert signal is 0, the PWM output starts LOW.

The wiced_hal_pwm_change_values() function changes the PWM settings such as toggle count and initial count of a specific PWM channel after the PWM hardware block has already been started.

The wiced_hal_pwm_configure_pin() function can be used to map any LHL GPIO to the specified PWM channel.

The wiced_hal_pwm_get_params() is a helper function that calculates the PWM parameters. This function takes in three parameters: input clock frequency, duty cycle, and desired PWM output frequency to determine the required initial count and toggle count. The initial count and toggle count is determined by the API using the following expression:

Initial count = 0xFFFF - (Input Clock Freq / PWM Freq out)

Toggle count = 0xFFFF - ((duty cycle in percentage) * (Input Clock Freq / PWM Freq out) / 100)

Filter Blog

By date:
By tag: