File indexing completed on 2025-05-11 08:23:52
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
0032
0033
0034
0035 #include <bsp.h>
0036 #include <bsp/mscan-base.h>
0037
0038 #define MIN_NO_OF_TQ 7
0039 #define TSEG_1 1
0040 #define TSEG_2 2
0041 #define NO_OF_TABLE_ENTRIES 4
0042 #define SJW 3
0043
0044 #define CAN_MAX_NO_OF_TQ 25
0045 #define CAN_MAX_NO_OF_TQ_TSEG1 15
0046 #define CAN_MAX_NO_OF_TQ_TSEG2 7
0047 #define CAN_MAX_NO_OF_TQ_SJW 2
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 static uint8_t can_time_segment_table
0062 [CAN_MAX_NO_OF_TQ - MIN_NO_OF_TQ + 1] [NO_OF_TABLE_ENTRIES] = {
0063 {7, 4, 2, 1},
0064 {8, 5, 2, 1},
0065 {9, 6, 2, 2},
0066 {10, 6, 3, 2},
0067 {11, 7, 3, 2},
0068 {12, 8, 3, 2},
0069 {13, 8, 4, 2},
0070 {14, 9, 4, 2},
0071 {15, 10, 4, 2},
0072 {16, 10, 5, 2},
0073 {17, 11, 5, 2},
0074 {18, 12, 5, 2},
0075 {19, 12, 6, 2},
0076 {20, 13, 6, 2},
0077 {21, 14, 6, 2},
0078 {22, 14, 7, 2},
0079 {23, 15, 7, 2},
0080 {24, 15, 8, 2},
0081 {25, 16, 8, 2}
0082 };
0083
0084
0085
0086
0087 static uint8_t prescaler_calculation(
0088 unsigned can_bit_rate,
0089 unsigned can_clock_frq,
0090 uint8_t *tq_no
0091 )
0092 {
0093
0094
0095 uint8_t presc_val,
0096 tq_no_dev_min = 0;
0097 uint32_t bit_rate,
0098 bit_rate_dev,
0099 frq_tq,
0100 bit_rate_dev_min = 0xFFFFFFFF;
0101
0102
0103 for (*tq_no = CAN_MAX_NO_OF_TQ; *tq_no >= MIN_NO_OF_TQ; (*tq_no)--) {
0104
0105
0106 frq_tq = *tq_no * can_bit_rate;
0107
0108
0109 presc_val = (can_clock_frq + frq_tq / 2) / frq_tq;
0110
0111
0112 bit_rate = can_clock_frq / (*tq_no * presc_val);
0113
0114
0115 if (can_bit_rate >= bit_rate) {
0116
0117 bit_rate_dev = can_bit_rate - bit_rate;
0118 } else {
0119
0120 bit_rate_dev = bit_rate - can_bit_rate;
0121 }
0122
0123
0124 if (bit_rate_dev == 0) {
0125
0126
0127 return (uint8_t) (presc_val);
0128 } else {
0129
0130
0131 if (bit_rate_dev < bit_rate_dev_min) {
0132
0133
0134 bit_rate_dev_min = bit_rate_dev;
0135
0136
0137 tq_no_dev_min = *tq_no;
0138 }
0139 }
0140 }
0141
0142
0143 *tq_no = tq_no_dev_min;
0144
0145
0146 frq_tq = *tq_no * can_bit_rate;
0147
0148
0149 return (uint8_t) ((can_clock_frq + frq_tq / 2) / frq_tq);
0150 }
0151
0152
0153
0154
0155
0156 bool mscan_set_bit_rate( volatile mscan *m, unsigned can_bit_rate)
0157 {
0158 mscan_context context;
0159 unsigned prescale_val = 0;
0160 uint8_t tq_no,
0161 tseg_1,
0162 tseg_2,
0163 sseg;
0164
0165 if (can_bit_rate < MSCAN_BIT_RATE_MIN || can_bit_rate > MSCAN_BIT_RATE_MAX) {
0166 return false;
0167 }
0168
0169
0170 mscan_initialization_mode_enter( m, &context);
0171
0172
0173 prescale_val = prescaler_calculation(can_bit_rate, IPB_CLOCK, &tq_no);
0174
0175
0176 if (prescale_val > 64) {
0177
0178 mscan_initialization_mode_leave( m, &context);
0179
0180 return false;
0181 }
0182
0183
0184 tseg_1 = can_time_segment_table[tq_no - MIN_NO_OF_TQ][TSEG_1];
0185 tseg_2 = can_time_segment_table[tq_no - MIN_NO_OF_TQ][TSEG_2];
0186 sseg = can_time_segment_table[tq_no - MIN_NO_OF_TQ][SJW];
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198 m->btr0 = (BTR0_SJW(sseg - 1) | BTR0_BRP(prescale_val - 1));
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 m->btr1 = (BTR1_TSEG2(tseg_2 - 1) | BTR1_TSEG1(tseg_1 - 1));
0211
0212
0213 mscan_initialization_mode_leave( m, &context);
0214
0215 return true;
0216 }
0217
0218
0219
0220
0221 void mscan_interrupts_disable( volatile mscan *m)
0222 {
0223 m->rier = 0;
0224 m->tier = 0;
0225 }
0226
0227
0228
0229
0230
0231
0232 void mscan_initialization_mode_enter( volatile mscan *m, mscan_context *context)
0233 {
0234
0235 context->ctl0 = m->ctl0 & CTL0_TIME;
0236 context->rier = m->rier;
0237 context->tier = m->tier;
0238
0239
0240 m->ctl0 |= CTL0_INITRQ;
0241
0242
0243 while ((m->ctl1 & CTL1_INITAK) == 0) {
0244
0245 }
0246 }
0247
0248
0249
0250
0251
0252
0253 void mscan_initialization_mode_leave( volatile mscan *m, const mscan_context *context)
0254 {
0255
0256 m->ctl0 &= ~CTL0_INITRQ;
0257
0258
0259 while ((m->ctl1 & CTL1_INITAK) != 0) {
0260
0261 }
0262
0263
0264 mscan_sleep_mode_leave( m);
0265
0266
0267 m->ctl0 |= context->ctl0;
0268 m->rier |= context->rier;
0269 m->tier |= context->tier;
0270 }
0271
0272
0273
0274
0275 void mscan_sleep_mode_enter( volatile mscan *m)
0276 {
0277
0278 m->ctl0 |= CTL0_SLPRQ;
0279 }
0280
0281
0282
0283
0284 void mscan_sleep_mode_leave( volatile mscan *m)
0285 {
0286
0287 m->ctl0 &= ~CTL0_SLPRQ;
0288
0289
0290 while ((m->ctl1 & CTL1_SLPAK) != 0) {
0291
0292 }
0293 }
0294
0295
0296
0297
0298
0299
0300 bool mscan_enable( volatile mscan *m, unsigned bit_rate)
0301 {
0302 bool s = true;
0303
0304
0305 mscan_disable( m);
0306
0307
0308 m->ctl1 = CTL1_CANE | CTL1_LISTEN;
0309
0310
0311 m->idac = IDAC_IDAM1 | IDAC_IDAM0;
0312
0313
0314 mscan_filter_clear( m);
0315
0316
0317 s = mscan_set_bit_rate( m, bit_rate);
0318
0319
0320 m->ctl0 = CTL0_RXFRM;
0321
0322
0323 mscan_interrupts_disable( m);
0324
0325 return s;
0326 }
0327
0328
0329
0330
0331
0332
0333 void mscan_disable( volatile mscan *m)
0334 {
0335 mscan_context context;
0336
0337
0338 mscan_interrupts_disable( m);
0339
0340
0341 mscan_initialization_mode_enter( m, &context);
0342
0343
0344 m->ctl1 &= ~CTL1_CANE;
0345 }
0346
0347
0348
0349
0350
0351 void mscan_filter_clear( volatile mscan *m)
0352 {
0353 mscan_context context;
0354
0355 mscan_initialization_mode_enter( m, &context);
0356
0357
0358 m->idar0 = MSCAN_FILTER_ID_DEFAULT;
0359 m->idar1 = MSCAN_FILTER_ID_DEFAULT;
0360 m->idar2 = MSCAN_FILTER_ID_DEFAULT;
0361 m->idar3 = MSCAN_FILTER_ID_DEFAULT;
0362 m->idar4 = MSCAN_FILTER_ID_DEFAULT;
0363 m->idar5 = MSCAN_FILTER_ID_DEFAULT;
0364 m->idar6 = MSCAN_FILTER_ID_DEFAULT;
0365 m->idar7 = MSCAN_FILTER_ID_DEFAULT;
0366
0367
0368 m->idmr0 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0369 m->idmr1 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0370 m->idmr2 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0371 m->idmr3 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0372 m->idmr4 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0373 m->idmr5 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0374 m->idmr6 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0375 m->idmr7 = (uint8_t) MSCAN_FILTER_MASK_DEFAULT;
0376
0377 mscan_initialization_mode_leave( m, &context);
0378 }
0379
0380
0381
0382
0383
0384
0385
0386 unsigned mscan_filter_number( volatile mscan *m)
0387 {
0388 uint8_t idam = m->idac & IDAC_IDAM;
0389
0390 switch (idam) {
0391 case 0:
0392 return MSCAN_FILTER_NUMBER_2;
0393 case IDAC_IDAM0:
0394 return MSCAN_FILTER_NUMBER_4;
0395 case IDAC_IDAM1:
0396 return MSCAN_FILTER_NUMBER_MAX;
0397 default:
0398 return MSCAN_FILTER_NUMBER_MIN;
0399 }
0400 }
0401
0402
0403
0404
0405
0406
0407
0408
0409 bool mscan_set_filter_number( volatile mscan *m, unsigned number)
0410 {
0411 mscan_context context;
0412 uint8_t idac = IDAC_IDAM1 | IDAC_IDAM0;
0413
0414 switch (number) {
0415 case MSCAN_FILTER_NUMBER_MIN:
0416 break;
0417 case MSCAN_FILTER_NUMBER_2:
0418 idac = 0;
0419 break;
0420 case MSCAN_FILTER_NUMBER_4:
0421 idac = IDAC_IDAM0;
0422 break;
0423 case MSCAN_FILTER_NUMBER_MAX:
0424 idac = IDAC_IDAM1;
0425 break;
0426 default:
0427 return false;
0428 }
0429
0430 mscan_initialization_mode_enter( m, &context);
0431
0432 m->idac = idac;
0433
0434 mscan_initialization_mode_leave( m, &context);
0435
0436
0437 mscan_filter_clear( m);
0438
0439 return true;
0440 }
0441
0442
0443
0444
0445
0446
0447
0448 volatile uint8_t *mscan_id_acceptance_register( volatile mscan *m, unsigned i)
0449 {
0450 volatile uint8_t *const idar [8] = {
0451 &m->idar0,
0452 &m->idar1,
0453 &m->idar2,
0454 &m->idar3,
0455 &m->idar4,
0456 &m->idar5,
0457 &m->idar6,
0458 &m->idar7
0459 };
0460
0461 return idar [i];
0462 }
0463
0464
0465
0466
0467
0468
0469
0470 volatile uint8_t *mscan_id_mask_register( volatile mscan *m, unsigned i)
0471 {
0472 volatile uint8_t *const idmr [8] = {
0473 &m->idmr0,
0474 &m->idmr1,
0475 &m->idmr2,
0476 &m->idmr3,
0477 &m->idmr4,
0478 &m->idmr5,
0479 &m->idmr6,
0480 &m->idmr7
0481 };
0482
0483 return idmr [i];
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493 bool mscan_filter_operation(
0494 volatile mscan *m,
0495 bool set,
0496 unsigned index,
0497 uint32_t *id,
0498 uint32_t *mask
0499 )
0500 {
0501 unsigned number = mscan_filter_number( m);
0502 unsigned offset = MSCAN_FILTER_NUMBER_MAX / number;
0503 unsigned shift = 24;
0504
0505 volatile uint8_t *idar = NULL;
0506 volatile uint8_t *idmr = NULL;
0507
0508 if (!set) {
0509 *id = MSCAN_FILTER_ID_DEFAULT;
0510 *mask = MSCAN_FILTER_MASK_DEFAULT;
0511 }
0512
0513 if (index < number) {
0514 mscan_context context;
0515
0516 mscan_initialization_mode_enter( m, &context);
0517
0518 index *= offset;
0519 offset += index;
0520 while (index < offset) {
0521 idar = mscan_id_acceptance_register( m, index);
0522 idmr = mscan_id_mask_register( m, index);
0523
0524 if (set) {
0525 *idar = (uint8_t) (*id >> shift);
0526 *idmr = (uint8_t) (*mask >> shift);
0527 } else {
0528 *id = (*id & ~(0xffU << shift)) | (*idar << shift);
0529 *mask = (*mask & ~(0xffU << shift)) | (*idmr << shift);
0530 }
0531
0532 shift -= 8;
0533
0534 ++index;
0535 }
0536
0537 mscan_initialization_mode_leave( m, &context);
0538 } else {
0539 return false;
0540 }
0541
0542 return true;
0543 }
0544
0545
0546
0547
0548
0549 void mscan_get_error_counters( volatile mscan *m, unsigned *rec, unsigned *tec)
0550 {
0551 mscan_context context;
0552
0553 mscan_initialization_mode_enter( m, &context);
0554
0555 *rec = m->rxerr;
0556 *tec = m->txerr;
0557
0558 mscan_initialization_mode_leave( m, &context);
0559 }