Open FFBoard
Open source force feedback firmware
Loading...
Searching...
No Matches
CANPort2B.cpp
Go to the documentation of this file.
1/*
2 * CANPort2B.cpp
3 *
4 * Created on: 21.09.2023
5 * Author: Yannick
6 */
7
8#include "CANPort2B.h"
9#if defined(CANTYPE_2B)
11 .name = "Can port",
12 .id = CLSID_CANPORT,
13 .visibility = ClassVisibility::visible};
14
15//CANPort::CANPort(const CANPortHardwareConfig<uint32_t>& presets,uint8_t instance) : presets(presets),CommandHandler("can", CLSID_CANPORT, instance){
16//
17//}
18
20 //HAL_CAN_Start(this->hcan);
22#ifdef CAN_COMMANDS_DISABLED_IF_NOT_USED
23 this->setCommandsEnabled(false);
24#endif
26}
27//CANPort_2B::CANPort(CAN_HandleTypeDef &hcan,const OutputPin* silentPin) : CommandHandler("can", CLSID_CANPORT, 0), hcan(&hcan), silentPin(silentPin) {
28// //HAL_CAN_Start(this->hcan);
29// restoreFlash();
30// registerCommands();
31//}
32
35 registerCommand("speed", CanPort_commands::speed, "CAN speed preset (! for list)", CMDFLAG_GET|CMDFLAG_SET|CMDFLAG_INFOSTRING);
36 registerCommand("send", CanPort_commands::send, "Send CAN frame. Adr&Value required", CMDFLAG_SETADR);
37 registerCommand("len", CanPort_commands::len, "Set length of next frames", CMDFLAG_SET|CMDFLAG_GET);
38}
39
41 if(this->getCommandHandlerInfo()->instance != 0){
42 return; // Only first instance can save
43 }
44 uint16_t data = (this->speedPreset & 0b111); // set the baudrate in 0..2 bit
45 Flash_Write(ADR_CANCONF1, data);
46}
47
49 if(this->getCommandHandlerInfo()->instance != 0){
50 return; // Only first instance can save
51 }
52 uint16_t data;
53 if(Flash_Read(ADR_CANCONF1, &data)){
54 setSpeedPreset(data & 0b111);
55 }
56}
57
58
60 // removes all filters
61 for (uint8_t i = 0; i < canFilters.size(); i++){
62 canFilters[i].FilterActivation = false;
63 HAL_CAN_ConfigFilter(this->hcan, &canFilters[i]);
64 }
65 canFilters.clear();
66 HAL_CAN_Stop(this->hcan);
67 if(silentPin){
68 silentPin->set(); // set pin high to disable
69 }
70}
71
76//void CANPort_2B::takePort(){
77// if(portUsers++ == 0){
78// start();
79// }
80//}
81
86//void CANPort_2B::freePort(){
87// if(portUsers>0){
88// portUsers--;
89// }
90//
91// if(portUsers == 0){
92// stop();
93// }
94//}
95
100 setSilentMode(false);
101 active = true;
102#ifdef CAN_COMMANDS_DISABLED_IF_NOT_USED
103 this->setCommandsEnabled(true);
104#endif
105 //CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO0_OVERRUN
106 HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING | CAN_IT_RX_FIFO0_FULL | CAN_IT_RX_FIFO0_OVERRUN | CAN_IT_RX_FIFO1_FULL | CAN_IT_RX_FIFO1_OVERRUN | CAN_IT_ERROR | CAN_IT_BUSOFF | CAN_IT_TX_MAILBOX_EMPTY);
107 setSpeedPreset(this->speedPreset); // Set preset again for a safe state
108 return HAL_CAN_Start(this->hcan) == HAL_OK;
109}
110
115 setSilentMode(true);
116 active = false;
117#ifdef CAN_COMMANDS_DISABLED_IF_NOT_USED
118 this->setCommandsEnabled(false);
119#endif
120 return HAL_CAN_Stop(this->hcan) == HAL_OK;
121}
122
123
126}
127
129 return (speedPreset);
130}
131
132
136void CANPort_2B::setSpeedPreset(uint8_t preset){
137 if(preset > 5)
138 return;
139 speedPreset = preset;
140
141 configSem.Take();
142 HAL_CAN_Stop(this->hcan);
143 HAL_CAN_AbortTxRequest(hcan, txMailboxes);
144 this->hcan->Instance->BTR = presets.getPreset(preset).init;
145 HAL_CAN_ResetError(hcan);
146
147 HAL_CAN_Start(this->hcan);
148 configSem.Give();
149}
150
156 uint8_t preset = speedToPreset(speed);
157 setSpeedPreset(preset);
158}
159
160
161
166 this->silent = silent;
167 if(silentPin){
168 silentPin->write(silent);
169 }
170}
171
177 return this->sendMessage(&msg.header,msg.data,nullptr);
178}
179
181 HAL_CAN_AbortTxRequest(hcan, txMailboxes);
182}
183
187bool CANPort_2B::sendMessage(CAN_msg_header_tx *pHeader, uint8_t aData[],uint32_t *pTxMailbox){
188
189 header.DLC = pHeader->length;
190 header.IDE = pHeader->extId ? CAN_ID_EXT : CAN_ID_STD;
191 header.RTR = pHeader->rtr ? CAN_RTR_REMOTE : CAN_RTR_DATA;
192 header.StdId = pHeader->extId ? 0 : pHeader->id;
193 header.ExtId = pHeader->extId ? pHeader->id : 0;
194
195 if(this->silent)
196 setSilentMode(false);
197 uint32_t mailbox;
198 if(pTxMailbox == nullptr){
199 pTxMailbox = &mailbox;
200 }
201
202 if(!HAL_CAN_GetTxMailboxesFreeLevel(hcan) && HAL_GetTick() - lastSentTime > sendTimeout){
203 // Mailbox full and nothing has been sent successfully for some time. Abort previous requests if timeout reached
204 HAL_CAN_AbortTxRequest(hcan, txMailboxes);
205 }
206//
207 if(!HAL_CAN_GetTxMailboxesFreeLevel(hcan)){ // Only wait if no mailbox is free
208 isWaitingFlag = true;
210 isWaitingFlag = false;
211 return false;
212 }
213
214 }
215
216 //this->isTakenFlag = true;
217 if (HAL_CAN_AddTxMessage(this->hcan, &header, aData, pTxMailbox) != HAL_OK)
218 {
219 /* Transmission request Error */
220 if(isWaitingFlag)
222 return false;
223 }
224 txMailboxes |= *pTxMailbox;
225// if(HAL_CAN_GetTxMailboxesFreeLevel(hcan)) // Give back semaphore immediately if mailboxes are still free
226// giveSemaphore();
227 return true;
228}
229
230void CANPort_2B::canTxCpltCallback(CANPort *port,uint32_t mailbox){
231 if(port == this){
232 lastSentTime = HAL_GetTick();
233 txMailboxes &= ~mailbox;
234 if(isWaitingFlag)
236 }
237}
238
239void CANPort_2B::canTxAbortCallback(CANPort *port,uint32_t mailbox){
240 if(port == this){
241 txMailboxes &= ~mailbox;
242 if(isWaitingFlag)
244 }
245}
246
247void CANPort_2B::canErrorCallback(CANPort *port, uint32_t code){
248 if(
249 port == this &&
250 code & (HAL_CAN_ERROR_TX_ALST0 | HAL_CAN_ERROR_TX_ALST1 | HAL_CAN_ERROR_TX_ALST2 | HAL_CAN_ERROR_TX_TERR0 | HAL_CAN_ERROR_TX_TERR1 | HAL_CAN_ERROR_TX_TERR2)
251 ){
253 }
254}
255
256
263
264 CAN_FilterTypeDef sFilterConfig;
265 sFilterConfig.FilterActivation = filter.active;
266 sFilterConfig.FilterBank = 0; // Init new
267 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
268 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
269 sFilterConfig.FilterFIFOAssignment = filter.buffer == 0 ? CAN_RX_FIFO0 : CAN_RX_FIFO1;
270
271
272 if (!filter.extid) {
273 // Standard 11-bit ID -> bits 31:21
274 sFilterConfig.FilterIdHigh = (filter.filter_id << 5) & 0xFFFF;
275 sFilterConfig.FilterIdLow = 0;
276 sFilterConfig.FilterMaskIdHigh = (filter.filter_mask << 5) & 0xFFFF;
277 sFilterConfig.FilterMaskIdLow = 0;
278 } else {
279 // Extended 29-bit ID -> bits 31:3
280 sFilterConfig.FilterIdHigh = (filter.filter_id >> 13) & 0xFFFF;
281 sFilterConfig.FilterIdLow = (filter.filter_id << 3) & 0xFFF8;
282 sFilterConfig.FilterMaskIdHigh = (filter.filter_mask >> 13) & 0xFFFF;
283 sFilterConfig.FilterMaskIdLow = (filter.filter_mask << 3) & 0xFFF8;
284
285 sFilterConfig.FilterIdLow |= 0x04; // IDE = 1
286 sFilterConfig.FilterMaskIdLow |= 0x04; // force IDE bit to match
287 }
288
289
290 configSem.Take();
291 int32_t lowestId = 0;// sFilterConfig.FilterFIFOAssignment == CAN_RX_FIFO0 ? 0 : slaveFilterStart;
292 int32_t highestId = slaveFilterStart;// sFilterConfig.FilterFIFOAssignment == CAN_RX_FIFO0 ? slaveFilterStart : 29;
293 int32_t foundId = -1;
294
295 for(uint8_t id = lowestId; id < highestId ; id++ ){
296 bool foundExisting = false;
297 for(CAN_FilterTypeDef filter : canFilters){
298 if(id == filter.FilterBank
299// && filter.FilterIdHigh == sFilterConfig.FilterIdHigh && filter.FilterIdLow == sFilterConfig.FilterIdLow &&filter.FilterFIFOAssignment == sFilterConfig.FilterFIFOAssignment &&
300// && filter.FilterMaskIdHigh == sFilterConfig.FilterMaskIdHigh && filter.FilterMaskIdLow == sFilterConfig.FilterMaskIdLow
301// && filter.FilterMode == sFilterConfig.FilterMode && filter.FilterScale == sFilterConfig.FilterScale
302 )
303 {
304 foundExisting = true;
305 break;
306 }
307 }
308 foundId = id;
309 if(!foundExisting){
310 break;
311 }
312
313 }
314 if(foundId < highestId){
315 if(sFilterConfig.FilterBank == 0)
316 sFilterConfig.FilterBank = foundId;
317 if (HAL_CAN_ConfigFilter(this->hcan, &sFilterConfig) == HAL_OK){
318 canFilters.push_back(sFilterConfig);
319 }
320 }
321 configSem.Give();
322 return foundId;
323}
324
329void CANPort_2B::removeCanFilter(uint8_t filterId){
330 configSem.Take();
331 for (uint8_t i = 0; i < canFilters.size(); i++){
332 if(canFilters[i].FilterBank == filterId){
333 canFilters[i].FilterActivation = false;
334 HAL_CAN_ConfigFilter(this->hcan, &canFilters[i]);
335 canFilters.erase(canFilters.begin()+i);
336 break;
337 }
338 }
339 configSem.Give();
340}
341
342
343CommandStatus CANPort_2B::command(const ParsedCommand& cmd,std::vector<CommandReply>& replies){
344
345 switch(static_cast<CanPort_commands>(cmd.cmdId)){
346
348 if(cmd.type == CMDtype::get){
349 replies.emplace_back(this->speedPreset);
350 }else if(cmd.type == CMDtype::set){
351 setSpeedPreset(cmd.val);
352 }else if(cmd.type == CMDtype::info){
353 for(uint8_t i = 0; i<presets.presets.size();i++){
354 replies.emplace_back(std::string(presets.presets[i].name) + ":" + std::to_string(i));
355 }
356 }
357 break;
358
360 {
361 if(cmd.type == CMDtype::setat){
362 if(!active){
363 start(); // If port is not used activate port at first use
364 }
365 CAN_tx_msg msg;
366 memcpy(msg.data,&cmd.val,8);
367 msg.header.id = cmd.adr;
368 msg.header.length = nextLen;
369 sendMessage(msg);
370 }else{
372 }
373 break;
374 }
376 handleGetSet(cmd, replies, nextLen);
377 nextLen = std::min<uint32_t>(nextLen,8);
378 break;
379 default:
381 }
382 return CommandStatus::OK;
383}
384#endif
CommandStatus
CAN_TxHeaderTypeDef header
Definition CANPort2B.h:71
void registerCommands()
Definition CANPort2B.cpp:33
static const uint32_t sendTimeout
Definition CANPort2B.h:69
virtual ~CANPort_2B()
Definition CANPort2B.cpp:59
bool sendMessage(CAN_tx_msg &msg)
bool stop()
bool start()
Definition CANPort2B.cpp:99
uint32_t txMailboxes
Definition CANPort2B.h:60
void canErrorCallback(CANPort *port, uint32_t code) override
bool active
Definition CANPort2B.h:65
const OutputPin * silentPin
Definition CANPort2B.h:63
static const uint8_t slaveFilterStart
Definition CANPort2B.h:39
CAN_HandleTypeDef * hcan
Definition CANPort2B.h:58
void saveFlash()
Definition CANPort2B.cpp:40
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
void restoreFlash()
Definition CANPort2B.cpp:48
void setSpeedPreset(uint8_t preset)
uint8_t nextLen
Definition CANPort2B.h:72
std::vector< CAN_FilterTypeDef > canFilters
Definition CANPort2B.h:59
int32_t addCanFilter(CAN_filter filter)
void canTxAbortCallback(CANPort *port, uint32_t mailbox) override
void setSilentMode(bool silent)
uint8_t speedPreset
Definition CANPort2B.h:57
static ClassIdentifier info
Definition CANPort2B.h:10
uint32_t lastSentTime
Definition CANPort2B.h:67
uint32_t getSpeed()
void setSpeed(uint32_t speed)
uint8_t getSpeedPreset()
bool silent
Definition CANPort2B.h:64
void canTxCpltCallback(CANPort *port, uint32_t mailbox) override
CANPort_2B(CAN_HandleTypeDef &hcan, const CANPortHardwareConfig &presets, const OutputPin *silentPin=nullptr, uint8_t instance=0)
Definition CANPort2B.cpp:19
void removeCanFilter(uint8_t filterId)
void abortTxRequests()
virtual void giveSemaphore()
Definition CAN.h:177
virtual uint8_t speedToPreset(uint32_t speed)
Gets preset index for a speed.
Definition CAN.h:201
cpp_freertos::BinarySemaphore configSem
Definition CAN.h:206
virtual bool takeSemaphore(uint32_t delay=portMAX_DELAY)
Definition CAN.h:187
const CANPortHardwareConfig & presets
CAN port presets for different speeds. Hardware dependent.
Definition CAN.h:207
CANPort(const CANPortHardwareConfig &presets, uint8_t instance=0)
Definition CAN.cpp:16
bool isWaitingFlag
Definition CAN.h:208
virtual uint32_t presetToSpeed(uint8_t preset)
Gets speed for a preset index.
Definition CAN.h:202
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
virtual void setCommandsEnabled(bool enable)
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
virtual CmdHandlerInfo * getCommandHandlerInfo()
CommandHandler(const char *clsname, uint16_t clsid, uint8_t instance=0)
static struct @024127060247016123033304002117326322243354210111 data
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
static void * memcpy(void *dst, const void *src, size_t n)
Definition ringbuffer.c:8
bool extid
Definition CAN.h:114
bool active
Definition CAN.h:113
uint32_t buffer
Definition CAN.h:112
uint32_t filter_mask
Definition CAN.h:111
uint32_t filter_id
Definition CAN.h:110
uint32_t id
Definition CAN.h:62
uint32_t length
Definition CAN.h:63
CAN_msg_header_tx header
Definition CAN.h:94
uint8_t data[CAN_MSGBUFSIZE]
Definition CAN.h:92