Mercurial > nand-ecoscentric
comparison packages/devs/can/loop/current/tests/can_overrun2.c @ 2059:f929becf4af2
CAN driver, from Uwe Kindler
| author | gthomas |
|---|---|
| date | Thu, 25 Aug 2005 13:40:35 +0000 |
| parents | |
| children | 1ca46bebd705 |
comparison
equal
deleted
inserted
replaced
| 2058:8d6df59beb34 | 2059:f929becf4af2 |
|---|---|
| 1 //========================================================================== | |
| 2 // | |
| 3 // can_overrun2.c | |
| 4 // | |
| 5 // Test CAN device RX overrun events | |
| 6 // | |
| 7 //========================================================================== | |
| 8 //####ECOSGPLCOPYRIGHTBEGIN#### | |
| 9 // ------------------------------------------- | |
| 10 // This file is part of eCos, the Embedded Configurable Operating System. | |
| 11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. | |
| 12 // | |
| 13 // eCos is free software; you can redistribute it and/or modify it under | |
| 14 // the terms of the GNU General Public License as published by the Free | |
| 15 // Software Foundation; either version 2 or (at your option) any later version. | |
| 16 // | |
| 17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| 20 // for more details. | |
| 21 // | |
| 22 // You should have received a copy of the GNU General Public License along | |
| 23 // with eCos; if not, write to the Free Software Foundation, Inc., | |
| 24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
| 25 // | |
| 26 // As a special exception, if other files instantiate templates or use macros | |
| 27 // or inline functions from this file, or you compile this file and link it | |
| 28 // with other works to produce a work based on this file, this file does not | |
| 29 // by itself cause the resulting work to be covered by the GNU General Public | |
| 30 // License. However the source code for this file must still be made available | |
| 31 // in accordance with section (3) of the GNU General Public License. | |
| 32 // | |
| 33 // This exception does not invalidate any other reasons why a work based on | |
| 34 // this file might be covered by the GNU General Public License. | |
| 35 // | |
| 36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. | |
| 37 // at http://sources.redhat.com/ecos/ecos-license/ | |
| 38 // ------------------------------------------- | |
| 39 //####ECOSGPLCOPYRIGHTEND#### | |
| 40 //========================================================================== | |
| 41 //#####DESCRIPTIONBEGIN#### | |
| 42 // | |
| 43 // Author(s): Uwe Kindler | |
| 44 // Contributors: Uwe Kindler | |
| 45 // Date: 2005-08-07 | |
| 46 // Description: Simple read/write test of CAN driver | |
| 47 //####DESCRIPTIONEND#### | |
| 48 | |
| 49 | |
| 50 //=========================================================================== | |
| 51 // INCLUDES | |
| 52 //=========================================================================== | |
| 53 #include <pkgconf/system.h> | |
| 54 | |
| 55 #include <cyg/infra/testcase.h> // test macros | |
| 56 #include <cyg/infra/cyg_ass.h> // assertion macros | |
| 57 #include <cyg/infra/diag.h> | |
| 58 | |
| 59 // Package requirements | |
| 60 #if defined(CYGPKG_IO_CAN) && defined(CYGPKG_KERNEL) | |
| 61 | |
| 62 #include <pkgconf/kernel.h> | |
| 63 #include <cyg/io/io.h> | |
| 64 #include <cyg/io/canio.h> | |
| 65 | |
| 66 // Package option requirements | |
| 67 #if defined(CYGFUN_KERNEL_API_C) | |
| 68 | |
| 69 #include <cyg/hal/hal_arch.h> // CYGNUM_HAL_STACK_SIZE_TYPICAL | |
| 70 #include <cyg/kernel/kapi.h> | |
| 71 | |
| 72 | |
| 73 //=========================================================================== | |
| 74 // DATA TYPES | |
| 75 //=========================================================================== | |
| 76 typedef struct st_thread_data | |
| 77 { | |
| 78 cyg_thread obj; | |
| 79 long stack[CYGNUM_HAL_STACK_SIZE_TYPICAL]; | |
| 80 cyg_handle_t hdl; | |
| 81 } thread_data_t; | |
| 82 | |
| 83 | |
| 84 //=========================================================================== | |
| 85 // LOCAL DATA | |
| 86 //=========================================================================== | |
| 87 cyg_thread_entry_t can0_thread; | |
| 88 thread_data_t can0_thread_data; | |
| 89 | |
| 90 cyg_thread_entry_t can1_thread; | |
| 91 thread_data_t can1_thread_data; | |
| 92 | |
| 93 | |
| 94 //=========================================================================== | |
| 95 // LOCAL FUNCTIONS | |
| 96 //=========================================================================== | |
| 97 #include "can_test_aux.inl" // include CAN test auxiliary functions | |
| 98 | |
| 99 | |
| 100 //=========================================================================== | |
| 101 // WRITER THREAD | |
| 102 //=========================================================================== | |
| 103 void can0_thread(cyg_addrword_t data) | |
| 104 { | |
| 105 cyg_io_handle_t hCAN0; | |
| 106 cyg_uint8 i; | |
| 107 cyg_uint32 len; | |
| 108 cyg_uint32 rx_bufsize; | |
| 109 cyg_can_buf_info_t tx_buf_info; | |
| 110 cyg_can_event rx_event; | |
| 111 cyg_can_message tx_msg = | |
| 112 { | |
| 113 0x000, // CAN identifier | |
| 114 {0x00, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7}, // 8 data bytes | |
| 115 CYGNUM_CAN_ID_STD, // standard frame | |
| 116 CYGNUM_CAN_FRAME_DATA, // data frame | |
| 117 2, // data length code | |
| 118 }; | |
| 119 | |
| 120 if (ENOERR != cyg_io_lookup("/dev/can0", &hCAN0)) | |
| 121 { | |
| 122 CYG_TEST_FAIL_FINISH("Error opening /dev/can0"); | |
| 123 } | |
| 124 | |
| 125 len = sizeof(tx_buf_info); | |
| 126 if (ENOERR != cyg_io_get_config(hCAN0, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&tx_buf_info, &len)) | |
| 127 { | |
| 128 CYG_TEST_FAIL_FINISH("Error reading config of /dev/can0"); | |
| 129 } | |
| 130 | |
| 131 // | |
| 132 // Before we can write the CAN messages, we need to know the buffer size of the | |
| 133 // receiver. The receiver will tell us this buffer size with one single CAN | |
| 134 // message | |
| 135 // | |
| 136 len = sizeof(rx_event); | |
| 137 | |
| 138 if (ENOERR != cyg_io_read(hCAN0, &rx_event, &len)) | |
| 139 { | |
| 140 CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); | |
| 141 } | |
| 142 | |
| 143 // | |
| 144 // we expect a RX event here - we treat any other flag as an error | |
| 145 // | |
| 146 if (!(rx_event.flags & CYGNUM_CAN_EVENT_RX) || (rx_event.flags & !CYGNUM_CAN_EVENT_RX)) | |
| 147 { | |
| 148 CYG_TEST_FAIL_FINISH("Unexpected RX event for /dev/can0"); | |
| 149 } | |
| 150 | |
| 151 rx_bufsize = *((cyg_uint32 *)rx_event.msg.data); | |
| 152 | |
| 153 // | |
| 154 // now we send exactly one CAN message more than there is space in the receive buffer | |
| 155 // this should cause an RX ovverun in receive buffer | |
| 156 // | |
| 157 diag_printf("/dev/can0: Sending %d CAN messages\n", rx_bufsize); | |
| 158 for (i = 0; i <= rx_bufsize; ++i) | |
| 159 { | |
| 160 // | |
| 161 // we store the message number as CAN id and in first data byte so | |
| 162 // a receiver can check this later | |
| 163 // | |
| 164 tx_msg.id = 0x000 + i; | |
| 165 tx_msg.data[0] = i; | |
| 166 len = sizeof(tx_msg); | |
| 167 | |
| 168 if (ENOERR != cyg_io_write(hCAN0, &tx_msg, &len)) | |
| 169 { | |
| 170 CYG_TEST_FAIL_FINISH("Error writing to /dev/can0"); | |
| 171 } | |
| 172 else | |
| 173 { | |
| 174 print_can_msg(&tx_msg, ""); | |
| 175 } | |
| 176 } // for (i = 0; i <= rx_bufsize; ++i) | |
| 177 | |
| 178 cyg_thread_suspend(cyg_thread_self()); | |
| 179 } | |
| 180 | |
| 181 | |
| 182 //=========================================================================== | |
| 183 // READER THREAD | |
| 184 //=========================================================================== | |
| 185 void can1_thread(cyg_addrword_t data) | |
| 186 { | |
| 187 cyg_io_handle_t hCAN1; | |
| 188 cyg_uint8 i; | |
| 189 cyg_uint32 len; | |
| 190 cyg_can_buf_info_t rx_buf_info; | |
| 191 cyg_can_event rx_event; | |
| 192 cyg_can_message tx_msg; | |
| 193 | |
| 194 if (ENOERR != cyg_io_lookup("/dev/can1", &hCAN1)) | |
| 195 { | |
| 196 CYG_TEST_FAIL_FINISH("Error opening /dev/can1"); | |
| 197 } | |
| 198 | |
| 199 len = sizeof(rx_buf_info); | |
| 200 if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len)) | |
| 201 { | |
| 202 CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1"); | |
| 203 } | |
| 204 | |
| 205 // | |
| 206 // first we send the size of our receive buffer to the writer | |
| 207 // we setup tx message now | |
| 208 // | |
| 209 tx_msg.id = 0x000; | |
| 210 tx_msg.ext = CYGNUM_CAN_ID_STD; | |
| 211 tx_msg.rtr = CYGNUM_CAN_FRAME_DATA; | |
| 212 tx_msg.dlc = sizeof(rx_buf_info.rx_bufsize); | |
| 213 | |
| 214 // | |
| 215 // we store size of rx buffer in CAN message. We do not need to care about | |
| 216 // endianess here because this is a loopback driver test and we will receive | |
| 217 // our own messages | |
| 218 // | |
| 219 *((cyg_uint32 *)tx_msg.data) = rx_buf_info.rx_bufsize; | |
| 220 len = sizeof(tx_msg); | |
| 221 | |
| 222 // | |
| 223 // as soon as we send a CAN message, thread 0 will resume because it is waiting | |
| 224 // for a message | |
| 225 // | |
| 226 diag_printf("/dev/can1: Sending size of RX buffer %d\n", rx_buf_info.rx_bufsize); | |
| 227 if (ENOERR != cyg_io_write(hCAN1, &tx_msg, &len)) | |
| 228 { | |
| 229 CYG_TEST_FAIL_FINISH("Error writing to /dev/can1"); | |
| 230 } | |
| 231 cyg_thread_delay(10); // let thread 0 run | |
| 232 | |
| 233 // | |
| 234 // now we check if we received CAN messages - if receive buffer is not full | |
| 235 // the we have an error here because we expect a full receive buffer | |
| 236 // | |
| 237 len = sizeof(rx_buf_info); | |
| 238 if (ENOERR != cyg_io_get_config(hCAN1, CYG_IO_GET_CONFIG_CAN_BUFFER_INFO ,&rx_buf_info, &len)) | |
| 239 { | |
| 240 CYG_TEST_FAIL_FINISH("Error reading config of /dev/can1"); | |
| 241 } | |
| 242 | |
| 243 if (rx_buf_info.rx_bufsize != rx_buf_info.rx_count) | |
| 244 { | |
| 245 CYG_TEST_FAIL_FINISH("RX buffer of /dev/can1 does not contain number of expected messages"); | |
| 246 } | |
| 247 | |
| 248 // | |
| 249 // now we wait for messages from /dev/can0 | |
| 250 // | |
| 251 diag_printf("/dev/can1: Receiving %d CAN messages\n", rx_buf_info.rx_count); | |
| 252 for (i = 0; i < rx_buf_info.rx_count; ++i) | |
| 253 { | |
| 254 len = sizeof(rx_event); | |
| 255 if (ENOERR != cyg_io_read(hCAN1, &rx_event, &len)) | |
| 256 { | |
| 257 CYG_TEST_FAIL_FINISH("Error reading from /dev/can0"); | |
| 258 } | |
| 259 else | |
| 260 { | |
| 261 if (rx_event.flags & CYGNUM_CAN_EVENT_RX) | |
| 262 { | |
| 263 print_can_msg(&rx_event.msg, ""); | |
| 264 if (rx_event.msg.data[0] != (i + 1)) | |
| 265 { | |
| 266 CYG_TEST_FAIL_FINISH("Received /dev/can1 RX event contains invalid data"); | |
| 267 } | |
| 268 } | |
| 269 else | |
| 270 { | |
| 271 CYG_TEST_FAIL_FINISH("Unexpected CAN event for /dev/can1"); | |
| 272 } | |
| 273 | |
| 274 // | |
| 275 // now check if any other flag is set | |
| 276 // | |
| 277 if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX) | |
| 278 { | |
| 279 diag_printf("RX queue overrun successfully indicated for /dev/can1\n"); | |
| 280 | |
| 281 // | |
| 282 // if TX events are supported then we have already a TX event in receive queue because | |
| 283 // we sent a message and the RX queue overrun will occur one message earlier | |
| 284 // | |
| 285 #if defined(CYGOPT_IO_CAN_TX_EVENT_SUPPORT) | |
| 286 if (i < (rx_buf_info.rx_bufsize - 2)) | |
| 287 #else | |
| 288 if (i < (rx_buf_info.rx_bufsize - 1)) | |
| 289 #endif | |
| 290 { | |
| 291 CYG_TEST_FAIL_FINISH("RX queue overrun occured too early for /dev/can1"); | |
| 292 } | |
| 293 else | |
| 294 { | |
| 295 CYG_TEST_PASS_FINISH("can_overrun2 test OK"); | |
| 296 } | |
| 297 } // if (rx_event.flags & CYGNUM_CAN_EVENT_OVERRUN_RX) | |
| 298 } | |
| 299 | |
| 300 } | |
| 301 } | |
| 302 | |
| 303 | |
| 304 | |
| 305 void | |
| 306 cyg_start(void) | |
| 307 { | |
| 308 CYG_TEST_INIT(); | |
| 309 | |
| 310 // | |
| 311 // create the two threads which access the CAN device driver | |
| 312 // | |
| 313 cyg_thread_create(4, can0_thread, | |
| 314 (cyg_addrword_t) 0, | |
| 315 "can0_thread", | |
| 316 (void *) can0_thread_data.stack, | |
| 317 1024 * sizeof(long), | |
| 318 &can0_thread_data.hdl, | |
| 319 &can0_thread_data.obj); | |
| 320 | |
| 321 cyg_thread_create(5, can1_thread, | |
| 322 (cyg_addrword_t) can0_thread_data.hdl, | |
| 323 "can1_thread", | |
| 324 (void *) can1_thread_data.stack, | |
| 325 1024 * sizeof(long), | |
| 326 &can1_thread_data.hdl, | |
| 327 &can1_thread_data.obj); | |
| 328 | |
| 329 cyg_thread_resume(can0_thread_data.hdl); | |
| 330 cyg_thread_resume(can1_thread_data.hdl); | |
| 331 | |
| 332 cyg_scheduler_start(); | |
| 333 } | |
| 334 | |
| 335 #else // CYGFUN_KERNEL_API_C | |
| 336 #define N_A_MSG "Needs kernel C API" | |
| 337 #endif | |
| 338 | |
| 339 #else // CYGPKG_IO_CAN && CYGPKG_KERNEL | |
| 340 #define N_A_MSG "Needs IO/CAN and Kernel" | |
| 341 #endif | |
| 342 | |
| 343 #ifdef N_A_MSG | |
| 344 void | |
| 345 cyg_start( void ) | |
| 346 { | |
| 347 CYG_TEST_INIT(); | |
| 348 CYG_TEST_NA( N_A_MSG); | |
| 349 } | |
| 350 #endif // N_A_MSG | |
| 351 | |
| 352 // EOF serial4.c |
