Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_blinky-bmd-200 bmd-200_accel_demo firstRig
Fork of mbed-src by
Revision 578:8e5b2476066a, committed 2015-06-19
- Comitter:
- mbed_official
- Date:
- Fri Jun 19 09:30:08 2015 +0100
- Parent:
- 577:ad23fe03a082
- Child:
- 579:30f9462b5296
- Commit message:
- Synchronized with git revision bb7d4bd4db3ad908ddcef72df3709e421318e28d
Full URL: https://github.com/mbedmicro/mbed/commit/bb7d4bd4db3ad908ddcef72df3709e421318e28d/
RZ_A1H - Add CAN driver.
Changed in this revision
--- a/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PeripheralNames.h Fri Jun 19 09:15:11 2015 +0100
+++ b/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/PeripheralNames.h Fri Jun 19 09:30:08 2015 +0100
@@ -95,6 +95,14 @@
I2C_3
} I2CName;
+typedef enum {
+ CAN_0 = 0,
+ CAN_1,
+ CAN_2,
+ CAN_3,
+ CAN_4
+} CANName;
+
#define STDIO_UART_TX USBTX
#define STDIO_UART_RX USBRX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/can_api.c Fri Jun 19 09:30:08 2015 +0100
@@ -0,0 +1,1009 @@
+/* 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 "pinmap.h"
+#include "rscan0_iodefine.h"
+#include "r_typedefs.h"
+#include "MBRZA1H.h"
+
+#define CAN_NUM 5
+#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 can1_rec_irq(void);
+static void can2_rec_irq(void);
+static void can3_rec_irq(void);
+static void can4_rec_irq(void);
+static void can0_trx_irq(void);
+static void can1_trx_irq(void);
+static void can2_trx_irq(void);
+static void can3_trx_irq(void);
+static void can4_trx_irq(void);
+static void can0_err_warning_irq(void);
+static void can1_err_warning_irq(void);
+static void can2_err_warning_irq(void);
+static void can3_err_warning_irq(void);
+static void can4_err_warning_irq(void);
+static void can0_overrun_irq(void);
+static void can1_overrun_irq(void);
+static void can2_overrun_irq(void);
+static void can3_overrun_irq(void);
+static void can4_overrun_irq(void);
+static void can0_passive_irq(void);
+static void can1_passive_irq(void);
+static void can2_passive_irq(void);
+static void can3_passive_irq(void);
+static void can4_passive_irq(void);
+static void can0_arb_lost_irq(void);
+static void can1_arb_lost_irq(void);
+static void can2_arb_lost_irq(void);
+static void can3_arb_lost_irq(void);
+static void can4_arb_lost_irq(void);
+static void can0_bus_err_irq(void);
+static void can1_bus_err_irq(void);
+static void can2_bus_err_irq(void);
+static void can3_bus_err_irq(void);
+static void can4_bus_err_irq(void);
+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 const PinMap PinMap_CAN_RD[] = {
+ {P7_8 , CAN_0, 4},
+ {P9_1 , CAN_0, 3},
+ {P1_4 , CAN_1, 3},
+ {P5_9 , CAN_1, 5},
+ {P7_11 , CAN_1, 4},
+ {P11_12, CAN_1, 1},
+ {P4_9 , CAN_2, 6},
+ {P6_4 , CAN_2, 3},
+ {P7_2 , CAN_2, 5},
+ {P2_12 , CAN_3, 5},
+ {P4_2 , CAN_3, 4},
+ {P1_5 , CAN_4, 3},
+ {P2_14 , CAN_4, 5},
+ {NC , NC , 0}
+};
+
+static const PinMap PinMap_CAN_TD[] = {
+ {P7_9 , CAN_0, 4},
+ {P9_0 , CAN_0, 3},
+ {P5_10 , CAN_1, 5},
+ {P7_10 , CAN_1, 4},
+ {P11_13, CAN_1, 1},
+ {P4_8 , CAN_2, 6},
+ {P6_5 , CAN_2, 3},
+ {P7_3 , CAN_2, 5},
+ {P2_13 , CAN_3, 5},
+ {P4_3 , CAN_3, 4},
+ {P4_11 , CAN_4, 6},
+ {P8_10 , CAN_4, 5},
+ {NC , NC , 0}
+};
+
+static __IO uint32_t *CTR_MATCH[] = {
+ &RSCAN0C0CTR,
+ &RSCAN0C1CTR,
+ &RSCAN0C2CTR,
+ &RSCAN0C3CTR,
+ &RSCAN0C4CTR,
+};
+
+static __IO uint32_t *CFG_MATCH[] = {
+ &RSCAN0C0CFG,
+ &RSCAN0C1CFG,
+ &RSCAN0C2CFG,
+ &RSCAN0C3CFG,
+ &RSCAN0C4CFG,
+};
+
+static __IO uint32_t *RFCC_MATCH[] = {
+ &RSCAN0RFCC0,
+ &RSCAN0RFCC1,
+ &RSCAN0RFCC2,
+ &RSCAN0RFCC3,
+ &RSCAN0RFCC4,
+ &RSCAN0RFCC5,
+ &RSCAN0RFCC6,
+ &RSCAN0RFCC7
+};
+
+static __IO uint32_t *TXQCC_MATCH[] = {
+ &RSCAN0TXQCC0,
+ &RSCAN0TXQCC1,
+ &RSCAN0TXQCC2,
+ &RSCAN0TXQCC3,
+ &RSCAN0TXQCC4,
+};
+
+static __IO uint32_t *THLCC_MATCH[] = {
+ &RSCAN0THLCC0,
+ &RSCAN0THLCC1,
+ &RSCAN0THLCC2,
+ &RSCAN0THLCC3,
+ &RSCAN0THLCC4,
+};
+
+static __IO uint32_t *STS_MATCH[] = {
+ &RSCAN0C0STS,
+ &RSCAN0C1STS,
+ &RSCAN0C2STS,
+ &RSCAN0C3STS,
+ &RSCAN0C4STS,
+};
+
+static __IO uint32_t *ERFL_MATCH[] = {
+ &RSCAN0C0ERFL,
+ &RSCAN0C1ERFL,
+ &RSCAN0C2ERFL,
+ &RSCAN0C3ERFL,
+ &RSCAN0C4ERFL,
+};
+
+static __IO uint32_t *CFCC_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFCC0 , &RSCAN0CFCC1 },
+ { &RSCAN0CFCC3 , &RSCAN0CFCC4 },
+ { &RSCAN0CFCC6 , &RSCAN0CFCC7 },
+ { &RSCAN0CFCC9 , &RSCAN0CFCC10 },
+ { &RSCAN0CFCC12, &RSCAN0CFCC13 }
+};
+
+static __IO uint32_t *CFSTS_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFSTS0 , &RSCAN0CFSTS1 },
+ { &RSCAN0CFSTS3 , &RSCAN0CFSTS4 },
+ { &RSCAN0CFSTS6 , &RSCAN0CFSTS7 },
+ { &RSCAN0CFSTS9 , &RSCAN0CFSTS10 },
+ { &RSCAN0CFSTS12, &RSCAN0CFSTS13 }
+};
+
+static __IO uint32_t *CFPCTR_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFPCTR0 , &RSCAN0CFPCTR1 },
+ { &RSCAN0CFPCTR3 , &RSCAN0CFPCTR4 },
+ { &RSCAN0CFPCTR6 , &RSCAN0CFPCTR7 },
+ { &RSCAN0CFPCTR9 , &RSCAN0CFPCTR10 },
+ { &RSCAN0CFPCTR12, &RSCAN0CFPCTR13 }
+};
+
+static __IO uint32_t *CFID_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFID0 , &RSCAN0CFID1 },
+ { &RSCAN0CFID3 , &RSCAN0CFID4 },
+ { &RSCAN0CFID6 , &RSCAN0CFID7 },
+ { &RSCAN0CFID9 , &RSCAN0CFID10 },
+ { &RSCAN0CFID12, &RSCAN0CFID13 }
+};
+
+static __IO uint32_t *CFPTR_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFPTR0 , &RSCAN0CFPTR1 },
+ { &RSCAN0CFPTR3 , &RSCAN0CFPTR4 },
+ { &RSCAN0CFPTR6 , &RSCAN0CFPTR7 },
+ { &RSCAN0CFPTR9 , &RSCAN0CFPTR10 },
+ { &RSCAN0CFPTR12, &RSCAN0CFPTR13 }
+};
+
+static __IO uint32_t *CFDF0_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFDF00 , &RSCAN0CFDF01 },
+ { &RSCAN0CFDF03 , &RSCAN0CFDF04 },
+ { &RSCAN0CFDF06 , &RSCAN0CFDF07 },
+ { &RSCAN0CFDF09 , &RSCAN0CFDF010 },
+ { &RSCAN0CFDF012, &RSCAN0CFDF013 }
+};
+
+static __IO uint32_t *CFDF1_TBL[CAN_NUM][CAN_SND_RCV] = {
+ { &RSCAN0CFDF10 , &RSCAN0CFDF11 },
+ { &RSCAN0CFDF13 , &RSCAN0CFDF14 },
+ { &RSCAN0CFDF16 , &RSCAN0CFDF17 },
+ { &RSCAN0CFDF19 , &RSCAN0CFDF110 },
+ { &RSCAN0CFDF112, &RSCAN0CFDF113 }
+};
+
+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 */
+ },
+ { /* 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 */
+ }
+};
+
+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_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 ADERRAB0ERRAB1ERRACERRAAERRAFERRASERR
+ *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 can1_rec_irq(void) {
+ can_rec_irq(CAN_1);
+}
+
+static void can2_rec_irq(void) {
+ can_rec_irq(CAN_2);
+}
+
+static void can3_rec_irq(void) {
+ can_rec_irq(CAN_3);
+}
+
+static void can4_rec_irq(void) {
+ can_rec_irq(CAN_4);
+}
+
+static void can0_trx_irq(void) {
+ can_trx_irq(CAN_0);
+}
+
+static void can1_trx_irq(void) {
+ can_trx_irq(CAN_1);
+}
+
+static void can2_trx_irq(void) {
+ can_trx_irq(CAN_2);
+}
+
+static void can3_trx_irq(void) {
+ can_trx_irq(CAN_3);
+}
+
+static void can4_trx_irq(void) {
+ can_trx_irq(CAN_4);
+}
+
+static void can0_err_warning_irq(void) {
+ can_err_irq(CAN_0, IRQ_ERROR);
+}
+
+static void can1_err_warning_irq(void) {
+ can_err_irq(CAN_1, IRQ_ERROR);
+}
+
+static void can2_err_warning_irq(void) {
+ can_err_irq(CAN_2, IRQ_ERROR);
+}
+
+static void can3_err_warning_irq(void) {
+ can_err_irq(CAN_3, IRQ_ERROR);
+}
+
+static void can4_err_warning_irq(void) {
+ can_err_irq(CAN_4, IRQ_ERROR);
+}
+
+static void can0_overrun_irq(void) {
+ can_err_irq(CAN_0, IRQ_OVERRUN);
+}
+
+static void can1_overrun_irq(void) {
+ can_err_irq(CAN_1, IRQ_OVERRUN);
+}
+
+static void can2_overrun_irq(void) {
+ can_err_irq(CAN_2, IRQ_OVERRUN);
+}
+
+static void can3_overrun_irq(void) {
+ can_err_irq(CAN_3, IRQ_OVERRUN);
+}
+
+static void can4_overrun_irq(void) {
+ can_err_irq(CAN_4, IRQ_OVERRUN);
+}
+
+static void can0_passive_irq(void) {
+ can_err_irq(CAN_0, IRQ_PASSIVE);
+}
+
+static void can1_passive_irq(void) {
+ can_err_irq(CAN_1, IRQ_PASSIVE);
+}
+
+static void can2_passive_irq(void) {
+ can_err_irq(CAN_2, IRQ_PASSIVE);
+}
+
+static void can3_passive_irq(void) {
+ can_err_irq(CAN_3, IRQ_PASSIVE);
+}
+
+static void can4_passive_irq(void) {
+ can_err_irq(CAN_4, IRQ_PASSIVE);
+}
+
+static void can0_arb_lost_irq(void) {
+ can_err_irq(CAN_0, IRQ_ARB);
+}
+
+static void can1_arb_lost_irq(void) {
+ can_err_irq(CAN_1, IRQ_ARB);
+}
+
+static void can2_arb_lost_irq(void) {
+ can_err_irq(CAN_2, IRQ_ARB);
+}
+
+static void can3_arb_lost_irq(void) {
+ can_err_irq(CAN_3, IRQ_ARB);
+}
+
+static void can4_arb_lost_irq(void) {
+ can_err_irq(CAN_4, IRQ_ARB);
+}
+
+static void can0_bus_err_irq(void) {
+ can_err_irq(CAN_0, IRQ_BUS);
+}
+
+static void can1_bus_err_irq(void) {
+ can_err_irq(CAN_1, IRQ_BUS);
+}
+
+static void can2_bus_err_irq(void) {
+ can_err_irq(CAN_2, IRQ_BUS);
+}
+
+static void can3_bus_err_irq(void) {
+ can_err_irq(CAN_3, IRQ_BUS);
+}
+
+static void can4_bus_err_irq(void) {
+ can_err_irq(CAN_4, IRQ_BUS);
+}
+
+void can_init(can_t *obj, PinName rd, PinName td) {
+ __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);
+}
+
+void can_free(can_t *obj) {
+ /* disable CAN clock */
+ CPGSTBCR3 |= CPG_STBCR3_BIT_MSTP32;
+}
+
+int can_frequency(can_t *obj, int f) {
+ 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);
+ 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 <= 0x03FFFF))) {
+ /* 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-11) */
+ 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 & 0x03FFFF) << 11);
+ }
+ /* 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-11) */
+ dmy_cfid = CFID_TBL[obj->ch][CAN_RECV];
+ msg->format = (CANFormat)(*dmy_cfid >> 31);
+ msg->type = (CANType)(*dmy_cfid >> 30);
+ if (msg->format == CANStandard) {
+ msg->id = (*dmy_cfid & 0x07FF);
+ } else {
+ msg->id = ((*dmy_cfid >> 11) & 0x03FFFF);
+ }
+ /* 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 channel 1 and channel 2 */
+ /* set Channel Hold mode */
+ for (tmp_obj->ch = CAN_1; tmp_obj->ch <= CAN_2; 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 channel1 and channel2 */
+ RSCAN0GTSTCFG = 0x06;
+ RSCAN0GTSTCTR = 0x01;
+ /* send and receive setting of channel1 and channel2 */
+ for (tmp_obj->ch = CAN_1; tmp_obj->ch <= CAN_2; 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 <= 0x03FFFF))) {
+ /* 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-11 */
+ *dmy_gaflid |= (id << 11);
+ } else {
+ /* set receive rule ID for bit10-0 */
+ *dmy_gaflid |= id;
+ }
+ /* 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;
+ RSCAN0GAFLCFG1 = 0x40000000;
+ /* 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;
+ RSCAN0TMIEC1 = 0x00000000;
+ RSCAN0TMIEC2 = 0x00000000;
+}
+
+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;
+
+ /* 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;
+ /* set RSCAN0CmCFG register */
+ dmy_cfg = CFG_MATCH[obj->ch];
+ *dmy_cfg = ((tseg2 - 1) << 20) | ((tseg1 - 1) << 16) | brp;
+}
+
+static void can_set_global_mode(int mode) {
+ /* set Global mode */
+ RSCAN0GCTR = ((RSCAN0GCTR & 0xFFFFFFFC) | mode);
+ /* Wait to cahnge into Global XXXX mode */
+ while ((RSCAN0GSTS & 0x07) != 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) | mode);
+ /* Wait to cahnge into Channel XXXX mode */
+ dmy_sts = STS_MATCH[ch];
+ while ((*dmy_sts & 0x07) != mode) {
+ __NOP();
+ }
+}
+
--- a/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h Fri Jun 19 09:15:11 2015 +0100 +++ b/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/device.h Fri Jun 19 09:30:08 2015 +0100 @@ -42,7 +42,7 @@ #define DEVICE_SPI 1 #define DEVICE_SPISLAVE 1 -#define DEVICE_CAN 0 +#define DEVICE_CAN 1 #define DEVICE_RTC 1
--- a/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h Fri Jun 19 09:15:11 2015 +0100
+++ b/targets/hal/TARGET_RENESAS/TARGET_RZ_A1H/objects.h Fri Jun 19 09:30:08 2015 +0100
@@ -72,6 +72,10 @@
ADCName adc;
};
+struct can_s {
+ uint32_t ch;
+};
+
#ifdef __cplusplus
}
#endif
