mirror of https://github.com/ARMmbed/mbed-os.git
1046 lines
31 KiB
C
1046 lines
31 KiB
C
/* mbed Microcontroller Library
|
||
* Copyright (c) 2006-2013 ARM Limited
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
#include <string.h>
|
||
#include "mbed_assert.h"
|
||
#include "can_api.h"
|
||
#include "RZ_A1_Init.h"
|
||
#include "cmsis.h"
|
||
#include "PeripheralPins.h"
|
||
#include "iodefine.h"
|
||
#include "r_typedefs.h"
|
||
#include "mbed_drv_cfg.h"
|
||
|
||
#if defined(TARGET_RZA1H)
|
||
#define CAN_NUM 5
|
||
#else
|
||
#define CAN_NUM 2
|
||
#endif
|
||
#define CAN_SND_RCV 2
|
||
#define IRQ_NUM 8
|
||
|
||
static void can_rec_irq(uint32_t ch);
|
||
static void can_trx_irq(uint32_t ch);
|
||
static void can_err_irq(uint32_t ch, CanIrqType type);
|
||
static void can0_rec_irq(void);
|
||
static void can0_trx_irq(void);
|
||
static void can0_err_warning_irq(void);
|
||
static void can0_overrun_irq(void);
|
||
static void can0_passive_irq(void);
|
||
static void can0_arb_lost_irq(void);
|
||
static void can0_bus_err_irq(void);
|
||
static void can1_rec_irq(void);
|
||
static void can1_trx_irq(void);
|
||
static void can1_err_warning_irq(void);
|
||
static void can1_overrun_irq(void);
|
||
static void can1_passive_irq(void);
|
||
static void can1_arb_lost_irq(void);
|
||
static void can1_bus_err_irq(void);
|
||
#if defined(TARGET_RZA1H)
|
||
static void can2_rec_irq(void);
|
||
static void can2_trx_irq(void);
|
||
static void can2_err_warning_irq(void);
|
||
static void can2_overrun_irq(void);
|
||
static void can2_passive_irq(void);
|
||
static void can2_arb_lost_irq(void);
|
||
static void can2_bus_err_irq(void);
|
||
static void can3_rec_irq(void);
|
||
static void can3_trx_irq(void);
|
||
static void can3_err_warning_irq(void);
|
||
static void can3_overrun_irq(void);
|
||
static void can3_passive_irq(void);
|
||
static void can3_arb_lost_irq(void);
|
||
static void can3_bus_err_irq(void);
|
||
static void can4_rec_irq(void);
|
||
static void can4_trx_irq(void);
|
||
static void can4_err_warning_irq(void);
|
||
static void can4_overrun_irq(void);
|
||
static void can4_passive_irq(void);
|
||
static void can4_arb_lost_irq(void);
|
||
static void can4_bus_err_irq(void);
|
||
#endif
|
||
|
||
static void can_reset_reg(can_t *obj);
|
||
static void can_reset_recv_rule(can_t *obj);
|
||
static void can_reset_buffer(can_t *obj);
|
||
static void can_reconfigure_channel(void);
|
||
static void can_set_frequency(can_t *obj, int f);
|
||
static void can_set_global_mode(int mode);
|
||
static void can_set_channel_mode(uint32_t ch, int mode);
|
||
|
||
typedef enum {
|
||
CAN_SEND = 0,
|
||
CAN_RECV
|
||
} CANfunc;
|
||
|
||
typedef enum {
|
||
GL_OPE = 0,
|
||
GL_RESET,
|
||
GL_TEST
|
||
} Globalmode;
|
||
|
||
typedef enum {
|
||
CH_COMM = 0,
|
||
CH_RESET,
|
||
CH_HOLD
|
||
} Channelmode;
|
||
|
||
typedef struct {
|
||
IRQn_Type int_num; /* Interrupt number */
|
||
IRQHandler handler; /* Interrupt handler */
|
||
} can_info_int_t;
|
||
|
||
static can_irq_handler irq_handler;
|
||
static uint32_t can_irq_id[CAN_NUM];
|
||
static int can_initialized[CAN_NUM] = {0};
|
||
|
||
|
||
static __IO uint32_t *CTR_MATCH[] = {
|
||
&RSCAN0C0CTR,
|
||
&RSCAN0C1CTR,
|
||
#if defined(TARGET_RZA1H)
|
||
&RSCAN0C2CTR,
|
||
&RSCAN0C3CTR,
|
||
&RSCAN0C4CTR,
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFG_MATCH[] = {
|
||
&RSCAN0C0CFG,
|
||
&RSCAN0C1CFG,
|
||
#if defined(TARGET_RZA1H)
|
||
&RSCAN0C2CFG,
|
||
&RSCAN0C3CFG,
|
||
&RSCAN0C4CFG,
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *RFCC_MATCH[] = {
|
||
&RSCAN0RFCC0,
|
||
&RSCAN0RFCC1,
|
||
&RSCAN0RFCC2,
|
||
&RSCAN0RFCC3,
|
||
&RSCAN0RFCC4,
|
||
&RSCAN0RFCC5,
|
||
&RSCAN0RFCC6,
|
||
&RSCAN0RFCC7
|
||
};
|
||
|
||
static __IO uint32_t *TXQCC_MATCH[] = {
|
||
&RSCAN0TXQCC0,
|
||
&RSCAN0TXQCC1,
|
||
#if defined(TARGET_RZA1H)
|
||
&RSCAN0TXQCC2,
|
||
&RSCAN0TXQCC3,
|
||
&RSCAN0TXQCC4,
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *THLCC_MATCH[] = {
|
||
&RSCAN0THLCC0,
|
||
&RSCAN0THLCC1,
|
||
#if defined(TARGET_RZA1H)
|
||
&RSCAN0THLCC2,
|
||
&RSCAN0THLCC3,
|
||
&RSCAN0THLCC4,
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *STS_MATCH[] = {
|
||
&RSCAN0C0STS,
|
||
&RSCAN0C1STS,
|
||
#if defined(TARGET_RZA1H)
|
||
&RSCAN0C2STS,
|
||
&RSCAN0C3STS,
|
||
&RSCAN0C4STS,
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *ERFL_MATCH[] = {
|
||
&RSCAN0C0ERFL,
|
||
&RSCAN0C1ERFL,
|
||
#if defined(TARGET_RZA1H)
|
||
&RSCAN0C2ERFL,
|
||
&RSCAN0C3ERFL,
|
||
&RSCAN0C4ERFL,
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFCC_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFCC0 , &RSCAN0CFCC1 },
|
||
{ &RSCAN0CFCC3 , &RSCAN0CFCC4 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFCC6 , &RSCAN0CFCC7 },
|
||
{ &RSCAN0CFCC9 , &RSCAN0CFCC10 },
|
||
{ &RSCAN0CFCC12, &RSCAN0CFCC13 },
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFSTS_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFSTS0 , &RSCAN0CFSTS1 },
|
||
{ &RSCAN0CFSTS3 , &RSCAN0CFSTS4 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFSTS6 , &RSCAN0CFSTS7 },
|
||
{ &RSCAN0CFSTS9 , &RSCAN0CFSTS10 },
|
||
{ &RSCAN0CFSTS12, &RSCAN0CFSTS13 },
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFPCTR_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFPCTR0 , &RSCAN0CFPCTR1 },
|
||
{ &RSCAN0CFPCTR3 , &RSCAN0CFPCTR4 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFPCTR6 , &RSCAN0CFPCTR7 },
|
||
{ &RSCAN0CFPCTR9 , &RSCAN0CFPCTR10 },
|
||
{ &RSCAN0CFPCTR12, &RSCAN0CFPCTR13 },
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFID_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFID0 , &RSCAN0CFID1 },
|
||
{ &RSCAN0CFID3 , &RSCAN0CFID4 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFID6 , &RSCAN0CFID7 },
|
||
{ &RSCAN0CFID9 , &RSCAN0CFID10 },
|
||
{ &RSCAN0CFID12, &RSCAN0CFID13 },
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFPTR_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFPTR0 , &RSCAN0CFPTR1 },
|
||
{ &RSCAN0CFPTR3 , &RSCAN0CFPTR4 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFPTR6 , &RSCAN0CFPTR7 },
|
||
{ &RSCAN0CFPTR9 , &RSCAN0CFPTR10 },
|
||
{ &RSCAN0CFPTR12, &RSCAN0CFPTR13 }
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFDF0_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFDF00 , &RSCAN0CFDF01 },
|
||
{ &RSCAN0CFDF03 , &RSCAN0CFDF04 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFDF06 , &RSCAN0CFDF07 },
|
||
{ &RSCAN0CFDF09 , &RSCAN0CFDF010 },
|
||
{ &RSCAN0CFDF012, &RSCAN0CFDF013 },
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *CFDF1_TBL[CAN_NUM][CAN_SND_RCV] = {
|
||
{ &RSCAN0CFDF10 , &RSCAN0CFDF11 },
|
||
{ &RSCAN0CFDF13 , &RSCAN0CFDF14 },
|
||
#if defined(TARGET_RZA1H)
|
||
{ &RSCAN0CFDF16 , &RSCAN0CFDF17 },
|
||
{ &RSCAN0CFDF19 , &RSCAN0CFDF110 },
|
||
{ &RSCAN0CFDF112, &RSCAN0CFDF113 },
|
||
#endif
|
||
};
|
||
|
||
static const can_info_int_t can_int_info[CAN_NUM][IRQ_NUM] =
|
||
{
|
||
{ /* ch0 */
|
||
{ INTRCAN0REC_IRQn, can0_rec_irq }, /* RxIrq */
|
||
{ INTRCAN0TRX_IRQn, can0_trx_irq }, /* TxIrq */
|
||
{ INTRCAN0ERR_IRQn, can0_err_warning_irq }, /* EwIrq */
|
||
{ INTRCAN0ERR_IRQn, can0_overrun_irq }, /* DoIrq */
|
||
{ INTRCAN0ERR_IRQn, NULL }, /* WuIrq(not supported) */
|
||
{ INTRCAN0ERR_IRQn, can0_passive_irq }, /* EpIrq */
|
||
{ INTRCAN0ERR_IRQn, can0_arb_lost_irq }, /* AlIrq */
|
||
{ INTRCAN0ERR_IRQn, can0_bus_err_irq } /* BeIrq */
|
||
},
|
||
{ /* ch1 */
|
||
{ INTRCAN1REC_IRQn, can1_rec_irq }, /* RxIrq */
|
||
{ INTRCAN1TRX_IRQn, can1_trx_irq }, /* TxIrq */
|
||
{ INTRCAN1ERR_IRQn, can1_err_warning_irq }, /* EwIrq */
|
||
{ INTRCAN1ERR_IRQn, can1_overrun_irq }, /* DoIrq */
|
||
{ INTRCAN1ERR_IRQn, NULL }, /* WuIrq(not supported) */
|
||
{ INTRCAN1ERR_IRQn, can1_passive_irq }, /* EpIrq */
|
||
{ INTRCAN1ERR_IRQn, can1_arb_lost_irq }, /* AlIrq */
|
||
{ INTRCAN1ERR_IRQn, can1_bus_err_irq } /* BeIrq */
|
||
},
|
||
#if defined(TARGET_RZA1H)
|
||
{ /* ch2 */
|
||
{ INTRCAN2REC_IRQn, can2_rec_irq }, /* RxIrq */
|
||
{ INTRCAN2TRX_IRQn, can2_trx_irq }, /* TxIrq */
|
||
{ INTRCAN2ERR_IRQn, can2_err_warning_irq }, /* EwIrq */
|
||
{ INTRCAN2ERR_IRQn, can2_overrun_irq }, /* DoIrq */
|
||
{ INTRCAN2ERR_IRQn, NULL }, /* WuIrq(not supported) */
|
||
{ INTRCAN2ERR_IRQn, can2_passive_irq }, /* EpIrq */
|
||
{ INTRCAN2ERR_IRQn, can2_arb_lost_irq }, /* AlIrq */
|
||
{ INTRCAN2ERR_IRQn, can2_bus_err_irq } /* BeIrq */
|
||
},
|
||
{ /* ch3 */
|
||
{ INTRCAN3REC_IRQn, can3_rec_irq }, /* RxIrq */
|
||
{ INTRCAN3TRX_IRQn, can3_trx_irq }, /* TxIrq */
|
||
{ INTRCAN3ERR_IRQn, can3_err_warning_irq }, /* EwIrq */
|
||
{ INTRCAN3ERR_IRQn, can3_overrun_irq }, /* DoIrq */
|
||
{ INTRCAN3ERR_IRQn, NULL }, /* WuIrq(not supported) */
|
||
{ INTRCAN3ERR_IRQn, can3_passive_irq }, /* EpIrq */
|
||
{ INTRCAN3ERR_IRQn, can3_arb_lost_irq }, /* AlIrq */
|
||
{ INTRCAN3ERR_IRQn, can3_bus_err_irq } /* BeIrq */
|
||
},
|
||
{ /* ch4 */
|
||
{ INTRCAN4REC_IRQn, can4_rec_irq }, /* RxIrq */
|
||
{ INTRCAN4TRX_IRQn, can4_trx_irq }, /* TxIrq */
|
||
{ INTRCAN4ERR_IRQn, can4_err_warning_irq }, /* EwIrq */
|
||
{ INTRCAN4ERR_IRQn, can4_overrun_irq }, /* DoIrq */
|
||
{ INTRCAN4ERR_IRQn, NULL }, /* WuIrq(not supported) */
|
||
{ INTRCAN4ERR_IRQn, can4_passive_irq }, /* EpIrq */
|
||
{ INTRCAN4ERR_IRQn, can4_arb_lost_irq }, /* AlIrq */
|
||
{ INTRCAN4ERR_IRQn, can4_bus_err_irq } /* BeIrq */
|
||
},
|
||
#endif
|
||
};
|
||
|
||
static __IO uint32_t *dmy_gaflid = &RSCAN0GAFLID0;
|
||
static __IO uint32_t *dmy_gaflm = &RSCAN0GAFLM0;
|
||
static __IO uint32_t *dmy_gaflp0 = &RSCAN0GAFLP00;
|
||
static __IO uint32_t *dmy_gaflp1 = &RSCAN0GAFLP10;
|
||
|
||
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id) {
|
||
irq_handler = handler;
|
||
can_irq_id[obj->ch] = id;
|
||
}
|
||
|
||
void can_irq_free(can_t *obj) {
|
||
can_irq_id[obj->ch] = 0;
|
||
}
|
||
|
||
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable) {
|
||
__IO uint32_t *dmy_ctr;
|
||
|
||
/* Wake-up Irq is not supported */
|
||
if (type != IRQ_WAKEUP) {
|
||
if (enable) {
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
if (type == IRQ_ERROR) {
|
||
/* EWIE interrupts is enable */
|
||
*dmy_ctr |= 0x00000200;
|
||
} else if (type == IRQ_OVERRUN) {
|
||
/* OLIE interrupts is enable */
|
||
*dmy_ctr |= 0x00002000;
|
||
} else if (type == IRQ_PASSIVE) {
|
||
/* EPIE interrupts is enable */
|
||
*dmy_ctr |= 0x00000400;
|
||
} else if (type == IRQ_ARB) {
|
||
/* ALIE interrupts is enable */
|
||
*dmy_ctr |= 0x00008000;
|
||
} else if (type == IRQ_BUS) {
|
||
/* BEIE interrupts is enable */
|
||
*dmy_ctr |= 0x00000100;
|
||
}
|
||
InterruptHandlerRegister(can_int_info[obj->ch][type].int_num, can_int_info[obj->ch][type].handler);
|
||
GIC_SetPriority(can_int_info[obj->ch][type].int_num, 5);
|
||
GIC_SetConfiguration(can_int_info[obj->ch][type].int_num, 1);
|
||
GIC_EnableIRQ(can_int_info[obj->ch][type].int_num);
|
||
} else {
|
||
GIC_DisableIRQ(can_int_info[obj->ch][type].int_num);
|
||
}
|
||
}
|
||
}
|
||
|
||
static void can_rec_irq(uint32_t ch) {
|
||
__IO uint32_t *dmy_cfsts;
|
||
|
||
dmy_cfsts = CFSTS_TBL[ch][CAN_RECV];
|
||
*dmy_cfsts &= 0xFFFFFFF7; // Clear CFRXIF
|
||
|
||
irq_handler(can_irq_id[ch], IRQ_RX);
|
||
}
|
||
|
||
static void can_trx_irq(uint32_t ch) {
|
||
__IO uint32_t *dmy_cfsts;
|
||
|
||
dmy_cfsts = CFSTS_TBL[ch][CAN_SEND];
|
||
*dmy_cfsts &= 0xFFFFFFEF; // Clear CFTXIF
|
||
|
||
irq_handler(can_irq_id[ch], IRQ_TX);
|
||
}
|
||
|
||
static void can_err_irq(uint32_t ch, CanIrqType type) {
|
||
__IO uint32_t *dmy_erfl;
|
||
int val = 1;
|
||
|
||
dmy_erfl = ERFL_MATCH[ch];
|
||
switch (type) {
|
||
case IRQ_ERROR:
|
||
*dmy_erfl &= 0xFFFFFFFD; // Clear EWF
|
||
break;
|
||
case IRQ_OVERRUN:
|
||
*dmy_erfl &= 0xFFFFFFDF; // Clear OVLF
|
||
break;
|
||
case IRQ_PASSIVE:
|
||
*dmy_erfl &= 0xFFFFFFFB; // Clear EPF
|
||
break;
|
||
case IRQ_ARB:
|
||
*dmy_erfl &= 0xFFFFFF7F; // Clear ALF
|
||
break;
|
||
case IRQ_BUS:
|
||
*dmy_erfl &= 0xFFFF00FF; // Clear ADERR<52>AB0ERR<52>AB1ERR<52>ACERR<52>AAERR<52>AFERR<52>ASERR
|
||
*dmy_erfl &= 0xFFFFFFFE; // Clear BEF
|
||
break;
|
||
case IRQ_WAKEUP:
|
||
/* not supported */
|
||
/* fall through */
|
||
default:
|
||
val = 0;
|
||
break;
|
||
}
|
||
if (val == 1) {
|
||
irq_handler(can_irq_id[ch], type);
|
||
}
|
||
}
|
||
|
||
static void can0_rec_irq(void) {
|
||
can_rec_irq(CAN_0);
|
||
}
|
||
|
||
static void can0_trx_irq(void) {
|
||
can_trx_irq(CAN_0);
|
||
}
|
||
|
||
static void can0_err_warning_irq(void) {
|
||
can_err_irq(CAN_0, IRQ_ERROR);
|
||
}
|
||
|
||
static void can0_overrun_irq(void) {
|
||
can_err_irq(CAN_0, IRQ_OVERRUN);
|
||
}
|
||
|
||
static void can0_passive_irq(void) {
|
||
can_err_irq(CAN_0, IRQ_PASSIVE);
|
||
}
|
||
|
||
static void can0_arb_lost_irq(void) {
|
||
can_err_irq(CAN_0, IRQ_ARB);
|
||
}
|
||
|
||
static void can0_bus_err_irq(void) {
|
||
can_err_irq(CAN_0, IRQ_BUS);
|
||
}
|
||
|
||
static void can1_rec_irq(void) {
|
||
can_rec_irq(CAN_1);
|
||
}
|
||
|
||
static void can1_trx_irq(void) {
|
||
can_trx_irq(CAN_1);
|
||
}
|
||
|
||
static void can1_err_warning_irq(void) {
|
||
can_err_irq(CAN_1, IRQ_ERROR);
|
||
}
|
||
|
||
static void can1_overrun_irq(void) {
|
||
can_err_irq(CAN_1, IRQ_OVERRUN);
|
||
}
|
||
|
||
static void can1_passive_irq(void) {
|
||
can_err_irq(CAN_1, IRQ_PASSIVE);
|
||
}
|
||
|
||
static void can1_arb_lost_irq(void) {
|
||
can_err_irq(CAN_1, IRQ_ARB);
|
||
}
|
||
|
||
static void can1_bus_err_irq(void) {
|
||
can_err_irq(CAN_1, IRQ_BUS);
|
||
}
|
||
|
||
#if defined(TARGET_RZA1H)
|
||
static void can2_rec_irq(void) {
|
||
can_rec_irq(CAN_2);
|
||
}
|
||
|
||
static void can2_trx_irq(void) {
|
||
can_trx_irq(CAN_2);
|
||
}
|
||
|
||
static void can2_err_warning_irq(void) {
|
||
can_err_irq(CAN_2, IRQ_ERROR);
|
||
}
|
||
|
||
static void can2_overrun_irq(void) {
|
||
can_err_irq(CAN_2, IRQ_OVERRUN);
|
||
}
|
||
|
||
static void can2_passive_irq(void) {
|
||
can_err_irq(CAN_2, IRQ_PASSIVE);
|
||
}
|
||
|
||
static void can2_arb_lost_irq(void) {
|
||
can_err_irq(CAN_2, IRQ_ARB);
|
||
}
|
||
|
||
static void can2_bus_err_irq(void) {
|
||
can_err_irq(CAN_2, IRQ_BUS);
|
||
}
|
||
|
||
static void can3_rec_irq(void) {
|
||
can_rec_irq(CAN_3);
|
||
}
|
||
|
||
static void can3_trx_irq(void) {
|
||
can_trx_irq(CAN_3);
|
||
}
|
||
|
||
static void can3_err_warning_irq(void) {
|
||
can_err_irq(CAN_3, IRQ_ERROR);
|
||
}
|
||
|
||
static void can3_overrun_irq(void) {
|
||
can_err_irq(CAN_3, IRQ_OVERRUN);
|
||
}
|
||
|
||
static void can3_passive_irq(void) {
|
||
can_err_irq(CAN_3, IRQ_PASSIVE);
|
||
}
|
||
|
||
static void can3_arb_lost_irq(void) {
|
||
can_err_irq(CAN_3, IRQ_ARB);
|
||
}
|
||
|
||
static void can3_bus_err_irq(void) {
|
||
can_err_irq(CAN_3, IRQ_BUS);
|
||
}
|
||
|
||
static void can4_rec_irq(void) {
|
||
can_rec_irq(CAN_4);
|
||
}
|
||
|
||
static void can4_trx_irq(void) {
|
||
can_trx_irq(CAN_4);
|
||
}
|
||
|
||
static void can4_err_warning_irq(void) {
|
||
can_err_irq(CAN_4, IRQ_ERROR);
|
||
}
|
||
|
||
static void can4_overrun_irq(void) {
|
||
can_err_irq(CAN_4, IRQ_OVERRUN);
|
||
}
|
||
|
||
static void can4_passive_irq(void) {
|
||
can_err_irq(CAN_4, IRQ_PASSIVE);
|
||
}
|
||
|
||
static void can4_arb_lost_irq(void) {
|
||
can_err_irq(CAN_4, IRQ_ARB);
|
||
}
|
||
|
||
static void can4_bus_err_irq(void) {
|
||
can_err_irq(CAN_4, IRQ_BUS);
|
||
}
|
||
#endif
|
||
|
||
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz) {
|
||
__IO uint32_t *dmy_ctr;
|
||
|
||
/* determine the CAN to use */
|
||
uint32_t can_rx = pinmap_peripheral(rd, PinMap_CAN_RD);
|
||
uint32_t can_tx = pinmap_peripheral(td, PinMap_CAN_TD);
|
||
obj->ch = pinmap_merge(can_tx, can_rx);
|
||
MBED_ASSERT((int)obj->ch != NC);
|
||
|
||
/* enable CAN clock */
|
||
CPGSTBCR3 &= ~(CPG_STBCR3_BIT_MSTP32);
|
||
/* Has CAN RAM initialisation completed ? */
|
||
while ((RSCAN0GSTS & 0x08) == 0x08) {
|
||
__NOP();
|
||
}
|
||
/* clear Global Stop mode bit */
|
||
RSCAN0GCTR &= 0xFFFFFFFB;
|
||
/* clear Channel Stop mode bit */
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
*dmy_ctr &= 0xFFFFFFFB;
|
||
/* Enter global reset mode */
|
||
can_set_global_mode(GL_RESET);
|
||
/* Enter channel reset mode */
|
||
can_set_channel_mode(obj->ch, CH_RESET);
|
||
/* reset register */
|
||
can_reset_reg(obj);
|
||
|
||
can_initialized[obj->ch] = 1;
|
||
/* reconfigure channel which is already initialized */
|
||
can_reconfigure_channel();
|
||
|
||
/* pin out the can pins */
|
||
pinmap_pinout(rd, PinMap_CAN_RD);
|
||
pinmap_pinout(td, PinMap_CAN_TD);
|
||
|
||
/* set can frequency */
|
||
can_frequency(obj, hz);
|
||
}
|
||
|
||
void can_init(can_t *obj, PinName rd, PinName td) {
|
||
can_init_freq(obj, rd, td, 100000);
|
||
}
|
||
|
||
void can_free(can_t *obj) {
|
||
/* disable CAN clock */
|
||
CPGSTBCR3 |= CPG_STBCR3_BIT_MSTP32;
|
||
}
|
||
|
||
int can_frequency(can_t *obj, int f) {
|
||
__IO uint32_t *dmy_cfcc;
|
||
int retval = 0;
|
||
|
||
if (f <= 1000000) {
|
||
/* less than 1Mhz */
|
||
/* set Channel Reset mode */
|
||
can_set_channel_mode(obj->ch, CH_RESET);
|
||
can_set_frequency(obj, f);
|
||
/* set Channel Communication mode */
|
||
can_set_channel_mode(obj->ch, CH_COMM);
|
||
/* restore CFE bit since it is cleared */
|
||
/* Use send/receive FIFO buffer */
|
||
dmy_cfcc = CFCC_TBL[obj->ch][CAN_SEND];
|
||
*dmy_cfcc |= 0x01;
|
||
dmy_cfcc = CFCC_TBL[obj->ch][CAN_RECV];
|
||
*dmy_cfcc |= 0x01;
|
||
retval = 1;
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
|
||
void can_reset(can_t *obj) {
|
||
/* Enter global reset mode */
|
||
can_set_global_mode(GL_RESET);
|
||
/* Enter channel reset mode */
|
||
can_set_channel_mode(obj->ch, CH_RESET);
|
||
/* reset register */
|
||
can_reset_reg(obj);
|
||
/* reconfigure channel which is already initialized */
|
||
can_reconfigure_channel();
|
||
}
|
||
|
||
int can_write(can_t *obj, CAN_Message msg, int cc) {
|
||
__IO uint32_t *dmy_sts;
|
||
__IO uint32_t *dmy_cfsts;
|
||
__IO uint32_t *dmy_cfid;
|
||
__IO uint32_t *dmy_cfptr;
|
||
__IO uint32_t *dmy_cfdf0;
|
||
__IO uint32_t *dmy_cfdf1;
|
||
__IO uint32_t *dmy_cfpctr;
|
||
int retval = 0;
|
||
|
||
/* Wait to become channel communication mode */
|
||
dmy_sts = STS_MATCH[obj->ch];
|
||
while ((*dmy_sts & 0x07) != 0) {
|
||
__NOP();
|
||
}
|
||
|
||
if (((msg.format == CANStandard) && (msg.id <= 0x07FF)) || ((msg.format == CANExtended) && (msg.id <= 0x1FFFFFFF))) {
|
||
/* send/receive FIFO buffer isn't full */
|
||
dmy_cfsts = CFSTS_TBL[obj->ch][CAN_SEND];
|
||
if ((*dmy_cfsts & 0x02) != 0x02) {
|
||
/* set format, frame type and send/receive FIFO buffer ID(b10-0 or b28-0) */
|
||
dmy_cfid = CFID_TBL[obj->ch][CAN_SEND];
|
||
*dmy_cfid = ((msg.format << 31) | (msg.type << 30));
|
||
if (msg.format == CANStandard) {
|
||
*dmy_cfid |= (msg.id & 0x07FF);
|
||
} else {
|
||
*dmy_cfid |= (msg.id & 0x1FFFFFFF);
|
||
}
|
||
/* set length */
|
||
dmy_cfptr = CFPTR_TBL[obj->ch][CAN_SEND];
|
||
*dmy_cfptr = msg.len << 28;
|
||
/* set data */
|
||
dmy_cfdf0 = CFDF0_TBL[obj->ch][CAN_SEND];
|
||
memcpy((void *)dmy_cfdf0, &msg.data[0], 4);
|
||
dmy_cfdf1 = CFDF1_TBL[obj->ch][CAN_SEND];
|
||
memcpy((void *)dmy_cfdf1, &msg.data[4], 4);
|
||
/* send request */
|
||
dmy_cfpctr = CFPCTR_TBL[obj->ch][CAN_SEND];
|
||
*dmy_cfpctr = 0xFF;
|
||
retval = 1;
|
||
}
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
|
||
int can_read(can_t *obj, CAN_Message *msg, int handle) {
|
||
__IO uint32_t *dmy_sts;
|
||
__IO uint32_t *dmy_cfsts;
|
||
__IO uint32_t *dmy_cfid;
|
||
__IO uint32_t *dmy_cfptr;
|
||
__IO uint32_t *dmy_cfdf0;
|
||
__IO uint32_t *dmy_cfdf1;
|
||
__IO uint32_t *dmy_cfpctr;
|
||
int retval = 0;
|
||
|
||
/* Wait to become channel communication mode */
|
||
dmy_sts = STS_MATCH[obj->ch];
|
||
while ((*dmy_sts & 0x07) != 0) {
|
||
__NOP();
|
||
}
|
||
|
||
/* send/receive FIFO buffer isn't empty */
|
||
dmy_cfsts = CFSTS_TBL[obj->ch][CAN_RECV];
|
||
while ((*dmy_cfsts & 0x01) != 0x01) {
|
||
/* get format, frame type and send/receive FIFO buffer ID(b10-0 or b28-0) */
|
||
dmy_cfid = CFID_TBL[obj->ch][CAN_RECV];
|
||
msg->format = (CANFormat)(*dmy_cfid >> 31);
|
||
msg->type = (CANType)((*dmy_cfid >> 30) & 0x1);
|
||
if (msg->format == CANStandard) {
|
||
msg->id = (*dmy_cfid & 0x07FF);
|
||
} else {
|
||
msg->id = (*dmy_cfid & 0x1FFFFFFF);
|
||
}
|
||
/* get length */
|
||
dmy_cfptr = CFPTR_TBL[obj->ch][CAN_RECV];
|
||
msg->len = (unsigned char)(*dmy_cfptr >> 28);
|
||
/* get data */
|
||
dmy_cfdf0 = CFDF0_TBL[obj->ch][CAN_RECV];
|
||
memcpy(&msg->data[0], (void *)dmy_cfdf0, 4);
|
||
dmy_cfdf1 = CFDF1_TBL[obj->ch][CAN_RECV];
|
||
memcpy(&msg->data[4], (void *)dmy_cfdf1, 4);
|
||
/* receive(next data) request */
|
||
dmy_cfpctr = CFPCTR_TBL[obj->ch][CAN_RECV];
|
||
*dmy_cfpctr = 0xFF;
|
||
retval = 1;
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
|
||
unsigned char can_rderror(can_t *obj) {
|
||
__IO uint32_t *dmy_sts;
|
||
|
||
dmy_sts = STS_MATCH[obj->ch];
|
||
return (unsigned char)((*dmy_sts >> 16) & 0xFF);
|
||
}
|
||
|
||
unsigned char can_tderror(can_t *obj) {
|
||
__IO uint32_t *dmy_sts;
|
||
|
||
dmy_sts = STS_MATCH[obj->ch];
|
||
return (unsigned char)((*dmy_sts >> 24) & 0xFF);
|
||
}
|
||
|
||
int can_mode(can_t *obj, CanMode mode) {
|
||
__IO uint32_t *dmy_ctr;
|
||
__IO uint32_t *dmy_sts;
|
||
__IO uint32_t *dmy_cfcc;
|
||
int ch_cnt;
|
||
can_t *tmp_obj;
|
||
tmp_obj = obj;
|
||
int retval = 1;
|
||
|
||
switch (mode) {
|
||
case MODE_RESET:
|
||
can_set_global_mode(GL_RESET);
|
||
can_set_channel_mode(obj->ch, CH_RESET);
|
||
for (ch_cnt = 0; ch_cnt < CAN_NUM; ch_cnt++) {
|
||
can_initialized[ch_cnt] = 0;
|
||
}
|
||
break;
|
||
case MODE_NORMAL:
|
||
can_set_global_mode(GL_OPE);
|
||
can_set_channel_mode(obj->ch, CH_COMM);
|
||
break;
|
||
case MODE_SILENT:
|
||
can_set_channel_mode(obj->ch, CH_HOLD);
|
||
/* set listen only mode, enable communication test mode */
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
*dmy_ctr = ((*dmy_ctr & 0x00FFFFFF) | 0x03000000);
|
||
can_set_channel_mode(obj->ch, CH_COMM);
|
||
break;
|
||
case MODE_TEST_LOCAL:
|
||
can_set_channel_mode(obj->ch, CH_HOLD);
|
||
/* set self test mode 0, enable communication test mode */
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
*dmy_ctr = ((*dmy_ctr & 0x00FFFFFF) | 0x05000000);
|
||
can_set_channel_mode(obj->ch, CH_COMM);
|
||
break;
|
||
case MODE_TEST_GLOBAL:
|
||
/* set the channel between the communication test on CAN_TEST_GLOBAL_CH and CAN_TEST_GLOBAL_CH+1 */
|
||
/* set Channel Hold mode */
|
||
for (tmp_obj->ch = CAN_TEST_GLOBAL_CH; tmp_obj->ch <= (CAN_TEST_GLOBAL_CH + 1); tmp_obj->ch++) {
|
||
dmy_sts = STS_MATCH[tmp_obj->ch];
|
||
if ((*dmy_sts & 0x04) == 0x04) {
|
||
/* Channel Stop mode */
|
||
/* clear Channel Stop mode bit */
|
||
dmy_ctr = CTR_MATCH[tmp_obj->ch];
|
||
*dmy_ctr &= 0xFFFFFFFB;
|
||
can_set_channel_mode(tmp_obj->ch, CH_RESET);
|
||
}
|
||
can_set_channel_mode(tmp_obj->ch, CH_HOLD);
|
||
}
|
||
can_set_global_mode(GL_TEST);
|
||
/* enable communication test between CAN_TEST_GLOBAL_CH and CAN_TEST_GLOBAL_CH+1 */
|
||
RSCAN0GTSTCFG = 0x06;
|
||
RSCAN0GTSTCTR = 0x01;
|
||
/* send and receive setting of channel1 and channel2 */
|
||
for (tmp_obj->ch = CAN_TEST_GLOBAL_CH; tmp_obj->ch <= (CAN_TEST_GLOBAL_CH + 1); tmp_obj->ch++) {
|
||
can_reset_buffer(tmp_obj);
|
||
/* set global interrrupt */
|
||
/* THLEIE, MEIE and DEIE interrupts are disable */
|
||
RSCAN0GCTR &= 0xFFFFF8FF;
|
||
/* BLIE, OLIE, BORIE and BOEIE interrupts are disable */
|
||
/* TAIE, ALIE, EPIE, EWIE and BEIE interrupts are enable */
|
||
dmy_ctr = CTR_MATCH[tmp_obj->ch];
|
||
*dmy_ctr &= 0x00018700;
|
||
can_set_global_mode(GL_OPE);
|
||
can_set_channel_mode(tmp_obj->ch, CH_COMM);
|
||
/* Use send/receive FIFO buffer */
|
||
dmy_cfcc = CFCC_TBL[tmp_obj->ch][CAN_SEND];
|
||
*dmy_cfcc |= 0x01;
|
||
dmy_cfcc = CFCC_TBL[tmp_obj->ch][CAN_RECV];
|
||
*dmy_cfcc |= 0x01;
|
||
}
|
||
break;
|
||
case MODE_TEST_SILENT:
|
||
/* not supported */
|
||
/* fall through */
|
||
default:
|
||
retval = 0;
|
||
break;
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
|
||
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
|
||
int retval = 0;
|
||
|
||
if ((format == CANStandard) || (format == CANExtended)) {
|
||
if (((format == CANStandard) && (id <= 0x07FF)) || ((format == CANExtended) && (id <= 0x1FFFFFFF))) {
|
||
/* set Global Reset mode and Channel Reset mode */
|
||
can_set_global_mode(GL_RESET);
|
||
can_set_channel_mode(obj->ch, CH_RESET);
|
||
/* enable receive rule table writing */
|
||
RSCAN0GAFLECTR = 0x00000100;
|
||
/* set the page number of receive rule table(page number = 0) */
|
||
RSCAN0GAFLECTR |= (obj->ch * 4);
|
||
/* set IDE format */
|
||
*dmy_gaflid = (format << 31);
|
||
if (format == CANExtended) {
|
||
/* set receive rule ID for bit28-0 */
|
||
*dmy_gaflid |= (id & 0x1FFFFFFF);
|
||
} else {
|
||
/* set receive rule ID for bit10-0 */
|
||
*dmy_gaflid |= (id & 0x07FF);
|
||
}
|
||
/* set ID mask bit */
|
||
*dmy_gaflm = (0xC0000000 | mask);
|
||
/* disable receive rule table writing */
|
||
RSCAN0GAFLECTR &= 0xFFFFFEFF;
|
||
/* reconfigure channel which is already initialized */
|
||
can_reconfigure_channel();
|
||
retval = 1;
|
||
}
|
||
}
|
||
|
||
return retval;
|
||
}
|
||
|
||
void can_monitor(can_t *obj, int silent) {
|
||
__IO uint32_t *dmy_ctr;
|
||
|
||
/* set Channel Hold mode */
|
||
can_set_channel_mode(obj->ch, CH_HOLD);
|
||
if (silent) {
|
||
/* set listen only mode, enable communication test mode */
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
*dmy_ctr = ((*dmy_ctr & 0x00FFFFFF) | 0x03000000);
|
||
can_set_channel_mode(obj->ch, CH_COMM);
|
||
} else {
|
||
/* set normal test mode, disable communication test mode */
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
*dmy_ctr &= 0x00FFFFFF;
|
||
/* reset register */
|
||
can_reset_reg(obj);
|
||
/* reconfigure channel which is already initialized */
|
||
can_reconfigure_channel();
|
||
}
|
||
}
|
||
|
||
static void can_reset_reg(can_t *obj) {
|
||
__IO uint32_t *dmy_ctr;
|
||
|
||
/* time stamp source uses peripheral clock (pclk(P1_phi)/2), CAN clock uses clkc(P1_phi/2), */
|
||
/* mirror off, DLC not transfer, DLC check permit, transmit buffer priority, clock source not divided */
|
||
RSCAN0GCFG = 0x00000003;
|
||
/* set default frequency at 100k */
|
||
can_set_frequency(obj, 100000);
|
||
/* set receive rule */
|
||
can_reset_recv_rule(obj);
|
||
/* set buffer */
|
||
can_reset_buffer(obj);
|
||
/* set global interrrupt */
|
||
/* THLEIE, MEIE and DEIE interrupts are disable */
|
||
RSCAN0GCTR &= 0xFFFFF8FF;
|
||
/* ALIE, BLIE, OLIE, BORIE, BOEIE, EPIE, EWIE and BEIE interrupts are disable */
|
||
dmy_ctr = CTR_MATCH[obj->ch];
|
||
*dmy_ctr &= 0xFFFF00FF;
|
||
}
|
||
|
||
static void can_reset_recv_rule(can_t *obj) {
|
||
/* number of receive rules of each chanel = 64 */
|
||
RSCAN0GAFLCFG0 = 0x40404040;
|
||
#if defined(TARGET_RZA1H)
|
||
RSCAN0GAFLCFG1 = 0x40000000;
|
||
#endif
|
||
/* enable receive rule table writing */
|
||
RSCAN0GAFLECTR = 0x00000100;
|
||
/* set the page number of receive rule table(ex: id ch = 1, page number = 4) */
|
||
RSCAN0GAFLECTR |= (obj->ch * 4);
|
||
/* set standard ID, data frame and receive rule ID */
|
||
*dmy_gaflid = 0x07FF;
|
||
/* IDE bit, RTR bit and ID bit(28-0) are not compared */
|
||
*dmy_gaflm = 0;
|
||
/* DLC check is 1 bytes, not use a receive buffer */
|
||
*dmy_gaflp0 = 0x10000000;
|
||
/* use a send/receive FIFO buffer(ex: if ch = 1, FIFO buffer number = 4 and bit = 12) */
|
||
*dmy_gaflp1 = (1 << ((obj->ch + 3) * 3));
|
||
/* disable receive rule table writing */
|
||
RSCAN0GAFLECTR &= 0xFFFFFEFF;
|
||
}
|
||
|
||
static void can_reset_buffer(can_t *obj) {
|
||
__IO uint32_t *dmy_rfcc;
|
||
__IO uint32_t *dmy_cfcc;
|
||
__IO uint32_t *dmy_txqcc;
|
||
__IO uint32_t *dmy_thlcc;
|
||
int cnt;
|
||
|
||
/* set linked send buffer number(ex: if ch = 1 and mode = send, buffer number = 16), interval timer is pclk/2 */
|
||
/* number of rows of send/receive FIFO buffer = 4 */
|
||
dmy_cfcc = CFCC_TBL[obj->ch][CAN_SEND];
|
||
*dmy_cfcc = 0x00011100; /* send/receive FIFO mode is send */
|
||
dmy_cfcc = CFCC_TBL[obj->ch][CAN_RECV];
|
||
*dmy_cfcc = 0x00001100; /* send/receive FIFO mode is receive */
|
||
/* receive buffer is not used */
|
||
RSCAN0RMNB = 0;
|
||
/* receive FIFO buffer is not used */
|
||
for (cnt = 0; cnt < 8; cnt++) {
|
||
dmy_rfcc = RFCC_MATCH[cnt];
|
||
*dmy_rfcc = 0;
|
||
}
|
||
/* send queue is not used */
|
||
dmy_txqcc = TXQCC_MATCH[obj->ch];
|
||
*dmy_txqcc = 0;
|
||
/* send history is not used */
|
||
dmy_thlcc = THLCC_MATCH[obj->ch];
|
||
*dmy_thlcc = 0;
|
||
|
||
/* CFTXIE and CFRXIE interrupts are enable */
|
||
dmy_cfcc = CFCC_TBL[obj->ch][CAN_SEND];
|
||
*dmy_cfcc |= 0x04;
|
||
dmy_cfcc = CFCC_TBL[obj->ch][CAN_RECV];
|
||
*dmy_cfcc |= 0x02;
|
||
/* TMIEp interrupt is disable */
|
||
RSCAN0TMIEC0 = 0x00000000;
|
||
#if defined(TARGET_RZA1H)
|
||
RSCAN0TMIEC1 = 0x00000000;
|
||
RSCAN0TMIEC2 = 0x00000000;
|
||
#endif
|
||
}
|
||
|
||
static void can_reconfigure_channel(void) {
|
||
__IO uint32_t *dmy_cfcc;
|
||
int ch_cnt;
|
||
|
||
for (ch_cnt = 0; ch_cnt < CAN_NUM; ch_cnt++) {
|
||
if (can_initialized[ch_cnt] == 1) {
|
||
/* set Global Operation mode and Channel Communication mode */
|
||
can_set_global_mode(GL_OPE);
|
||
can_set_channel_mode(ch_cnt, CH_COMM);
|
||
/* Use send/receive FIFO buffer */
|
||
dmy_cfcc = CFCC_TBL[ch_cnt][CAN_SEND];
|
||
*dmy_cfcc |= 0x01;
|
||
dmy_cfcc = CFCC_TBL[ch_cnt][CAN_RECV];
|
||
*dmy_cfcc |= 0x01;
|
||
}
|
||
}
|
||
}
|
||
|
||
static void can_set_frequency(can_t *obj, int f) {
|
||
__IO uint32_t *dmy_cfg;
|
||
int oldfreq = 0;
|
||
int newfreq = 0;
|
||
uint32_t clkc_val;
|
||
uint8_t tmp_tq;
|
||
uint8_t tq = 0;
|
||
uint8_t tmp_brp;
|
||
uint8_t brp = 0;
|
||
uint8_t tseg1 = 0;
|
||
uint8_t tseg2 = 0;
|
||
uint8_t sjw = 0;
|
||
|
||
/* set clkc */
|
||
if (RZ_A1_IsClockMode0() == false) {
|
||
clkc_val = CM1_RENESAS_RZ_A1_P1_CLK / 2;
|
||
} else {
|
||
clkc_val = CM0_RENESAS_RZ_A1_P1_CLK / 2;
|
||
}
|
||
/* calculate BRP bit and Choose max value of calculated frequency */
|
||
for (tmp_tq = 8; tmp_tq <= 25; tmp_tq++) {
|
||
/* f = fCAN / ((BRP+1) * Tq) */
|
||
/* BRP = (fCAN / (f * Tq)) - 1 */
|
||
tmp_brp = ((clkc_val / (f * tmp_tq)) - 1) + 1; // carry(decimal point is carry)
|
||
newfreq = clkc_val / ((tmp_brp + 1) * tmp_tq);
|
||
if (newfreq >= oldfreq) {
|
||
oldfreq = newfreq;
|
||
tq = tmp_tq;
|
||
brp = tmp_brp;
|
||
}
|
||
}
|
||
/* calculate TSEG1 bit and TSEG2 bit */
|
||
tseg1 = (tq - 1) * 0.666666667;
|
||
tseg2 = (tq - 1) - tseg1;
|
||
sjw = (tseg2 > 4)? 4 : tseg2;
|
||
/* set RSCAN0CmCFG register */
|
||
dmy_cfg = CFG_MATCH[obj->ch];
|
||
*dmy_cfg = ((sjw - 1) << 24) | ((tseg2 - 1) << 20) | ((tseg1 - 1) << 16) | brp;
|
||
}
|
||
|
||
static void can_set_global_mode(int mode) {
|
||
/* set Global mode */
|
||
RSCAN0GCTR = ((RSCAN0GCTR & 0xFFFFFFFC) | (uint32_t)mode);
|
||
/* Wait to cahnge into Global XXXX mode */
|
||
while ((RSCAN0GSTS & 0x07) != (uint32_t)mode) {
|
||
__NOP();
|
||
}
|
||
}
|
||
|
||
static void can_set_channel_mode(uint32_t ch, int mode) {
|
||
__IO uint32_t *dmy_ctr;
|
||
__IO uint32_t *dmy_sts;
|
||
|
||
/* set Channel mode */
|
||
dmy_ctr = CTR_MATCH[ch];
|
||
*dmy_ctr = ((*dmy_ctr & 0xFFFFFFFC) | (uint32_t)mode);
|
||
/* Wait to cahnge into Channel XXXX mode */
|
||
dmy_sts = STS_MATCH[ch];
|
||
while ((*dmy_sts & 0x07) != (uint32_t)mode) {
|
||
__NOP();
|
||
}
|
||
}
|
||
|
||
const PinMap *can_rd_pinmap()
|
||
{
|
||
return PinMap_CAN_TD;
|
||
}
|
||
|
||
const PinMap *can_td_pinmap()
|
||
{
|
||
return PinMap_CAN_RD;
|
||
}
|
||
|