1 /*
2  * CANopen main program file.
3  *
4  * This file is a template for other microcontrollers.
5  *
6  * @file        main_generic.c
7  * @author      Janez Paternoster
8  * @copyright   2004 - 2020 Janez Paternoster
9  *
10  * This file is part of CANopenNode, an opensource CANopen Stack.
11  * Project home page is <https://github.com/CANopenNode/CANopenNode>.
12  * For more information on CANopen see <http://www.can-cia.org/>.
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  *     http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  */
26 
27 
28 #include "CANopen.h"
29 
30 
31 #define TMR_TASK_INTERVAL   (1000)          /* Interval of tmrTask thread in microseconds */
32 #define INCREMENT_1MS(var)  (var++)         /* Increment 1ms variable in tmrTask */
33 
34 /**
35  * User-defined CAN base structure, passed as argument to CO_init.
36  */
37 struct CANbase {
38     uintptr_t baseAddress;  /**< Base address of the CAN module */
39 };
40 
41 /* Global variables and objects */
42     volatile uint16_t   CO_timer1ms = 0U;   /* variable increments each millisecond */
43 
44 
45 /* main ***********************************************************************/
main(void)46 int main (void){
47     CO_NMT_reset_cmd_t reset = CO_RESET_NOT;
48 
49     /* Configure microcontroller. */
50 
51 
52     /* initialize EEPROM */
53 
54 
55     /* increase variable each startup. Variable is stored in EEPROM. */
56     OD_powerOnCounter++;
57 
58 
59     while(reset != CO_RESET_APP){
60 /* CANopen communication reset - initialize CANopen objects *******************/
61         CO_ReturnError_t err;
62         uint16_t timer1msPrevious;
63 
64         /* disable CAN and CAN interrupts */
65         struct CANbase canBase = {
66             .baseAddress = 0u,  /* CAN module address */
67         };
68 
69         /* initialize CANopen */
70         err = CO_init(&canBase, 10/* NodeID */, 125 /* bit rate */);
71         if(err != CO_ERROR_NO){
72             while(1);
73             /* CO_errorReport(CO->em, CO_EM_MEMORY_ALLOCATION_ERROR, CO_EMC_SOFTWARE_INTERNAL, err); */
74         }
75 
76 
77         /* Configure Timer interrupt function for execution every 1 millisecond */
78 
79 
80         /* Configure CAN transmit and receive interrupt */
81 
82 
83         /* start CAN */
84         CO_CANsetNormalMode(CO->CANmodule[0]);
85 
86         reset = CO_RESET_NOT;
87         timer1msPrevious = CO_timer1ms;
88 
89         while(reset == CO_RESET_NOT){
90 /* loop for normal program execution ******************************************/
91             uint16_t timer1msCopy, timer1msDiff;
92 
93             timer1msCopy = CO_timer1ms;
94             timer1msDiff = timer1msCopy - timer1msPrevious;
95             timer1msPrevious = timer1msCopy;
96 
97 
98             /* CANopen process */
99             reset = CO_process(CO, timer1msDiff, NULL);
100 
101             /* Nonblocking application code may go here. */
102 
103             /* Process EEPROM */
104         }
105     }
106 
107 
108 /* program exit ***************************************************************/
109     /* stop threads */
110 
111 
112     /* delete objects from memory */
113     CO_delete((void*) 0/* CAN module address */);
114 
115 
116     /* reset */
117     return 0;
118 }
119 
120 
121 /* timer thread executes in constant intervals ********************************/
tmrTask_thread(void)122 static void tmrTask_thread(void){
123 
124     for(;;) {
125 
126         /* sleep for interval */
127 
128         INCREMENT_1MS(CO_timer1ms);
129 
130         if(CO->CANmodule[0]->CANnormal) {
131             bool_t syncWas;
132 
133             /* Process Sync */
134             syncWas = CO_process_SYNC(CO, TMR_TASK_INTERVAL);
135 
136             /* Read inputs */
137             CO_process_RPDO(CO, syncWas);
138 
139             /* Further I/O or nonblocking application code may go here. */
140 
141             /* Write outputs */
142             CO_process_TPDO(CO, syncWas, TMR_TASK_INTERVAL);
143 
144             /* verify timer overflow */
145             if(0) {
146                 CO_errorReport(CO->em, CO_EM_ISR_TIMER_OVERFLOW, CO_EMC_SOFTWARE_INTERNAL, 0U);
147             }
148         }
149     }
150 }
151 
152 
153 /* CAN interrupt function *****************************************************/
CO_CAN1InterruptHandler(void)154 void /* interrupt */ CO_CAN1InterruptHandler(void){
155     CO_CANinterrupt(CO->CANmodule[0]);
156 
157 
158     /* clear interrupt flag */
159 }
160