target icon

Purpose

The main purpose of this tutorial is to manage events and print out event’s values, using serial line for traces purpose, to display events and to receive data from the serial line. In this tutorial, we are going to set up a simplest demo program. We will create a hypos-tuto-211-event.c program based on Hyperpanel OS. We will compile and build a new Hyperpanel OS including our program.

list icon

Prerequisites

  • A complete installation of an Hyperpanel OS release on a linux based PC including tools for flashing and debugging.
  • A stm32 Pyboard kit.
  • A visual editor to create or modify hello.c (We are using vi in our demo).

list icon

Software release

hypv9wr58 and higher

align left icon

Description

This program :

    1.

    Creates a new task.

    2.

    Opens a serial line for communication with a PC.

    3.

    On the Linux PC, open cutecom sudo cutecom (install it if necessary).

    4.

    In order to check the dev where the serial line is connected you can use dmesg. Take a look a the video 3 for more information.

    5.

    Parameters are: 8Bits – Parity: None – Baud rate: 9600 – Stop bits: 1

    6.

    On the cutecom trace you will find :

     

    • All the events received by hello1.c program.
    • Each 5 seconds a TIC..TAC. message.
    • If you enter a Hello World string in the input box you will get the echo trace in the main window.

    Connection and LED triggering.

    Edition, compilation, link, loading, execution.

    Ending connection.

    Code

    hypos-tuto-211.event.c

    /* Includes files and external references ...................................*/
    
    #include <stdtyp.l>
    #include <moteur.h>                    /* vmk.c and vmio.c interface         */
    #include <drv.h>                       /* drv.c interface                    */
    #include <automaton.h>                 /* Automaton definitions.             */
    #include <emu32.h>                     /* E32_ctx                            */
    #include <genio.h>                     /* Kbd_desc,Rcu_sym,Rcu_key,...       */
    
    #include <rdrv.h>                      /* drv.c tags interface               */
    #include <memoire.h>                   /* mem_buf.c interface                */
    #include <hypstring.h>                 /* memcpy strcy .. interface          */
    #include <text.h>                      /* Prototype hsprintf().              */
    #include <keycode.h>                   /* Key codes from RCU                 */
    #include <telecom.h>                   /* Constants and definitions for tags.*/
    #include <engine.h>                    /* Constants for automatong engine.   */
    #include <drv_rcu.h>                   /* RCU procedures prototypes          */
    
    #include <keym.txt>                    /* Applicative key codes              */
    #include <systemm.txt>                 /* WAIT_CODERES                       */
    #include <vmkm.txt>                    /* TSK_INIT_DATA TASK_INIT_BSS        */
    
    #include "./myio.h"                    /* Prototypes for "myio_xxx" procs    */
    #include "./myapp.h"                   /* Constant and structs for myapp.c   */
    
    static void    snd_trace        (char * , int                               ) ;
    static int     hsled            (int ,int                                   ) ;
    
    
    /* Internal global variables for the user task ------------------------------*/
    
    int                 mystack[512]     ; // The stack of our task (2kB)
    int                 myapp_taskid     ; // Our task id
    int                 myapp_memuid     ; // Our memory user id
    
    int                 asy_iod0         ; // IOD of devive ASY\DEV0
    int                 asy_iod1         ; // IOD of device ASY\DEV1
    int                 asy_iod2         ; // IOD of device ASY\DEV2
    
    int                 gpio_iod         ; // IOD of device GPIO\DEV0
    int                 gpio_iod1        ; // IOD of subchannel 0 of GPIO\DEV0
    int                 gpio_iod2        ; // IOD of subchannel 1 of GPIO\DEV1
    int                 gpio_iod3        ; // IOD of subchannel 2 of GPIO\DEV2
    
    int                 led_iod          ; // IOD of device LED\DEV0
    int                 led_iod0         ; // IOD of subchannel 0 of LED\DEV0
    int                 led_iod1         ; // IOD of subchannel 1 of LED\DEV1
    int                 led_iod2         ; // IOD of subchannel 2 of LED\DEV2
    
    int                 state_led0 = 1   ; // state of the IOD of LED0
    int                 state_led1 = 1   ; // state of the IOD of LED1
    int                 state_led2 = 1   ; // state of the IOD of LED2
    
    int                 kbd_iod          ; // IOD of device KBDITF\DEV0
    int                 rcusnd_id        ; // ID for RCU SND
    int                 rcurcv_id        ; // ID for RCU RCV
    
    int                 idto             ; // Timer identifier
    
    unsigned char      *buf_snd[ASYMAX]  ; // Address of transmit buffer
    unsigned char      *buf_rcv[ASYMAX]  ; // Address of received buffer
    int                 tok_rcv[ASYMAX]  ; // Count of receive tokens
    unsigned char      *buf_rcu          ; // Address of RCU send buffer
    
    int                 ev_val           ; // Returned by "wait_myevent"
    
    /* Lists of tags for the "open_xyz" procedures ..............................*/
    
    static const char *asy_taglist0 = "BAUDS=9600\nNBBITS=8\n"
                                      "STOPBIT=1\nPARITY=NONE"                   ;
    
    static const char *asy_taglist1 = "BAUDS=9600\nNBBITS=8\n"
                                      "STOPBIT=1\nPARITY=NONE\nBUFSIZE=0\n"
                                      "FLOWCTL=NONE\nCHAR1=10"        ;
    
    static const char *asy_taglist2 = "BAUDS=9600\nNBBITS=8\n"
                                      "STOPBIT=1\nPARITY=NONE\n"
                                      "FLOWCTL=NONE\nCHAR1=10"        ;
    
    static const char *gpio_taglist = "FUNC=GPIO\nOUTPUT=HI_Z\nWEAKPULL=UP\n"
                                      "EVENTS=REPORT"                            ;
    
    
    /*****************************************************************************/
    int init_vmk_fsm(Task_grp *g,char *mod, char*conf)
      {
    
        return 0                         ; // Exit without any error
      }
    
    
    /*****************************************************************************/
    int init_myapp(Task_grp *g,char *mod, char*conf)
      {
    
        int ret  ;
    
        create_task("app"           ,      // Taskgroup name
                    mytask_proc     ,      // Task entry point
                    myfree_proc     ,      // Task termination call-back
                    mystack         ,      // Stack address
                    sizeof(mystack) ,      // Stack size in bytes
                    PRIO_TSK_MIN    ,      // Task Priority
                    HNULL           ,      // Parameter for "mytask_proc"
                    TASK_INIT_BSS  +       // Init Flags
                    TASK_INIT_DATA +       //
                    TASK_INIT_CODE  ,      //
                    &myapp_taskid     )  ; // Task_id = 0x12FFFF00 + LW
    
    
        start_task(myapp_taskid,           // Send an event to VMK in order
                   &ret          )       ; // to request the task start
    
    
        alloc_memuid(&myapp_memuid,        // Allocates a user id for alloc_buf
                     &ret          )     ; // and other allocation procedures
    
    
        init_telecom()                   ; // Initialize driver/protocol/services
                                           // API
        return 0                         ; // Exit without any error
      }
    
    
    /*****************************************************************************/
    static INT mytask_proc(void *param)
      {
    
        open_asy()                       ; // Open the serial ports
        open_gpio()                      ; // Open the GPIO driver
        open_led()                       ; // Open the LED driver
        open_kbd()                       ; // Open the KBDITF driver
    
        myio_givetok(asy_iod0  ,           // I/O descriptor
                     2         ,           // Number of receive token
                     1         ,           // Size of receive buffer
                     &tok_rcv[0] )       ; // Counter of given tokens
    
        myio_givetok(asy_iod1 ,            // I/O descriptor
                     2        ,            // Number of receive token
                     LGRCV12  ,            // Size of receive buffer
                     &tok_rcv[1])        ; // Counter of given tokens
    
        myio_givetok(asy_iod2 ,            // I/O descriptor
                     2        ,            // Number of receive token
                     LGRCV12  ,            // Size of receive buffer
                     &tok_rcv[2])        ; // Counter of given tokens
    
    
        set_tto(CLOCK      ,               // Timer mode: clock
                5000       ,               // Duration in milliseconds
                TICK       ,               // Event code
                0          ,               // Event reserve field
                &idto        )           ; // Timer identifier
    
        snd_trace("\n\r=========== HELLO WORLD ============",asy_iod2);
        wait_ev                          : // Start of our event loop
                                           // -------------------------------------
        ev_val  = wait_myevents()        ; // Unschedule until one event is
                                           // received
        goto wait_ev                     ; // Goto wait for the next event or
    
        close_asy()                      ; // Close the two serial ports
        close_gpio()                     ; // Close the GPIO driver
        close_led()                      ; // Close the LED driver
        close_kbd()                      ; // Close the RCU keyboard
     
        return 0                         ;
     
      }
    
    
    /*****************************************************************************/
    static int myfree_proc(void)
      {
        int             ret              ; // Procedurs return code
    
        free_memuid(myapp_memuid,          // Frees a user id for alloc_buf
                    0x00000007  ,          // mask = buffers/links/huge
                    &ret          )      ; //
        return 0                         ;
      }
    
    
    static void open_asy(void)
      {
        int             ret              ; // Procedures returned code
    
    
        myio_open(DRVASY,DEV0,"",&asy_iod0) ; // Open "ASY\DEV0"
        myio_open(DRVASY,DEV1,"",&asy_iod1) ; // Open "ASY\DEV1"
        myio_open(DRVASY,DEV2,"",&asy_iod2) ; // Open "ASY\DEV2"
    
    
        myio_setval(asy_iod0,asy_taglist0)  ; // Set "ASY\DEV0" tags
        myio_setval(asy_iod1,asy_taglist1)  ; // Set "ASY\DEV1" tags
        myio_setval(asy_iod2,asy_taglist2)  ; // Set "ASY\DEV2" tags
    
    
        alloc_buf(myapp_memuid ,           // Memory user id
                  1500         ,           // Size in bytes of requested buffer
                  0            ,           // Flags
                  &buf_snd[0]  ,           // Address of allocated buffer
                  &ret          )        ; // Return code
    
        alloc_buf(myapp_memuid ,           // Memory user id
                  256          ,           // Size in bytes of requested buffer
                  0            ,           // Flags
                  &buf_snd[1]  ,           // Address of allocated buffer
                  &ret          )        ; // Return code
    
        alloc_buf(myapp_memuid ,           // Memory user id
                  256          ,           // Size in bytes of requested buffer
                  0            ,           // Flags
                  &buf_snd[2]  ,           // Address of allocated buffer
                  &ret          )        ; // Return code
    
    
      }
    
    
    /*  Procedure close_asy -------------------------------------------------------
    
        Purpose : This procedure closes the two USART, then frees those two 
                  devices, terminates the ASY module, delete the route that has 
                  been created for the IND_REPORT events, and finally frees the 2 
                  telecom buffers that were allocated by "open_asy".
    */
    
    static void close_asy(void)
      {
    
        int             ret              ; // Return code
    
        myio_close(asy_iod0)             ; // Closes "ASY\DEV0"
        myio_close(asy_iod1)             ; // Closes "ASY\DEV1"
        myio_close(asy_iod2)             ; // Closes "ASY\DEV2"
    
    
        free_buf(buf_snd[0], &ret )      ; // Free "buf_snd0"
        free_buf(buf_snd[1], &ret )      ; // Free "buf_snd1"
        free_buf(buf_snd[2], &ret )      ; // Free "buf_snd1"
      }
    
    
    /*  Procedure open_gpio -------------------------------------------------------
    
    */
    
    static void open_gpio(void)
      {
    
    
        myio_open(DRVGPIO,DEV0,"",&gpio_iod); // Open GPIO\DEV0
    
    
        myio_alloc_sub(gpio_iod,"UNAME=BUT1",&gpio_iod1); // Alloc BUT0 GPIO
        myio_alloc_sub(gpio_iod,"UNAME=BUT2",&gpio_iod2); // Alloc BUT1 GPIO
        myio_alloc_sub(gpio_iod,"UNAME=BUT3",&gpio_iod3); // Alloc BUT2 GPIO
    
        myio_setval(gpio_iod1,gpio_taglist) ; // Configure BUTO GPIO
        myio_setval(gpio_iod2,gpio_taglist) ; // Configure BUT1 GPIO
        myio_setval(gpio_iod3,gpio_taglist) ; // Configure BUT2 GPIO
      }
    
    
    /*  Procedure close_gpio ------------------------------------------------------
    
    */
    
    static void close_gpio(void)
      {
    
    
        myio_free_sub(gpio_iod1)         ; // Free BUT1 GPIO
        myio_free_sub(gpio_iod2)         ; // Free BUT2 GPIO
        myio_free_sub(gpio_iod3)         ; // Free BUT3 GPIO
    
    
    
        myio_close(gpio_iod)             ; // Closes the GPIO device and the driver
      }
    
    
    /*****************************************************************************/
    static void open_led(void)
      {
       
        int ret = 0 ;
    
        ret = myio_open(DRVLED,DEV0,"",&led_iod)  ; // Open LED\DEV0
    
        ret = myio_alloc_sub(led_iod,"LEDNAME=RED"    ,&led_iod0); // Allocates RED
        ret = myio_alloc_sub(led_iod,"LEDNAME=GREEN"  ,&led_iod1); // Allocates GREEN
        ret = myio_alloc_sub(led_iod,"LEDNAME=YELLOW" ,&led_iod2); // Allocates YELLOW
    
        if (ret) ret ++ ;
      }
    
    
    
    /*****************************************************************************/
    static void close_led(void)
      {
    
        myio_free_sub(led_iod0)          ; // Frees RED
        myio_free_sub(led_iod1)          ; // Frees GREEN
        myio_free_sub(led_iod2)          ; // Frees YELLOW
    
        myio_close(led_iod)              ; // Closes LED device and driver
      }
    
    /*****************************************************************************/
    
    
    /*  Procedure open_kbd --------------------------------------------------------
    
    */
    
    static void open_kbd(void)
      {
    
        int             ret              ; // Procedures returned code
        unsigned short  *pt              ; // Write pointer in "buf_rcu
    
    
        myio_open(DRVKBD,DEV0,"",&kbd_iod)  ; // Opens KBDITF\DEV0
    
    
        get_rcu_id(1          ,              // 0:Receiver 1:Transmitter
                   0          ,              // numdev = the first one
                   &rcusnd_id ,              // Corresponding id
                   &ret        )           ; // Error code
    
        get_rcu_id(0          ,              // 0:Receiver 1:Transmitter
                   0          ,              // numdev = the first one
                   &rcurcv_id ,              // Corresponding id
                   &ret        )           ; // Error code
    
    
    
        alloc_buf(myapp_memuid ,           // Memory user id
                  160          ,           // Size in bytes of requested buffer
                  0            ,           // Flags
                  &buf_rcu     ,           // Address of allocated buffer
                  &ret          )        ; // Return code
    
        pt = (unsigned short*) buf_rcu   ;
    
    
        *pt++ = 400                  ;
        *pt++ = 600                  ;
    
        *pt++ = 200                  ;
        *pt++ = 800                  ;
    
        *pt++ = 200                  ;
        *pt++ = 800                  ;
    
        *pt++ =  200                 ;
        *pt++ = 1800                 ;
      }
    
    
    /*  Procedure close_kbd ------------------------------------------------------*/
    
    
    static void close_kbd(void)
      {
    
        int             ret              ; // Procedures returned code
    
    
        myio_close(kbd_iod)              ; // Closes KBDITF\DEV0
    
    
        free_buf(buf_rcu   , &ret )      ; // Free "buf_snd0"
    
      }
    
    /**********************************************************************/
    static int hsled(int n,int state)
    
      {
    
        int ret = 0 ;
    
    // state = 0 switch off the led if state = 1 switch on the led 
    
        switch ( n )
          {
            case 0 :
              ret = myio_setval(led_iod0, "CMD=POPALL" );
              if (state == 1)                            
                ret = myio_setval(led_iod0, "PATTERN=ON:0\nCMD=PUSH")  ;
              else
                ret = myio_setval(led_iod0, "PATTERN=OFF:0\nCMD=PUSH"     )  ;
            break;
    
            case 1 :
              ret = myio_setval(led_iod1, "CMD=POPALL" );
              if (state == 1)
                ret = myio_setval(led_iod1, "PATTERN=ON:0\nCMD=PUSH")  ;
              else
                ret = myio_setval(led_iod1, "PATTERN=OFF:0\nCMD=PUSH"     )  ;
            break;
    
            case 2 :
              ret = myio_setval(led_iod2, "CMD=POPALL" );
              if (state == 1)
                ret = myio_setval(led_iod2, "PATTERN=ON:0\nCMD=PUSH")  ;
              else
                ret = myio_setval(led_iod2, "PATTERN=OFF:0\nCMD=PUSH"     )  ;
            break;
          }
    
        return ret                       ; // No error
      }
    
    
    /*  Procedure wait_myevents ---------------------------------------------------
    
        Purpose : Unschedule until any of my events is received or "msec" seconds
                  have been elapsed. A value of 0 for "msec" means no maximum
                  time limit. Accordind to the received event, the retourn value
                  of this procedure is as follows :
    
                  Code             Reserve        Return value
                  ---------------  --------       ---------------
                  RESP_READ        asy_iod0   ->  EV_ASY0_RCV   0
                  RESP_READ        asy_iod1   ->  EV_ASY1_RCV   1
                  RESP_READ        asy_iod2   ->  EV_ASY2_RCV   2
                  RESP_WRITE       asy_iod0   ->  EV_ASY0_SND   3
                  RESP_WRITE       asy_iod1   ->  EV_ASY1_SND   4
                  RESP_WRITE       asy_iod2   ->  EV_ASY2_SND   5
                  IND_REPORT       gpio_iod1  ->  EV_GPIO0_IN   10
                  IND_REPORT       gpio_iod2  ->  EV_GPIO1_IN   11
                  IND_REPORT       gpio_iod3  ->  EV_GPIO2_IN   12
                  TICK             any        ->  EV_MSEC       40
    
                  The "ret" value maybe -1 if we receive something else
    */
    
    static int wait_myevents(void)
      {
        int             waitlist[7][3]   ; // Parameter of "waitevt_task
        unsigned char  *bufevt           ; // Buffer address
        int             res              ; // Field "reserve" of task_evt.reserve
        int             code             ; // code evt
        int             lgc              ; // task_evt.reserve
        int             ret              ; // Return code
        int             err              ;
        char            buf[80]          ; // trace buffer
    
    
        waitlist[0][0]  = WAIT_CODERES   ; // All events with 
        waitlist[0][1]  = RESP_READ      ; // an event code RESP_READ
        waitlist[0][2]  = -1             ; // whatever the value of "reserve" is
    
        waitlist[1][0]  = WAIT_CODERES   ; // All events with 
        waitlist[1][1]  = RESP_WRITE     ; // an event code RESP_WRITE
        waitlist[1][2]  = -1             ; // whatever the value of "reserve" is
    
        waitlist[2][0]  = WAIT_CODERES   ; // All events with
        waitlist[2][1]  = IND_REPORT     ; // an event code IND_REPORT
        waitlist[2][2]  = -1             ; // whatever the value of "reserve" is
    
        waitlist[3][0]  = WAIT_CODERES   ; // All events with
        waitlist[3][1]  = DRV_KEY_PRESS  ; // an event code DRV_KEY_PRESS
        waitlist[3][2]  = -1             ; // whatever the value of "reserve" is
    
        waitlist[4][0]  = WAIT_CODERES   ; // All events with
        waitlist[4][1]  = DRV_KEY_RELEASE; // an event code DRV_KEY_RELEASE
        waitlist[4][2]  = -1             ; // whatever the value of "reserve" is
    
        waitlist[5][0]  = WAIT_CODERES   ; // All events with
        waitlist[5][1]  = EVTS_I2C_END   ; // an event code EVTS_I2C_END
        waitlist[5][2]  = -1             ; // whatever the value of "reserve" is
    
        waitlist[6][0]  = WAIT_CODERES   ; // All events with
        waitlist[6][1]  = TICK           ; // an event code TICK
        waitlist[6][2]  = 0              ; // with "reserve" equal to request
    
        waitevt_task(waitlist ,            // Address of waiting list
                     7        ,            // Size of "waitlist[]"
                     0        ,            // maximum waiting time = no
                     0        ,            // Do not purge previous events
                     &ret       )        ; // Return code
    
    
    /*****************************************************************************
     * Step 2 : Here we are scheduled again. The VMK has written into its        *
     * ------   global variable "task_evt" a copy of the event that has          *
     *          scheduled us again. As a code event value, we can have RESP_READ *
     *          RESP_WRITE, IND_REPORT, DRV_KEY_PRESS,                           *
     *          DRV_KEY_RELEASE but also the VMK generated event TICK (every     *
     *          second). According to the value of "task_evt.code" but also      *
     *          "task_evt.reserve" we compute the return value "ret". If we      *
     *          receive something we are not expecting, we will return a default *
     *          value of -1.                                                     *
     *****************************************************************************/
    
        bufevt = task_evt.adresse        ; // Read buffer address from event
        code= task_evt.code              ; // Extract the "code" field
        res = task_evt.reserve           ; // Extract the "reserve" field
        lgc = task_evt.longueur          ; // Extract the "longueur" field
        ret = -1                         ; // received event.
    
        hsprintf((char*)buf, "EVT:%d | RES:%d LONGUEUR:%d", code,res,lgc );
        snd_trace(buf,asy_iod2)          ; // After this call task_evt is
                                           // changed so keep the variable 
                                           // you want to work with 
        switch ( code )
          {
            case RESP_READ               : // For a RESP_READ, the "reserve"
              *(bufevt+lgc-1) = 0 ;        // cancel the line feed
              snd_trace((char *)bufevt,asy_iod2) ; // For info
              free_buf(bufevt, &err)     ; // Free the buffer.
              ret = myio_givetok(res,      // I/O descriptor
                         1          ,      // Number of receive token
                         LGRCV12    ,      // Size of receive buffer
                         &err         )  ; // Counter of given tokens
              break                      ; //
    
            case RESP_WRITE              : // For a RESP_WRITE, the "reserve"
              if      (res EQ asy_iod0)    // field is the "iod" value. So
                ret = EV_ASY0_SND        ; // we compare it to our IOD's,
              else if (res EQ asy_iod1)    // that are "asy_iod0" for ASY\DEV0,
                ret = EV_ASY1_SND        ; // "asy_iod1" for ASY\DEV1 and
              else if (res EQ asy_iod2)    // then
                ret = EV_ASY2_SND        ; // "asy_iod2" for ASY\DEV2
              break                      ; //
    
            case IND_REPORT              : // For a IND_REPORT, the "reserve" field
              if (lgc EQ 0)                // If INPUT is LOW,else it is a release
              {                            // on release do nothing
                if      (res EQ gpio_iod1)           // value is the "iod". we compare
                  ret = hsled(0,(state_led0++)%2)  ; // change the led state
                else if (res EQ gpio_iod2)          
                  ret = hsled(1,(state_led1++)%2)  ; // change the led state
                else if (res EQ gpio_iod3)           
                  ret = hsled(2,(state_led2++)%2)  ; // change the led state
              }
              break                      ; //
    
            case EVTS_I2C_END            : // For a EVTS_I2C_END, the "reserve"
              ret = EV_I2C_END           ; // field is a copy of the one received
              break                      ; // and we don't care.
    
            case TICK                    : // For a TICK, the "reserve"
              snd_trace("TIC..TAC.",asy_iod2);
              ret = EV_MSEC              ; // field is a copy of the one received
              break                      ; // and we don't care.
    
            case DRV_KEY_PRESS           : // For a DRV_KEY_PRESS, the "reserve"
              ret = EV_KBD_RCV           ; // field is the code of the key that
              break                      ; // has been pressed.
    
            case DRV_KEY_RELEASE         : // For a DRV_KEY_RELEASE, the "reserve"
              ret = EV_KBD_RCV           ; // field is the code of the key that
              break                      ; // has been released.
    
            default                      : // This should never occur if there
              break                      ; // is no bug.
    
          }
    
        return ret                       ;
       }
    
    /*  Procedure snd_trace---------------------------------------------------------
    
        Purpose : Send a message on asy_iod2
    */
    
    static void snd_trace(char * mes, int iod) 
      {
    
        unsigned char   *snd            ; // Address of buffer to be sent
        int             d, m, y         ; // Day, Month, Year
        int             h, mi, s, ms    ; // Hour, minutes, seconds, milliseconds
        int              lg             ; // to compute the size of the message
    
        tim_get(&d  ,                      // day
                &m  ,                      // Month
                &y  ,                      // Year
                &h  ,                      // Hour (0..23)
                &mi ,                      // Minutes (0..59)
                &s  ,                      // Seconds (0..59)
                &ms   )                  ; // Milliseconds (0..999)
    
        snd = buf_snd[1]                ; // Buffer to be sent
        hsprintf((char*)snd      ,        // Put in the transmit buffer
                 "%02d:%02d:%02d <%s>\n" ,  // 8 characters HH:MM:SS
                 h, mi, s , mes        ); //
    
        lg = strlen((char*)snd)         ; // Number of characters to send
        myio_write  (iod      ,            // I/O descriptor 
                     snd      ,            // Address of buffer
                     lg          );        // Number of bytes to send
      }
    
    

     

    Terminal

    cojyp@Ubuntu:~$ sudo -i
    root@Ubuntu ~ # cd /home/hyperpanel/hypv9wr58/os/linux
    root@Ubuntu /home/hyperpanel/hypv9wr58/os/linux # source stm32py
    root@Ubuntu /home/hyperpanel/hypv9wr58 # exe
    root@Ubuntu /home/hyperpanel/hypv9wr58/stm32py/exe # user stm32
    root@Ubuntu /home/hyperpanel/hypv9wr58/user/stm32 # exe
    root@Ubuntu /home/hyperpanel/hypv9wr58/stm32py/exe # hgdb
    GNU gdb (7.10-1ubuntu3+9) 7.10
    Copyright (C) 2015 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=x86_64-linux-gnu --target=arm-none-eabi".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word".
    (gdb) romload stm32py hypos
    Open On-Chip Debugger 0.10.0+dev-00001-g0ecee83-dirty (2017-02-10-06:53)
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    0x000367c4 in ?? ()
    target halted due to debug-request, current mode: Thread
    xPSR: 0x01000000 pc: 0x00001008 msp: 0x20002000
    auto erase enabled
    wrote 262144 bytes from file hypos.bin in 9.063136s (28.246 KiB/s)
    (gdb) c
    Continuing.
    
    ---------------------
    Enjoy ............