This post is part of my Roadtest Review of Cypress PSoC 62S2 Wi-Fi & BT5.0 Pioneer Dev Kit - Review. My review is splitted into multiple reviews and tutorials. Main page of review contains brief description of every chapter. Some projects are implemented in multiple variants. Main page of review contains brief description about every chapter, project and variants and contains some reccomendations for reading.

 

Table of Contents

 

 

Project 1 – Serial Interfaces

Project 1 is simple project in which I connect I2C temperature sensor HTU21D, reads temperature using them and prints it over UART. All articles and variants of this project are available as tutorials. I have used this to make opinions about Cypress platform and I reused these skills later when writing chapters with “Review” in name. This chapter is designed as tutorial, not a review. I have implemented this project in 4 ways:

  • In C and ModusToolbox IDE without using any library. Just accessing registers. I have done this to look how are some peripherals of MCU designed. If their design makes sense and If it is easy to use them. It shows how to setup clocks of the MCU, setup I2C, UART and Timer (TCPWM) and communicate over it. All just using raw registry access. For definition of registers, I am including PDL but otherwise solution shown in tutorial does not use any library.
  • In C and ModusToolbox IDE using PDL library provided by Cypress. This example features my library from github to control sensor and is based on PDL library provided by Cypress. Otherwise, it does the same as previous two variants, but it is hidden in library calls. This mainly shows how easy is to use library provided by Cypress.
  • In C and ModusToolbox IDE using HAL library provided by Cypress. This variant also does the same but uses HAL library provided by Cypress and shows how easy is to use this library.
  • In C and MBED Studio. Solution is based on MBED OS. This variant shows portable solution using MBED environment.

 

This is the last variant of the simple sensor project. It is implemented using MBED OS and MBED Studio development environment. This approach has some advantages. For example, It is very easy to program MCU in this way. It has also some disadvantages like very huge amount of software at background and limited possibility to optimize at low level. Cypress has ported MBED environment to support PSoC6. High-level features of MBED are internally implemented uses their HAL and PDL library. As a result of that for example port names are referenced in the same way as in the PDL and HAL libraries.

 

Create project in MBED Studio

 

Open MBED Studio and select File > New program.

 

  Then select the “empty Mbed OS program” as a template, enter project name, check that field “Make this the active program” is checked, selected “Store Mbed OS in the program folder (+1GB)” and confirm by Add Program.

 

Selecting correct I2C pins

Now, open the main.cpp file and let’s start coding. In the project I will use the HTU21DHTU21D which will be attached to the board using expansion port. I will use P9_1 as SDA and P9_0 as SCL. This choice is not random. Selected ports must have support for I2C which means that there must exists at least one Serial Communication Block (SCB) which’s signals can be connected to these ports using High Speed Input Output Matrix (HSIOM). These mappings are described in the datasheet (not a TRM) because they are device specific (partially they are family specific). In this case on the P9_1 and P9_0 is mapped SCB number 2.

 

 

If you select ports that has no I2C support entire MBED OS will crash at runtime. So, lets declare global variable for controlling I2C bus in the following way.

 

I2C i2c(P9_1, P9_0);

 

Communicating with sensor

 

Now we must write function which will read temperature using sensor. The function will do following I2C operations:

 

  • Start
  • Address (0x40 << 1) + Write (0)
  • Write command 0xE3
  • Repeated start
  • Address (0x40 << 1) + Read (1)
  • Read 3 bytes (2 bytes are encoded temperature and third is CRC)
  • Stop

 

There is no delay in transmission executed using MCU. The delay for the time that sensor needs to measure temperature is done by sensor sensor itself by holding line low after the execution of command while the measurement is in progress. This is valid I2C behavior. All the tasks described above are implemented using following code. At the end we will call two additional functions. One of them checks if CRC is valid and second one parses temperature to float. Function returns 0 on success, otherwise non-zero.

 

int ReadTemperature(float* temperature) {
    char command = 0xE3;
    char temperatureBuffer[3];
    int status;

    status = i2c.write(0x80, &command, 1, false);
    if (status) {
        return 1;
    }

    status = i2c.read(0x80, temperatureBuffer, 3, true);
    if (status) {
        return 1;
    }

    if (HTU21D_VerifyChecksum((uint8_t*)temperatureBuffer)) {
        return 1;
    }
    
    HTU21D_ParseTemperature(temperature, temperatureBuffer);
    return 0;
}

 

Functions HTU21D_VerifyChecksum , HTU21D_ParseTemperature are implemented in my library. Copy them from https://github.com/misaz/HTU21DLibrary/blob/master/src/HTU21D.c and remove underscore from the beginning of the name. Status codes of the results are defined using following constants (you can find them in HTU21D.h file in the library). Add them to the start of the file.

 

#define HTU21D_E_OK 0
#define HTU21D_E_TIMEOUT -1
#define HTU21D_E_ADDR_NACKED -2
#define HTU21D_E_BUS_ERROR -3
#define HTU21D_E_BAD_CRC -4

 

In main we will call the function in infinite loop and print measured temperature over UART (initialization of SCB for UART is done in the core of MBED OS). We will also light green RGB channel of RGB led in case of successful measurement and red in case of error.

int main() {
    printf("Initialization completed.\r\n");

    DigitalOut ledG(P0_5);
    DigitalOut ledR(P1_1);

    ledG = 1;
    ledR = 1;

    while (true) {
        float temperature;
        
        if (ReadTemperature(&temperature) == 0) {
            ledR = 1;
            ledG = 0;
            printf("Temperature is %.2f °C\r\n", temperature);
        } else {
            ledR = 0;
            ledG = 1;
            printf("Error while reading temperature.\r\n");
        }

        ThisThread::sleep_for(500ms);
    }
}

Floating point support in printf

 

Code that we have written works but has one issue. The MBED OS by default can’t print floats. If you want to print floats you need to enable support for that. You can do it by creating mbed_app.json file in the root directory of program (at the same level as main.cpp) with following content.

 

{
 "target_overrides": {
 "*": {
 "target.printf_lib": "minimal-printf",
 "platform.minimal-printf-enable-floating-point": true,
 "platform.minimal-printf-set-floating-point-max-decimals": 6,
 "platform.minimal-printf-enable-64-bit": false
        }
    }
 }

Run project

 

And that’s all for this example. You can run example using Run button. Before this you must select correct development board. If MBED Studio does not detect any board, check that you switched onboard programmer KitProg3 to DAPLink mode (KitProg3 Status LED must slowly flash) using MODE button. Run button causes that project will build (this will take a plenty of time, at least at the first build) and copies firmware to your board. In my case it does not work on Windows because I was not able to make PyOCD working on Windows. On Linux it works without issue. On the UART (which you can see in the MBED Studio) you can see the output.

My thoughts (review) about the environment, libraries, MCU, performance and much more which I gained by doing this (and not only this) project you can find in chapters with name that starts with “Review”. Links to all of them you can find at the beginning of this tutorial.