1 /** 2 * CANopen Network management and Heartbeat producer protocol. 3 * 4 * @file CO_NMT_Heartbeat.h 5 * @ingroup CO_NMT_Heartbeat 6 * @author Janez Paternoster 7 * @copyright 2004 - 2020 Janez Paternoster 8 * 9 * This file is part of CANopenNode, an opensource CANopen Stack. 10 * Project home page is <https://github.com/CANopenNode/CANopenNode>. 11 * For more information on CANopen see <http://www.can-cia.org/>. 12 * 13 * Licensed under the Apache License, Version 2.0 (the "License"); 14 * you may not use this file except in compliance with the License. 15 * You may obtain a copy of the License at 16 * 17 * http://www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, software 20 * distributed under the License is distributed on an "AS IS" BASIS, 21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 * See the License for the specific language governing permissions and 23 * limitations under the License. 24 */ 25 26 27 #ifndef CO_NMT_HEARTBEAT_H 28 #define CO_NMT_HEARTBEAT_H 29 30 #ifdef __cplusplus 31 extern "C" { 32 #endif 33 34 /** 35 * @defgroup CO_NMT_Heartbeat NMT and Heartbeat 36 * @ingroup CO_CANopen 37 * @{ 38 * 39 * CANopen Network management and Heartbeat producer protocol. 40 * 41 * CANopen device can be in one of the #CO_NMT_internalState_t 42 * - Initializing. It is active before CANopen is initialized. 43 * - Pre-operational. All CANopen objects are active, except PDOs. 44 * - Operational. Process data objects (PDOs) are active too. 45 * - Stopped. Only Heartbeat producer and NMT consumer are active. 46 * 47 * NMT master can change the internal state of the devices by sending 48 * #CO_NMT_command_t. 49 * 50 * ###NMT message contents: 51 * 52 * Byte | Description 53 * -----|----------------------------------------------------------- 54 * 0 | #CO_NMT_command_t 55 * 1 | Node ID. If zero, command addresses all nodes. 56 * 57 * ###Heartbeat message contents: 58 * 59 * Byte | Description 60 * -----|----------------------------------------------------------- 61 * 0 | #CO_NMT_internalState_t 62 * 63 * @see #CO_Default_CAN_ID_t 64 * 65 * ###Status LED diodes 66 * Macros for @ref CO_NMT_statusLEDdiodes are also implemented in this object. 67 */ 68 69 70 /** 71 * @defgroup CO_NMT_statusLEDdiodes Status LED diodes 72 * @{ 73 * 74 * Macros for status LED diodes. 75 * 76 * Helper macros for implementing status LED diodes are used by stack and can 77 * also be used by the application. If macro returns 1 LED should be ON, 78 * otherwise OFF. Function CO_NMT_blinkingProcess50ms() must be called cyclically 79 * to update the variables. 80 */ 81 #define LED_FLICKERING(NMT) (((NMT)->LEDflickering>=0) ? 1 : 0) /**< 10HZ (100MS INTERVAL) */ 82 #define LED_BLINKING(NMT) (((NMT)->LEDblinking>=0) ? 1 : 0) /**< 2.5HZ (400MS INTERVAL) */ 83 #define LED_SINGLE_FLASH(NMT) (((NMT)->LEDsingleFlash>=0) ? 1 : 0) /**< 200MS ON, 1000MS OFF */ 84 #define LED_DOUBLE_FLASH(NMT) (((NMT)->LEDdoubleFlash>=0) ? 1 : 0) /**< 200MS ON, 200MS OFF, 200MS ON, 1000MS OFF */ 85 #define LED_TRIPLE_FLASH(NMT) (((NMT)->LEDtripleFlash>=0) ? 1 : 0) /**< 200MS ON, 200MS OFF, 200MS ON, 200MS OFF, 200MS ON, 1000MS OFF */ 86 #define LED_QUADRUPLE_FLASH(NMT)(((NMT)->LEDquadrupleFlash>=0) ? 1 : 0) /**< 200MS ON, 200MS OFF, 200MS ON, 200MS OFF, 200MS ON, 200MS OFF, 200MS ON, 1000MS OFF */ 87 #define LED_GREEN_RUN(NMT) (((NMT)->LEDgreenRun>=0) ? 1 : 0) /**< CANOPEN RUN LED ACCORDING TO CIA DR 303-3 */ 88 #define LED_RED_ERROR(NMT) (((NMT)->LEDredError>=0) ? 1 : 0) /**< CANopen error LED according to CiA DR 303-3 */ 89 /** @} */ 90 91 92 /** 93 * Internal network state of the CANopen node 94 */ 95 typedef enum{ 96 CO_NMT_INITIALIZING = 0, /**< Device is initializing */ 97 CO_NMT_PRE_OPERATIONAL = 127, /**< Device is in pre-operational state */ 98 CO_NMT_OPERATIONAL = 5, /**< Device is in operational state */ 99 CO_NMT_STOPPED = 4 /**< Device is stopped */ 100 }CO_NMT_internalState_t; 101 102 103 /** 104 * Commands from NMT master. 105 */ 106 typedef enum{ 107 CO_NMT_ENTER_OPERATIONAL = 1, /**< Start device */ 108 CO_NMT_ENTER_STOPPED = 2, /**< Stop device */ 109 CO_NMT_ENTER_PRE_OPERATIONAL = 128, /**< Put device into pre-operational */ 110 CO_NMT_RESET_NODE = 129, /**< Reset device */ 111 CO_NMT_RESET_COMMUNICATION = 130 /**< Reset CANopen communication on device */ 112 }CO_NMT_command_t; 113 114 115 /** 116 * Return code for CO_NMT_process() that tells application code what to 117 * reset. 118 */ 119 typedef enum{ 120 CO_RESET_NOT = 0,/**< Normal return, no action */ 121 CO_RESET_COMM = 1,/**< Application must provide communication reset. */ 122 CO_RESET_APP = 2,/**< Application must provide complete device reset */ 123 CO_RESET_QUIT = 3 /**< Application must quit, no reset of microcontroller (command is not requested by the stack.) */ 124 }CO_NMT_reset_cmd_t; 125 126 127 /** 128 * NMT consumer and Heartbeat producer object. It includes also variables for 129 * @ref CO_NMT_statusLEDdiodes. Object is initialized by CO_NMT_init(). 130 */ 131 typedef struct{ 132 uint8_t operatingState; /**< See @ref CO_NMT_internalState_t */ 133 #ifdef CO_USE_LEDS 134 int8_t LEDflickering; /**< See @ref CO_NMT_statusLEDdiodes */ 135 int8_t LEDblinking; /**< See @ref CO_NMT_statusLEDdiodes */ 136 int8_t LEDsingleFlash; /**< See @ref CO_NMT_statusLEDdiodes */ 137 int8_t LEDdoubleFlash; /**< See @ref CO_NMT_statusLEDdiodes */ 138 int8_t LEDtripleFlash; /**< See @ref CO_NMT_statusLEDdiodes */ 139 int8_t LEDquadrupleFlash; /**< See @ref CO_NMT_statusLEDdiodes */ 140 int8_t LEDgreenRun; /**< See @ref CO_NMT_statusLEDdiodes */ 141 int8_t LEDredError; /**< See @ref CO_NMT_statusLEDdiodes */ 142 #endif /* CO_USE_LEDS */ 143 144 uint8_t resetCommand; /**< If different than zero, device will reset */ 145 uint8_t nodeId; /**< CANopen Node ID of this device */ 146 uint16_t HBproducerTimer;/**< Internal timer for HB producer */ 147 uint16_t firstHBTime; /**< From CO_NMT_init() */ 148 CO_EMpr_t *emPr; /**< From CO_NMT_init() */ 149 CO_CANmodule_t *HB_CANdev; /**< From CO_NMT_init() */ 150 void (*pFunctNMT)(CO_NMT_internalState_t state); /**< From CO_NMT_initCallback() or NULL */ 151 CO_CANtx_t *HB_TXbuff; /**< CAN transmit buffer */ 152 }CO_NMT_t; 153 154 155 /** 156 * Initialize NMT and Heartbeat producer object. 157 * 158 * Function must be called in the communication reset section. 159 * 160 * @param NMT This object will be initialized. 161 * @param emPr Emergency main object. 162 * @param nodeId CANopen Node ID of this device. 163 * @param firstHBTime Time between bootup and first heartbeat message in milliseconds. 164 * If firstHBTime is greater than _Producer Heartbeat time_ 165 * (object dictionary, index 0x1017), latter is used instead. 166 * @param NMT_CANdev CAN device for NMT reception. 167 * @param NMT_rxIdx Index of receive buffer in above CAN device. 168 * @param CANidRxNMT CAN identifier for NMT message. 169 * @param HB_CANdev CAN device for HB transmission. 170 * @param HB_txIdx Index of transmit buffer in the above CAN device. 171 * @param CANidTxHB CAN identifier for HB message. 172 * 173 * @return #CO_ReturnError_t CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT. 174 */ 175 CO_ReturnError_t CO_NMT_init( 176 CO_NMT_t *NMT, 177 CO_EMpr_t *emPr, 178 uint8_t nodeId, 179 uint16_t firstHBTime, 180 CO_CANmodule_t *NMT_CANdev, 181 uint16_t NMT_rxIdx, 182 uint16_t CANidRxNMT, 183 CO_CANmodule_t *HB_CANdev, 184 uint16_t HB_txIdx, 185 uint16_t CANidTxHB); 186 187 /** 188 * Initialize NMT callback function. 189 * 190 * Function initializes optional callback function, which is called after 191 * NMT State change has occured. Function may wake up external task which 192 * handles NMT events. 193 * The first call is made immediately to give the consumer the current NMT state. 194 * 195 * @remark Be aware that the callback function is run inside the CAN receive 196 * function context. Depending on the driver, this might be inside an interrupt! 197 * 198 * @param NMT This object. 199 * @param pFunctNMT Pointer to the callback function. Not called if NULL. 200 */ 201 void CO_NMT_initCallback( 202 CO_NMT_t *NMT, 203 void (*pFunctNMT)(CO_NMT_internalState_t state)); 204 205 206 /** 207 * Calculate blinking bytes. 208 * 209 * Function must be called cyclically every 50 milliseconds. See @ref CO_NMT_statusLEDdiodes. 210 * 211 * @param NMT NMT object. 212 */ 213 #ifdef CO_USE_LEDS 214 void CO_NMT_blinkingProcess50ms(CO_NMT_t *NMT); 215 #endif /* CO_USE_LEDS */ 216 217 218 /** 219 * Process received NMT and produce Heartbeat messages. 220 * 221 * Function must be called cyclically. 222 * 223 * @param NMT This object. 224 * @param timeDifference_ms Time difference from previous function call in [milliseconds]. 225 * @param HBtime _Producer Heartbeat time_ (object dictionary, index 0x1017). 226 * @param NMTstartup _NMT startup behavior_ (object dictionary, index 0x1F80). 227 * @param errorRegister _Error register_ (object dictionary, index 0x1001). 228 * @param errorBehavior pointer to _Error behavior_ array (object dictionary, index 0x1029). 229 * Object controls, if device should leave NMT operational state. 230 * Length of array must be 6. If pointer is NULL, no calculation is made. 231 * @param timerNext_ms Return value - info to OS - see CO_process(). 232 * 233 * @return #CO_NMT_reset_cmd_t 234 */ 235 CO_NMT_reset_cmd_t CO_NMT_process( 236 CO_NMT_t *NMT, 237 uint16_t timeDifference_ms, 238 uint16_t HBtime, 239 uint32_t NMTstartup, 240 uint8_t errorRegister, 241 const uint8_t errorBehavior[], 242 uint16_t *timerNext_ms); 243 244 245 /** 246 * Query current NMT state 247 * 248 * @param NMT This object. 249 * 250 * @return #CO_NMT_internalState_t 251 */ 252 CO_NMT_internalState_t CO_NMT_getInternalState( 253 CO_NMT_t *NMT); 254 255 256 #ifdef __cplusplus 257 } 258 #endif /*__cplusplus*/ 259 260 /** @} */ 261 #endif 262