You are here

PSoC Creator News and Information | Cypress Semiconductor

Sep 13, 2017

PSoC FreeRTOS Task Notify

[re-printed from https://iotexpert.com]

I have been writing a bunch of articles about implementing PSoC FreeRTOS so, this morning I was reading the FreeRTOS manual (yes I am one of those…) and I noticed a section in the API guide that I hadn’t see before… Task Notifications.  Every task in the FreeRTOS has a built in 32-bit integer notification value.  This value is super light weight and can be used like a task specific counting semaphore, or a signaling bit mask, or binary semaphore.  The API includes:

It seems like this API is good for the situations when your Semaphore has a specific task target in mind.  I thought that this would be a perfect scheme to have a PSoC FreeRTOS UART ISR signal the UART Handling task that there is data available to do something with.

Setup the PSoC FreeRTOS Project

I start this process by making a copy of “1-BlinkingLED” (which already has all of the FreeRTOS stuff in it) and naming it “9-TaskNotify”.  Then I add a UART to the schematic and name it “UART”

PSoC FreeRTOS Schematic

I attach the UART to the right pins on the CY8CKIT-044 kit.

PSoC Creator Pin Assignment

 

Next I turn on the interrupt which will be called when there is data in the receive FIFO.

PSoC UART Configuration

 

PSoC FreeRTOS UART Code

Now that the schematic is all configured I update my firmware.  The function “uartHandler” is called when there is data in the UART RX FIFO.  It turns of the interrupts for the UART (which I will turn back on after I have cleared the data in the input buffer), clears the interrupt  (so that it will stop pending) and then sends the notification to the UART_Task.

The UART Task just registers the handler… then while(1)’s until the end of time.  It waits for a notification, then reads data out of the RX fifo and puts out,  then re-enables the interrupts.

CY_ISR(uartHandler)
{
    BaseType_t xHigherPriorityTaskWoken;
 
    // disable the interrupt
    UART_SetRxInterruptMode(0);
    vTaskNotifyGiveFromISR(uartTaskHandle,&xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
 
void UART_Task( void *arg)
{
    (void)arg;
    char c;
    UART_Start();
    UART_SetCustomInterruptHandler(uartHandler);
    while(1)
    {
        ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
        while(UART_SpiUartGetRxBufferSize())
        {
            c = UART_UartGetChar();
            UART_UartPutChar(c);
        }
        // clear & re-enable the interrupt
        UART_ClearRxInterruptSource(UART_INTR_RX_NOT_EMPTY);
        UART_SetRxInterruptMode(UART_INTR_RX_NOT_EMPTY);
    }
}

 

Sep 12, 2017

Happy Programmer's Day!

On September 11, 2009, President of Russia Dmitry Medvedev declared a new professional holiday, Day of the Programmer. It falls on day number 256 of every year. It's probably better to say that it is day 0x100 or day 2^8 given the subject of the celebration. I am not sure what happens if the day falls on a суббота or Воскресенье. In leap years the holiday arrives a day early, of course, because Pope Gregory XIII did not think of adding the "extra day" at the end of the year. I've always wondered why leap days happen in February instead of December... but not quite enough to google it.

I am a big fan of holidays. I like what I do for a living but, I'll be honest, not doing it is a little bit better. I think that the guys who thought of it - Valentin Balt and Michael Cherviakov - did a great job, except they got the day wrong. If we're doing bitwise operations on the day number ("day & PROGRAMMERS_DAY") to decide if we should go to work then setting PROGRAMMERS_DAY to September 10th is a whole lot better... but maybe not for my boss.

Anyway, since I do not live in Russia, and I am not really a programmer, and my boss does not care about the result an implicit cast of a bitwise operation with 0xFF, I guess I should get back to work.

Sep 08, 2017

Percepio Tracealyzer - Running on PSoC 6

[re-printed from https://iotexpert.com]

I have been having an excellent experience with Percepio Tracealyzer on PSoC 4, so now, the next question is, “Will it work on PSoC 6?”  The answer is yes, but it takes a few gyrations.  In the next two Articles I will show you how to use Tracealyzer on PSoC 6 with:

  1. JLINK and Snapshot mode
  2. JLINK and Segger RTT in Streaming Mode
  3. A PSoC6 DMA –> UART Streaming Mode

In order to make these work you need to

  1. Make a new project and integrate the Trace Recorder Library
  2. Modify trcConfig.h
  3. Install the JLINK
  4. Build the project & test

Create a new PSoC6 project & Integrate the Trace Recorder Library

The process of integrating the TraceRecorder library is very similar to PSoC 4.  You need to add the include directories into your project.  Right click the project and pick “Build Settings…”

Build Settings…

 

Click on the “Additional Include Directories”

Additional Include Directories

 

Then add the two TraceRecorder include directory and the StreamPort include directory.

Add the TraceRecorder and StreamPort include directories

 

Next you should copy the configuration header files into your project so that you can edit them.  You can copy-paste them in Windows Explorer from “TraceRecorder/config” into your project

TraceRecorder/config

Next add the TraceRecoder .c and .h files into your project by right clicking “Add –>Existing Item..”

Add –>Existing Item..

 

You need the .c and .h files from

  • yourproject/{trcConfig.h, trcSnapshotConfig.h, trcStreamingConfig.h}
  • TraceRecorder/*.c
  • TraceRecorder/include/*.h
  • TraceRecorder/streamports/Jlink_RTT/include/*.h
  • TraceRecorder/streamports/Jlink_RTT/*.c

  

 

 

 

 

 

Modify FreeRTOSConfig.h & trcConfig.h

The next step is to modify FreeRTOSConfig.h to include the trace recorder header.   Copy this block of code into the bottom for FreeRTOSConfig.h

#if ( configUSE_TRACE_FACILITY == 1 )
#include "trcRecorder.h"
#endif

Update the FreeRTOSConfig.h to turn on tracing.

#define configUSE_TRACE_FACILITY                1

Then modify trcConfig.h to include the CMSIS Core headers.

/******************************************************************************
* Include of processor header file
*
* Here you may need to include the header file for your processor. This is
* required at least for the ARM Cortex-M port, that uses the ARM CMSIS API.
* Try that in case of build problems. Otherwise, remove the #error line below.
*****************************************************************************/
//#error "Trace Recorder: Please include your processor's header file here and remove this line."
 
#include "cy8c6347bzi_bld53.h"

The first time that I did this, I tried just #include <project.h> but if you do that you will end up with hundreds of errors and hours and hours of trying to figure out what is going on.  It turns out that the FreeRTOS is picky about the order in which files are included.  And when PSoC Creator makes the project.h it assumes that the order of includes doesn’t matter.  I fixed this by just including the “cy8c6347bzi_bld53.h” header which just? has the CMSIS files.

 

After fixing that mess, I modify the trcConfig to specify that I am using a Cortex-M processor (actually two of them)

/*******************************************************************************
* Configuration Macro: TRC_CFG_HARDWARE_PORT
*
* Specify what hardware port to use (i.e., the "timestamping driver").
*
* All ARM Cortex-M MCUs are supported by "TRC_HARDWARE_PORT_ARM_Cortex_M".
* This port uses the DWT cycle counter for Cortex-M3/M4/M7 devices, which is
* available on most such devices. In case your device don't have DWT support,
* you will get an error message opening the trace. In that case, you may
* force the recorder to use SysTick timestamping instead, using this define:
*
* #define TRC_CFG_ARM_CM_USE_SYSTICK
*
* For ARM Cortex-M0/M0+ devices, SysTick mode is used automatically.
*
* See trcHardwarePort.h for available ports and information on how to
* define your own port, if not already present.
******************************************************************************/
//#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_NOT_SET
#define TRC_CFG_HARDWARE_PORT TRC_HARDWARE_PORT_ARM_Cortex_M

I'll start the project just using Snapshot mode

/*******************************************************************************
* Configuration Macro: TRC_CFG_RECORDER_MODE
*
* Specify what recording mode to use. Snapshot means that the data is saved in
* an internal RAM buffer, for later upload. Streaming means that the data is
* transferred continuously to the host PC.
*
* For more information, see http://percepio.com/2016/10/05/rtos-tracing/
* and the Tracealyzer User Manual.
*
* Values:
* TRC_RECORDER_MODE_SNAPSHOT
* TRC_RECORDER_MODE_STREAMING
******************************************************************************/
#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT
//#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING

To start the testing I created a really simple, single task blinked led program in main_cm4.c. The only thing that you have to add is the “vTraceEnable(TRC_START)” to turn on the TraceRecorder.

#include "project.h"
 
void ledTask(void *arg)
{
    (void)arg;
    while(1)
    {
        Cy_GPIO_Inv(RED_PORT,RED_NUM);
        vTaskDelay(500);
    }
}
 
int main(void)
{
    __enable_irq(); /* Enable global interrupts. */
 
    vTraceEnable(TRC_START);
    xTaskCreate(ledTask,"LED Task",configMINIMAL_STACK_SIZE,0,1,0);
    vTaskStartScheduler();
}

Testing Percepio Tracealyzer

To start with I setup snapshot mode.  I wasn’t sure exactly what the memory map was for the new PSoC6.  But I did know that PSoC Creator copied in a linker file (actually 3 linker files) and that if I looked in the file I would find the memory map.

 

When I opened the GCC linker file “cy8c6xx7_cm4_dual.ld” I found the memory map for the chip.

MEMORY
{
    flash       (rx)    : ORIGIN = 0x10080000, LENGTH = 0x80000
    wflash            (rx)    : ORIGIN = 0x14000000, LENGTH = 0x8000          /*  32 KB */
    sflash_user_data  (rx)    : ORIGIN = 0x16000800, LENGTH = 0x800
    sflash_nar        (rx)    : ORIGIN = 0x16001A00, LENGTH = 0x200
    sflash_public_key (rx)    : ORIGIN = 0x16005A00, LENGTH = 0xC00
    sflash_toc_2      (rx)    : ORIGIN = 0x16007C00, LENGTH = 0x400
    xip               (rx)    : ORIGIN = 0x18000000, LENGTH = 0x8000000       /* 128 MB */
    efuse             (r)     : ORIGIN = 0x90700000, LENGTH = 0x100000        /*   1 MB */
    ram   (rwx) : ORIGIN = 0x08024000, LENGTH = 0x23800
}

To make read the Percepio Tracealyzer snapshot you need to select “JLink -> Read Trace (Snapshot)”.  When you do that, it asks you where the RAM is on that device.  I simply copy from the linker file the start and length of the RAM

 

After that I get the trace.

 

The next thing to do is modify the trcConfig.h to switch to streaming mode:

/*******************************************************************************
* Configuration Macro: TRC_CFG_RECORDER_MODE
*
* Specify what recording mode to use. Snapshot means that the data is saved in
* an internal RAM buffer, for later upload. Streaming means that the data is
* transferred continuously to the host PC.
*
* For more information, see http://percepio.com/2016/10/05/rtos-tracing/
* and the Tracealyzer User Manual.
*
* Values:
* TRC_RECORDER_MODE_SNAPSHOT
* TRC_RECORDER_MODE_STREAMING
******************************************************************************/
//#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_SNAPSHOT
#define TRC_CFG_RECORDER_MODE TRC_RECORDER_MODE_STREAMING

After I reprogram my CY8CKIT-062 BLE, then “File->Connect to Target System” I end up with a nice stream of data.

 

And when I look at the stream it says that things are working just as expected.

 

Im not sure what is next.  Maybe I will make a DMA/UART version so as not to require the JLKINK.

As always you can find all of these projects on the IotExpert GitHub site or git@github.com:iotexpert/PSoC-Tracelyzer.git

Sep 05, 2017

Percepio Tracealyzer - a PSoC DMA Streamport

[re-printed from https://iotexpert.com]

In the last Article I analyzed the performance problems of my firmware based PSoC Tracealyzer Streamport … which was terrible.  Although it has been a long time since I used the PSoC4M DMA engine, I knew that it would solve my problem.  In this article I'll show how to use the PSoC DMA, then Ill build and analyze a PSoC DMA Streamport for Tracealyzer.

PSoC4 UART DMA

The DMA block that shows up in the PSoC4200M, PSoC 4200L and PSoC 4 BLE is pretty amazing.  It can do a bunch of stuff.  Here is a snapshot that I took out of the TRM.  This block sits on the main AHB bus inside of the PSoC.  It can act as a master (see the block that says Master I/F) and read and write any of things in the ARM address space including the Flash, SRAM, and all of the peripherals.  It has an incoming trigger which can get the transfers going and when it is done it can trigger an interrupt or another DMA channel.  The Slave I/F allows the CPU to program the block.  The device has 8-channels with each channel having 2 descriptors (so it can ping pong).

PSoC4 DMA

 

Before I tried to make the PSoC DMA Streamport I started by looking at the example projects by pressing “File->Code Example”

PSoC Creator Example

 

Then filtering for DMA

PSoC Creator Example Project - DMA

 

Finally creating project.  This project uses two DMA channels, one for the UART receive and one for the UART Transfer.  It lets you type characters into the UART, it saves them in one of the RAM buffers, then when you have typed 8, it DMAs them back into the Transmit channel of the UART.  This example ping-pings back and forth between two RAM buffers.

PSoC Creator DMA Example

 

I decided that it would be best to build a bare metal DMA project called “test-uart” to prove that I understood.  This project will DMA transfer an array of characters to the UART when the user presses the switch on the board or a “s” on the keyboard.  The first thing to do is build the schematic with a UART, a DMA block,  two output pins, and input pin and an interrupt.

PSoC DMA Streamport

Place an SCB UART, then configure it (change the name, but accept all of the defaults)

PSoC Creator UART

 

Then click on the advanced tab.  Turn on the DMA for Transfer (TX Output) and set the “FIFO Level” to 7.  This will cause the UART to assert DMA signal anytime the transmit FIFO has less than 7 bytes.  In  other words … FEED ME!!!

PSoC Creator UART - Advanced setup

 

After configuring the UART, Set the PINs

PSoC DMA Streamport Pin Assignment

 

Next configure the DMA.  The memory array that I have will be “uint8_t” aka “char”.  So the input needs to be “bytes”.  The UART FIFO hold Words… aka 4 bytes.  So I need to configure the transfers to do “Byte to Word”.  After the DMA transfer is done, I setup the DMA to create an interrupt (so that I can reset everything in the CPU) and to invalidate the descriptor.

PSoC DMA Streamport

In the firmware works by

  • Turning on the UART
  • Enabling the DMA
  • Setting up the channel with the address of the buffer that I am going to write to (aka the TX FIFO) and asking for an interrupt

Then looping:

  • When the User presses “s” or the switch, I set myFlag to be 1.
  • If it is 1 and the channel is inactive, then initialize the “source” address, setup the number of transfer elements to be the number in my array, validate the descriptor, and turn on the channel.

When the channel turns on, the Tx fifo will be empty so it will assert the Tx Out, which will make the DMA keep triggering and copying 1 byte at a time into the FIFO.  While this is happening, the UART will try to empty the fifo by sending the bytes.  Finally when the DMA reaches the end of the RAM buffer, it will stop, and at some point the TX FIFO will finish emptying.  The DMA will trigger the interrupt to toggle the BLUE LED.  And the whole process can start again.

#include "project.h"
#include <stdio.h>
 
// A flag to trigger the DMA
volatile int myFlag=0;
  
static const char myArray[]="asdf1234asdfadsfasdfadsfqwerasdfqwerqwer9\n";
 
CY_ISR(sw_handler)
{
    myFlag = 1;
    SW_ClearInterrupt();
}
 
// This is called TWICE at the end of the DMA transaction
CY_ISR(myDMA)
{
    BLUE_Write(~BLUE_Read());
}
int main(void)
{
    CyIntEnable(CYDMA_INTR_NUMBER);
    CyGlobalIntEnable; /* Enable global interrupts. */
 
    char c;
    
    UART_Start();
    UART_UartPutString("Started\n");
  
    isr_1_StartEx(sw_handler);
  
    CyDmaEnable();
    
    DMA_Init();
    DMA_SetDstAddress(0, (void *)UART_TX_FIFO_WR_PTR);
    DMA_SetInterruptCallback(myDMA);
 
    while(1)
    {
        c = UART_UartGetChar();
        switch(c)
        {      
            case 's':
                myFlag = 1;
            break;
        }
        
        // This turns on the DMA so that the string will go to the UART.
        if(myFlag && CyDmaGetActiveChannels() == 0)
        {
            DMA_SetSrcAddress(0, (void *)myArray);
            DMA_SetNumDataElements(0,strlen(myArray)-1);
            DMA_ValidateDescriptor(0);
            DMA_ChEnable();
            myFlag=0;
        }
    }
}

PSoC DMA Streamport

Now that I understand how to use the DMA, I can create the PSoC DMA Streamport by copying the project “1-BlionkingLED_UART_TRACE” project and calling it “1-BlinkingLED_UART_TRCE_DMA”.  Next, add the DMA and modify the UART.

PSoC DMA Streamport

 

Configure the UART

PSoC DMA Streamport - UART Configuration

 

Turn on the UART DMA and set the level to 7

PSoC DMA Streamport - UART Configuration - Advanced setup

 

Configure the DMA Block

PSoC DMA Streamport Configuration

 

Make byte transfers and byte –> word.

PSoC DMA Streamport - DMA Configuration

 

Finally modify the trcStreamingPort.c – AKA the PSoC DMA Streamport file.  Specifically you need to fix up the PSoC_Transmit to send out the data when the TraceRecorder buffer is full.

  • If the DMA is busy… then wait until the previous transaction is done.
  • Then setup the DMA and let it rip.

int32_t PSoC_Transmit(void* data, uint32_t size, int32_t *numOfBytesSent )
{
    
    while( CyDmaGetActiveChannels()& DMA_CHANNEL_MASK);
    DMA_SetSrcAddress(0, (void *)data);
    DMA_SetNumDataElements(0,size);
    DMA_ValidateDescriptor(0);
    DMA_ChEnable();
 
    *numOfBytesSent=size;
    
    return 0; // Doesnt matter what you return... i dont think that it is checked
}

The only other thing that needs to happen is configure the DMA in main.c

CyDmaEnable();
DMA_Init();
DMA_SetDstAddress(0, (void *)UART_TX_FIFO_WR_PTR);

Testing the PSoC DMA Streamport

Now when I startup the Tracealyzer, here is what I get:

PSoC DMA Streamport - New CPU Load

It looks like I solved my problem because that is way way better than:

PSoC DMA Streamport - Terrible Performance

As always you can find all of these projects on the IotExpert GitHub site or git@github.com:iotexpert/PSoC-Tracelyzer.git

 

Aug 29, 2017

Percepio Tracealyzer - Analyzing the PSoC Tracealyzer Streamport

[re-printed from https://iotexpert.com]

In the previous article I showed you how to make a PSoC Tracealyzer Streamport using the SCB based UART on a PSoC 4200M. It didn’t take long for me to realize that 115200 baud was not going to cut it. That realization lead me to figure out that the KitProg on the CY8CKIT-044 was limited to 115200, which I worked around by using the Cypress USB Serial Bridge that I got from the CY8CKIT-049.  But when I look at the CPU graph I found out that it took 50% of the CPU to support streaming the data.  So now what?  In this Article lets analyze the data, both old school with a logic analyzer, and new school with PSoC Tracealyzer.

Analyzing the PSoC Tracealyzer Data

While I was capturing the streaming data from PSoC Tracealyzer I could see that the CPU was burning about 50% of the time just running the TzCntrl and blinking LED thread.  That isn’t good.

PSoC Tracealyzer

 

When you look at the PSoC Tracealyzer trace viewing you can see the problem is the TzCtrl task.  This task is running for 83 milliseconds and using 57.6% of the CPU.

PSoC Tracealyzer - analyzing the CPU Usage

 

If you look at the data transmit function called “PSoC_Transmit”, there isn’t much going on.  Just a call to UART_SpiUartPutArray.  But if you look at the UART documentation you will find that SpiUartPutArray is a blocking function, meaning it doesn’t return until it is done.  If you calculate the time to transfer a block of 1024 bytes at 8bits/byte and 230400 baud you will find that just sending the data takes 35ms.

int32_t PSoC_Transmit(void* data, uint32_t size, int32_t *numOfBytesSent )
{
    timing_Write(1);
    UART_SpiUartPutArray((uint8_t *)data,size);
    *numOfBytesSent=size;
    timing_Write(0);
    return 0; // Doesnt matter what you return... i dont think that it is checked
}

I was not very sure why the task was taking 83 milliseconds to run when the data transfer was only taking 40ms. To figure this out I added a toggle pin to the data write routine, just to make sure. What I found is the data write routine is getting called about every 70ms takes ~30ms to run.

Old school with Salae Logic

 

How is that possible, the calculation says that it should take 35ms.  It turns out that I configured the UART to have a 64 byte buffer.

PSoC Creator SCB Configuration

 

When you remove the 64 bytes from the calculation you end up with 32ish milliseconds.  The other thing that this chart shows is that the TzCntrl task is calling the PSoC_Transmit function more frequently that I thought, at least twice per cycle.  You can also see from the plot that function is taking 30/70=42.8% of the CPU by itself.  Not good, but we are starting to understand what is going on.

As I typed this part of the Article I realized that toggling a GPIO probably wasn’t the best way to figure out what was happening.  In fact, that is the whole point of Tracealyzer, that is analyzing the performance of your program.  When I looked at the Tracealyzer documentation (I always hate doing that), I found a nice function called vTracePrintf.  I added a “toggle” aka printing a 0 and printing a 1 into trace channel 0.

int32_t PSoC_Transmit(void* data, uint32_t size, int32_t *numOfBytesSent )
{
    timing_Write(1);
    vTracePrintF(0,"1");
    UART_SpiUartPutArray((uint8_t *)data,size);
    vTracePrintF(0,"0");
    timing_Write(0);
    *numOfBytesSent=size;
    
    return 0; // Doesnt matter what you return... i dont think that it is checked
}

After running another trace, look what I get.  You can see the “1” printing at the start and the 0 printing at the end.

PSoC Tracealyzer - Analyzing the CPU usage with vTaskPrintF

 

Even better, when I double clicked on the “[Default Channel] 0” it took me to this nice screen which shows when the events occurred.  The one that I clicked on started at 8.136.039 and ended at 8.176.176, in other words it took about 40ms

PSoC Tracealyzer - User events from Tracealyzer

 

After hand calculating the time, I realized that once again I should have done something even more obvious, let the ARM calculate the time.  the vTracePrintf will let you specify the output format, in this case a %d

int32_t PSoC_Transmit(void* data, uint32_t size, int32_t *numOfBytesSent )
{
    TickType_t time;
    
    timing_Write(1);
    
    time = xTaskGetTickCount();
    UART_SpiUartPutArray((uint8_t *)data,size);
    time = xTaskGetTickCount() - time;
    vTracePrintF(0,"%d",time);
    timing_Write(0);
    *numOfBytesSent=size;
    
    return 0; // Doesnt matter what you return... i dont think that it is checked
}

When you look at the trace, you need to click on the “User Events” to see the print outs from the trace.

PSoC Tracealyzer - CPU Usage

 

Now that we have a pretty good feel for what is going on, how do we fix it?  Simple, use the PSoC DMA take the CPU mostly out of the UART transmission path, which is the topic of the next Article.

As always you can find all of these projects on the IotExpert GitHub site or git@github.com:iotexpert/PSoC-Tracelyzer.git

 

ALL CONTENT AND MATERIALS ON THIS SITE ARE PROVIDED "AS IS". CYPRESS SEMICONDUCTOR AND ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF THESE MATERIALS FOR ANY PURPOSE AND DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THESE MATERIALS, INCLUDING BUT NOT LIMITED TO, ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT OF ANY THIRD PARTY INTELLECTUAL PROPERTY RIGHT. NO LICENSE, EITHER EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, IS GRANTED BY CYPRESS SEMICONDUCTOR. USE OF THE INFORMATION ON THIS SITE MAY REQUIRE A LICENSE FROM A THIRD PARTY, OR A LICENSE FROM CYPRESS SEMICONDUCTOR.

Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms and Conditions of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms and Conditions of this site. Cypress Semiconductor and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.