Re: About the CAN controller.
Posted: Sun Dec 25, 2016 1:17 am
Hi guys,
Im trying to implement a CAN driver based on eerimoq's implementation, using ESP-IDF on a AI ESP-32S.
So far, there are not too much things that could go wrong... at least I thought so... I can't get any interrupts from the CAN module. The transceiver works fine with my other micros.
The plan is to go with GPIO32 for TX and GPIO33 for RX.
Im new to the ESP32. I have seen some strange mapping for the GPIOs and the pins on the boards. I hope GPIO33 is mapped to IO33 on the ESP-32S?
I have tried to implement eerimoq's approach with magic numbers, as well using the inbuild gpio API. No success
Im a bit confused about the IO Multiplexer, because the defines in the code are not documented
I use esp-idf-template as base project (empty, besides CAN). Maybe I need to configure some dependent modules?
Thanks for reading
Thomas
Im trying to implement a CAN driver based on eerimoq's implementation, using ESP-IDF on a AI ESP-32S.
So far, there are not too much things that could go wrong... at least I thought so... I can't get any interrupts from the CAN module. The transceiver works fine with my other micros.
The plan is to go with GPIO32 for TX and GPIO33 for RX.
Im new to the ESP32. I have seen some strange mapping for the GPIOs and the pins on the boards. I hope GPIO33 is mapped to IO33 on the ESP-32S?
I have tried to implement eerimoq's approach with magic numbers, as well using the inbuild gpio API. No success
Im a bit confused about the IO Multiplexer, because the defines in the code are not documented
I use esp-idf-template as base project (empty, besides CAN). Maybe I need to configure some dependent modules?
Thanks for reading
Thomas
Code: Select all
#define ESP32_CAN ((volatile esp32_can_t *)0x3ff6b000)
#define CAN_SPEED_1000KBPS (ESP32_CAN_BTIM0_BRP(0x6) | ESP32_CAN_BTIM0_SJW(3) | ((ESP32_CAN_BTIM1_TSEG1(2) | ESP32_CAN_BTIM1_TSEG2(3) | ESP32_CAN_BTIM1_SAM) << 8))
#define ESP32_CAN_OCTRL_MODE_NORMAL BIT(1)
/** \brief clock control bitfields */
typedef struct {
unsigned int RR:1; /**< \brief CR.0 Reset Request */
unsigned int RIE:1; /**< \brief CR.1 Receive Interrupt Enable */
unsigned int TIE:1; /**< \brief CR.2 Transmit Interrupt Enable */
unsigned int EIE:1; /**< \brief CR.3 Error Interrupt Enable */
unsigned int OIE:1; /**< \brief CR.4 Overrun Interrupt Enable */
unsigned int reserved_24:24; /**< \brief \internal Reserved */
} _CAN_CR_BITS;
/** \brief clock control register. */
typedef union
{
/** \brief Unsigned access */
unsigned int U;
/** \brief Signed access */
signed int I;
/** \brief Bitfield access */
_CAN_CR_BITS B;
} _CAN_CR_t;
typedef struct {
uint32_t MODE;
uint32_t COMMAND;
uint32_t STATUS;
uint32_t INT;
uint32_t INTE;
uint32_t RESERVED0;
uint32_t BTIM0;
uint32_t BTIM1;
uint32_t OCTRL;
uint32_t RESERVED1[2];
uint32_t ALC;
uint32_t ECC;
uint32_t EWL;
uint32_t RXERR;
uint32_t TXERR;
union {
struct {
uint32_t CODE[4];
uint32_t MASK[4];
uint32_t RESERVED2[5];
} ACC;
struct {
uint32_t FRAME_INFO;
uint32_t ID_DATA[12];
} TX_RX;
} U;
uint32_t RMC;
uint32_t RBSA;
uint32_t CDIV;
uint32_t IRAM[2];
}esp32_can_t;
static void CAN_isr(void *arg_p){
ESP_LOGI("CAN", "ISR");
}
int CAN_start(){
volatile esp32_can_t *p_regs=ESP32_CAN;
volatile uint16_t test=0;
/* Enable the CAN hardware. */
SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN);
CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST);
/* Configure TX pin in the GPIO matrix and IO MUX. */
gpio_set_direction(GPIO_NUM_32,GPIO_MODE_OUTPUT);
gpio_matrix_out(GPIO_NUM_32,CAN_TX_IDX,0,0);
/* Configure RX pin in the GPIO matrix and IO MUX. */
gpio_set_direction(GPIO_NUM_33,GPIO_MODE_INPUT);
gpio_matrix_in(GPIO_NUM_33,CAN_RX_IDX,0);
// ESP32_GPIO->FUNC_IN_SEL_CFG[ESP32_PERIPHERAL_SIGNAL_CAN_RX] = 33;
// ESP32_GPIO->PIN[33] = 0;
// ESP32_IO_MUX->PIN[7] = (ESP32_IO_MUX_PIN_MCU_SEL_GPIO| ESP32_IO_MUX_PIN_FUNC_IE);
// + /* Configure RX pin in the GPIO matrix and IO MUX. */
// + ESP32_GPIO->FUNC_IN_SEL_CFG[ESP32_PERIPHERAL_SIGNAL_CAN_RX] = rx_pin_p->id;
// + ESP32_GPIO->PIN[rx_pin_p->id] = 0;
// + ESP32_IO_MUX->PIN[rx_pin_p->iomux] = (ESP32_IO_MUX_PIN_MCU_SEL_GPIO
// + | ESP32_IO_MUX_PIN_FUNC_IE);
/* Clock configuration. */
p_regs->CDIV = BIT(7);
/* Bus speed configuration. */
p_regs->BTIM0 = LO8(CAN_cfg.speed);
p_regs->BTIM1 = HI8(CAN_cfg.speed);
/* Enable all interrupts. */
p_regs->INTE = 0xff;
/* Accept all frames. */
p_regs->U.ACC.CODE[0] = 0;
p_regs->U.ACC.CODE[1] = 0;
p_regs->U.ACC.CODE[2] = 0;
p_regs->U.ACC.CODE[3] = 0;
p_regs->U.ACC.MASK[0] = 0xff;
p_regs->U.ACC.MASK[1] = 0xff;
p_regs->U.ACC.MASK[2] = 0xff;
p_regs->U.ACC.MASK[3] = 0xff;
p_regs->OCTRL = (ESP32_CAN_OCTRL_MODE_NORMAL);
/* Clear error counters and error code capture */
p_regs->TXERR = 0;
p_regs->RXERR = 0;
(void)p_regs->ECC;
/* Clear interrupt flags by reading the interrupt status register. */
(void)p_regs->INT;
/* Install the interrupt handler. */
xt_set_interrupt_handler(ESP32_CPU_INTR_CAN_NUM, CAN_isr, NULL);
xt_ints_on(BIT(ESP32_CPU_INTR_CAN_NUM));
/* Map the CAN peripheral interrupt to the CAN CPU interrupt. */
intr_matrix_set(xPortGetCoreID(), ESP32_INTR_SOURCE_CAN, ESP32_CPU_INTR_CAN_NUM);
/* Set chip to normal mode. */
p_regs->MODE = 0;
return (0);
}