Subversion Repositories svn.mios32

Rev

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