File indexing completed on 2025-05-11 08:24:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031 #include <bsp.h>
0032 #include <stdlib.h>
0033 #include <stdio.h>
0034 #include <string.h>
0035 #include <assert.h>
0036 #include <ctype.h>
0037 #include <rtems/bspIo.h>
0038
0039 #include <grlib/grcan.h>
0040 #include <grlib/canbtrs.h>
0041 #include <drvmgr/drvmgr.h>
0042 #include <grlib/ambapp_bus.h>
0043 #include <grlib/ambapp.h>
0044
0045 #include <grlib/grlib_impl.h>
0046 #include "grcan_internal.h"
0047
0048
0049
0050 #define DBG_TX 2
0051 #define DBG_RX 4
0052 #define DBG_STATE 8
0053
0054 #define DEBUG_FLAGS (DBG_STATE | DBG_RX | DBG_TX )
0055
0056
0057
0058
0059 #include <grlib/debug_defs.h>
0060
0061 static int grcan_hw_read_try(
0062 struct grcan_priv *pDev,
0063 struct grcan_regs *regs,
0064 CANMsg * buffer,
0065 int max
0066 )
0067 {
0068 int i, j;
0069 CANMsg *dest;
0070 struct grcan_msg *source, tmp;
0071 unsigned int wp, rp, size, rxmax, addr;
0072 int trunk_msg_cnt;
0073
0074 FUNCDBG();
0075
0076 wp = READ_REG(®s->rx0wr);
0077 rp = READ_REG(®s->rx0rd);
0078
0079
0080
0081
0082
0083
0084
0085
0086 if (wp != rp) {
0087
0088
0089
0090 size = READ_REG(®s->rx0size);
0091
0092
0093 trunk_msg_cnt = grcan_hw_rxavail(rp, wp, size);
0094
0095
0096
0097
0098 if (trunk_msg_cnt > max)
0099 trunk_msg_cnt = max;
0100
0101
0102 i = trunk_msg_cnt;
0103
0104 addr = (unsigned int)pDev->rx;
0105 source = (struct grcan_msg *)(addr + rp);
0106 dest = buffer;
0107 rxmax = addr + (size - GRCAN_MSG_SIZE);
0108
0109
0110 while (i > 0) {
0111
0112 tmp.head[0] = READ_DMA_WORD(&source->head[0]);
0113 tmp.head[1] = READ_DMA_WORD(&source->head[1]);
0114 if (tmp.head[1] & 0x4) {
0115 DBGC(DBG_RX, "overrun\n");
0116 }
0117 if (tmp.head[1] & 0x2) {
0118 DBGC(DBG_RX, "bus-off mode\n");
0119 }
0120 if (tmp.head[1] & 0x1) {
0121 DBGC(DBG_RX, "error-passive mode\n");
0122 }
0123
0124 dest->extended = tmp.head[0] >> 31;
0125 dest->rtr = (tmp.head[0] >> 30) & 0x1;
0126 if (dest->extended) {
0127 dest->id = tmp.head[0] & 0x3fffffff;
0128 } else {
0129 dest->id = (tmp.head[0] >> 18) & 0xfff;
0130 }
0131 dest->len = tmp.head[1] >> 28;
0132 for (j = 0; j < dest->len; j++)
0133 dest->data[j] = READ_DMA_BYTE(&source->data[j]);
0134
0135
0136 source =
0137 ((unsigned int)source >= rxmax) ?
0138 (struct grcan_msg *)addr : source + 1;
0139 dest++;
0140 i--;
0141 }
0142 {
0143
0144 SPIN_IRQFLAGS(oldLevel);
0145
0146 SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0147 if (pDev->started == STATE_STARTED) {
0148 regs->rx0rd = (unsigned int) source - addr;
0149 regs->rx0ctrl = GRCAN_RXCTRL_ENABLE;
0150 } else {
0151 DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0152 trunk_msg_cnt = state2err[pDev->started];
0153 }
0154 SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0155 }
0156 return trunk_msg_cnt;
0157 }
0158 return 0;
0159 }
0160
0161 static int grcan_hw_write_try(
0162 struct grcan_priv *pDev,
0163 struct grcan_regs *regs,
0164 CANMsg * buffer,
0165 int count
0166 )
0167 {
0168 unsigned int rp, wp, size, txmax, addr;
0169 int ret;
0170 struct grcan_msg *dest;
0171 CANMsg *source;
0172 int space_left;
0173 unsigned int tmp;
0174 int i;
0175
0176 DBGC(DBG_TX, "\n");
0177
0178
0179 rp = READ_REG(®s->tx0rd);
0180 wp = READ_REG(®s->tx0wr);
0181 size = READ_REG(®s->tx0size);
0182
0183 space_left = grcan_hw_txspace(rp, wp, size);
0184
0185
0186 if (space_left < 1)
0187 return 0;
0188
0189
0190 if (space_left > count)
0191 space_left = count;
0192 ret = space_left;
0193
0194 addr = (unsigned int)pDev->tx;
0195
0196 dest = (struct grcan_msg *)(addr + wp);
0197 source = (CANMsg *) buffer;
0198 txmax = addr + (size - GRCAN_MSG_SIZE);
0199
0200 while (space_left > 0) {
0201
0202 if (source->extended) {
0203 tmp = (1 << 31) | (source->id & 0x3fffffff);
0204 } else {
0205 tmp = (source->id & 0xfff) << 18;
0206 }
0207 if (source->rtr)
0208 tmp |= (1 << 30);
0209 dest->head[0] = tmp;
0210 dest->head[1] = source->len << 28;
0211 for (i = 0; i < source->len; i++)
0212 dest->data[i] = source->data[i];
0213 source++;
0214 dest =
0215 ((unsigned int)dest >= txmax) ?
0216 (struct grcan_msg *)addr : dest + 1;
0217 space_left--;
0218 }
0219
0220 {
0221
0222 SPIN_IRQFLAGS(oldLevel);
0223
0224 SPIN_LOCK_IRQ(&pDev->devlock, oldLevel);
0225 if (pDev->started == STATE_STARTED) {
0226 regs->tx0wr = (unsigned int) dest - addr;
0227 regs->tx0ctrl = GRCAN_TXCTRL_ENABLE;
0228 } else {
0229 DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n");
0230 ret = state2err[pDev->started];
0231 }
0232 SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel);
0233 }
0234 return ret;
0235 }
0236
0237
0238 int grcan_read(void *d, CANMsg *msg, size_t ucount)
0239 {
0240 struct grcan_priv *pDev = d;
0241 CANMsg *dest;
0242 unsigned int count, left;
0243 int nread;
0244 int req_cnt;
0245
0246 FUNCDBG();
0247
0248 dest = msg;
0249 req_cnt = ucount;
0250
0251 if ( (!dest) || (req_cnt<1) )
0252 return GRCAN_RET_INVARG;
0253
0254 if (pDev->started != STATE_STARTED) {
0255 return GRCAN_RET_NOTSTARTED;
0256 }
0257
0258 DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount);
0259
0260 nread = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt);
0261 if (nread < 0) {
0262 return nread;
0263 }
0264 count = nread;
0265 if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){
0266 if ( count > 0 ) {
0267
0268 return count;
0269 }
0270
0271
0272 if ( !pDev->rxblock ) {
0273
0274 return GRCAN_RET_TIMEOUT;
0275 }
0276 }
0277
0278 while (count == 0 || (pDev->rxcomplete && (count!=req_cnt))) {
0279 if (!pDev->rxcomplete) {
0280 left = 1;
0281 } else {
0282 left = req_cnt - count;
0283
0284
0285
0286
0287
0288
0289 if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){
0290 left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2;
0291 }
0292 }
0293
0294 nread = grcan_wait_rxdata(pDev, left);
0295 if (nread) {
0296
0297
0298
0299
0300 return nread;
0301 }
0302
0303
0304 nread = grcan_hw_read_try(
0305 pDev,
0306 pDev->regs,
0307 dest+count,
0308 req_cnt-count);
0309
0310 if (nread < 0) {
0311
0312 return nread;
0313 }
0314 count += nread;
0315 }
0316
0317 return count;
0318 }
0319
0320 int grcan_write(void *d, CANMsg *msg, size_t ucount)
0321 {
0322 struct grcan_priv *pDev = d;
0323 CANMsg *source;
0324 unsigned int count, left;
0325 int nwritten;
0326 int req_cnt;
0327
0328 DBGC(DBG_TX,"\n");
0329
0330 if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing)
0331 return GRCAN_RET_NOTSTARTED;
0332
0333 req_cnt = ucount;
0334 source = (CANMsg *) msg;
0335
0336
0337 if (( req_cnt < 1) || (source == NULL) ){
0338 return GRCAN_RET_INVARG;
0339 }
0340
0341 nwritten = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt);
0342 if (nwritten < 0) {
0343 return nwritten;
0344 }
0345 count = nwritten;
0346 if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) {
0347 if ( count > 0 ) {
0348
0349 return count;
0350 }
0351
0352
0353 if ( !pDev->txblock ) {
0354
0355 return GRCAN_RET_TIMEOUT;
0356 }
0357 }
0358
0359
0360 while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){
0361
0362
0363
0364
0365 if ( !pDev->txcomplete ){
0366 left = 1;
0367 }else{
0368 left = req_cnt - count;
0369
0370
0371
0372
0373
0374 if ( left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2) ){
0375 left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2;
0376 }
0377 }
0378
0379 nwritten = grcan_wait_txspace(pDev,left);
0380
0381 if ( nwritten ) {
0382
0383
0384
0385
0386
0387 return nwritten;
0388 }
0389
0390
0391 nwritten = grcan_hw_write_try(
0392 pDev,
0393 pDev->regs,
0394 source+count,
0395 req_cnt-count);
0396
0397 if (nwritten < 0) {
0398
0399 return nwritten;
0400 }
0401 count += nwritten;
0402 }
0403
0404
0405 return count;
0406 }
0407
0408
0409 int grcan_set_speed(void *d, unsigned int speed)
0410 {
0411 struct grcan_priv *pDev = d;
0412 struct grcan_timing timing;
0413 int ret;
0414
0415 FUNCDBG();
0416
0417
0418 if ((pDev->started == STATE_STARTED) || pDev->fd_capable)
0419 return -1;
0420
0421
0422 ret = grlib_canbtrs_calc_timing(
0423 speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT,
0424 &grcan_btrs_ranges, (struct grlib_canbtrs_timing *)&timing);
0425 if (ret)
0426 return -2;
0427
0428
0429 pDev->config.timing = timing;
0430 pDev->config_changed = 1;
0431
0432 return 0;
0433 }
0434
0435 int grcan_set_btrs(void *d, const struct grcan_timing *timing)
0436 {
0437 struct grcan_priv *pDev = d;
0438
0439 FUNCDBG();
0440
0441
0442
0443
0444 if ((pDev->started == STATE_STARTED) || pDev->fd_capable)
0445 return -1;
0446
0447 if ( !timing )
0448 return -2;
0449
0450 pDev->config.timing = *timing;
0451 pDev->config_changed = 1;
0452
0453 return 0;
0454 }