added my Recipes

This commit is contained in:
2024-07-11 14:16:35 +02:00
parent 38bc4f53ac
commit 09b621d929
7118 changed files with 525762 additions and 3 deletions

View File

@@ -0,0 +1,53 @@
SUMMARY = "Hand writing character recognition launcher based on HCR Neural Network"
LICENSE = "GPL-2.0-only & BSD-3-Clause"
LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
DEPENDS = "gtk+3 gstreamer1.0-plugins-base demo-launcher"
DEPENDS:append:stm32mpcommon = " m4projects-stm32mp1 "
inherit pkgconfig
SRC_URI = " file://ai_char_reco_launcher.c \
file://apps_launcher_example.sh \
file://copro.c \
file://copro.h \
file://Makefile \
file://timer.c \
file://timer.h \
\
file://media \
\
file://demo \
"
PV = "2.1"
S = "${WORKDIR}"
do_configure[noexec] = "1"
#Provides the firmware location for DK2 and EV1 boards
EXTRA_OEMAKE = 'FIRMWARE_PATH_DK2="${STM32MP_USERFS_MOUNTPOINT}/Cube-M4-examples/STM32MP157C-DK2/Demonstrations/AI_Character_Recognition/lib/firmware"'
EXTRA_OEMAKE += 'FIRMWARE_PATH_EV1="${STM32MP_USERFS_MOUNTPOINT}/Cube-M4-examples/STM32MP157C-EV1/Demonstrations/AI_Character_Recognition/lib/firmware"'
#Provides the firmware name
EXTRA_OEMAKE += 'FIRMWARE_NAME="AI_Character_Recognition.elf"'
do_install() {
install -d ${D}${prefix}/local/demo/bin/
install -d ${D}${prefix}/local/demo/media/
install -d ${D}${prefix}/local/demo/application/m4_ai/bin
install -d ${D}${prefix}/local/demo/application/m4_ai/pictures
install -m 0755 ${B}/ai_char_reco_launcher ${D}${prefix}/local/demo/bin/
install -m 0755 ${B}/apps_launcher_example.sh ${D}${prefix}/local/demo/bin/
install -m 0644 ${B}/media/* ${D}${prefix}/local/demo/media/
install -m 0755 -D ${WORKDIR}/demo/application/m4_ai/bin/* ${D}${prefix}/local/demo/application/m4_ai/bin/
install -m 0755 -D ${WORKDIR}/demo/application/m4_ai/pictures/* ${D}${prefix}/local/demo/application/m4_ai/pictures/
install -m 0644 -D ${WORKDIR}/demo/application/*.yaml ${D}${prefix}/local/demo/application/
}
FILES:${PN} += "${prefix}/local/demo/"
RDEPENDS:${PN} += "gtk+3 gstreamer1.0-plugins-base demo-launcher"
RDEPENDS:${PN}:append:stm32mpcommon = " m4projects-stm32mp1-userfs "

View File

@@ -0,0 +1,15 @@
FIRMWARE_PATH_DK2?="/usr/local/Cube-M4-examples/STM32MP157C-DK2/Demonstrations/AI_Character_Recognition/lib/firmware"
FIRMWARE_PATH_EV1?="/usr/local/Cube-M4-examples/STM32MP157C-EV1/Demonstrations/AI_Character_Recognition/lib/firmware"
FIRMWARE_NAME?="AI_Character_Recognition.elf"
# support GTK
CFLAGS += -Wall $(shell pkg-config --cflags gtk+-3.0)
LDFLAGS += $(shell pkg-config --libs gtk+-3.0)
all: ai_char_reco_launcher
ai_char_reco_launcher: copro.c timer.c ai_char_reco_launcher.c
$(CC) -DFIRMWARE_PATH_DK2='"${FIRMWARE_PATH_DK2}"' -DFIRMWARE_PATH_EV1='"${FIRMWARE_PATH_EV1}"' -DFIRMWARE_NAME='"${FIRMWARE_NAME}"' -o $@ $^ $(CFLAGS) $(LDFLAGS)
clean: ; rm -rf *.o ai_char_reco_launcher

View File

@@ -0,0 +1,66 @@
#!/bin/sh
video() {
echo "Launch video"
gst-launch-1.0 playbin uri=file:///usr/local/demo/media/Teaser-STM32MP1.webm video-sink="waylandsink sync=false" audio-sink="fakesink" &
}
audio() {
echo "Launch audio"
gst-launch-1.0 playbin uri=file:///usr/local/demo/media/ST12266_269_full_technology-freaks_0160.ogg &
}
picture() {
echo "Display picture"
gst-launch-1.0 filesrc location=/usr/local/demo/media/stm32cubeai.png ! pngdec ! videoconvert ! imagefreeze ! glimagesink &
}
camera() {
echo "Launch preview camera"
v4l2-ctl --set-parm=20
gst-launch-1.0 v4l2src ! "video/x-raw, format=YUY2, width=320, height=240" ! waylandsink &
}
kill_all() {
echo "kill previous app"
killall gst-launch-1.0
}
quit() {
kill_all
killall ai_char_reco_launcher
}
case "$1" in
V)
video
;;
S)
kill_all
;;
A)
audio
;;
P)
picture
;;
C)
camera
;;
Q)
quit
;;
*)
echo "HELP: $0 [command]"
echo "available commands:"
echo " V (launch video)"
echo " A (Launch audio)"
echo " P (Display picture)"
echo " C (Launch preview camera)"
echo " S (kill previous app)"
echo " Q (quit the launcher)"
;;
esac
exit 0

View File

@@ -0,0 +1,267 @@
/*
* copro.c
* Implements Copro's abstraction layer
*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
* Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
*
* License type: GPLv2
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include "copro.h"
#define MAX_BUF 80
/* The file descriptor used to manage our TTY over RPMSG */
static int mFdRpmsg = -1;
int copro_isFwRunning(void)
{
int fd;
size_t byte_read;
int result = 0;
unsigned char bufRead[MAX_BUF];
char *user = getenv("USER");
if (user && strncmp(user, "root", 4)) {
system("XTERM=xterm su root -c 'cat /sys/class/remoteproc/remoteproc0/state' > /tmp/remoteproc0_state");
fd = open("/tmp/remoteproc0_state", O_RDONLY);
} else {
fd = open("/sys/class/remoteproc/remoteproc0/state", O_RDONLY);
}
if (fd < 0) {
printf("Error opening remoteproc0/state, err=-%d\n", errno);
return (errno * -1);
}
byte_read = (size_t) read (fd, bufRead, MAX_BUF);
if (byte_read >= strlen("running")) {
char* pos = strstr((char*)bufRead, "running");
if(pos) {
result = 1;
}
}
close(fd);
return result;
}
int copro_stopFw(void)
{
int fd;
char *user = getenv("USER");
if (user && strncmp(user, "root",4)) {
system("su root -c 'echo stop > /sys/class/remoteproc/remoteproc0/state'");
return 0;
}
fd = open("/sys/class/remoteproc/remoteproc0/state", O_RDWR);
if (fd < 0) {
printf("Error opening remoteproc0/state, err=-%d\n", errno);
return (errno * -1);
}
write(fd, "stop", strlen("stop"));
close(fd);
return 0;
}
int copro_startFw(void)
{
int fd;
char *user = getenv("USER");
if (user && strncmp(user, "root",4)) {
system("su root -c 'echo start > /sys/class/remoteproc/remoteproc0/state'");
return 0;
}
fd = open("/sys/class/remoteproc/remoteproc0/state", O_RDWR);
if (fd < 0) {
printf("Error opening remoteproc0/state, err=-%d\n", errno);
return (errno * -1);
}
write(fd, "start", strlen("start"));
close(fd);
return 0;
}
int copro_getFwPath(char* pathStr)
{
int fd;
int byte_read;
char *user = getenv("USER");
if (user && strncmp(user, "root",4)) {
system("XTERM=xterm su root -c 'cat /sys/module/firmware_class/parameters/path' > /tmp/parameters_path");
fd = open("/tmp/parameters_path", O_RDONLY);
} else {
fd = open("/sys/module/firmware_class/parameters/path", O_RDONLY);
}
if (fd < 0) {
printf("Error opening firmware_class/parameters/path, err=-%d\n", errno);
return (errno * -1);
}
byte_read = read (fd, pathStr, MAX_BUF);
close(fd);
return byte_read;
}
int copro_setFwPath(char* pathStr)
{
int fd;
int result = 0;
char *user = getenv("USER");
if (user && strncmp(user, "root",4)) {
char cmd[1024];
snprintf(cmd, 1024, "su root -c 'echo %s > /sys/module/firmware_class/parameters/path'", pathStr);
system(cmd);
return strlen(pathStr);
}
fd = open("/sys/module/firmware_class/parameters/path", O_RDWR);
if (fd < 0) {
printf("Error opening firmware_class/parameters/path, err=-%d\n", errno);
return (errno * -1);
}
result = write(fd, pathStr, strlen(pathStr));
close(fd);
return result;
}
int copro_getFwName(char* name)
{
int fd;
int byte_read;
char *user = getenv("USER");
if (user && strncmp(user, "root",4)) {
system("XTERM=xterm su root -c 'cat /sys/class/remoteproc/remoteproc0/firmware' > /tmp/remoteproc0_firmware");
fd = open("/tmp/remoteproc0_firmware", O_RDONLY);
} else {
fd = open("/sys/class/remoteproc/remoteproc0/firmware", O_RDWR);
}
if (fd < 0) {
printf("Error opening remoteproc0/firmware, err=-%d\n", errno);
return (errno * -1);
}
byte_read = read (fd, name, MAX_BUF);
close(fd);
/* remove \n from the read character */
return byte_read - 1;
}
int copro_setFwName(char* nameStr)
{
int fd;
int result = 0;
char *user = getenv("USER");
if (user && strncmp(user, "root",4)) {
char cmd[1024];
snprintf(cmd, 1024, "su root -c 'echo %s > /sys/class/remoteproc/remoteproc0/firmware'", nameStr);
system(cmd);
return strlen(nameStr);
}
fd = open("/sys/class/remoteproc/remoteproc0/firmware", O_RDWR);
if (fd < 0) {
printf("Error opening remoteproc0/firmware, err=-%d\n", errno);
return (errno * -1);
}
result = write(fd, nameStr, strlen(nameStr));
close(fd);
return result;
}
int copro_openTtyRpmsg(int modeRaw)
{
struct termios tiorpmsg;
mFdRpmsg = open("/dev/ttyRPMSG0", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (mFdRpmsg < 0) {
printf("Error opening ttyRPMSG0, err=-%d\n", errno);
return (errno * -1);
}
/* get current port settings */
tcgetattr(mFdRpmsg,&tiorpmsg);
if (modeRaw) {
tiorpmsg.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
tiorpmsg.c_oflag &= ~OPOST;
tiorpmsg.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
tiorpmsg.c_cflag &= ~(CSIZE | PARENB);
tiorpmsg.c_cflag |= CS8;
} else {
/* ECHO off, other bits unchanged */
tiorpmsg.c_lflag &= ~ECHO;
/*do not convert LF to CR LF */
tiorpmsg.c_oflag &= ~ONLCR;
}
tcsetattr(mFdRpmsg, TCSANOW, &tiorpmsg);
return 0;
}
int copro_closeTtyRpmsg(void)
{
close(mFdRpmsg);
mFdRpmsg = -1;
return 0;
}
int copro_writeTtyRpmsg(int len, char* pData)
{
int result = 0;
if (mFdRpmsg < 0) {
printf("Error writing ttyRPMSG0, fileDescriptor is not set\n");
return mFdRpmsg;
}
result = write(mFdRpmsg, pData, len);
return result;
}
int copro_readTtyRpmsg(int len, char* pData)
{
int byte_rd, byte_avail;
int result = 0;
if (mFdRpmsg < 0) {
printf("Error reading ttyRPMSG0, fileDescriptor is not set\n");
return mFdRpmsg;
}
ioctl(mFdRpmsg, FIONREAD, &byte_avail);
if (byte_avail > 0) {
if (byte_avail >= len) {
byte_rd = read (mFdRpmsg, pData, len);
} else {
byte_rd = read (mFdRpmsg, pData, byte_avail);
}
/*printf("copro_readTtyRpmsg, read successfully %d bytes to %p, [0]=0x%x\n", byte_rd, pData, pData[0]);*/
result = byte_rd;
} else {
result = 0;
}
return result;
}
char copro_computeCRC(char *bb, int size)
{
short sum = 0;
for (int i = 0; i < size - 1; i++)
sum += (bb[i] & 0xFF);
char res = (char) (sum & 0xFF);
res += (char) (sum >> 8);
return res;
}

View File

@@ -0,0 +1,44 @@
/*
* copro.h
* Implements Copro's abstraction layer
*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
* Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
*
* License type: GPLv2
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __COPRO_H__
#define __COPRO_H__
#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
int copro_isFwRunning(void);
int copro_stopFw(void);
int copro_startFw(void);
int copro_getFwPath(char* pathStr);
int copro_setFwPath(char* pathStr);
int copro_getFwName(char* pathStr);
int copro_setFwName(char* nameStr);
int copro_openTtyRpmsg(int modeRaw);
int copro_closeTtyRpmsg(void);
int copro_writeTtyRpmsg(int len, char* pData);
int copro_readTtyRpmsg(int len, char* pData);
char copro_computeCRC(char *bb, int size);
#endif /* __COPRO_H__ */

View File

@@ -0,0 +1,14 @@
Application:
Name: Artificial
Description: Intelligence
Icon: application/m4_ai/pictures/ST7079_AI_neural_pink.png
Type: script
Board:
List: stm32mp15
Script:
Start: application/m4_ai/bin/launch_AI.sh
Action:
button_release_event: script_start
button_press_event: highlight_eventBox

View File

@@ -0,0 +1,2 @@
#!/bin/sh
script -qc "/usr/local/demo/bin/ai_char_reco_launcher /usr/local/demo/bin/apps_launcher_example.sh"

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,121 @@
/**
*************************************************************************************************
* @file readme.txt
* @author MCD Application Team
* @brief Description of the Artificial Intelligence Hand Writing Character Recognition example.
*************************************************************************************************
*
* Copyright (c) 2019 STMicroelectronics. All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*************************************************************************************************
*/
This project demonstrate a complex application that is running on both CPU1(CA7) and CPU2(CM4).
The application is a launcher that recognize hand writing character drawn on the touch screen in order
to execute specific actions.
CPU1 (CA7) control the touch event and the Graphic User Interface.
CPU2 (CM4) is used to offload the processing of a Cube.AI pre-build Neural Network.
The communication between the CPU1(CA7) and the CPU2(CM4) is done through a Virtual UART to create an
Inter-Processor Communication channel seen as a TTY device in Linux.
The implementation is based on:
* RPMSG framework on CPU1(CA7) side
* and OpenAMP MW on the CPU2(CM4) side
OpenAMP MW uses the following HW resources
* IPCC peripheral for event signal (mailbox) between CPU1(CA7) and CPU2(CM4)
* MCUSRAM peripheral for buffer communications (virtio buffers) between CPU1(CA7) and CPU2(CM4)
Reserved shared memeory region for this example: SHM_ADDR=0x10040000 and SHM_SIZE=128k.
It is defined in platform_info.c file
A communication protocol has been defined between the CPU1(CA7 and the CPU2(CM4).
The data frames exchanged have the follwowing structure:
----------------------------------------------------------------
| msg ID | data Length | data Byte 1 | ... | data Byte n | CRC |
----------------------------------------------------------------
- 3 types of message could be received by CPU2(CM4):
* Set the Neural Network input type (0x20, 0x01, data, CRC)
* data = 0 => NN input is letter or digit
* data = 1 => NN input is letter only
* data = 2 => NN input is digit only
* Provide the touch screen coordinate (0x20, n, data_x1, data_y1, ... , data_xn, data_yn, CRC)
* n => the number of coordinate points
* data_xn => x coordinate of the point n
* data_yn => y coordinate of the point n
* Start ai nn processing (0x22, 0x00, CRC)
- 4 types of acknowledges could be received on CPU1(CA7) side:
* Bad acknowledge (0xFF, 0x00, CRC)
* Good acknowledge (0xF0, 0x00, CRC)
* Touch screen acknowledge (0xF0, 0x01, n, CRC)
* n => number of screen coordinate points acknowledged
* AI processing result acknowledge (0xF0, 0x04, char, accuracy, time_1, time_2, CRC)
* char => this is the recognized letter (or digit)
* accuracy => this is the confidence expressed in percentage
* time_1 => upper Bytes of the time (word) expressed in ms
* time_2 => lower Bytes of the time (word) expressed in ms
On CPU2(CM4) side:
- CPU2(CM4) initialize OPenAMP MW which initializes/configures IPCC peripheral through HAL
and setup openamp-rpmsg framwork infrastructure
- CPU2(CM4) creates 1 rpmsg channels for 1 virtual UART instance UART0
- CPU2(CM4) initialize the Character Recognition Neural Network
- CPU2(CM4) is waiting for messages from CPU1(CA7) on this channels
- When CPU2(CM4) receives a message on 1 Virtual UART instance/rpmsg channel, it processes the message
to execute the associated action:
* set the NN input type to the desire value
* or register the touch event coordinate to generate the picture that will be processed by the NN
* or start the NN processing and wait for the results
- On every previous action, the CPU(CM4) is sending back to the CPU1(CA7) and acknowledge already defined
above.
On CPU1(CA7) side:
- CPU1(CA7) open the input event to register the touch events generated by the user's finger drawing
- CPU1(CA7) configure the input type (Letter only) of the Neural Network running on the CPU2(CM4) by
sending a message throught the virtual TTY communication channel
- when the drawing is finished, CPU1(CA7) process the touch event data and send it to the CPU2(CM4)
- CPU1(CA7) start the Neural Network processing wait for the result and display the recognized character on
the diplay
Some information about the Character Recognition Neural Network:
The Character Recognition Neural Network used is a Keras model processed by Cube.AI to generate the executable
that can be run on the CPU2(CM4).
The Keras model used is located in the root directory of this project:
model-ABC123-112.h5
This model has been used in Cube.AI to generate the Neural Network binary.
The model accept as input a 28x28 picture encoded with float in black and white (black = 0.0 or White = 1.0).
The output layer of the Neural Network contains 36 neurons (A -> Z and 0 -> 9).
Notes:
- It requires Linux console to run the application.
- CM4 logging is redirected in Shared memory in MCUSRAM and can be displayed using following command:
cat /sys/kernel/debug/remoteproc/remoteproc0/trace0
Following command should be done in Linux console on CA7 to run the example :
> /usr/local/demo/bin/ai_char_reco_launcher /usr/local/demo/bin/apps_launcher_example.sh
You are ready to draw letter on the touch screen
Hardware and Software environment:
- This example runs on STM32MP157CACx devices.
- This example has been tested with STM32MP157C-DK2 and STM32MP157c-EVAL board and can be
easily tailored to any other supported device and development board.
Where to find the M4 firmware source code:
The M4 firmware source code is delivered as demonstration inside the STM32CubeMP1.
For the DK2 board:
<STM32CubeMP1>/Firmware/Projects/STM32MP157C-DK2/Demonstrations/AI_Character_Recognition
For the EV1 board:
<STM32CubeMP1>/Firmware/Projects/STM32MP157C-DK2/Demonstrations/AI_Character_Recognition

View File

@@ -0,0 +1,190 @@
/*
* timer.c
* Implements timer services
*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
* Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
*
* License type: GPLv2
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <fcntl.h>
#include <stdint.h>
#include <string.h>
#include <sys/timerfd.h>
#include <pthread.h>
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
#include "timer.h"
#define MAX_TIMER_COUNT 1000
struct timer_node
{
int fd;
timer_handler callback;
void * user_data;
unsigned int interval;
struct timer_node * next;
};
static void * _timer_thread(void * data);
static pthread_t g_thread_id;
static struct timer_node *g_head = NULL;
int timer_init()
{
if(pthread_create(&g_thread_id, NULL, _timer_thread, NULL))
{
/*Thread creation failed*/
return 0;
}
return 1;
}
void timer_finalize()
{
while(g_head) timer_stop((size_t)g_head);
pthread_cancel(g_thread_id);
pthread_join(g_thread_id, NULL);
}
size_t timer_start(unsigned int interval,
timer_handler handler,
void * user_data)
{
struct timer_node * new_node = NULL;
struct itimerspec new_value;
new_node = (struct timer_node *)malloc(sizeof(struct timer_node));
if(new_node == NULL) return 0;
new_node->callback = handler;
new_node->user_data = user_data;
new_node->interval = interval;
new_node->fd = timerfd_create(CLOCK_REALTIME, 0);
if (new_node->fd == -1)
{
free(new_node);
return 0;
}
new_value.it_value.tv_sec = interval / 1000;
new_value.it_value.tv_nsec = (interval % 1000) * 1000 * 1000;
new_value.it_interval.tv_sec = 0;
new_value.it_interval.tv_nsec = 0;
timerfd_settime(new_node->fd, 0, &new_value, NULL);
/*Inserting the timer node into the list*/
new_node->next = g_head;
g_head = new_node;
return (size_t)new_node;
}
void timer_stop(size_t timer_id)
{
struct timer_node * tmp = NULL;
struct timer_node * node = (struct timer_node *)timer_id;
if (node == NULL) return;
close(node->fd);
if(node == g_head)
{
g_head = g_head->next;
}
tmp = g_head;
while(tmp && tmp->next != node) tmp = tmp->next;
if(tmp && tmp->next)
{
tmp->next = tmp->next->next;
}
if(node) free(node);
}
struct timer_node * _get_timer_from_fd(int fd)
{
struct timer_node * tmp = g_head;
while(tmp)
{
if(tmp->fd == fd) return tmp;
tmp = tmp->next;
}
return NULL;
}
void * _timer_thread(void * data)
{
struct pollfd ufds[MAX_TIMER_COUNT] = {{0}};
int iMaxCount = 0;
struct timer_node * tmp = NULL;
int read_fds = 0, i, s;
uint64_t exp;
while(1)
{
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
iMaxCount = 0;
tmp = g_head;
memset(ufds, 0, sizeof(struct pollfd)*MAX_TIMER_COUNT);
while(tmp)
{
ufds[iMaxCount].fd = tmp->fd;
ufds[iMaxCount].events = POLLIN;
iMaxCount++;
tmp = tmp->next;
}
read_fds = poll(ufds, iMaxCount, 100);
if (read_fds <= 0) continue;
for (i = 0; i < iMaxCount; i++)
{
if (ufds[i].revents & POLLIN)
{
s = read(ufds[i].fd, &exp, sizeof(uint64_t));
if (s != sizeof(uint64_t)) continue;
tmp = _get_timer_from_fd(ufds[i].fd);
if(tmp && tmp->callback) tmp->callback((size_t)tmp, tmp->user_data);
}
}
}
return NULL;
}

View File

@@ -0,0 +1,36 @@
/*
* timer.h
* Implements timer services
*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
* Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
*
* License type: GPLv2
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef __TIMER_H
#define __TIMER_H
#include <stdlib.h>
typedef void (*timer_handler)(size_t timer_id, void * user_data);
int timer_init();
void timer_finalize();
size_t timer_start(unsigned int interval, timer_handler handler, void * user_data);
void timer_stop(size_t timer_id);
#endif