Page 1 of 2

[NEW] Improved PAL driver with synchronous API

Posted: Sat Sep 02, 2017 1:43 pm
by Giovanni
Hi,

This is an example of the new PAL driver, note, the same application is implemented using callbacks or the new synchronous API, the new API looks much simpler.

Code: Select all

/*
    ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

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

/*===========================================================================*/
/* Generic code.                                                             */
/*===========================================================================*/

#if defined(PORTAB_LINE_LED2)
/*
 * LED blinker thread, times are in milliseconds.
 */
static THD_WORKING_AREA(waThread1, 128);
static THD_FUNCTION(Thread1, arg) {
  (void)arg;
  chRegSetThreadName("blinker");
  while (true) {
    systime_t time = palReadLine(PORTAB_LINE_BUTTON) == PORTAB_BUTTON_PRESSED ? 250 : 500;
    palToggleLine(PORTAB_LINE_LED2);
    chThdSleepMilliseconds(time);
  }
}
#endif

#if PAL_USE_WAIT || defined(__DOXYGEN__)

/*
 * 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();

#if defined(PORTAB_LINE_LED2)
  /*
   * Creates the blinker thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
#endif

  /* Enabling events on both edges of the button line.*/
  palEnableLineEvent(PORTAB_LINE_BUTTON, PAL_EVENT_MODE_BOTH_EDGES);

  /*
   * Normal main() thread activity.
   */
  while (true) {
    /* Waiting for an edge on the button.*/
    palWaitLineTimeout(PORTAB_LINE_BUTTON, TIME_INFINITE);

    /* Action depending on button state.*/
    if (palReadLine(PORTAB_LINE_BUTTON) == PORTAB_BUTTON_PRESSED) {
      palWriteLine(PORTAB_LINE_LED1, PORTAB_LEN_ON);
    }
    else {
      palWriteLine(PORTAB_LINE_LED1, PORTAB_LEN_OFF);
    }
  }
}

#endif /* PAL_USE_WAIT */

#if !PAL_USE_WAIT && PAL_USE_CALLBACKS

static event_source_t button_pressed_event;
static event_source_t button_released_event;

static void button_cb(void *arg) {

  (void)arg;

  chSysLockFromISR();
  if (palReadLine(PORTAB_LINE_BUTTON) == PORTAB_BUTTON_PRESSED) {
    chEvtBroadcastI(&button_pressed_event);
  }
  else {
    chEvtBroadcastI(&button_released_event);
  }
  chSysUnlockFromISR();
}

/*
 * Application entry point.
 */
int main(void) {
  event_listener_t el0, el1;

  /*
   * 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();

  /* Events initialization and registration.*/
  chEvtObjectInit(&button_pressed_event);
  chEvtObjectInit(&button_released_event);
  chEvtRegister(&button_pressed_event, &el0, 0);
  chEvtRegister(&button_released_event, &el1, 1);

#if defined(PORTAB_LINE_LED2)
  /*
   * Creates the blinker thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
#endif

  /* Enabling events on both edges of the button line.*/
  palEnableLineEvent(PORTAB_LINE_BUTTON, PAL_EVENT_MODE_BOTH_EDGES);
  palSetLineCallback(PORTAB_LINE_BUTTON, button_cb, NULL);

  /*
   * Normal main() thread activity.
   */
  while (true) {
    eventmask_t events;

    events = chEvtWaitOne(EVENT_MASK(0) | EVENT_MASK(1));
    if (events & EVENT_MASK(0)) {
      palWriteLine(PORTAB_LINE_LED1, PORTAB_LEN_ON);
    }
    if (events & EVENT_MASK(1)) {
      palWriteLine(PORTAB_LINE_LED1, PORTAB_LEN_OFF);
    }
  }
}
#endif /* !PAL_USE_WAIT && PAL_USE_CALLBACKS */

#if !PAL_USE_WAIT && !PAL_USE_CALLBACKS
/*
 * 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();

#if defined(PORTAB_LINE_LED2)
  /*
   * Creates the blinker thread.
   */
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
#endif

  /*
   * Normal main() thread activity.
   */
  while (true) {
    palToggleLine(PORTAB_LINE_LED1);
    chThdSleepMilliseconds(500);
  }
}
#endif /* !PAL_USE_WAIT && !PAL_USE_CALLBACKS */


The test application is available under /testhal/STM32/multi/PAL

Giovanni

Re: [NEW] Improved PAL driver with synchronous API

Posted: Sun Sep 03, 2017 4:53 pm
by Giovanni
More changes, now it is possible to enable/disable the callback and synchronous APIs independently, this way it is possible to save memory disabling what it is not needed.

Giovanni

Re: [NEW] Improved PAL driver with synchronous API

Posted: Sun Sep 03, 2017 8:03 pm
by tfAteba
Hi Giovanni,

I just want to know, is the synchronous API allow to use External interruptions in the PAL lld ?

What is the advantage to have a synchronous API?

Thanks.

Re: [NEW] Improved PAL driver with synchronous API

Posted: Sun Sep 03, 2017 8:09 pm
by Giovanni
See the demo, you can make a thread wait for a state transition without having to define callbacks.

Giovanni

Re: [NEW] Improved PAL driver with synchronous API

Posted: Sat Sep 09, 2017 5:09 pm
by tfAteba
Hi,

Yes, by reading the demo, it is clear now.

Now I have to implement this feature and make some test :)

Thanks.

Re: [NEW] Improved PAL driver with synchronous API

Posted: Fri Dec 01, 2017 4:26 pm
by omcdr
When this new PAL driver will be added in stable branch ? I see it only in trunk.
It is safe to use ?

Re: [NEW] Improved PAL driver with synchronous API

Posted: Fri Dec 01, 2017 6:30 pm
by Giovanni
Hi,

It will be included in next major release, probably 18.1.

It is safe to use knowing that it could change, usually I commit usable code, if not then I put a warning in this forum (note there is a warning right now, trunk is in the middle of something).

Giovanni

Re: [NEW] Improved PAL driver with synchronous API

Posted: Mon Apr 16, 2018 2:17 pm
by Xela
I have been following some example to write an interrupt handler, but failed to compile with the following:
./os/hal/ports/STM32/LLD/EXTIv1/hal_ext_lld.h:30:29: fatal error: hal_ext_lld_isr.h: No such file or directory
That has led me to this forum thread.

Are the 'events' referred to in this demo meant to replace the EXTI subsystem?

Re: [NEW] Improved PAL driver with synchronous API

Posted: Mon Apr 16, 2018 2:23 pm
by Giovanni
Hi,

Correct, the EXT driver has been obsoleted, PAL replaces it (it uses EXTI internally).

Giovanni

Re: [NEW] Improved PAL driver with synchronous API

Posted: Mon Apr 16, 2018 5:37 pm
by Xela
If I understand the example code, it is demonstrating the use of events. In the first example application it demonstrates polling for an event.
The second application demonstrates issuing an event in a callback that is triggered by an interrupt (the main while loop also listens for the event).

It is all a bit overkill for an interrupt example as I am getting a bit confused between the event listening and interrupt handling. Well I think I understand it but I don't follow how in the example event listeners are instantiated, registered, and never referenced again (I don't see the purpose of el0,el1).

Code: Select all

event_listener_t el0, el1;
chEvtRegister(&button_pressed_event, &el0, 0);
chEvtRegister(&button_released_event, &el1, 1);


However, that is very much an aside as at this point I am only interested in the latest convention for setting up an ISR as EXT is depreciated.

If rip eveything out that is related to event signalling, all I am left with is the following:

Code: Select all

palEnableLineEvent(PORTAB_LINE_BUTTON, PAL_EVENT_MODE_BOTH_EDGES);
palSetLineCallback(PORTAB_LINE_BUTTON, button_cb, NULL);
 



Following this I have the bare minimum for and ISR:
(heartbeat green output and if the interrupt pin is reset once the red light comes on permanently)

Code: Select all

static void ledtest_cb(void *arg) {
  (void)arg;
  XAL_LED_on(&LED_RED);
}


int main(void) {

  halInit();
  chSysInit();

  palEnableLineEvent(GPIOC_TEST_INT, PAL_EVENT_MODE_FALLING_EDGE);
  palSetLineCallback(GPIOC_TEST_INT, ledtest_cb, NULL);

  while (true) {
    XAL_LED_on(&LED_GREEN);
    XOS_SleepMs(30);
    XAL_LED_off(&LED_GREEN);
    XOS_SleepMs(940);
  }
}


It is a Monday so of course this doesn't actually work. So either I don't understand the minimum requirements for an ISR or I have my pin GPIOC_TEST_INT configured incorrectly.


Also, is the following guide still the preferred way to write an ISR?:
http://www.chibios.org/dokuwiki/doku.ph ... interrupts

It is what I have been following but haven't been able to figure out how to trigger the myIRQ handle yet.