Files
Beslan 0ef1717155
Some checks failed
Basic Checks / license-check (push) Has been cancelled
Basic Checks / include-check (push) Has been cancelled
Basic Checks / style-check (push) Has been cancelled
Basic Checks / docs-check (push) Has been cancelled
Basic Checks / python-tests (push) Has been cancelled
Basic Checks / pin-validation (push) Has been cancelled
Basic Checks / cmake-checks (push) Has been cancelled
Basic Checks / frozen-tools-check (push) Has been cancelled
Publish or Update docker image for head of branch / prepare-tags (push) Has been cancelled
Release or update docker image for a released mbed-os version / prepare-tags (push) Has been cancelled
Publish or Update docker image for head of branch / build-container (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/amd64) (push) Has been cancelled
Publish or Update docker image for head of branch / test-container (linux/arm64) (push) Has been cancelled
Publish or Update docker image for head of branch / deploy-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / build-container (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/amd64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / test-container (linux/arm64) (push) Has been cancelled
Release or update docker image for a released mbed-os version / deploy-container (push) Has been cancelled
Prune temporary docker images / prune-images (push) Has been cancelled
Mirror mbed-os-6.15.0
2026-07-10 18:42:39 +03:00

928 lines
31 KiB
C

/* mbed Microcontroller Library
* Copyright (c) 2006-2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*/
#if DEVICE_CAN
#include "mbed_assert.h"
#include "can_api.h"
#include "RZ_A2_Init.h"
#include "cmsis.h"
#include "PeripheralPins.h"
#include "iodefine.h"
#include "r_typedefs.h"
#include "mbed_drv_cfg.h"
#include "rza_io_regrw.h"
#include "iobitmask.h"
#include "r_can_rz_config.h"
#include "r_can_rz_if.h"
/* RZA IO */
#define REG_32W RZA_IO_RegWrite_32
#define REG_NONSHIFT IOREG_NONSHIFT_ACCESS
#define REG_NONMASK IOREG_NONMASK_ACCESS
/* Channel */
#define CHANNEL_MAX MAX_CHANNELS
#define CAN_TX_RX 2
#define CAN_IRQ_TYPE_MAX 8
/* RX rule */
#define RXRULE_J_MAX 16
#define RXRULE_CH0_MAX CAN0_RX_RULE_NUM
#define RXRULE_CH1_MAX CAN1_RX_RULE_NUM
/* TR_FIFO */
#define TX_TRFIFO_INDEX(ch) (ch * TRFIFO_NUM_PER_CH)
#define RX_TRFIFO_INDEX(ch) (ch * TRFIFO_NUM_PER_CH) + 1
/* Normal bit rate */
#define NSS_MAX 1
#define NTSEG1_MAX 128
#define NTSEG2_MAX 32
#define N_TOTAL_TQMAX (NSS_MAX + NTSEG1_MAX + NTSEG2_MAX)
#define N_TOTAL_TQMIN 8
#define N_SAMPLE_POINT 0.666666667
#define N_SJW 3
#define N_BITRATE_DEFAULT 100000
#define N_BITRATE_MAX 1000000
/* Data bit rate */
#define DSS_MAX 1
#define DTSEG1_MAX 16
#define DTSEG2_MAX 8
#define D_TOTAL_TQMAX (DSS_MAX + DTSEG1_MAX + DTSEG2_MAX)
#define D_TOTAL_TQMIN 8
#define D_SAMPLE_POINT 0.666666667
#define D_SJW 3
#define D_CH0_BITRATE 2000000
#define D_CH1_BITRATE 2000000
/*
* RCANFD Register
*/
/* CmCTR */
#define CTR_BEIE RCANFD_RSCFD0CFDC0CTR_BEIE
#define CTR_EWIE RCANFD_RSCFD0CFDC0CTR_EWIE
#define CTR_EPIE RCANFD_RSCFD0CFDC0CTR_EPIE
#define CTR_BOEIE RCANFD_RSCFD0CFDC0CTR_BOEIE
#define CTR_BORIE RCANFD_RSCFD0CFDC0CTR_BORIE
#define CTR_OLIE RCANFD_RSCFD0CFDC0CTR_OLIE
#define CTR_BLIE RCANFD_RSCFD0CFDC0CTR_BLIE
#define CTR_ALIE RCANFD_RSCFD0CFDC0CTR_ALIE
#define CTR_TAIE RCANFD_RSCFD0CFDC0CTR_TAIE
#define CTR_IEALL (CTR_BEIE | CTR_EWIE | CTR_EPIE | CTR_BOEIE | CTR_BORIE | \
CTR_OLIE | CTR_BLIE | CTR_ALIE | CTR_TAIE)
#define CTR_EOCOIE RCANFD_RSCFD0CFDC0CTR_EOCOIE
#define CTR_SOCOIE RCANFD_RSCFD0CFDC0CTR_SOCOIE
#define CTR_TDCVFIE RCANFD_RSCFD0CFDC0CTR_TDCVFIE
#define CTR_BOM RCANFD_RSCFD0CFDC0CTR_BOM
#define CTR_ERRD RCANFD_RSCFD0CFDC0CTR_ERRD
#define CTR_CTME RCANFD_RSCFD0CFDC0CTR_CTME
#define CTR_CTMS RCANFD_RSCFD0CFDC0CTR_CTMS
#define CTR_CRCT RCANFD_RSCFD0CFDC0CTR_CRCT
#define CTR_ROM RCANFD_RSCFD0CFDC0CTR_ROM
#define CTR_CTME_SHIFT RCANFD_RSCFD0CFDC0CTR_CTME_SHIFT
#define CTR_CTMS_SHIFT RCANFD_RSCFD0CFDC0CTR_CTMS_SHIFT
#define MASK_CTR_INIT (CTR_ERRD | CTR_BOM | CTR_TDCVFIE | CTR_SOCOIE | CTR_EOCOIE | CTR_IEALL)
/* CmERFL */
#define ERFL_BEF RCANFD_RSCFD0CFDC0ERFL_BEF
#define ERFL_EWF RCANFD_RSCFD0CFDC0ERFL_EWF
#define ERFL_EPF RCANFD_RSCFD0CFDC0ERFL_EPF
#define ERFL_BOEF RCANFD_RSCFD0CFDC0ERFL_BOEF
#define ERFL_BORF RCANFD_RSCFD0CFDC0ERFL_BORF
#define ERFL_OVLF RCANFD_RSCFD0CFDC0ERFL_OVLF
#define ERFL_BLF RCANFD_RSCFD0CFDC0ERFL_BLF
#define ERFL_ALF RCANFD_RSCFD0CFDC0ERFL_ALF
#define ERFL_SERR RCANFD_RSCFD0CFDC0ERFL_SERR
#define ERFL_FERR RCANFD_RSCFD0CFDC0ERFL_FERR
#define ERFL_AERR RCANFD_RSCFD0CFDC0ERFL_AERR
#define ERFL_CERR RCANFD_RSCFD0CFDC0ERFL_CERR
#define ERFL_B1ERR RCANFD_RSCFD0CFDC0ERFL_B1ERR
#define ERFL_B0ERR RCANFD_RSCFD0CFDC0ERFL_B0ERR
#define ERFL_ADERR RCANFD_RSCFD0CFDC0ERFL_ADERR
#define ERFL_ALLERR (ERFL_SERR | ERFL_FERR | ERFL_AERR | ERFL_CERR | ERFL_B1ERR | ERFL_B0ERR | ERFL_ADERR)
/* CmFDCFG */
#define FDCFG_EOCCFG RCANFD_RSCFD0CFDC0FDCFG_EOCCFG
#define FDCFG_ESIC RCANFD_RSCFD0CFDC0FDCFG_ESIC
#define FDCFG_GWEN RCANFD_RSCFD0CFDC0FDCFG_GWEN
#define FDCFG_GWFDF RCANFD_RSCFD0CFDC0FDCFG_GWFDF
#define FDCFG_GWBRS RCANFD_RSCFD0CFDC0FDCFG_GWBRS
#define FDCFG_TMME RCANFD_RSCFD0CFDC0FDCFG_TMME
#define FDCFG_FDOE RCANFD_RSCFD0CFDC0FDCFG_FDOE
#define FDCFG_REFE RCANFD_RSCFD0CFDC0FDCFG_REFE
#define MASK_FDCFG_INIT (FDCFG_REFE | FDCFG_FDOE | FDCFG_TMME | FDCFG_GWBRS | FDCFG_GWFDF| \
FDCFG_GWEN | FDCFG_ESIC | FDCFG_EOCCFG)
/* GCTR */
#define GCTR_DEIE RCANFD_RSCFD0CFDGCTR_DEIE
#define GCTR_MEIE RCANFD_RSCFD0CFDGCTR_MEIE
#define GCTR_THLEIE RCANFD_RSCFD0CFDGCTR_THLEIE
#define GCTR_CMPOFIE RCANFD_RSCFD0CFDGCTR_CMPOFIE
#define MASK_GCTR_INIT (GCTR_DEIE | GCTR_MEIE | GCTR_THLEIE | GCTR_CMPOFIE)
/* CFCCk */
#define CFCC_CFTXIE RCANFD_RSCFD0CFDCFCC0_CFTXIE
#define CFCC_CFRXIE RCANFD_RSCFD0CFDCFCC0_CFRXIE
#define CFCC_CFE RCANFD_RSCFD0CFDCFCC0_CFE
#define MASK_CFCC_INIT ~(CFCC_CFTXIE | CFCC_CFRXIE | CFCC_CFE)
/* CFSTSk */
#define CFSTS_CFRXIF RCANFD_RSCFD0CFDCFSTS0_CFRXIF
#define CFSTS_CFTXIF RCANFD_RSCFD0CFDCFSTS0_CFTXIF
/* RFCCx*/
#define RFCC_RFIE RCANFD_RSCFD0CFDRFCC0_RFIE
#define RFCC_RFE RCANFD_RSCFD0CFDRFCC0_RFE
#define MASK_RFCC_INIT ~(RFCC_RFIE | RFCC_RFE)
/* TXQCCm */
#define TXQCC_TXQDC RCANFD_RSCFD0CFDTXQCC0_TXQDC
#define TXQCC_TXQIE RCANFD_RSCFD0CFDTXQCC0_TXQIE
#define TXQCC_TXQIM RCANFD_RSCFD0CFDTXQCC0_TXQIM
/* THLCCm */
#define THLCC_THLIE RCANFD_RSCFD0CFDTHLCC0_THLIE
#define THLCC_THLIM RCANFD_RSCFD0CFDTHLCC0_THLIM
#define THLCC_THLDTE RCANFD_RSCFD0CFDTHLCC0_THLDTE
/* GTSTCFG */
#define GTSTCFG_C0ICBCE RCANFD_RSCFD0CFDGTSTCFG_C0ICBCE
#define GTSTCFG_C1ICBCE RCANFD_RSCFD0CFDGTSTCFG_C1ICBCE
#define GTSTCFG_C0ICBCE_SHIFT RCANFD_RSCFD0CFDGTSTCFG_C0ICBCE_SHIFT
#define GTSTCFG_C1ICBCE_SHIFT RCANFD_RSCFD0CFDGTSTCFG_C1ICBCE_SHIFT
/* GTSTCTR */
#define GTSTCTR_ICBCTME RCANFD_RSCFD0CFDGTSTCTR_ICBCTME
#define GTSTCTR_ICBCTME_SHIFT RCANFD_RSCFD0CFDGTSTCTR_ICBCTME_SHIFT
/* RX buffer size */
#define RX_FIFO_MULTIPLE 8
#define RX_BUFFER_MAX (4 * ((19 * RX_FIFO_MULTIPLE) + 1)) / 4
static void can_rec_irq(uint32_t ch);
static void can_trx_irq(uint32_t ch);
static void can_err_irq(uint32_t ch);
static void can0_rec_irq(void);
static void can0_trx_irq(void);
static void can0_err_irq(void);
static void can1_rec_irq(void);
static void can1_trx_irq(void);
static void can1_err_irq(void);
static void set_normal_bitrate(uint32_t ch, int f);
static void reset_register(uint32_t ch);
static void reset_buffer(uint32_t ch);
static void get_rxrule_index(uint32_t ch, int32_t handle, uint8_t *page, uint8_t *j);
static void reconfigure_channel(uint32_t ch);
static void set_test_mode(uint32_t ch, uint32_t mode, uint32_t enable);
typedef enum {
CAN_TX = 0,
CAN_RX
} can_operation;
typedef enum {
TEST_DISABLE = 0,
TEST_ENABLE
} ctr_ctme;
typedef struct {
IRQn_Type id; /* Interrupt identifier */
IRQHandler handler; /* Interrupt handler */
} can_irq_int_t;
static const can_irq_int_t irq_tbl[CHANNEL_MAX][CAN_IRQ_TYPE_MAX] = {
{ /* ch0 */
{ CFRXI0_IRQn, can0_rec_irq }, /* RxIrq : IRQ_RX */
{ CTXI0_IRQn, can0_trx_irq }, /* TxIrq : IRQ_TX */
{ CERI0_IRQn, can0_err_irq }, /* EwIrq : IRQ_ERROR */
{ CERI0_IRQn, can0_err_irq }, /* DoIrq : IRQ_OVERRUN */
{ CERI0_IRQn, can0_err_irq }, /* WuIrq : IRQ_WAKEUP */
{ CERI0_IRQn, can0_err_irq }, /* EpIrq : IRQ_PASSIVE */
{ CERI0_IRQn, can0_err_irq }, /* AlIrq : IRQ_ARB */
{ CERI0_IRQn, can0_err_irq } /* BeIrq : IRQ_BUS */
},
{ /* ch1 */
{ CFRXI1_IRQn, can1_rec_irq }, /* RxIrq : IRQ_RX */
{ CTXI1_IRQn, can1_trx_irq }, /* TxIrq : IRQ_TX */
{ CERI1_IRQn, can1_err_irq }, /* EwIrq : IRQ_ERROR */
{ CERI1_IRQn, can1_err_irq }, /* DoIrq : IRQ_OVERRUN */
{ CERI1_IRQn, can1_err_irq }, /* WuIrq : IRQ_WAKEUP */
{ CERI1_IRQn, can1_err_irq }, /* EpIrq : IRQ_PASSIVE */
{ CERI1_IRQn, can1_err_irq }, /* EpIrq : IRQ_PASSIVE */
{ CERI1_IRQn, can1_err_irq } /* BeIrq : IRQ_BUS */
},
};
static const uint32_t irq_enable_flag_tbl[CAN_IRQ_TYPE_MAX] = {
CFCC_CFRXIE, /* RxIrq : IRQ_RX */
CFCC_CFTXIE, /* TxIrq : IRQ_TX */
CTR_EWIE, /* EwIrq : IRQ_ERROR */
CTR_OLIE, /* DoIrq : IRQ_OVERRUN */
0, /* WuIrq : IRQ_WAKEUP */
CTR_EPIE, /* EpIrq : IRQ_PASSIVE */
CTR_ALIE, /* AlIrq : IRQ_ARB */
CTR_BEIE, /* BeIrq : IRQ_BUS */
};
/* Channel bit rate configuration */
static __IO uint32_t *g_regtbl_ncfg[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDC0NCFG.LONG,
&RCANFD.RSCFD0CFDC1NCFG.LONG
};
/* Channel data bit rate configuration */
static __IO uint32_t *g_regtbl_dcfg[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDC0DCFG.LONG,
&RCANFD.RSCFD0CFDC1DCFG.LONG
};
/* Channel CANFD configuration */
static __IO uint32_t *g_regtbl_fdcfg[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDC0FDCFG.LONG,
&RCANFD.RSCFD0CFDC1FDCFG.LONG
};
static uint32_t g_fdcfg_init[CHANNEL_MAX] = {
CAN_C0FDCFG,
CAN_C1FDCFG
};
/* Channel control */
static __IO uint32_t *g_regtbl_ctr[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDC0CTR.LONG,
&RCANFD.RSCFD0CFDC1CTR.LONG
};
static uint32_t g_ctr_init[CHANNEL_MAX] = {
CAN_C0CTR,
CAN_C1CTR
};
/* Channel status */
static __IO uint32_t *g_regtbl_sts[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDC0STS.LONG,
&RCANFD.RSCFD0CFDC1STS.LONG
};
/* Channel error flag */
static __IO uint32_t *g_regtbl_erfl[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDC0ERFL.LONG,
&RCANFD.RSCFD0CFDC1ERFL.LONG
};
/* TRFIFO Configuration */
static __IO uint32_t *g_regtbl_cfcc[CHANNEL_MAX][CAN_TX_RX] = {
{ &RCANFD.RSCFD0CFDCFCC0.LONG, &RCANFD.RSCFD0CFDCFCC1.LONG }, // CAN0(TX TR_FIFO0, RX TR_FIFO1)
{ &RCANFD.RSCFD0CFDCFCC3.LONG, &RCANFD.RSCFD0CFDCFCC4.LONG } // CAN1(TX TR_FIFO3, RX TR_FIFO4)
};
static uint32_t g_cfcc_init[CHANNEL_MAX][CAN_TX_RX] = {
{ CAN_CFCC0, CAN_CFCC1 }, // CAN0(TX TR_FIFO0, RX TR_FIFO1)
{ CAN_CFCC3, CAN_CFCC4 } // CAN1(TX TR_FIFO3, RX TR_FIFO4)
};
/* TRFIFO Status */
static __IO uint32_t *g_regtbl_cfsts[CHANNEL_MAX][CAN_TX_RX] = {
{ &RCANFD.RSCFD0CFDCFSTS0.LONG, &RCANFD.RSCFD0CFDCFSTS1.LONG }, // CAN0(TX TR_FIFO0, RX TR_FIFO1)
{ &RCANFD.RSCFD0CFDCFSTS3.LONG, &RCANFD.RSCFD0CFDCFSTS4.LONG } // CAN1(TX TR_FIFO3, RX TR_FIFO4)
};
/* RXFIFO Configuration */
static __IO uint32_t *g_regtbl_rfcc[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDRFCC0.LONG, // CAN0(RX_FIFO0)
&RCANFD.RSCFD0CFDRFCC4.LONG // CAN1(RX_FIFO4)
};
static uint32_t g_rfcc_init[CHANNEL_MAX] = {
CAN_RFCC0, // CAN0(RX_FIFO0)
CAN_RFCC4 // CAN1(RX_FIFO4)
};
/* TXQCC */
static __IO uint32_t *g_regtbl_txqcc[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDTXQCC0.LONG,
&RCANFD.RSCFD0CFDTXQCC1.LONG
};
static uint32_t g_init_txqcc[CHANNEL_MAX] = {
CAN_TXQCC0,
CAN_TXQCC1
};
/* THLCC */
static __IO uint32_t *g_regtbl_thlcc[CHANNEL_MAX] = {
&RCANFD.RSCFD0CFDTHLCC0.LONG,
&RCANFD.RSCFD0CFDTHLCC1.LONG
};
static uint32_t g_init_thlcc[CHANNEL_MAX] = {
CAN_THLCC0,
CAN_THLCC1
};
/* RX rule register : ID */
static __IO uint32_t *g_regtbl_gaflid[RXRULE_J_MAX] = {
&RCANFD.RSCFD0CFDGAFLID0.LONG,
&RCANFD.RSCFD0CFDGAFLID1.LONG,
&RCANFD.RSCFD0CFDGAFLID2.LONG,
&RCANFD.RSCFD0CFDGAFLID3.LONG,
&RCANFD.RSCFD0CFDGAFLID4.LONG,
&RCANFD.RSCFD0CFDGAFLID5.LONG,
&RCANFD.RSCFD0CFDGAFLID6.LONG,
&RCANFD.RSCFD0CFDGAFLID7.LONG,
&RCANFD.RSCFD0CFDGAFLID8.LONG,
&RCANFD.RSCFD0CFDGAFLID9.LONG,
&RCANFD.RSCFD0CFDGAFLID10.LONG,
&RCANFD.RSCFD0CFDGAFLID11.LONG,
&RCANFD.RSCFD0CFDGAFLID12.LONG,
&RCANFD.RSCFD0CFDGAFLID13.LONG,
&RCANFD.RSCFD0CFDGAFLID14.LONG,
&RCANFD.RSCFD0CFDGAFLID15.LONG
};
/* RX rule register : Mask */
static __IO uint32_t *g_regtbl_gaflm[RXRULE_J_MAX] = {
&RCANFD.RSCFD0CFDGAFLM0.LONG,
&RCANFD.RSCFD0CFDGAFLM1.LONG,
&RCANFD.RSCFD0CFDGAFLM2.LONG,
&RCANFD.RSCFD0CFDGAFLM3.LONG,
&RCANFD.RSCFD0CFDGAFLM4.LONG,
&RCANFD.RSCFD0CFDGAFLM5.LONG,
&RCANFD.RSCFD0CFDGAFLM6.LONG,
&RCANFD.RSCFD0CFDGAFLM7.LONG,
&RCANFD.RSCFD0CFDGAFLM8.LONG,
&RCANFD.RSCFD0CFDGAFLM9.LONG,
&RCANFD.RSCFD0CFDGAFLM10.LONG,
&RCANFD.RSCFD0CFDGAFLM11.LONG,
&RCANFD.RSCFD0CFDGAFLM12.LONG,
&RCANFD.RSCFD0CFDGAFLM13.LONG,
&RCANFD.RSCFD0CFDGAFLM14.LONG,
&RCANFD.RSCFD0CFDGAFLM15.LONG
};
/* RX rule register : pointer1 */
static __IO uint32_t *g_regtbl_gaflp1[RXRULE_J_MAX] = {
&RCANFD.RSCFD0CFDGAFLP1_0.LONG,
&RCANFD.RSCFD0CFDGAFLP1_1.LONG,
&RCANFD.RSCFD0CFDGAFLP1_2.LONG,
&RCANFD.RSCFD0CFDGAFLP1_3.LONG,
&RCANFD.RSCFD0CFDGAFLP1_4.LONG,
&RCANFD.RSCFD0CFDGAFLP1_5.LONG,
&RCANFD.RSCFD0CFDGAFLP1_6.LONG,
&RCANFD.RSCFD0CFDGAFLP1_7.LONG,
&RCANFD.RSCFD0CFDGAFLP1_8.LONG,
&RCANFD.RSCFD0CFDGAFLP1_9.LONG,
&RCANFD.RSCFD0CFDGAFLP1_10.LONG,
&RCANFD.RSCFD0CFDGAFLP1_11.LONG,
&RCANFD.RSCFD0CFDGAFLP1_12.LONG,
&RCANFD.RSCFD0CFDGAFLP1_13.LONG,
&RCANFD.RSCFD0CFDGAFLP1_14.LONG,
&RCANFD.RSCFD0CFDGAFLP1_15.LONG
};
/* DLC to data length */
static const uint8_t dlc_to_length[16] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64
};
volatile int g_normal_bitrate[CHANNEL_MAX];
volatile int g_data_bitrate[CHANNEL_MAX] = {D_CH0_BITRATE, D_CH1_BITRATE};
uint32_t rx_buf[RX_BUFFER_MAX];
static can_irq_handler irq_handler[CHANNEL_MAX] = {NULL};
static uint32_t can_irq_id[CHANNEL_MAX] = {0};
void can_irq_init(can_t *obj, can_irq_handler handler, uint32_t id)
{
irq_handler[obj->ch] = handler;
can_irq_id[obj->ch] = id;
}
void can_irq_free(can_t *obj)
{
can_irq_id[obj->ch] = 0;
*g_regtbl_cfcc[obj->ch][CAN_RX] &= ~CFCC_CFRXIE;
*g_regtbl_cfcc[obj->ch][CAN_TX] &= ~CFCC_CFTXIE;
*g_regtbl_ctr[obj->ch] &= ~(CTR_EWIE | CTR_OLIE | CTR_EPIE | CTR_ALIE | CTR_BEIE);
if (CH_0 == obj->ch) {
GIC_DisableIRQ(CFRXI0_IRQn);
GIC_DisableIRQ(CTXI0_IRQn);
GIC_DisableIRQ(CERI0_IRQn);
} else {
GIC_DisableIRQ(CFRXI1_IRQn);
GIC_DisableIRQ(CTXI1_IRQn);
GIC_DisableIRQ(CERI1_IRQn);
}
}
void can_irq_set(can_t *obj, CanIrqType type, uint32_t enable)
{
switch (type) {
case IRQ_RX:
if (enable) {
*g_regtbl_cfcc[obj->ch][CAN_RX] |= CFCC_CFRXIE;
} else {
*g_regtbl_cfcc[obj->ch][CAN_RX] &= ~CFCC_CFRXIE;
}
break;
case IRQ_TX:
if (enable) {
*g_regtbl_cfcc[obj->ch][CAN_TX] |= CFCC_CFTXIE;
} else {
*g_regtbl_cfcc[obj->ch][CAN_TX] &= ~CFCC_CFTXIE;
}
break;
case IRQ_ERROR:
case IRQ_OVERRUN:
case IRQ_PASSIVE:
case IRQ_ARB:
case IRQ_BUS:
if (enable) {
*g_regtbl_ctr[obj->ch] |= irq_enable_flag_tbl[type];
} else {
*g_regtbl_ctr[obj->ch] &= ~irq_enable_flag_tbl[type];
}
break;
case IRQ_WAKEUP:
/* not supported */
/* fall through */
default:
return;
}
if (enable) {
InterruptHandlerRegister(irq_tbl[obj->ch][type].id, irq_tbl[obj->ch][type].handler);
GIC_SetPriority(irq_tbl[obj->ch][type].id, 20);
GIC_EnableIRQ(irq_tbl[obj->ch][type].id);
GIC_SetConfiguration(irq_tbl[obj->ch][type].id, 1);
} else {
GIC_DisableIRQ(irq_tbl[obj->ch][type].id);
}
}
static void can_rec_irq(uint32_t ch)
{
*g_regtbl_cfsts[ch][CAN_RX] &= ~CFSTS_CFRXIF;
irq_handler[ch](can_irq_id[ch], IRQ_RX);
}
static void can_trx_irq(uint32_t ch)
{
*g_regtbl_cfsts[ch][CAN_TX] &= ~CFSTS_CFTXIF;
irq_handler[ch](can_irq_id[ch], IRQ_TX);
}
static void can_err_irq(uint32_t ch)
{
/* error warning */
if (*g_regtbl_erfl[ch] & ERFL_EWF) {
*g_regtbl_erfl[ch] &= ~ERFL_EWF;
irq_handler[ch](can_irq_id[ch], IRQ_ERROR);
}
/* over load */
if (*g_regtbl_erfl[ch] & ERFL_OVLF) {
*g_regtbl_erfl[ch] &= ~ERFL_OVLF;
irq_handler[ch](can_irq_id[ch], IRQ_OVERRUN);
}
/* error passive */
if (*g_regtbl_erfl[ch] & ERFL_EPF) {
*g_regtbl_erfl[ch] &= ~ERFL_EPF;
irq_handler[ch](can_irq_id[ch], IRQ_PASSIVE);
}
/* arbitration lost */
if (*g_regtbl_erfl[ch] & ERFL_ALF) {
*g_regtbl_erfl[ch] &= ~ERFL_ALF;
irq_handler[ch](can_irq_id[ch], IRQ_ARB);
}
/* bus error */
if (*g_regtbl_erfl[ch] & ERFL_ALLERR) {
*g_regtbl_erfl[ch] &= ~ERFL_ALLERR;
*g_regtbl_erfl[ch] &= ~ERFL_BEF;
irq_handler[ch](can_irq_id[ch], IRQ_BUS);
}
}
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_irq(void)
{
can_err_irq(CAN_0);
}
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_irq(void)
{
can_err_irq(CAN_1);
}
static void set_normal_bitrate(uint32_t ch, int f)
{
uint32_t clkc;
uint16_t tq_total;
uint16_t brp;
uint8_t tseg1 = 0;
uint8_t tseg2 = 0;
uint8_t sjw = 0;
/* clkc */
if (false == RZ_A2_IsClockMode0()) {
clkc = CM1_RENESAS_RZ_A2_P1_CLK / 2;
} else {
clkc = CM0_RENESAS_RZ_A2_P1_CLK / 2;
}
/* calculate NTSEG1 bit and NTSEG2 bit */
for (brp = 1; brp < 1024; brp++) {
tq_total = clkc / (f * brp);
if ((N_TOTAL_TQMIN <= tq_total) && (tq_total <= N_TOTAL_TQMAX)) {
tseg1 = tq_total * N_SAMPLE_POINT - NSS_MAX;
tseg2 = tq_total - (NSS_MAX + tseg1);
if ((NTSEG1_MAX >= tseg1) && (NTSEG2_MAX >= tseg2)) {
break;
}
}
}
/* calculate NSJW */
sjw = (tseg2 > N_SJW) ? N_SJW : tseg2;
/* set RSCAN0CmCFG register */
*g_regtbl_ncfg[ch] = ((tseg2 - 1) << 24) | ((tseg1 - 1) << 16) | ((sjw - 1) << 11) | (brp - 1);
}
static void set_data_bitrate(uint32_t ch, int f)
{
uint32_t clkc;
uint16_t tq_total;
uint16_t dbrp;
uint8_t dtseg1 = 0;
uint8_t dtseg2 = 0;
uint8_t dsjw = 0;
/* clkc */
if (false == RZ_A2_IsClockMode0()) {
clkc = CM1_RENESAS_RZ_A2_P1_CLK / 2;
} else {
clkc = CM0_RENESAS_RZ_A2_P1_CLK / 2;
}
/* calculate DTSEG1 bit and DTSEG2 bit */
for (dbrp = 1; dbrp < 256; dbrp++) {
tq_total = clkc / (f * dbrp);
if ((D_TOTAL_TQMIN <= tq_total) && (tq_total <= D_TOTAL_TQMAX)) {
dtseg1 = tq_total * D_SAMPLE_POINT - DSS_MAX;
dtseg2 = tq_total - (DSS_MAX + dtseg1);
if ((DTSEG1_MAX >= dtseg1) && (DTSEG2_MAX >= dtseg2)) {
break;
}
}
}
/* calculate DSJW */
dsjw = (dtseg2 >= D_SJW) ? D_SJW : dtseg2;
/* set RSCAN0CmDCFG register */
*g_regtbl_dcfg[ch] = ((dsjw - 1) << 24) | ((dtseg2 - 1) << 20) | ((dtseg1 - 1) << 16) | (dbrp - 1);
}
static void reset_register(uint32_t ch)
{
/* Global function setting */
REG_32W(&RCANFD.RSCFD0CFDGCFG.LONG, CAN_GCFG, REG_NONSHIFT, REG_NONMASK);
REG_32W(&RCANFD.RSCFD0CFDGFDCFG.LONG, CAN_GFDCFG, REG_NONSHIFT, REG_NONMASK);
/* Communication speed setting */
set_normal_bitrate(ch, g_normal_bitrate[ch]);
set_data_bitrate(ch, g_data_bitrate[ch]);
/* Rx rule setting */
Wrap_Can_SetRxRule();
/* Buffer setting */
reset_buffer(ch);
/* Global Error Interrupt setting */
REG_32W(&RCANFD.RSCFD0CFDGCTR.LONG, CAN_GCTR, REG_NONSHIFT, MASK_GCTR_INIT);
/* CANFD setting */
REG_32W(g_regtbl_ctr[ch], g_ctr_init[ch], REG_NONSHIFT, MASK_CTR_INIT);
REG_32W(g_regtbl_fdcfg[ch], g_fdcfg_init[ch], REG_NONSHIFT, MASK_FDCFG_INIT);
/* Global Test mode switch (reset->test) */
R_CAN_Control(UNUSED, GLOBAL_TEST);
/* Channel halt mode switch (reset->halt) */
R_CAN_Control(ch, CHANNEL_HALT);
/* Channel Restricted Operation Mode setting */
REG_32W(g_regtbl_ctr[ch], g_ctr_init[ch], REG_NONSHIFT, CTR_ROM);
}
static void reset_buffer(uint32_t ch)
{
/* TR FIFO */
REG_32W(g_regtbl_cfcc[ch][CAN_TX], g_cfcc_init[ch][CAN_TX], REG_NONSHIFT, MASK_CFCC_INIT);
REG_32W(g_regtbl_cfcc[ch][CAN_RX], g_cfcc_init[ch][CAN_RX], REG_NONSHIFT, MASK_CFCC_INIT);
/* RX FIFO */
REG_32W(g_regtbl_rfcc[ch], g_rfcc_init[ch], REG_NONSHIFT, MASK_RFCC_INIT);
/* RX buffer */
REG_32W(&RCANFD.RSCFD0CFDRMNB.LONG, CAN_RMNB, REG_NONSHIFT, REG_NONMASK);
/* TX buffer */
REG_32W(&RCANFD.RSCFD0CFDTMIEC0.LONG, CAN_TMIEC0, REG_NONSHIFT, REG_NONMASK);
/* TX queue */
REG_32W(g_regtbl_txqcc[ch], g_init_txqcc[ch], REG_NONSHIFT, (TXQCC_TXQDC | TXQCC_TXQIE | TXQCC_TXQIM));
/* TX history */
REG_32W(g_regtbl_thlcc[ch], g_init_thlcc[ch], REG_NONSHIFT, (THLCC_THLIE | THLCC_THLIM | THLCC_THLDTE));
}
static void get_rxrule_index(uint32_t ch, int32_t handle, uint8_t *page, uint8_t *j)
{
*page = (handle + (ch * CAN0_RX_RULE_NUM)) / RXRULE_J_MAX;
*j = (handle + (ch * CAN0_RX_RULE_NUM)) % RXRULE_J_MAX;
}
static void reconfigure_channel(uint32_t ch)
{
R_CAN_Control(UNUSED, GLOBAL_OPERATION);
R_CAN_Control(ch, CHANNEL_COM);
REG_32W(g_regtbl_cfcc[ch][CAN_TX], CFCC_CFE, REG_NONSHIFT, CFCC_CFE);
REG_32W(g_regtbl_cfcc[ch][CAN_RX], CFCC_CFE, REG_NONSHIFT, CFCC_CFE);
}
static void set_test_mode(uint32_t ch, uint32_t mode, uint32_t enable)
{
R_CAN_Control(ch, CHANNEL_HALT);
REG_32W(g_regtbl_ctr[ch], mode, CTR_CTMS_SHIFT, CTR_CTMS);
REG_32W(g_regtbl_ctr[ch], enable, CTR_CTME_SHIFT, CTR_CTME);
}
void can_init(can_t *obj, PinName rd, PinName td)
{
/* set default frequency */
can_init_freq(obj, rd, td, N_BITRATE_DEFAULT);
}
void can_init_freq(can_t *obj, PinName rd, PinName td, int hz)
{
/* 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);
/* initialize */
CPG.STBCR3.BYTE &= ~CPG_STBCR3_MSTP32;
R_CAN_PortSet(obj->ch, ENABLE_COMMON);
R_CAN_PortSet(obj->ch, ENABLE_CHANNEL);
Wrap_Can_WaitRamInitOver();
R_CAN_Control(UNUSED, GLOBAL_RESET);
RCANFD.RSCFD0CFDGRMCFG.LONG |= RCANFD_RSCFD0CFDGRMCFG_RCMC;
R_CAN_Control(obj->ch, CHANNEL_RESET);
g_normal_bitrate[obj->ch] = hz;
reset_register(obj->ch);
reconfigure_channel(obj->ch);
/* pin out the can pins */
pinmap_pinout(rd, PinMap_CAN_RD);
pinmap_pinout(td, PinMap_CAN_TD);
}
void can_free(can_t *obj)
{
/* disable CANFD clock */
CPG.STBCR3.BYTE |= CPG_STBCR3_MSTP32;
}
int can_frequency(can_t *obj, int f)
{
int retval = 0;
/* less than normal bitrate */
if (f <= N_BITRATE_MAX) {
/* set normal bit rate */
R_CAN_Control(obj->ch, CHANNEL_RESET);
g_normal_bitrate[obj->ch] = f;
set_normal_bitrate(obj->ch, g_normal_bitrate[obj->ch]);
reconfigure_channel(obj->ch);
retval = 1;
}
return retval;
}
int can_write(can_t *obj, CAN_Message msg, int cc)
{
can_frame_t frame;
/* CAN frame */
frame.ID = msg.id; // Message ID
frame.THDSE = 0;
frame.RTR = msg.type; // 0:CANData, 1:CANRemote
frame.IDE = msg.format; // 0:Standard ID, 1:Extend ID
frame.LBL = 0;
frame.DLC = msg.len; // Data length
frame.FDSTS = 1;
frame.BRS = 1;
frame.ESI = 0;
if (R_CAN_OK != R_CAN_TxSet(TX_TRFIFO, TX_TRFIFO_INDEX(obj->ch), &frame, (uint32_t *)&msg.data[0])) {
return 0;
}
if (R_CAN_OK != R_CAN_Tx(TX_TRFIFO, TX_TRFIFO_INDEX(obj->ch), ENABLE)) {
return 0;
}
return 1;
}
int can_read(can_t *obj, CAN_Message *msg, int handle)
{
uint32_t page_index = 0;
uint8_t received_msg_num = 0;
uint8_t msg_cnt;
if (R_CAN_OK != R_CAN_RxPoll(RX_TRFIFO, RX_TRFIFO_INDEX(obj->ch))) {
return 0;
}
if (R_CAN_OK != R_CAN_RxRead(RX_TRFIFO, RX_TRFIFO_INDEX(obj->ch), (uint32_t *)&rx_buf[0])) {
return 0;
}
/* number of received message */
received_msg_num = rx_buf[0];
for (msg_cnt = 0; msg_cnt < received_msg_num; msg_cnt++) {
page_index = msg_cnt * 19;
/* IDE 0:Standard ID, 1:Extend ID */
msg->format = (CANFormat)(rx_buf[page_index + 1] >> 31);
/* RTR/RRS : Data or Remote */
msg->type = (CANType)((rx_buf[page_index + 1] >> 30) & 0x1);
/* ID : Standard ID(b10-b0), Extend ID(b28-b0) */
msg->id = (rx_buf[page_index + 1] & 0x1FFFFFFF);
/* data Length */
msg->len = dlc_to_length[(uint8_t)(rx_buf[page_index + 2] >> 28)];
/* received data */
msg->data[0] = (uint8_t)(rx_buf[page_index + 4] & 0x000000FF);
msg->data[1] = (uint8_t)(rx_buf[page_index + 4] >> 8) & 0x000000FF;
msg->data[2] = (uint8_t)(rx_buf[page_index + 4] >> 16) & 0x000000FF;
msg->data[3] = (uint8_t)(rx_buf[page_index + 4] >> 24) & 0x000000FF;
msg->data[4] = (uint8_t)(rx_buf[page_index + 5] & 0x000000FF);
msg->data[5] = (uint8_t)(rx_buf[page_index + 5] >> 8) & 0x000000FF;
msg->data[6] = (uint8_t)(rx_buf[page_index + 5] >> 16) & 0x000000FF;
msg->data[7] = (uint8_t)(rx_buf[page_index + 5] >> 24) & 0x000000FF;
}
return 1; /* message arrived */
}
int can_mode(can_t *obj, CanMode mode)
{
int retval = 1;
switch (mode) {
case MODE_RESET:
/* set to reset mode */
R_CAN_Control(UNUSED, GLOBAL_RESET);
R_CAN_Control(obj->ch, CHANNEL_RESET);
break;
case MODE_NORMAL:
/* disable test mode */
set_test_mode(obj->ch, STD_TEST, TEST_DISABLE);
reconfigure_channel(obj->ch);
break;
case MODE_SILENT:
/* enable listen only mode */
set_test_mode(obj->ch, TEST_LISTEN_ONLY, TEST_ENABLE);
reconfigure_channel(obj->ch);
break;
case MODE_TEST_LOCAL:
/* enable self test mode 0 */
set_test_mode(obj->ch, EXT_LOOPBACK, TEST_ENABLE);
reconfigure_channel(obj->ch);
break;
case MODE_TEST_GLOBAL:
/* enable Inter-Channel Communication Test */
R_CAN_Control(UNUSED, GLOBAL_TEST);
REG_32W(&RCANFD.RSCFD0CFDGTSTCFG.LONG, TEST_ENABLE, GTSTCFG_C0ICBCE_SHIFT, GTSTCFG_C0ICBCE);
REG_32W(&RCANFD.RSCFD0CFDGTSTCFG.LONG, TEST_ENABLE, GTSTCFG_C1ICBCE_SHIFT, GTSTCFG_C1ICBCE);
REG_32W(&RCANFD.RSCFD0CFDGTSTCTR.LONG, TEST_ENABLE, GTSTCTR_ICBCTME_SHIFT, GTSTCTR_ICBCTME);
/* enable standard test */
set_test_mode(CH_0, STD_TEST, TEST_ENABLE);
set_test_mode(CH_1, STD_TEST, TEST_ENABLE);
reconfigure_channel(CH_0);
reconfigure_channel(CH_1);
break;
case MODE_TEST_SILENT:
/* enable self test mode 1 */
set_test_mode(obj->ch, INT_LOOPBACK, TEST_ENABLE);
reconfigure_channel(obj->ch);
break;
default:
retval = 0;
break;
}
return retval;
}
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle)
{
uint8_t page_index;
uint8_t j_index;
if ((CH_0 == obj->ch) && (handle >= CAN0_RX_RULE_NUM)) {
return 0;
}
if ((CH_1 == obj->ch) && (handle >= CAN1_RX_RULE_NUM)) {
return 0;
}
/* set to reset mode */
R_CAN_Control(UNUSED, GLOBAL_RESET);
R_CAN_Control(obj->ch, CHANNEL_RESET);
/* write enable (RSCFD0CFDGAFLECTR.AFLDAE) */
RCANFD.RSCFD0CFDGAFLECTR.LONG |= RCANFD_RSCFD0CFDGAFLECTR_AFLDAE;
/* set page number */
get_rxrule_index(obj->ch, handle, &page_index, &j_index);
REG_32W(&RCANFD.RSCFD0CFDGAFLECTR.LONG, page_index, REG_NONSHIFT, 0x0000001F);
/* set CAN format */
REG_32W(g_regtbl_gaflid[j_index], format, 31, 0x80000000);
if (CANExtended == format) {
REG_32W(g_regtbl_gaflid[j_index], (id & 0x1FFFFFFF), REG_NONSHIFT, 0x1FFFFFFF);
} else {
REG_32W(g_regtbl_gaflid[j_index], (id & 0x000007FF), REG_NONSHIFT, 0x000007FF);
}
/* set masks(IDE, RTR, ID) */
if (CANAny == format) {
/* no masks */
REG_32W(g_regtbl_gaflm[j_index], 0, REG_NONSHIFT, REG_NONMASK);
} else {
/* IDE and ID */
REG_32W(g_regtbl_gaflm[j_index], (0x80000000 | mask), REG_NONSHIFT, REG_NONMASK);
}
/* set GAFLFDP1_j.GAFLFDP */
if (CH_0 == obj->ch) {
REG_32W(g_regtbl_gaflp1[j_index], 0x00000200, REG_NONSHIFT, REG_NONMASK); // CH0:use TRFIFO1
} else {
REG_32W(g_regtbl_gaflp1[j_index], 0x00001000, REG_NONSHIFT, REG_NONMASK); // CH1:use TRFIFO4
}
/* write disable (RSCFD0CFDGAFLECTR.AFLDAE) */
RCANFD.RSCFD0CFDGAFLECTR.LONG &= ~RCANFD_RSCFD0CFDGAFLECTR_AFLDAE;
reconfigure_channel(obj->ch);
return 1;
}
void can_reset(can_t *obj)
{
R_CAN_Control(UNUSED, GLOBAL_RESET);
R_CAN_Control(obj->ch, CHANNEL_RESET);
reset_register(obj->ch);
reconfigure_channel(obj->ch);
}
unsigned char can_rderror(can_t *obj)
{
return (unsigned char)(*g_regtbl_sts[obj->ch] >> RCANFD_RSCFD0CFDC0STS_REC_SHIFT);
}
unsigned char can_tderror(can_t *obj)
{
return (unsigned char)(*g_regtbl_sts[obj->ch] >> RCANFD_RSCFD0CFDC0STS_TEC_SHIFT);
}
void can_monitor(can_t *obj, int silent)
{
if (silent) {
set_test_mode(obj->ch, TEST_LISTEN_ONLY, TEST_ENABLE);
} else {
set_test_mode(obj->ch, STD_TEST, TEST_DISABLE);
}
reconfigure_channel(obj->ch);
}
const PinMap *can_rd_pinmap()
{
return PinMap_CAN_TD;
}
const PinMap *can_td_pinmap()
{
return PinMap_CAN_RD;
}
#endif // DEVICE_CAN