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