Apollo 10.0
自动驾驶开放平台
hermes_can_client.cc
浏览该文件的文档.
1/******************************************************************************
2 * Copyright 2017 The Apollo Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *****************************************************************************/
16
18
19#include <cstdio>
20#include <cstring>
21#include <iostream>
22#include <vector>
23
24namespace apollo {
25namespace drivers {
26namespace canbus {
27namespace can {
28
30
32 if (dev_handler_) {
33 Stop();
34 }
35}
36
38 if (!parameter.has_channel_id()) {
39 AERROR << "Init CAN failed: parameter does not have channel id. The "
40 "parameter is "
41 << parameter.DebugString();
42 return false;
43 }
44 port_ = parameter.channel_id();
45 auto num_ports = parameter.num_ports();
46 if (port_ > static_cast<int32_t>(num_ports) || port_ < 0) {
47 AERROR << "Can port number [" << port_ << "] is out of bound [0,"
48 << num_ports << ")";
49 return false;
50 }
51
52 return true;
53}
54
56 if (is_init_) {
57 return ErrorCode::OK;
58 }
59
60 // open device
61 int32_t ret = bcan_open(port_, 0,
62 5, // 5ms for rx timeout
63 5, // 5ms for tx timeout
64 &dev_handler_);
65
66 if (ret != ErrorCode::OK) {
67 AERROR << "Open device error code: " << ret << ", channel id: " << port_;
68 return ErrorCode::CAN_CLIENT_ERROR_BASE;
69 }
70 AINFO << "Open device success, channel id: " << port_;
71
72 // 1. set baudrate to 500k
73 ret = bcan_set_baudrate(dev_handler_, BCAN_BAUDRATE_500K);
74 if (ret != ErrorCode::OK) {
75 AERROR << "Set baudrate error Code: " << ret;
76 return ErrorCode::CAN_CLIENT_ERROR_BASE;
77 }
78
79 // 2. start receive
80 ret = bcan_start(dev_handler_);
81 if (ret != ErrorCode::OK) {
82 AERROR << "Start hermes can card failed: " << ret;
83 return ErrorCode::CAN_CLIENT_ERROR_BASE;
84 }
85
86 is_init_ = true;
87 return ErrorCode::OK;
88}
89
91 if (is_init_) {
92 is_init_ = false;
93 int32_t ret = bcan_close(dev_handler_);
94 if (ret != ErrorCode::OK) {
95 AERROR << "close error code: " << ret;
96 }
97 }
98}
99
100// Synchronous transmission of CAN messages
102 const std::vector<CanFrame> &frames, int32_t *const frame_num) {
103 /*
104 typedef struct bcan_msg {
105 uint32_t bcan_msg_id; // source CAN node id
106 uint8_t bcan_msg_datalen; // message data length
107 uint8_t bcan_msg_rsv[3]; // reserved
108 uint8_t bcan_msg_data[8]; // message data
109 uint64_t bcan_msg_timestamp; // TBD
110 } bcan_msg_t;
111 */
112 CHECK_NOTNULL(frame_num);
113 CHECK_EQ(frames.size(), static_cast<size_t>(*frame_num));
114
115 if (!is_init_) {
116 AERROR << "Hermes can client is not init! Please init first!";
117 return ErrorCode::CAN_CLIENT_ERROR_SEND_FAILED;
118 }
119 // if (*frame_num > MAX_CAN_SEND_FRAME_LEN || *frame_num < 0) {
120 // AERROR << "send can frame num not in range[0, "
121 // << MAX_CAN_SEND_FRAME_LEN << "], frame_num:" << *frame_num;
122 // return ErrorCode::CAN_CLIENT_ERROR_FRAME_NUM;
123 // }
124 for (int i = 0; i < *frame_num; ++i) {
125 _send_frames[i].bcan_msg_id = frames[i].id;
126 _send_frames[i].bcan_msg_datalen = frames[i].len;
127 memcpy(_send_frames[i].bcan_msg_data, frames[i].data, frames[i].len);
128 }
129
130 // Synchronous transmission of CAN messages
131 int32_t send_num = *frame_num;
132 int32_t ret = bcan_send(dev_handler_, _send_frames, send_num);
133 if (ret < 0) {
134 int ret_send_error = bcan_get_status(dev_handler_);
135 AERROR << "send message failed, error code: " << ret
136 << ", send error: " << ret_send_error;
137 return ErrorCode::CAN_CLIENT_ERROR_SEND_FAILED;
138 }
139 *frame_num = ret;
140 return ErrorCode::OK;
141}
142
143// buf size must be 8 bytes, every time, we receive only one frame
144const int RX_TIMEOUT = -7;
145
147 std::vector<CanFrame> *const frames, int32_t *const frame_num) {
148 if (!is_init_) {
149 AERROR << "Hermes can client is not init! Please init first!";
150 return ErrorCode::CAN_CLIENT_ERROR_RECV_FAILED;
151 }
152 if (*frame_num > MAX_CAN_RECV_FRAME_LEN || *frame_num < 0) {
153 AERROR << "recv can frame num not in range[0, " << MAX_CAN_RECV_FRAME_LEN
154 << "], frame_num:" << *frame_num;
155 return ErrorCode::CAN_CLIENT_ERROR_FRAME_NUM;
156 }
157
158 int32_t ret = bcan_recv(dev_handler_, _recv_frames, *frame_num);
159 // don't log timeout
160 if (ret == RX_TIMEOUT) {
161 *frame_num = 0;
162 return ErrorCode::OK;
163 }
164 if (ret < 0) {
165 int ret_rece_error = bcan_get_status(dev_handler_);
166 AERROR << "receive message failed, error code:" << ret
167 << "receive error:" << ret_rece_error;
168 return ErrorCode::CAN_CLIENT_ERROR_RECV_FAILED;
169 }
170 *frame_num = ret;
171
172 // is ret num is equal *frame_num?
173 for (int i = 0; i < *frame_num; ++i) {
174 CanFrame cf;
175 cf.id = _recv_frames[i].bcan_msg_id;
176 cf.len = _recv_frames[i].bcan_msg_datalen;
177 cf.timestamp.tv_sec = _recv_frames[i].bcan_msg_timestamp.tv_sec;
178 cf.timestamp.tv_usec = _recv_frames[i].bcan_msg_timestamp.tv_usec;
179 memcpy(cf.data, _recv_frames[i].bcan_msg_data, cf.len);
180 frames->push_back(cf);
181 }
182
183 return ErrorCode::OK;
184}
185
186std::string HermesCanClient::GetErrorString(int32_t ntstatus) { return ""; }
187
188void HermesCanClient::SetInited(bool init) { is_init_ = init; }
189
190} // namespace can
191} // namespace canbus
192} // namespace drivers
193} // namespace apollo
194
195/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
int bcan_recv(bcan_hdl_t hdl, bcan_msg_t *buf, uint32_t num_msg)
int bcan_set_baudrate(bcan_hdl_t hdl, uint32_t rate)
@ BCAN_BAUDRATE_500K
Definition bcan.h:52
int bcan_get_status(bcan_hdl_t hdl)
int bcan_open(uint32_t dev_index, uint32_t flags, uint64_t tx_to, uint64_t rx_to, bcan_hdl_t *hdl)
int bcan_start(bcan_hdl_t hdl)
int bcan_close(bcan_hdl_t hdl)
int bcan_send(bcan_hdl_t hdl, bcan_msg_t *buf, uint32_t num_msg)
virtual ~HermesCanClient()
Initialize the BCAN client by specified CAN card parameters.
bool Init(const CANCardParameter &parameter) override
Start the ESD CAN client.
virtual std::string GetErrorString(const int32_t status)
Get the error string.
virtual apollo::common::ErrorCode Receive(std::vector< CanFrame > *const frames, int32_t *const frame_num)
Receive messages
void SetInited(bool init)
Set inited status.
virtual void Stop()
Stop the ESD CAN client.
apollo::common::ErrorCode Start() override
Start the ESD CAN client.
virtual apollo::common::ErrorCode Send(const std::vector< CanFrame > &frames, int32_t *const frame_num)
Send messages
#define AERROR
Definition log.h:44
#define AINFO
Definition log.h:42
const int32_t MAX_CAN_RECV_FRAME_LEN
class register implement
Definition arena_queue.h:37
The class which defines the information to send and receive.
Definition can_client.h:48
uint8_t len
Message length
Definition can_client.h:52
struct timeval timestamp
Time stamp
Definition can_client.h:56
uint8_t data[8]
Message content
Definition can_client.h:54
unsigned int bcan_msg_id
Definition bcan_defs.h:29
struct timeval bcan_msg_timestamp
Definition bcan_defs.h:33
unsigned char bcan_msg_data[8]
Definition bcan_defs.h:32
unsigned char bcan_msg_datalen
Definition bcan_defs.h:30