This section provides code examples for using the MCU SDK and accompanying API. See the links below:

Requirements

The examples below assume that you have the following:

Reading the value of an I2C device and sending it back to the host

This example reads the WHOAMI register value of an MPU6050 sensor via the I2C interface and sends it back to the host. You may need some extra hardware for this setup, including a breadboard, the correct value of resistors (as per the I2C device spec), and a few jumper wires.

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
    #include "mcu_api.h"
    #include "mcu_errno.h"
    
    /* the I2C address of MPU6050 */
    #define MPU6050_ADDR    0x68
    /* the register address of WHOAMI register, which is used to verify 
    the identity of the device */
    #define MPU6050_WHOAMI          ((unsigned char)0x75)
    #define MPU6050_WHOAMI_VALUE    ((unsigned char)0x68)
    
    static unsigned char mpu6050_read_whoami()
    {
        unsigned char id;
        int res;
        res = i2c_read(MPU6050_ADDR, MPU6050_WHOAMI, &id, 1);
        if (res)
        {
            debug_print(DBG_ERROR, "mpu6050_i2c_read whoami fail...");
            return 0Xff;
        }
        if (id != MPU6050_WHOAMI_VALUE)
        {
            debug_print(DBG_ERROR, "wrong chip ID 0x%x, expected 0x%x\n", 
                        id, MPU6050_WHOAMI_VALUE);
            return 0xff;
        }
        return id;
    }
    
    void mcu_main()
    {
        unsigned char device_id;
        char buf[16];
        int len;
        while (1)
        {
            mcu_sleep(300);
            debug_print(DBG_INFO, "after sleep 3 seconds\n");
            device_id = mpu6050_read_whoami();
            len = mcu_snprintf(buf, 16, "id = %d\n", device_id);
            host_send((unsigned char*)buf, len);
        }
    }
    
  3. Set up an I2C circuit between the MPU6050 sensor and the Intel Edison board. Connect the SDA, SCL, VCC and GND ports of the I2C interface, as shown in the image below. In our example, we have used an MPU-6050 triaxial gyroscope + accelerometer sensor module for Arduino.

    Diagram of setting up an I2C circuit
  4. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  5. Choose MCU > Download. Your program is downloaded to your device.
  6. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  7. Run init_i2c8.sh from the Edison shell.
  8. Run cat /dev/ttymcu0 to fetch the data from the MCU that the host_send() API sent, as shown in the example below:
    root@edison:~# cat /dev/ttymcu0
    id = 104
    id = 104
    id = 104
    

You should be able to see the output every 3 seconds.

Sending data via UART

Because the host and MCU share UART2 (for example, ttyMFD2), it is possible to send data to UART2 via the MCU. To create an MCU project to send data via UART, do the following:

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
    #include "mcu_api.h"
    #include "mcu_errno.h"
    /*
    * This program sends a string to UART2 every 3 seconds
    */
    void mcu_main()
    {
        /* your configuration code starts here */
        uart_setup(2, 115200);
     
        while (1)
        {
            uart_write(2, (unsigned char*)"hello mcu\r\n", 11);
            mcu_sleep(300);
        }
    }
    
  3. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  4. Choose MCU > Download. Your program is downloaded to your device.
  5. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  6. If it is not already connected, connect the Arduino serial port to your computer.
  7. If you are successful, you will see the following output from the MCU:
    hello mcu
    hello mcu
    hello mcu
    

Controlling PWM ports

The MCU can access all PWM ports, from PWM 0 to PWM 3. The PWM period can vary from 104 ns to 218,453,000 ns. This example shows how the MCU can control the PWM port.

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
    #include "mcu_api.h"
    #include "mcu_errno.h"
     
    #define PORT 0
     
    void mcu_main()
    {
            /* Configure PWM and enable it */
            pwm_configure(PORT, 60000, 200000);
            pwm_enable(PORT);
     
            while (1)
            {
                    mcu_sleep(2000);
                    debug_print(DBG_INFO, "I am still alive...\n");
            }
    }
    
  3. Edit the /etc/intel_mcu/mcu_fw_loader.sh file to disable the PWM power management on the Linux* side, as shown below. This enables the MCU to configure the PWM modules.
    root@edison:/etc/intel_mcu# cat mcu_fw_loader.sh
    #!/bin/sh
    #author: JiuJin Hong (jiujinx.hong@intel.com)
    if [ ! -d "/sys/devices/platform/intel_mcu" ];then
            exit
    fi
    if [ ! -f "/lib/firmware/intel_mcu.bin" ];then
            exit
    fi
    echo "on" > /sys/devices/pci0000\:00/0000\:00\:17.0/power/control
    echo "load mcu app" > /sys/devices/platform/intel_mcu/control
    
  4. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  5. Choose MCU > Download. Your program is downloaded to your device.
  6. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  7. Run init_mcu_PWM.sh to set up the PWM configuration for the Arduino expansion board.
  8. Measure the output of DIG 3, which maps to PWM 0. You should see output on the DIG output screen similar to the image below.

Example of the DIG output screen

The table below shows PWM port numbers mapped to Arduino DIG numbers by default.

PWM port 0 1 2 3
Arduino DIG port 3  5 6  9

Registering an interrupt handler to a GPIO port

This example shows how you can register an interrupt handler for the MCU.

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
     #include "mcu_api.h"
    #include "mcu_errno.h"
     
     
     /*
      * This program use GPIO 48 as an interrupt handler, which connects to 
      * Edison Arduino board DIG 7. GPIO 49 (DIG 8)is simulated as an interrupt 
      * input, which triggers the ISR that defined in GPIO 48. 
     */
     
     int my_irq(int req)
     {
       debug_print(DBG_INFO, "Interrupt triggered!\n");
       return IRQ_HANDLED;
     }
     
     void mcu_main()
     {
        /* your configuration code starts here */
        gpio_setup(48, 0);  /* set GPIO 48 as input*/
        gpio_setup(49, 1);  /* set GPIO 49 (DIG 8) as output and as an interrupt trigger */
        gpio_register_interrupt(48, 0, my_irq); /* define the ISR on GPIO 48 */
        while (1)
        {
    debug_print(DBG_INFO, "I am in main loop!\n");
    gpio_write(49, 0);
    mcu_sleep(300);         /* sleep 3 second */
    gpio_write(49, 1);
    mcu_sleep(300);         /* sleep 3 second */
        }
     }
    
  3. Connect the Arduino digital port 7 to digital port 8 with a wire. DIG 7 is used as an interrupt input and DIG 8 is used to simulate triggering an interrupt.
  4. Power on the device.
  5. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  6. Choose MCU > Download. Your program is downloaded to your device.
  7. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  8. After reboot, run init_DIG.sh -o 7 -d input and init_DIG.sh -o 8 -d output to set up the GPIO configuration for the Arduino expansion board.
    root@edison:~# ./tools/init_DIG.sh -o 7 -d input
    DIG = 7
    DIR = input
    root@edison:~# ./tools/init_DIG.sh -o 8 -d output
    DIG = 8
    DIR = output
    root@edison:~#
    
  9. Run cat /dev/ttymcu1 to fetch the debug message from the MCU. You can see log messages from both main thread and handler function of the GPIO interrupt, as shown in the example output below.
    root@edison:~# cat /dev/ttymcu1
    ( INFO): I am in main loop!
    ( INFO): Interrupt triggered!
    ( INFO): I am in main loop!
    ( INFO): Interrupt triggered!
    ( INFO): I am in main loop!
    ( INFO): Interrupt triggered!
    ^C
    

Communicating between the host and the MCU

This sample shows how the MCU can retrieve a command from the host and send a response to the host.

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
    #include "mcu_api.h"
    #include "mcu_errno.h"
    #include <string.h>
     
    void mcu_main()
    {
        /* your configuration code starts here */
        char buf[64];
        int len;
     
        while (1)       /* your loop code starts here */
        {
            do {
                len = host_receive((unsigned char *)buf, 64);
                mcu_sleep(10);
            } while (len <= 0);
            if (strncmp(buf, "start", 5) == 0)
            {
                debug_print(DBG_INFO, "received start command!\n");
                host_send((unsigned char*)"hello mcu\n", 10);
            }
        }
    }
    
  3. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  4. Choose MCU > Download. Your program is downloaded to your device.
  5. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  6. Run echo "start" > /dev/ttymcu0 on the target device.
  7. Run cat /dev/ttymcu0 to retrieve the response from the MCU, as shown in the example output below:
    root@edison:~# cat /dev/ttymcu0
    ^C
    root@edison:~# echo “start” > /dev/ttymcu0
    root@edison:~# cat /dev/ttymcu0
    hello mcu
    ^C
    
As an alternative, you can also get the response using C code. The following is a code example for communicating with the host using host-side C code:
#include <stdio.h>   /* Standard input/output definitions */
#include <fcntl.h>   /* File control definitions */
int main()
{
    int fd;
    unsigned char data;
    unsigned char buf[100];
    int i, n;
    fd = open("/dev/ttymcu0", O_RDWR | O_NOCTTY);
    if (fd == -1)
    {
        printf("open ttymcu0 failed!\n");
        return 1;
    }
 
    i = 0;
 
    do
    {
        n = read(fd, &data, 1);
        buf[i] = data;
        i++;
    } while(data != '\n' && i < 100);
 
    i = (i >=99? 99:i);
    buf[i] = '\0';
    printf("Response from MCU: %s", buf);
 
    close(fd);
    return 0;
}

Waking up the host CPU using the MCU

In situations when power consumption is critical, you can have the host CPU rest in a sleep status while the MCU is kept active to collect data and wake the CPU only when necessary. The MCU can communicate with the host via the host_send and host_receive APIs. The MCU will wake up the host using host_send. This example shows how to set the MCU to wake the CPU every two minutes.

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
    #include "mcu_api.h"
    #include "mcu_errno.h"
     
     
    void mcu_main()
    {
        /* your configuration code starts here */
     
        while (1)       /* your loop code starts here */
        {
            mcu_sleep(12000);   /* wake up CPU every 2 minutes */
            host_send((unsigned char*)"wake up!\n", 10);
        }
    }
    
  3. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  4. Choose MCU > Download. Your program is downloaded to your device.
  5. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  6. Check the count of interrupts from the MCU using the cat /proc/interrupts command, and the output from /dev/ttymcu0, as shown below:
    Poky (Yocto Project Reference Distro) 1.6.1 edison ttyMFD2
    
    edison login: root
    root@edison:~#
    root@edison:~# cat /proc/interrupts | grep intel_psh_ipc
     47:          1          1   IO-APIC-fasteoi   intel_psh_ipc
    root@edison:~# cat ttymcu0
    ^C
    root@edison:~# 
    
    Note: To enable power management of the serial port, you might need to run the following command:

    echo auto > /sys/devices/pci0000\:00/0000\:00\:04.3/power/control

    This lets the CPU enter into sleep mode when there is no input from the serial port.
  7. Wait for several minutes and check again. You should be able to see more interrupts from the MCU, which will wake up the CPU, and the strings from the MCU on /dev/ttymcu0, as shown in the example below.
    root@edison:~# cat /proc/interrupts | grep intel_psh_ipc
    47: 2 2 IO-APIC-fasteoi intel_psh_ipc
    root@edison:~# cat ttymcu0
    wake up!
    wake up!
    ^C
    root@edison:~# 
    

Getting debug messages from the MCU 

On the Linux side, there is a TTY driver, which can communicate with MCU to get debug messages.
The sample below shows how the MCU can output messages to the Linux side with different log levels. You can get debug messages from the MCU through the TTY node.

  1. Create a new project from a template. For steps, see Creating a new MCU project.
  2. In your main file, paste the following code:
    #include "mcu_api.h"
    #include "mcu_errno.h"
    /*
    * This program outputs debug messages to host in different loglevel every 10 seconds
    */
    void mcu_main()
    {
        /* your configuration code starts here */
        while (1)       /* your loop code starts here */
       {
            debug_print(DBG_DEBUG, "mcu dbg message print in DEBUG      level...\n");
            debug_print(DBG_INFO, "mcu dbg message print in INFO level...\n");
            debug_print(DBG_WARNING, "mcu dbg message print in WARNING level...\n");
            debug_print(DBG_ERROR, "mcu dbg message print in ERROR level...\n");
            debug_print(DBG_FATAL, "mcu dbg message print in FATAL level...\n");
            mcu_sleep(1000);
        }
    }
    
  3. To build your project, choose MCU > Build Project. A log of the build process is shown on the Console tab. Verify that your project builds successfully and a Build Finished message is displayed.
  4. Choose MCU > Download. Your program is downloaded to your device.
  5. Click OK to reboot and update your device. Wait one or two minutes for the board to boot up.
  6. Connect to the Intel® Edison board, and run:
    1. cat /dev/ttymcu1 to retrieve debug message from MCU.
    2. cat /sys/devices/platform/intel_mcu/log_level to get the current debug log level in the MCU.
    3. echo debug > /sys/devices/platform/intel_mcu/log_level to set the debug log level for the MCU.
      root@edison:~# cat /dev/ttymcu1
      (DEBUG) : mcu dbg message print in DEBUG level...
      ( INFO) : mcu dbg message print in INFO level...
      ( WARN) : mcu dbg message print in WARN level...
      (ERROR) : mcu dbg message print in ERROR level...
      (FATAL) : mcu dbg message print in FATAL level...
      root@edison:~#
      root@edison:~# cat /sys/devices/platform/intel_mcu/log_level
      debug
      root@edison:~#
      root@edison:~# echo "debug" > /sys/devices/platform/intel_mcu/log_level
      root@edison:~#
      

If you want to get messages from all available log levels from the MCU, you should set log_level to debug, since debug is the highest level. MCU will output the messages with levels lower than the current level set. The MCU log level supports five kinds of levels, which are fatal, error, warning, info, and debug (in order from lowest to highest level).

Setting the Intel® Edison board up to test system on a chip (SoC) GPIOs

This section provides information to set up the tests for the GPIOs on an Intel Edison board. In order to thest the GPIOs, you must upload a series of scripts to your board and enable them to be executed using the chmod command. If you have already uploaded these scripts, as described in Loading the MCU SDK scripts onto your board, you should not need to repeat this portion of the steps.

Note:
Only the GPIOs for the SoC that are available on the Arduino shield have been tested.

Requirements

  1. In order to test the GPIOs, you need to initialize the board. To do so, download the files named init_DIG.sh, set_DIG.sh, and read_DIG.sh on the host system in the /home/lab/GPIO directory.
  2. Open a shell and run the following command to send the files to the board:
    scp ~/GPIO/*.sh root@192.168.2.15:~
    ssh root@192.168.2.15 "chmod +x ~/*_DIG.sh "
    Note: Export the IP_ADDR variable (optional). To avoid setting the Intel® Edison board's IP address on each test step, you can set it to the current shell environment using the following command:
    IP_ADDR=192.168.2.15

    Or you can set it for the profile (every shell) by editing the ~/.profile file, and adding the following line to the end:
    export IP_ADDR=192.168.2.15

    Note: To test the GPIOs, use the script init_DIG.sh to set up the multiplexers to have the SoC's GPIO on the shield.
    root@edison:~# init_DIG.sh -o <number> -d <direction>

    ...where <number> is the digital output number and <direction> is input or output mode.
  3. The following are examples of commands to work with output:
    1. Initializing the DIG3 output:
      root@edison:~# ./init_DIG.sh -o 3 -d output
    2. Setting the output to high level:
      root@edison:~# ./set_DIG.sh -o 3 -v high
    3. Setting the output to low level:
      root@edison:~# ./set_DIG.sh -o 3 -v low
  4. The following are examples of commands to work with input:
    1. Initializing the DIG3 output:
      root@edison:~# ./init_DIG.sh -o 3 -d input
    2. Reading the input status (low or high):
      root@edison:~# ./read_DIG.sh -o 3
有关编译器优化的更完整信息,请参阅优化通知