Subversion Repositories svn.mios32

Rev

Rev 2646 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2646 Antichambr 1
// $Id: mios32_can.c 2312 2016-02-27 23:04:51Z tk $
2
//! \defgroup MIOS32_CAN
3
//!
4
//! U(S)ART functions for MIOS32
5
//!
6
//! Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
7
//!
8
//! \{
9
/* ==========================================================================
10
 *
11
 *  Copyright (C) 2008 Thorsten Klose (tk@midibox.org)
12
 *  Licensed for personal non-commercial use only.
13
 *  All other rights reserved.
14
 *
15
 * ==========================================================================
16
 */
17
 
18
/////////////////////////////////////////////////////////////////////////////
19
// Include files
20
/////////////////////////////////////////////////////////////////////////////
21
 
22
#include <mios32.h>
23
 
24
// this module can be optionally enabled in a local mios32_config.h file (included from mios32.h)
25
#if defined(MIOS32_USE_CAN)
26
 
27
 
28
/////////////////////////////////////////////////////////////////////////////
29
// Pin definitions and USART mappings
30
/////////////////////////////////////////////////////////////////////////////
31
 
32
// how many CANs are supported?
33
#define NUM_SUPPORTED_CANS MIOS32_CAN_NUM
34
#if MIOS32_CAN_NUM >1
35
// Note:If CAN2 is used, J19:SO(PB5) and J4B:SC(PB6))  OR  J8/9:SC(PB13) and J8/9:RC1(PB12) are no more available! :-/
36
// Defines the start filter bank for the CAN2 interface (Slave) in the range 0 to 27.
37
#define MIOS32_CAN2_STARTBANK 14
38
#else
39
// All filters banks for CAN1
40
#define MIOS32_CAN2_STARTBANK 27 // no bank for CAN2
41
#endif
42
#define MIOS32_CAN1             CAN1
43
#define MIOS32_CAN1_RX_PORT     GPIOD
44
#define MIOS32_CAN1_RX_PIN      GPIO_Pin_0
45
#define MIOS32_CAN1_TX_PORT     GPIOD
46
#define MIOS32_CAN1_TX_PIN      GPIO_Pin_1
47
#define MIOS32_CAN1_REMAP_FUNC  { GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_CAN1); GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_CAN1); }
48
#define MIOS32_CAN1_RX0_IRQn    CAN1_RX0_IRQn
49
#define MIOS32_CAN1_RX1_IRQn    CAN1_RX1_IRQn
50
#define MIOS32_CAN1_TX_IRQn     CAN1_TX_IRQn
51
#define MIOS32_CAN1_ER_IRQn     CAN1_SCE_IRQn
52
#define MIOS32_CAN1_RX0_IRQHANDLER_FUNC void CAN1_RX0_IRQHandler(void)
53
#define MIOS32_CAN1_RX1_IRQHANDLER_FUNC void CAN1_RX1_IRQHandler(void)
54
#define MIOS32_CAN1_TX_IRQHANDLER_FUNC void CAN1_TX_IRQHandler(void)
55
#define MIOS32_CAN1_ER_IRQHANDLER_FUNC void CAN1_SCE_IRQHandler(void)
56
 
57
 
58
#define MIOS32_CAN2             CAN2
59
#if MIOS32_CAN2_ALTFUNC == 0    //  0: CAN2.RX->PB5, CAN2.TX->PB6
60
#define MIOS32_CAN2_RX_PORT     GPIOB
61
#define MIOS32_CAN2_RX_PIN      GPIO_Pin_5
62
#define MIOS32_CAN2_TX_PORT     GPIOB
63
#define MIOS32_CAN2_TX_PIN      GPIO_Pin_6
64
#define MIOS32_CAN2_REMAP_FUNC  { GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_CAN2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_CAN2); }
65
#else                           //  1: CAN2.RX->PB12, CAN2.TX->PB13
66
#define MIOS32_CAN2_RX_PORT     GPIOB
67
#define MIOS32_CAN2_RX_PIN      GPIO_Pin_12
68
#define MIOS32_CAN2_TX_PORT     GPIOB
69
#define MIOS32_CAN2_TX_PIN      GPIO_Pin_13
70
#define MIOS32_CAN2_REMAP_FUNC  { GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_CAN2); GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_CAN2); }
71
#endif
72
#define MIOS32_CAN2_RX0_IRQn    CAN2_RX0_IRQn
73
#define MIOS32_CAN2_RX1_IRQn    CAN2_RX1_IRQn
74
#define MIOS32_CAN2_TX_IRQn     CAN2_TX_IRQn
75
#define MIOS32_CAN2_ER_IRQn     CAN2_SCE_IRQn
76
#define MIOS32_CAN2_RX0_IRQHANDLER_FUNC void CAN2_RX0_IRQHandler(void)
77
#define MIOS32_CAN2_RX1_IRQHANDLER_FUNC void CAN2_RX1_IRQHandler(void)
78
#define MIOS32_CAN2_TX_IRQHANDLER_FUNC void CAN2_TX_IRQHandler(void)
79
#define MIOS32_CAN2_ER_IRQHANDLER_FUNC void CAN2_SCE_IRQHandler(void)
80
 
81
//#define MIOS32_CAN_MIDI_FILT_BK_NODE_SYSEX    0     //Filter Number for Node SysEx
82
//#define MIOS32_CAN_MIDI_FILT_BK_SYSEX         1     //Filter Number for Device SysEx
83
//
84
//#define MIOS32_CAN_MIDI_FILT_BK_NODE_SYSCOM   2     //Filter Number for Node SysCom
85
//#define MIOS32_CAN_MIDI_FILT_BK_BYPASS        2     //Filter Number for Node SysCom
86
//
87
//#define MIOS32_CAN_BANK_FILT_BK_RT       3     //Filter Number for Real time messges
88
//#define MIOS32_CAN_MIDI_FILT_BK_SYSCOM   3     //Filter Number for Real time messges
89
//
90
//#define MIOS32_CAN_MIDI_FILT_BK_NODE_SYSEX    0     //Filter Number for Node SysEx
91
//#define MIOS32_CAN_MIDI_FILT_BK_SYSEX         1     //Filter Number for Device SysEx
92
 
93
/////////////////////////////////////////////////////////////////////////////
94
// Local variables
95
/////////////////////////////////////////////////////////////////////////////
96
 
97
#if NUM_SUPPORTED_CANS >= 1
98
static u8  can_assigned_to_midi;
99
static can_packet_t rx_buffer[NUM_SUPPORTED_CANS][MIOS32_CAN_RX_BUFFER_SIZE];
100
static volatile u16 rx_buffer_tail[NUM_SUPPORTED_CANS];
101
static volatile u16 rx_buffer_head[NUM_SUPPORTED_CANS];
102
static volatile u16 rx_buffer_size[NUM_SUPPORTED_CANS];
103
 
104
static can_packet_t tx_buffer[NUM_SUPPORTED_CANS][MIOS32_CAN_TX_BUFFER_SIZE];
105
static volatile u16 tx_buffer_tail[NUM_SUPPORTED_CANS];
106
static volatile u16 tx_buffer_head[NUM_SUPPORTED_CANS];
107
static volatile u16 tx_buffer_size[NUM_SUPPORTED_CANS];
108
 
109
static can_stat_report_t can_stat_report[NUM_SUPPORTED_CANS];
110
#endif
111
 
112
#if defined MIOS32_CAN_VERBOSE
113
static u8 can_verbose = MIOS32_CAN_VERBOSE;
114
#else
115
static u8 can_verbose = 0;
116
#endif
117
 
118
u32 can_temp;
119
 
120
 
121
 
122
/////////////////////////////////////////////////////////////////////////////
123
//! Initializes CAN MIDI layer
124
//! \param[in] mode currently only mode 0 supported
125
//! \return < 0 if initialisation failed
126
//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
127
/////////////////////////////////////////////////////////////////////////////
128
s32 MIOS32_CAN_VerboseSet(u8 level)
129
{
130
#if MIOS32_CAN_NUM == 0
131
  return -1; // no CAN enabled
132
#else
133
 
134
  can_verbose = level;
135
 
136
  return 0; // no error
137
#endif
138
}
139
 
140
 
141
/////////////////////////////////////////////////////////////////////////////
142
//! Initializes CAN MIDI layer
143
//! \param[in] mode currently only mode 0 supported
144
//! \return < 0 if initialisation failed
145
//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_MIDI layer functions
146
/////////////////////////////////////////////////////////////////////////////
147
s32 MIOS32_CAN_VerboseGet(void)
148
{
149
#if MIOS32_CAN_NUM == 0
150
  return -1; // no CAN enabled
151
#else
152
  return can_verbose; // no error
153
#endif
154
}
155
 
156
 
157
/////////////////////////////////////////////////////////////////////////////
158
//! Initializes CAN interfaces
159
//! \param[in] mode currently only mode 0 supported
160
//! \return < 0 if initialisation failed
161
//! \note Applications shouldn't call this function directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
162
/////////////////////////////////////////////////////////////////////////////
163
s32 MIOS32_CAN_Init(u32 mode)
164
{
165
  // currently only mode 0 supported
166
  if( mode != 0 )
167
    return -1; // unsupported mode
168
 
169
#if NUM_SUPPORTED_CANS == 0
170
  return -1; // no CANs
171
#else
172
 
173
  // map and init CAN pins
174
#if  MIOS32_CAN1_ASSIGNMENT != 0 // not disabled
175
  MIOS32_CAN1_REMAP_FUNC;
176
#endif
177
#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
178
  MIOS32_CAN2_REMAP_FUNC;
179
#endif
180
 
181
  // enable CANx clocks
182
#if  MIOS32_CAN1_ASSIGNMENT != 0 // not disabled
183
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
184
#endif
185
#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
186
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
187
#endif
188
 
189
  // initialize CANs and clear buffers
190
  u8 can;
191
  for(can=0; can<NUM_SUPPORTED_CANS; ++can) {
192
    // initialize Tx/Rx Buffers
193
    rx_buffer_tail[can] = rx_buffer_head[can] = rx_buffer_size[can] = 0;
194
    tx_buffer_tail[can] = tx_buffer_head[can] = tx_buffer_size[can] = 0;
195
    // initialize info report structure
196
    MIOS32_CAN_ReportReset(can);
197
    // initialize Default port
198
    MIOS32_CAN_InitPortDefault(can);
199
    // initialize peripheral
200
    if(MIOS32_CAN_InitPeriph(can) < 0)return -1;
201
  }
202
 
203
  // configure and enable CAN interrupts
204
#if MIOS32_CAN1_ASSIGNMENT != 0 // not disabled
205
  // enable CAN interrupt
206
  MIOS32_CAN1->IER = 0x0000000;
207
  /* Enable MIOS32_CAN1 RX0 interrupt IRQ channel */
208
  MIOS32_IRQ_Install(MIOS32_CAN1_RX0_IRQn, MIOS32_IRQ_CAN_PRIORITY);
209
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_FMP0, ENABLE);
210
  /* Enable MIOS32_CAN1 RX1 interrupt IRQ channel */
211
  MIOS32_IRQ_Install(MIOS32_CAN1_RX1_IRQn, MIOS32_IRQ_CAN_PRIORITY);
212
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_FMP1, ENABLE);
213
  /* Enable MIOS32_CAN1 TX interrupt IRQ channel */
214
  MIOS32_IRQ_Install(MIOS32_CAN1_TX_IRQn, MIOS32_IRQ_CAN_PRIORITY);
215
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_TME, DISABLE);
216
#if 1
217
  /* Enable MIOS32_CAN1 SCE(errors) interrupts IRQ channels */
218
  MIOS32_IRQ_Install(MIOS32_CAN1_ER_IRQn, MIOS32_IRQ_CAN_PRIORITY);
219
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_EWG, ENABLE);
220
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, ENABLE);
221
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
222
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_LEC, DISABLE);
223
  CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
224
#endif
225
#endif
226
 
227
#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN1_ASSIGNMENT != 0
228
  // enable CAN interrupt
229
  MIOS32_CAN2->IER = 0x0000000;
230
  /* Enable MIOS32_CAN2 RX0 interrupt IRQ channel */
231
  MIOS32_IRQ_Install(MIOS32_CAN2_RX0_IRQn, MIOS32_IRQ_CAN_PRIORITY);
232
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_FMP0, ENABLE);
233
  /* Enable MIOS32_CAN2 RX1 interrupt IRQ channel */
234
  MIOS32_IRQ_Install(MIOS32_CAN2_RX1_IRQn, MIOS32_IRQ_CAN_PRIORITY);
235
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_FMP1, ENABLE);
236
  /* Enable MIOS32_CAN2 TX interrupt IRQ channel */
237
  MIOS32_IRQ_Install(MIOS32_CAN2_TX_IRQn, MIOS32_IRQ_CAN_PRIORITY);
238
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_TME, ENABLE);
239
#if 0
240
  /* Enable MIOS32_CAN2 SCE(errors) interrupts IRQ channels */
241
  MIOS32_IRQ_Install(MIOS32_CAN2_ER_IRQn, MIOS32_IRQ_PRIO_MED);
242
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_EWG, ENABLE);
243
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_EPV, ENABLE);
244
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_BOF, ENABLE);
245
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_LEC, ENABLE);
246
  CAN_ITConfig(MIOS32_CAN2, CAN_IT_ERR, ENABLE);
247
#endif
248
#endif
249
 
250
  return 0; // no error
251
#endif
252
}
253
 
254
 
255
/////////////////////////////////////////////////////////////////////////////
256
//! \return 0 if CAN is not assigned to a MIDI function
257
//! \return 1 if CAN is assigned to a MIDI function
258
/////////////////////////////////////////////////////////////////////////////
259
s32 MIOS32_CAN_IsAssignedToMIDI(u8 can)
260
{
261
#if NUM_SUPPORTED_CANS == 0
262
  return 0; // no CAN available
263
#else
264
  return (can_assigned_to_midi & (1 << can)) ? 1 : 0;
265
#endif
266
}
267
 
268
 
269
/////////////////////////////////////////////////////////////////////////////
270
//! Initializes a given CAN interface based on given baudrate and TX output mode
271
//! \param[in] CAN number (0..1)
272
//! \param[in] is_midi MIDI or common CAN interface?
273
//! \return < 0 if initialisation failed
274
/////////////////////////////////////////////////////////////////////////////
275
s32 MIOS32_CAN_InitPort(u8 can, u8 is_midi)
276
{
277
#if NUM_SUPPORTED_CANS == 0
278
  return -1; // no CAN available
279
#else
280
  GPIO_InitTypeDef GPIO_InitStructure;
281
  GPIO_StructInit(&GPIO_InitStructure);
282
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
283
 
284
  if( can >= NUM_SUPPORTED_CANS )
285
    return -1; // unsupported CAN
286
 
287
  // MIDI assignment
288
  if( is_midi ) {
289
    can_assigned_to_midi |= (1 << can);
290
  } else {
291
    can_assigned_to_midi &= ~(1 << can);
292
  }
293
 
294
  switch( can ) {
295
#if NUM_SUPPORTED_CANS >= 1 && MIOS32_CAN1_ASSIGNMENT != 0
296
    case 0: {
297
      // configure CAN pins
298
      GPIO_InitTypeDef GPIO_InitStructure;
299
      GPIO_StructInit(&GPIO_InitStructure);
300
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
301
 
302
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
303
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
304
      GPIO_InitStructure.GPIO_Pin = MIOS32_CAN1_RX_PIN;
305
      GPIO_Init(MIOS32_CAN1_RX_PORT, &GPIO_InitStructure);
306
 
307
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
308
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
309
      GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
310
      GPIO_InitStructure.GPIO_Pin = MIOS32_CAN1_TX_PIN;
311
      GPIO_Init(MIOS32_CAN1_TX_PORT, &GPIO_InitStructure);
312
    } break;
313
#endif
314
 
315
#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
316
    case 1: {
317
      // configure CAN pins
318
      GPIO_InitTypeDef GPIO_InitStructure;
319
      GPIO_StructInit(&GPIO_InitStructure);
320
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
321
 
322
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
323
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
324
      GPIO_InitStructure.GPIO_Pin = MIOS32_CAN2_RX_PIN;
325
      GPIO_Init(MIOS32_CAN2_RX_PORT, &GPIO_InitStructure);
326
 
327
      GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
328
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
329
      GPIO_InitStructure.GPIO_Pin = MIOS32_CAN2_TX_PIN;
330
      GPIO_Init(MIOS32_CAN2_TX_PORT, &GPIO_InitStructure);
331
    } break;
332
#endif
333
 
334
    default:
335
      return -1; // unsupported CAN
336
  }
337
 
338
  return 0; // no error
339
#endif
340
}
341
 
342
 
343
/////////////////////////////////////////////////////////////////////////////
344
//! Initializes a given CAN interface based on default settings
345
//! \param[in] CAN number (0..1)
346
//! \return < 0 if initialisation failed
347
/////////////////////////////////////////////////////////////////////////////
348
s32 MIOS32_CAN_InitPortDefault(u8 can)
349
{
350
#if NUM_SUPPORTED_CANS == 0
351
  return -1; // no CAN available
352
#else
353
  switch( can ) {
354
#if NUM_SUPPORTED_CANS >= 1 && MIOS32_CAN1_ASSIGNMENT != 0
355
    case 0: {
356
      MIOS32_CAN_InitPort(0, MIOS32_CAN1_ASSIGNMENT == 1);
357
    } break;
358
#endif
359
 
360
#if NUM_SUPPORTED_CANS >= 2 && MIOS32_CAN2_ASSIGNMENT != 0
361
    case 1: {
362
      MIOS32_CAN_InitPort(1, MIOS32_CAN2_ASSIGNMENT == 1);
363
    } break;
364
#endif
365
 
366
    default:
367
      return -1; // unsupported CAN
368
  }
369
 
370
  return 0; // no error
371
#endif
372
}
373
 
374
 
375
/////////////////////////////////////////////////////////////////////////////
376
//! sets the baudrate of a CAN port
377
//! \param[in] CAN number (0..1)
378
//! \return -1: can not available
379
//! \return -2: function not prepared for this CAN
380
//! \return -3: CAN Initialisation failed
381
/////////////////////////////////////////////////////////////////////////////
382
s32 MIOS32_CAN_InitPeriph(u8 can)
383
{
384
#if NUM_SUPPORTED_CANS == 0
385
  return -1; // no CAN available
386
#else
387
  if( can >= NUM_SUPPORTED_CANS )
388
    return -1;
389
 
390
  // CAN initialisation
391
  CAN_InitTypeDef CAN_InitStruct;
392
  CAN_StructInit(&CAN_InitStruct);
393
  CAN_InitStruct.CAN_TTCM = DISABLE;
394
  CAN_InitStruct.CAN_NART = DISABLE;
395
  CAN_InitStruct.CAN_RFLM = ENABLE;
396
  CAN_InitStruct.CAN_TXFP = ENABLE;
397
  CAN_InitStruct.CAN_ABOM = ENABLE;
398
  CAN_InitStruct.CAN_Mode = CAN_Mode_Normal;
399
  // -> 84 Mhz / 2 / 3 -> 14 MHz --> 7 quanta for 2 MBaud
400
  CAN_InitStruct.CAN_SJW = CAN_SJW_1tq;
401
  CAN_InitStruct.CAN_BS1 = CAN_BS1_4tq;
402
  CAN_InitStruct.CAN_BS2 = CAN_BS2_2tq;
403
  CAN_InitStruct.CAN_Prescaler = 4;
404
 
405
  switch( can ) {
406
    case 0: if(CAN_Init(MIOS32_CAN1, &CAN_InitStruct) == CAN_InitStatus_Failed)return -3; break;
407
#if NUM_SUPPORTED_CANS >= 2
408
    case 1: if(CAN_Init(MIOS32_CAN2, &CAN_InitStruct) == CAN_InitStatus_Failed)return -3; break;
409
#endif
410
    default:
411
      return -2; // not prepared
412
  }
413
 
414
  return 0;
415
#endif
416
}
417
 
418
/////////////////////////////////////////////////////////////////////////////
419
//! Initializes a 32 bits filter
420
//! \param[in] can filter bank number
421
//! \param[in] extended id for filter
422
//! \param[in] extended id for mask
423
//! \return < 0 if initialisation failed
424
/////////////////////////////////////////////////////////////////////////////
425
s32 MIOS32_CAN_Init32bitFilter(u8 bank, u8 fifo, can_ext_filter_t filter, u8 enabled)
426
{
427
#if MIOS32_CAN_NUM == 0
428
  return -1; // no CAN enabled
429
#else
430
  CAN_FilterInitTypeDef CAN_FilterInitStructure;
431
  // bank / mode / scale
432
  CAN_FilterInitStructure.CAN_FilterNumber=bank;
433
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
434
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
435
  // filter / mask
436
  CAN_FilterInitStructure.CAN_FilterIdHigh=filter.filt.data_h;
437
  CAN_FilterInitStructure.CAN_FilterIdLow=filter.filt.data_l;
438
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh=filter.mask.data_h;
439
  CAN_FilterInitStructure.CAN_FilterMaskIdLow=filter.mask.data_l;
440
  // fifo / enable
441
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=0;
442
  CAN_FilterInitStructure.CAN_FilterActivation=enabled;
443
  CAN_FilterInit(&CAN_FilterInitStructure);
444
 
445
  return 0; // no error
446
#endif
447
}
448
 
449
/////////////////////////////////////////////////////////////////////////////
450
//! Initializes a 16 bits filter
451
//! \param[in] can filter bank number
452
//! \param[in] standard id for filter
453
//! \param[in] standard id for mask
454
//! \return < 0 if initialisation failed
455
/////////////////////////////////////////////////////////////////////////////
456
s32 MIOS32_CAN_Init16bitFilter(u8 bank, u8 fifo, can_std_filter_t filter1, can_std_filter_t filter2, u8 enabled)
457
{
458
#if MIOS32_CAN_NUM == 0
459
  return -1; // no CAN enabled
460
#else
461
  CAN_FilterInitTypeDef CAN_FilterInitStructure;
462
  // bank / mode / scale
463
  CAN_FilterInitStructure.CAN_FilterNumber=bank;
464
  CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
465
  CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_16bit;
466
  // first filter/ firsf mask
467
  CAN_FilterInitStructure.CAN_FilterIdLow = filter1.filt.ALL;
468
  CAN_FilterInitStructure.CAN_FilterMaskIdLow = filter1.mask.ALL;
469
  // second filter / second mask
470
  CAN_FilterInitStructure.CAN_FilterIdHigh =  filter2.filt.ALL;
471
  CAN_FilterInitStructure.CAN_FilterMaskIdHigh = filter2.mask.ALL;
472
  // fifo / enable
473
  CAN_FilterInitStructure.CAN_FilterFIFOAssignment=fifo;
474
  CAN_FilterInitStructure.CAN_FilterActivation=enabled;
475
  CAN_FilterInit(&CAN_FilterInitStructure);
476
 
477
  return 0; // no error
478
#endif
479
}
480
 
481
/////////////////////////////////////////////////////////////////////////////
482
//! sets the baudrate of a CAN port
483
//! \param[in] CAN number (0..1)
484
//! \return -1: can not available
485
//! \return -2: function not prepared for this CAN
486
//! \return -3: CAN Initialisation failed
487
/////////////////////////////////////////////////////////////////////////////
488
s32 MIOS32_CAN_InitPacket(can_packet_t *packet)
489
{
490
#if NUM_SUPPORTED_CANS == 0
491
  return -1; // no CAN available
492
#else
493
  // reset
494
  packet->id.ALL = 0;
495
  packet->ctrl.ALL = 0;
496
  packet->data.data_l = 0;
497
  packet->data.data_h = 0;
498
  return 0;
499
#endif
500
}
501
 
502
/////////////////////////////////////////////////////////////////////////////
503
//! returns number of free bytes in receive buffer
504
//! \param[in] CAN number (0..1)
505
//! \return can number of free bytes
506
//! \return 1: can available
507
//! \return 0: can not available
508
/////////////////////////////////////////////////////////////////////////////
509
s32 MIOS32_CAN_RxBufferFree(u8 can)
510
{
511
#if NUM_SUPPORTED_CANS == 0
512
  return 0; // no CAN available
513
#else
514
  if( can >= NUM_SUPPORTED_CANS )
515
    return 0;
516
  else
517
    return MIOS32_CAN_RX_BUFFER_SIZE - rx_buffer_size[can];
518
#endif
519
}
520
 
521
 
522
/////////////////////////////////////////////////////////////////////////////
523
//! returns number of used bytes in receive buffer
524
//! \param[in] CAN number (0..1)
525
//! \return > 0: number of used bytes
526
//! \return 0 if can not available
527
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
528
/////////////////////////////////////////////////////////////////////////////
529
s32 MIOS32_CAN_RxBufferUsed(u8 can)
530
{
531
#if NUM_SUPPORTED_CANS == 0
532
  return 0; // no CAN available
533
#else
534
  if( can >= NUM_SUPPORTED_CANS )
535
    return 0;
536
  else
537
    return rx_buffer_size[can];
538
#endif
539
}
540
 
541
 
542
/////////////////////////////////////////////////////////////////////////////
543
//! gets a byte from the receive buffer
544
//! \param[in] CAN number (0..1)
545
//! \return -1 if CAN not available
546
//! \return -2 if no new byte available
547
//! \return >= 0: number of received bytes
548
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
549
/////////////////////////////////////////////////////////////////////////////
550
s32 MIOS32_CAN_RxBufferGet(u8 can, can_packet_t *p)
551
{
552
#if NUM_SUPPORTED_CANS == 0
553
  return -1; // no CAN available
554
#else
555
  if( can >= NUM_SUPPORTED_CANS )
556
    return -1; // CAN not available
557
 
558
  if( !rx_buffer_size[can] )
559
    return -2; // nothing new in buffer
560
 
561
  // get byte - this operation should be atomic!
562
  MIOS32_IRQ_Disable();
563
  *p = rx_buffer[can][rx_buffer_tail[can]];
564
  if( ++rx_buffer_tail[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
565
    rx_buffer_tail[can] = 0;
566
  --rx_buffer_size[can];
567
 
568
  //can_stat_report[can].tx_done_ctr++;
569
  MIOS32_IRQ_Enable();
570
 
571
  return 0; // return received byte
572
#endif
573
}
574
 
575
 
576
/////////////////////////////////////////////////////////////////////////////
577
//! returns the next byte of the receive buffer without taking it
578
//! \param[in] CAN number (0..1)
579
//! \return -1 if CAN not available
580
//! \return -2 if no new byte available
581
//! \return >= 0: number of received bytes
582
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
583
/////////////////////////////////////////////////////////////////////////////
584
s32 MIOS32_CAN_RxBufferPeek(u8 can, can_packet_t *p)
585
{
586
#if NUM_SUPPORTED_CANS == 0
587
  return -1; // no CAN available
588
#else
589
  if( can >= NUM_SUPPORTED_CANS )
590
    return -1; // CAN not available
591
 
592
  if( !rx_buffer_size[can] )
593
    return -2; // nothing new in buffer
594
 
595
  // get byte - this operation should be atomic!
596
  MIOS32_IRQ_Disable();
597
  *p = rx_buffer[can][rx_buffer_tail[can]];
598
  MIOS32_IRQ_Enable();
599
 
600
  return 0; // return received byte
601
#endif
602
}
603
 
604
/////////////////////////////////////////////////////////////////////////////
605
//! remove the next byte of the receive buffer without taking it
606
//! \param[in] CAN number (0..1)
607
//! \return -1 if CAN not available
608
//! \return -2 if no new byte available
609
//! \return >= 0: number of received bytes
610
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
611
/////////////////////////////////////////////////////////////////////////////
612
s32 MIOS32_CAN_RxBufferRemove(u8 can)
613
{
614
#if NUM_SUPPORTED_CANS == 0
615
  return -1; // no CAN available
616
#else
617
  if( can >= NUM_SUPPORTED_CANS )
618
    return -1; // CAN not available
619
 
620
  if( !rx_buffer_size[can] )
621
    return -2; // nothing new in buffer
622
 
623
  // dec buffer - this operation should be atomic!
624
  MIOS32_IRQ_Disable();
625
  if( ++rx_buffer_tail[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
626
    rx_buffer_tail[can] = 0;
627
  --rx_buffer_size[can];
628
  MIOS32_IRQ_Enable();
629
 
630
  return 0; // return received byte
631
#endif
632
}
633
 
634
/////////////////////////////////////////////////////////////////////////////
635
//! puts a byte onto the receive buffer
636
//! \param[in] CAN number (0..1)
637
//! \param[in] b byte which should be put into Rx buffer
638
//! \return 0 if no error
639
//! \return -1 if CAN not available
640
//! \return -2 if buffer full (retry)
641
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
642
/////////////////////////////////////////////////////////////////////////////
643
s32 MIOS32_CAN_RxBufferPut(u8 can, can_packet_t p)
644
{
645
#if NUM_SUPPORTED_CANS == 0
646
  return -1; // no CAN available
647
#else
648
  if( can >= NUM_SUPPORTED_CANS )
649
    return -1; // CAN not available
650
 
651
  if( rx_buffer_size[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
652
    return -2; // buffer full (retry)
653
 
654
  // copy received can packet into receive buffer
655
  // this operation should be atomic!
656
  MIOS32_IRQ_Disable();
657
  rx_buffer[can][rx_buffer_head[can]] = p;
658
  if( ++rx_buffer_head[can] >= MIOS32_CAN_RX_BUFFER_SIZE )
659
    rx_buffer_head[can] = 0;
660
  ++rx_buffer_size[can];
661
 
662
 
663
  MIOS32_IRQ_Enable();
664
 
665
  return 0; // no error
666
#endif
667
}
668
 
669
/////////////////////////////////////////////////////////////////////////////
670
//! returns number of free bytes in transmit buffer
671
//! \param[in] CAN number (0..1)
672
//! \return number of free bytes
673
//! \return 0 if can not available
674
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
675
/////////////////////////////////////////////////////////////////////////////
676
s32 MIOS32_CAN_TxBufferFree(u8 can)
677
{
678
#if NUM_SUPPORTED_CANS == 0
679
  return -1; // no CAN available
680
#else
681
  if( can >= NUM_SUPPORTED_CANS )
682
    return -1;
683
  else
684
    return MIOS32_CAN_TX_BUFFER_SIZE - tx_buffer_size[can];
685
#endif
686
}
687
 
688
 
689
/////////////////////////////////////////////////////////////////////////////
690
//! returns number of used bytes in transmit buffer
691
//! \param[in] CAN number (0..1)
692
//! \return number of used bytes
693
//! \return 0 if can not available
694
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
695
/////////////////////////////////////////////////////////////////////////////
696
s32 MIOS32_CAN_TxBufferUsed(u8 can)
697
{
698
#if NUM_SUPPORTED_CANS == 0
699
  return -1; // no CAN available
700
#else
701
  if( can >= NUM_SUPPORTED_CANS )
702
    return -1;
703
  else
704
    return tx_buffer_size[can];
705
#endif
706
}
707
 
708
 
709
/////////////////////////////////////////////////////////////////////////////
710
//! gets a byte from the transmit buffer
711
//! \param[in] CAN number (0..1)
712
//! \return -1 if CAN not available
713
//! \return -2 if no new byte available
714
//! \return >= 0: transmitted byte
715
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
716
/////////////////////////////////////////////////////////////////////////////
717
s32 MIOS32_CAN_TxBufferGet(u8 can, can_packet_t *p)
718
{
719
#if NUM_SUPPORTED_CANS == 0
720
  return -1; // no CAN available
721
#else
722
  if( can >= NUM_SUPPORTED_CANS )
723
    return -1; // CAN not available
724
 
725
  if( !tx_buffer_size[can] )
726
    return -2; // nothing new in buffer
727
 
728
  // get byte - this operation should be atomic!
729
  MIOS32_IRQ_Disable();
730
  *p = tx_buffer[can][tx_buffer_tail[can]];
731
  if( ++tx_buffer_tail[can] >= MIOS32_CAN_TX_BUFFER_SIZE )
732
    tx_buffer_tail[can] = 0;
733
  --tx_buffer_size[can];
734
  MIOS32_IRQ_Enable();
735
 
736
  return 0; // return transmitted byte
737
#endif
738
}
739
 
740
 
741
/////////////////////////////////////////////////////////////////////////////
742
//! puts more than one byte onto the transmit buffer (used for atomic sends)
743
//! \param[in] CAN number (0..1)
744
//! \param[in] *buffer pointer to buffer to be sent
745
//! \param[in] len number of bytes to be sent
746
//! \return 0 if no error
747
//! \return -1 if CAN not available
748
//! \return -2 if buffer full or cannot get all requested bytes (retry)
749
//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
750
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
751
/////////////////////////////////////////////////////////////////////////////
752
s32 MIOS32_CAN_TxBufferPutMore_NonBlocking(u8 can, can_packet_t* p,u16 len)
753
{
754
#if NUM_SUPPORTED_CANS == 0
755
  return -1; // no CAN available
756
#else
757
  if( can >= NUM_SUPPORTED_CANS )
758
    return -1; // CAN not available
759
 
760
  if( (tx_buffer_size[can] + len) >= MIOS32_CAN_TX_BUFFER_SIZE )
761
    return -2; // buffer full or cannot get all requested bytes (retry)
762
 
763
  // exit immediately if CAN bus errors (CAN doesn't send messages anymore)
764
  if( MIOS32_CAN_BusErrorCheck(can) < 0 )
765
    return -3; // bus error
766
 
767
  CAN_TypeDef* CANx = NULL;
768
  if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
769
  u16 i;
770
  for(i=0; i<len; ++i) {
771
    // if buffer is empty / interrupt is not enable
772
    // we first try to fill some empty mailboxes
773
    if(MIOS32_CAN_TxBufferUsed(can) == 0){
774
      // is any mailbox empty ?
775
      s8 mailbox = -1;
776
      if( CANx->TSR & CAN_TSR_TME0)mailbox = 0;
777
      else if( CANx->TSR & CAN_TSR_TME1)mailbox = 1;
778
      else if( CANx->TSR & CAN_TSR_TME2)mailbox = 2;
779
 
780
      if(mailbox>=0){
781
        // yes, we send the packet
782
        p[i].id.txrq = 1; //TX Req flag
783
        CANx->sTxMailBox[mailbox].TDTR = p[i].ctrl.ALL;
784
        CANx->sTxMailBox[mailbox].TDLR = p[i].data.data_l;
785
        CANx->sTxMailBox[mailbox].TDHR = p[i].data.data_h;
786
        CANx->sTxMailBox[mailbox].TIR = p[i].id.ALL;
787
        // for CAN_Report
788
        can_stat_report[can].tx_packets_ctr +=1;
789
        // packet directly put in mailbox
790
        return mailbox; // >= 0 no error
791
      }
792
    }
793
    // there's something in buffer, new packet must be put after
794
    // or mailbpx < 0, we put packet in the buffer first
795
    // copy bytes to be transmitted into transmit buffer
796
    // this operation should be atomic!
797
    MIOS32_IRQ_Disable();
798
    tx_buffer[can][tx_buffer_head[can]] = p[i];
799
    // for CAN_Report
800
    can_stat_report[can].tx_packets_ctr +=1;
801
    if( ++tx_buffer_head[can] >= MIOS32_CAN_TX_BUFFER_SIZE )
802
      tx_buffer_head[can] = 0;
803
    tx_buffer_size[can]++;
804
 
805
    // and we start TME interrupt
806
    CANx->IER |= CAN_IT_TME;
807
 
808
    MIOS32_IRQ_Enable();
809
  }
810
 
811
 
812
  return 0; // no error
813
#endif
814
}
815
 
816
/////////////////////////////////////////////////////////////////////////////
817
//! puts more than one byte onto the transmit buffer (used for atomic sends)<BR>
818
//! (blocking function)
819
//! \param[in] CAN number (0..1)
820
//! \param[in] *buffer pointer to buffer to be sent
821
//! \param[in] len number of bytes to be sent
822
//! \return 0 if no error
823
//! \return -1 if CAN not available
824
//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
825
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
826
/////////////////////////////////////////////////////////////////////////////
827
s32 MIOS32_CAN_TxBufferPutMore(u8 can, can_packet_t *packets, u16 len)
828
{
829
  s32 error;
830
 
831
  while( (error=MIOS32_CAN_TxBufferPutMore_NonBlocking(can, packets, len)) == -2 );
832
 
833
  return error;
834
}
835
 
836
 
837
/////////////////////////////////////////////////////////////////////////////
838
//! puts a byte onto the transmit buffer
839
//! \param[in] CAN number (0..1)
840
//! \param[in] b byte which should be put into Tx buffer
841
//! \return 0 if no error
842
//! \return -1 if CAN not available
843
//! \return -2 if buffer full (retry)
844
//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
845
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
846
/////////////////////////////////////////////////////////////////////////////
847
s32 MIOS32_CAN_TxBufferPut_NonBlocking(u8 can, can_packet_t p)
848
{
849
  // for more comfortable usage...
850
  // -> just forward to MIOS32_CAN_TxBufferPutMore
851
  return MIOS32_CAN_TxBufferPutMore(can, &p, 1);
852
}
853
 
854
 
855
/////////////////////////////////////////////////////////////////////////////
856
//! puts a byte onto the transmit buffer<BR>
857
//! (blocking function)
858
//! \param[in] CAN number (0..1)
859
//! \param[in] b byte which should be put into Tx buffer
860
//! \return 0 if no error
861
//! \return -1 if CAN not available
862
//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
863
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
864
/////////////////////////////////////////////////////////////////////////////
865
s32 MIOS32_CAN_TxBufferPut(u8 can, can_packet_t p)
866
{
867
  s32 error;
868
 
869
  while( (error=MIOS32_CAN_TxBufferPutMore(can, &p, 1)) == -2 );
870
 
871
  return error;
872
}
873
 
874
 
875
/////////////////////////////////////////////////////////////////////////////
876
// Used during transmit or receive polling to determine if a bus error has occured
877
// (e.g. receiver passive or no nodes connected to bus)
878
// In this case, all pending transmissions will be aborted
879
// The midian_state.PANIC flag is set to report to the application, that the
880
// bus is not ready for transactions (flag accessible via MIDIAN_ErrorStateGet).
881
// This flag will be cleared by WaitAck once we got back a message from any slave
882
// OUT: returns -1 if bus permanent off (requires re-initialisation)
883
//      returns -2 if panic state reached
884
/////////////////////////////////////////////////////////////////////////////
885
s32 MIOS32_CAN_BusErrorCheck(u8 can)
886
{
887
#if NUM_SUPPORTED_CANS == 0
888
  return -1; // no CAN available
889
#else
890
 
891
  can_stat_err_t err;
892
  err = can_stat_report[can].bus_last_err;
893
  //if((CANx->ESR &7)!=0){
894
  if((err.tec) > (can_stat_report[can].bus_curr_err.tec)){
895
      if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] %s %s %s. rec:%d, tec:%d>", err.ewgf? "warning" : "", err.epvf? "passive" : "", err.boff? "off" : "", err.rec, err.tec);
896
 
897
      if(err.ewgf){
898
          can_stat_report[can].bus_state = WARNING;
899
      }
900
 
901
      if(err.epvf){
902
          can_stat_report[can].bus_state = PASSIVE;
903
      }
904
      if(err.boff){
905
          can_stat_report[can].bus_state = BUS_OFF;
906
      }
907
      can_stat_report[can].bus_curr_err = err;
908
  }else {
909
      CAN_TypeDef* CANx = NULL;
910
      if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
911
      err.ALL = CANx->ESR;
912
      if((err.tec) < (can_stat_report[can].bus_curr_err.tec)){
913
          if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] %s %s %s. rec:%d, tec:%d<", err.ewgf? "warning" : "", err.epvf? "passive" : "", err.boff? "off" : "", err.rec, err.tec);
914
          can_stat_report[can].bus_curr_err = err;
915
          can_stat_report[can].bus_last_err = err;
916
      }
917
      if(!(err.ALL & 7))can_stat_report[can].bus_state = BUS_OK;
918
 
919
  }
920
//    CAN_TypeDef* CANx = NULL;
921
//    if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
922
//    err = CANx->ESR;
923
//
924
//    if((err.ALL & 7) < (can_stat_report[can].bus_curr_err.ALL & 7)){
925
//
926
//
927
//    if(!err.boff){
928
//        //MIOS32_CAN_InitPeriph(can);
929
//        can_stat_report[can].bus_state = PASSIVE;
930
//        if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] CAN is On! :)");
931
//    }
932
//    if(!err.epvf){
933
//        can_stat_report[can].bus_state = WARNING;
934
//        CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
935
//        CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
936
//        if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] Leaves Passive.");
937
//    }
938
//    if(!err.ewgf){
939
//        can_stat_report[can].bus_state = WARNING;
940
//        CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, ENABLE);
941
//        CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
942
//        CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
943
//        if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] Leaves Warning.");
944
//    }
945
//
946
//    can_stat_report[can].bus_curr_err = err;
947
//    CAN_ITConfig(MIOS32_CAN1, CAN_IT_EWG, ENABLE);
948
//    CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, ENABLE);
949
//    CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, ENABLE);
950
//    CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, ENABLE);
951
//    can_stat_report[can].bus_state = BUS_OK;
952
//    if(can_verbose)MIOS32_MIDI_SendDebugMessage("[MIOS32_CAN_BusErrorCheck] Bus OK.");
953
//  }
954
  //if(err.lec != 0)can_stat_report[can].bus_last_err = err;
955
  return (s32)can_stat_report[can].bus_state ;
956
#endif
957
}
958
 
959
/////////////////////////////////////////////////////////////////////////////
960
//! transmit more than one byte
961
//! \param[in] CAN number (0..1)
962
//! \param[in] *buffer pointer to buffer to be sent
963
//! \param[in] len number of bytes to be sent
964
//! \return 0 if no error
965
//! \return -1 if CAN not available
966
//! \return -2 if buffer full or cannot get all requested bytes (retry)
967
//! \return -3 if CAN not supported by MIOS32_CAN_TxBufferPut Routine
968
//! \note Applications shouldn't call these functions directly, instead please use \ref MIOS32_COM or \ref MIOS32_MIDI layer functions
969
/////////////////////////////////////////////////////////////////////////////
970
s32 MIOS32_CAN_Transmit(u8 can, can_packet_t p, s16 block_time)
971
{
972
#if NUM_SUPPORTED_CANS == 0
973
  return -1; // no CAN available
974
#else
975
  if( can >= NUM_SUPPORTED_CANS )
976
    return -1; // CAN not available
977
 
978
  s8 mailbox = -2;
979
  CAN_TypeDef* CANx = NULL;
980
 
981
  //MIOS32_IRQ_Disable();
982
 
983
  if(!can)CANx = MIOS32_CAN1; else CANx = MIOS32_CAN2;
984
 
985
  // exit immediately if CAN bus errors (CAN doesn't send messages anymore)
986
  //if( MIOS32_CAN_BusErrorCheck(can) < 0 )
987
    //return -3; // bus error
988
 
989
 
990
  do {
991
    if(block_time>=1)block_time--;
992
 
993
    // select an empty transmit mailbox
994
    if( CANx->TSR & CAN_TSR_TME0)mailbox = 0;
995
    else if( CANx->TSR & CAN_TSR_TME1)mailbox = 1;
996
    else if( CANx->TSR & CAN_TSR_TME2)mailbox = 2;
997
 
998
  } while (mailbox == -2 && block_time);
999
 
1000
  // exit on busy mailboxes and time out
1001
  if(mailbox == -2)return -2;
1002
 
1003
  p.id.txrq = 1;
1004
  CANx->sTxMailBox[mailbox].TDTR = p.ctrl.ALL;
1005
  CANx->sTxMailBox[mailbox].TDLR = p.data.data_l;
1006
  CANx->sTxMailBox[mailbox].TDHR = p.data.data_h;
1007
  CANx->sTxMailBox[mailbox].TIR = p.id.ALL;
1008
  // for CAN_Report
1009
  can_stat_report[can].tx_packets_ctr++;
1010
 
1011
  //DEBUG_MSG("[MIOS32_CAN_Transmit] mailbox:%d",mailbox);
1012
 
1013
  return 0; // no error
1014
#endif
1015
}
1016
 
1017
/////////////////////////////////////////////////////////////////////////////
1018
// Interrupt handler for first CAN
1019
// always in this order TX, RX0, RX1, don't change it!
1020
/////////////////////////////////////////////////////////////////////////////
1021
#if NUM_SUPPORTED_CANS >= 1
1022
MIOS32_CAN1_TX_IRQHANDLER_FUNC
1023
{
1024
  //if( MIOS32_CAN1->IER & CAN_IT_TME ) { // check if TME enabled
1025
    while(CAN_GetITStatus(MIOS32_CAN1, CAN_IT_TME)){
1026
      if(MIOS32_CAN_TxBufferUsed(0) >= 1){
1027
        u8 mailbox = -1;
1028
        if( MIOS32_CAN1->TSR & CAN_TSR_TME0)mailbox = 0;
1029
        else if( MIOS32_CAN1->TSR & CAN_TSR_TME1)mailbox = 1;
1030
        else if( MIOS32_CAN1->TSR & CAN_TSR_TME2)mailbox = 2;
1031
        can_packet_t p;
1032
        MIOS32_CAN_TxBufferGet(0, &p);
1033
        p.id.txrq = 1; //TX Req flag, this reset RQCPx
1034
        MIOS32_CAN1->sTxMailBox[mailbox].TDTR = p.ctrl.ALL;
1035
        MIOS32_CAN1->sTxMailBox[mailbox].TDLR = p.data.data_l;
1036
        MIOS32_CAN1->sTxMailBox[mailbox].TDHR = p.data.data_h;
1037
        MIOS32_CAN1->sTxMailBox[mailbox].TIR = p.id.ALL;
1038
      }else{
1039
        // nothing to send anymore we reset all RQCPx flags
1040
        MIOS32_CAN1->TSR |= CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2;
1041
        // disable TME interrupt
1042
        MIOS32_CAN1->IER &=~CAN_IT_TME;
1043
      }
1044
    }
1045
    // I don't knoow why
1046
    //MIOS32_CAN1->TSR |= (CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);
1047
}
1048
MIOS32_CAN1_RX0_IRQHANDLER_FUNC
1049
{
1050
 
1051
  while(MIOS32_CAN1->RF0R & CAN_RF0R_FMP0){     // FMP0 contains number of messages
1052
    // get EID, MSG and DLC
1053
    can_packet_t p;
1054
    p.id.ALL = MIOS32_CAN1->sFIFOMailBox[0].RIR;
1055
    p.ctrl.ALL = MIOS32_CAN1->sFIFOMailBox[0].RDTR;
1056
    p.data.data_l = MIOS32_CAN1->sFIFOMailBox[0].RDLR;
1057
    p.data.data_h = MIOS32_CAN1->sFIFOMailBox[0].RDHR;
1058
    can_stat_report[0].rx_packets_ctr++;
1059
 
1060
    s32 status = 0;
1061
//    if((status = MIOS32_CAN_IsAssignedToMIDI(0))){
1062
//      switch(p.id.event){
1063
//        case 0x78 ... 0x7f:  // Realtime
1064
//          // no data, we forward (event +0x80)
1065
//          status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, 0x80 + p.id.event);
1066
//          break;
1067
//        case 0x80 ... 0xe7:  // Channel Voice messages
1068
//          // Source and destination are transmited first. We just foward MIDI event bytes
1069
//          for( i=2; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1070
//          break;
1071
//        case 0xf0:  // SysEx messages
1072
//          // Here we forward all data bytes
1073
//          for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1074
//          break;
1075
//        case 0xf1 ... 0xf7:  // System Common messages
1076
//          // depends on DLC
1077
//          if(!p.ctrl.dlc)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.id.event);
1078
//          else for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1079
//          break;
1080
//        case 0xfe:  // Node active Sensing ;) 
1081
//          // Here we forward all data bytes
1082
//          for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1083
//          break;
1084
//        case 0xf8 ... 0xfd:  // Node System Exclusive and Common messages
1085
//          // toDo: foward to Node System Receive
1086
//          break;
1087
//        case 0xff:  // Node System Exclusive and Common messages
1088
//          // toDo: foward to Node System Receive
1089
//          break;
1090
//        default:
1091
//          break;
1092
//      }
1093
//    }
1094
//    if( status == 0 ){
1095
      if((status = MIOS32_CAN_RxBufferPut(0, p)) < 0 ){
1096
        can_stat_report[0].rx_last_buff_err = status;
1097
        can_stat_report[0].rx_buff_err_ctr = rx_buffer_size[0];
1098
      }
1099
//    }
1100
    // release FIFO
1101
    MIOS32_CAN1->RF0R |= CAN_RF0R_RFOM0; // set RFOM1 flag
1102
  }
1103
}
1104
 
1105
MIOS32_CAN1_RX1_IRQHANDLER_FUNC
1106
{
1107
 
1108
  while(MIOS32_CAN1->RF1R & CAN_RF1R_FMP1){     // FMP1 contains number of messages
1109
    // get EID, MSG and DLC
1110
    can_packet_t p;
1111
    p.id.ALL = MIOS32_CAN1->sFIFOMailBox[1].RIR;
1112
    p.ctrl.ALL = MIOS32_CAN1->sFIFOMailBox[1].RDTR;
1113
    p.data.data_l = MIOS32_CAN1->sFIFOMailBox[1].RDLR;
1114
    p.data.data_h = MIOS32_CAN1->sFIFOMailBox[1].RDHR;
1115
    can_stat_report[0].rx_packets_ctr++;
1116
 
1117
    s32 status = 0;
1118
//    if((status = MIOS32_CAN_IsAssignedToMIDI(0))){
1119
//      switch(p.id.event){
1120
//        case 0x78 ... 0x7f:  // Realtime
1121
//          // no data, we forward (event +0x80)
1122
//          status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, 0x80 + p.id.event);
1123
//          break;
1124
//        case 0x80 ... 0xe7:  // Channel Voice messages
1125
//          // Source and destination are transmited first. We just foward MIDI event bytes
1126
//          for( i=2; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1127
//          break;
1128
//        case 0xf0:  // SysEx messages
1129
//          // Here we foward all data bytes
1130
//          for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1131
//          break;
1132
//        case 0xf1 ... 0xf7:  // System Common messages
1133
//          if(!p.ctrl.dlc)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.id.event);
1134
//          else for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0, p.data.bytes[i]);
1135
//          break;
1136
//        case 0xf8 ... 0xff:  // Node System Exclusive and Common messages
1137
//          // toDo: foward to Node System Receive
1138
//          break;
1139
//        default:
1140
//          break;
1141
//      }
1142
//    }
1143
//    if( status == 0 ){
1144
      if((status = MIOS32_CAN_RxBufferPut(0, p)) < 0 ){
1145
        can_stat_report[0].rx_last_buff_err = status;
1146
        can_stat_report[0].rx_buff_err_ctr = rx_buffer_size[0];
1147
        can_stat_report[0].rx_packets_err++;
1148
      }
1149
//    }
1150
    // release FIFO
1151
    MIOS32_CAN1->RF1R |= CAN_RF1R_RFOM1; // set RFOM1 flag
1152
  }
1153
}
1154
 
1155
#if 1 // Here i tried to add a software fifo and using TME interrupt
1156
MIOS32_CAN1_ER_IRQHANDLER_FUNC
1157
{
1158
 
1159
  if( CAN_GetITStatus(MIOS32_CAN1, CAN_IT_ERR) ) { // General Err interrupt is enabled
1160
 
1161
    if( (can_stat_report[0].bus_last_err.ALL & 7) != (MIOS32_CAN1->ESR & 7) ){
1162
      //can_stat_err_t err = MIOS32_CAN1->ESR;
1163
      can_stat_report[0].bus_last_err.ALL = MIOS32_CAN1->ESR;
1164
      //if(can_verbose)MIOS32_MIDI_SendDebugMessage("0x%0x", can_stat_report[0].bus_last_err.ALL & 7);
1165
 
1166
      if(can_stat_report[0].bus_last_err.ewgf){
1167
        //can_stat_report[0].bus_state = WARNING;
1168
        CAN_ITConfig(MIOS32_CAN1, CAN_IT_EWG, DISABLE);
1169
        //MIOS32_CAN_BusErrorCheck(0);
1170
      }
1171
      if(can_stat_report[0].bus_last_err.epvf){
1172
        // definively stop the interrupt
1173
        //can_stat_report[0].bus_state = PASSIVE;
1174
        //CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, DISABLE);
1175
        CAN_ITConfig(MIOS32_CAN1, CAN_IT_EPV, DISABLE);
1176
        //MIOS32_CAN_BusErrorCheck(0);
1177
      }
1178
      if(can_stat_report[0].bus_last_err.boff){
1179
        // definively stop the interrupt
1180
        //can_stat_report[0].bus_state = BUS_OFF;
1181
        CAN_ITConfig(MIOS32_CAN1, CAN_IT_ERR, DISABLE);
1182
        CAN_ITConfig(MIOS32_CAN1, CAN_IT_BOF, DISABLE);
1183
        //MIOS32_CAN_BusErrorCheck(0);
1184
      }
1185
    }
1186
    CAN_ClearITPendingBit(MIOS32_CAN1, CAN_IT_ERR);
1187
 
1188
  }
1189
}
1190
#endif
1191
 
1192
#endif
1193
 
1194
 
1195
/////////////////////////////////////////////////////////////////////////////
1196
// Interrupt handler for second CAN
1197
/////////////////////////////////////////////////////////////////////////////
1198
#if NUM_SUPPORTED_CANS >= 2
1199
#if 0
1200
MIOS32_CAN2_TX_IRQHANDLER_FUNC
1201
{
1202
  //if( MIOS32_CAN1->IER & CAN_IT_TME ) { // check if TME enabled
1203
  while(CAN_GetITStatus(MIOS32_CAN2, CAN_IT_TME)){
1204
    if(MIOS32_CAN_TxBufferUsed(1) >= 1){
1205
      u8 mailbox = -1;
1206
      if( MIOS32_CAN2->TSR & CAN_TSR_TME0)mailbox = 0;
1207
      else if( MIOS32_CAN2->TSR & CAN_TSR_TME1)mailbox = 1;
1208
      else if( MIOS32_CAN2->TSR & CAN_TSR_TME2)mailbox = 2;
1209
      can_packet_t p;
1210
      MIOS32_CAN_TxBufferGet(1, &p);
1211
      p.id.txrq = 1; //TX Req flag, this reset RQCPx
1212
      MIOS32_CAN2->sTxMailBox[mailbox].TDTR = p.ctrl.ALL;
1213
      MIOS32_CAN2->sTxMailBox[mailbox].TDLR = p.data.data_l;
1214
      MIOS32_CAN2->sTxMailBox[mailbox].TDHR = p.data.data_h;
1215
      MIOS32_CAN2->sTxMailBox[mailbox].TIR = p.id.ALL;
1216
    }else{
1217
      // nothing to send anymore we reset all RQCPx flags
1218
      MIOS32_CAN2->TSR |= CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2;
1219
      // disable TME interrupt
1220
      MIOS32_CAN2->IER &=~CAN_IT_TME;
1221
    }
1222
  }
1223
  // I don't knoow why
1224
  MIOS32_CAN2->TSR |= (CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);
1225
}
1226
#endif
1227
MIOS32_CAN2_RX0_IRQHANDLER_FUNC
1228
{
1229
  while(MIOS32_CAN2->RF0R & CAN_RF0R_FMP0){     // FMP0 contains number of messages
1230
    // get EID, MSG and DLC
1231
    can_packet_t p;
1232
    p.id.ALL = MIOS32_CAN2->sFIFOMailBox[0].RIR;
1233
    p.ctrl.ALL = MIOS32_CAN2->sFIFOMailBox[0].RDTR;
1234
    p.data.data_l = MIOS32_CAN2->sFIFOMailBox[0].RDLR;
1235
    p.data.data_h = MIOS32_CAN2->sFIFOMailBox[0].RDHR;
1236
 
1237
    u8 i;
1238
    s32 status = 0;
1239
 
1240
    if(MIOS32_CAN_RxBufferPut(1, p) < 0 ){
1241
      // here we could add some error handling
1242
    }
1243
    // release FIFO
1244
    MIOS32_CAN2->RF0R |= CAN_RF0R_RFOM0; // set RFOM1 flag
1245
  }
1246
}
1247
 
1248
MIOS32_CAN2_RX1_IRQHANDLER_FUNC
1249
{
1250
  while(MIOS32_CAN2->RF1R & CAN_RF1R_FMP1 ){     // FMP1 contains number of messages
1251
    // get EID, MSG and DLC
1252
    can_packet_t p;
1253
    p.id.ALL = MIOS32_CAN2->sFIFOMailBox[1].RIR;
1254
    p.ctrl.ALL = MIOS32_CAN2->sFIFOMailBox[1].RDTR;
1255
    p.data.data_l = MIOS32_CAN2->sFIFOMailBox[1].RDLR;
1256
    p.data.data_h = MIOS32_CAN2->sFIFOMailBox[1].RDHR;
1257
 
1258
    u8 i;
1259
    s32 status = 0;
1260
    if((status = MIOS32_CAN_IsAssignedToMIDI(1))){
1261
      switch(p.id.event){
1262
        case 0x78 ... 0x7f:  // Realtime
1263
          // no data, we forward (event +0x80)
1264
          status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, 0x80 + p.id.event);
1265
          break;
1266
        case 0x80 ... 0xe7:  // Channel Voice messages
1267
          // Source and destination are transmited first. We just foward MIDI event bytes
1268
          for( i=2; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.data.bytes[i]);
1269
          break;
1270
        case 0xf0:  // SysEx messages
1271
          // Here we foward all data bytes
1272
          for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.data.bytes[i]);
1273
          break;
1274
        case 0xf1 ... 0xf7:  // System Common messages
1275
          if(!p.ctrl.dlc)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.id.event);
1276
          else for( i=0; i< p.ctrl.dlc; i++)status = MIOS32_MIDI_SendByteToRxCallback(MCAN0+16, p.data.bytes[i]);
1277
          break;
1278
        case 0xf8 ... 0xff:  // Node System Exclusive and Common messages
1279
          // toDo: foward to Node System Receive
1280
          break;
1281
        default:
1282
          break;
1283
      }
1284
    }
1285
    if( status == 0 ){
1286
      if(MIOS32_CAN_RxBufferPut(1, p) < 0 ){
1287
        // here we could add some error handling
1288
      }
1289
    }
1290
    // release FIFO
1291
    MIOS32_CAN2->RF1R |= CAN_RF1R_RFOM1; // set RFOM1 flag
1292
  }
1293
}
1294
 
1295
#endif
1296
 
1297
 
1298
/////////////////////////////////////////////////////////////////////////////
1299
//
1300
/////////////////////////////////////////////////////////////////////////////
1301
s32 MIOS32_CAN_Hlp_ErrorVerbose(CAN_TypeDef* CANx)
1302
{
1303
#if NUM_SUPPORTED_CANS == 0
1304
  return -1; // no CAN available
1305
#else
1306
 
1307
 
1308
  return 0; // no error
1309
#endif
1310
}
1311
 
1312
 
1313
/////////////////////////////////////////////////////////////////////////////
1314
//
1315
/////////////////////////////////////////////////////////////////////////////
1316
s32 MIOS32_CAN_ReportLastErr(u8 can, can_stat_err_t* err)
1317
{
1318
#if NUM_SUPPORTED_CANS == 0
1319
  return -1; // no CAN available
1320
#else
1321
  *err= can_stat_report[can].bus_last_err;
1322
  return 0; // no error
1323
#endif
1324
}
1325
 
1326
/////////////////////////////////////////////////////////////////////////////
1327
//
1328
/////////////////////////////////////////////////////////////////////////////
1329
s32 MIOS32_CAN_ReportGetCurr(u8 can, can_stat_report_t* report)
1330
{
1331
#if NUM_SUPPORTED_CANS == 0
1332
  return -1; // no CAN available
1333
#else
1334
  CAN_TypeDef* CANx = NULL;
1335
  if(!can)CANx = MIOS32_CAN1;else CANx = MIOS32_CAN2;
1336
 
1337
  can_stat_report[can].bus_curr_err.ALL = CANx->ESR;
1338
  *report = can_stat_report[can];
1339
 
1340
  return 0; // no error
1341
#endif
1342
}
1343
 
1344
/////////////////////////////////////////////////////////////////////////////
1345
//
1346
/////////////////////////////////////////////////////////////////////////////
1347
s32 MIOS32_CAN_ReportReset(u8 can)
1348
{
1349
#if NUM_SUPPORTED_CANS == 0
1350
  return -1; // no CAN available
1351
#else
1352
 
1353
  can_stat_report[can].tx_packets_ctr = 0;
1354
  can_stat_report[can].rx_packets_err = 0;
1355
  can_stat_report[can].rx_last_buff_err = 0;
1356
  can_stat_report[can].rx_buff_err_ctr = 0;
1357
  can_stat_report[can].rx_packets_ctr = 0;
1358
 
1359
  return 0; // no error
1360
#endif
1361
}
1362
 
1363
 
1364
#endif /* MIOS32_USE_CAN */