Page 1 of 1

Error with GPT driver in several threads

Posted: Fri Jul 17, 2015 7:21 am
by radiotechkz
Hi all,
I got a strange bug in my code with GPT. Below I will give my code. In a nutshell, I create two threads and pull pin with 1kHz frequency in each. If used one thread no problem, in oscilloscope I can see normal signal.
Image

If used two threads signal looks like this:
Image

A different scale
Image

Code: Select all

#include "ch.h"
#include "hal.h"

#include <chprintf.h>

static WORKING_AREA(waThread2, 128);
static msg_t Thread2(void *arg) {
    (void)arg;
    chRegSetThreadName("Ring1");
    while (TRUE) {
        moveRing1(TRUE, TRUE, 400, 150);
}

static WORKING_AREA(waThread3, 128);
static msg_t Thread3(void *arg) {
    (void)arg;
    chRegSetThreadName("Ring2");
    while (TRUE) {
        moveRing2(TRUE, TRUE, 400, 150);
}


void moveRing1(bool_t enable, bool_t dir, uint32_t stepsNum, uint32_t period) {
    uint32_t count = 0;
    if (enable != TRUE) {
        palSetPad(GPIOE, GPIOE_INT2);        // if not enable set pin GPIOE.1, stop driver
    }
    else {
        palClearPad(GPIOE, GPIOE_INT2);        // if enable clear pin GPIOE.1, start driver
    }
    if (dir == TRUE) {
        palSetPad(GPIOE, GPIOE_PIN12);        // directory of rotary, DIR pin on Driver, GPIOE.12
    }
    else {
        palClearPad(GPIOE, GPIOE_PIN12);
    }
    while(count < stepsNum) {
        palSetPad(GPIOC, GPIOC_PIN6);
        gptPolledDelay(&GPTD2, period);
        palClearPad(GPIOC, GPIOC_PIN6);
        gptPolledDelay(&GPTD2, period);
        count ++;
    }
}

void moveRing2(bool_t enable, bool_t dir, uint32_t stepsNum, uint32_t period) {
    uint32_t count = 0;
    if (enable != TRUE) {
        palSetPad(GPIOE, GPIOE_PIN2);        // if not enable set pin GPIOE.1, stop driver
    }
    else {
        palClearPad(GPIOE, GPIOE_PIN2);        // if enable clear pin GPIOE.1, start driver
    }
    if (dir == TRUE) {
        palSetPad(GPIOE, GPIOE_PIN13);        // directory of rotary, DIR pin on Driver, GPIOE.12
    }
    else {
        palClearPad(GPIOE, GPIOE_PIN13);
    }
    while(count < stepsNum) {
        palSetPad(GPIOC, GPIOC_MCLK);
        gptPolledDelay(&GPTD3, period);
        palClearPad(GPIOC, GPIOC_MCLK);
        gptPolledDelay(&GPTD3, period);
        count ++;
    }
}

/*
* GPT2 configuration.
*/
static GPTConfig gpt2cfg =
{
    300000,     /* timer clock.*/
    NULL        /* Timer callback.*/
};

/*
* GPT3 configuration.
*/
static GPTConfig gpt3cfg =
{
    300000,     /* timer clock.*/
    NULL        /* Timer callback.*/
};

void ringInit() {
    palSetPadMode(GPIOE, GPIOE_INT2, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOE, GPIOE_PIN12, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOC, GPIOC_PIN6, PAL_MODE_OUTPUT_PUSHPULL); // step pin for ring 1

    palSetPadMode(GPIOE, GPIOE_PIN2, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOE, GPIOE_PIN13, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOC, GPIOC_MCLK, PAL_MODE_OUTPUT_PUSHPULL); // step pin for ring2

    palSetPadMode(GPIOE, GPIOE_CS_SPI, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOE, GPIOE_PIN14, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOB, GPIOB_PIN0, PAL_MODE_OUTPUT_PUSHPULL); // step pin for ring3

    palSetPadMode(GPIOE, GPIOE_PIN4, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOE, GPIOE_PIN15, PAL_MODE_OUTPUT_PUSHPULL);
    palSetPadMode(GPIOB, GPIOB_PIN1, PAL_MODE_OUTPUT_PUSHPULL); // step pin for ring3
}

// Application entry point.
int main(void) {
    /*
     * System initializations.
     * - HAL initialization, this also initializes the configured device drivers
     *   and performs the board-specific initializations.
     * - Kernel initialization, the main() function becomes a thread and the
     *   RTOS is active.
     */
    halInit();
    chSysInit();
 
    /*
      * Activates the serial driver 2 using the driver default configuration.
        * PA2(TX) and PA3(RX) are routed to USART2.
        */
    /*sdStart(&SD2, NULL);
    palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
    palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));*/

    ringInit();
    gptStart(&GPTD2, &gpt2cfg);
    gptStart(&GPTD3, &gpt3cfg);

    /*
     * Creates the example thread.
     */
    chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, NULL);
    chThdCreateStatic(waThread3, sizeof(waThread3), NORMALPRIO, Thread3, NULL);

    /*
     * Normal main() thread activity, in this demo it does nothing except
     * sleeping in a loop.
     */
    while (TRUE) {
        //chprintf((BaseSequentialStream *) &SD2, " %d\r", 101);     
        chThdSleepMilliseconds(1);     // Задержка для считывания новых данных, заменить на пин прерывания DRDY
    }
}


Help. I don't understand something simple.

Re: Error with GPT driver in several threads

Posted: Fri Jul 17, 2015 8:00 am
by Giovanni
Hi,

You have two threads at same priority which perform chPolledDelay(). It is a polled delay so the CPU is not made available to other threads.

What you are seeing the is the round robin mechanism, the two threads each use a slice of time and alternates.

Giovanni

Re: Error with GPT driver in several threads

Posted: Mon Jul 20, 2015 5:22 am
by radiotechkz
Giovanni wrote:Hi,

You have two threads at same priority which perform chPolledDelay(). It is a polled delay so the CPU is not made available to other threads.

What you are seeing the is the round robin mechanism, the two threads each use a slice of time and alternates.

Giovanni

Thanks, Giovanni.
But how can I resolve this task with delays in microseconds which not using cpu time?

Re: Error with GPT driver in several threads

Posted: Mon Jul 20, 2015 5:54 am
by Giovanni
Using ChibiOS 3.0 you can increase the system time frequency to 1MHz and use chThdSleepMicroseconds but you will discover that your generated signal will be affected heavily by jitter. You should not rely on threads for timings at that timescale.

If you need to generate signals you may use the PWM driver or use HW timers directly.

Giovanni