Check max read frequency

JoseJose Posts: 5New Member
I was trying to write 15bits to UPBoard from a microcontroller. I have an additional IO (CTL) to inform UP Board that there is new data to read. To test it I wrote a simple program on a microcontroller that increment a 15bits number and write it to 15 IOs that are connected to UP Board. Using a logic analyzer the data looks ok.

s4vYJ1w.png

On the UP Board side I check when there is a rising edge on the CTL pin and read the 15 IOs. I'm doing this to check what is the max frequency I can write the data.

I changed the twd (time after write data to the ios) and trd (time that UP Board have to read the data) from around 500us to 5000us. The higher the value the less data failures I get but there is always a failure. I'm going to increase trd to 100ms and let it run during the weekend to check if it can get the data without errors.

Change some settings about CPU scaling help a little but there is always an error after some time. From the results I can say that the error is caused because UPBoard skip a CTL rising edge. It should read per example 1004 and it reads 1005 and last value read was 1003.

You can check the code below:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>

#include "mraa.h"

#define DEFAULT_IOPIN 0

int running = 0;
static int iopins[16] = {3,5,7,11,13,15,19,21,23,27,29,31,33,35,37,8};
volatile int state = 0;
volatile uint16_t last_value = 0;
volatile int samples = 0;

void sig_handler(int signo)
{
    if (signo == SIGINT) {
        printf("closing IOs nicely\n");
        running = -1;
    }
}

main(int argc, char** argv)
{
    mraa_result_t r = MRAA_SUCCESS;
    mraa_init();
    fprintf(stdout, "MRAA Version: %s\n", mraa_get_version());

    mraa_gpio_context gpio[16];

    int i = 0; 
    for(i=0;i<16;i++){
        gpio[i] = mraa_gpio_init(iopins[i]);
        if (gpio[i] == NULL) {
            fprintf(stderr, "Are you sure that pin%d you requested is valid on your platform?", iopins[i]);
            exit(1);
        }

        r = mraa_gpio_dir(gpio[i], MRAA_GPIO_IN);
        if (r != MRAA_SUCCESS) {
            mraa_result_print(r);
        }

        printf("Initialised pin%d\n", iopins[i]);
    }

    signal(SIGINT, sig_handler);

    while (running == 0) {

        if( state == 0 && mraa_gpio_read(gpio[0]) == 0 ){

            state = 1;
            uint16_t value = 0;	

	    for(i=1;i<16;i++)
	        value |= mraa_gpio_read(gpio[i]) << (i-1);

	    if( (last_value+1) != value )
	    	printf("Error! last_value:%d != value:%d\n",last_value,value);

	    last_value = value;

        }else if( state == 1 && mraa_gpio_read(gpio[0]) == 1){
            state = 0;
        }
        usleep(1);
    }

    for(i=0;i<16;i++){
        r = mraa_gpio_close(gpio[i]);
        if (r != MRAA_SUCCESS) {
            mraa_result_print(r);
        }
    }
    return r;
}

I tried with interruptions and while it have less failures it still fail.

Any idea to improve it?

Comments

  • Nicola LunghiNicola Lunghi Posts: 131Emutex mod
    Hi Xavier
    is absolutely necessary for you to read the 15 bit in parallel using GPIOs?
    The up GPIO are slow and you have a big overhead (kernel) here

    for(i=1;i<16;i++)
    value |= mraa_gpio_read(gpio) << (i-1);

    also if you enter the if branch you don't know if this condition remain true while you read all the 16 GPIOs
    if( state == 0 && mraa_gpio_read(gpio[0]) == 0 ){

    If you have to do something like this is more simple/dependable to use SPI/serial interfaces instead of GPIO.

    The serial could go up to 3MBaud and the SPI up to 10Mhz -> much faster for communication; and the result are more predictable.
    The GPIO are more useful to get/set slow changing signal they are not very good to transmit data.

    Regards
    Nicola Lunghi
  • JoseJose Posts: 5New Member
    The problem is not reading the data, it can read the gpio very fast but sometimes it can't detect the rising edge. Do SPI depend on CPU?
  • Nicola LunghiNicola Lunghi Posts: 131Emutex mod
    Hi
    SPI and UART are actual hardware peripheral so they generate an interrupt when the data is "ready"

    https://github.com/intel-iot-devkit/mraa/blob/master/examples/spi_max7219.c
    https://github.com/intel-iot-devkit/mraa/blob/master/examples/uart.c

    also if you implement a serial with Hardware Flow control the CPU can signal the micro that is busy so you can obtain higher throughput

    Regards
    Nicola Lunghi
  • JoseJose Posts: 5New Member
    edited October 2017
    Thank you for your replies.

    During the weekend I let it run with a trd time of 100ms and twd time of 20ms and still it failed to get some CTL RE signal. 100ms is a lot of time...

    To use a serial protocol I'll need to develop external hardware which isn't impossible but will be expensive since we will use +- 100 boards.
  • JoseJose Posts: 5New Member
    edited October 2017
    Hi
    SPI and UART are actual hardware peripheral so they generate an interrupt when the data is "ready"

    That interrupt will make my application to be called so I don't lost any data?

    Do I2C also has its own hardware peripheral like SPI and UART?
  • Nicola LunghiNicola Lunghi Posts: 131Emutex mod
    >> Do I2C also has its own hardware peripheral like SPI and UART?
    Yes of course
    Regards
    Nicola Lunghi
Sign In or Register to comment.