Subversion Repositories svn.mios32

Rev

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