Error with GPT driver in several threads

ChibiOS public support forum for topics related to the STMicroelectronics STM32 family of micro-controllers.

Moderator: RoccoMarco

Post Reply
radiotechkz
Posts: 2
Joined: Fri Jul 17, 2015 7:00 am

Error with GPT driver in several threads

Post 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.
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Error with GPT driver in several threads

Post 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
radiotechkz
Posts: 2
Joined: Fri Jul 17, 2015 7:00 am

Re: Error with GPT driver in several threads

Post 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?
User avatar
Giovanni
Site Admin
Posts: 14892
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Error with GPT driver in several threads

Post 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
Post Reply