XCP_SIM
win/hw.c
1 /*
2  * BlueParrot XCP
3  *
4  * (C) 2007-2022 by Christoph Schueler <github.com/Christoph2,
5  * cpu12.gems@googlemail.com>
6  *
7  * All Rights Reserved
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * s. FLOSS-EXCEPTION.txt
24  */
25 
26 #define _CRTDBG_MAP_ALLOC
27 
28 #include <crtdbg.h>
29 #include <ctype.h>
30 #include <fcntl.h>
31 #include <io.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <windows.h>
35 
37 #include "xcp.h"
38 #include "xcp_hw.h"
41 /*
42 ** Local Types.
43 */
44 typedef struct tagHwStateType {
45  LARGE_INTEGER StartingTime;
46  LARGE_INTEGER TicksPerSecond;
47 } HwStateType;
48 
49 /*
50 ** Local Defines.
51 */
52 #define TIMER_PS_1US (1000000UL)
53 #define TIMER_PS_10US (100000UL)
54 #define TIMER_PS_100US (10000UL)
55 
56 #define TIMER_PS_1MS (1000UL)
57 #define TIMER_PS_10MS (100UL)
58 #define TIMER_PS_100MS (10UL)
59 #define TIMER_PS_1S (1UL)
60 
61 /* Set timer prescaler value. */
62 #if XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_1US
63 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_1US)
64 #elif XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_10US
65 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_10US)
66 #elif XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_100US
67 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_100US)
68 #elif XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_1MS
69 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_1MS)
70 #elif XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_10MS
71 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_10MS)
72 #elif XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_100MS
73 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_100MS)
74 #elif XCP_DAQ_TIMESTAMP_UNIT == XCP_DAQ_TIMESTAMP_UNIT_1S
75 #define XCP_HW_TIMER_PRESCALER (TIMER_PS_1S)
76 #else
77 #error Timestamp-unit not supported.
78 #endif // XCP_DAQ_TIMESTAMP_UNIT
79 
80 #define TIMER_MASK_1 (0x000000FFUL)
81 #define TIMER_MASK_2 (0x0000FFFFUL)
82 #define TIMER_MASK_4 (0xFFFFFFFFUL)
83 
84 /*
85 ** Local Function Prototypes.
86 */
87 static void XcpHw_InitLocks(void);
88 
89 static void XcpHw_DeinitLocks();
90 
91 static uint64_t XcpHw_GetElapsedTime(uint32_t prescaler);
92 
93 /*
94 ** External Function Prototypes.
95 */
96 void XcpTl_PrintConnectionInformation(void);
97 
98 void FlsEmu_Info(void);
99 
100 void XcpDaq_Info(void);
101 
102 void XcpDaq_PrintDAQDetails();
103 
104 bool XcpDaq_QueueEmpty(void);
105 
106 bool XcpDaq_QueueDequeue(uint16_t *len, uint8_t *data);
107 
108 void XcpHw_MainFunction(void);
109 
110 void exitFunc(void);
111 
112 /*
113 ** Local Variables.
114 */
115 static HwStateType HwState = {0};
116 CRITICAL_SECTION XcpHw_Locks[XCP_HW_LOCK_COUNT];
117 
118 /*
119 ** Global Functions.
120 */
121 void XcpHw_Init(void) {
122  fflush(stdout);
123  QueryPerformanceFrequency(&HwState.TicksPerSecond);
124  QueryPerformanceCounter(&HwState.StartingTime);
125  XcpHw_InitLocks();
126 }
127 
128 void XcpHw_Deinit(void) { XcpHw_DeinitLocks(); }
129 
130 static uint64_t XcpHw_GetElapsedTime(uint32_t prescaler) {
131  /* TODO: check initialisation state. */
132  LARGE_INTEGER Now;
133  LARGE_INTEGER Elapsed;
134 
135  QueryPerformanceCounter(&Now);
136  Elapsed.QuadPart = Now.QuadPart - HwState.StartingTime.QuadPart;
137  Elapsed.QuadPart /= (HwState.TicksPerSecond.QuadPart / prescaler);
138  return Elapsed.QuadPart;
139 }
140 
141 uint32_t XcpHw_GetTimerCounter(void) {
142  uint64_t Now = XcpHw_GetElapsedTime(XCP_HW_TIMER_PRESCALER);
143 
144 #if XCP_DAQ_TIMESTAMP_SIZE == XCP_DAQ_TIMESTAMP_SIZE_1
145  return (uint32_t)Now & TIMER_MASK_1;
146 #elif XCP_DAQ_TIMESTAMP_SIZE == XCP_DAQ_TIMESTAMP_SIZE_2
147  return (uint32_t)Now & TIMER_MASK_2;
148 #elif XCP_DAQ_TIMESTAMP_SIZE == XCP_DAQ_TIMESTAMP_SIZE_4
149  return (uint32_t)Now & TIMER_MASK_4;
150 #else
151 #error Timestamp-size not supported.
152 #endif // XCP_DAQ_TIMESTAMP_SIZE
153 }
154 
155 uint32_t XcpHw_GetTimerCounterMS(void) {
156  return (uint32_t)((XcpHw_GetElapsedTime(TIMER_PS_1MS)) & TIMER_MASK_4);
157 }
158 
159 static void XcpHw_InitLocks(void) {
160  uint8_t idx = UINT8(0);
161 
162  for (idx = UINT8(0); idx < XCP_HW_LOCK_COUNT; ++idx) {
163  InitializeCriticalSection(&XcpHw_Locks[idx]);
164  }
165 }
166 
167 static void XcpHw_DeinitLocks(void) {
168  uint8_t idx = UINT8(0);
169 
170  for (idx = UINT8(0); idx < XCP_HW_LOCK_COUNT; ++idx) {
171  DeleteCriticalSection(&XcpHw_Locks[idx]);
172  }
173 }
174 
175 void XcpHw_AcquireLock(uint8_t lockIdx) {
176  if (lockIdx >= XCP_HW_LOCK_COUNT) {
177  return;
178  }
179  EnterCriticalSection(&XcpHw_Locks[lockIdx]);
180 }
181 
182 void XcpHw_ReleaseLock(uint8_t lockIdx) {
183  if (lockIdx >= XCP_HW_LOCK_COUNT) {
184  return;
185  }
186  LeaveCriticalSection(&XcpHw_Locks[lockIdx]);
187 }
188 
189 void XcpHw_ErrorMsg(char *const fun, int errorCode) {
190  char buffer[1024];
191 
192  FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
193  NULL, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
194  buffer, 1024, NULL);
195  fprintf(stderr, "[%s] failed with: [%d] %s", fun, errorCode, buffer);
196 }
197 
198 void XcpHw_TransmitDtos(void) {
199  uint16_t len;
200  uint8_t *dataOut = Xcp_GetDtoOutPtr();
201  while (!XcpDaq_QueueEmpty()) {
202  XcpDaq_QueueDequeue(&len, dataOut);
203  Xcp_SetDtoOutLen(len);
204  Xcp_SendDto();
205  }
206 }
207 
208 /*
209  *
210  * Sleep for `usec` microseconds.
211  *
212  */
213 void XcpHw_Sleep(uint64_t usec) {
214  HANDLE timer;
215  LARGE_INTEGER ft;
216 
217  ZeroMemory(&ft, sizeof(LARGE_INTEGER));
218  ft.QuadPart = -(10 * (int64_t)usec);
219  timer = CreateWaitableTimer(NULL, TRUE, NULL);
220  SetWaitableTimer(timer, &ft, 0, NULL, NULL, 0);
221  WaitForSingleObject(timer, INFINITE);
222  CloseHandle(timer);
223 }