├── README.md └── code ├── timer.h ├── can.h ├── timer.c ├── can.c ├── autosarNMServer.h ├── autosarNMServer.c ├── Driver_Common.h ├── autosarNM.h ├── Driver_Common.c └── autosarNM.c /README.md: -------------------------------------------------------------------------------- 1 | # autosar-nm 2 | autosar网络管理demo 3 | 4 | 5 | 2019-12-5 6 | 1. 参考了 https://github.com/sydyg/OSEK_NM 这里的架构设计; 7 | 2,仔细对比了标准文档的流程,暂时没发现问题; 8 | 3,暂时没实际验证; 9 | -------------------------------------------------------------------------------- /code/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIMER_H_ 2 | #define _TIMER_H_ 3 | 4 | // include "special mcu header" 5 | 6 | void TimerInit(void); 7 | void TimerStop(void); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /code/can.h: -------------------------------------------------------------------------------- 1 | #ifndef _CAN_H_ 2 | #define _CAN_H_ 3 | 4 | #include "autosarNM.h" 5 | #include "Driver_Common.h" 6 | int MCU_CAN_Transmit(NMPDU_t* NMPDU); 7 | void MCU_CAN_Init(void); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /code/timer.c: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | 3 | extern void Timer10(void); 4 | 5 | void TimerInit(void) 6 | { 7 | // add timer init period = 10ms 8 | } 9 | 10 | 11 | void TimerStop(void) 12 | { 13 | // add stop timer code here 14 | } 15 | 16 | // 定时器中断服务函数 17 | void TIME_IRQHandler(void) 18 | { 19 | Timer10(); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /code/can.c: -------------------------------------------------------------------------------- 1 | #include "can.h" 2 | 3 | void MCU_CAN_Init(void) 4 | { 5 | // add can init code here 6 | } 7 | 8 | 9 | /* 10 | return: 11 | 0: send fail 12 | 1: send success 13 | */ 14 | int MCU_CAN_Transmit(NMPDU_t* NMPDU) 15 | { 16 | // add can transmit code here 17 | 18 | return 1; 19 | } 20 | 21 | // CAN 中断服务函数 22 | void MCU_CAN_RX_IRQHandler(void) 23 | { 24 | NMPDU_t NMPDU; 25 | 26 | // 添加填充 NMPDU 27 | 28 | //将报文放入缓冲区,这里确保只有网络管理报文才可以放进缓冲区 29 | Recv_EveryMessage(&NMPDU); 30 | } 31 | -------------------------------------------------------------------------------- /code/autosarNMServer.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUTOSAR_NM_SERVER_H_ 2 | #define _AUTOSAR_NM_SERVER_H_ 3 | 4 | #include "autosarNM.h" 5 | 6 | #define E_OK 0 7 | #define E_ERROR -1 8 | 9 | typedef unsigned char StatusType_t; 10 | 11 | StatusType_t StartAutosarNM(void); 12 | StatusType_t StopAutosarNM(void); 13 | 14 | StatusType_t CanNm_PassiveStartup(void); 15 | StatusType_t CanNm_NetworkRequest(void); 16 | 17 | StatusType_t CanNm_NetworkReleases(void); 18 | StatusType_t RepeatMessageRequest(void); 19 | 20 | StatusType_t StartAutosarAppMsgSend(void); 21 | StatusType_t EnableAppMsgTxAndRx(void); 22 | StatusType_t DisableAppMsgTxAndRx(void); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /code/autosarNMServer.c: -------------------------------------------------------------------------------- 1 | #include "autosarNMServer.h" 2 | 3 | extern NMStateType_t NMCurrentState; 4 | extern NMStateType_t NMPreState; 5 | 6 | extern NMTypeU8_t NM_NodeCommReq; 7 | extern NMTypeU8_t NM_RepeatMsgReq; 8 | 9 | StatusType_t StartAutosarNM(void) 10 | { 11 | NMCurrentState = NM_INIT; 12 | NMPreState = NM_OFF; 13 | 14 | NMStateManage(); 15 | 16 | return E_OK; 17 | } 18 | 19 | StatusType_t StopAutosarNM(void) 20 | { 21 | NMCurrentState = NM_SHUTDOWN; 22 | NMPreState = NM_INIT; 23 | 24 | return E_OK; 25 | } 26 | 27 | StatusType_t CanNm_NetworkRequest(void) 28 | { 29 | NM_NodeCommReq = 1; 30 | } 31 | 32 | StatusType_t CanNm_NetworkReleases(void) 33 | { 34 | NM_NodeCommReq = 0; 35 | } 36 | 37 | StatusType_t RepeatMessageRequest(void) 38 | { 39 | NM_RepeatMsgReq = 1; 40 | } 41 | 42 | StatusType_t StartAutosarAppMsgSend(void) 43 | { 44 | 45 | } 46 | 47 | StatusType_t EnableAppMsgTxAndRx(void) 48 | { 49 | // 增加使能应用报文发送和接收前的处理 50 | } 51 | 52 | StatusType_t DisableAppMsgTxAndRx(void) 53 | { 54 | // 增加失能应用报文发送和接收前的处理 55 | } 56 | -------------------------------------------------------------------------------- /code/Driver_Common.h: -------------------------------------------------------------------------------- 1 | #ifndef _DRIVER_COMMON_H_ 2 | #define _DRIVER_COMMON_H_ 3 | 4 | #include "autosarNM.h" 5 | 6 | #define MCU_TYPE_MACRO 7 | 8 | #ifdef MCU_TYPE_MACRO 9 | #include "timer.h" 10 | #include "can.h" 11 | // #include "uart.h" 12 | #endif 13 | 14 | /*平台无关的定义*/ 15 | typedef int TimerOutFlag_t; 16 | 17 | #define NMID (0x0cffA019) 18 | #define NMSNI (0x19) 19 | 20 | #define TIMER_PERIOD (10) 21 | 22 | #define T_REPEAT_MESSAGE (1500) 23 | #define T_NM_TIMEOUT (2000) 24 | #define T_WAIT_BUS_SLEEP (2000) 25 | #define T_START_NM_TX (50) 26 | #define T_START_App_TX (20) 27 | #define T_NM_ImmediateCycleTime (20) 28 | #define T_NM_MessageCycle (500) 29 | #define T_WakeUp (100) 30 | 31 | #define N_ImmediateNM_TIMES (5) 32 | 33 | #define NM_TIMER_REPEAT_MSG (0) 34 | #define NM_TIMER_NM_TIMEOUT (1) 35 | #define NM_TIMER_WAIT_BUS_SLEEP (2) 36 | #define NM_TIMER_IMMEDIATE_CYCLE_TIME (3) 37 | #define NM_TIMER_NM_MSG_CYCLE (4) 38 | 39 | //FIFO大小 40 | #define FIFOMAX (20) 41 | 42 | 43 | //接受报文FIFO 44 | typedef struct { 45 | NMPDU_t MSGs[FIFOMAX];//FIFO缓冲区 46 | char Total;//FIFO中的报文数量 47 | char Head;//指向队列头 48 | char Tail;//指向队尾 49 | char FullFlag;//缓冲区满 50 | char EmptyFlag;//缓冲区空 51 | char(*GetMsg) (NMPDU_t* msg); //从缓冲区获取报文 52 | char(*SetMsg) (NMPDU_t* smsg); //放入报文到缓冲区 53 | void(*ClearBuff)(void);//清空FIFO 54 | }RecvFIFO_t; 55 | 56 | char SetToFIFO(NMPDU_t* msg); 57 | char GetFromFIFO(NMPDU_t* msg); 58 | void ClearFIFO(void); 59 | void InitPlatform(void); 60 | void InitNMPDU(NMPDU_t* NMPDU); 61 | NMTypeU8_t TX_CAN_Transmit(NMPDU_t* NMPDU); 62 | TimerOutFlag_t GetTimerIsOut(NMTimerType_t TimerType); 63 | void ClcTimerOutFlag(NMTimerType_t TimerType); 64 | void Recv_EveryMessage(NMPDU_t* p_Msg); 65 | 66 | #endif -------------------------------------------------------------------------------- /code/autosarNM.h: -------------------------------------------------------------------------------- 1 | #ifndef _AUTOSAR_NM_H_ 2 | #define _AUTOSAR_NM_H_ 3 | 4 | typedef unsigned char NMStateType_t; 5 | typedef unsigned char NMTypeU8_t; 6 | typedef unsigned int NMTypeU16_t; 7 | typedef unsigned long NMTypeU32_t; 8 | 9 | typedef unsigned int NMTimerType_t; 10 | 11 | typedef unsigned long NMMsgID_t; 12 | typedef unsigned char NMMsgSNI_t; 13 | typedef unsigned char NMMsgCtl_t; 14 | typedef unsigned char NMMsgData_t; 15 | 16 | enum 17 | { 18 | NM_SHUTDOWN = 255, 19 | NM_OFF = 0, 20 | NM_INIT, 21 | NM_BUS_SLEEP, 22 | NM_PRE_BUS_SLEEP, 23 | NM_REPEAT_MSG, 24 | NM_NORMAL_OP, 25 | NM_READY_SLEEP, 26 | }; 27 | 28 | #define AUTOSARNM_DLC (8) 29 | 30 | #define NM_CTRL_REPEAT_MSG (1 << 0) 31 | #define NM_CTRL_ACTIVE_WAKEUP (1 << 1) 32 | 33 | /* 34 | #define T_REPEAT_MESSAGE (1500) 35 | #define T_NM_TIMEOUT (2000) 36 | #define T_WAIT_BUS_SLEEP (2000) 37 | #define T_START_NM_TX (50) 38 | #define T_START_App_TX (20) 39 | #define T_NM_ImmediateCycleTime (20) 40 | #define T_NM_MessageCycle (500) 41 | #define T_WakeUp (100) 42 | #define N_ImmediateNM_TIMES (5) 43 | */ 44 | 45 | typedef struct 46 | { 47 | NMTypeU16_t t_repeat_message; 48 | NMTypeU16_t t_nm_timeout; 49 | NMTypeU16_t t_wait_bus_sleep; 50 | NMTypeU16_t t_start_nm_tx; 51 | NMTypeU16_t t_start_app_tx; 52 | NMTypeU16_t t_nm_immediate_cycle_time; 53 | NMTypeU16_t t_nm_message_cycle; 54 | NMTypeU16_t t_wake_up; 55 | NMTypeU8_t n_immediate_nm_times; 56 | }ConfPara_t; 57 | 58 | 59 | typedef struct 60 | { 61 | NMMsgID_t MsgID; //报文ID 62 | NMMsgSNI_t MsgSNI; //源节点地址 63 | NMMsgCtl_t MsgCtl;//控制字节 64 | NMMsgData_t MsgData[6];//数据域 65 | }NMPDU_t; 66 | 67 | 68 | void NMStateManage(void); 69 | 70 | #endif -------------------------------------------------------------------------------- /code/Driver_Common.c: -------------------------------------------------------------------------------- 1 | #include "Driver_Common.h" 2 | 3 | //报文缓冲区定义 4 | static RecvFIFO_t RecvFIFO; 5 | 6 | /* 7 | #define NM_TIMER_REPEAT_MSG (0) 8 | #define NM_TIMER_NM_TIMEOUT (1) 9 | #define NM_TIMER_WAIT_BUS_SLEEP (2) 10 | #define NM_TIMER_IMMEDIATE_CYCLE_TIME (3) 11 | #define NM_TIMER_NM_MSG_CYCLE (4) 12 | */ 13 | 14 | //定时器设置 15 | static char SetAlarm_REPEAT_MSG = 0; 16 | static char SetAlarm_NM_TIMEOUT = 0; 17 | static char SetAlarm_WAIT_BUS_SLEEP = 0; 18 | static char SetAlarm_IMMEDIATE_CYCLE_TIME = 0; 19 | static char SetAlarm_NM_MSG_CYCLE = 0; 20 | 21 | //定时器计数器 22 | static int REPEAT_MSG_Count = 0; 23 | static int NM_TIMEOUT_Count = 0; 24 | static int WAIT_BUS_SLEEP_Count = 0; 25 | static int IMMEDIATE_CYCLE_TIME_Count = 0; 26 | static int NM_MSG_CYCLE_Count = 0; 27 | 28 | //报文缓冲区定义 29 | static RecvFIFO_t RecvFIFO; 30 | 31 | //定时器超时标志 32 | static TimerOutFlag_t TimerOutFlag_REPEAT_MSG = 0; 33 | static TimerOutFlag_t TimerOutFlag_NM_TIMEOUT = 0; 34 | static TimerOutFlag_t TimerOutFlag_WAIT_BUS_SLEEP = 0; 35 | static TimerOutFlag_t TimerOutFlag_IMMEDIATE_CYCLE_TIME = 0; 36 | static TimerOutFlag_t TimerOutFlag_NM_MSG_CYCLE = 0; 37 | 38 | void InitPlatform(void) 39 | { 40 | /*缓冲区初始化*/ 41 | RecvFIFO.GetMsg = GetFromFIFO; 42 | RecvFIFO.SetMsg = SetToFIFO; 43 | RecvFIFO.ClearBuff = ClearFIFO; 44 | RecvFIFO.ClearBuff(); 45 | /*1.STM32相关的初始化*/ 46 | #ifdef MCU_TYPE_MACRO 47 | /*定时器初始化*/ 48 | TimerInit();//10ms中断一次 49 | /*CAN模块初始化*/ 50 | MCU_CAN_Init(); 51 | #endif 52 | } 53 | 54 | /*函数名:TX_CAN_Transmit 55 | *参数:NMPDU 56 | *返回值:成功 1 57 | *说明:调用平台相关的报文发送函数 58 | */ 59 | NMTypeU8_t TX_CAN_Transmit(NMPDU_t* NMPDU) 60 | { 61 | /*发送报文到总线*/ 62 | #ifdef MCU_TYPE_MACRO 63 | return MCU_CAN_Transmit(NMPDU); 64 | #endif 65 | } 66 | 67 | //NMPDU初始化,保留位置1 68 | void InitNMPDU(NMPDU_t* NMPDU) 69 | { 70 | int i = 0; 71 | NMPDU->MsgID = NMID; 72 | NMPDU->MsgSNI = NMSNI; 73 | NMPDU->MsgCtl = 0x00; 74 | 75 | for (; i < 6; i++) 76 | { 77 | NMPDU->MsgData[i] = 0xff; 78 | } 79 | } 80 | 81 | //返回定时器是否超时,-1 失败 82 | TimerOutFlag_t GetTimerIsOut(NMTimerType_t TimerType) 83 | { 84 | switch (TimerType) 85 | { 86 | case NM_TIMER_REPEAT_MSG: 87 | return TimerOutFlag_REPEAT_MSG; 88 | case NM_TIMER_NM_TIMEOUT: 89 | return TimerOutFlag_NM_TIMEOUT; 90 | case NM_TIMER_WAIT_BUS_SLEEP: 91 | return TimerOutFlag_WAIT_BUS_SLEEP; 92 | case NM_TIMER_IMMEDIATE_CYCLE_TIME: 93 | return TimerOutFlag_IMMEDIATE_CYCLE_TIME; 94 | case NM_TIMER_NM_MSG_CYCLE: 95 | return TimerOutFlag_NM_MSG_CYCLE; 96 | } 97 | return -1; 98 | } 99 | 100 | //清除定时器超时标志 101 | void ClcTimerOutFlag(NMTimerType_t TimerType) 102 | { 103 | switch (TimerType) 104 | { 105 | case NM_TIMER_REPEAT_MSG: 106 | TimerOutFlag_REPEAT_MSG = 0; 107 | break; 108 | case NM_TIMER_NM_TIMEOUT: 109 | TimerOutFlag_NM_TIMEOUT = 0; 110 | break; 111 | case NM_TIMER_WAIT_BUS_SLEEP: 112 | TimerOutFlag_WAIT_BUS_SLEEP = 0; 113 | break; 114 | case NM_TIMER_IMMEDIATE_CYCLE_TIME: 115 | TimerOutFlag_IMMEDIATE_CYCLE_TIME = 0; 116 | break; 117 | case NM_TIMER_NM_MSG_CYCLE: 118 | TimerOutFlag_NM_MSG_CYCLE = 0; 119 | break; 120 | } 121 | } 122 | 123 | 124 | //FIFO相关的函数 125 | /*说明:SetFIFO,将收到的报文放入FIFO,并调整FIFO 126 | * 参数:GenericMessage* msg,报文指针 127 | * 返回值:1:成功放入报文到FIFO,0:放入失败 128 | */ 129 | char SetToFIFO(NMPDU_t* msg) 130 | { 131 | if (RecvFIFO.FullFlag == 1)//先判断缓冲区满否 132 | return 0; 133 | /*放入报文到缓冲区*/ 134 | RecvFIFO.MSGs[RecvFIFO.Tail% FIFOMAX] = *msg; 135 | RecvFIFO.Tail = (RecvFIFO.Tail + 1) % FIFOMAX; 136 | /*清除空标识*/ 137 | RecvFIFO.EmptyFlag = 0; 138 | if ((RecvFIFO.Tail + 1) == RecvFIFO.Head)//缓冲区满 139 | RecvFIFO.FullFlag = 1; 140 | return 1; 141 | } 142 | /*说明:GetFIFO,从FIFO取出报文,并调整FIFO 143 | * 参数:GenericMessage* msg,报文指针 144 | * 返回值:1:成功取出报文,0:取出失败 145 | */ 146 | char GetFromFIFO(NMPDU_t* msg) 147 | { 148 | int i = 2; 149 | if (RecvFIFO.EmptyFlag == 1)//先判断缓冲区空否 150 | return 0; 151 | /*从缓冲区取出报文*/ 152 | msg->MsgSNI = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgSNI; 153 | msg->MsgCtl = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgCtl; 154 | msg->MsgID = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgID; 155 | //数据域直接复制 156 | for (; i < AUTOSARNM_DLC; i++) 157 | { 158 | msg->MsgData[i] = RecvFIFO.MSGs[RecvFIFO.Head% FIFOMAX].MsgData[i]; 159 | } 160 | RecvFIFO.Head = (RecvFIFO.Head + 1) % FIFOMAX; 161 | /*清除满标识*/ 162 | RecvFIFO.FullFlag = 0; 163 | if ((RecvFIFO.Tail) == RecvFIFO.Head)//缓冲区空 164 | RecvFIFO.EmptyFlag = 1; 165 | return 1; 166 | } 167 | /*说明:ClearFIFO,清空整个FIFO 168 | * 参数:void 169 | * 返回值:void 170 | */ 171 | void ClearFIFO(void) 172 | { 173 | RecvFIFO.Total = 0; 174 | RecvFIFO.Head = 0; 175 | RecvFIFO.Tail = 0; 176 | RecvFIFO.FullFlag = 0; 177 | RecvFIFO.EmptyFlag = 1; 178 | } 179 | 180 | //10ms定时器 181 | void Timer10() 182 | { 183 | /*调用SetAlarm(xx),定时器开始递增*/ 184 | if (SetAlarm_REPEAT_MSG) 185 | { 186 | REPEAT_MSG_Count++; 187 | 188 | if (REPEAT_MSG_Count >= (T_REPEAT_MESSAGE / TIMER_PERIOD))// T_REPEAT_MESSAGE=1500ms 189 | { 190 | REPEAT_MSG_Count = 0;//重新计数 191 | TimerOutFlag_REPEAT_MSG = 1; 192 | SetAlarm_REPEAT_MSG = 0;//每次用完定时器都将其关闭,从而简化定时器管理 193 | } 194 | } 195 | else { 196 | REPEAT_MSG_Count = 0; 197 | } 198 | 199 | if (SetAlarm_NM_TIMEOUT) 200 | { 201 | NM_TIMEOUT_Count++; 202 | if (NM_TIMEOUT_Count >= (T_NM_TIMEOUT / TIMER_PERIOD))//T_NM_TIMEOUT=2000ms 203 | { 204 | NM_TIMEOUT_Count = 0;//重新计数 205 | TimerOutFlag_NM_TIMEOUT = 1; 206 | SetAlarm_NM_TIMEOUT = 0;//每次用完定时器都将其关闭 207 | } 208 | } 209 | else { 210 | NM_TIMEOUT_Count = 0; 211 | } 212 | 213 | if (SetAlarm_WAIT_BUS_SLEEP) 214 | { 215 | WAIT_BUS_SLEEP_Count++; 216 | if (WAIT_BUS_SLEEP_Count >= 100)//TError=1000ms 217 | { 218 | WAIT_BUS_SLEEP_Count = 0;//重新计数 219 | TimerOutFlag_WAIT_BUS_SLEEP = 1; 220 | SetAlarm_WAIT_BUS_SLEEP = 0;//每次用完定时器都将其关闭 221 | } 222 | } 223 | else { 224 | WAIT_BUS_SLEEP_Count = 0; 225 | } 226 | 227 | if (SetAlarm_IMMEDIATE_CYCLE_TIME) 228 | { 229 | IMMEDIATE_CYCLE_TIME_Count++; 230 | if (IMMEDIATE_CYCLE_TIME_Count >= (T_NM_ImmediateCycleTime / TIMER_PERIOD))//T_NM_ImmediateCycleTime=20ms 231 | { 232 | IMMEDIATE_CYCLE_TIME_Count = 0;//重新计数 233 | TimerOutFlag_IMMEDIATE_CYCLE_TIME = 1; 234 | SetAlarm_IMMEDIATE_CYCLE_TIME = 0;//每次用完定时器都将其关闭 235 | } 236 | } 237 | else { 238 | IMMEDIATE_CYCLE_TIME_Count = 0; 239 | } 240 | 241 | if (SetAlarm_NM_MSG_CYCLE) 242 | { 243 | NM_MSG_CYCLE_Count++; 244 | if (NM_MSG_CYCLE_Count >= (T_NM_MessageCycle / TIMER_PERIOD))//T_NM_MessageCycle=500ms 245 | { 246 | NM_MSG_CYCLE_Count = 0;//重新计数 247 | TimerOutFlag_NM_MSG_CYCLE = 1; 248 | SetAlarm_NM_MSG_CYCLE = 0;//每次用完定时器都将其关闭 249 | } 250 | } 251 | else { 252 | NM_MSG_CYCLE_Count = 0; 253 | } 254 | } 255 | 256 | /* 257 | *自定义定时器函数:SetAlarm 258 | 参数:定时器类型 259 | 说明:每次调用都使定时器重新从0开始 260 | *返回值:定时器ID,用定时器类型ID代替定时器ID 261 | */ 262 | int SetAlarm(NMTimerType_t timer) 263 | { 264 | int Tid = 0; 265 | switch (timer) 266 | { 267 | case NM_TIMER_REPEAT_MSG: 268 | REPEAT_MSG_Count = 0; 269 | SetAlarm_REPEAT_MSG = 1; 270 | TimerOutFlag_REPEAT_MSG = 0;//每次设置定时器前先清除标志位 271 | Tid = NM_TIMER_REPEAT_MSG; 272 | break; 273 | case NM_TIMER_NM_TIMEOUT: 274 | NM_TIMEOUT_Count = 0; 275 | SetAlarm_NM_TIMEOUT = 1; 276 | TimerOutFlag_NM_TIMEOUT = 0;//每次设置定时器前先清除标志位 277 | Tid = NM_TIMER_NM_TIMEOUT; 278 | break; 279 | case NM_TIMER_WAIT_BUS_SLEEP: 280 | WAIT_BUS_SLEEP_Count = 0; 281 | SetAlarm_WAIT_BUS_SLEEP = 1; 282 | TimerOutFlag_WAIT_BUS_SLEEP = 0;//每次设置定时器前先清除标志位 283 | Tid = NM_TIMER_WAIT_BUS_SLEEP; 284 | break; 285 | case NM_TIMER_IMMEDIATE_CYCLE_TIME: 286 | IMMEDIATE_CYCLE_TIME_Count = 0; 287 | SetAlarm_IMMEDIATE_CYCLE_TIME = 1; 288 | TimerOutFlag_IMMEDIATE_CYCLE_TIME = 0;//每次设置定时器前先清除标志位 289 | Tid = NM_TIMER_IMMEDIATE_CYCLE_TIME; 290 | break; 291 | case NM_TIMER_NM_MSG_CYCLE: 292 | NM_MSG_CYCLE_Count = 0; 293 | SetAlarm_NM_MSG_CYCLE = 1; 294 | TimerOutFlag_NM_MSG_CYCLE = 0;//每次设置定时器前先清除标志位 295 | Tid = NM_TIMER_NM_MSG_CYCLE; 296 | break; 297 | } 298 | return Tid; 299 | } 300 | /* 301 | *自定义定时器函数:CancelAlarm 302 | 参数:定时器类型 303 | 说明:定时器清0,不再计数 304 | */ 305 | void CancelAlarm(NMTimerType_t timer) 306 | { 307 | switch (timer) 308 | { 309 | case NM_TIMER_REPEAT_MSG: 310 | SetAlarm_REPEAT_MSG = 0; 311 | REPEAT_MSG_Count = 0; 312 | TimerOutFlag_REPEAT_MSG = 0;//每次关闭定时器先清除标志位 313 | break; 314 | case NM_TIMER_NM_TIMEOUT: 315 | NM_TIMEOUT_Count = 0; 316 | SetAlarm_NM_TIMEOUT = 0; 317 | TimerOutFlag_NM_TIMEOUT = 0;//每次关闭定时器先清除标志位 318 | break; 319 | case NM_TIMER_WAIT_BUS_SLEEP: 320 | WAIT_BUS_SLEEP_Count = 0; 321 | SetAlarm_WAIT_BUS_SLEEP = 0; 322 | TimerOutFlag_WAIT_BUS_SLEEP = 0;//每次关闭定时器先清除标志位 323 | break; 324 | case NM_TIMER_IMMEDIATE_CYCLE_TIME: 325 | IMMEDIATE_CYCLE_TIME_Count = 0; 326 | SetAlarm_IMMEDIATE_CYCLE_TIME = 0; 327 | TimerOutFlag_IMMEDIATE_CYCLE_TIME = 0;//每次关闭定时器先清除标志位 328 | break; 329 | case NM_TIMER_NM_MSG_CYCLE: 330 | NM_MSG_CYCLE_Count = 0; 331 | SetAlarm_NM_MSG_CYCLE = 0; 332 | TimerOutFlag_NM_MSG_CYCLE = 0;//每次关闭定时器先清除标志位 333 | break; 334 | } 335 | } 336 | /*CAN中断收到的报文*/ 337 | void Recv_EveryMessage(NMPDU_t* p_Msg) 338 | { 339 | /*将所有收到的NM报文放入缓冲区FIFO*/ 340 | if (((p_Msg->MsgID) != NMID) && ((p_Msg->MsgID>>8) == (NMID>>8)))//过滤网络报文,不接收自己发出去的 341 | { 342 | RecvFIFO.SetMsg(p_Msg);//暂时不处理返回值 343 | } 344 | } -------------------------------------------------------------------------------- /code/autosarNM.c: -------------------------------------------------------------------------------- 1 | #include "autosarNM.h" 2 | #include "Driver_Common.h" 3 | #include "autosarNMServer.h" 4 | 5 | // 串口相关的部分这里没涉及 6 | #define AUTOSARNM_DEBUG 7 | #ifdef AUTOSARNM_DEBUG 8 | #define AUTOSARNM_PRINT(...) printf(__VA_ARGS__) 9 | #else 10 | #define AUTOSARNM_PRINT(...) 11 | #endif 12 | 13 | NMStateType_t NMCurrentState = NM_OFF; 14 | NMStateType_t NMPreState = NM_OFF; 15 | 16 | ConfPara_t ConfigPara; 17 | 18 | NMTypeU8_t NM_NodeCommReq = 0; 19 | NMTypeU8_t NM_RepeatMsgReq = 0; 20 | 21 | static void NMInit(void) 22 | { 23 | AUTOSARNM_PRINT("NMInit\n"); 24 | 25 | ConfigPara.t_repeat_message = T_REPEAT_MESSAGE; 26 | ConfigPara.t_nm_timeout = T_NM_TIMEOUT; 27 | ConfigPara.t_wait_bus_sleep = T_WAIT_BUS_SLEEP; 28 | ConfigPara.t_start_nm_tx = T_START_NM_TX; 29 | ConfigPara.t_start_app_tx = T_START_App_TX; 30 | ConfigPara.t_nm_immediate_cycle_time = T_NM_ImmediateCycleTime; 31 | ConfigPara.t_nm_message_cycle = T_NM_MessageCycle; 32 | ConfigPara.t_wake_up = T_WakeUp; 33 | ConfigPara.n_immediate_nm_times = N_ImmediateNM_TIMES; 34 | 35 | InitPlatform(); 36 | 37 | // 失能应用报文发送和接收 38 | DisableAppMsgTxAndRx(); 39 | 40 | NMCurrentState = NM_BUS_SLEEP; 41 | NMPreState = NM_INIT; 42 | } 43 | 44 | static void NMBusSleep(void) 45 | { 46 | NMPDU_t NMMsgRecv; 47 | 48 | AUTOSARNM_PRINT("NMBusSleep\n"); 49 | 50 | while(1) 51 | { 52 | // 收到其他节点发送的网络管理报文 53 | if(GetFromFIFO(&NMMsgRecv)) 54 | { 55 | AUTOSARNM_PRINT("receive id:%lx sni:%x\n", NMMsgRecv.MsgID, NMMsgRecv.MsgSNI); 56 | 57 | NMCurrentState = NM_REPEAT_MSG; 58 | NMPreState = NM_BUS_SLEEP; 59 | 60 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 61 | SetAlarm(NM_TIMER_NM_TIMEOUT); 62 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 63 | 64 | break; 65 | } 66 | 67 | // 如果当前节点需要与其他节点通信,则进入重复发送报文状态 68 | if(NM_NodeCommReq) 69 | { 70 | AUTOSARNM_PRINT("NM_NodeCommReq = 1\n"); 71 | 72 | NMCurrentState = NM_REPEAT_MSG; 73 | NMPreState = NM_BUS_SLEEP; 74 | 75 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 76 | SetAlarm(NM_TIMER_NM_TIMEOUT); 77 | 78 | break; 79 | } 80 | } // end while 81 | } 82 | 83 | static void NMRepeatMsg(void) 84 | { 85 | NMTypeU8_t N_ImmediateNM_TIMES_Cnt = 0; 86 | NMPDU_t NMMsgTx; 87 | NMPDU_t NMMsgRecv; 88 | NMTypeU8_t NMTxFlag = 0; 89 | 90 | AUTOSARNM_PRINT("NMRepeatMsg\n"); 91 | 92 | // 使能应用报文的发送和接受 93 | EnableAppMsgTxAndRx(); 94 | 95 | InitNMPDU(&NMMsgTx); 96 | 97 | // 如果是因为节点需要通信进来的,则开启 NM_TIMER_IMMEDIATE_CYCLE_TIME 定时器 98 | if(NM_NodeCommReq) 99 | { 100 | NMMsgTx.MsgCtl |= NM_CTRL_ACTIVE_WAKEUP; 101 | 102 | SetAlarm(NM_TIMER_IMMEDIATE_CYCLE_TIME); 103 | } 104 | 105 | // 如果通过 repeatMessageRequest 函数调用而进入重复报文状态的,则开启 NM_TIMER_IMMEDIATE_CYCLE_TIME 定时器 106 | if(NM_RepeatMsgReq) 107 | { 108 | NM_RepeatMsgReq = 0; 109 | 110 | NMMsgTx.MsgCtl |= NM_CTRL_REPEAT_MSG; 111 | 112 | SetAlarm(NM_TIMER_IMMEDIATE_CYCLE_TIME); 113 | } 114 | 115 | // 先发送一帧 116 | NMTxFlag = TX_CAN_Transmit(&NMMsgTx); 117 | 118 | // 如果是从总线睡眠模式或准备总线睡眠模式进入到重复报文状态,则在发送第一帧网络管理报文后在 T_START_App_TX 时间内将第一帧 CAN应用报文发送出来 119 | if((NMPreState == NM_BUS_SLEEP) || (NMPreState == NM_PRE_BUS_SLEEP)) 120 | { 121 | StartAutosarAppMsgSend(); 122 | } 123 | 124 | while(1) 125 | { 126 | if(GetTimerIsOut(NM_TIMER_IMMEDIATE_CYCLE_TIME)) 127 | { 128 | CancelAlarm(NM_TIMER_IMMEDIATE_CYCLE_TIME); 129 | 130 | N_ImmediateNM_TIMES_Cnt += 1; 131 | 132 | // send nm msg 133 | NMTxFlag = TX_CAN_Transmit(&NMMsgTx); 134 | 135 | if(N_ImmediateNM_TIMES_Cnt <= (N_ImmediateNM_TIMES - 1)) 136 | SetAlarm(NM_TIMER_IMMEDIATE_CYCLE_TIME); 137 | else 138 | { 139 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 140 | } 141 | } 142 | 143 | // 成功发送CAN报文,重启 NM_TIMER_NM_TIMEOUT 144 | if(NMTxFlag) 145 | { 146 | NMTxFlag = 0; 147 | 148 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 149 | SetAlarm(NM_TIMER_NM_TIMEOUT); 150 | } 151 | 152 | // 收到其他节点发送的网络管理报文,重启 NM_TIMER_NM_TIMEOUT 153 | if(GetFromFIFO(&NMMsgRecv)) 154 | { 155 | AUTOSARNM_PRINT("receive id:%lx sni:%x\n", NMMsgRecv.MsgID, NMMsgRecv.MsgSNI); 156 | 157 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 158 | SetAlarm(NM_TIMER_NM_TIMEOUT); 159 | } 160 | 161 | if(GetTimerIsOut(NM_TIMER_NM_MSG_CYCLE)) 162 | { 163 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 164 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 165 | 166 | // send nm msg 167 | NMTxFlag = TX_CAN_Transmit(&NMMsgTx); 168 | } 169 | 170 | if(GetTimerIsOut(NM_TIMER_NM_TIMEOUT)) 171 | { 172 | // 重启 NM_TIMEOUT 173 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 174 | SetAlarm(NM_TIMER_NM_TIMEOUT); 175 | } 176 | 177 | if(GetTimerIsOut(NM_TIMER_REPEAT_MSG)) 178 | { 179 | // NM_NodeCommReq = 1,表示当前节点需要与网络上其他节点通信,准备进入 NM_NORMAL_OP 状态 180 | if(NM_NodeCommReq) 181 | { 182 | // REPEAT_MSG 超时要进入正常操作模式 183 | CancelAlarm(NM_TIMER_REPEAT_MSG); 184 | 185 | // 进入到 NM_NORMAL_OP 状态时不关闭 NM_TIMER_NM_MSG_CYCLE 和 NM_TIMER_NM_TIMEOUT 定时器 186 | 187 | NMCurrentState = NM_NORMAL_OP; 188 | NMPreState = NM_REPEAT_MSG; 189 | 190 | break; 191 | } 192 | // NM_NodeCommReq = 0,表示当前节点不再需要与网络上其他节点通信,准备进入 NM_READY_SLEEP 状态 193 | else 194 | { 195 | CancelAlarm(NM_TIMER_REPEAT_MSG); 196 | 197 | NMCurrentState = NM_READY_SLEEP; 198 | NMPreState = NM_REPEAT_MSG; 199 | 200 | break; 201 | } 202 | 203 | } 204 | } // end while 205 | } 206 | 207 | static void NMNormalOperation(void) 208 | { 209 | NMPDU_t NMMsgTx; 210 | NMPDU_t NMMsgRecv; 211 | NMTypeU8_t NMTxFlag = 0; 212 | 213 | AUTOSARNM_PRINT("NMNormalOperation\n"); 214 | 215 | InitNMPDU(&NMMsgTx); 216 | 217 | if(NM_NodeCommReq) 218 | { 219 | NMMsgTx.MsgCtl |= NM_CTRL_ACTIVE_WAKEUP; 220 | } 221 | 222 | while(1) 223 | { 224 | if(GetTimerIsOut(NM_TIMER_NM_MSG_CYCLE)) 225 | { 226 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 227 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 228 | 229 | // send nm msg 230 | NMTxFlag = TX_CAN_Transmit(&NMMsgTx); 231 | } 232 | 233 | if(GetTimerIsOut(NM_TIMER_NM_TIMEOUT)) 234 | { 235 | // 重启 NM_TIMEOUT 236 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 237 | SetAlarm(NM_TIMER_NM_TIMEOUT); 238 | } 239 | 240 | // 成功发送CAN报文,重启 NM_TIMER_NM_TIMEOUT 241 | if(NMTxFlag) 242 | { 243 | NMTxFlag = 0; 244 | 245 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 246 | 247 | SetAlarm(NM_TIMER_NM_TIMEOUT); 248 | } 249 | 250 | // 收到其他节点发送的网络管理报文,重启 NM_TIMER_NM_TIMEOUT 251 | if(GetFromFIFO(&NMMsgRecv)) 252 | { 253 | AUTOSARNM_PRINT("receive id:%lx sni:%x\n", NMMsgRecv.MsgID, NMMsgRecv.MsgSNI); 254 | 255 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 256 | SetAlarm(NM_TIMER_NM_TIMEOUT); 257 | 258 | // 如果收到 repeat message request bit 为1 的网络管理报文, 则进入重复报文状态 259 | if(NMMsgRecv.MsgCtl & NM_CTRL_REPEAT_MSG) 260 | { 261 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 262 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 263 | 264 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 265 | SetAlarm(NM_TIMER_NM_TIMEOUT); 266 | 267 | NMCurrentState = NM_REPEAT_MSG; 268 | NMPreState = NM_NORMAL_OP; 269 | 270 | break; 271 | } 272 | } 273 | 274 | // 如果 repeatMessageRequest 函数被调用需进入重复报文状态 275 | if(NM_RepeatMsgReq) 276 | { 277 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 278 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 279 | 280 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 281 | SetAlarm(NM_TIMER_NM_TIMEOUT); 282 | 283 | NMCurrentState = NM_REPEAT_MSG; 284 | NMPreState = NM_NORMAL_OP; 285 | 286 | break; 287 | } 288 | 289 | // 如果本地睡眠条件满足,即不需要与其他节点通信,则进入准备睡眠状态 290 | if(!NM_NodeCommReq) 291 | { 292 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 293 | 294 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 295 | SetAlarm(NM_TIMER_NM_TIMEOUT); 296 | 297 | NMCurrentState = NM_READY_SLEEP; 298 | NMPreState = NM_NORMAL_OP; 299 | 300 | break; 301 | } 302 | } // end while 303 | } 304 | 305 | static void NMReadySleepState(void) 306 | { 307 | NMPDU_t NMMsgRecv; 308 | 309 | AUTOSARNM_PRINT("NMReadySleepState\n"); 310 | 311 | while(1) 312 | { 313 | // 如果 NM_TIMER_NM_TIMEOUT 超时,则进入准备总线睡眠状态 314 | if(GetTimerIsOut(NM_TIMER_NM_TIMEOUT)) 315 | { 316 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 317 | 318 | CancelAlarm(NM_TIMER_WAIT_BUS_SLEEP); 319 | SetAlarm(NM_TIMER_WAIT_BUS_SLEEP); 320 | 321 | NMCurrentState = NM_PRE_BUS_SLEEP; 322 | NMPreState = NM_READY_SLEEP; 323 | 324 | break; 325 | } 326 | 327 | // 收到其他节点发送的网络管理报文,重启 NM_TIMER_NM_TIMEOUT 328 | if(GetFromFIFO(&NMMsgRecv)) 329 | { 330 | AUTOSARNM_PRINT("receive id:%lx sni:%x\n", NMMsgRecv.MsgID, NMMsgRecv.MsgSNI); 331 | 332 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 333 | SetAlarm(NM_TIMER_NM_TIMEOUT); 334 | 335 | // 如果收到 repeat message request bit 为1 的网络管理报文, 则进入重复报文状态 336 | if(NMMsgRecv.MsgCtl & NM_CTRL_REPEAT_MSG) 337 | { 338 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 339 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 340 | 341 | NMCurrentState = NM_REPEAT_MSG; 342 | NMPreState = NM_READY_SLEEP; 343 | 344 | break; 345 | } 346 | } 347 | 348 | // 如果 repeatMessageRequest 函数被调用需进入重复报文状态 349 | if(NM_RepeatMsgReq) 350 | { 351 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 352 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 353 | 354 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 355 | SetAlarm(NM_TIMER_NM_TIMEOUT); 356 | 357 | NMCurrentState = NM_REPEAT_MSG; 358 | NMPreState = NM_READY_SLEEP; 359 | 360 | break; 361 | } 362 | 363 | // 如果本地睡眠条件不再满足,则进入正常操作状态 364 | if(NM_NodeCommReq) 365 | { 366 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 367 | SetAlarm(NM_TIMER_NM_TIMEOUT); 368 | 369 | NMCurrentState = NM_NORMAL_OP; 370 | NMPreState = NM_READY_SLEEP; 371 | 372 | break; 373 | } 374 | } // end while 375 | } 376 | 377 | static void NMPreBusSleep(void) 378 | { 379 | NMPDU_t NMMsgRecv; 380 | 381 | AUTOSARNM_PRINT("NMPreBusSleep\n"); 382 | 383 | // 失能应用报文发送和接收 384 | DisableAppMsgTxAndRx(); 385 | 386 | while(1) 387 | { 388 | // 如果 NM_TIMER_WAIT_BUS_SLEEP 超时,则进入总线睡眠模式 389 | if(GetTimerIsOut(NM_TIMER_WAIT_BUS_SLEEP)) 390 | { 391 | CancelAlarm(NM_TIMER_WAIT_BUS_SLEEP); 392 | 393 | NMCurrentState = NM_BUS_SLEEP; 394 | NMPreState = NM_PRE_BUS_SLEEP; 395 | 396 | break; 397 | } 398 | 399 | // 收到其他节点发送的网络管理报文,进入重复报文状态 400 | if(GetFromFIFO(&NMMsgRecv)) 401 | { 402 | AUTOSARNM_PRINT("receive id:%lx sni:%x\n", NMMsgRecv.MsgID, NMMsgRecv.MsgSNI); 403 | 404 | CancelAlarm(NM_TIMER_NM_MSG_CYCLE); 405 | SetAlarm(NM_TIMER_NM_MSG_CYCLE); 406 | 407 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 408 | SetAlarm(NM_TIMER_NM_TIMEOUT); 409 | 410 | NMCurrentState = NM_REPEAT_MSG; 411 | NMPreState = NM_PRE_BUS_SLEEP; 412 | 413 | break; 414 | } 415 | 416 | // 如果本地节点有通信需求,则进入重复报文状态 417 | if(NM_NodeCommReq) 418 | { 419 | CancelAlarm(NM_TIMER_NM_TIMEOUT); 420 | SetAlarm(NM_TIMER_NM_TIMEOUT); 421 | 422 | NMCurrentState = NM_REPEAT_MSG; 423 | NMPreState = NM_PRE_BUS_SLEEP; 424 | 425 | break; 426 | } 427 | } // end while 428 | } 429 | 430 | /* 431 | enum 432 | { 433 | NM_SHUTDOWN = 255, 434 | NM_OFF = 0, 435 | NM_INIT, 436 | NM_BUS_SLEEP, 437 | NM_PRE_BUS_SLEEP, 438 | NM_REPEAT_MSG, 439 | NM_NORMAL_OP, 440 | NM_READY_SLEEP, 441 | }; 442 | */ 443 | void NMStateManage(void) 444 | { 445 | while(1) 446 | { 447 | switch(NMCurrentState) 448 | { 449 | case NM_INIT: 450 | NMInit(); 451 | break; 452 | 453 | case NM_BUS_SLEEP: 454 | NMBusSleep(); 455 | break; 456 | 457 | case NM_REPEAT_MSG: 458 | NMRepeatMsg(); 459 | break; 460 | 461 | case NM_NORMAL_OP: 462 | NMNormalOperation(); 463 | break; 464 | 465 | case NM_READY_SLEEP: 466 | NMReadySleepState(); 467 | break; 468 | 469 | case NM_PRE_BUS_SLEEP: 470 | NMPreBusSleep(); 471 | break; 472 | } // end switch 473 | } // end while 474 | 475 | } --------------------------------------------------------------------------------