40 static int mainline_epoll_fd;
46 static int rtPriority = 2;
47 static void *rt_thread(
void *arg);
48 static pthread_t rt_thread_id;
49 static int rt_thread_epoll_fd;
51 static int rtControlPriority = 80;
52 static void *rt_control_thread(
void *arg);
53 static pthread_t rt_control_thread_id;
54 static int rt_control_thread_epoll_fd;
63 static void periodic_task_init(
struct period_info *pinfo);
64 static void wait_rest_of_period(
struct period_info *pinfo);
66 void configureCANopen(
int nodeId,
int rtPriority,
int CANdevice0Index,
char *CANdevice);
71 static void sigHandler(
int sig) {
78 int main(
int argc,
char *argv[]) {
80 CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
81 bool_t firstRun =
true;
82 bool_t rebootEnable =
false;
83 char CANdevice[10] =
"vcan0";
86 int CANdevice0Index = if_nametoindex(CANdevice);
91 if (signal(SIGINT, sigHandler) == SIG_ERR)
92 CO_errExit(
"Program init - SIGINIT handler creation failed");
93 if (signal(SIGTERM, sigHandler) == SIG_ERR)
94 CO_errExit(
"Program init - SIGTERM handler creation failed");
95 printf(
"starting CANopen device with Node ID %d(0x%02X)", nodeId, nodeId);
97 while (reset != CO_RESET_APP && reset != CO_RESET_QUIT &&
CO_endProgram == 0) {
105 CO->CANmodule[0]->CANnormal =
false;
109 if (CO_init(CANdevice0Index, nodeId, 0) != CO_ERROR_NO) {
111 snprintf(s, 120,
"Communication reset - CANopen initialization failed, err=%d", err);
115 CO_EM_initCallback(CO->em, taskMain_cbSignal);
116 CO_SDO_initCallback(CO->SDO[0], taskMain_cbSignal);
117 CO_SDOclient_initCallback(CO->SDOclient, taskMain_cbSignal);
126 mainline_epoll_fd = epoll_create(4);
127 if (mainline_epoll_fd == -1)
128 CO_errExit(
"Program init - epoll_create mainline failed");
131 taskMain_init(mainline_epoll_fd, &OD_performance[ODA_performance_mainCycleMaxTime]);
133 rt_thread_epoll_fd = epoll_create(2);
134 if (rt_thread_epoll_fd == -1)
135 CO_errExit(
"Program init - epoll_create rt_thread failed");
137 CANrx_taskTmr_init(rt_thread_epoll_fd,
TMR_TASK_INTERVAL_NS, &OD_performance[ODA_performance_timerCycleMaxTime]);
141 if (pthread_create(&rt_thread_id, NULL, rt_thread, NULL) != 0)
142 CO_errExit(
"Program init - rt_thread creation failed");
144 if (rtPriority > 0) {
145 struct sched_param param;
146 param.sched_priority = rtPriority;
147 if (pthread_setschedparam(rt_thread_id, SCHED_FIFO, ¶m) != 0)
148 CO_errExit(
"Program init - rt_thread set scheduler failed");
151 if (pthread_create(&rt_control_thread_id, NULL, rt_control_thread, NULL) != 0)
152 CO_errExit(
"Program init - rt_thread_control creation failed");
154 if (rtPriority > 0) {
155 struct sched_param paramc;
156 paramc.sched_priority = rtControlPriority;
157 if (pthread_setschedparam(rt_control_thread_id, SCHED_FIFO, ¶mc) != 0)
158 CO_errExit(
"Program init - rt_thread set scheduler failed");
161 CO_CANsetNormalMode(CO->CANmodule[0]);
163 reset = CO_RESET_NOT;
171 struct epoll_event ev;
172 ready = epoll_wait(mainline_epoll_fd, &ev, 1, -1);
174 if (errno != EINTR) {
177 }
else if (taskMain_process(ev.data.fd, &reset,
CO_timer1ms)) {
193 if (pthread_join(rt_thread_id, NULL) != 0) {
194 CO_errExit(
"Program end - pthread_join failed");
196 if (pthread_join(rt_control_thread_id, NULL) != 0) {
197 CO_errExit(
"Program end - pthread_join failed");
201 CANrx_taskTmr_close();
203 CO_delete(CANdevice0Index);
204 printf(
"Canopend on %s (nodeId=0x%02X) - finished.\n\n", CANdevice, nodeId);
206 if (rebootEnable && reset == CO_RESET_APP) {
208 if (reboot(LINUX_REBOOT_CMD_RESTART) != 0) {
218 static void *rt_thread(
void *arg) {
220 struct epoll_event ev;
221 int ready = epoll_wait(rt_thread_epoll_fd, &ev, 1, -1);
223 if (errno != EINTR) {
226 }
else if (CANrx_taskTmr_process(ev.data.fd)) {
232 for (i = 0; i < OD_traceEnable && i < CO_NO_TRACE; i++) {
237 if (OD_performance[ODA_performance_timerCycleMaxTime] >
TMR_TASK_OVERFLOW_US && rtPriority > 0 && CO->CANmodule[0]->CANnormal) {
238 CO_errorReport(CO->em, CO_EM_ISR_TIMER_OVERFLOW, CO_EMC_SOFTWARE_INTERNAL, 0x22400000L | OD_performance[ODA_performance_timerCycleMaxTime]);
251 static void *rt_control_thread(
void *arg) {
253 periodic_task_init(&pinfo);
256 wait_rest_of_period(&pinfo);
260 wait_rest_of_period(&pinfo);
265 static void inc_period(
struct period_info *pinfo) {
274 static void periodic_task_init(
struct period_info *pinfo) {
278 clock_gettime(CLOCK_MONOTONIC, &(pinfo->
next_period));
280 static void wait_rest_of_period(
struct period_info *pinfo) {
284 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pinfo->
next_period, NULL);
289 if (nodeId < 1 || nodeId > 127) {
290 fprintf(stderr,
"NODE ID outside range (%d)\n", nodeId);
294 if (rtPriority != -1 && (rtPriority < sched_get_priority_min(SCHED_FIFO) || rtPriority > sched_get_priority_max(SCHED_FIFO))) {
295 fprintf(stderr,
"Wrong RT priority (%d)\n", rtPriority);
299 if (CANdevice0Index == 0) {
301 snprintf(s, 120,
"Can't find CAN device \"%s\"", CANdevice);
306 if (CO_OD_RAM.FirstWord != CO_OD_RAM.LastWord) {
307 fprintf(stderr,
"Program init - Canopend- Error in CO_OD_RAM.\n");
316 CO_errorReport(CO->em, CO_EM_GENERIC_SOFTWARE_ERROR, CO_EMC_SOFTWARE_INTERNAL, info);
317 fprintf(stderr,
"canopend generic error: 0x%X\n", info);
void app_programEnd(void)
Function is called just before program ends.
void CO_errExit(char *msg)
void CO_error(const uint32_t info)
struct timespec next_period
volatile uint32_t CO_timer1ms
void app_communicationReset(void)
void CO_time_init(CO_time_t *tm, CO_SDO_t *SDO, uint64_t *epochTimeBaseMs, uint32_t *epochTimeOffsetMs, uint16_t idx_OD_time)
void CO_time_process(CO_time_t *tm)
uint64_t * epochTimeBaseMs
void app_programControlLoop(void)
Function is called cyclically from Control loop thread at constant intervals.
Time object, usable for timestamping - Defined in CANOpen code.
void app_programStart(void)
#define TMR_TASK_OVERFLOW_US
#define TMR_TASK_INTERVAL_NS
Task Timer used for the Control Loop.
#define INCREMENT_1MS(var)
void app_programAsync(uint16_t timer1msDiffy)
pthread_mutex_t CO_CAN_VALID_mtx
volatile sig_atomic_t CO_endProgram
int main(int argc, char *argv[])
void configureCANopen(int nodeId, int rtPriority, int CANdevice0Index, char *CANdevice)
uint32_t * epochTimeOffsetMs