]> rtime.felk.cvut.cz Git - socketcan-simulink.git/blob - blocks/tlc_c/sfunction_cansetup.tlc
Document myself as author of SocketCAN port of the original RPP library.
[socketcan-simulink.git] / blocks / tlc_c / sfunction_cansetup.tlc
1 %% Copyright (C) 2014 Czech Technical University in Prague
2 %%
3 %% Authors:
4 %%     Michal Horn  <hornmich@fel.cvut.cz>
5 %%     Michal Sojka <sojkam1@fel.cvut.cz>
6 %%     Pavel Pisa <pisa@cmp.felk.cvut.cz> - author of SocketCAN port
7 %%
8 %% Redistribution and use in source and binary forms, with or without
9 %% modification, are permitted provided that the following conditions are
10 %% met:
11 %%
12 %% 1. Redistributions of source code must retain the above copyright
13 %%    notice, this list of conditions and the following disclaimer.
14 %%
15 %% 2. Redistributions in binary form must reproduce the above copyright
16 %%    notice, this list of conditions and the following disclaimer in the
17 %%    documentation and/or other materials provided with the
18 %%    distribution.
19 %%
20 %% 3. Neither the name of the copyright holder nor the names of its
21 %%    contributors may be used to endorse or promote products derived
22 %%    from this software without specific prior written permission.
23 %%
24 %% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 %% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 %% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 %% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 %% HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 %% SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 %% LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 %% DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 %% THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 %% (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 %% OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 %%
36 %% File : sfunction_cansetup.tlc
37 %% Abstract:
38 %%     TLC file for configuring the CAN modules on the TI TMS570LS3137 MCU
39 %%
40 %% References:
41 %%     BlockTypeSetup() : refs/rtw_tlc.pdf p. 277
42 %%     Outputs()        : refs/rtw_tlc.pdf p. 281
43
44
45 %implements sfunction_cansetup "C"
46
47 %include "common.tlc"
48 %include "rpp_can_common.tlc"
49
50 %% Function: BlockTypeSetup ====================================================
51 %function BlockTypeSetup(block, system) void
52
53     %% Ensure required header files are included
54     %<RppCommonBlockTypeSetup(block, system)>
55         %% %<LibAddToCommonIncludes("<sys/ti_drv_dmm.h>")>
56
57         %assign ::rpp_can_config_present = 1
58
59         %<RppCANCommonBlockTypeSetup()>
60 %endfunction
61
62 %function BlockInstanceSetup(block, system) void
63     %if EXISTS("rpp_canc_in_model") == 0
64         %assign ::rpp_canc_in_model = 1
65     %else
66         %<LibBlockReportError(block, "Only one CAN Setup block is allowed in the model.")>
67     %endif
68 %endfunction
69
70
71 %% Function: Start =============================================================
72 %function Start(block, system) Output
73  %openfile buffer
74
75         enum ert_can_msg_types {
76                 ERT_CAN_STANDARD,
77                 ERT_CAN_EXTENDED,
78                 ERT_CAN_MIXED,
79         };
80
81         struct ert_can_channel_config {
82                 unsigned int baudrate;
83                 const char *net_dev_name;
84         };
85
86         struct ert_can_tx_config {
87                 int channel;
88                 int id_type;
89                 canid_t id;
90                 int msg_obj;
91         };
92
93         struct ert_can_rx_config {
94                 int channel;
95                 int id_type;
96                 canid_t id;
97                 canid_t mask;
98                 int msg_obj;
99         };
100
101         struct ert_can_config {
102                 int num_tx_obj;
103                 int num_rx_obj;
104                 struct ert_can_tx_config *tx_config;
105                 struct ert_can_rx_config *rx_config;
106                 struct ert_can_channel_config *channel_config;
107                 const char **channel_ifname;
108         };
109
110         #define CAN_TX_COUNT %<Rpp.Can.Tx.NumBlocks>
111         #define CAN_RX_COUNT %<Rpp.Can.Rx.NumBlocks>
112
113         struct ert_can_channel_config can_channel_config[3] = {
114                 {
115                         .baudrate = %<LibBlockParameterValue(baudrate_can1, 0)>
116                 },
117                 {
118                         .baudrate = %<LibBlockParameterValue(baudrate_can2, 0)>
119                 },
120                 {
121                         .baudrate = %<LibBlockParameterValue(baudrate_can3, 0)>
122                 }
123         };
124
125         struct ert_can_tx_config tx_config[CAN_TX_COUNT] = {
126           %foreach id = Rpp.Can.Tx.NumBlocks
127                 %with Rpp.Can.Tx.Block[id]
128                 // %<Name>
129                 {
130                   %if %<Type> == 1
131                         .id_type = ERT_CAN_STANDARD,
132                   %elseif %<Type> == 2
133                         .id_type = ERT_CAN_EXTENDED,
134                   %else
135                         .id_type = ERT_CAN_MIXED,
136                   %endif
137                   .id = %<Id>,
138                   .channel = %<Controller>,
139                   .msg_obj = %<MsgObj>,
140                 },
141                 %endwith
142           %endforeach
143         };
144
145         struct ert_can_rx_config rx_config[CAN_RX_COUNT] = {
146           %foreach id = Rpp.Can.Rx.NumBlocks
147                 %with Rpp.Can.Rx.Block[id]
148                 // %<Name>
149                 {
150                   %if %<Type>==1
151                         .id_type = ERT_CAN_STANDARD,
152                   %elseif %<Type>==2
153                         .id_type = ERT_CAN_EXTENDED,
154                   %else
155                         .id_type = ERT_CAN_MIXED,
156                   %endif
157                   .id = %<Id>,
158                   .mask = %<SPRINTF("%#x", Mask)>,
159                   .channel = %<Controller>,
160                   .msg_obj = %<MsgObj>,
161                 },
162                 %endwith
163           %endforeach
164         };
165
166         const char *ert_can_channel_ifname[] = {
167                 "can0", /*FIXME - for now skip this */
168                 "can0",
169                 "can1",
170                 "can2",
171                 "can3"
172         };
173
174         const struct ert_can_config can_config = {
175                 .num_tx_obj = CAN_TX_COUNT,
176                 .num_rx_obj = CAN_RX_COUNT,
177                 .tx_config = tx_config,
178                 .rx_config = rx_config,
179                 .channel_config = can_channel_config,
180                 .channel_ifname = ert_can_channel_ifname
181         };
182
183         int can_tx_handles[CAN_TX_COUNT];
184
185         int can_rx_handles[CAN_RX_COUNT];
186
187         %closefile buffer
188         %<LibSetSourceFileSection(LibGetModelDotCFile(), "Declarations", buffer)>
189         {
190                 int idx;
191
192                 for (idx = 0; idx < CAN_TX_COUNT; idx++) {
193                         struct ert_can_tx_config *cfg = &can_config.tx_config[idx];
194                         const char *ifname = can_config.channel_ifname[cfg->channel];
195                         int fd;
196                         struct sockaddr_can addr;
197                         struct ifreq ifr;
198
199                         fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
200                         if (fd == -1) {
201                                 printf("CAN socket create error.\n");
202                                 exit(1);
203                         }
204                         if(fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
205                                 printf("CAN socket set O_NONBLOCK error.\n");
206                                 exit(1);
207                         }
208                         memset(&addr, 0, sizeof(addr));
209                         addr.can_family = AF_CAN;
210                         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
211                         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
212                                 printf("CAN socket ioctl SIOCGIFINDEX error.\n");
213                                 exit(1);
214                         }
215                         addr.can_ifindex = ifr.ifr_ifindex;
216
217                         /* disable default receive filter on this RAW socket */
218                         setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
219
220                         if (bind(fd, (struct sockaddr *)(void*)&addr, sizeof(addr)) < 0) {
221                                 printf("CAN socket bind error.\n");
222                                 exit(1);
223                         }
224                         printf("rx opening %s\n", ifname);
225                         can_tx_handles[idx] = fd;
226                 }
227
228                 for (idx = 0; idx < CAN_RX_COUNT; idx++) {
229                         struct ert_can_rx_config *cfg = &can_config.rx_config[idx];
230                         const char *ifname = can_config.channel_ifname[cfg->channel];
231                         int fd;
232                         struct sockaddr_can addr;
233                         struct ifreq ifr;
234                         struct can_filter sc_filter;
235
236                         fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
237                         if (fd == -1) {
238                                 printf("CAN socket create error.\n");
239                                 exit(1);
240                         }
241                         if(fcntl(fd, F_SETFL, O_NONBLOCK) < 0) {
242                                 printf("CAN socket set O_NONBLOCK error.\n");
243                                 exit(1);
244                         }
245                         memset(&addr, 0, sizeof(addr));
246                         addr.can_family = AF_CAN;
247                         strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
248                         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
249                                 printf("CAN socket ioctl SIOCGIFINDEX error.\n");
250                                 exit(1);
251                         }
252                         addr.can_ifindex = ifr.ifr_ifindex;
253
254                         /* disable default receive filter on this RAW socket */
255                         setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
256
257                         if (bind(fd, (struct sockaddr *)(void*)&addr, sizeof(addr)) < 0) {
258                                 printf("CAN socket bind error.\n");
259                                 exit(1);
260                         }
261
262                         memset(&sc_filter, 0, sizeof(sc_filter));
263                         sc_filter.can_id = cfg->id;
264                         sc_filter.can_mask = CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG;
265                         if (cfg->id_type == ERT_CAN_EXTENDED)
266                                 sc_filter.can_id |= CAN_EFF_FLAG;
267                         else if(cfg->id_type == ERT_CAN_MIXED)
268                                 sc_filter.can_mask &= ~CAN_EFF_FLAG;
269
270                         if (setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &sc_filter, sizeof(sc_filter)) < 0) {
271                                 printf("CAN socket setsockopt CAN_RAW_FILTER error.\n");
272                                 exit(1);
273                         }
274
275                         printf("tx opening %s\n", ifname);
276                         can_rx_handles[idx] = fd;
277                 }
278         }
279         %%else {
280         %%      printf("CAN communication initialized.\n");
281         %%}
282  %endfunction
283
284 %% [EOF]