From 96b8646059a776ec29f736c7379cd30795f9b5fa Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 26 Sep 2019 22:29:04 +0200 Subject: [PATCH 001/180] first commit --- ports/esp32/Makefile | 2 + ports/esp32/machine_can.c | 133 +++++++++++++++++++++++++++++++++++++ ports/esp32/machine_can.h | 94 ++++++++++++++++++++++++++ ports/esp32/modmachine.c | 3 + ports/esp32/modmachine.h | 1 + ports/esp32/mpconfigport.h | 1 + 6 files changed, 234 insertions(+) create mode 100644 ports/esp32/machine_can.c create mode 100644 ports/esp32/machine_can.h diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 919a047eb6a87..ef4d598d639b4 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -161,6 +161,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/app_update/include INC_ESPCOMP += -I$(ESPCOMP)/pthread/include INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include +#INC_ESPCOMP += -I$(ESPCOMP)/can/include ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include @@ -266,6 +267,7 @@ SRC_C = \ machine_i2c.c \ machine_pwm.c \ machine_uart.c \ + machine_can.c \ modmachine.c \ modnetwork.c \ network_lan.c \ diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c new file mode 100644 index 0000000000000..5652079b5c2a3 --- /dev/null +++ b/ports/esp32/machine_can.c @@ -0,0 +1,133 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/mperrno.h" + +#include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h + +#include "driver/can.h" +#include "machine_can.h" + +#if MICROPY_HW_ENABLE_CAN + +STATIC const mp_obj_type_t machine_hw_can_type; +STATIC machine_hw_can_obj_t machine_hw_can_obj; + +bool can_init(machine_hw_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, CAN_speed_t baudrate, uint32_t mode) { + + can_driver_install( + CAN_GENERAL_CONFIG_DEFAULT(rx, rx, mode), + CAN_TIMING_CONFIG_1MBITS(), + CAN_FILTER_CONFIG_ACCEPT_ALL() + ); + + double __tq; //Time quantum + + //enable module + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST); + + //configure TX pin + gpio_set_level(tx, 1); + gpio_set_direction(tx,GPIO_MODE_OUTPUT); + gpio_matrix_out(tx,CAN_TX_IDX,0,0); + gpio_pad_select_gpio(tx); + + //configure RX pin + gpio_set_direction(rx,GPIO_MODE_INPUT); + gpio_matrix_in(rx,CAN_RX_IDX,0); + gpio_pad_select_gpio(rx); + + //set to PELICAN mode #FIXME: ability to change the mode to LOOPBACK + MODULE_CAN->CDR.B.CAN_M = 0x1; + + //synchronization jump width is the same for all baud rates + MODULE_CAN->BTR0.B.SJW = 0x1; + + //TSEG2 is the same for all baud rates + MODULE_CAN->BTR1.B.TSEG2 = 0x1; + + //select time quantum and set TSEG1 + switch(baudrate){ + case CAN_SPEED_1000KBPS: + MODULE_CAN->BTR1.B.TSEG1 = 0x4; + __tq = 0.125; + break; + + case CAN_SPEED_800KBPS: + MODULE_CAN->BTR1.B.TSEG1 =0x6; + __tq = 0.125; + break; + default: + MODULE_CAN->BTR1.B.TSEG1 = 0xc; + __tq = ((float)1000/baudrate) / 16; + } + + //set baud rate prescaler FIXME: APB_CLK_FREQ in soc/soc.h + MODULE_CAN->BTR0.B.BRP=(uint8_t)round((((APB_CLK_FREQ * __tq) / 2) - 1)/1000000)-1; + + /* Set sampling + * 1 -> triple; the bus is sampled three times; recommended for low/medium speed buses (class A and B) where filtering spikes on the bus line is beneficial + * 0 -> single; the bus is sampled once; recommended for high speed buses (SAE class C)*/ + MODULE_CAN->BTR1.B.SAM =0x1; + + //enable all interrupts + MODULE_CAN->IER.U = 0xff; + + //no acceptance filtering, as we want to fetch all messages + MODULE_CAN->MBX_CTRL.ACC.CODE[0] = 0; + MODULE_CAN->MBX_CTRL.ACC.CODE[1] = 0; + MODULE_CAN->MBX_CTRL.ACC.CODE[2] = 0; + MODULE_CAN->MBX_CTRL.ACC.CODE[3] = 0; + MODULE_CAN->MBX_CTRL.ACC.MASK[0] = 0xff; + MODULE_CAN->MBX_CTRL.ACC.MASK[1] = 0xff; + MODULE_CAN->MBX_CTRL.ACC.MASK[2] = 0xff; + MODULE_CAN->MBX_CTRL.ACC.MASK[3] = 0xff; + + //set to normal mode + MODULE_CAN->OCR.B.OCMODE=__CAN_OC_NOM; + + //clear error counters + MODULE_CAN->TXERR.U = 0; + MODULE_CAN->RXERR.U = 0; + (void)MODULE_CAN->ECC; + + //clear interrupt flags + (void)MODULE_CAN->IR.U; + + //install CAN ISR + esp_intr_alloc(ETS_CAN_INTR_SOURCE,0,CAN_isr,NULL,NULL); + + //Showtime. Release Reset Mode. + MODULE_CAN->MOD.B.RM = 0; + + return 0; +} + +int can_deinit(machine_hw_can_obj_t *self){ + return can_driver_uninstall(); +} + +#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h new file mode 100644 index 0000000000000..1793133a1da82 --- /dev/null +++ b/ports/esp32/machine_can.h @@ -0,0 +1,94 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ESP32_CAN_H +#define MICROPY_INCLUDED_ESP32_CAN_H + +#if MICROPY_HW_ENABLE_CAN + +typedef enum { + CAN_SPEED_100KBPS=100, /**< \brief CAN Node runs at 100kBit/s. */ + CAN_SPEED_125KBPS=125, /**< \brief CAN Node runs at 125kBit/s. */ + CAN_SPEED_250KBPS=250, /**< \brief CAN Node runs at 250kBit/s. */ + CAN_SPEED_500KBPS=500, /**< \brief CAN Node runs at 500kBit/s. */ + CAN_SPEED_800KBPS=800, /**< \brief CAN Node runs at 800kBit/s. */ + CAN_SPEED_1000KBPS=1000 /**< \brief CAN Node runs at 1000kBit/s. */ +}CAN_speed_t; + +enum { + CAN_STATE_STOPPED, + CAN_STATE_ERROR_ACTIVE, + CAN_STATE_ERROR_WARNING, + CAN_STATE_ERROR_PASSIVE, + CAN_STATE_BUS_OFF, +}; + +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + + + +/** \brief CAN configuration structure */ +typedef struct { + CAN_speed_t speed; /**< \brief CAN speed. */ + gpio_num_t tx_pin_id; /**< \brief TX pin. */ + gpio_num_t rx_pin_id; /**< \brief RX pin. */ + QueueHandle_t rx_queue; /**< \brief Handler to FreeRTOS RX queue. */ +}CAN_device_t; + +typedef struct _machine_hw_can_obj_t { + mp_obj_base_t base; + mp_obj_t rxcallback0; + mp_obj_t rxcallback1; + mp_uint_t can_id : 8; + bool is_enabled : 1; + bool extframe : 1; + byte rx_state0; + byte rx_state1; + uint16_t num_error_warning; + uint16_t num_error_passive; + uint16_t num_bus_off; + CAN_HandleTypeDef can; +} esp32_can_obj_t; + +extern const mp_obj_type_t machine_can_type; + +//void can_init0(void); #TODO: +//void can_deinit_all(void); #TODO: +bool can_init(machine_hw_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, CAN_speed_t baudrate, uint32_t mode); +void can_deinit(machine_hw_can_obj_t *self); + +void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank); +int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms); +HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); +void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason); + +#endif // MICROPY_HW_ENABLE_CAN + +#endif // MICROPY_INCLUDED_ESP32_CAN_H diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 0c803d0960d18..b8ba1745c4a6d 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -258,6 +258,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #if MICROPY_HW_ENABLE_CAN + { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, + #endif // Reset reasons { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index ca1776d8bf721..9e52deb99d04c 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -18,6 +18,7 @@ extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_pwm_type; extern const mp_obj_type_t machine_hw_spi_type; extern const mp_obj_type_t machine_uart_type; +extern const mp_obj_type_t machine_can_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 1c0d8700facda..66d3b5b1270fa 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -150,6 +150,7 @@ #define MICROPY_PY_MACHINE_SPI_LSB (1) #define MICROPY_PY_MACHINE_SPI_MAKE_NEW machine_hw_spi_make_new #define MICROPY_HW_ENABLE_SDCARD (1) +#define MICROPY_HW_ENABLE_CAN (1) #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly #define MICROPY_PY_USSL (1) From 4b06c23d083647726f84deaa8875c4d0ab3b8c61 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sat, 28 Sep 2019 18:26:39 +0200 Subject: [PATCH 002/180] Enabled module --- ports/esp32/Makefile | 2 +- ports/esp32/machine_can.c | 129 ++++++++++---------------------------- ports/esp32/machine_can.h | 60 +++++------------- ports/esp32/modmachine.c | 4 +- 4 files changed, 52 insertions(+), 143 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index ef4d598d639b4..a79daf79a034f 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -161,7 +161,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/app_update/include INC_ESPCOMP += -I$(ESPCOMP)/pthread/include INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include -#INC_ESPCOMP += -I$(ESPCOMP)/can/include +INC_ESPCOMP += -I$(ESPCOMP)/can/include ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5652079b5c2a3..467d7b4e5a85a 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -21,113 +21,52 @@ * THE SOFTWARE. */ +#include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" +#include +//Headers of ESP-IDF library #include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h - #include "driver/can.h" +#include "esp_err.h" +#include "esp_log.h" + #include "machine_can.h" #if MICROPY_HW_ENABLE_CAN -STATIC const mp_obj_type_t machine_hw_can_type; -STATIC machine_hw_can_obj_t machine_hw_can_obj; - -bool can_init(machine_hw_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, CAN_speed_t baudrate, uint32_t mode) { - - can_driver_install( - CAN_GENERAL_CONFIG_DEFAULT(rx, rx, mode), - CAN_TIMING_CONFIG_1MBITS(), - CAN_FILTER_CONFIG_ACCEPT_ALL() - ); - - double __tq; //Time quantum - - //enable module - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST); - - //configure TX pin - gpio_set_level(tx, 1); - gpio_set_direction(tx,GPIO_MODE_OUTPUT); - gpio_matrix_out(tx,CAN_TX_IDX,0,0); - gpio_pad_select_gpio(tx); - - //configure RX pin - gpio_set_direction(rx,GPIO_MODE_INPUT); - gpio_matrix_in(rx,CAN_RX_IDX,0); - gpio_pad_select_gpio(rx); - - //set to PELICAN mode #FIXME: ability to change the mode to LOOPBACK - MODULE_CAN->CDR.B.CAN_M = 0x1; - - //synchronization jump width is the same for all baud rates - MODULE_CAN->BTR0.B.SJW = 0x1; - - //TSEG2 is the same for all baud rates - MODULE_CAN->BTR1.B.TSEG2 = 0x1; - - //select time quantum and set TSEG1 - switch(baudrate){ - case CAN_SPEED_1000KBPS: - MODULE_CAN->BTR1.B.TSEG1 = 0x4; - __tq = 0.125; - break; - - case CAN_SPEED_800KBPS: - MODULE_CAN->BTR1.B.TSEG1 =0x6; - __tq = 0.125; - break; - default: - MODULE_CAN->BTR1.B.TSEG1 = 0xc; - __tq = ((float)1000/baudrate) / 16; - } - - //set baud rate prescaler FIXME: APB_CLK_FREQ in soc/soc.h - MODULE_CAN->BTR0.B.BRP=(uint8_t)round((((APB_CLK_FREQ * __tq) / 2) - 1)/1000000)-1; - - /* Set sampling - * 1 -> triple; the bus is sampled three times; recommended for low/medium speed buses (class A and B) where filtering spikes on the bus line is beneficial - * 0 -> single; the bus is sampled once; recommended for high speed buses (SAE class C)*/ - MODULE_CAN->BTR1.B.SAM =0x1; - - //enable all interrupts - MODULE_CAN->IER.U = 0xff; - - //no acceptance filtering, as we want to fetch all messages - MODULE_CAN->MBX_CTRL.ACC.CODE[0] = 0; - MODULE_CAN->MBX_CTRL.ACC.CODE[1] = 0; - MODULE_CAN->MBX_CTRL.ACC.CODE[2] = 0; - MODULE_CAN->MBX_CTRL.ACC.CODE[3] = 0; - MODULE_CAN->MBX_CTRL.ACC.MASK[0] = 0xff; - MODULE_CAN->MBX_CTRL.ACC.MASK[1] = 0xff; - MODULE_CAN->MBX_CTRL.ACC.MASK[2] = 0xff; - MODULE_CAN->MBX_CTRL.ACC.MASK[3] = 0xff; - - //set to normal mode - MODULE_CAN->OCR.B.OCMODE=__CAN_OC_NOM; - - //clear error counters - MODULE_CAN->TXERR.U = 0; - MODULE_CAN->RXERR.U = 0; - (void)MODULE_CAN->ECC; - - //clear interrupt flags - (void)MODULE_CAN->IR.U; - - //install CAN ISR - esp_intr_alloc(ETS_CAN_INTR_SOURCE,0,CAN_isr,NULL,NULL); - - //Showtime. Release Reset Mode. - MODULE_CAN->MOD.B.RM = 0; - - return 0; +const mp_obj_type_t machine_can_type; + +void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t baudrate, uint32_t mode) { + static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); + static const can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS(); + //Set TX queue length to 0 due to listen only mode + can_general_config_t g_config = {.mode = mode, + .tx_io = tx, .rx_io = rx, + .clkout_io = CAN_IO_UNUSED, .bus_off_io = CAN_IO_UNUSED, + .tx_queue_len = 0, .rx_queue_len = 5, + .alerts_enabled = CAN_ALERT_NONE, + .clkout_divider = 0}; + ESP_ERROR_CHECK(can_driver_install(&g_config, &t_config, &f_config)); + ESP_LOGI("CAN", "Driver installed"); + ESP_ERROR_CHECK(can_start()); + ESP_LOGI("CAN", "Driver started"); } -int can_deinit(machine_hw_can_obj_t *self){ - return can_driver_uninstall(); +/*void machine_can_trasmit(machine_hw_can_obj_t *self, uint32_t address, size_t length, mp_machine_can_buf_t *data) +{ + can_message_t tx_msg = {.data_length_code = length, .identifier = address, .flags = CAN_MSG_FLAG_SELF}; + for (uint8_t i=0; i Date: Sun, 29 Sep 2019 12:07:47 +0200 Subject: [PATCH 003/180] Stable basic code for module loading in Python --- ports/esp32/machine_can.c | 26 ++++++++++++------ ports/esp32/machine_can.h | 57 +++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 467d7b4e5a85a..dac51bb1b9459 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -23,6 +23,7 @@ #include "py/obj.h" #include "py/runtime.h" +#include "py/builtin.h" #include "py/mphal.h" #include "py/mperrno.h" #include @@ -35,12 +36,19 @@ #include "machine_can.h" -#if MICROPY_HW_ENABLE_CAN +//#if MICROPY_HW_ENABLE_CAN -const mp_obj_type_t machine_can_type; +const machine_hw_can_obj_t can_default = {.tx=6, .rx=4}; -void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t baudrate, uint32_t mode) { - static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); +STATIC const mp_obj_type_t machine_hw_can_type; //FIXME: da popolare + +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_hw_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "CAN(tx=%u, rx=%u)", self->tx, self->rx); +} + +STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in) { + /*static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); static const can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS(); //Set TX queue length to 0 due to listen only mode can_general_config_t g_config = {.mode = mode, @@ -52,9 +60,11 @@ void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t ba ESP_ERROR_CHECK(can_driver_install(&g_config, &t_config, &f_config)); ESP_LOGI("CAN", "Driver installed"); ESP_ERROR_CHECK(can_start()); - ESP_LOGI("CAN", "Driver started"); + ESP_LOGI("CAN", "Driver started");*/ + return mp_const_none; } + /*void machine_can_trasmit(machine_hw_can_obj_t *self, uint32_t address, size_t length, mp_machine_can_buf_t *data) { can_message_t tx_msg = {.data_length_code = length, .identifier = address, .flags = CAN_MSG_FLAG_SELF}; @@ -62,11 +72,11 @@ void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t ba ESP_ERROR_CHECK(can_transmit(&tx_msg, portMAX_DELAY)); }*/ -void machine_can_deinit(machine_can_obj_t *self){ +/*void machine_can_deinit(machine_can_obj_t *self){ ESP_ERROR_CHECK(can_stop()); ESP_LOGI("CAN", "Driver stopped"); ESP_ERROR_CHECK(can_driver_uninstall()); ESP_LOGI("CAN", "Driver uninstalled"); -} +}*/ -#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file +//#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3b20ea5a3929e..5cccb97ba7e97 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -30,37 +30,34 @@ #include "py/obj.h" - -typedef enum _rx_state_t { - RX_STATE_FIFO_EMPTY = 0, - RX_STATE_MESSAGE_PENDING, - RX_STATE_FIFO_FULL, - RX_STATE_FIFO_OVERFLOW, -} rx_state_t; - typedef struct _machine_can_obj_t { mp_obj_base_t base; - mp_obj_t rxcallback; - gpio_num_t tx; - gpio_num_t rx; -} machine_can_obj_t; - -extern const mp_obj_type_t machine_can_type; - -//extern const mp_obj_type_t machine_can_type; -void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t baudrate, uint32_t mode); -void can_deinit(machine_can_obj_t *self); - -//void can_trasmit(uint32_t address, byte data[], uint8_t length); - -//void can_init0(void); #TODO: -//void can_deinit_all(void); #TODO: - - -/*void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank); -int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms); -HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); -void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason); -*/ + uint8_t tx; + uint8_t rx; +} machine_hw_can_obj_t; + +//Functions signature definition +STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in); +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); + +//Python function declarations +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_init_obj, machine_hw_can_init); + +//Python objects list declaration +STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(125) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(250) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(500) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(1000) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); + +//Python object definition +const mp_obj_type_t machine_can_type = { + { &mp_type_type }, + .name = MP_QSTR_CAN, + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, +}; #endif // MICROPY_INCLUDED_ESP32_CAN_H From 263338c4cdc38895f590b2bd2f5442ba6a8468d8 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 18:52:25 +0200 Subject: [PATCH 004/180] Full initialization and dummy write --- ports/esp32/machine_can.c | 222 +++++++++++++++++++++++++++++++++----- ports/esp32/machine_can.h | 74 +++++++++++-- 2 files changed, 260 insertions(+), 36 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index dac51bb1b9459..6077f4ac48a7b 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -38,30 +38,78 @@ //#if MICROPY_HW_ENABLE_CAN -const machine_hw_can_obj_t can_default = {.tx=6, .rx=4}; +// singleton CAN device object +machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), + .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), + .timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()), + .initialized = false}; + +STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; -STATIC const mp_obj_type_t machine_hw_can_type; //FIXME: da popolare -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_hw_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "CAN(tx=%u, rx=%u)", self->tx, self->rx); + + + +STATIC can_state_t _machine_hw_can_get_state(){ + can_status_info_t status; + ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + return status.state; } -STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in) { - /*static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); - static const can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS(); - //Set TX queue length to 0 due to listen only mode - can_general_config_t g_config = {.mode = mode, - .tx_io = tx, .rx_io = rx, - .clkout_io = CAN_IO_UNUSED, .bus_off_io = CAN_IO_UNUSED, - .tx_queue_len = 0, .rx_queue_len = 5, - .alerts_enabled = CAN_ALERT_NONE, - .clkout_divider = 0}; - ESP_ERROR_CHECK(can_driver_install(&g_config, &t_config, &f_config)); - ESP_LOGI("CAN", "Driver installed"); - ESP_ERROR_CHECK(can_start()); - ESP_LOGI("CAN", "Driver started");*/ - return mp_const_none; +STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in){ + can_status_info_t status; + ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + return mp_obj_new_int(status.msgs_to_rx); +} + +STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ + can_status_info_t status; + ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + return mp_obj_new_int(status.msgs_to_tx); +} + +STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) { + int value = mp_obj_get_int(address); + if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); + + if (_machine_hw_can_get_state()==CAN_STATE_RUNNING){ + //TODO: Check if queue is full + can_message_t tx_msg = {.data_length_code = 2, .identifier = 0x86, .flags = CAN_MSG_FLAG_SELF}; + tx_msg.data[0] = 0x58; + tx_msg.data[1] = 0x86; + ESP_ERROR_CHECK(can_transmit(&tx_msg, 100)); //FIXME: remove ESP_ERROR_CHECK + return machine_hw_can_get_rx_waiting_messages(self_in); + }else{ + ESP_LOGW(DEVICE_NAME, "Unable to send the message"); + return MP_OBJ_NEW_SMALL_INT(-1); + } +} + +STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in) { + can_message_t rx_message; + switch(can_receive(&rx_message, 1)){ + case ESP_ERR_TIMEOUT: + ESP_LOGW(DEVICE_NAME, "Time-out"); break; + case ESP_ERR_INVALID_ARG: + ESP_LOGE(DEVICE_NAME, "Invalid Args"); break; + case ESP_ERR_INVALID_STATE: + ESP_LOGW(DEVICE_NAME, "Invalid State"); break; + case ESP_OK: + return MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + }; + return MP_OBJ_NEW_SMALL_INT(-1); + +} + +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->config->initialized){ + mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%u)", self->config->general->tx_io, self->config->general->rx_io, + self->config->baudrate, self->config->general->mode); + }else{ + mp_printf(print, "CAN Device is not initialized"); + } + } @@ -72,11 +120,133 @@ STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in) { ESP_ERROR_CHECK(can_transmit(&tx_msg, portMAX_DELAY)); }*/ -/*void machine_can_deinit(machine_can_obj_t *self){ - ESP_ERROR_CHECK(can_stop()); - ESP_LOGI("CAN", "Driver stopped"); - ESP_ERROR_CHECK(can_driver_uninstall()); - ESP_LOGI("CAN", "Driver uninstalled"); -}*/ +// CAN(...) No argument to get the object +// Any argument will be used to init the device through init function +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args){ + const machine_can_obj_t *self = &machine_can_obj; + + if (n_args > 0 || n_kw > 0) { + if (self->config->initialized) { + // The caller is requesting a reconfiguration of the hardware + // this can only be done if the hardware is in init mode + ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); + machine_hw_can_deinit(&self); + } + //TODO: implement callback + /*self->rxcallback0 = mp_const_none; + self->rxcallback1 = mp_const_none; + self->rx_state0 = RX_STATE_FIFO_EMPTY; + self->rx_state1 = RX_STATE_FIFO_EMPTY;*/ + + // start the peripheral + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_hw_can_init_helper(self, n_args, args, &kw_args); + } + return MP_OBJ_FROM_PTR(self); +} + +// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + const machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized){ + ESP_LOGW(DEVICE_NAME, "Device is already initialized"); + return mp_const_false; + } + return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); +} + +// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + }; + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + //Check if device was already configured + if (self->config->initialized){ + ESP_LOGE(DEVICE_NAME, "Device is already initialized: unable to re-init"); + return mp_const_none; + } + //Configure device + can_general_config_t g_config = {.mode = args[ARG_mode].u_int, + .tx_io = args[ARG_tx].u_int, + .rx_io = args[ARG_rx].u_int, + .clkout_io = CAN_IO_UNUSED, + .bus_off_io = CAN_IO_UNUSED, + .tx_queue_len = args[ARG_tx_queue].u_int, + .rx_queue_len = args[ARG_rx_queue].u_int, + .alerts_enabled = CAN_ALERT_NONE, + .clkout_divider = 0}; + self->config->general = &g_config; + + switch ((int)args[ARG_baudrate].u_int){ + case CAN_BAUDRATE_25k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + break; + case CAN_BAUDRATE_50k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + break; + case CAN_BAUDRATE_100k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + break; + case CAN_BAUDRATE_125k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + break; + case CAN_BAUDRATE_250k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + break; + case CAN_BAUDRATE_500k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + break; + case CAN_BAUDRATE_800k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + break; + case CAN_BAUDRATE_1M: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + break; + default: + ESP_LOGE(DEVICE_NAME, "Unable to set baudrate"); + self->config->baudrate = 0; + return mp_const_none; + } + self->config->baudrate = args[ARG_baudrate].u_int; + + uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); + if (status != ESP_OK){ + ESP_LOGE(DEVICE_NAME, "Unable to init the device. ErrCode: %u",status); + }else if (can_start() != ESP_OK){ + ESP_LOGE(DEVICE_NAME, "Unable to start the device. ErrCode: %u",status); + }else{ + self->config->initialized = true; + } + + return mp_const_none; +} + +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ + const machine_can_obj_t *self = &machine_can_obj; + if (self->config->initialized != true){ + ESP_LOGW(DEVICE_NAME, "Device is not initialized"); + return mp_const_false; + } + if(can_stop()!=ESP_OK){ + ESP_LOGW(DEVICE_NAME, "Unable to stop device"); + } + if (can_driver_uninstall() != ESP_OK){ + ESP_LOGW(DEVICE_NAME, "Unable to uninstall device"); + return mp_const_false; + } + self->config->initialized = false; + return mp_const_true; +} //#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 5cccb97ba7e97..d2b2d101553db 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -30,26 +30,78 @@ #include "py/obj.h" +#define DEVICE_NAME "CAN" + +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 + + +typedef struct _machine_can_config_t { + const can_timing_config_t *timing; + const can_filter_config_t *filter; + const can_general_config_t *general; + uint16_t baudrate; + bool initialized; +} machine_can_config_t; + typedef struct _machine_can_obj_t { mp_obj_base_t base; - uint8_t tx; - uint8_t rx; -} machine_hw_can_obj_t; + machine_can_config_t *config; +} machine_can_obj_t; + +//Internal functions +STATIC can_state_t _machine_hw_can_get_state(); //Functions signature definition -STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in); +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) ; +STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in); //Python function declarations -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_init_obj, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_write_obj, machine_hw_can_write); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_read_obj, machine_hw_can_read); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); +MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { + //CAN_ATTRIBUTES + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, + //CAN_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(125) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(250) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(500) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(1000) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_write_obj)}, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_hw_can_read_obj)}, + //CAN_MODE + { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_CAN_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + //CAN_STATE + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + //CAN_BAUDRATE + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); @@ -57,7 +109,9 @@ STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_tab const mp_obj_type_t machine_can_type = { { &mp_type_type }, .name = MP_QSTR_CAN, - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members }; #endif // MICROPY_INCLUDED_ESP32_CAN_H From 79540e33b7358c3137384a5fbd1baba0b6101dff Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 19:15:39 +0200 Subject: [PATCH 005/180] added function to retrieve information of CAN STATUS --- ports/esp32/machine_can.c | 49 +++++++++++++++++++++++++++++---------- ports/esp32/machine_can.h | 20 ++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 6077f4ac48a7b..69bdd25996184 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -26,7 +26,7 @@ #include "py/builtin.h" #include "py/mphal.h" #include "py/mperrno.h" -#include +#include "mpconfigport.h" //Headers of ESP-IDF library #include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h @@ -46,28 +46,53 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; - - - +STATIC can_status_info_t _machine_hw_can_get_status(){ + can_status_info_t status; + if(can_get_status_info(&status)!=ESP_OK){ + mp_raise_ValueError("Unable to get CAN status"); + } + return status; +} STATIC can_state_t _machine_hw_can_get_state(){ - can_status_info_t status; - ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK - return status.state; + can_status_info_t status = _machine_hw_can_get_status(); + return status.state; } STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in){ - can_status_info_t status; - ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK - return mp_obj_new_int(status.msgs_to_rx); + can_status_info_t status = _machine_hw_can_get_status(); + return mp_obj_new_int(status.msgs_to_rx); } STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ - can_status_info_t status; - ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.msgs_to_tx); } +//Return status information +STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in){ + can_status_info_t status = _machine_hw_can_get_status(); + return mp_obj_new_int(status.tx_error_counter); +} + +STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in){ + can_status_info_t status = _machine_hw_can_get_status(); + return mp_obj_new_int(status.rx_error_counter); +} + +STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in){ + return mp_obj_new_int(_machine_hw_can_get_state()); +} + +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ + return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); +} + +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ + return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); +} + + STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) { int value = mp_obj_get_int(address); if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index d2b2d101553db..70018c50acc0c 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -67,13 +67,26 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) ; +STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); + //Python function declarations MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_write_obj, machine_hw_can_write); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_read_obj, machine_hw_can_read); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tec_obj, machine_hw_can_get_tec); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rec_obj, machine_hw_can_get_rec); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tx_waiting_messages_obj, machine_hw_can_get_tx_waiting_messages); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rx_waiting_messages_obj, machine_hw_can_get_rx_waiting_messages); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_state_obj, machine_hw_can_get_state); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { @@ -84,6 +97,13 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_write_obj)}, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_hw_can_read_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_tec), MP_ROM_PTR(&machine_hw_can_get_tec_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_rec), MP_ROM_PTR(&machine_hw_can_get_rec_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_tx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_tx_waiting_messages_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_rx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_rx_waiting_messages_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_state), MP_ROM_PTR(&machine_hw_can_get_state_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, //CAN_MODE { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, From 5c6a318dcab294468a715979f94b6335647d8b06 Mon Sep 17 00:00:00 2001 From: Salvo Musumeci Date: Sun, 6 Oct 2019 21:09:49 +0200 Subject: [PATCH 006/180] Update quickref.rst Added quick commands for CAN usage --- docs/esp32/quickref.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index dd85b102b2551..846d194a43a5a 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -325,6 +325,22 @@ pins can be used for SCL and SDA. The driver is accessed via the buf = bytearray(10) # create a buffer with 10 bytes i2c.writeto(0x3a, buf) # write the given buffer to the slave +CAN bus +------- + +The CAN driver is based on hardware implementation. +Any available output-capablepins can be used for SCL and SDA. +The driver is accessed via the :ref:`machine.CAN ` class:: + + from machine import CAN + + # construct a CAN bus + bus = CAN(tx=4, rx=2, baudrate=500, mode=CAN.MODE_NO_ACK) + + bus.send([0,1,2,3], 0x86, self_flag=True) #Send a self message + bus.recv() #Read the message sent + + Real time clock (RTC) --------------------- From 83297b4fcf5e153748082b4284968fe98491f01d Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 21:02:59 +0200 Subject: [PATCH 007/180] Function SEND and RECV implemented --- ports/esp32/machine_can.c | 107 +++++++++++++++++++++++++++----------- ports/esp32/machine_can.h | 12 ++--- 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 69bdd25996184..c81a06373a03c 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -46,6 +46,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; +//Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; if(can_get_status_info(&status)!=ESP_OK){ @@ -69,7 +70,6 @@ STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ return mp_obj_new_int(status.msgs_to_tx); } -//Return status information STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.tx_error_counter); @@ -84,67 +84,113 @@ STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in){ return mp_obj_new_int(_machine_hw_can_get_state()); } +//Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); } - +//Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); } - -STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) { - int value = mp_obj_get_int(address); - if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); - +//send([data], id, timeout=0, rtr=False, self_flag=False) +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_self_flag, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // populate message + size_t length; + mp_obj_t *items; + mp_obj_get_array(args[ARG_data].u_obj,&length, &items); + if (length>8){ + mp_raise_ValueError("CAN data field too long"); + } + uint8_t flags = (args[ARG_rtr].u_bool==true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + if (args[ARG_id].u_int>0x7ff){ + flags += CAN_MSG_FLAG_EXTD; + } + if (args[ARG_self].u_bool){ + flags += CAN_MSG_FLAG_SELF; + } + + can_message_t tx_msg = {.data_length_code = length, + .identifier = args[ARG_id].u_int & 0x1FFFFFFF, + .flags = flags}; + for (uint8_t i=0; iitems; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + can_message_t rx_message; switch(can_receive(&rx_message, 1)){ + case ESP_OK: + items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + items[1] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); + items[2] = MP_OBJ_NEW_SMALL_INT(rx_message.flags); + return ret_obj; case ESP_ERR_TIMEOUT: - ESP_LOGW(DEVICE_NAME, "Time-out"); break; + mp_raise_ValueError("Timeout"); case ESP_ERR_INVALID_ARG: - ESP_LOGE(DEVICE_NAME, "Invalid Args"); break; + mp_raise_ValueError("Invalid Args"); case ESP_ERR_INVALID_STATE: - ESP_LOGW(DEVICE_NAME, "Invalid State"); break; - case ESP_OK: - return MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + mp_raise_ValueError("Invalid State"); + default: + mp_raise_ValueError(""); }; - return MP_OBJ_NEW_SMALL_INT(-1); - } STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->config->initialized){ + qstr mode; + switch(self->config->general->mode){ + case CAN_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; + case CAN_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; + case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; + default: mode = MP_QSTR_UNKNOWN; break; + } mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%u)", self->config->general->tx_io, self->config->general->rx_io, - self->config->baudrate, self->config->general->mode); + self->config->baudrate, mode); }else{ mp_printf(print, "CAN Device is not initialized"); } } - -/*void machine_can_trasmit(machine_hw_can_obj_t *self, uint32_t address, size_t length, mp_machine_can_buf_t *data) -{ - can_message_t tx_msg = {.data_length_code = length, .identifier = address, .flags = CAN_MSG_FLAG_SELF}; - for (uint8_t i=0; iconfig->initialized != true){ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 70018c50acc0c..b3beef0d5203d 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -65,8 +65,8 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); -STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) ; +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); @@ -76,10 +76,10 @@ STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); //Python function declarations -MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_write_obj, machine_hw_can_write); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_read_obj, machine_hw_can_read); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); +MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tec_obj, machine_hw_can_get_tec); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rec_obj, machine_hw_can_get_rec); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tx_waiting_messages_obj, machine_hw_can_get_tx_waiting_messages); @@ -95,8 +95,8 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { //CAN_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_write_obj)}, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_hw_can_read_obj)}, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_get_tec), MP_ROM_PTR(&machine_hw_can_get_tec_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_get_rec), MP_ROM_PTR(&machine_hw_can_get_rec_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_get_tx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_tx_waiting_messages_obj)}, From e184574e7a8f158335707d14251b7bd49db33fa3 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 21:17:39 +0200 Subject: [PATCH 008/180] improve object print --- ports/esp32/machine_can.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index c81a06373a03c..22fc4de7c10a9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -183,8 +183,11 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; default: mode = MP_QSTR_UNKNOWN; break; } - mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%u)", self->config->general->tx_io, self->config->general->rx_io, - self->config->baudrate, mode); + mp_printf(print, + "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q)", + self->config->general->tx_io, + self->config->general->rx_io, + self->config->baudrate, mode); }else{ mp_printf(print, "CAN Device is not initialized"); } From e4abe724f29854420981165c7acf9e0505602c8e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 21:18:04 +0200 Subject: [PATCH 009/180] remove prefix CAN_ from constants --- ports/esp32/machine_can.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index b3beef0d5203d..46dea4202f3e3 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -105,14 +105,14 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, //CAN_MODE - { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_CAN_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, //CAN_STATE - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + { MP_ROM_QSTR(MP_QSTR_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, //CAN_BAUDRATE { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, From 872ce7383709e9a8b320c96dd4d1ed8e315a5e91 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 8 Oct 2019 21:12:45 +0200 Subject: [PATCH 010/180] implementation of hardware filter --- ports/esp32/machine_can.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 22fc4de7c10a9..1631a3a975994 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -29,12 +29,12 @@ #include "mpconfigport.h" //Headers of ESP-IDF library -#include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h +#include "soc/dport_reg.h" #include "driver/can.h" #include "esp_err.h" #include "esp_log.h" -#include "machine_can.h" +#include //#if MICROPY_HW_ENABLE_CAN @@ -231,16 +231,19 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue}; + enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { - { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, + { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -261,6 +264,12 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t .alerts_enabled = CAN_ALERT_NONE, .clkout_divider = 0}; self->config->general = &g_config; + can_filter_config_t f_config = { + .acceptance_code = args[ARG_filter_code].u_int, + .acceptance_mask = args[ARG_filter_mask].u_int, + .single_filter = args[ARG_single_filter].u_bool + }; + self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ case CAN_BAUDRATE_25k: From b2e7e23d4baa24cb9abdc1675ce30cd057d0fac1 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 8 Oct 2019 21:13:33 +0200 Subject: [PATCH 011/180] update includePath --- .vscode/c_cpp_properties.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000..5f0824b540e6b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "${workspaceFolder}/../esp-idf/components/**", + "${workspaceFolder}/ports/esp32/**", + "${workspaceFolder}/**" + ], + "defines": [], + "macFrameworkPath": [ + "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file From d175e3c04b63d2a7eab88aa60c5f962e67ca189d Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:33:15 +0100 Subject: [PATCH 012/180] Changed author --- ports/esp32/machine_can.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 46dea4202f3e3..fa67df93cca41 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014 Damien P. George + * Copyright (c) 2019 Musumeci Salvatore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 11cec6d6964fe02dcf115c69c3aaaa54a9b1a8ba Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:52:37 +0100 Subject: [PATCH 013/180] STM32 Harmonization: rename get_state() to state(), add info() and any() functions and remove functions now included in info() --- ports/esp32/machine_can.c | 57 ++++++++++++++++++++++++++++----------- ports/esp32/machine_can.h | 27 +++++++------------ 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 1631a3a975994..081e3b159fb4d 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -38,6 +38,9 @@ //#if MICROPY_HW_ENABLE_CAN +// Internal Functions +STATIC can_state_t _machine_hw_can_get_state(); + // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), @@ -55,33 +58,54 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } -STATIC can_state_t _machine_hw_can_get_state(){ - can_status_info_t status = _machine_hw_can_get_status(); - return status.state; } -STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in){ +// any(fifo) - return `True` if any message waiting on the FIFO, else `False` +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.msgs_to_rx); + if(mp_obj_new_int(status.msgs_to_rx)>0){ + return mp_const_true; + }else{ + return mp_const_false; + } } -STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ +// Get the state of the controller +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.msgs_to_tx); + return mp_obj_new_int(status.state); } -STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in){ +STATIC can_state_t _machine_hw_can_get_state(){ can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.tx_error_counter); + return status.state; } -STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in){ +// Get info about error states and TX/RX buffers +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { + //machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); //FIXME: Remove it if useless + mp_obj_list_t *list; + if (n_args == 1) { + list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); + } else { + if (!mp_obj_is_type(args[1], &mp_type_list)) { + mp_raise_TypeError(NULL); + } + list = MP_OBJ_TO_PTR(args[1]); + if (list->len < 8) { + mp_raise_ValueError(NULL); + } + } can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.rx_error_counter); -} - -STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in){ - return mp_obj_new_int(_machine_hw_can_get_state()); + list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); + list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); + //list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); //FIXME: + //list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); //FIXME: + //list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); //FIXME: + list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); + //list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); //FIXME: + //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: + return MP_OBJ_FROM_PTR(list); } //Clear TX Queue @@ -137,7 +161,8 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ case ESP_ERR_INVALID_STATE: ESP_LOGW(DEVICE_NAME, "Device is not initialized"); break; case ESP_ERR_NOT_SUPPORTED: ESP_LOGW(DEVICE_NAME, "Listen Only Mode active"); break; } - return machine_hw_can_get_tx_waiting_messages(pos_args[0]); + + return 0; //machine_hw_can_get_tx_waiting_messages(pos_args[0]); }else{ ESP_LOGW(DEVICE_NAME, "Unable to send the message"); return MP_OBJ_NEW_SMALL_INT(-1); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index fa67df93cca41..e65830d76a6ad 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -55,9 +55,6 @@ typedef struct _machine_can_obj_t { machine_can_config_t *config; } machine_can_obj_t; -//Internal functions -STATIC can_state_t _machine_hw_can_get_state(); - //Functions signature definition mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); @@ -66,27 +63,23 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); //Python function declarations MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tec_obj, machine_hw_can_get_tec); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rec_obj, machine_hw_can_get_rec); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tx_waiting_messages_obj, machine_hw_can_get_tx_waiting_messages); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rx_waiting_messages_obj, machine_hw_can_get_rx_waiting_messages); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_state_obj, machine_hw_can_get_state); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); +MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { @@ -95,13 +88,11 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { //CAN_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_tec), MP_ROM_PTR(&machine_hw_can_get_tec_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_rec), MP_ROM_PTR(&machine_hw_can_get_rec_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_tx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_tx_waiting_messages_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_rx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_rx_waiting_messages_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_state), MP_ROM_PTR(&machine_hw_can_get_state_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, //CAN_MODE From 1baa023e8bd60dd201b6709f18faaba82b8b7aba Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:54:19 +0100 Subject: [PATCH 014/180] STM32 Harmonization: added restart() signature --- ports/esp32/machine_can.c | 4 ++++ ports/esp32/machine_can.h | 1 + 2 files changed, 5 insertions(+) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 081e3b159fb4d..a8df1cf6190bd 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -58,6 +58,10 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } +// Force a software restart of the controller, to allow transmission after a bus error +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ + mp_raise_NotImplementedError(""); //TODO: Implement this function + return self_in; } // any(fifo) - return `True` if any message waiting on the FIFO, else `False` diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index e65830d76a6ad..594c299da12bb 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -78,6 +78,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); From 175073d58c97be74b00eb59bd558662eba8b1b49 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:54:51 +0100 Subject: [PATCH 015/180] STM32 Harmonization: move private methods in c file --- ports/esp32/machine_can.c | 10 ++++++++++ ports/esp32/machine_can.h | 8 -------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index a8df1cf6190bd..57d86f412f13a 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -41,6 +41,16 @@ // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); + +//Python object definition +const mp_obj_type_t machine_can_type = { + { &mp_type_type }, + .name = MP_QSTR_CAN, + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members +}; + // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 594c299da12bb..3b8499acdfaf8 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -117,13 +117,5 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); -//Python object definition -const mp_obj_type_t machine_can_type = { - { &mp_type_type }, - .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members -}; #endif // MICROPY_INCLUDED_ESP32_CAN_H From b8a5c0efe49694758b3e1ff58f2ece7366c0fe35 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:55:30 +0100 Subject: [PATCH 016/180] Enabled compiler switch for module --- ports/esp32/machine_can.c | 4 ++-- ports/esp32/machine_can.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 57d86f412f13a..5f8bba2dab98e 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -36,7 +36,7 @@ #include -//#if MICROPY_HW_ENABLE_CAN +#if MICROPY_HW_ENABLE_CAN // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); @@ -372,4 +372,4 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ return mp_const_true; } -//#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file +#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3b8499acdfaf8..7c707c4fdb410 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -30,6 +30,8 @@ #include "py/obj.h" +#if MICROPY_HW_ENABLE_CAN + #define DEVICE_NAME "CAN" #define CAN_BAUDRATE_25k 25 @@ -118,4 +120,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); + +#endif // MICROPY_HW_ENABLE_CAN #endif // MICROPY_INCLUDED_ESP32_CAN_H From 195088fc4bf2873119f0daf5df582feb12e3ccaf Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:57:03 +0100 Subject: [PATCH 017/180] Code Cleaning: Reordered the function sequence --- ports/esp32/machine_can.h | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 7c707c4fdb410..eb818aa905b5a 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -60,15 +60,20 @@ typedef struct _machine_can_obj_t { //Functions signature definition mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +//Micropython Generic API +//FIXME: check init arguments and harmonize with pyBoard as well as the outputs +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + +//ESP32 specific API STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); @@ -84,29 +89,33 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); + //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { //CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, - //CAN_FUNCTIONS + //Micropython Generic API { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + //ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - //CAN_MODE - { MP_ROM_QSTR(MP_QSTR_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + + //CAN_MODE + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, //CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, //CAN_BAUDRATE { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, From a03c23bbcba895530f34f21daef4c5c2ac4c1d88 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 22:21:51 +0100 Subject: [PATCH 018/180] STM32 Harmonization: init() returns mp_const_none and raise exceptions instead Error Logs --- ports/esp32/machine_can.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5f8bba2dab98e..37b222e50c55d 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -265,19 +265,19 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ const machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized){ ESP_LOGW(DEVICE_NAME, "Device is already initialized"); - return mp_const_false; + return mp_const_none; } return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) +// INTERNAL FUNCTION init(mode, tx, rx, baudrate, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + enum { ARG_mode, ARG_tx, ARG_rx, ARG_baudrate, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, @@ -287,12 +287,13 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - //Check if device was already configured + // Check if device was already configured if (self->config->initialized){ - ESP_LOGE(DEVICE_NAME, "Device is already initialized: unable to re-init"); + //TODO: check if this condition is redundant compared to init() + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN device is already initialized")); return mp_const_none; } - //Configure device + // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int, .tx_io = args[ARG_tx].u_int, .rx_io = args[ARG_rx].u_int, @@ -336,7 +337,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); break; default: - ESP_LOGE(DEVICE_NAME, "Unable to set baudrate"); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Unable to set baudrate")); self->config->baudrate = 0; return mp_const_none; } @@ -344,9 +345,9 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); if (status != ESP_OK){ - ESP_LOGE(DEVICE_NAME, "Unable to init the device. ErrCode: %u",status); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to init the device. ErrCode: %u",status)); }else if (can_start() != ESP_OK){ - ESP_LOGE(DEVICE_NAME, "Unable to start the device. ErrCode: %u",status); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to start the device. ErrCode: %u",status)); }else{ self->config->initialized = true; } @@ -359,17 +360,17 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; if (self->config->initialized != true){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); - return mp_const_false; + return mp_const_none; } if(can_stop()!=ESP_OK){ - ESP_LOGW(DEVICE_NAME, "Unable to stop device"); + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); } if (can_driver_uninstall() != ESP_OK){ - ESP_LOGW(DEVICE_NAME, "Unable to uninstall device"); - return mp_const_false; + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); + return mp_const_none; } self->config->initialized = false; - return mp_const_true; + return mp_const_none; } #endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file From c0c8c8bffbd46a8f8f73dfc64db4c023fd5433ab Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 12 Dec 2019 22:48:40 +0100 Subject: [PATCH 019/180] STM32 Harmonization: Alignment of init function to pyCan. --- ports/esp32/machine_can.c | 82 +++++++++++++++++++++++++++------------ ports/esp32/machine_can.h | 13 +++++++ 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 37b222e50c55d..9ba8762452e53 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -20,8 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include #include "py/obj.h" +#include "py/objarray.h" +#include "py/binary.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/mphal.h" @@ -38,6 +41,12 @@ #if MICROPY_HW_ENABLE_CAN +//Default baudrate: 500kb +#define CAN_DEFAULT_PRESCALER (8) +#define CAN_DEFAULT_SJW (3) +#define CAN_DEFAULT_BS1 (15) +#define CAN_DEFAULT_BS2 (4) + // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); @@ -57,7 +66,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA .timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()), .initialized = false}; -STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; +STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; //Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ @@ -233,36 +242,41 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } -// CAN(...) No argument to get the object -// Any argument will be used to init the device through init function +// CAN(bus, ...) No argument to get the object +//If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){ - const machine_can_obj_t *self = &machine_can_obj; - - if (n_args > 0 || n_kw > 0) { + // check arguments + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + if (mp_obj_is_int(args[0])!=true){ + mp_raise_TypeError("bus must be a number"); + } + mp_uint_t can_idx = mp_obj_get_int(args[0]); + if (can_idx > 1) { //TODO: check naming convention + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); + } + machine_can_obj_t *self = &machine_can_obj; + if (n_args > 1 || n_kw > 0) { if (self->config->initialized) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); machine_hw_can_deinit(&self); } - //TODO: implement callback - /*self->rxcallback0 = mp_const_none; - self->rxcallback1 = mp_const_none; - self->rx_state0 = RX_STATE_FIFO_EMPTY; - self->rx_state1 = RX_STATE_FIFO_EMPTY;*/ + self->rxcallback = mp_const_none; + self->rx_state = RX_STATE_FIFO_EMPTY; // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_hw_can_init_helper(self, n_args, args, &kw_args); + machine_hw_can_init_helper(self, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(self); } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - const machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized){ ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; @@ -270,20 +284,28 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -// INTERNAL FUNCTION init(mode, tx, rx, baudrate, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) +// init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_tx, ARG_rx, ARG_baudrate, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, + ARG_auto_restart, ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, - { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, + { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, + { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, + { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, + { MP_QSTR_auto_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, }; + //FIXME: auto_restart // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -295,8 +317,8 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t } // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int, - .tx_io = args[ARG_tx].u_int, - .rx_io = args[ARG_rx].u_int, + .tx_io = args[ARG_tx_io].u_int, + .rx_io = args[ARG_rx_io].u_int, .clkout_io = CAN_IO_UNUSED, .bus_off_io = CAN_IO_UNUSED, .tx_queue_len = args[ARG_tx_queue].u_int, @@ -312,6 +334,14 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ + case 0: + self->config->timing = &((can_timing_config_t){ + .brp = args[ARG_prescaler].u_int, + .sjw = args[ARG_sjw].u_int, + .tseg_1 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs1].u_int, + .triple_sampling = false}); + break; case CAN_BAUDRATE_25k: self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); break; @@ -345,13 +375,15 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); if (status != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to init the device. ErrCode: %u",status)); - }else if (can_start() != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to start the device. ErrCode: %u",status)); + mp_raise_OSError(-status); }else{ - self->config->initialized = true; + status = can_start() + if (status != ESP_OK){ + mp_raise_OSError(-status); + }else{ + self->config->initialized = true; + } } - return mp_const_none; } diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index eb818aa905b5a..e4275d79b24cd 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -55,8 +55,21 @@ typedef struct _machine_can_config_t { typedef struct _machine_can_obj_t { mp_obj_base_t base; machine_can_config_t *config; + mp_obj_t rxcallback; + byte rx_state; + bool extframe : 1; + uint16_t num_error_warning; //FIXME: populate this value somewhere + uint16_t num_error_passive; + uint16_t num_bus_off; } machine_can_obj_t; +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + //Functions signature definition mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); From b362179c62847800d7731d245b7a22c9e38285f4 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 12 Dec 2019 22:50:24 +0100 Subject: [PATCH 020/180] STM32 Harmonization: Alignment of send(...) and recv(...) methods to pyBoard signature and return values --- ports/esp32/machine_can.c | 80 +++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 9ba8762452e53..5aae874708bc0 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -177,48 +177,70 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ tx_msg.data[i] = mp_obj_get_int(items[i]); } if (_machine_hw_can_get_state()==CAN_STATE_RUNNING){ - switch(can_transmit(&tx_msg, args[ARG_timeout].u_int)){ - case ESP_ERR_INVALID_ARG: ESP_LOGW(DEVICE_NAME, "Arguments are invalid"); break; - case ESP_ERR_TIMEOUT: //TX Queue is full - case ESP_FAIL: ESP_LOGW(DEVICE_NAME, "Message transmission failed"); break; - case ESP_ERR_INVALID_STATE: ESP_LOGW(DEVICE_NAME, "Device is not initialized"); break; - case ESP_ERR_NOT_SUPPORTED: ESP_LOGW(DEVICE_NAME, "Listen Only Mode active"); break; + int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); + if (status!=ESP_OK){ + mp_raise_OSError(-status); } - - return 0; //machine_hw_can_get_tx_waiting_messages(pos_args[0]); + return mp_const_none; }else{ - ESP_LOGW(DEVICE_NAME, "Unable to send the message"); - return MP_OBJ_NEW_SMALL_INT(-1); + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to send the message")); } } -// recv(timeout=5000) +// recv(list=None, *, timeout=5000) STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_timeout }; - mp_obj_t ret_obj = mp_obj_new_tuple(3, NULL); - mp_obj_t *items = ((mp_obj_tuple_t*)MP_OBJ_TO_PTR(ret_obj))->items; + enum { ARG_fifo, ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { + { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; + + // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); can_message_t rx_message; - switch(can_receive(&rx_message, 1)){ - case ESP_OK: - items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - items[2] = MP_OBJ_NEW_SMALL_INT(rx_message.flags); - return ret_obj; - case ESP_ERR_TIMEOUT: - mp_raise_ValueError("Timeout"); - case ESP_ERR_INVALID_ARG: - mp_raise_ValueError("Invalid Args"); - case ESP_ERR_INVALID_STATE: - mp_raise_ValueError("Invalid State"); - default: - mp_raise_ValueError(""); - }; + int status = can_receive(&rx_message, 1); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + //TODO: manage callback + // Create the tuple, or get the list, that will hold the return values + // Also populate the fourth element, either a new bytes or reuse existing memoryview + mp_obj_t ret_obj = args[ARG_list].u_obj; + mp_obj_t *items; + if (ret_obj == mp_const_none){ + ret_obj = mp_obj_new_tuple(4, NULL); + items = ((mp_obj_tuple_t*)MP_OBJ_TO_PTR(ret_obj))->items; + items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); + } else { + // User should provide a list of length at least 4 to hold the values + if (!mp_obj_is_type(ret_obj, &mp_type_list)) { + mp_raise_TypeError(NULL); + } + mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); + if (list->len < 4) { + mp_raise_ValueError(NULL); + } + items = list->items; + // Fourth element must be a memoryview which we assume points to a + // byte-like array which is large enough, and then we resize it inplace + if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { + mp_raise_TypeError(NULL); + } + mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) + || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { + mp_raise_ValueError(NULL); + } + mv->len = rx_message.data_length_code; + memcpy(mv->items, rx_message.data, rx_message.data_length_code); + + } + items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; + items[2] = 0; //TODO: check if Filter Mailbox Index is available for ESP32 + return ret_obj; } STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { From 02cadd0214771c95d7ea0004f36f89f380f2d297 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 12 Dec 2019 22:58:51 +0100 Subject: [PATCH 021/180] removed auto_restart option since the esp32 framework doesn't have this feature. It could be implemented in the feature if needed --- ports/esp32/machine_can.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5aae874708bc0..d684a8bce34a4 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -309,7 +309,7 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ // init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, - ARG_auto_restart, ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, @@ -318,7 +318,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_auto_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, @@ -327,7 +326,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, }; - //FIXME: auto_restart // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -399,7 +397,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t if (status != ESP_OK){ mp_raise_OSError(-status); }else{ - status = can_start() + status = can_start(); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ From 82017a9f9d0035449c875820f1f64cab984822e5 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 08:03:30 +0100 Subject: [PATCH 022/180] Added signature for RX Callback; currently this method is not implemented --- ports/esp32/machine_can.c | 18 ++++++++++++++++++ ports/esp32/machine_can.h | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index d684a8bce34a4..2eecd32048b7f 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -407,6 +407,24 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t return mp_const_none; } +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + mp_raise_NotImplementedError("IRQ not supported yet"); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (callback_in == mp_const_none) { + self->rxcallback = mp_const_none; + } else if (self->rxcallback != mp_const_none) { + // Rx call backs has already been initialized + // only the callback function should be changed + self->rxcallback = callback_in; + // TODO: disable interrupt + } else if (mp_obj_is_callable(callback_in)) { + self->rxcallback = callback_in; + // TODO: set interrupt + } + return mp_const_none; +} + //deinit() STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index e4275d79b24cd..3e05e204f16a6 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -85,6 +85,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in); //ESP32 specific API STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); @@ -101,7 +102,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clea MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); - +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { @@ -116,6 +117,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, //ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, From a65026af61884096a8412db8167a4ce2b69dcef3 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 08:32:00 +0100 Subject: [PATCH 023/180] Python Interface has been moved from header to source --- ports/esp32/machine_can.c | 167 ++++++++++++++++++++++++++------------ ports/esp32/machine_can.h | 76 +---------------- 2 files changed, 116 insertions(+), 127 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 2eecd32048b7f..81c957844294c 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -49,16 +49,12 @@ // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); + -//Python object definition -const mp_obj_type_t machine_can_type = { - { &mp_type_type }, - .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members -}; // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), @@ -82,6 +78,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ mp_raise_NotImplementedError(""); //TODO: Implement this function return self_in; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any(fifo) - return `True` if any message waiting on the FIFO, else `False` STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ @@ -92,6 +89,7 @@ STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ return mp_const_false; } } +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { @@ -103,6 +101,7 @@ STATIC can_state_t _machine_hw_can_get_state(){ can_status_info_t status = _machine_hw_can_get_status(); return status.state; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { @@ -130,15 +129,20 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: return MP_OBJ_FROM_PTR(list); } +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); //Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); + //Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); + //send([data], id, timeout=0, rtr=False, self_flag=False) STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -186,6 +190,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to send the message")); } } +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); // recv(list=None, *, timeout=5000) STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -242,6 +247,27 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ items[2] = 0; //TODO: check if Filter Mailbox Index is available for ESP32 return ret_obj; } +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); + +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + mp_raise_NotImplementedError("IRQ not supported yet"); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (callback_in == mp_const_none) { + self->rxcallback = mp_const_none; + } else if (self->rxcallback != mp_const_none) { + // Rx call backs has already been initialized + // only the callback function should be changed + self->rxcallback = callback_in; + // TODO: disable interrupt + } else if (mp_obj_is_callable(callback_in)) { + self->rxcallback = callback_in; + // TODO: set interrupt + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); + STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -264,6 +290,37 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } + +// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized){ + ESP_LOGW(DEVICE_NAME, "Device is already initialized"); + return mp_const_none; + } + return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); + +//deinit() +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ + const machine_can_obj_t *self = &machine_can_obj; + if (self->config->initialized != true){ + ESP_LOGW(DEVICE_NAME, "Device is not initialized"); + return mp_const_none; + } + if(can_stop()!=ESP_OK){ + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); + } + if (can_driver_uninstall() != ESP_OK){ + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); + return mp_const_none; + } + self->config->initialized = false; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); + // CAN(bus, ...) No argument to get the object //If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, @@ -296,16 +353,6 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized){ - ESP_LOGW(DEVICE_NAME, "Device is already initialized"); - return mp_const_none; - } - return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); -} - // init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, @@ -407,40 +454,56 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t return mp_const_none; } -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { - mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (callback_in == mp_const_none) { - self->rxcallback = mp_const_none; - } else if (self->rxcallback != mp_const_none) { - // Rx call backs has already been initialized - // only the callback function should be changed - self->rxcallback = callback_in; - // TODO: disable interrupt - } else if (mp_obj_is_callable(callback_in)) { - self->rxcallback = callback_in; - // TODO: set interrupt - } - return mp_const_none; -} -//deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ - const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true){ - ESP_LOGW(DEVICE_NAME, "Device is not initialized"); - return mp_const_none; - } - if(can_stop()!=ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); - } - if (can_driver_uninstall() != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); - return mp_const_none; - } - self->config->initialized = false; - return mp_const_none; -} +STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { + //CAN_ATTRIBUTES + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, + //Micropython Generic API + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + /* + { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, + */ + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, + //ESP32 Specific API + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + + //CAN_MODE + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + //CAN_STATE + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + //CAN_BAUDRATE + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); +//Python object definition +const mp_obj_type_t machine_can_type = { + { &mp_type_type }, + .name = MP_QSTR_CAN, + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members +}; #endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3e05e204f16a6..f1d0a22633a10 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,7 +43,6 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 - typedef struct _machine_can_config_t { const can_timing_config_t *timing; const can_filter_config_t *filter; @@ -70,80 +69,7 @@ typedef enum _rx_state_t { RX_STATE_FIFO_OVERFLOW, } rx_state_t; -//Functions signature definition -mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); - -//Micropython Generic API -//FIXME: check init arguments and harmonize with pyBoard as well as the outputs -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in); - -//ESP32 specific API -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); - -//Python function declarations -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); -MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); - -//Python objects list declaration -STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { - //CAN_ATTRIBUTES - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, - //Micropython Generic API - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, - { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, - { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, - //ESP32 Specific API - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - - //CAN_MODE - { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, - //CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, - //CAN_BAUDRATE - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); - - +extern const mp_obj_type_t machine_can_type; #endif // MICROPY_HW_ENABLE_CAN #endif // MICROPY_INCLUDED_ESP32_CAN_H From de8c71b6a6466f5e6275613f0bde4594949c4718 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 08:34:26 +0100 Subject: [PATCH 024/180] Removed redundant function --- ports/esp32/machine_can.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 81c957844294c..da72ded6caeb3 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -48,7 +48,6 @@ #define CAN_DEFAULT_BS2 (4) // Internal Functions -STATIC can_state_t _machine_hw_can_get_state(); mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); @@ -64,7 +63,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; -//Return status information +//INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; if(can_get_status_info(&status)!=ESP_OK){ @@ -96,11 +95,6 @@ STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } - -STATIC can_state_t _machine_hw_can_get_state(){ - can_status_info_t status = _machine_hw_can_get_status(); - return status.state; -} STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers @@ -180,7 +174,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ for (uint8_t i=0; i Date: Fri, 13 Dec 2019 08:37:00 +0100 Subject: [PATCH 025/180] beautify --- ports/esp32/machine_can.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index da72ded6caeb3..43b045fa869d8 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -31,7 +31,7 @@ #include "py/mperrno.h" #include "mpconfigport.h" -//Headers of ESP-IDF library +// Headers of ESP-IDF library #include "soc/dport_reg.h" #include "driver/can.h" #include "esp_err.h" @@ -41,20 +41,18 @@ #if MICROPY_HW_ENABLE_CAN -//Default baudrate: 500kb +// Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) #define CAN_DEFAULT_BS1 (15) #define CAN_DEFAULT_BS2 (4) + // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); - - - // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), @@ -63,7 +61,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; -//INTERNAL FUNCTION Return status information +// INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; if(can_get_status_info(&status)!=ESP_OK){ @@ -125,20 +123,20 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); -//Clear TX Queue +// Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); -//Clear RX Queue +// Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); -//send([data], id, timeout=0, rtr=False, self_flag=False) +// send([data], id, timeout=0, rtr=False, self_flag=False) STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; static const mp_arg_t allowed_args[] = { @@ -296,7 +294,7 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); -//deinit() +// deinit() STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; if (self->config->initialized != true){ @@ -316,7 +314,7 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); // CAN(bus, ...) No argument to get the object -//If no arguments are provided, the initialized object will be returned +// If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){ // check arguments @@ -450,9 +448,9 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { - //CAN_ATTRIBUTES + // CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, - //Micropython Generic API + // Micropython Generic API { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, @@ -467,20 +465,20 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, */ { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, - //ESP32 Specific API + // ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - //CAN_MODE + // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, - //CAN_STATE + // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, - //CAN_BAUDRATE + // CAN_BAUDRATE { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, @@ -492,7 +490,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); -//Python object definition +// Python object definition const mp_obj_type_t machine_can_type = { { &mp_type_type }, .name = MP_QSTR_CAN, From bbdfa6f72d3c40d43e83b247937ce63ab15cbeed Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 09:52:03 +0100 Subject: [PATCH 026/180] STM32 Harmonization: implemented same CAN_MODE --- ports/esp32/machine_can.c | 21 +++++++++++++-------- ports/esp32/machine_can.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 43b045fa869d8..ffebfc44fc469 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -136,7 +136,7 @@ STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); -// send([data], id, timeout=0, rtr=False, self_flag=False) +// send([data], id, *) STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; static const mp_arg_t allowed_args[] = { @@ -144,10 +144,10 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_self_flag, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // parse args + machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -159,15 +159,17 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ mp_raise_ValueError("CAN data field too long"); } uint8_t flags = (args[ARG_rtr].u_bool==true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); - if (args[ARG_id].u_int>0x7ff){ + uint32_t id = args[ARG_id].u_int; + if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; + id &= 0x1FFFFFFF; } - if (args[ARG_self].u_bool){ + if (self->loopback){ flags += CAN_MSG_FLAG_SELF; + id &= 0x1FF; } - can_message_t tx_msg = {.data_length_code = length, - .identifier = args[ARG_id].u_int & 0x1FFFFFFF, + .identifier = id, .flags = flags}; for (uint8_t i=0; iconfig->general = &g_config; + self->loopback = (args[ARG_mode] && 0x10 > 0) can_filter_config_t f_config = { .acceptance_code = args[ARG_filter_code].u_int, .acceptance_mask = args[ARG_filter_mask].u_int, @@ -471,7 +474,9 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index f1d0a22633a10..3e91588682ab0 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -57,6 +57,7 @@ typedef struct _machine_can_obj_t { mp_obj_t rxcallback; byte rx_state; bool extframe : 1; + bool loopback : 1; uint16_t num_error_warning; //FIXME: populate this value somewhere uint16_t num_error_passive; uint16_t num_bus_off; From cf0f92aea56b7bca0622e1a36bd81f1d0ad182b0 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:06:55 +0100 Subject: [PATCH 027/180] minor fix --- ports/esp32/machine_can.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index ffebfc44fc469..8eb936508b42e 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -64,8 +64,9 @@ STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_co // INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; - if(can_get_status_info(&status)!=ESP_OK){ - mp_raise_ValueError("Unable to get CAN status"); + uint8_t err_code = can_get_status_info(&status); + if(err_code!=ESP_OK){ + mp_raise_OSError(-err_code); } return status; } @@ -97,7 +98,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { - //machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); //FIXME: Remove it if useless mp_obj_list_t *list; if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); @@ -113,9 +113,9 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { can_status_info_t status = _machine_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); - //list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); //FIXME: - //list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); //FIXME: - //list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); //FIXME: + list->items[2] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_warning + list->items[3] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_passive + list->items[4] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_bus_off list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); //list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); //FIXME: //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: @@ -303,12 +303,13 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } - if(can_stop()!=ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); + uint8_t status = can_stop(); + if(status!=ESP_OK){ + mp_raise_OSError(-status); } - if (can_driver_uninstall() != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); - return mp_const_none; + status = can_driver_uninstall(); + if (status != ESP_OK){ + mp_raise_OSError(-status); } self->config->initialized = false; return mp_const_none; @@ -429,7 +430,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Unable to set baudrate")); + mp_raise_ValueError("Unable to set baudrate"); self->config->baudrate = 0; return mp_const_none; } From 9e00b411afb231146162b3ff2a315fc45a5a00df Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:51:47 +0100 Subject: [PATCH 028/180] manage flags for loopback and extframe --- ports/esp32/machine_can.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 8eb936508b42e..6f9464a99caec 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -50,7 +50,7 @@ // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object @@ -349,7 +349,7 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { @@ -388,7 +388,8 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t .alerts_enabled = CAN_ALERT_NONE, .clkout_divider = 0}; self->config->general = &g_config; - self->loopback = (args[ARG_mode] && 0x10 > 0) + self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); + self->extframe = args[ARG_extframe].u_bool; can_filter_config_t f_config = { .acceptance_code = args[ARG_filter_code].u_int, .acceptance_mask = args[ARG_filter_mask].u_int, From 8e45d1173669cdfe49474b3eb36e63a3e0b71bd7 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:52:45 +0100 Subject: [PATCH 029/180] removed unused input variable from any() --- ports/esp32/machine_can.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 6f9464a99caec..255ed7064b380 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -78,16 +78,12 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); -// any(fifo) - return `True` if any message waiting on the FIFO, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ +// any() - return `True` if any message waiting, else `False` +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); - if(mp_obj_new_int(status.msgs_to_rx)>0){ - return mp_const_true; - }else{ - return mp_const_false; - } + return mp_obj_new_bool((status.msgs_to_rx)>0); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { From 215dd81ed29a5473e8b7bb2cc21ccd93549b7a8e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:53:02 +0100 Subject: [PATCH 030/180] bugfix --- ports/esp32/machine_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 255ed7064b380..4f108d589e594 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -184,7 +184,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_sen // recv(list=None, *, timeout=5000) STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_fifo, ARG_list, ARG_timeout }; + enum { ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, From 9d0190851fff92f50afac566d34fcecc7bcf5feb Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:53:15 +0100 Subject: [PATCH 031/180] Improved print function --- ports/esp32/machine_can.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 4f108d589e594..69de73a279338 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -270,10 +270,13 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p default: mode = MP_QSTR_UNKNOWN; break; } mp_printf(print, - "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q)", + "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", self->config->general->tx_io, self->config->general->rx_io, - self->config->baudrate, mode); + self->config->baudrate, + mode, + self->loopback, + self->extframe); }else{ mp_printf(print, "CAN Device is not initialized"); } From 7fed70972c8b37914b272f44b9693a11723a2cf0 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Wed, 18 Dec 2019 23:35:00 +0100 Subject: [PATCH 032/180] Implementation of restart function --- ports/esp32/machine_can.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 69de73a279338..493ef0d8656f9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -73,8 +73,16 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ - mp_raise_NotImplementedError(""); //TODO: Implement this function - return self_in; + uint32_t status = can_initiate_recovery(); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution + status = can_start(); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); From 38b2e6cca5c0838bc4e617341252ecf7489ef279 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Wed, 18 Dec 2019 23:35:39 +0100 Subject: [PATCH 033/180] data type bugfix --- ports/esp32/machine_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 493ef0d8656f9..f8dd96e5a731e 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -310,7 +310,7 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } - uint8_t status = can_stop(); + uint32_t status = can_stop(); if(status!=ESP_OK){ mp_raise_OSError(-status); } @@ -444,7 +444,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg } self->config->baudrate = args[ARG_baudrate].u_int; - uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); + uint32_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ From bb0ed63be37dc50891bb00c6343ab74a9e42fc1e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 22:20:52 +0100 Subject: [PATCH 034/180] Added alert function --- ports/esp32/machine_can.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f8dd96e5a731e..5a7473c8195cc 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -127,6 +127,16 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ + uint32_t alerts; + uint32_t status = can_read_alerts(&alerts, 0); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + return mp_obj_new_int(alerts); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); + // Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); @@ -392,7 +402,8 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .bus_off_io = CAN_IO_UNUSED, .tx_queue_len = args[ARG_tx_queue].u_int, .rx_queue_len = args[ARG_rx_queue].u_int, - .alerts_enabled = CAN_ALERT_NONE, + .alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || + CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF, .clkout_divider = 0}; self->config->general = &g_config; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); @@ -481,6 +492,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, @@ -501,6 +513,20 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, + // CAN_ALERT + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); From a508f4cb33acbf506e56e9abedf42582fcdb7d30 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:01:04 +0100 Subject: [PATCH 035/180] Added docs for ESP32 CAN --- docs/library/esp32.CAN.rst | 326 +++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 docs/library/esp32.CAN.rst diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst new file mode 100644 index 0000000000000..e17e9f4a5598f --- /dev/null +++ b/docs/library/esp32.CAN.rst @@ -0,0 +1,326 @@ +.. currentmodule:: esp32 +.. _esp32.CAN: + +class CAN -- controller area network communication bus +====================================================== + +CAN implements the standard CAN communications protocol. At +the physical level it consists of 2 lines: RX and TX. Note that +to connect the ESP32 to a CAN bus you must use a CAN transceiver +to convert the CAN logic signals from the ESP32 to the correct +voltage levels on the bus. + +Example usage (works without anything connected):: + + from machine import CAN + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) + can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 + can.send([1,2,3], 123) # send a message with id 123 + can.recv() # receive message + + +Constructors +------------ + +.. class:: machine.CAN(bus, ...) + + Construct a CAN object on the given bus. *bus* can be 0 or 1 (for compatibility with STM32). It will point at the same device + With no additional parameters, the CAN object is created but not + initialised (it has the settings from the last initialisation of + the bus, if any). If extra arguments are given, the bus is initialised. + See :meth:`CAN.init` for parameters of initialisation. + + The physical pins of the CAN bus can be assigned during init. + +Class Methods +------------- +.. classmethod:: CAN.initfilterbanks(nr) TODO: + + Reset and disable all filter banks and assign how many banks should be available for CAN(1). + + STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. + This function configures how many filter banks should be assigned to each. *nr* is the number of banks + that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). + At boot, 14 banks are assigned to each controller. + +Methods +------- + +.. method:: CAN.init(mode, extframe=False, baudrate, prescaler, \*, sjw=1, bs1=6, bs2=8, auto_restart=False) + + Initialise the CAN bus with the given parameters: + + - *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK + - if *extframe* is True then the bus uses extended identifiers in the frames + (29 bits); otherwise it uses standard 11 bit identifiers + - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* + will be ignored. Standard speeds are available as CAN.BAUDRATE_* + - *prescaler* is used to set the duration of 1 time quanta; the time quanta + will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler + - *sjw* is the resynchronisation jump width in units of the time quanta; + it can be 1, 2, 3, 4 + - *bs1* defines the location of the sample point in units of the time quanta; + it can be between 1 and 1024 inclusive + - *bs2* defines the location of the transmit point in units of the time quanta; + it can be between 1 and 16 inclusive + - *tx_io* defines the gpio used for transmission + - *rx_io* defines the gpio used for receiving + - *tx_queue* defines the number of waiting tx messages can be stored + - *rx_queue* defines the number of received messages can be stored + - *auto_restart* sets whether the controller will automatically try and restart + communications after entering the bus-off state; if this is disabled then + :meth:`~CAN.restart()` can be used to leave the bus-off state. + This parameter is currently not implemented and it must be set to False + + +.. method:: CAN.deinit() + + Turn off the CAN bus. + +.. method:: CAN.restart() + + Force a software restart of the CAN controller without resetting its + configuration. + + If the controller enters the bus-off state then it will no longer participate + in bus activity. If the controller is not configured to automatically restart + (see :meth:`~CAN.init()`) then this method can be used to trigger a restart, + and the controller will follow the CAN protocol to leave the bus-off state and + go into the error active state. + +.. method:: CAN.state() + + Return the state of the controller. The return value can be one of: + + - ``CAN.STOPPED`` -- the controller is completely off and reset; + - ``CAN.ERROR_ACTIVE`` -- the controller is on and in the Error Active state + (both TEC and REC are less than 96); + - ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity + (TEC overflowed beyond 255). + - ``CAN.RECOVERING`` -- the controller is under recover from bus-off state; + + +.. method:: CAN.info([list]) + + Get information about the controller's error states and TX and RX buffers. + If *list* is provided then it should be a list object with at least 8 entries, + which will be filled in with the information. Otherwise a new list will be + created and filled in. In both cases the return value of the method is the + populated list. + + The values in the list are: + + - TEC value + - REC value + - number of times the controller enterted the Error Warning state (wrapped + around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED + - number of times the controller enterted the Error Passive state (wrapped + around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED + - number of times the controller enterted the Bus Off state (wrapped + around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED + - number of pending TX messages + - number of pending RX messages + - Reserved + +.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) TODO: + + Configure a filter bank: + + - *bank* is the filter bank that is to be configured. + - *mode* is the mode the filter should operate in. + - *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. + - *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument. + + +-----------+---------------------------------------------------------+ + |*mode* |contents of *params* array | + +===========+=========================================================+ + |CAN.LIST16 |Four 16 bit ids that will be accepted | + +-----------+---------------------------------------------------------+ + |CAN.LIST32 |Two 32 bit ids that will be accepted | + +-----------+---------------------------------------------------------+ + |CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | + | | | The first pair, 1 and 3 will accept all ids | + | | | that have bit 0 = 1 and bit 1 = 0. | + | | | The second pair, 4 and 4, will accept all ids | + | | | that have bit 2 = 1. | + +-----------+---------------------------------------------------------+ + |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| + +-----------+---------------------------------------------------------+ + + - *rtr* is an array of booleans that states if a filter should accept a + remote transmission request message. If this argument is not given + then it defaults to ``False`` for all entries. The length of the array + depends on the *mode* argument. + + +-----------+----------------------+ + |*mode* |length of *rtr* array | + +===========+======================+ + |CAN.LIST16 |4 | + +-----------+----------------------+ + |CAN.LIST32 |2 | + +-----------+----------------------+ + |CAN.MASK16 |2 | + +-----------+----------------------+ + |CAN.MASK32 |1 | + +-----------+----------------------+ + +.. method:: CAN.clearfilter(bank) TODO: + + Clear and disables a filter bank: + + - *bank* is the filter bank that is to be cleared. + +.. method:: CAN.any(fifo) + + Return ``True`` if any message waiting on the FIFO, else ``False``. + +.. method:: CAN.recv(list=None, \*, timeout=5000) + + Receive data on the bus: + + - *list* is an optional list object to be used as the return value + - *timeout* is the timeout in milliseconds to wait for the receive. + + Return value: A tuple containing four values. + + - The id of the message. + - A boolean that indicates if the message is an RTR message. + - Reserved. + - An array containing the data. + + If *list* is ``None`` then a new tuple will be allocated, as well as a new + bytes object to contain the data (as the fourth element in the tuple). + + If *list* is not ``None`` then it should be a list object with a least four + elements. The fourth element should be a memoryview object which is created + from either a bytearray or an array of type 'B' or 'b', and this array must + have enough room for at least 8 bytes. The list object will then be + populated with the first three return values above, and the memoryview object + will be resized inplace to the size of the data and filled in with that data. + The same list and memoryview objects can be reused in subsequent calls to + this method, providing a way of receiving data without using the heap. + For example:: + + buf = bytearray(8) + lst = [0, 0, 0, memoryview(buf)] + # No heap memory is allocated in the following call + can.recv(0, lst) + +.. method:: CAN.send(data, id, \*, timeout=0, rtr=False) + + Send a message on the bus: + + - *data* is the data to send (an integer to send, or a buffer object). + - *id* is the id of the message to be sent. + - *timeout* is the timeout in milliseconds to wait for the send. + - *rtr* is a boolean that specifies if the message shall be sent as + a remote transmission request. If *rtr* is True then only the length + of *data* is used to fill in the DLC slot of the frame; the actual + bytes in *data* are unused. + + If timeout is 0 the message is placed in a buffer and the method returns + immediately. If all three buffers are in use an exception is thrown. + If timeout is not 0, the method waits until the message is transmitted. + If the message can't be transmitted within the specified time an exception + is thrown. + + Return value: ``None``. + +.. method:: CAN.clear_tx_queue() + + Clear all messages from transmitting queue. + +.. method:: CAN.clear_rx_queue() + + Clear all messages from receiving queue. + +.. method:: CAN.get_alerts() + + Read the alert status word directly from hardware. + + +.. method:: CAN.rxcallback(fifo, fun) TODO: NOT YET IMPLEMENTED + + Register a function to be called when a message is accepted into a empty fifo: + + - *fifo* is the receiving fifo. + - *fun* is the function to be called when the fifo becomes non empty. + + The callback function takes two arguments the first is the can object it self the second is + a integer that indicates the reason for the callback. + + +--------+------------------------------------------------+ + | Reason | | + +========+================================================+ + | 0 | A message has been accepted into a empty FIFO. | + +--------+------------------------------------------------+ + | 1 | The FIFO is full | + +--------+------------------------------------------------+ + | 2 | A message has been lost due to a full FIFO | + +--------+------------------------------------------------+ + + Example use of rxcallback:: + + def cb0(bus, reason): + print('cb0') + if reason == 0: + print('pending') + if reason == 1: + print('full') + if reason == 2: + print('overflow') + + can = CAN(1, CAN.LOOPBACK) + can.rxcallback(0, cb0) + +Constants +--------- + +.. data:: CAN.NORMAL + CAN.LOOPBACK + CAN.SILENT + CAN.SILENT_LOOPBACK + CAN.LISTEN_ONLY + + The mode of the CAN bus used in :meth:`~CAN.init()`. + +.. data:: CAN.BAUDRATE_25k + CAN.BAUDRATE_50k + CAN.BAUDRATE_100k + CAN.BAUDRATE_125k + CAN.BAUDRATE_250k + CAN.BAUDRATE_500k + CAN.BAUDRATE_800k + CAN.BAUDRATE_1M + + The baudrate of the CAN bus used in :meth:`~CAN.init()`. + +.. data:: CAN.STOPPED + CAN.ERROR_ACTIVE + CAN.BUS_OFF + CAN.RECOVERING + + Possible states of the CAN controller returned from :meth:`~CAN.state()`. + +.. data:: CAN.LIST16 TODO: + CAN.MASK16 + CAN.LIST32 + CAN.MASK32 + + The operation mode of a filter used in :meth:`~CAN.setfilter()`. + +.. data:: CAN.ALERT_TX_IDLE + CAN.ALERT_TX_SUCCESS + CAN.ALERT_BELOW_ERR_WARN + CAN.ALERT_ERR_ACTIVE + CAN.ALERT_RECOVERY_IN_PROGRESS + CAN.ALERT_BUS_RECOVERED + CAN.ALERT_ARB_LOST + CAN.ALERT_ABOVE_ERR_WARN + CAN.ALERT_BUS_ERROR + CAN.ALERT_TX_FAILED + CAN.ALERT_RX_QUEUE_FULL + CAN.ALERT_ERR_PASS + CAN.ALERT_BUS_OFF + + Possibile bit position of alert mask returned by :meth:`~CAN.get_alerts()`. From 11cca71e30b1955cdbc8fdaa82777c887bfe836c Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:03:24 +0100 Subject: [PATCH 036/180] Removed filter setup from init. --- ports/esp32/machine_can.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5a7473c8195cc..d8233b7f31ced 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -368,7 +368,7 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, // init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, - ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_auto_restart}; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, @@ -381,9 +381,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, - { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = true} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -408,11 +406,10 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general = &g_config; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - can_filter_config_t f_config = { - .acceptance_code = args[ARG_filter_code].u_int, - .acceptance_mask = args[ARG_filter_mask].u_int, - .single_filter = args[ARG_single_filter].u_bool - }; + if (args[ARG_auto_restart].u_bool){ + mp_raise_NotImplementedError("Auto-restart not supported"); + } + can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ From 57efe7979494a6488f1ad0fc2c39492a82f010ed Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:08:09 +0100 Subject: [PATCH 037/180] STM32 Harmonization --- ports/esp32/machine_can.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index d8233b7f31ced..c8118de30b408 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -121,8 +121,8 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[3] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_passive list->items[4] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_bus_off list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); - //list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); //FIXME: - //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: + list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); + list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); @@ -252,7 +252,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; - items[2] = 0; //TODO: check if Filter Mailbox Index is available for ESP32 + items[2] = 0; return ret_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); @@ -489,7 +489,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, @@ -498,7 +498,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, // CAN_BAUDRATE From 3f04346145e3d730e8b20753be1afd470a9ad4ac Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:25:18 +0100 Subject: [PATCH 038/180] Integrated you docs with existing one --- docs/esp32/quickref.rst | 10 ++++++---- docs/library/esp32.rst | 8 ++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 846d194a43a5a..2b8893c45881a 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -328,6 +328,8 @@ pins can be used for SCL and SDA. The driver is accessed via the CAN bus ------- +See :ref:`esp32.CAN ` :: + The CAN driver is based on hardware implementation. Any available output-capablepins can be used for SCL and SDA. The driver is accessed via the :ref:`machine.CAN ` class:: @@ -335,10 +337,10 @@ The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN # construct a CAN bus - bus = CAN(tx=4, rx=2, baudrate=500, mode=CAN.MODE_NO_ACK) - - bus.send([0,1,2,3], 0x86, self_flag=True) #Send a self message - bus.recv() #Read the message sent + bus = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) + + bus.send([0,1,2,3], 0x86) #Send the message + bus.recv() #Read the message sent Real time clock (RTC) diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index a593965ae2740..4cd7efc3949e5 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -109,3 +109,11 @@ Constants esp32.WAKEUP_ANY_HIGH Selects the wake level for pins. + +Classes +------- + +.. toctree:: + :maxdepth: 1 + + esp32.CAN.rst From c346b591af0f7e7eab945cbc5e4d92b9b1bb17ae Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 20 Dec 2019 18:52:51 +0100 Subject: [PATCH 039/180] Code cleaning --- ports/esp32/machine_can.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index c8118de30b408..d48c68b0093c3 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -117,9 +117,9 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { can_status_info_t status = _machine_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); - list->items[2] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_warning - list->items[3] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_passive - list->items[4] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_bus_off + list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); + list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); + list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); list->items[7] = mp_const_none; @@ -217,7 +217,6 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ if (status != ESP_OK){ mp_raise_OSError(-status); } - //TODO: manage callback // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; @@ -298,10 +297,8 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p }else{ mp_printf(print, "CAN Device is not initialized"); } - } - // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); @@ -343,7 +340,7 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) { //TODO: check naming convention + if (can_idx > 1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } machine_can_obj_t *self = &machine_can_obj; @@ -386,11 +383,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // Check if device was already configured - if (self->config->initialized){ - //TODO: check if this condition is redundant compared to init() - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN device is already initialized")); - return mp_const_none; + return mp_const_none; } // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int & 0x0F, @@ -466,7 +459,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg return mp_const_none; } - STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, From d13310e850e17c8c3864bb0ef8ee426d55da7b1f Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 20 Dec 2019 18:53:14 +0100 Subject: [PATCH 040/180] WIP: first implementation of filters --- ports/esp32/machine_can.c | 49 +++++++++++++++++++++++++++++++++++++++ ports/esp32/machine_can.h | 9 ++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index d48c68b0093c3..97ddc7afb5f9f 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -275,6 +275,54 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +// bank: 1 or 2(only for std) +// mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL +// params: [id, mask] +// rtr: ignored if FILTER_RAW +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, + }; + + // parse args + machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + size_t len; + mp_obj_t *params; + mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); + if(len != 2){ + mp_raise_ValueError("params shall be a 2-values list"); + } + bool single_filter = (args[ARG_mode].u_int==FILTER_ADDR_SINGLE || args[ARG_mode].u_int==FILTER_RAW_SINGLE); + if (args[ARG_bank].u_int<0 || (args[ARG_bank].u_int > (single_filter ? 1 : 2))){ + mp_raise_ValueError("selected bank is not available"); + } + can_filter_config_t *filter = self->config->filter; + if (args[ARG_mode].u_int==FILTER_RAW_DUAL || args[ARG_mode].u_int==FILTER_RAW_DUAL){ + filter->single_filter = single_filter; + filter->acceptance_code = params[0]; + filter->acceptance_mask = params[1]; // FIXME: check if order is right + }else{ + if (self->extframe && !single_filter){ + mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL") + } + if (filter->single_filter==true & single_filter==false){ + // Switch to dual filter from single filter + filter->single_filter = single_filter; + filter->acceptance_code = 0; + filter->acceptance_mask = 0xFFFFFFFF; + } + + } + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter);s STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -403,6 +451,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); + f_config->single_filter = self->extframe; self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3e91588682ab0..704e6daa3f134 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,9 +43,16 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 +typedef enum _filter_mode_t{ + FILTER_RAW_SINGLE = 0, + FILTER_RAW_DUAL, + FILTER_ADDR_SINGLE, + FILTER_ADDR_DUAL +} + typedef struct _machine_can_config_t { const can_timing_config_t *timing; - const can_filter_config_t *filter; + can_filter_config_t *filter; //FIXME: point to this variable for setting const can_general_config_t *general; uint16_t baudrate; bool initialized; From 34053452891f494cb2f4a18533cf55d141db87c8 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 20 Dec 2019 18:55:45 +0100 Subject: [PATCH 041/180] WIP --- ports/esp32/machine_can.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 97ddc7afb5f9f..913be60994d14 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -71,6 +71,10 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } +STATIC void _machine_hw_can_set_filter(uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ + //addr = addr & () +} + // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ uint32_t status = can_initiate_recovery(); @@ -318,7 +322,7 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args filter->acceptance_code = 0; filter->acceptance_mask = 0xFFFFFFFF; } - + uint32_t addr = params[0] & (self->extframe ? 0x1FFFFFFF : 0x7FF) } } From c43aef3e0315dce8af951c83e861b1ed7c762822 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sat, 21 Dec 2019 11:41:37 +0100 Subject: [PATCH 042/180] Syntax Correction --- .gitignore | 3 +++ ports/esp32/machine_can.c | 17 ++++++++--------- ports/esp32/machine_can.h | 2 +- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 50bd30e877e87..a4ef09599ecb6 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ user.props # Generated rst files ###################### genrst/ +docs/_build +.vscode +esp-idf diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 913be60994d14..f2df6e41f20e1 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -106,6 +106,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); @@ -310,23 +311,23 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args can_filter_config_t *filter = self->config->filter; if (args[ARG_mode].u_int==FILTER_RAW_DUAL || args[ARG_mode].u_int==FILTER_RAW_DUAL){ filter->single_filter = single_filter; - filter->acceptance_code = params[0]; - filter->acceptance_mask = params[1]; // FIXME: check if order is right + filter->acceptance_code = mp_obj_get_int(params[0]); + filter->acceptance_mask = mp_obj_get_int(params[1]); // FIXME: check if order is right }else{ if (self->extframe && !single_filter){ - mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL") + mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL"); } - if (filter->single_filter==true & single_filter==false){ + if (filter->single_filter==true && single_filter==false){ // Switch to dual filter from single filter filter->single_filter = single_filter; filter->acceptance_code = 0; filter->acceptance_mask = 0xFFFFFFFF; } - uint32_t addr = params[0] & (self->extframe ? 0x1FFFFFFF : 0x7FF) + uint32_t addr = mp_obj_get_int(params[0]) & (self->extframe ? 0x1FFFFFFF : 0x7FF); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter);s +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -435,8 +436,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - return mp_const_none; - } // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int & 0x0F, .tx_io = args[ARG_tx_io].u_int, @@ -455,7 +454,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); - f_config->single_filter = self->extframe; + f_config.single_filter = self->extframe; self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 704e6daa3f134..b5d1db38fa8e2 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -48,7 +48,7 @@ typedef enum _filter_mode_t{ FILTER_RAW_DUAL, FILTER_ADDR_SINGLE, FILTER_ADDR_DUAL -} +} filter_mode_t; typedef struct _machine_can_config_t { const can_timing_config_t *timing; From 68a3880fe526035ca93646ce482001dce3553341 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 22 Dec 2019 16:56:32 +0100 Subject: [PATCH 043/180] CAN configuration is stored in object struct --- ports/esp32/machine_can.c | 64 +++++++++++++++++++++------------------ ports/esp32/machine_can.h | 6 ++-- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f2df6e41f20e1..0c77e552ef7d9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -54,9 +54,9 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), - .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), - .timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()), +machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2,4,0), + .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), + .timing = CAN_TIMING_CONFIG_25KBITS(), .initialized = false}; STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; @@ -333,7 +333,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->config->initialized){ qstr mode; - switch(self->config->general->mode){ + switch(self->config->general.mode){ case CAN_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; case CAN_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; @@ -341,8 +341,8 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", - self->config->general->tx_io, - self->config->general->rx_io, + self->config->general.tx_io, + self->config->general.rx_io, self->config->baudrate, mode, self->loopback, @@ -437,29 +437,29 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // Configure device - can_general_config_t g_config = {.mode = args[ARG_mode].u_int & 0x0F, - .tx_io = args[ARG_tx_io].u_int, - .rx_io = args[ARG_rx_io].u_int, - .clkout_io = CAN_IO_UNUSED, - .bus_off_io = CAN_IO_UNUSED, - .tx_queue_len = args[ARG_tx_queue].u_int, - .rx_queue_len = args[ARG_rx_queue].u_int, - .alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || - CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF, - .clkout_divider = 0}; - self->config->general = &g_config; + self->config->general.mode = args[ARG_mode].u_int & 0x0F; + self->config->general.tx_io = args[ARG_tx_io].u_int; + self->config->general.rx_io = args[ARG_rx_io].u_int; + self->config->general.clkout_io = CAN_IO_UNUSED; + self->config->general.bus_off_io = CAN_IO_UNUSED; + self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; + self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; + self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || + CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; + self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; if (args[ARG_auto_restart].u_bool){ mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); - f_config.single_filter = self->extframe; - self->config->filter = &f_config; - + self->config->filter.single_filter = self->extframe; + self->config->filter.acceptance_code = f_config.acceptance_code; + self->config->filter.acceptance_mask = f_config.acceptance_mask; + can_timing_config_t *timing; switch ((int)args[ARG_baudrate].u_int){ case 0: - self->config->timing = &((can_timing_config_t){ + timing = &((can_timing_config_t){ .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, @@ -467,37 +467,41 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .triple_sampling = false}); break; case CAN_BAUDRATE_25k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); break; case CAN_BAUDRATE_50k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); break; case CAN_BAUDRATE_100k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); break; case CAN_BAUDRATE_125k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); break; case CAN_BAUDRATE_250k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); break; case CAN_BAUDRATE_500k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); break; case CAN_BAUDRATE_800k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); break; case CAN_BAUDRATE_1M: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); break; default: mp_raise_ValueError("Unable to set baudrate"); self->config->baudrate = 0; return mp_const_none; } + self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - uint32_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); + uint32_t status = can_driver_install( + &self->config->general, + &self->config->timing, + &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); //self->config->filter); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index b5d1db38fa8e2..c4c9cc4c34c48 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -51,9 +51,9 @@ typedef enum _filter_mode_t{ } filter_mode_t; typedef struct _machine_can_config_t { - const can_timing_config_t *timing; - can_filter_config_t *filter; //FIXME: point to this variable for setting - const can_general_config_t *general; + can_timing_config_t timing; + can_filter_config_t filter; + can_general_config_t general; uint16_t baudrate; bool initialized; } machine_can_config_t; From 960435c1fc1ed264a419f8c95937bd17f75c5fe4 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 22 Dec 2019 16:59:27 +0100 Subject: [PATCH 044/180] Bugfixes --- ports/esp32/machine_can.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0c77e552ef7d9..2cee0bbd01348 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -64,7 +64,7 @@ STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_co // INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; - uint8_t err_code = can_get_status_info(&status); + uint32_t err_code = can_get_status_info(&status); if(err_code!=ESP_OK){ mp_raise_OSError(-err_code); } @@ -182,10 +182,11 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; + }else{ + id &= 0x1FF; } if (self->loopback){ flags += CAN_MSG_FLAG_SELF; - id &= 0x1FF; } can_message_t tx_msg = {.data_length_code = length, .identifier = id, @@ -431,7 +432,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; From 7b9a9a904f04f74bec3aef7a3111c804aef7c20c Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 22 Dec 2019 17:04:08 +0100 Subject: [PATCH 045/180] WIP: implementation of setfilter() --- ports/esp32/machine_can.c | 71 ++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 2cee0bbd01348..cf5e8046f31a9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -71,8 +71,29 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } -STATIC void _machine_hw_can_set_filter(uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ - //addr = addr & () +//INTERNAL FUNCTION Populates the filter register according to inputs +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ + //Check if bank is allowed + if (bank<0 && bank>((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ + mp_raise_ValueError("CAN filter parameter error"); + } + uint32_t preserve_mask; + if (self->extframe){ + addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); + mask = (mask & 0x1FFFFFFF) << 3 | 0x04; + preserve_mask = 0; + }else{ + addr = ((addr & 0x7FF) | (rtr ? 0x800 : 0)) << (bank==1 ? 16 : 0); + mask = ((mask & 0x7FF) | 0x800) << (bank==1 ? 16 : 0); + preserve_mask = 0xFFFF << (bank==0 ? 16 : 0);; + } + ESP_LOGI(DEVICE_NAME, "Address: %08X",addr); + ESP_LOGI(DEVICE_NAME, "Mask: %08X", mask); + ESP_LOGI(DEVICE_NAME, "Preserve: %08X", preserve_mask); + self->config->filter.acceptance_code &= preserve_mask; + self->config->filter.acceptance_code |= addr; + self->config->filter.acceptance_mask &= preserve_mask; + self->config->filter.acceptance_mask |= mask; } // Force a software restart of the controller, to allow transmission after a bus error @@ -281,7 +302,7 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); -// bank: 1 or 2(only for std) +// bank: 0 or 1(only for std) // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW @@ -301,32 +322,31 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; - mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); + mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); if(len != 2){ mp_raise_ValueError("params shall be a 2-values list"); } - bool single_filter = (args[ARG_mode].u_int==FILTER_ADDR_SINGLE || args[ARG_mode].u_int==FILTER_RAW_SINGLE); - if (args[ARG_bank].u_int<0 || (args[ARG_bank].u_int > (single_filter ? 1 : 2))){ - mp_raise_ValueError("selected bank is not available"); - } - can_filter_config_t *filter = self->config->filter; - if (args[ARG_mode].u_int==FILTER_RAW_DUAL || args[ARG_mode].u_int==FILTER_RAW_DUAL){ - filter->single_filter = single_filter; - filter->acceptance_code = mp_obj_get_int(params[0]); - filter->acceptance_mask = mp_obj_get_int(params[1]); // FIXME: check if order is right + uint32_t id = mp_obj_get_int(params[0]); + uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask + if (args[ARG_mode].u_int==FILTER_RAW_SINGLE || args[ARG_mode].u_int==FILTER_RAW_DUAL){ + self->config->filter.single_filter = (args[ARG_mode].u_int==FILTER_RAW_SINGLE); + self->config->filter.acceptance_code = id; + self->config->filter.acceptance_mask = mask; }else{ - if (self->extframe && !single_filter){ - mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL"); - } - if (filter->single_filter==true && single_filter==false){ - // Switch to dual filter from single filter - filter->single_filter = single_filter; - filter->acceptance_code = 0; - filter->acceptance_mask = 0xFFFFFFFF; - } - uint32_t addr = mp_obj_get_int(params[0]) & (self->extframe ? 0x1FFFFFFF : 0x7FF); + _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } +ESP_LOGI(DEVICE_NAME, "New Code: %08X",self->config->filter.acceptance_code); +ESP_LOGI(DEVICE_NAME, "New Mask: %08X",self->config->filter.acceptance_mask); + ESP_STATUS_CHECK(can_stop()); + ESP_STATUS_CHECK(can_driver_uninstall()); + ESP_STATUS_CHECK(can_driver_install( + &self->config->general, + &self->config->timing, + &self->config->filter)); + ESP_STATUS_CHECK(can_start()); + ESP_LOGI(DEVICE_NAME, "Restarted"); + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -528,6 +548,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, /* { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, @@ -559,6 +580,10 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, + // CAN_FILTER_MODE + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, // CAN_ALERT { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, From 96721c9367ff7acfe368614c606a41d0c7072d1f Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:49:17 +0100 Subject: [PATCH 046/180] Completed setfilter() --- ports/esp32/machine_can.c | 32 ++++++++++++++++++++------------ ports/esp32/machine_can.h | 4 ++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index cf5e8046f31a9..272b05126cf72 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -80,16 +80,27 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u uint32_t preserve_mask; if (self->extframe){ addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); - mask = (mask & 0x1FFFFFFF) << 3 | 0x04; + mask = (mask & 0x1FFFFFFF) << 3 | 0x03; + preserve_mask = 0; + }else if(self->config->filter.single_filter){ + addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); + mask = ((mask & 0x7FF) << 5); + mask |= 0xFFFFF000; preserve_mask = 0; }else{ - addr = ((addr & 0x7FF) | (rtr ? 0x800 : 0)) << (bank==1 ? 16 : 0); - mask = ((mask & 0x7FF) | 0x800) << (bank==1 ? 16 : 0); - preserve_mask = 0xFFFF << (bank==0 ? 16 : 0);; + addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); + mask = ((mask & 0x7FF) << 5); + preserve_mask = 0xFFFF << (bank==0 ? 16 : 0); + if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank==0 ? 16 : 0))){ + // Other filter accepts all; it will replaced duplicating current filter + addr = addr | (addr << 16); + mask = mask | (mask << 16); + preserve_mask = 0; + }else{ + addr = addr << (bank==1 ? 16 : 0); + mask = mask << (bank==1 ? 16 : 0); + } } - ESP_LOGI(DEVICE_NAME, "Address: %08X",addr); - ESP_LOGI(DEVICE_NAME, "Mask: %08X", mask); - ESP_LOGI(DEVICE_NAME, "Preserve: %08X", preserve_mask); self->config->filter.acceptance_code &= preserve_mask; self->config->filter.acceptance_code |= addr; self->config->filter.acceptance_mask &= preserve_mask; @@ -333,11 +344,9 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; }else{ + self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - -ESP_LOGI(DEVICE_NAME, "New Code: %08X",self->config->filter.acceptance_code); -ESP_LOGI(DEVICE_NAME, "New Mask: %08X",self->config->filter.acceptance_mask); ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( @@ -345,7 +354,6 @@ ESP_LOGI(DEVICE_NAME, "New Mask: %08X",self->config->filter.acceptance_mask); &self->config->timing, &self->config->filter)); ESP_STATUS_CHECK(can_start()); - ESP_LOGI(DEVICE_NAME, "Restarted"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -522,7 +530,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg uint32_t status = can_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); //self->config->filter); + &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index c4c9cc4c34c48..a79a23271345a 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,11 +43,11 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 +#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, - FILTER_ADDR_SINGLE, - FILTER_ADDR_DUAL + FILTER_ADDRESS } filter_mode_t; typedef struct _machine_can_config_t { From 89208858af0579367bbcbf9871b1f785fe0606e1 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:49:34 +0100 Subject: [PATCH 047/180] added clearfilter() --- ports/esp32/machine_can.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 272b05126cf72..fddba0ccc8778 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -313,6 +313,22 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->config->filter.single_filter = self->extframe; + self->config->filter.acceptance_code = 0; + self->config->filter.acceptance_mask = 0xFFFFFFFF; + ESP_STATUS_CHECK(can_stop()); + ESP_STATUS_CHECK(can_driver_uninstall()); + ESP_STATUS_CHECK(can_driver_install( + &self->config->general, + &self->config->timing, + &self->config->filter)); + ESP_STATUS_CHECK(can_start()); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); + // bank: 0 or 1(only for std) // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] @@ -557,12 +573,8 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, - /* - { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, - { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, - */ - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, // ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, From 2c6b6f4f64878a3093ada218e486f2d844ad3c62 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:50:07 +0100 Subject: [PATCH 048/180] Added unittest as example --- examples/esp32_can.py | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 examples/esp32_can.py diff --git a/examples/esp32_can.py b/examples/esp32_can.py new file mode 100644 index 0000000000000..b5c4966a04dbc --- /dev/null +++ b/examples/esp32_can.py @@ -0,0 +1,68 @@ +from machine import CAN +import time + +def sendAndCheck(dev, name, id, expectedLP = True): + dev.clear_tx_queue() + dev.clear_rx_queue() + dev.send([], id) + time.sleep_ms(100) + if dev.any() == expectedLP: + print("{}: OK".format(name)) + if expectedLP: + dev.recv() + else: + print("{}: FAILED".format(name)) + +dev = CAN(0, + extframe=False, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18,rx_io=19, auto_restart=False) + +#Test send/receive message +print("Loopback Test: no filter - STD") +sendAndCheck(dev, "No filter", 0x100, True) + +#Set filter1 +print("Loopback Test: one filter - STD") +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) +sendAndCheck(dev, "Passing Message", 0x101, True) +sendAndCheck(dev, "Blocked Message", 0x100, False) + +#Set filter2 +print("Loopback Test: second filter - STD") +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) +sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) +sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) +sendAndCheck(dev, "Blocked Message", 0x100, False) + +#Remove filter +print("Loopback Test: clear filter - STD") +dev.clearfilter() +sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) +sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) +sendAndCheck(dev, "Passing any Message", 0x100, True) + +#Move to Extended +dev = CAN(0, + extframe=True, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18,rx_io=19, auto_restart=False) + +#Test send/receive message +print("Loopback Test: no filter - Extd") +sendAndCheck(dev, "No filter", 0x100, True) + +#Set filter1 +print("Loopback Test: one filter - Extd") +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) +sendAndCheck(dev, "Passing Message", 0x101, True) +sendAndCheck(dev, "Blocked Message", 0x100, False) + +#Remove filter +print("Loopback Test: clear filter - Extd") +dev.clearfilter() +sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) +sendAndCheck(dev, "Passing any Message", 0x100, True) + From 5432a7d884c2b50d5237376e745d52c6a143c52b Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:58:51 +0100 Subject: [PATCH 049/180] removed machine_can.h --- ports/esp32/machine_can.c | 49 ++++++++++++++++++++++- ports/esp32/machine_can.h | 83 --------------------------------------- 2 files changed, 47 insertions(+), 85 deletions(-) delete mode 100644 ports/esp32/machine_can.h diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index fddba0ccc8778..0ffbf7e88382a 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -37,10 +37,55 @@ #include "esp_err.h" #include "esp_log.h" -#include +#include "modmachine.h" #if MICROPY_HW_ENABLE_CAN +#define DEVICE_NAME "CAN" + +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 + +#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} +typedef enum _filter_mode_t{ + FILTER_RAW_SINGLE = 0, + FILTER_RAW_DUAL, + FILTER_ADDRESS +} filter_mode_t; + +typedef struct _machine_can_config_t { + can_timing_config_t timing; + can_filter_config_t filter; + can_general_config_t general; + uint16_t baudrate; + bool initialized; +} machine_can_config_t; + +typedef struct _machine_can_obj_t { + mp_obj_base_t base; + machine_can_config_t *config; + mp_obj_t rxcallback; + byte rx_state; + bool extframe : 1; + bool loopback : 1; + uint16_t num_error_warning; //FIXME: populate this value somewhere + uint16_t num_error_passive; + uint16_t num_bus_off; +} machine_can_obj_t; + +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + // Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) @@ -113,7 +158,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ if (status != ESP_OK){ mp_raise_OSError(-status); } - mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution + mp_hal_delay_ms(200); // TODO: replace it with a smarter solution status = can_start(); if (status != ESP_OK){ mp_raise_OSError(-status); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h deleted file mode 100644 index a79a23271345a..0000000000000 --- a/ports/esp32/machine_can.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Musumeci Salvatore - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ESP32_CAN_H -#define MICROPY_INCLUDED_ESP32_CAN_H - -#include "modmachine.h" - -#include "py/obj.h" - -#if MICROPY_HW_ENABLE_CAN - -#define DEVICE_NAME "CAN" - -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 - -#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} -typedef enum _filter_mode_t{ - FILTER_RAW_SINGLE = 0, - FILTER_RAW_DUAL, - FILTER_ADDRESS -} filter_mode_t; - -typedef struct _machine_can_config_t { - can_timing_config_t timing; - can_filter_config_t filter; - can_general_config_t general; - uint16_t baudrate; - bool initialized; -} machine_can_config_t; - -typedef struct _machine_can_obj_t { - mp_obj_base_t base; - machine_can_config_t *config; - mp_obj_t rxcallback; - byte rx_state; - bool extframe : 1; - bool loopback : 1; - uint16_t num_error_warning; //FIXME: populate this value somewhere - uint16_t num_error_passive; - uint16_t num_bus_off; -} machine_can_obj_t; - -typedef enum _rx_state_t { - RX_STATE_FIFO_EMPTY = 0, - RX_STATE_MESSAGE_PENDING, - RX_STATE_FIFO_FULL, - RX_STATE_FIFO_OVERFLOW, -} rx_state_t; - -extern const mp_obj_type_t machine_can_type; - -#endif // MICROPY_HW_ENABLE_CAN -#endif // MICROPY_INCLUDED_ESP32_CAN_H From 2616b9e96f30260199379bdda185e024c770b8e9 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 10:00:58 +0100 Subject: [PATCH 050/180] Bugfix --- ports/esp32/modmachine.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 894ad2f6d9ac7..067e909d5bb65 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -253,7 +253,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, + #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, From f5ed914023b2f5c66fa4d153fd0456c0c5527173 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 10:18:52 +0100 Subject: [PATCH 051/180] Docs updated --- docs/library/esp32.CAN.rst | 77 +++++++++++++------------------------- ports/esp32/machine_can.c | 6 ++- 2 files changed, 30 insertions(+), 53 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index e17e9f4a5598f..0a35accdf630a 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -32,17 +32,6 @@ Constructors The physical pins of the CAN bus can be assigned during init. -Class Methods -------------- -.. classmethod:: CAN.initfilterbanks(nr) TODO: - - Reset and disable all filter banks and assign how many banks should be available for CAN(1). - - STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. - This function configures how many filter banks should be assigned to each. *nr* is the number of banks - that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). - At boot, 14 banks are assigned to each controller. - Methods ------- @@ -122,53 +111,37 @@ Methods - number of pending RX messages - Reserved -.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) TODO: +.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) Configure a filter bank: - - *bank* is the filter bank that is to be configured. + - *bank* is the filter bank that is to be configured (0 for extended, 0 or 1 for standard msg) - *mode* is the mode the filter should operate in. - - *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. - - *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument. + - *params* is an array of two values that defines the filter. + The first element will be the id to filter and the second element will be the mask to apply. + mask bit implementation considers 1 as a don't care state and 0 as a check state. - +-----------+---------------------------------------------------------+ + +----------------------+----------------------------------------------+ |*mode* |contents of *params* array | - +===========+=========================================================+ - |CAN.LIST16 |Four 16 bit ids that will be accepted | - +-----------+---------------------------------------------------------+ - |CAN.LIST32 |Two 32 bit ids that will be accepted | - +-----------+---------------------------------------------------------+ - |CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | - | | | The first pair, 1 and 3 will accept all ids | - | | | that have bit 0 = 1 and bit 1 = 0. | - | | | The second pair, 4 and 4, will accept all ids | - | | | that have bit 2 = 1. | - +-----------+---------------------------------------------------------+ - |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| - +-----------+---------------------------------------------------------+ - - - *rtr* is an array of booleans that states if a filter should accept a - remote transmission request message. If this argument is not given - then it defaults to ``False`` for all entries. The length of the array - depends on the *mode* argument. - - +-----------+----------------------+ - |*mode* |length of *rtr* array | - +===========+======================+ - |CAN.LIST16 |4 | - +-----------+----------------------+ - |CAN.LIST32 |2 | - +-----------+----------------------+ - |CAN.MASK16 |2 | - +-----------+----------------------+ - |CAN.MASK32 |1 | - +-----------+----------------------+ - -.. method:: CAN.clearfilter(bank) TODO: - - Clear and disables a filter bank: - - - *bank* is the filter bank that is to be cleared. + +======================+==============================================+ + |CAN.FILTER_RAW_SINGLE | *params* will be copied in hardware variable | + | | and single_filter_mode will be selected | + | | In this mode, *bank* will be ignored | + +----------------------+----------------------------------------------+ + |CAN.FILTER_RAW_DUAL | *params* will be copied in hardware variable | + | | and single_filter_mode will be cleared | + | | In this mode, *bank* will be ignored | + +----------------------+----------------------------------------------+ + |CAN.FILTER_ADDRESS | *params* will be set in hardware registers | + | | according to *bank* selection | + +----------------------+----------------------------------------------+ + + - *rtr* is bool that states if a filter should accept a remote transmission request message. + If this argument is not given then it defaults to ``False``. + +.. method:: CAN.clearfilter(bank) + + Clear and disables all filters .. method:: CAN.any(fifo) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0ffbf7e88382a..ac5455aaed451 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -209,6 +209,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); +// Get Alert info STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); @@ -358,6 +359,7 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +// Clear filters setting STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; @@ -378,6 +380,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW +// Set CAN HW filter STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr }; static const mp_arg_t allowed_args[] = { @@ -674,4 +677,5 @@ const mp_obj_type_t machine_can_type = { .make_new = machine_hw_can_make_new, // give it a constructor .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members }; -#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file +#endif // MICROPY_HW_ENABLE_CAN + \ No newline at end of file From ef0ae9f1415d8d470f52f14c7e05a0fe5fa6fe7f Mon Sep 17 00:00:00 2001 From: Salvo Musumeci Date: Mon, 23 Dec 2019 10:23:12 +0100 Subject: [PATCH 052/180] Update Author name --- ports/esp32/machine_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index ac5455aaed451..dcdda0d2f7442 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -1,6 +1,6 @@ /* The MIT License (MIT) * - * Copyright (c) 2019 Damien P. George + * Copyright (c) 2019 Musumeci Salvatore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -678,4 +678,4 @@ const mp_obj_type_t machine_can_type = { .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members }; #endif // MICROPY_HW_ENABLE_CAN - \ No newline at end of file + From e5a7e9d3b18ebba417c18f76a7ecbd6bbbd5fc70 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 10:25:52 +0100 Subject: [PATCH 053/180] remove .vscode folder --- .vscode/c_cpp_properties.json | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 5f0824b540e6b..0000000000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "${workspaceFolder}/../esp-idf/components/**", - "${workspaceFolder}/ports/esp32/**", - "${workspaceFolder}/**" - ], - "defines": [], - "macFrameworkPath": [ - "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks" - ], - "compilerPath": "/usr/bin/clang", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "clang-x64" - } - ], - "version": 4 -} \ No newline at end of file From 66c8a3227c92a75e8582d4f86f87a6f8c72da6b7 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:09:13 +0100 Subject: [PATCH 054/180] Formatting sources --- examples/esp32_can.py | 37 +-- ports/esp32/machine_can.c | 636 +++++++++++++++++++++++--------------- 2 files changed, 399 insertions(+), 274 deletions(-) diff --git a/examples/esp32_can.py b/examples/esp32_can.py index b5c4966a04dbc..495370bb1d5e8 100644 --- a/examples/esp32_can.py +++ b/examples/esp32_can.py @@ -1,7 +1,8 @@ from machine import CAN import time -def sendAndCheck(dev, name, id, expectedLP = True): + +def sendAndCheck(dev, name, id, expectedLP=True): dev.clear_tx_queue() dev.clear_rx_queue() dev.send([], id) @@ -13,56 +14,56 @@ def sendAndCheck(dev, name, id, expectedLP = True): else: print("{}: FAILED".format(name)) + dev = CAN(0, - extframe=False, - mode=CAN.SILENT_LOOPBACK, - baudrate=CAN.BAUDRATE_500k, - tx_io=18,rx_io=19, auto_restart=False) + extframe=False, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18, rx_io=19, auto_restart=False) -#Test send/receive message +# Test send/receive message print("Loopback Test: no filter - STD") sendAndCheck(dev, "No filter", 0x100, True) -#Set filter1 +# Set filter1 print("Loopback Test: one filter - STD") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) sendAndCheck(dev, "Passing Message", 0x101, True) sendAndCheck(dev, "Blocked Message", 0x100, False) -#Set filter2 +# Set filter2 print("Loopback Test: second filter - STD") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) sendAndCheck(dev, "Blocked Message", 0x100, False) -#Remove filter +# Remove filter print("Loopback Test: clear filter - STD") dev.clearfilter() sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) sendAndCheck(dev, "Passing any Message", 0x100, True) -#Move to Extended +# Move to Extended dev = CAN(0, - extframe=True, - mode=CAN.SILENT_LOOPBACK, - baudrate=CAN.BAUDRATE_500k, - tx_io=18,rx_io=19, auto_restart=False) + extframe=True, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18, rx_io=19, auto_restart=False) -#Test send/receive message +# Test send/receive message print("Loopback Test: no filter - Extd") sendAndCheck(dev, "No filter", 0x100, True) -#Set filter1 +# Set filter1 print("Loopback Test: one filter - Extd") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) sendAndCheck(dev, "Passing Message", 0x101, True) sendAndCheck(dev, "Blocked Message", 0x100, False) -#Remove filter +# Remove filter print("Loopback Test: clear filter - Extd") dev.clearfilter() sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) sendAndCheck(dev, "Passing any Message", 0x100, True) - diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index dcdda0d2f7442..7dfc8729c6178 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -52,22 +52,29 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 -#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} -typedef enum _filter_mode_t{ +#define ESP_STATUS_CHECK(status) \ + if (status != ESP_OK) \ + { \ + mp_raise_OSError(-status); \ + } +typedef enum _filter_mode_t +{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t { +typedef struct _machine_can_config_t +{ can_timing_config_t timing; - can_filter_config_t filter; + can_filter_config_t filter; can_general_config_t general; uint16_t baudrate; bool initialized; } machine_can_config_t; -typedef struct _machine_can_obj_t { +typedef struct _machine_can_obj_t +{ mp_obj_base_t base; machine_can_config_t *config; mp_obj_t rxcallback; @@ -79,7 +86,8 @@ typedef struct _machine_can_obj_t { uint16_t num_bus_off; } machine_can_obj_t; -typedef enum _rx_state_t { +typedef enum _rx_state_t +{ RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, @@ -87,11 +95,10 @@ typedef enum _rx_state_t { } rx_state_t; // Default baudrate: 500kb -#define CAN_DEFAULT_PRESCALER (8) -#define CAN_DEFAULT_SJW (3) -#define CAN_DEFAULT_BS1 (15) -#define CAN_DEFAULT_BS2 (4) - +#define CAN_DEFAULT_PRESCALER (8) +#define CAN_DEFAULT_SJW (3) +#define CAN_DEFAULT_BS1 (15) +#define CAN_DEFAULT_BS2 (4) // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); @@ -99,51 +106,63 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2,4,0), +machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), .timing = CAN_TIMING_CONFIG_25KBITS(), .initialized = false}; - -STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; + +STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config = &can_config}; // INTERNAL FUNCTION Return status information -STATIC can_status_info_t _machine_hw_can_get_status(){ +STATIC can_status_info_t _machine_hw_can_get_status() +{ can_status_info_t status; uint32_t err_code = can_get_status_info(&status); - if(err_code!=ESP_OK){ + if (err_code != ESP_OK) + { mp_raise_OSError(-err_code); } return status; } //INTERNAL FUNCTION Populates the filter register according to inputs -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) +{ //Check if bank is allowed - if (bank<0 && bank>((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ + if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)) + { mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; - if (self->extframe){ + if (self->extframe) + { addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - }else if(self->config->filter.single_filter){ + } + else if (self->config->filter.single_filter) + { addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); + mask = ((mask & 0x7FF) << 5); mask |= 0xFFFFF000; preserve_mask = 0; - }else{ + } + else + { addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); - preserve_mask = 0xFFFF << (bank==0 ? 16 : 0); - if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank==0 ? 16 : 0))){ + mask = ((mask & 0x7FF) << 5); + preserve_mask = 0xFFFF << (bank == 0 ? 16 : 0); + if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))) + { // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); preserve_mask = 0; - }else{ - addr = addr << (bank==1 ? 16 : 0); - mask = mask << (bank==1 ? 16 : 0); + } + else + { + addr = addr << (bank == 1 ? 16 : 0); + mask = mask << (bank == 1 ? 16 : 0); } } self->config->filter.acceptance_code &= preserve_mask; @@ -153,14 +172,17 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u } // Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) +{ uint32_t status = can_initiate_recovery(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } mp_hal_delay_ms(200); // TODO: replace it with a smarter solution status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } return mp_const_none; @@ -168,31 +190,39 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) +{ can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_bool((status.msgs_to_rx)>0); + return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) +{ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) +{ machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; - if (n_args == 1) { + if (n_args == 1) + { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - } else { - if (!mp_obj_is_type(args[1], &mp_type_list)) { + } + else + { + if (!mp_obj_is_type(args[1], &mp_type_list)) + { mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); - if (list->len < 8) { + if (list->len < 8) + { mp_raise_ValueError(NULL); } } @@ -210,10 +240,12 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) +{ uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } return mp_obj_new_int(alerts); @@ -221,75 +253,99 @@ STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ - return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) +{ + return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ - return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) +{ + return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); - // send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_data, + ARG_id, + ARG_timeout, + ARG_rtr, + ARG_self + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + {MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, }; - + // parse args machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // populate message size_t length; mp_obj_t *items; - mp_obj_get_array(args[ARG_data].u_obj,&length, &items); - if (length>8){ + mp_obj_get_array(args[ARG_data].u_obj, &length, &items); + if (length > 8) + { mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool==true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + uint8_t flags = (args[ARG_rtr].u_bool == true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; - if (self->extframe){ + if (self->extframe) + { flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; - }else{ + } + else + { id &= 0x1FF; } - if (self->loopback){ + if (self->loopback) + { flags += CAN_MSG_FLAG_SELF; } - can_message_t tx_msg = {.data_length_code = length, - .identifier = id, + can_message_t tx_msg = {.data_length_code = length, + .identifier = id, .flags = flags}; - for (uint8_t i=0; iitems; + items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - } else { + } + else + { // User should provide a list of length at least 4 to hold the values - if (!mp_obj_is_type(ret_obj, &mp_type_list)) { + if (!mp_obj_is_type(ret_obj, &mp_type_list)) + { mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); - if (list->len < 4) { + if (list->len < 4) + { mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace - if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { + if (!mp_obj_is_type(items[3], &mp_type_memoryview)) + { mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); - if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) - || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) + { mp_raise_ValueError(NULL); } mv->len = rx_message.data_length_code; memcpy(mv->items, rx_message.data, rx_message.data_length_code); - } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; @@ -340,18 +402,24 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) +{ mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (callback_in == mp_const_none) { + if (callback_in == mp_const_none) + { self->rxcallback = mp_const_none; - } else if (self->rxcallback != mp_const_none) { + } + else if (self->rxcallback != mp_const_none) + { // Rx call backs has already been initialized // only the callback function should be changed self->rxcallback = callback_in; // TODO: disable interrupt - } else if (mp_obj_is_callable(callback_in)) { + } + else if (mp_obj_is_callable(callback_in)) + { self->rxcallback = callback_in; // TODO: set interrupt } @@ -360,7 +428,8 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) +{ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; @@ -368,8 +437,8 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( - &self->config->general, - &self->config->timing, + &self->config->general, + &self->config->timing, &self->config->filter)); ESP_STATUS_CHECK(can_start()); return mp_const_none; @@ -381,15 +450,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr }; +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_bank, + ARG_mode, + ARG_params, + ARG_rtr + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, + {MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false}}, }; - + // parse args machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -397,58 +473,77 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; - mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if(len != 2){ + mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); + if (len != 2) + { mp_raise_ValueError("params shall be a 2-values list"); } uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int==FILTER_RAW_SINGLE || args[ARG_mode].u_int==FILTER_RAW_DUAL){ - self->config->filter.single_filter = (args[ARG_mode].u_int==FILTER_RAW_SINGLE); + if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) + { + self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; - }else{ + } + else + { self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - ESP_STATUS_CHECK(can_stop()); + ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( - &self->config->general, - &self->config->timing, + &self->config->general, + &self->config->timing, &self->config->filter)); ESP_STATUS_CHECK(can_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized){ + if (self->config->initialized) + { qstr mode; - switch(self->config->general.mode){ - case CAN_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; - case CAN_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; - case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; - default: mode = MP_QSTR_UNKNOWN; break; + switch (self->config->general.mode) + { + case CAN_MODE_LISTEN_ONLY: + mode = MP_QSTR_LISTEN; + break; + case CAN_MODE_NO_ACK: + mode = MP_QSTR_NO_ACK; + break; + case CAN_MODE_NORMAL: + mode = MP_QSTR_NORMAL; + break; + default: + mode = MP_QSTR_UNKNOWN; + break; } - mp_printf(print, - "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", - self->config->general.tx_io, - self->config->general.rx_io, - self->config->baudrate, - mode, - self->loopback, - self->extframe); - }else{ + mp_printf(print, + "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", + self->config->general.tx_io, + self->config->general.rx_io, + self->config->baudrate, + mode, + self->loopback, + self->extframe); + } + else + { mp_printf(print, "CAN Device is not initialized"); } } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized){ +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized) + { ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; } @@ -457,18 +552,22 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); // deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ - const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true){ +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) +{ + const machine_can_obj_t *self = &machine_can_obj; + if (self->config->initialized != true) + { ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } uint32_t status = can_stop(); - if(status!=ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } status = can_driver_uninstall(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } self->config->initialized = false; @@ -478,20 +577,25 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deini // CAN(bus, ...) No argument to get the object // If no arguments are provided, the initialized object will be returned -mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args){ +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args) +{ // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0])!=true){ + if (mp_obj_is_int(args[0]) != true) + { mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) { + if (can_idx > 1) + { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } - machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0) { - if (self->config->initialized) { + machine_can_obj_t *self = &machine_can_obj; + if (n_args > 1 || n_kw > 0) + { + if (self->config->initialized) + { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); @@ -509,22 +613,36 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, - ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_auto_restart}; +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_mode, + ARG_extframe, + ARG_baudrate, + ARG_prescaler, + ARG_sjw, + ARG_bs1, + ARG_bs2, + ARG_tx_io, + ARG_rx_io, + ARG_tx_queue, + ARG_rx_queue, + ARG_auto_restart + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, - { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, - { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, - { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, - { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, + {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL}}, + {MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false}}, + {MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER}}, + {MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW}}, + {MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1}}, + {MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2}}, + {MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4}}, + {MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2}}, + {MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5}}, + {MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -537,12 +655,13 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.bus_off_io = CAN_IO_UNUSED; self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; - self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || - CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; + self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || + CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; self->config->general.clkout_divider = 0; - self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); + self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool){ + if (args[ARG_auto_restart].u_bool) + { mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); @@ -550,58 +669,65 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; can_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int){ - case 0: - timing = &((can_timing_config_t){ - .brp = args[ARG_prescaler].u_int, - .sjw = args[ARG_sjw].u_int, - .tseg_1 = args[ARG_bs1].u_int, - .tseg_2 = args[ARG_bs1].u_int, - .triple_sampling = false}); - break; - case CAN_BAUDRATE_25k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); - break; - case CAN_BAUDRATE_50k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); - break; - case CAN_BAUDRATE_100k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); - break; - case CAN_BAUDRATE_125k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); - break; - case CAN_BAUDRATE_250k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); - break; - case CAN_BAUDRATE_500k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); - break; - case CAN_BAUDRATE_800k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); - break; - case CAN_BAUDRATE_1M: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); - break; - default: - mp_raise_ValueError("Unable to set baudrate"); - self->config->baudrate = 0; - return mp_const_none; + switch ((int)args[ARG_baudrate].u_int) + { + case 0: + timing = &((can_timing_config_t){ + .brp = args[ARG_prescaler].u_int, + .sjw = args[ARG_sjw].u_int, + .tseg_1 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs1].u_int, + .triple_sampling = false}); + break; + case CAN_BAUDRATE_25k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + break; + case CAN_BAUDRATE_50k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + break; + case CAN_BAUDRATE_100k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + break; + case CAN_BAUDRATE_125k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + break; + case CAN_BAUDRATE_250k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + break; + case CAN_BAUDRATE_500k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + break; + case CAN_BAUDRATE_800k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + break; + case CAN_BAUDRATE_1M: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + break; + default: + mp_raise_ValueError("Unable to set baudrate"); + self->config->baudrate = 0; + return mp_const_none; } self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - + uint32_t status = can_driver_install( - &self->config->general, - &self->config->timing, - &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); - if (status != ESP_OK){ + &self->config->general, + &self->config->timing, + &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); + if (status != ESP_OK) + { mp_raise_OSError(-status); - }else{ + } + else + { status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); - }else{ + } + else + { self->config->initialized = true; } } @@ -610,72 +736,70 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_ATTRIBUTES - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN)}, // Micropython Generic API - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, - { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, - { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, - // ESP32 Specific API - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - - { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, - // CAN_MODE - { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, - { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, - { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj)}, + {MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj)}, + {MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj)}, + {MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj)}, + {MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj)}, + {MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj)}, + {MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, + {MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + {MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj)}, + {MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj)}, + {MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj)}, + // ESP32 Specific API + {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + + {MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, + // CAN_MODE + {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL)}, + {MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10)}, + {MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK)}, + {MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10)}, + {MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY)}, // CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + {MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED)}, + {MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING)}, + {MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF)}, + {MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING)}, // CAN_BAUDRATE - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M)}, // CAN_FILTER_MODE - { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, - { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, - { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, + {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE)}, + {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL)}, + {MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS)}, // CAN_ALERT - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } -}; + {MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF)}}; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); // Python object definition const mp_obj_type_t machine_can_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t *)&machine_can_locals_dict, // and the global members }; #endif // MICROPY_HW_ENABLE_CAN - From c807e7d99cfd64bc7e71c7ea41e35b36079e6c54 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:27:47 +0100 Subject: [PATCH 055/180] Removed additional constants and added in documentation --- docs/library/esp32.CAN.rst | 20 +++++++++++++++++++- ports/esp32/machine_can.c | 25 +------------------------ 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index 0a35accdf630a..6c3ebe2f8679c 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -43,7 +43,7 @@ Methods - if *extframe* is True then the bus uses extended identifiers in the frames (29 bits); otherwise it uses standard 11 bit identifiers - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* - will be ignored. Standard speeds are available as CAN.BAUDRATE_* + will be ignored. Standard speeds are 25, 50, 100, 125, 250, 500, 1000 - *prescaler* is used to set the duration of 1 time quanta; the time quanta will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler - *sjw* is the resynchronisation jump width in units of the time quanta; @@ -210,6 +210,24 @@ Methods .. method:: CAN.get_alerts() Read the alert status word directly from hardware. + In order to save space in the firmware, the constants for the result decoding are not included on the :mod:`machine.CAN` module. Add the ones that you need from the list below to your program. + + The event codes are:: + + from micropython import const + CAN_ALERT_TX_IDLE = const(0x0001) + CAN_ALERT_TX_SUCCESS = const(0x0002) + CAN_ALERT_BELOW_ERR_WARN = const(0x0004) + CAN_ALERT_ERR_ACTIVE = const(0x0008) + CAN_ALERT_RECOVERY_IN_PROGRESS = const(0x0010) + CAN_ALERT_BUS_RECOVERED = const(0x0020) + CAN_ALERT_ARB_LOST = const(0x0040) + CAN_ALERT_ABOVE_ERR_WARN = const(0x0080) + CAN_ALERT_BUS_ERROR = const(0x0100) + CAN_ALERT_TX_FAILED = const(0x0200) + CAN_ALERT_RX_QUEUE_FULL = const(0x0400) + CAN_ALERT_ERR_PASS = const(0x0800) + CAN_ALERT_BUS_OFF = const(0x1000) .. method:: CAN.rxcallback(fifo, fun) TODO: NOT YET IMPLEMENTED diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 7dfc8729c6178..f607e140ea95f 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -752,7 +752,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // ESP32 Specific API {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, // CAN_MODE {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL)}, @@ -765,33 +764,11 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING)}, {MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF)}, {MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING)}, - // CAN_BAUDRATE - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M)}, // CAN_FILTER_MODE {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE)}, {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL)}, {MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS)}, - // CAN_ALERT - {MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF)}}; +}; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); // Python object definition From b07db3a05a45afc9a05584fbafe27a1ec3ce16ea Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:39:10 +0100 Subject: [PATCH 056/180] Documentation bugfix --- docs/library/esp32.CAN.rst | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index 6c3ebe2f8679c..7c9152ba801fb 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -14,9 +14,9 @@ Example usage (works without anything connected):: from machine import CAN can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) - can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 - can.send([1,2,3], 123) # send a message with id 123 - can.recv() # receive message + dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can.send([1,2,3], 0x102) # send a message with id 123 + can.recv() # receive message Constructors @@ -45,7 +45,7 @@ Methods - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* will be ignored. Standard speeds are 25, 50, 100, 125, 250, 500, 1000 - *prescaler* is used to set the duration of 1 time quanta; the time quanta - will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler + will be the input clock divided by the prescaler - *sjw* is the resynchronisation jump width in units of the time quanta; it can be 1, 2, 3, 4 - *bs1* defines the location of the sample point in units of the time quanta; @@ -293,25 +293,9 @@ Constants Possible states of the CAN controller returned from :meth:`~CAN.state()`. -.. data:: CAN.LIST16 TODO: - CAN.MASK16 - CAN.LIST32 - CAN.MASK32 +.. data:: CAN.FILTER_RAW_SINGLE + CAN.FILTER_RAW_DUAL + CAN.FILTER_ADDRESS The operation mode of a filter used in :meth:`~CAN.setfilter()`. -.. data:: CAN.ALERT_TX_IDLE - CAN.ALERT_TX_SUCCESS - CAN.ALERT_BELOW_ERR_WARN - CAN.ALERT_ERR_ACTIVE - CAN.ALERT_RECOVERY_IN_PROGRESS - CAN.ALERT_BUS_RECOVERED - CAN.ALERT_ARB_LOST - CAN.ALERT_ABOVE_ERR_WARN - CAN.ALERT_BUS_ERROR - CAN.ALERT_TX_FAILED - CAN.ALERT_RX_QUEUE_FULL - CAN.ALERT_ERR_PASS - CAN.ALERT_BUS_OFF - - Possibile bit position of alert mask returned by :meth:`~CAN.get_alerts()`. From c8afef6e86f07f80563bd5d29a34d051258facba Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:39:39 +0100 Subject: [PATCH 057/180] removed implemented methods --- docs/library/esp32.CAN.rst | 47 +------------------------------------- ports/esp32/machine_can.c | 28 +---------------------- 2 files changed, 2 insertions(+), 73 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index 7c9152ba801fb..299e0cc2010f0 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -87,7 +87,7 @@ Methods - ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity (TEC overflowed beyond 255). - ``CAN.RECOVERING`` -- the controller is under recover from bus-off state; - + .. method:: CAN.info([list]) @@ -228,41 +228,7 @@ Methods CAN_ALERT_RX_QUEUE_FULL = const(0x0400) CAN_ALERT_ERR_PASS = const(0x0800) CAN_ALERT_BUS_OFF = const(0x1000) - - -.. method:: CAN.rxcallback(fifo, fun) TODO: NOT YET IMPLEMENTED - - Register a function to be called when a message is accepted into a empty fifo: - - - *fifo* is the receiving fifo. - - *fun* is the function to be called when the fifo becomes non empty. - The callback function takes two arguments the first is the can object it self the second is - a integer that indicates the reason for the callback. - - +--------+------------------------------------------------+ - | Reason | | - +========+================================================+ - | 0 | A message has been accepted into a empty FIFO. | - +--------+------------------------------------------------+ - | 1 | The FIFO is full | - +--------+------------------------------------------------+ - | 2 | A message has been lost due to a full FIFO | - +--------+------------------------------------------------+ - - Example use of rxcallback:: - - def cb0(bus, reason): - print('cb0') - if reason == 0: - print('pending') - if reason == 1: - print('full') - if reason == 2: - print('overflow') - - can = CAN(1, CAN.LOOPBACK) - can.rxcallback(0, cb0) Constants --------- @@ -275,17 +241,6 @@ Constants The mode of the CAN bus used in :meth:`~CAN.init()`. -.. data:: CAN.BAUDRATE_25k - CAN.BAUDRATE_50k - CAN.BAUDRATE_100k - CAN.BAUDRATE_125k - CAN.BAUDRATE_250k - CAN.BAUDRATE_500k - CAN.BAUDRATE_800k - CAN.BAUDRATE_1M - - The baudrate of the CAN bus used in :meth:`~CAN.init()`. - .. data:: CAN.STOPPED CAN.ERROR_ACTIVE CAN.BUS_OFF diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f607e140ea95f..2c674debd3a6b 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -179,7 +179,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { mp_raise_OSError(-status); } - mp_hal_delay_ms(200); // TODO: replace it with a smarter solution + mp_hal_delay_ms(200); status = can_start(); if (status != ESP_OK) { @@ -402,31 +402,6 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) -{ - mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (callback_in == mp_const_none) - { - self->rxcallback = mp_const_none; - } - else if (self->rxcallback != mp_const_none) - { - // Rx call backs has already been initialized - // only the callback function should be changed - self->rxcallback = callback_in; - // TODO: disable interrupt - } - else if (mp_obj_is_callable(callback_in)) - { - self->rxcallback = callback_in; - // TODO: set interrupt - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); - // Clear filters setting STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { @@ -748,7 +723,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, {MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj)}, {MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj)}, - {MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj)}, // ESP32 Specific API {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, From b9525138ec4ef1c7203998586567295fdd60c4b0 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 30 Jan 2020 19:01:23 +0100 Subject: [PATCH 058/180] beautify: brackets inline --- ports/esp32/machine_can.c | 227 ++++++++++++-------------------------- 1 file changed, 72 insertions(+), 155 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 2c674debd3a6b..e74636470da93 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -57,15 +57,13 @@ { \ mp_raise_OSError(-status); \ } -typedef enum _filter_mode_t -{ +typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t -{ +typedef struct _machine_can_config_t{ can_timing_config_t timing; can_filter_config_t filter; can_general_config_t general; @@ -73,8 +71,7 @@ typedef struct _machine_can_config_t bool initialized; } machine_can_config_t; -typedef struct _machine_can_obj_t -{ +typedef struct _machine_can_obj_t{ mp_obj_base_t base; machine_can_config_t *config; mp_obj_t rxcallback; @@ -86,8 +83,7 @@ typedef struct _machine_can_obj_t uint16_t num_bus_off; } machine_can_obj_t; -typedef enum _rx_state_t -{ +typedef enum _rx_state_t{ RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, @@ -114,8 +110,7 @@ machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0 STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config = &can_config}; // INTERNAL FUNCTION Return status information -STATIC can_status_info_t _machine_hw_can_get_status() -{ +STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; uint32_t err_code = can_get_status_info(&status); if (err_code != ESP_OK) @@ -126,41 +121,31 @@ STATIC can_status_info_t _machine_hw_can_get_status() } //INTERNAL FUNCTION Populates the filter register according to inputs -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) -{ +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ //Check if bank is allowed - if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)) - { + if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; - if (self->extframe) - { + if (self->extframe){ addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - } - else if (self->config->filter.single_filter) - { + }else if (self->config->filter.single_filter){ addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); mask = ((mask & 0x7FF) << 5); mask |= 0xFFFFF000; preserve_mask = 0; - } - else - { + }else{ addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); mask = ((mask & 0x7FF) << 5); preserve_mask = 0xFFFF << (bank == 0 ? 16 : 0); - if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))) - { + if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))){ // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); preserve_mask = 0; - } - else - { + }else{ addr = addr << (bank == 1 ? 16 : 0); mask = mask << (bank == 1 ? 16 : 0); } @@ -172,17 +157,14 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u } // Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ uint32_t status = can_initiate_recovery(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } mp_hal_delay_ms(200); status = can_start(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } return mp_const_none; @@ -190,39 +172,31 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) -{ +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; - if (n_args == 1) - { + if (n_args == 1){ list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - } - else - { - if (!mp_obj_is_type(args[1], &mp_type_list)) - { + }else{ + if (!mp_obj_is_type(args[1], &mp_type_list)){ mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); - if (list->len < 8) - { + if (list->len < 8){ mp_raise_ValueError(NULL); } } @@ -240,12 +214,10 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } return mp_obj_new_int(alerts); @@ -253,24 +225,20 @@ STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); // send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum - { +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum{ ARG_data, ARG_id, ARG_timeout, @@ -293,53 +261,41 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ size_t length; mp_obj_t *items; mp_obj_get_array(args[ARG_data].u_obj, &length, &items); - if (length > 8) - { + if (length > 8){ mp_raise_ValueError("CAN data field too long"); } uint8_t flags = (args[ARG_rtr].u_bool == true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; - if (self->extframe) - { + if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; - } - else - { + }else{ id &= 0x1FF; } - if (self->loopback) - { + if (self->loopback){ flags += CAN_MSG_FLAG_SELF; } can_message_t tx_msg = {.data_length_code = length, .identifier = id, .flags = flags}; - for (uint8_t i = 0; i < length; i++) - { + for (uint8_t i = 0; i < length; i++){ tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) - { + if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING){ int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } return mp_const_none; - } - else - { + }else{ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); // recv(list=None, *, timeout=5000) -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum - { +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum{ ARG_list, ARG_timeout }; @@ -354,42 +310,34 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ can_message_t rx_message; int status = can_receive(&rx_message, 1); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; mp_obj_t *items; - if (ret_obj == mp_const_none) - { + if (ret_obj == mp_const_none){ ret_obj = mp_obj_new_tuple(4, NULL); items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - } - else - { + }else{ // User should provide a list of length at least 4 to hold the values - if (!mp_obj_is_type(ret_obj, &mp_type_list)) - { + if (!mp_obj_is_type(ret_obj, &mp_type_list)){ mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); - if (list->len < 4) - { + if (list->len < 4){ mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace - if (!mp_obj_is_type(items[3], &mp_type_memoryview)) - { + if (!mp_obj_is_type(items[3], &mp_type_memoryview)){ mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); - if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) - { + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))){ mp_raise_ValueError(NULL); } mv->len = rx_message.data_length_code; @@ -403,8 +351,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in){ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; @@ -425,8 +372,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ enum { ARG_bank, @@ -449,20 +395,16 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if (len != 2) - { + if (len != 2){ mp_raise_ValueError("params shall be a 2-values list"); } uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) - { + if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL){ self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; - } - else - { + }else{ self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } @@ -477,11 +419,9 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) -{ +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind){ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized) - { + if (self->config->initialized){ qstr mode; switch (self->config->general.mode) { @@ -506,19 +446,15 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p mode, self->loopback, self->extframe); - } - else - { + }else{ mp_printf(print, "CAN Device is not initialized"); } } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) -{ +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args){ machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized) - { + if (self->config->initialized){ ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; } @@ -527,22 +463,18 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); // deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true) - { + if (self->config->initialized != true){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } uint32_t status = can_stop(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } status = can_driver_uninstall(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } self->config->initialized = false; @@ -553,24 +485,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deini // CAN(bus, ...) No argument to get the object // If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args) -{ + size_t n_kw, const mp_obj_t *args){ // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0]) != true) - { + if (mp_obj_is_int(args[0]) != true){ mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) - { + if (can_idx > 1){ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0) - { - if (self->config->initialized) - { + if (n_args > 1 || n_kw > 0){ + if (self->config->initialized){ // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); @@ -588,10 +515,8 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum - { +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum{ ARG_mode, ARG_extframe, ARG_baudrate, @@ -635,8 +560,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool) - { + if (args[ARG_auto_restart].u_bool){ mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); @@ -644,8 +568,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; can_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int) - { + switch ((int)args[ARG_baudrate].u_int){ case 0: timing = &((can_timing_config_t){ .brp = args[ARG_prescaler].u_int, @@ -690,19 +613,13 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg &self->config->general, &self->config->timing, &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); - } - else - { + }else{ status = can_start(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); - } - else - { + }else{ self->config->initialized = true; } } From faf2e9063e907a2f261e79541c99e181e20e2ecf Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 30 Jan 2020 19:02:17 +0100 Subject: [PATCH 059/180] documentation update: from esp32 specifc module to machine module --- docs/esp32/quickref.rst | 13 ++++++------- docs/library/{esp32.CAN.rst => machine.CAN.rst} | 11 ++++++----- 2 files changed, 12 insertions(+), 12 deletions(-) rename docs/library/{esp32.CAN.rst => machine.CAN.rst} (97%) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 2b8893c45881a..9eb063f187dab 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -328,19 +328,18 @@ pins can be used for SCL and SDA. The driver is accessed via the CAN bus ------- -See :ref:`esp32.CAN ` :: +See :ref:`machine.CAN ` :: The CAN driver is based on hardware implementation. Any available output-capablepins can be used for SCL and SDA. The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN - - # construct a CAN bus - bus = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) - - bus.send([0,1,2,3], 0x86) #Send the message - bus.recv() #Read the message sent + BAUDRATE_500k = 500 + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) + dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can.send([1,2,3], 0x102) # send a message with id 123 + can.recv() # receive message Real time clock (RTC) diff --git a/docs/library/esp32.CAN.rst b/docs/library/machine.CAN.rst similarity index 97% rename from docs/library/esp32.CAN.rst rename to docs/library/machine.CAN.rst index 299e0cc2010f0..4b73f185da0ce 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -1,19 +1,20 @@ -.. currentmodule:: esp32 -.. _esp32.CAN: +.. currentmodule:: machine +.. _machine.CAN: class CAN -- controller area network communication bus ====================================================== CAN implements the standard CAN communications protocol. At the physical level it consists of 2 lines: RX and TX. Note that -to connect the ESP32 to a CAN bus you must use a CAN transceiver -to convert the CAN logic signals from the ESP32 to the correct +to connect the microcontroller to a CAN bus you must use a CAN transceiver +to convert the CAN logic signals from the microcontroller to the correct voltage levels on the bus. Example usage (works without anything connected):: from machine import CAN - can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) + BAUDRATE_500k = 500 + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 can.send([1,2,3], 0x102) # send a message with id 123 can.recv() # receive message From d95976244cfd2a425fc8eb0e6606e15c5ddd212a Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 30 Jan 2020 19:11:00 +0100 Subject: [PATCH 060/180] revert unnecessary changes --- .gitignore | 3 --- docs/library/esp32.rst | 10 +--------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index a4ef09599ecb6..50bd30e877e87 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,3 @@ user.props # Generated rst files ###################### genrst/ -docs/_build -.vscode -esp-idf diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 4cd7efc3949e5..77d0485f51414 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -108,12 +108,4 @@ Constants .. data:: esp32.WAKEUP_ALL_LOW esp32.WAKEUP_ANY_HIGH - Selects the wake level for pins. - -Classes -------- - -.. toctree:: - :maxdepth: 1 - - esp32.CAN.rst + Selects the wake level for pins. \ No newline at end of file From 3cf09b09b1554396c1e6f389bb496bb65d7cd696 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 4 Feb 2020 23:07:03 +0100 Subject: [PATCH 061/180] code beautify --- ports/esp32/machine_can.c | 190 +++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 97 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index e74636470da93..0974b7d37e32d 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -53,17 +53,16 @@ #define CAN_BAUDRATE_1M 1000 #define ESP_STATUS_CHECK(status) \ - if (status != ESP_OK) \ - { \ + if (status != ESP_OK) { \ mp_raise_OSError(-status); \ } -typedef enum _filter_mode_t{ +typedef enum _filter_mode_t { FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t{ +typedef struct _machine_can_config_t { can_timing_config_t timing; can_filter_config_t filter; can_general_config_t general; @@ -71,7 +70,7 @@ typedef struct _machine_can_config_t{ bool initialized; } machine_can_config_t; -typedef struct _machine_can_obj_t{ +typedef struct _machine_can_obj_t { mp_obj_base_t base; machine_can_config_t *config; mp_obj_t rxcallback; @@ -83,7 +82,7 @@ typedef struct _machine_can_obj_t{ uint16_t num_bus_off; } machine_can_obj_t; -typedef enum _rx_state_t{ +typedef enum _rx_state_t { RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, @@ -102,28 +101,25 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), - .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), - .timing = CAN_TIMING_CONFIG_25KBITS(), - .initialized = false}; +machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), + .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), + .timing = CAN_TIMING_CONFIG_25KBITS(), + .initialized = false }; -STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config = &can_config}; +STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; -// INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; uint32_t err_code = can_get_status_info(&status); - if (err_code != ESP_OK) - { + if (err_code != ESP_OK){ mp_raise_OSError(-err_code); } return status; } -//INTERNAL FUNCTION Populates the filter register according to inputs STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ //Check if bank is allowed - if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ + if ( bank < 0 && bank > ( (self->extframe && self->config->filter.single_filter) ? 0 : 1 ) ){ mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; @@ -131,21 +127,21 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - }else if (self->config->filter.single_filter){ - addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); + } else if (self->config->filter.single_filter){ + addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); + mask = ( (mask & 0x7FF) << 5 ); mask |= 0xFFFFF000; preserve_mask = 0; - }else{ - addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); - preserve_mask = 0xFFFF << (bank == 0 ? 16 : 0); - if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))){ + } else { + addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); + mask = ( (mask & 0x7FF) << 5 ); + preserve_mask = 0xFFFF << ( bank == 0 ? 16 : 0 ); + if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ){ // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); preserve_mask = 0; - }else{ + } else { addr = addr << (bank == 1 ? 16 : 0); mask = mask << (bank == 1 ? 16 : 0); } @@ -191,7 +187,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ mp_obj_list_t *list; if (n_args == 1){ list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - }else{ + } else{ if (!mp_obj_is_type(args[1], &mp_type_list)){ mp_raise_TypeError(NULL); } @@ -264,20 +260,20 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ if (length > 8){ mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool == true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + uint8_t flags = (args[ARG_rtr].u_bool ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; - }else{ + } else { id &= 0x1FF; } if (self->loopback){ flags += CAN_MSG_FLAG_SELF; } - can_message_t tx_msg = {.data_length_code = length, - .identifier = id, - .flags = flags}; + can_message_t tx_msg = { .data_length_code = length, + .identifier = id, + .flags = flags }; for (uint8_t i = 0; i < length; i++){ tx_msg.data[i] = mp_obj_get_int(items[i]); } @@ -287,7 +283,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ mp_raise_OSError(-status); } return mp_const_none; - }else{ + } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); } } @@ -300,8 +296,8 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ ARG_timeout }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)}}, - {MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000}}, + { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args @@ -319,9 +315,9 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_obj_t *items; if (ret_obj == mp_const_none){ ret_obj = mp_obj_new_tuple(4, NULL); - items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; + items = ( (mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj) )->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - }else{ + } else { // User should provide a list of length at least 4 to hold the values if (!mp_obj_is_type(ret_obj, &mp_type_list)){ mp_raise_TypeError(NULL); @@ -344,7 +340,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ memcpy(mv->items, rx_message.data, rx_message.data_length_code); } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; + items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? true : false); items[2] = 0; return ret_obj; } @@ -381,10 +377,10 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args ARG_rtr }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false}}, + { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, }; // parse args @@ -404,17 +400,17 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; - }else{ + } else { self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - ESP_STATUS_CHECK(can_stop()); - ESP_STATUS_CHECK(can_driver_uninstall()); - ESP_STATUS_CHECK(can_driver_install( + ESP_STATUS_CHECK( can_stop() ); + ESP_STATUS_CHECK( can_driver_uninstall() ); + ESP_STATUS_CHECK( can_driver_install( &self->config->general, &self->config->timing, - &self->config->filter)); - ESP_STATUS_CHECK(can_start()); + &self->config->filter) ); + ESP_STATUS_CHECK( can_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -446,7 +442,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p mode, self->loopback, self->extframe); - }else{ + } else { mp_printf(print, "CAN Device is not initialized"); } } @@ -531,18 +527,18 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg ARG_auto_restart }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL}}, - {MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false}}, - {MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER}}, - {MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW}}, - {MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1}}, - {MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2}}, - {MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4}}, - {MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2}}, - {MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5}}, - {MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, + { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, + { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, + { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, + { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -578,28 +574,28 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .triple_sampling = false}); break; case CAN_BAUDRATE_25k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); break; case CAN_BAUDRATE_50k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS() ); break; case CAN_BAUDRATE_100k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS() ); break; case CAN_BAUDRATE_125k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS() ); break; case CAN_BAUDRATE_250k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS() ); break; case CAN_BAUDRATE_500k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS() ); break; case CAN_BAUDRATE_800k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_800KBITS() ); break; case CAN_BAUDRATE_1M: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS() ); break; default: mp_raise_ValueError("Unable to set baudrate"); @@ -612,14 +608,14 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg uint32_t status = can_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); + &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); if (status != ESP_OK){ mp_raise_OSError(-status); - }else{ + } else { status = can_start(); if (status != ESP_OK){ mp_raise_OSError(-status); - }else{ + } else { self->config->initialized = true; } } @@ -628,37 +624,37 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_ATTRIBUTES - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN)}, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, // Micropython Generic API - {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj)}, - {MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj)}, - {MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj)}, - {MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj)}, - {MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj)}, - {MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj)}, - {MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, - {MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - {MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj)}, - {MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj)}, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, // ESP32 Specific API - {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, // CAN_MODE - {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL)}, - {MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10)}, - {MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK)}, - {MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10)}, - {MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY)}, + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE - {MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED)}, - {MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING)}, - {MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF)}, - {MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING)}, + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, // CAN_FILTER_MODE - {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE)}, - {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL)}, - {MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS)}, + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); From 1e7e0384792e320cfcd5af02639ed837f843cee5 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 9 Feb 2020 15:53:13 +0100 Subject: [PATCH 062/180] Beautify --- ports/esp32/machine_can.c | 151 +++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0974b7d37e32d..56c806bd545c2 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -104,30 +104,31 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), .timing = CAN_TIMING_CONFIG_25KBITS(), - .initialized = false }; + .initialized = false + }; STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; -STATIC can_status_info_t _machine_hw_can_get_status(){ +STATIC can_status_info_t _machine_hw_can_get_status() { can_status_info_t status; uint32_t err_code = can_get_status_info(&status); - if (err_code != ESP_OK){ + if (err_code != ESP_OK) { mp_raise_OSError(-err_code); } return status; } -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { //Check if bank is allowed - if ( bank < 0 && bank > ( (self->extframe && self->config->filter.single_filter) ? 0 : 1 ) ){ + if ( bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; - if (self->extframe){ + if (self->extframe) { addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - } else if (self->config->filter.single_filter){ + } else if (self->config->filter.single_filter) { addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); mask = ( (mask & 0x7FF) << 5 ); mask |= 0xFFFFF000; @@ -136,7 +137,7 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); mask = ( (mask & 0x7FF) << 5 ); preserve_mask = 0xFFFF << ( bank == 0 ? 16 : 0 ); - if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ){ + if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ) { // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); @@ -153,14 +154,14 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u } // Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { uint32_t status = can_initiate_recovery(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } mp_hal_delay_ms(200); status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } return mp_const_none; @@ -168,31 +169,31 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; - if (n_args == 1){ + if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - } else{ - if (!mp_obj_is_type(args[1], &mp_type_list)){ + } else { + if (!mp_obj_is_type(args[1], &mp_type_list)) { mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); - if (list->len < 8){ + if (list->len < 8) { mp_raise_ValueError(NULL); } } @@ -210,10 +211,10 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } return mp_obj_new_int(alerts); @@ -221,20 +222,20 @@ STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) { return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) { return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); // send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum{ +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_id, ARG_timeout, @@ -257,29 +258,30 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ size_t length; mp_obj_t *items; mp_obj_get_array(args[ARG_data].u_obj, &length, &items); - if (length > 8){ + if (length > 8) { mp_raise_ValueError("CAN data field too long"); } uint8_t flags = (args[ARG_rtr].u_bool ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; - if (self->extframe){ + if (self->extframe) { flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; } else { id &= 0x1FF; } - if (self->loopback){ + if (self->loopback) { flags += CAN_MSG_FLAG_SELF; } can_message_t tx_msg = { .data_length_code = length, .identifier = id, - .flags = flags }; - for (uint8_t i = 0; i < length; i++){ + .flags = flags + }; + for (uint8_t i = 0; i < length; i++) { tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING){ + if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } return mp_const_none; @@ -290,8 +292,8 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); // recv(list=None, *, timeout=5000) -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum{ +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_list, ARG_timeout }; @@ -306,48 +308,48 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ can_message_t rx_message; int status = can_receive(&rx_message, 1); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; mp_obj_t *items; - if (ret_obj == mp_const_none){ + if (ret_obj == mp_const_none) { ret_obj = mp_obj_new_tuple(4, NULL); items = ( (mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj) )->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); } else { // User should provide a list of length at least 4 to hold the values - if (!mp_obj_is_type(ret_obj, &mp_type_list)){ + if (!mp_obj_is_type(ret_obj, &mp_type_list)) { mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); - if (list->len < 4){ + if (list->len < 4) { mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace - if (!mp_obj_is_type(items[3], &mp_type_memoryview)){ + if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); - if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))){ + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { mp_raise_ValueError(NULL); } mv->len = rx_message.data_length_code; memcpy(mv->items, rx_message.data, rx_message.data_length_code); } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? true : false); + items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0); items[2] = 0; return ret_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; @@ -355,9 +357,9 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in){ ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( - &self->config->general, - &self->config->timing, - &self->config->filter)); + &self->config->general, + &self->config->timing, + &self->config->filter)); ESP_STATUS_CHECK(can_start()); return mp_const_none; } @@ -368,7 +370,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bank, @@ -391,12 +393,12 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if (len != 2){ + if (len != 2) { mp_raise_ValueError("params shall be a 2-values list"); } uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL){ + if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) { self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; @@ -407,17 +409,17 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args ESP_STATUS_CHECK( can_stop() ); ESP_STATUS_CHECK( can_driver_uninstall() ); ESP_STATUS_CHECK( can_driver_install( - &self->config->general, - &self->config->timing, - &self->config->filter) ); + &self->config->general, + &self->config->timing, + &self->config->filter) ); ESP_STATUS_CHECK( can_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind){ +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized){ + if (self->config->initialized) { qstr mode; switch (self->config->general.mode) { @@ -448,9 +450,9 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args){ +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized){ + if (self->config->initialized) { ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; } @@ -459,18 +461,18 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); // deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true){ + if (self->config->initialized != true) { ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } uint32_t status = can_stop(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } status = can_driver_uninstall(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } self->config->initialized = false; @@ -481,19 +483,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deini // CAN(bus, ...) No argument to get the object // If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args){ + size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0]) != true){ + if (mp_obj_is_int(args[0]) != true) { mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1){ + if (can_idx > 1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0){ - if (self->config->initialized){ + if (n_args > 1 || n_kw > 0) { + if (self->config->initialized) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); @@ -511,8 +513,8 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum{ +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_extframe, ARG_baudrate, @@ -556,7 +558,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool){ + if (args[ARG_auto_restart].u_bool) { mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); @@ -564,14 +566,15 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; can_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int){ + switch ((int)args[ARG_baudrate].u_int) { case 0: - timing = &((can_timing_config_t){ + timing = &((can_timing_config_t) { .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, .tseg_2 = args[ARG_bs1].u_int, - .triple_sampling = false}); + .triple_sampling = false + }); break; case CAN_BAUDRATE_25k: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); @@ -606,14 +609,14 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->baudrate = args[ARG_baudrate].u_int; uint32_t status = can_driver_install( - &self->config->general, - &self->config->timing, - &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); - if (status != ESP_OK){ + &self->config->general, + &self->config->timing, + &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); + if (status != ESP_OK) { mp_raise_OSError(-status); } else { status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } else { self->config->initialized = true; From 8fba25fd20641c051250ad7c6dffbfcb1c6dc0ae Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 02:35:29 -0700 Subject: [PATCH 063/180] esp32: modmachine.c Fix after merge from master --- ports/esp32/modmachine.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 709ce815a291d..ac00de4f85601 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -281,7 +281,6 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, #endif - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, From 6dabef8b22a98d80791534e8a5f06202e3e44832 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 02:38:35 -0700 Subject: [PATCH 064/180] esp32: Add machine_can.c to CMakeLists.txt --- ports/esp32/main/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt index 1cc30b71ec558..2dd233c834f5e 100644 --- a/ports/esp32/main/CMakeLists.txt +++ b/ports/esp32/main/CMakeLists.txt @@ -52,6 +52,7 @@ set(MICROPY_SOURCE_PORT ${PROJECT_DIR}/machine_i2c.c ${PROJECT_DIR}/machine_pwm.c ${PROJECT_DIR}/machine_uart.c + ${PROJECT_DIR}/machine_can.c ${PROJECT_DIR}/modmachine.c ${PROJECT_DIR}/modnetwork.c ${PROJECT_DIR}/network_lan.c From 023342b458542bc4abbf956a0276e717d9a4342c Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 05:09:01 -0700 Subject: [PATCH 065/180] esp32:machine_can Merge https://github.com/nos86/micropython/tree/esp32-can-driver and https://github.com/nos86/micropython/tree/esp32-can-driver-harmonization --- ports/esp32/machine_can.c | 104 +++++++++++++++++++------------------- ports/esp32/machine_can.h | 83 ++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 53 deletions(-) mode change 100644 => 100755 ports/esp32/machine_can.c create mode 100755 ports/esp32/machine_can.h diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c old mode 100644 new mode 100755 index 56c806bd545c2..3500f2618cea8 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -1,6 +1,7 @@ /* The MIT License (MIT) * * Copyright (c) 2019 Musumeci Salvatore + * Copyright (c) 2021 Ihor Nehrutsa * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,58 +38,10 @@ #include "esp_err.h" #include "esp_log.h" -#include "modmachine.h" +#include #if MICROPY_HW_ENABLE_CAN -#define DEVICE_NAME "CAN" - -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 - -#define ESP_STATUS_CHECK(status) \ - if (status != ESP_OK) { \ - mp_raise_OSError(-status); \ - } -typedef enum _filter_mode_t { - FILTER_RAW_SINGLE = 0, - FILTER_RAW_DUAL, - FILTER_ADDRESS -} filter_mode_t; - -typedef struct _machine_can_config_t { - can_timing_config_t timing; - can_filter_config_t filter; - can_general_config_t general; - uint16_t baudrate; - bool initialized; -} machine_can_config_t; - -typedef struct _machine_can_obj_t { - mp_obj_base_t base; - machine_can_config_t *config; - mp_obj_t rxcallback; - byte rx_state; - bool extframe : 1; - bool loopback : 1; - uint16_t num_error_warning; //FIXME: populate this value somewhere - uint16_t num_error_passive; - uint16_t num_bus_off; -} machine_can_obj_t; - -typedef enum _rx_state_t { - RX_STATE_FIFO_EMPTY = 0, - RX_STATE_MESSAGE_PENDING, - RX_STATE_FIFO_FULL, - RX_STATE_FIFO_OVERFLOW, -} rx_state_t; - // Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) @@ -109,6 +62,7 @@ machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; +// INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status() { can_status_info_t status; uint32_t err_code = can_get_status_info(&status); @@ -118,6 +72,7 @@ STATIC can_status_info_t _machine_hw_can_get_status() { return status; } +//INTERNAL FUNCTION Populates the filter register according to inputs STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { //Check if bank is allowed if ( bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { @@ -159,7 +114,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { if (status != ESP_OK) { mp_raise_OSError(-status); } - mp_hal_delay_ms(200); + mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution status = can_start(); if (status != ESP_OK) { mp_raise_OSError(-status); @@ -348,6 +303,25 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + mp_raise_NotImplementedError("IRQ not supported yet"); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (callback_in == mp_const_none) { + self->rxcallback = mp_const_none; + } else if (self->rxcallback != mp_const_none) { + // Rx call backs has already been initialized + // only the callback function should be changed + self->rxcallback = callback_in; + // TODO: disable interrupt + } else if (mp_obj_is_callable(callback_in)) { + self->rxcallback = callback_in; + // TODO: set interrupt + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); + // Clear filters setting STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -379,9 +353,9 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args ARG_rtr }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, }; @@ -639,6 +613,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, // ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, @@ -654,10 +629,33 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + // CAN_BAUDRATE + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, // CAN_FILTER_MODE { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, + // CAN_ALERT + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h new file mode 100755 index 0000000000000..a79a23271345a --- /dev/null +++ b/ports/esp32/machine_can.h @@ -0,0 +1,83 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Musumeci Salvatore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ESP32_CAN_H +#define MICROPY_INCLUDED_ESP32_CAN_H + +#include "modmachine.h" + +#include "py/obj.h" + +#if MICROPY_HW_ENABLE_CAN + +#define DEVICE_NAME "CAN" + +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 + +#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} +typedef enum _filter_mode_t{ + FILTER_RAW_SINGLE = 0, + FILTER_RAW_DUAL, + FILTER_ADDRESS +} filter_mode_t; + +typedef struct _machine_can_config_t { + can_timing_config_t timing; + can_filter_config_t filter; + can_general_config_t general; + uint16_t baudrate; + bool initialized; +} machine_can_config_t; + +typedef struct _machine_can_obj_t { + mp_obj_base_t base; + machine_can_config_t *config; + mp_obj_t rxcallback; + byte rx_state; + bool extframe : 1; + bool loopback : 1; + uint16_t num_error_warning; //FIXME: populate this value somewhere + uint16_t num_error_passive; + uint16_t num_bus_off; +} machine_can_obj_t; + +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + +extern const mp_obj_type_t machine_can_type; + +#endif // MICROPY_HW_ENABLE_CAN +#endif // MICROPY_INCLUDED_ESP32_CAN_H From 2b6b1a7eb757dd93b28a76360df8f26ab6796b10 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 06:06:14 -0700 Subject: [PATCH 066/180] esp32:CAN Add TWAI block diagram Fix SCL, SDA to TX, RX --- docs/esp32/img/twai_blockdiag.png | Bin 0 -> 10157 bytes docs/esp32/quickref.rst | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100755 docs/esp32/img/twai_blockdiag.png diff --git a/docs/esp32/img/twai_blockdiag.png b/docs/esp32/img/twai_blockdiag.png new file mode 100755 index 0000000000000000000000000000000000000000..183352ea610de1aa53b149730db94cf068661609 GIT binary patch literal 10157 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 :: The CAN driver is based on hardware implementation. -Any available output-capablepins can be used for SCL and SDA. +Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT signal lines. +.. image:: img/twai_blockdiag.png The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN From 0e0686e1eef41fc0003e607d0bf873c5c5204d81 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 06:49:06 -0700 Subject: [PATCH 067/180] esp32:machine_can Replace ESP_STATUS_CHECK() to check_esp_err() --- ports/esp32/machine_can.c | 16 ++++++++-------- ports/esp32/machine_can.h | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 3500f2618cea8..77974f437a91a 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -328,13 +328,13 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; self->config->filter.acceptance_mask = 0xFFFFFFFF; - ESP_STATUS_CHECK(can_stop()); - ESP_STATUS_CHECK(can_driver_uninstall()); - ESP_STATUS_CHECK(can_driver_install( + check_esp_err(can_stop()); + check_esp_err(can_driver_uninstall()); + check_esp_err(can_driver_install( &self->config->general, &self->config->timing, &self->config->filter)); - ESP_STATUS_CHECK(can_start()); + check_esp_err(can_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); @@ -380,13 +380,13 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - ESP_STATUS_CHECK( can_stop() ); - ESP_STATUS_CHECK( can_driver_uninstall() ); - ESP_STATUS_CHECK( can_driver_install( + check_esp_err( can_stop() ); + check_esp_err( can_driver_uninstall() ); + check_esp_err( can_driver_install( &self->config->general, &self->config->timing, &self->config->filter) ); - ESP_STATUS_CHECK( can_start() ); + check_esp_err( can_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index a79a23271345a..9ed50a504f791 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,7 +43,6 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 -#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, From 730148d807ba2b140e2270b2b6f269d328042765 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 07:10:19 -0700 Subject: [PATCH 068/180] esp32:machine_can.c Replace mp_raise_OSError(-status) to check_esp_err() --- ports/esp32/machine_can.c | 57 +++++++++------------------------------ 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 77974f437a91a..428fb6132f2d9 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -65,10 +65,7 @@ STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can // INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status() { can_status_info_t status; - uint32_t err_code = can_get_status_info(&status); - if (err_code != ESP_OK) { - mp_raise_OSError(-err_code); - } + check_esp_err(can_get_status_info(&status)); return status; } @@ -110,15 +107,9 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { - uint32_t status = can_initiate_recovery(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_initiate_recovery()); mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution - status = can_start(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); @@ -168,10 +159,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machin // Get Alert info STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; - uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_read_alerts(&alerts, 0)); return mp_obj_new_int(alerts); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); @@ -235,10 +223,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ tx_msg.data[i] = mp_obj_get_int(items[i]); } if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { - int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_transmit(&tx_msg, args[ARG_timeout].u_int)); return mp_const_none; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); @@ -262,10 +247,8 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); can_message_t rx_message; - int status = can_receive(&rx_message, 1); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + //int status = + check_esp_err(can_receive(&rx_message, 1)); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; @@ -441,14 +424,8 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } - uint32_t status = can_stop(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } - status = can_driver_uninstall(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_stop()); + check_esp_err(can_driver_uninstall()); self->config->initialized = false; return mp_const_none; } @@ -582,20 +559,12 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - uint32_t status = can_driver_install( + check_esp_err(can_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } else { - status = can_start(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } else { - self->config->initialized = true; - } - } + &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL())); + check_esp_err(can_start()); + self->config->initialized = true; return mp_const_none; } From 3b9610a9f60517c5539d2f280d88af846d05cdad Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 07:12:44 -0700 Subject: [PATCH 069/180] Update esp32.rst Remove duplicate lines. --- docs/library/esp32.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 1aad80955930a..1cfb304c14b88 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -269,7 +269,6 @@ Constants esp32.WAKEUP_ANY_HIGH Selects the wake level for pins. - Selects the wake level for pins. Non-Volatile Storage -------------------- From d286a8890a3b2ffc684d29cea244214e0bb2e255 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 07:15:22 -0700 Subject: [PATCH 070/180] Update machine.CAN.rst Correct GPOI connected to CAN signal lines. --- docs/library/machine.CAN.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst index 4b73f185da0ce..f481ad7f1b69d 100644 --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -53,8 +53,10 @@ Methods it can be between 1 and 1024 inclusive - *bs2* defines the location of the transmit point in units of the time quanta; it can be between 1 and 16 inclusive - - *tx_io* defines the gpio used for transmission - - *rx_io* defines the gpio used for receiving + - *tx* defines the gpio used for transmission + - *rx* defines the gpio used for receiving + - *bus_off* defines the gpio used for BUS-OFF signal line(optional) + - *clkout* defines the gpio used for CLKOUT signal line(optional) - *tx_queue* defines the number of waiting tx messages can be stored - *rx_queue* defines the number of received messages can be stored - *auto_restart* sets whether the controller will automatically try and restart From f0d7a4167c38f69d0841d261e21fb9ea5d8e4acb Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 16:26:51 -0700 Subject: [PATCH 071/180] esp32: CAN docs fix --- docs/esp32/quickref.rst | 36 +++++++++++++++++++----------------- docs/library/machine.CAN.rst | 28 ++++++++++++++-------------- docs/library/machine.rst | 1 + 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 3b44eb996b735..29ee81fd607e3 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -355,23 +355,6 @@ accessed via the :ref:`machine.SoftI2C ` class:: buf = bytearray(10) # create a buffer with 10 bytes i2c.writeto(0x3a, buf) # write the given buffer to the slave -CAN bus -------- - -See :ref:`machine.CAN ` :: - -The CAN driver is based on hardware implementation. -Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT signal lines. -.. image:: img/twai_blockdiag.png -The driver is accessed via the :ref:`machine.CAN ` class:: - - from machine import CAN - BAUDRATE_500k = 500 - can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) - dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 - can.send([1,2,3], 0x102) # send a message with id 123 - can.recv() # receive message - Hardware I2C bus ---------------- @@ -394,6 +377,25 @@ has the same methods as software I2C above:: i2c = I2C(0) i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000) +CAN bus +------- + +See :ref:`machine.CAN ` :: + +The CAN driver is based on hardware implementation. +Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT signal lines. + +.. image:: img/twai_blockdiag.png + +The driver is accessed via the :ref:`machine.CAN ` class:: + + from machine import CAN + BAUDRATE_500k = 500 + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) + dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can.send([1,2,3], 0x102) # send a message with id 123 + can.recv() # receive message + Real time clock (RTC) --------------------- diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst index f481ad7f1b69d..1e025b7fa99f7 100644 --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -124,20 +124,20 @@ Methods The first element will be the id to filter and the second element will be the mask to apply. mask bit implementation considers 1 as a don't care state and 0 as a check state. - +----------------------+----------------------------------------------+ - |*mode* |contents of *params* array | - +======================+==============================================+ - |CAN.FILTER_RAW_SINGLE | *params* will be copied in hardware variable | - | | and single_filter_mode will be selected | - | | In this mode, *bank* will be ignored | - +----------------------+----------------------------------------------+ - |CAN.FILTER_RAW_DUAL | *params* will be copied in hardware variable | - | | and single_filter_mode will be cleared | - | | In this mode, *bank* will be ignored | - +----------------------+----------------------------------------------+ - |CAN.FILTER_ADDRESS | *params* will be set in hardware registers | - | | according to *bank* selection | - +----------------------+----------------------------------------------+ + +-----------------------+----------------------------------------------+ + | *mode* | contents of *params* array | + +=======================+==============================================+ + | CAN.FILTER_RAW_SINGLE | *params* will be copied in hardware variable | + | | and single_filter_mode will be selected | + | | In this mode, *bank* will be ignored | + +-----------------------+----------------------------------------------+ + | CAN.FILTER_RAW_DUAL | *params* will be copied in hardware variable | + | | and single_filter_mode will be cleared | + | | In this mode, *bank* will be ignored | + +-----------------------+----------------------------------------------+ + | CAN.FILTER_ADDRESS | *params* will be set in hardware registers | + | | according to *bank* selection | + +-----------------------+----------------------------------------------+ - *rtr* is bool that states if a filter should accept a remote transmission request message. If this argument is not given then it defaults to ``False``. diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 0a1c1c953005f..baf94c2258f55 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -181,6 +181,7 @@ Classes machine.UART.rst machine.SPI.rst machine.I2C.rst + machine.CAN.rst machine.RTC.rst machine.Timer.rst machine.WDT.rst From 73ef89bf72298bbb0d83ec0b93004a591a6fe92a Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Mon, 14 Jun 2021 14:59:01 -0700 Subject: [PATCH 072/180] docs: machine.CAN.rst: Add CAN modes images. --- docs/library/img/can_mode_listen_only.png | Bin 0 -> 3572 bytes docs/library/img/can_mode_loopback.png | Bin 0 -> 3669 bytes docs/library/img/can_mode_normal.png | Bin 0 -> 3513 bytes docs/library/img/can_mode_silent.png | Bin 0 -> 3632 bytes docs/library/img/can_mode_silent_loopback.png | Bin 0 -> 3646 bytes docs/library/machine.CAN.rst | 40 ++++++++++++------ 6 files changed, 28 insertions(+), 12 deletions(-) create mode 100755 docs/library/img/can_mode_listen_only.png create mode 100755 docs/library/img/can_mode_loopback.png create mode 100755 docs/library/img/can_mode_normal.png create mode 100755 docs/library/img/can_mode_silent.png create mode 100755 docs/library/img/can_mode_silent_loopback.png mode change 100644 => 100755 docs/library/machine.CAN.rst diff --git a/docs/library/img/can_mode_listen_only.png b/docs/library/img/can_mode_listen_only.png new file mode 100755 index 0000000000000000000000000000000000000000..45fb05f57f62c3429b2c4ba1cf67336b71035718 GIT binary patch literal 3572 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 AvH$=8 literal 0 HcmV?d00001 diff --git a/docs/library/img/can_mode_loopback.png b/docs/library/img/can_mode_loopback.png new file mode 100755 index 0000000000000000000000000000000000000000..73c3290fc5864a75e951f8af85389ccdc503969e GIT binary patch literal 3669 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 literal 0 HcmV?d00001 diff --git a/docs/library/img/can_mode_normal.png b/docs/library/img/can_mode_normal.png new file mode 100755 index 0000000000000000000000000000000000000000..4ac218a2aafe1dd3567ed8778b245d6dd97e7575 GIT binary patch literal 3513 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 UXY@q@FL{u;skKR+k!Rw+0hLWxivR!s literal 0 HcmV?d00001 diff --git a/docs/library/img/can_mode_silent.png b/docs/library/img/can_mode_silent.png new file mode 100755 index 0000000000000000000000000000000000000000..5b74491be0bfe1a0468dedb7b2b9ce1cf5c6ac41 GIT binary patch literal 3632 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 UDQ)f#{7!%{Cf3H)hHlaS1ADxUtN;K2 literal 0 HcmV?d00001 diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst old mode 100644 new mode 100755 index 1e025b7fa99f7..8ca920fbbfafd --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -25,7 +25,7 @@ Constructors .. class:: machine.CAN(bus, ...) - Construct a CAN object on the given bus. *bus* can be 0 or 1 (for compatibility with STM32). It will point at the same device + Construct a CAN object on the given bus(controller). *bus* can be 0 or 1 for STM32 and 0 for ESP32. With no additional parameters, the CAN object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. @@ -73,7 +73,7 @@ Methods Force a software restart of the CAN controller without resetting its configuration. - + If the controller enters the bus-off state then it will no longer participate in bus activity. If the controller is not configured to automatically restart (see :meth:`~CAN.init()`) then this method can be used to trigger a restart, @@ -114,13 +114,13 @@ Methods - number of pending RX messages - Reserved -.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) +.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) Configure a filter bank: - *bank* is the filter bank that is to be configured (0 for extended, 0 or 1 for standard msg) - *mode* is the mode the filter should operate in. - - *params* is an array of two values that defines the filter. + - *params* is an array of two values that defines the filter. The first element will be the id to filter and the second element will be the mask to apply. mask bit implementation considers 1 as a don't care state and 0 as a check state. @@ -139,8 +139,8 @@ Methods | | according to *bank* selection | +-----------------------+----------------------------------------------+ - - *rtr* is bool that states if a filter should accept a remote transmission request message. - If this argument is not given then it defaults to ``False``. + - *rtr* is bool that states if a filter should accept a remote transmission request message. + If this argument is not given then it defaults to ``False``. .. method:: CAN.clearfilter(bank) @@ -180,7 +180,7 @@ Methods buf = bytearray(8) lst = [0, 0, 0, memoryview(buf)] # No heap memory is allocated in the following call - can.recv(0, lst) + can.recv(lst, timeout=0) .. method:: CAN.send(data, id, \*, timeout=0, rtr=False) @@ -194,10 +194,10 @@ Methods of *data* is used to fill in the DLC slot of the frame; the actual bytes in *data* are unused. - If timeout is 0 the message is placed in a buffer and the method returns - immediately. If all three buffers are in use an exception is thrown. - If timeout is not 0, the method waits until the message is transmitted. - If the message can't be transmitted within the specified time an exception + If timeout is 0 the message is placed in a buffer and the method returns + immediately. If all three buffers are in use an exception is thrown. + If timeout is not 0, the method waits until the message is transmitted. + If the message can't be transmitted within the specified time an exception is thrown. Return value: ``None``. @@ -208,7 +208,7 @@ Methods .. method:: CAN.clear_rx_queue() - Clear all messages from receiving queue. + Clear all messages from receiving queue. .. method:: CAN.get_alerts() @@ -242,8 +242,24 @@ Constants CAN.SILENT_LOOPBACK CAN.LISTEN_ONLY + The mode of the CAN bus used in :meth:`~CAN.init()`. + +---------------------+---------------------------------------------+-------+-------+ + | *mode* | \ | STM32 | ESP32 | + +=====================+=============================================+=======+=======+ + | CAN.NORMAL | .. image:: img/can_mode_normal.png | + | + | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.LOOPBACK | .. image:: img/can_mode_loopback.png | + | + | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.SILENT | .. image:: img/can_mode_silent.png | + | + | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.SILENT_LOOPBACK | .. image:: img/can_mode_silent_loopback.png | + | | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.LISTEN_ONLY | .. image:: img/can_mode_listen_only.png | | + | + +---------------------+---------------------------------------------+-------+-------+ + + .. data:: CAN.STOPPED CAN.ERROR_ACTIVE CAN.BUS_OFF From 94316fe650326bde029994623c9522fe74fc1a36 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Tue, 15 Jun 2021 18:43:21 +0300 Subject: [PATCH 073/180] .gitignore: Add docs/_build directory under Windows --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 7342489927888..7b5f2241147db 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ # Build directories ###################### build/ +_build/ build-*/ # Test failure outputs From 6ed2fa5c0c8afa3e82966173bbeccca901c421e7 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:32:32 +0300 Subject: [PATCH 074/180] ESP32: machine_can.c: Remove meaningless comparison --- ports/esp32/machine_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 428fb6132f2d9..0f9d403b17ede 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -72,7 +72,7 @@ STATIC can_status_info_t _machine_hw_can_get_status() { //INTERNAL FUNCTION Populates the filter register according to inputs STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { //Check if bank is allowed - if ( bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { + if (bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; From 3175cf6b6f767118bc47f17c26c2fc758075adf2 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:36:21 +0300 Subject: [PATCH 075/180] ESP32: machine_can.c: Convert timeout in ms to RTOS ticks pdMS_TO_TICKS() --- ports/esp32/machine_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0f9d403b17ede..f9d897eb97814 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -223,7 +223,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ tx_msg.data[i] = mp_obj_get_int(items[i]); } if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { - check_esp_err(can_transmit(&tx_msg, args[ARG_timeout].u_int)); + check_esp_err(can_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); return mp_const_none; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); @@ -248,7 +248,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ can_message_t rx_message; //int status = - check_esp_err(can_receive(&rx_message, 1)); + check_esp_err(can_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; From e947db4e77f3411fb10e5506b5c646b7a20065e7 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:46:54 +0300 Subject: [PATCH 076/180] ESP32: machine_can.c: Simplify error messages --- ports/esp32/machine_can.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f9d897eb97814..e0084d54511ee 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -226,7 +226,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ check_esp_err(can_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); return mp_const_none; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); + mp_raise_msg(&mp_type_RuntimeError, "Device is not ready"); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); @@ -402,7 +402,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p self->loopback, self->extframe); } else { - mp_printf(print, "CAN Device is not initialized"); + mp_printf(print, "Device is not initialized"); } } @@ -410,7 +410,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized) { - ESP_LOGW(DEVICE_NAME, "Device is already initialized"); + mp_raise_msg(&mp_type_RuntimeError, "Device is already initialized"); return mp_const_none; } return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); @@ -421,7 +421,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_ini STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { const machine_can_obj_t *self = &machine_can_obj; if (self->config->initialized != true) { - ESP_LOGW(DEVICE_NAME, "Device is not initialized"); + mp_raise_msg(&mp_type_RuntimeError, "Device is not initialized"); return mp_const_none; } check_esp_err(can_stop()); @@ -441,15 +441,15 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); + if (can_idx != 0) { + mp_raise_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx); } machine_can_obj_t *self = &machine_can_obj; if (n_args > 1 || n_kw > 0) { if (self->config->initialized) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode - ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); + //mp_raise_msg(&mp_type_RuntimeError, "Device is going to be reconfigured"); machine_hw_can_deinit(&self); } self->rxcallback = mp_const_none; From cea632bf826c55d860214dfec1eba6470bd67e7b Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:50:44 +0300 Subject: [PATCH 077/180] ESP32: machine_can.c: Use LOOPBACK_MASK instead of magic 0x10 --- ports/esp32/machine_can.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index e0084d54511ee..8140b776ab1d1 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -42,6 +42,8 @@ #if MICROPY_HW_ENABLE_CAN +#define LOOPBACK_MASK 0x10 + // Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) @@ -507,7 +509,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; self->config->general.clkout_divider = 0; - self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); + self->loopback = ((args[ARG_mode].u_int & LOOPBACK_MASK) > 0); self->extframe = args[ARG_extframe].u_bool; if (args[ARG_auto_restart].u_bool) { mp_raise_NotImplementedError("Auto-restart not supported"); @@ -589,9 +591,9 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | LOOPBACK_MASK) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, +// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, From 05d119e0dd1189d21ad06a4ffacba084c8e11cd2 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:58:39 +0300 Subject: [PATCH 078/180] ESP32: machine_can.c: Use direct baudrate values in bit/s instead of CAN_BAUDRATE_Xk const's --- ports/esp32/machine_can.c | 25 ++++++++----------------- ports/esp32/machine_can.h | 11 +---------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 8140b776ab1d1..b65cbaf49b5ed 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -529,28 +529,28 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .triple_sampling = false }); break; - case CAN_BAUDRATE_25k: + case 25000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); break; - case CAN_BAUDRATE_50k: + case 50000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS() ); break; - case CAN_BAUDRATE_100k: + case 100000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS() ); break; - case CAN_BAUDRATE_125k: + case 125000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS() ); break; - case CAN_BAUDRATE_250k: + case 250000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS() ); break; - case CAN_BAUDRATE_500k: + case 500000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS() ); break; - case CAN_BAUDRATE_800k: + case 800000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_800KBITS() ); break; - case CAN_BAUDRATE_1M: + case 1000000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS() ); break; default: @@ -600,15 +600,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, - // CAN_BAUDRATE - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, // CAN_FILTER_MODE { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 9ed50a504f791..10f7f07abea40 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -34,15 +34,6 @@ #define DEVICE_NAME "CAN" -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 - typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, @@ -53,7 +44,7 @@ typedef struct _machine_can_config_t { can_timing_config_t timing; can_filter_config_t filter; can_general_config_t general; - uint16_t baudrate; + uint32_t baudrate; // bit/s bool initialized; } machine_can_config_t; From c74423aa4f17757bc7677665c3fc2cc66d3ecd31 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 19 Jun 2021 00:06:27 +0300 Subject: [PATCH 079/180] ESP32: machine_can.c: Dict more informative than list --- ports/esp32/machine_can.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index b65cbaf49b5ed..8a3fb9391d73c 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -132,6 +132,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { +#if 0 machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { @@ -155,6 +156,23 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); +#else + can_status_info_t status = _machine_hw_can_get_status(); + mp_obj_t dict = mp_obj_new_dict(0); + #define dict_key(key) mp_obj_new_str(#key, strlen(#key)) + #define dict_value(key) MP_OBJ_NEW_SMALL_INT(status.key) + #define dict_store(key) mp_obj_dict_store(dict, dict_key(key), dict_value(key)); + dict_store(state); + dict_store(msgs_to_tx); + dict_store(msgs_to_rx); + dict_store(tx_error_counter); + dict_store(rx_error_counter); + dict_store(tx_failed_count); + dict_store(rx_missed_count); + dict_store(arb_lost_count); + dict_store(bus_error_count); + return dict; +#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); From 0df569da3b53545ba2d3a5d500ea62c7f7aed6ff Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 19 Jun 2021 00:08:35 +0300 Subject: [PATCH 080/180] ESP32: machine_can.c: Add some comments --- ports/esp32/machine_can.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 8a3fb9391d73c..27904d577168d 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -203,7 +203,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ ARG_id, ARG_timeout, ARG_rtr, - ARG_self + //ARG_self }; static const mp_arg_t allowed_args[] = { {MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, @@ -342,7 +342,7 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); -// bank: 0 or 1(only for std) +// bank: 0 only // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW @@ -613,6 +613,17 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, // { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, +/* esp32 can modes +CAN_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages +CAN_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). +CAN_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. +*/ +/* stm32 can modes +#define CAN_MODE_NORMAL FDCAN_MODE_NORMAL +#define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK +#define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING +#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK +*/ // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, From 51be1abcafbe7e4aefb3fe79cffd3a30dfc16b66 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 19 Jun 2021 00:09:29 +0300 Subject: [PATCH 081/180] ESP32: machine_can.c: Set default inits --- ports/esp32/machine_can.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 27904d577168d..a3606bc140e71 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -502,15 +502,15 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_tx, MP_ARG_INT, {.u_int = 17} }, + { MP_QSTR_rx, MP_ARG_INT, {.u_int = 15} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args From 99b827cf8cb907a02c87a117c985cd7945ae2e12 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 14:55:33 -0700 Subject: [PATCH 082/180] esp32: CAN: Use twai.h --- ports/esp32/machine_can.c | 166 +++++++++++++++++++------------------- ports/esp32/machine_can.h | 6 +- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index a3606bc140e71..81c62c170980c 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -34,7 +34,7 @@ // Headers of ESP-IDF library #include "soc/dport_reg.h" -#include "driver/can.h" +#include "driver/twai.h" #include "esp_err.h" #include "esp_log.h" @@ -56,18 +56,18 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), - .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), - .timing = CAN_TIMING_CONFIG_25KBITS(), +machine_can_config_t can_config = { .general = TWAI_GENERAL_CONFIG_DEFAULT(2, 4, 0), + .filter = TWAI_FILTER_CONFIG_ACCEPT_ALL(), + .timing = TWAI_TIMING_CONFIG_25KBITS(), .initialized = false }; STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; // INTERNAL FUNCTION Return status information -STATIC can_status_info_t _machine_hw_can_get_status() { - can_status_info_t status; - check_esp_err(can_get_status_info(&status)); +STATIC twai_status_info_t _machine_hw_can_get_status() { + twai_status_info_t status; + check_esp_err(twai_get_status_info(&status)); return status; } @@ -109,23 +109,23 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { - check_esp_err(can_initiate_recovery()); + check_esp_err(twai_initiate_recovery()); mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution - check_esp_err(can_start()); + check_esp_err(twai_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) { - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); @@ -146,7 +146,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { mp_raise_ValueError(NULL); } } - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); @@ -157,7 +157,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); #else - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); mp_obj_t dict = mp_obj_new_dict(0); #define dict_key(key) mp_obj_new_str(#key, strlen(#key)) #define dict_value(key) MP_OBJ_NEW_SMALL_INT(status.key) @@ -179,20 +179,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machin // Get Alert info STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; - check_esp_err(can_read_alerts(&alerts, 0)); + check_esp_err(twai_read_alerts(&alerts, 0)); return mp_obj_new_int(alerts); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) { - return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); + return mp_obj_new_bool(twai_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) { - return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); + return mp_obj_new_bool(twai_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); @@ -224,26 +224,26 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ if (length > 8) { mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + uint8_t flags = (args[ARG_rtr].u_bool ? TWAI_MSG_FLAG_RTR : TWAI_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; if (self->extframe) { - flags += CAN_MSG_FLAG_EXTD; + flags += TWAI_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; } else { id &= 0x1FF; } if (self->loopback) { - flags += CAN_MSG_FLAG_SELF; + flags += TWAI_MSG_FLAG_SELF; } - can_message_t tx_msg = { .data_length_code = length, + twai_message_t tx_msg = { .data_length_code = length, .identifier = id, .flags = flags }; for (uint8_t i = 0; i < length; i++) { tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { - check_esp_err(can_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + if (_machine_hw_can_get_status().state == TWAI_STATE_RUNNING) { + check_esp_err(twai_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); return mp_const_none; } else { mp_raise_msg(&mp_type_RuntimeError, "Device is not ready"); @@ -266,9 +266,9 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - can_message_t rx_message; + twai_message_t rx_message; //int status = - check_esp_err(can_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + check_esp_err(twai_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; @@ -300,7 +300,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ memcpy(mv->items, rx_message.data, rx_message.data_length_code); } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0); + items[1] = mp_obj_new_bool(rx_message.flags && TWAI_MSG_FLAG_RTR > 0); items[2] = 0; return ret_obj; } @@ -331,13 +331,13 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; self->config->filter.acceptance_mask = 0xFFFFFFFF; - check_esp_err(can_stop()); - check_esp_err(can_driver_uninstall()); - check_esp_err(can_driver_install( + check_esp_err(twai_stop()); + check_esp_err(twai_driver_uninstall()); + check_esp_err(twai_driver_install( &self->config->general, &self->config->timing, &self->config->filter)); - check_esp_err(can_start()); + check_esp_err(twai_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); @@ -383,13 +383,13 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - check_esp_err( can_stop() ); - check_esp_err( can_driver_uninstall() ); - check_esp_err( can_driver_install( + check_esp_err( twai_stop() ); + check_esp_err( twai_driver_uninstall() ); + check_esp_err( twai_driver_install( &self->config->general, &self->config->timing, &self->config->filter) ); - check_esp_err( can_start() ); + check_esp_err( twai_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -400,13 +400,13 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p qstr mode; switch (self->config->general.mode) { - case CAN_MODE_LISTEN_ONLY: + case TWAI_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; - case CAN_MODE_NO_ACK: + case TWAI_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; - case CAN_MODE_NORMAL: + case TWAI_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; default: @@ -426,7 +426,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } } -// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +// init(tx, rx, baudrate, mode = TWAI_MODE_NORMAL, tx_queue = 2, rx_queue = 5) STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized) { @@ -444,8 +444,8 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { mp_raise_msg(&mp_type_RuntimeError, "Device is not initialized"); return mp_const_none; } - check_esp_err(can_stop()); - check_esp_err(can_driver_uninstall()); + check_esp_err(twai_stop()); + check_esp_err(twai_driver_uninstall()); self->config->initialized = false; return mp_const_none; } @@ -500,7 +500,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg ARG_auto_restart }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = TWAI_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, @@ -520,26 +520,26 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.mode = args[ARG_mode].u_int & 0x0F; self->config->general.tx_io = args[ARG_tx_io].u_int; self->config->general.rx_io = args[ARG_rx_io].u_int; - self->config->general.clkout_io = CAN_IO_UNUSED; - self->config->general.bus_off_io = CAN_IO_UNUSED; + self->config->general.clkout_io = TWAI_IO_UNUSED; + self->config->general.bus_off_io = TWAI_IO_UNUSED; self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; - self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || - CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; + self->config->general.alerts_enabled = TWAI_ALERT_AND_LOG || TWAI_ALERT_BELOW_ERR_WARN || TWAI_ALERT_ERR_ACTIVE || TWAI_ALERT_BUS_RECOVERED || + TWAI_ALERT_ABOVE_ERR_WARN || TWAI_ALERT_BUS_ERROR || TWAI_ALERT_ERR_PASS || TWAI_ALERT_BUS_OFF; self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & LOOPBACK_MASK) > 0); self->extframe = args[ARG_extframe].u_bool; if (args[ARG_auto_restart].u_bool) { mp_raise_NotImplementedError("Auto-restart not supported"); } - can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); + twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; - can_timing_config_t *timing; + twai_timing_config_t *timing; switch ((int)args[ARG_baudrate].u_int) { case 0: - timing = &((can_timing_config_t) { + timing = &((twai_timing_config_t) { .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, @@ -548,28 +548,28 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg }); break; case 25000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_25KBITS() ); break; case 50000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_50KBITS() ); break; case 100000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_100KBITS() ); break; case 125000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_125KBITS() ); break; case 250000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_250KBITS() ); break; case 500000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_500KBITS() ); break; case 800000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_800KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_800KBITS() ); break; case 1000000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_1MBITS() ); break; default: mp_raise_ValueError("Unable to set baudrate"); @@ -579,11 +579,11 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - check_esp_err(can_driver_install( + check_esp_err(twai_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL())); - check_esp_err(can_start()); + &(twai_filter_config_t) TWAI_FILTER_CONFIG_ACCEPT_ALL())); + check_esp_err(twai_start()); self->config->initialized = true; return mp_const_none; } @@ -608,15 +608,15 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, // CAN_MODE - { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | LOOPBACK_MASK) }, - { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, -// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact - { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(TWAI_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(TWAI_MODE_NORMAL | LOOPBACK_MASK) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(TWAI_MODE_NO_ACK) }, +// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(TWAI_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(TWAI_MODE_LISTEN_ONLY) }, /* esp32 can modes -CAN_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages -CAN_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). -CAN_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. +TWAI_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages +TWAI_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). +TWAI_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. */ /* stm32 can modes #define CAN_MODE_NORMAL FDCAN_MODE_NORMAL @@ -625,28 +625,28 @@ CAN_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transm #define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK */ // CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(TWAI_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(TWAI_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(TWAI_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(TWAI_STATE_RECOVERING) }, // CAN_FILTER_MODE { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, // CAN_ALERT - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(TWAI_ALERT_TX_IDLE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(TWAI_ALERT_TX_SUCCESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(TWAI_ALERT_BELOW_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(TWAI_ALERT_ERR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(TWAI_ALERT_RECOVERY_IN_PROGRESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(TWAI_ALERT_BUS_RECOVERED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(TWAI_ALERT_ARB_LOST) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(TWAI_ALERT_ABOVE_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(TWAI_ALERT_BUS_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(TWAI_ALERT_TX_FAILED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(TWAI_ALERT_RX_QUEUE_FULL) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(TWAI_ALERT_ERR_PASS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(TWAI_ALERT_BUS_OFF) } }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 10f7f07abea40..f4bbc00eb38d3 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -41,9 +41,9 @@ typedef enum _filter_mode_t{ } filter_mode_t; typedef struct _machine_can_config_t { - can_timing_config_t timing; - can_filter_config_t filter; - can_general_config_t general; + twai_timing_config_t timing; + twai_filter_config_t filter; + twai_general_config_t general; uint32_t baudrate; // bit/s bool initialized; } machine_can_config_t; From 85984fad24715daf1c9471f738e089b81a9beb9b Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 14:59:53 -0700 Subject: [PATCH 083/180] esp32: CAN: Remove trailing spaces --- ports/esp32/machine_can.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 81c62c170980c..dbee251fc0838 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -172,7 +172,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { dict_store(arb_lost_count); dict_store(bus_error_count); return dict; -#endif +#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); @@ -267,7 +267,6 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); twai_message_t rx_message; - //int status = check_esp_err(twai_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview @@ -308,7 +307,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_rec STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (callback_in == mp_const_none) { self->rxcallback = mp_const_none; @@ -613,16 +612,16 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(TWAI_MODE_NO_ACK) }, // { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(TWAI_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(TWAI_MODE_LISTEN_ONLY) }, -/* esp32 can modes +/* esp32 can modes TWAI_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages TWAI_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). TWAI_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. */ -/* stm32 can modes +/* stm32 can modes #define CAN_MODE_NORMAL FDCAN_MODE_NORMAL #define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK #define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING -#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK +#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK */ // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(TWAI_STATE_STOPPED) }, From 7e8a8f46edf082d832ac780213c85926a86f2944 Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Thu, 8 Jul 2021 10:07:42 +0300 Subject: [PATCH 084/180] esp32: machine_can.c fix initialisation argument ARG_bs2 https://github.com/micropython/micropython/pull/7381#issuecomment-876154663 Thanks to @kdschlosser --- ports/esp32/machine_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index dbee251fc0838..5bb7741d7837c 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -542,7 +542,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, - .tseg_2 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs2].u_int, .triple_sampling = false }); break; From a6c3c65a1372ecece3c78643ca2e63464d6371ae Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 26 Sep 2019 22:29:04 +0200 Subject: [PATCH 085/180] first commit --- lib/axtls | 2 +- lib/tinyusb | 2 +- ports/esp32/Makefile | 214 ++++++++++++++++++++++++++++++++++++- ports/esp32/machine_can.c | 133 +++++++++++++++++++++++ ports/esp32/machine_can.h | 94 ++++++++++++++++ ports/esp32/modmachine.c | 3 + ports/esp32/modmachine.h | 1 + ports/esp32/mpconfigport.h | 2 +- 8 files changed, 447 insertions(+), 4 deletions(-) create mode 100644 ports/esp32/machine_can.c create mode 100644 ports/esp32/machine_can.h diff --git a/lib/axtls b/lib/axtls index 531cab9c278c9..43a6e6bd3bbc0 160000 --- a/lib/axtls +++ b/lib/axtls @@ -1 +1 @@ -Subproject commit 531cab9c278c947d268bd4c94ecab9153a961b43 +Subproject commit 43a6e6bd3bbc03dc501e16b89fba0ef042ed3ea0 diff --git a/lib/tinyusb b/lib/tinyusb index d49938d0f5052..7b62c71dd5ec4 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit d49938d0f5052bce70e55c652b657c0a6a7e84fe +Subproject commit 7b62c71dd5ec42e61499d2d83902df9484842670 diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 403b698a32335..a6220eee4e851 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -11,6 +11,168 @@ BUILD ?= build-$(BOARD) # Device serial settings. PORT ?= /dev/ttyUSB0 BAUD ?= 460800 +FLASH_MODE ?= dio +FLASH_FREQ ?= 40m +FLASH_SIZE ?= 4MB +CROSS_COMPILE ?= xtensa-esp32-elf- +OBJDUMP = $(CROSS_COMPILE)objdump + +SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined +SDKCONFIG_H = $(BUILD)/sdkconfig.h + +# the git hash of the currently supported ESP IDF version +ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df +ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f + +define print_supported_git_hash +$(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) +$(info Supported git hash (v4.0-beta1) (experimental): $(ESPIDF_SUPHASH_V4)) +endef + +# paths to ESP IDF and its components +ifeq ($(ESPIDF),) +ifneq ($(IDF_PATH),) +ESPIDF = $(IDF_PATH) +else +$(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) +$(info See README.md for installation instructions.) +$(call print_supported_git_hash) +$(error ESPIDF not set) +endif +endif + +ESPCOMP = $(ESPIDF)/components +ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py +ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) +ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) + +# verify the ESP IDF version +ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') + +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) +$(info Building with ESP IDF v3) +else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +$(info Building with ESP IDF v4) + +PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') +ifneq ($(PYPARSING_VERSION),2.3.1) +$(info ** ERROR **) +$(info EDP IDF requires pyparsing version less than 2.4) +$(info You will need to set up a Python virtual environment with pyparsing 2.3.1) +$(info Please see README.md for more information) +$(error Incorrect pyparsing version) +endif +else +$(info ** WARNING **) +$(info The git hash of ESP IDF does not match the supported version) +$(info The build may complete and the firmware may work but it is not guaranteed) +$(info ESP IDF path: $(ESPIDF)) +$(info Current git hash: $(ESPIDF_CURHASH)) +$(call print_supported_git_hash) +endif + +# pretty format of ESP IDF version, used internally by the IDF +IDF_VER := $(shell git -C $(ESPIDF) describe) + +ifeq ($(shell which $(CC) 2> /dev/null),) +$(info ** ERROR **) +$(info Cannot find C compiler $(CC)) +$(info Add the xtensa toolchain to your PATH. See README.md) +$(error C compiler missing) +endif + +# include sdkconfig to get needed configuration values +include $(SDKCONFIG) + +################################################################################ +# Compiler and linker flags + +INC += -I. +INC += -I$(TOP) +INC += -I$(TOP)/lib/mp-readline +INC += -I$(TOP)/lib/netutils +INC += -I$(TOP)/lib/timeutils +INC += -I$(BUILD) + +INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include +INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader +INC_ESPCOMP += -I$(ESPCOMP)/console +INC_ESPCOMP += -I$(ESPCOMP)/driver/include +INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver +INC_ESPCOMP += -I$(ESPCOMP)/efuse/include +INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include +INC_ESPCOMP += -I$(ESPCOMP)/soc/include +INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/heap/include +INC_ESPCOMP += -I$(ESPCOMP)/log/include +INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include +INC_ESPCOMP += -I$(ESPCOMP)/newlib/include +INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include +INC_ESPCOMP += -I$(ESPCOMP)/freertos/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_ringbuf/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_event/include +INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include +INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include +INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps +INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include +INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include +INC_ESPCOMP += -I$(ESPCOMP)/mdns/include +INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include +INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include +INC_ESPCOMP += -I$(ESPCOMP)/ulp/include +INC_ESPCOMP += -I$(ESPCOMP)/vfs/include +INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include +INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include +INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include +INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include +INC_ESPCOMP += -I$(ESPCOMP)/app_update/include +INC_ESPCOMP += -I$(ESPCOMP)/pthread/include +INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include +INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include +#INC_ESPCOMP += -I$(ESPCOMP)/can/include + +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_eth/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_event/private_include +INC_ESPCOMP += -I$(ESPCOMP)/esp_rom/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/include +INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/esp32/include +INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp +INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/private_include +INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include/esp_supplicant +INC_ESPCOMP += -I$(ESPCOMP)/xtensa/include +INC_ESPCOMP += -I$(ESPCOMP)/xtensa/esp32/include +else +INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include +INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib +INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include +INC_ESPCOMP += -I$(ESPCOMP)/json/include +INC_ESPCOMP += -I$(ESPCOMP)/json/port/include +INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc +INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include +INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes +endif + +# these flags are common to C and C++ compilation +CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ + -mlongcalls -nostdlib \ + -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ + -Wno-error=unused-variable -Wno-error=deprecated-declarations \ + -DESP_PLATFORM + +CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H +CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) +CFLAGS += -DIDF_VER=\"$(IDF_VER)\" +CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) +CFLAGS += -I$(BOARD_DIR) + +ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) +CFLAGS += -DMICROPY_ESP_IDF_4=1 +endif PYTHON ?= python3 @@ -24,7 +186,57 @@ ifdef USER_C_MODULES CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES} endif -IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD) $(CMAKE_ARGS) +################################################################################ +# List of MicroPython source and object files + +SRC_C = \ + main.c \ + uart.c \ + gccollect.c \ + mphalport.c \ + fatfs_port.c \ + help.c \ + modutime.c \ + moduos.c \ + machine_timer.c \ + machine_pin.c \ + machine_touchpad.c \ + machine_adc.c \ + machine_dac.c \ + machine_i2c.c \ + machine_pwm.c \ + machine_uart.c \ + machine_can.c \ + modmachine.c \ + modnetwork.c \ + network_lan.c \ + network_ppp.c \ + modsocket.c \ + modesp.c \ + esp32_partition.c \ + esp32_ulp.c \ + modesp32.c \ + espneopixel.c \ + machine_hw_spi.c \ + machine_wdt.c \ + mpthreadport.c \ + machine_rtc.c \ + machine_sdcard.c \ + $(wildcard $(BOARD_DIR)/*.c) \ + $(SRC_MOD) + +EXTMOD_SRC_C = $(addprefix extmod/,\ + modonewire.c \ + ) + +LIB_SRC_C = $(addprefix lib/,\ + mp-readline/readline.c \ + netutils/netutils.c \ + timeutils/timeutils.c \ + utils/pyexec.c \ + utils/interrupt_char.c \ + utils/sys_stdio_mphal.c \ + ) ifdef FROZEN_MANIFEST IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c new file mode 100644 index 0000000000000..5652079b5c2a3 --- /dev/null +++ b/ports/esp32/machine_can.c @@ -0,0 +1,133 @@ +/* The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/runtime.h" +#include "py/mphal.h" +#include "py/mperrno.h" + +#include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h + +#include "driver/can.h" +#include "machine_can.h" + +#if MICROPY_HW_ENABLE_CAN + +STATIC const mp_obj_type_t machine_hw_can_type; +STATIC machine_hw_can_obj_t machine_hw_can_obj; + +bool can_init(machine_hw_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, CAN_speed_t baudrate, uint32_t mode) { + + can_driver_install( + CAN_GENERAL_CONFIG_DEFAULT(rx, rx, mode), + CAN_TIMING_CONFIG_1MBITS(), + CAN_FILTER_CONFIG_ACCEPT_ALL() + ); + + double __tq; //Time quantum + + //enable module + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST); + + //configure TX pin + gpio_set_level(tx, 1); + gpio_set_direction(tx,GPIO_MODE_OUTPUT); + gpio_matrix_out(tx,CAN_TX_IDX,0,0); + gpio_pad_select_gpio(tx); + + //configure RX pin + gpio_set_direction(rx,GPIO_MODE_INPUT); + gpio_matrix_in(rx,CAN_RX_IDX,0); + gpio_pad_select_gpio(rx); + + //set to PELICAN mode #FIXME: ability to change the mode to LOOPBACK + MODULE_CAN->CDR.B.CAN_M = 0x1; + + //synchronization jump width is the same for all baud rates + MODULE_CAN->BTR0.B.SJW = 0x1; + + //TSEG2 is the same for all baud rates + MODULE_CAN->BTR1.B.TSEG2 = 0x1; + + //select time quantum and set TSEG1 + switch(baudrate){ + case CAN_SPEED_1000KBPS: + MODULE_CAN->BTR1.B.TSEG1 = 0x4; + __tq = 0.125; + break; + + case CAN_SPEED_800KBPS: + MODULE_CAN->BTR1.B.TSEG1 =0x6; + __tq = 0.125; + break; + default: + MODULE_CAN->BTR1.B.TSEG1 = 0xc; + __tq = ((float)1000/baudrate) / 16; + } + + //set baud rate prescaler FIXME: APB_CLK_FREQ in soc/soc.h + MODULE_CAN->BTR0.B.BRP=(uint8_t)round((((APB_CLK_FREQ * __tq) / 2) - 1)/1000000)-1; + + /* Set sampling + * 1 -> triple; the bus is sampled three times; recommended for low/medium speed buses (class A and B) where filtering spikes on the bus line is beneficial + * 0 -> single; the bus is sampled once; recommended for high speed buses (SAE class C)*/ + MODULE_CAN->BTR1.B.SAM =0x1; + + //enable all interrupts + MODULE_CAN->IER.U = 0xff; + + //no acceptance filtering, as we want to fetch all messages + MODULE_CAN->MBX_CTRL.ACC.CODE[0] = 0; + MODULE_CAN->MBX_CTRL.ACC.CODE[1] = 0; + MODULE_CAN->MBX_CTRL.ACC.CODE[2] = 0; + MODULE_CAN->MBX_CTRL.ACC.CODE[3] = 0; + MODULE_CAN->MBX_CTRL.ACC.MASK[0] = 0xff; + MODULE_CAN->MBX_CTRL.ACC.MASK[1] = 0xff; + MODULE_CAN->MBX_CTRL.ACC.MASK[2] = 0xff; + MODULE_CAN->MBX_CTRL.ACC.MASK[3] = 0xff; + + //set to normal mode + MODULE_CAN->OCR.B.OCMODE=__CAN_OC_NOM; + + //clear error counters + MODULE_CAN->TXERR.U = 0; + MODULE_CAN->RXERR.U = 0; + (void)MODULE_CAN->ECC; + + //clear interrupt flags + (void)MODULE_CAN->IR.U; + + //install CAN ISR + esp_intr_alloc(ETS_CAN_INTR_SOURCE,0,CAN_isr,NULL,NULL); + + //Showtime. Release Reset Mode. + MODULE_CAN->MOD.B.RM = 0; + + return 0; +} + +int can_deinit(machine_hw_can_obj_t *self){ + return can_driver_uninstall(); +} + +#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h new file mode 100644 index 0000000000000..1793133a1da82 --- /dev/null +++ b/ports/esp32/machine_can.h @@ -0,0 +1,94 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ESP32_CAN_H +#define MICROPY_INCLUDED_ESP32_CAN_H + +#if MICROPY_HW_ENABLE_CAN + +typedef enum { + CAN_SPEED_100KBPS=100, /**< \brief CAN Node runs at 100kBit/s. */ + CAN_SPEED_125KBPS=125, /**< \brief CAN Node runs at 125kBit/s. */ + CAN_SPEED_250KBPS=250, /**< \brief CAN Node runs at 250kBit/s. */ + CAN_SPEED_500KBPS=500, /**< \brief CAN Node runs at 500kBit/s. */ + CAN_SPEED_800KBPS=800, /**< \brief CAN Node runs at 800kBit/s. */ + CAN_SPEED_1000KBPS=1000 /**< \brief CAN Node runs at 1000kBit/s. */ +}CAN_speed_t; + +enum { + CAN_STATE_STOPPED, + CAN_STATE_ERROR_ACTIVE, + CAN_STATE_ERROR_WARNING, + CAN_STATE_ERROR_PASSIVE, + CAN_STATE_BUS_OFF, +}; + +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + + + +/** \brief CAN configuration structure */ +typedef struct { + CAN_speed_t speed; /**< \brief CAN speed. */ + gpio_num_t tx_pin_id; /**< \brief TX pin. */ + gpio_num_t rx_pin_id; /**< \brief RX pin. */ + QueueHandle_t rx_queue; /**< \brief Handler to FreeRTOS RX queue. */ +}CAN_device_t; + +typedef struct _machine_hw_can_obj_t { + mp_obj_base_t base; + mp_obj_t rxcallback0; + mp_obj_t rxcallback1; + mp_uint_t can_id : 8; + bool is_enabled : 1; + bool extframe : 1; + byte rx_state0; + byte rx_state1; + uint16_t num_error_warning; + uint16_t num_error_passive; + uint16_t num_bus_off; + CAN_HandleTypeDef can; +} esp32_can_obj_t; + +extern const mp_obj_type_t machine_can_type; + +//void can_init0(void); #TODO: +//void can_deinit_all(void); #TODO: +bool can_init(machine_hw_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, CAN_speed_t baudrate, uint32_t mode); +void can_deinit(machine_hw_can_obj_t *self); + +void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank); +int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms); +HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); +void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason); + +#endif // MICROPY_HW_ENABLE_CAN + +#endif // MICROPY_INCLUDED_ESP32_CAN_H diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 5f94007d4995b..7e8aa33926e13 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -307,6 +307,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) }, { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) }, + #if MICROPY_HW_ENABLE_CAN + { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, + #endif // Reset reasons { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) }, diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index 7bf03b0cabc7e..2586440e210ee 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -20,6 +20,7 @@ extern const mp_obj_type_t machine_hw_i2c_type; extern const mp_obj_type_t machine_hw_spi_type; extern const mp_obj_type_t machine_i2s_type; extern const mp_obj_type_t machine_uart_type; +extern const mp_obj_type_t machine_can_type; extern const mp_obj_type_t machine_rtc_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 057251fa49b3c..96b20c50aa038 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -170,7 +170,7 @@ #endif #ifndef MICROPY_HW_ENABLE_SDCARD #define MICROPY_HW_ENABLE_SDCARD (1) -#endif +#define MICROPY_HW_ENABLE_CAN (1) #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly #define MICROPY_PY_USSL (1) From 60be66072fbb9528a8c4e37e444b07960e4d235a Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sat, 28 Sep 2019 18:26:39 +0200 Subject: [PATCH 086/180] Enabled module --- ports/esp32/Makefile | 2 +- ports/esp32/machine_can.c | 129 ++++++++++---------------------------- ports/esp32/machine_can.h | 60 +++++------------- ports/esp32/modmachine.c | 11 +--- 4 files changed, 53 insertions(+), 149 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index a6220eee4e851..5950efbe37f10 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -132,7 +132,7 @@ INC_ESPCOMP += -I$(ESPCOMP)/app_update/include INC_ESPCOMP += -I$(ESPCOMP)/pthread/include INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include -#INC_ESPCOMP += -I$(ESPCOMP)/can/include +INC_ESPCOMP += -I$(ESPCOMP)/can/include ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5652079b5c2a3..467d7b4e5a85a 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -21,113 +21,52 @@ * THE SOFTWARE. */ +#include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" #include "py/mperrno.h" +#include +//Headers of ESP-IDF library #include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h - #include "driver/can.h" +#include "esp_err.h" +#include "esp_log.h" + #include "machine_can.h" #if MICROPY_HW_ENABLE_CAN -STATIC const mp_obj_type_t machine_hw_can_type; -STATIC machine_hw_can_obj_t machine_hw_can_obj; - -bool can_init(machine_hw_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, CAN_speed_t baudrate, uint32_t mode) { - - can_driver_install( - CAN_GENERAL_CONFIG_DEFAULT(rx, rx, mode), - CAN_TIMING_CONFIG_1MBITS(), - CAN_FILTER_CONFIG_ACCEPT_ALL() - ); - - double __tq; //Time quantum - - //enable module - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_CAN_CLK_EN); - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_CAN_RST); - - //configure TX pin - gpio_set_level(tx, 1); - gpio_set_direction(tx,GPIO_MODE_OUTPUT); - gpio_matrix_out(tx,CAN_TX_IDX,0,0); - gpio_pad_select_gpio(tx); - - //configure RX pin - gpio_set_direction(rx,GPIO_MODE_INPUT); - gpio_matrix_in(rx,CAN_RX_IDX,0); - gpio_pad_select_gpio(rx); - - //set to PELICAN mode #FIXME: ability to change the mode to LOOPBACK - MODULE_CAN->CDR.B.CAN_M = 0x1; - - //synchronization jump width is the same for all baud rates - MODULE_CAN->BTR0.B.SJW = 0x1; - - //TSEG2 is the same for all baud rates - MODULE_CAN->BTR1.B.TSEG2 = 0x1; - - //select time quantum and set TSEG1 - switch(baudrate){ - case CAN_SPEED_1000KBPS: - MODULE_CAN->BTR1.B.TSEG1 = 0x4; - __tq = 0.125; - break; - - case CAN_SPEED_800KBPS: - MODULE_CAN->BTR1.B.TSEG1 =0x6; - __tq = 0.125; - break; - default: - MODULE_CAN->BTR1.B.TSEG1 = 0xc; - __tq = ((float)1000/baudrate) / 16; - } - - //set baud rate prescaler FIXME: APB_CLK_FREQ in soc/soc.h - MODULE_CAN->BTR0.B.BRP=(uint8_t)round((((APB_CLK_FREQ * __tq) / 2) - 1)/1000000)-1; - - /* Set sampling - * 1 -> triple; the bus is sampled three times; recommended for low/medium speed buses (class A and B) where filtering spikes on the bus line is beneficial - * 0 -> single; the bus is sampled once; recommended for high speed buses (SAE class C)*/ - MODULE_CAN->BTR1.B.SAM =0x1; - - //enable all interrupts - MODULE_CAN->IER.U = 0xff; - - //no acceptance filtering, as we want to fetch all messages - MODULE_CAN->MBX_CTRL.ACC.CODE[0] = 0; - MODULE_CAN->MBX_CTRL.ACC.CODE[1] = 0; - MODULE_CAN->MBX_CTRL.ACC.CODE[2] = 0; - MODULE_CAN->MBX_CTRL.ACC.CODE[3] = 0; - MODULE_CAN->MBX_CTRL.ACC.MASK[0] = 0xff; - MODULE_CAN->MBX_CTRL.ACC.MASK[1] = 0xff; - MODULE_CAN->MBX_CTRL.ACC.MASK[2] = 0xff; - MODULE_CAN->MBX_CTRL.ACC.MASK[3] = 0xff; - - //set to normal mode - MODULE_CAN->OCR.B.OCMODE=__CAN_OC_NOM; - - //clear error counters - MODULE_CAN->TXERR.U = 0; - MODULE_CAN->RXERR.U = 0; - (void)MODULE_CAN->ECC; - - //clear interrupt flags - (void)MODULE_CAN->IR.U; - - //install CAN ISR - esp_intr_alloc(ETS_CAN_INTR_SOURCE,0,CAN_isr,NULL,NULL); - - //Showtime. Release Reset Mode. - MODULE_CAN->MOD.B.RM = 0; - - return 0; +const mp_obj_type_t machine_can_type; + +void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t baudrate, uint32_t mode) { + static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); + static const can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS(); + //Set TX queue length to 0 due to listen only mode + can_general_config_t g_config = {.mode = mode, + .tx_io = tx, .rx_io = rx, + .clkout_io = CAN_IO_UNUSED, .bus_off_io = CAN_IO_UNUSED, + .tx_queue_len = 0, .rx_queue_len = 5, + .alerts_enabled = CAN_ALERT_NONE, + .clkout_divider = 0}; + ESP_ERROR_CHECK(can_driver_install(&g_config, &t_config, &f_config)); + ESP_LOGI("CAN", "Driver installed"); + ESP_ERROR_CHECK(can_start()); + ESP_LOGI("CAN", "Driver started"); } -int can_deinit(machine_hw_can_obj_t *self){ - return can_driver_uninstall(); +/*void machine_can_trasmit(machine_hw_can_obj_t *self, uint32_t address, size_t length, mp_machine_can_buf_t *data) +{ + can_message_t tx_msg = {.data_length_code = length, .identifier = address, .flags = CAN_MSG_FLAG_SELF}; + for (uint8_t i=0; i Date: Sun, 29 Sep 2019 12:07:47 +0200 Subject: [PATCH 087/180] Stable basic code for module loading in Python --- ports/esp32/machine_can.c | 26 ++++++++++++------ ports/esp32/machine_can.h | 57 +++++++++++++++++++-------------------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 467d7b4e5a85a..dac51bb1b9459 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -23,6 +23,7 @@ #include "py/obj.h" #include "py/runtime.h" +#include "py/builtin.h" #include "py/mphal.h" #include "py/mperrno.h" #include @@ -35,12 +36,19 @@ #include "machine_can.h" -#if MICROPY_HW_ENABLE_CAN +//#if MICROPY_HW_ENABLE_CAN -const mp_obj_type_t machine_can_type; +const machine_hw_can_obj_t can_default = {.tx=6, .rx=4}; -void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t baudrate, uint32_t mode) { - static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); +STATIC const mp_obj_type_t machine_hw_can_type; //FIXME: da popolare + +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_hw_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "CAN(tx=%u, rx=%u)", self->tx, self->rx); +} + +STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in) { + /*static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); static const can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS(); //Set TX queue length to 0 due to listen only mode can_general_config_t g_config = {.mode = mode, @@ -52,9 +60,11 @@ void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t ba ESP_ERROR_CHECK(can_driver_install(&g_config, &t_config, &f_config)); ESP_LOGI("CAN", "Driver installed"); ESP_ERROR_CHECK(can_start()); - ESP_LOGI("CAN", "Driver started"); + ESP_LOGI("CAN", "Driver started");*/ + return mp_const_none; } + /*void machine_can_trasmit(machine_hw_can_obj_t *self, uint32_t address, size_t length, mp_machine_can_buf_t *data) { can_message_t tx_msg = {.data_length_code = length, .identifier = address, .flags = CAN_MSG_FLAG_SELF}; @@ -62,11 +72,11 @@ void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t ba ESP_ERROR_CHECK(can_transmit(&tx_msg, portMAX_DELAY)); }*/ -void machine_can_deinit(machine_can_obj_t *self){ +/*void machine_can_deinit(machine_can_obj_t *self){ ESP_ERROR_CHECK(can_stop()); ESP_LOGI("CAN", "Driver stopped"); ESP_ERROR_CHECK(can_driver_uninstall()); ESP_LOGI("CAN", "Driver uninstalled"); -} +}*/ -#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file +//#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3b20ea5a3929e..5cccb97ba7e97 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -30,37 +30,34 @@ #include "py/obj.h" - -typedef enum _rx_state_t { - RX_STATE_FIFO_EMPTY = 0, - RX_STATE_MESSAGE_PENDING, - RX_STATE_FIFO_FULL, - RX_STATE_FIFO_OVERFLOW, -} rx_state_t; - typedef struct _machine_can_obj_t { mp_obj_base_t base; - mp_obj_t rxcallback; - gpio_num_t tx; - gpio_num_t rx; -} machine_can_obj_t; - -extern const mp_obj_type_t machine_can_type; - -//extern const mp_obj_type_t machine_can_type; -void can_init(machine_can_obj_t *self, gpio_num_t tx, gpio_num_t rx, uint32_t baudrate, uint32_t mode); -void can_deinit(machine_can_obj_t *self); - -//void can_trasmit(uint32_t address, byte data[], uint8_t length); - -//void can_init0(void); #TODO: -//void can_deinit_all(void); #TODO: - - -/*void can_clearfilter(pyb_can_obj_t *self, uint32_t f, uint8_t bank); -int can_receive(CAN_HandleTypeDef *can, int fifo, CanRxMsgTypeDef *msg, uint8_t *data, uint32_t timeout_ms); -HAL_StatusTypeDef CAN_Transmit(CAN_HandleTypeDef *hcan, uint32_t Timeout); -void pyb_can_handle_callback(pyb_can_obj_t *self, uint fifo_id, mp_obj_t callback, mp_obj_t irq_reason); -*/ + uint8_t tx; + uint8_t rx; +} machine_hw_can_obj_t; + +//Functions signature definition +STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in); +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); + +//Python function declarations +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_init_obj, machine_hw_can_init); + +//Python objects list declaration +STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(125) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(250) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(500) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(1000) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); + +//Python object definition +const mp_obj_type_t machine_can_type = { + { &mp_type_type }, + .name = MP_QSTR_CAN, + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, +}; #endif // MICROPY_INCLUDED_ESP32_CAN_H From a3ca589b4dc7314f8fa96c4ba677c62d01721352 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 18:52:25 +0200 Subject: [PATCH 088/180] Full initialization and dummy write --- ports/esp32/machine_can.c | 222 +++++++++++++++++++++++++++++++++----- ports/esp32/machine_can.h | 74 +++++++++++-- 2 files changed, 260 insertions(+), 36 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index dac51bb1b9459..6077f4ac48a7b 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -38,30 +38,78 @@ //#if MICROPY_HW_ENABLE_CAN -const machine_hw_can_obj_t can_default = {.tx=6, .rx=4}; +// singleton CAN device object +machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), + .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), + .timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()), + .initialized = false}; + +STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; -STATIC const mp_obj_type_t machine_hw_can_type; //FIXME: da popolare -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_hw_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "CAN(tx=%u, rx=%u)", self->tx, self->rx); + + + +STATIC can_state_t _machine_hw_can_get_state(){ + can_status_info_t status; + ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + return status.state; } -STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in) { - /*static const can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); - static const can_timing_config_t t_config = CAN_TIMING_CONFIG_25KBITS(); - //Set TX queue length to 0 due to listen only mode - can_general_config_t g_config = {.mode = mode, - .tx_io = tx, .rx_io = rx, - .clkout_io = CAN_IO_UNUSED, .bus_off_io = CAN_IO_UNUSED, - .tx_queue_len = 0, .rx_queue_len = 5, - .alerts_enabled = CAN_ALERT_NONE, - .clkout_divider = 0}; - ESP_ERROR_CHECK(can_driver_install(&g_config, &t_config, &f_config)); - ESP_LOGI("CAN", "Driver installed"); - ESP_ERROR_CHECK(can_start()); - ESP_LOGI("CAN", "Driver started");*/ - return mp_const_none; +STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in){ + can_status_info_t status; + ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + return mp_obj_new_int(status.msgs_to_rx); +} + +STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ + can_status_info_t status; + ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + return mp_obj_new_int(status.msgs_to_tx); +} + +STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) { + int value = mp_obj_get_int(address); + if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); + + if (_machine_hw_can_get_state()==CAN_STATE_RUNNING){ + //TODO: Check if queue is full + can_message_t tx_msg = {.data_length_code = 2, .identifier = 0x86, .flags = CAN_MSG_FLAG_SELF}; + tx_msg.data[0] = 0x58; + tx_msg.data[1] = 0x86; + ESP_ERROR_CHECK(can_transmit(&tx_msg, 100)); //FIXME: remove ESP_ERROR_CHECK + return machine_hw_can_get_rx_waiting_messages(self_in); + }else{ + ESP_LOGW(DEVICE_NAME, "Unable to send the message"); + return MP_OBJ_NEW_SMALL_INT(-1); + } +} + +STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in) { + can_message_t rx_message; + switch(can_receive(&rx_message, 1)){ + case ESP_ERR_TIMEOUT: + ESP_LOGW(DEVICE_NAME, "Time-out"); break; + case ESP_ERR_INVALID_ARG: + ESP_LOGE(DEVICE_NAME, "Invalid Args"); break; + case ESP_ERR_INVALID_STATE: + ESP_LOGW(DEVICE_NAME, "Invalid State"); break; + case ESP_OK: + return MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + }; + return MP_OBJ_NEW_SMALL_INT(-1); + +} + +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->config->initialized){ + mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%u)", self->config->general->tx_io, self->config->general->rx_io, + self->config->baudrate, self->config->general->mode); + }else{ + mp_printf(print, "CAN Device is not initialized"); + } + } @@ -72,11 +120,133 @@ STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in) { ESP_ERROR_CHECK(can_transmit(&tx_msg, portMAX_DELAY)); }*/ -/*void machine_can_deinit(machine_can_obj_t *self){ - ESP_ERROR_CHECK(can_stop()); - ESP_LOGI("CAN", "Driver stopped"); - ESP_ERROR_CHECK(can_driver_uninstall()); - ESP_LOGI("CAN", "Driver uninstalled"); -}*/ +// CAN(...) No argument to get the object +// Any argument will be used to init the device through init function +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args){ + const machine_can_obj_t *self = &machine_can_obj; + + if (n_args > 0 || n_kw > 0) { + if (self->config->initialized) { + // The caller is requesting a reconfiguration of the hardware + // this can only be done if the hardware is in init mode + ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); + machine_hw_can_deinit(&self); + } + //TODO: implement callback + /*self->rxcallback0 = mp_const_none; + self->rxcallback1 = mp_const_none; + self->rx_state0 = RX_STATE_FIFO_EMPTY; + self->rx_state1 = RX_STATE_FIFO_EMPTY;*/ + + // start the peripheral + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_hw_can_init_helper(self, n_args, args, &kw_args); + } + return MP_OBJ_FROM_PTR(self); +} + +// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + const machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized){ + ESP_LOGW(DEVICE_NAME, "Device is already initialized"); + return mp_const_false; + } + return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); +} + +// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + }; + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + //Check if device was already configured + if (self->config->initialized){ + ESP_LOGE(DEVICE_NAME, "Device is already initialized: unable to re-init"); + return mp_const_none; + } + //Configure device + can_general_config_t g_config = {.mode = args[ARG_mode].u_int, + .tx_io = args[ARG_tx].u_int, + .rx_io = args[ARG_rx].u_int, + .clkout_io = CAN_IO_UNUSED, + .bus_off_io = CAN_IO_UNUSED, + .tx_queue_len = args[ARG_tx_queue].u_int, + .rx_queue_len = args[ARG_rx_queue].u_int, + .alerts_enabled = CAN_ALERT_NONE, + .clkout_divider = 0}; + self->config->general = &g_config; + + switch ((int)args[ARG_baudrate].u_int){ + case CAN_BAUDRATE_25k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + break; + case CAN_BAUDRATE_50k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + break; + case CAN_BAUDRATE_100k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + break; + case CAN_BAUDRATE_125k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + break; + case CAN_BAUDRATE_250k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + break; + case CAN_BAUDRATE_500k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + break; + case CAN_BAUDRATE_800k: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + break; + case CAN_BAUDRATE_1M: + self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + break; + default: + ESP_LOGE(DEVICE_NAME, "Unable to set baudrate"); + self->config->baudrate = 0; + return mp_const_none; + } + self->config->baudrate = args[ARG_baudrate].u_int; + + uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); + if (status != ESP_OK){ + ESP_LOGE(DEVICE_NAME, "Unable to init the device. ErrCode: %u",status); + }else if (can_start() != ESP_OK){ + ESP_LOGE(DEVICE_NAME, "Unable to start the device. ErrCode: %u",status); + }else{ + self->config->initialized = true; + } + + return mp_const_none; +} + +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ + const machine_can_obj_t *self = &machine_can_obj; + if (self->config->initialized != true){ + ESP_LOGW(DEVICE_NAME, "Device is not initialized"); + return mp_const_false; + } + if(can_stop()!=ESP_OK){ + ESP_LOGW(DEVICE_NAME, "Unable to stop device"); + } + if (can_driver_uninstall() != ESP_OK){ + ESP_LOGW(DEVICE_NAME, "Unable to uninstall device"); + return mp_const_false; + } + self->config->initialized = false; + return mp_const_true; +} //#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 5cccb97ba7e97..d2b2d101553db 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -30,26 +30,78 @@ #include "py/obj.h" +#define DEVICE_NAME "CAN" + +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 + + +typedef struct _machine_can_config_t { + const can_timing_config_t *timing; + const can_filter_config_t *filter; + const can_general_config_t *general; + uint16_t baudrate; + bool initialized; +} machine_can_config_t; + typedef struct _machine_can_obj_t { mp_obj_base_t base; - uint8_t tx; - uint8_t rx; -} machine_hw_can_obj_t; + machine_can_config_t *config; +} machine_can_obj_t; + +//Internal functions +STATIC can_state_t _machine_hw_can_get_state(); //Functions signature definition -STATIC mp_obj_t machine_hw_can_init(mp_obj_t self_in); +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) ; +STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in); //Python function declarations -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_init_obj, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_write_obj, machine_hw_can_write); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_read_obj, machine_hw_can_read); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); +MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { + //CAN_ATTRIBUTES + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, + //CAN_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(125) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(250) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(500) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(1000) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_write_obj)}, + { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_hw_can_read_obj)}, + //CAN_MODE + { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_CAN_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + //CAN_STATE + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + //CAN_BAUDRATE + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); @@ -57,7 +109,9 @@ STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_tab const mp_obj_type_t machine_can_type = { { &mp_type_type }, .name = MP_QSTR_CAN, - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members }; #endif // MICROPY_INCLUDED_ESP32_CAN_H From 883435af0bbb76d3fab521007db39acdef0b6245 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 19:15:39 +0200 Subject: [PATCH 089/180] added function to retrieve information of CAN STATUS --- ports/esp32/machine_can.c | 49 +++++++++++++++++++++++++++++---------- ports/esp32/machine_can.h | 20 ++++++++++++++++ 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 6077f4ac48a7b..69bdd25996184 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -26,7 +26,7 @@ #include "py/builtin.h" #include "py/mphal.h" #include "py/mperrno.h" -#include +#include "mpconfigport.h" //Headers of ESP-IDF library #include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h @@ -46,28 +46,53 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; - - - +STATIC can_status_info_t _machine_hw_can_get_status(){ + can_status_info_t status; + if(can_get_status_info(&status)!=ESP_OK){ + mp_raise_ValueError("Unable to get CAN status"); + } + return status; +} STATIC can_state_t _machine_hw_can_get_state(){ - can_status_info_t status; - ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK - return status.state; + can_status_info_t status = _machine_hw_can_get_status(); + return status.state; } STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in){ - can_status_info_t status; - ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK - return mp_obj_new_int(status.msgs_to_rx); + can_status_info_t status = _machine_hw_can_get_status(); + return mp_obj_new_int(status.msgs_to_rx); } STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ - can_status_info_t status; - ESP_ERROR_CHECK(can_get_status_info(&status)); //FIXME: remove ESP_ERROR_CHECK + can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.msgs_to_tx); } +//Return status information +STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in){ + can_status_info_t status = _machine_hw_can_get_status(); + return mp_obj_new_int(status.tx_error_counter); +} + +STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in){ + can_status_info_t status = _machine_hw_can_get_status(); + return mp_obj_new_int(status.rx_error_counter); +} + +STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in){ + return mp_obj_new_int(_machine_hw_can_get_state()); +} + +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ + return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); +} + +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ + return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); +} + + STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) { int value = mp_obj_get_int(address); if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index d2b2d101553db..70018c50acc0c 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -67,13 +67,26 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) ; +STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); + //Python function declarations MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_write_obj, machine_hw_can_write); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_read_obj, machine_hw_can_read); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tec_obj, machine_hw_can_get_tec); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rec_obj, machine_hw_can_get_rec); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tx_waiting_messages_obj, machine_hw_can_get_tx_waiting_messages); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rx_waiting_messages_obj, machine_hw_can_get_rx_waiting_messages); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_state_obj, machine_hw_can_get_state); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { @@ -84,6 +97,13 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_write_obj)}, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_hw_can_read_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_tec), MP_ROM_PTR(&machine_hw_can_get_tec_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_rec), MP_ROM_PTR(&machine_hw_can_get_rec_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_tx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_tx_waiting_messages_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_rx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_rx_waiting_messages_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_state), MP_ROM_PTR(&machine_hw_can_get_state_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, //CAN_MODE { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, From 5b42a782173da6ca2cda2f5fe42b3a80640a7425 Mon Sep 17 00:00:00 2001 From: Salvo Musumeci Date: Sun, 6 Oct 2019 21:09:49 +0200 Subject: [PATCH 090/180] Update quickref.rst Added quick commands for CAN usage --- docs/esp32/quickref.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 3153ebd57130f..1b8f9a81a5f71 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -403,6 +403,22 @@ users is encouraged. Based on this feedback, the I2S class API and implementati ESP32 has two I2S buses with id=0 and id=1 +CAN bus +------- + +The CAN driver is based on hardware implementation. +Any available output-capablepins can be used for SCL and SDA. +The driver is accessed via the :ref:`machine.CAN ` class:: + + from machine import CAN + + # construct a CAN bus + bus = CAN(tx=4, rx=2, baudrate=500, mode=CAN.MODE_NO_ACK) + + bus.send([0,1,2,3], 0x86, self_flag=True) #Send a self message + bus.recv() #Read the message sent + + Real time clock (RTC) --------------------- From 6449e7f05c3d5927e59104e177d1b63ccaa1a78f Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 21:02:59 +0200 Subject: [PATCH 091/180] Function SEND and RECV implemented --- ports/esp32/machine_can.c | 107 +++++++++++++++++++++++++++----------- ports/esp32/machine_can.h | 12 ++--- 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 69bdd25996184..c81a06373a03c 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -46,6 +46,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; +//Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; if(can_get_status_info(&status)!=ESP_OK){ @@ -69,7 +70,6 @@ STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ return mp_obj_new_int(status.msgs_to_tx); } -//Return status information STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.tx_error_counter); @@ -84,67 +84,113 @@ STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in){ return mp_obj_new_int(_machine_hw_can_get_state()); } +//Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); } - +//Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); } - -STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) { - int value = mp_obj_get_int(address); - if (value < 0 || value > 255) mp_raise_ValueError("Value out of range"); - +//send([data], id, timeout=0, rtr=False, self_flag=False) +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_self_flag, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // populate message + size_t length; + mp_obj_t *items; + mp_obj_get_array(args[ARG_data].u_obj,&length, &items); + if (length>8){ + mp_raise_ValueError("CAN data field too long"); + } + uint8_t flags = (args[ARG_rtr].u_bool==true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + if (args[ARG_id].u_int>0x7ff){ + flags += CAN_MSG_FLAG_EXTD; + } + if (args[ARG_self].u_bool){ + flags += CAN_MSG_FLAG_SELF; + } + + can_message_t tx_msg = {.data_length_code = length, + .identifier = args[ARG_id].u_int & 0x1FFFFFFF, + .flags = flags}; + for (uint8_t i=0; iitems; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + can_message_t rx_message; switch(can_receive(&rx_message, 1)){ + case ESP_OK: + items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + items[1] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); + items[2] = MP_OBJ_NEW_SMALL_INT(rx_message.flags); + return ret_obj; case ESP_ERR_TIMEOUT: - ESP_LOGW(DEVICE_NAME, "Time-out"); break; + mp_raise_ValueError("Timeout"); case ESP_ERR_INVALID_ARG: - ESP_LOGE(DEVICE_NAME, "Invalid Args"); break; + mp_raise_ValueError("Invalid Args"); case ESP_ERR_INVALID_STATE: - ESP_LOGW(DEVICE_NAME, "Invalid State"); break; - case ESP_OK: - return MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + mp_raise_ValueError("Invalid State"); + default: + mp_raise_ValueError(""); }; - return MP_OBJ_NEW_SMALL_INT(-1); - } STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->config->initialized){ + qstr mode; + switch(self->config->general->mode){ + case CAN_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; + case CAN_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; + case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; + default: mode = MP_QSTR_UNKNOWN; break; + } mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%u)", self->config->general->tx_io, self->config->general->rx_io, - self->config->baudrate, self->config->general->mode); + self->config->baudrate, mode); }else{ mp_printf(print, "CAN Device is not initialized"); } } - -/*void machine_can_trasmit(machine_hw_can_obj_t *self, uint32_t address, size_t length, mp_machine_can_buf_t *data) -{ - can_message_t tx_msg = {.data_length_code = length, .identifier = address, .flags = CAN_MSG_FLAG_SELF}; - for (uint8_t i=0; iconfig->initialized != true){ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 70018c50acc0c..b3beef0d5203d 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -65,8 +65,8 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); -STATIC mp_obj_t machine_hw_can_read(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_write(mp_obj_t self_in, mp_obj_t address) ; +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); @@ -76,10 +76,10 @@ STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); //Python function declarations -MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_write_obj, machine_hw_can_write); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_read_obj, machine_hw_can_read); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); +MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tec_obj, machine_hw_can_get_tec); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rec_obj, machine_hw_can_get_rec); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tx_waiting_messages_obj, machine_hw_can_get_tx_waiting_messages); @@ -95,8 +95,8 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { //CAN_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_write_obj)}, - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_hw_can_read_obj)}, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_get_tec), MP_ROM_PTR(&machine_hw_can_get_tec_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_get_rec), MP_ROM_PTR(&machine_hw_can_get_rec_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_get_tx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_tx_waiting_messages_obj)}, From ea189d0d6b6a56b19dc023a58e2ec89686c5ddd9 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 21:17:39 +0200 Subject: [PATCH 092/180] improve object print --- ports/esp32/machine_can.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index c81a06373a03c..22fc4de7c10a9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -183,8 +183,11 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; default: mode = MP_QSTR_UNKNOWN; break; } - mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%u)", self->config->general->tx_io, self->config->general->rx_io, - self->config->baudrate, mode); + mp_printf(print, + "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q)", + self->config->general->tx_io, + self->config->general->rx_io, + self->config->baudrate, mode); }else{ mp_printf(print, "CAN Device is not initialized"); } From 086ed59912a8f6f3609e9fce14f662d4d28f779c Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 6 Oct 2019 21:18:04 +0200 Subject: [PATCH 093/180] remove prefix CAN_ from constants --- ports/esp32/machine_can.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index b3beef0d5203d..46dea4202f3e3 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -105,14 +105,14 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, //CAN_MODE - { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_CAN_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_CAN_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, //CAN_STATE - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_CAN_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + { MP_ROM_QSTR(MP_QSTR_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, //CAN_BAUDRATE { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, From 37f445ab2eb64163dc5f4c54358952127f050846 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 8 Oct 2019 21:12:45 +0200 Subject: [PATCH 094/180] implementation of hardware filter --- ports/esp32/machine_can.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 22fc4de7c10a9..1631a3a975994 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -29,12 +29,12 @@ #include "mpconfigport.h" //Headers of ESP-IDF library -#include "soc/dport_reg.h" //FIXME: check if path is found. full path is ESPIDF/components/soc/esp32/include/soc/dport_reg.h +#include "soc/dport_reg.h" #include "driver/can.h" #include "esp_err.h" #include "esp_log.h" -#include "machine_can.h" +#include //#if MICROPY_HW_ENABLE_CAN @@ -231,16 +231,19 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue}; + enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { - { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, + { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, + { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -261,6 +264,12 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t .alerts_enabled = CAN_ALERT_NONE, .clkout_divider = 0}; self->config->general = &g_config; + can_filter_config_t f_config = { + .acceptance_code = args[ARG_filter_code].u_int, + .acceptance_mask = args[ARG_filter_mask].u_int, + .single_filter = args[ARG_single_filter].u_bool + }; + self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ case CAN_BAUDRATE_25k: From f1fa355280f0e98f562c51c9d8db65cf0cc3bb81 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 8 Oct 2019 21:13:33 +0200 Subject: [PATCH 095/180] update includePath --- .vscode/c_cpp_properties.json | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000000000..5f0824b540e6b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "name": "Mac", + "includePath": [ + "${workspaceFolder}/../esp-idf/components/**", + "${workspaceFolder}/ports/esp32/**", + "${workspaceFolder}/**" + ], + "defines": [], + "macFrameworkPath": [ + "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks" + ], + "compilerPath": "/usr/bin/clang", + "cStandard": "c11", + "cppStandard": "c++17", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file From c07e0ab702ca5acdc0507ffe83ceecbb7901cc20 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:33:15 +0100 Subject: [PATCH 096/180] Changed author --- ports/esp32/machine_can.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 46dea4202f3e3..fa67df93cca41 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014 Damien P. George + * Copyright (c) 2019 Musumeci Salvatore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 537ad1ce781200e267bf8232492f1c46754e5a4d Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:52:37 +0100 Subject: [PATCH 097/180] STM32 Harmonization: rename get_state() to state(), add info() and any() functions and remove functions now included in info() --- ports/esp32/machine_can.c | 57 ++++++++++++++++++++++++++++----------- ports/esp32/machine_can.h | 27 +++++++------------ 2 files changed, 50 insertions(+), 34 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 1631a3a975994..081e3b159fb4d 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -38,6 +38,9 @@ //#if MICROPY_HW_ENABLE_CAN +// Internal Functions +STATIC can_state_t _machine_hw_can_get_state(); + // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), @@ -55,33 +58,54 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } -STATIC can_state_t _machine_hw_can_get_state(){ - can_status_info_t status = _machine_hw_can_get_status(); - return status.state; } -STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in){ +// any(fifo) - return `True` if any message waiting on the FIFO, else `False` +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.msgs_to_rx); + if(mp_obj_new_int(status.msgs_to_rx)>0){ + return mp_const_true; + }else{ + return mp_const_false; + } } -STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in){ +// Get the state of the controller +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.msgs_to_tx); + return mp_obj_new_int(status.state); } -STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in){ +STATIC can_state_t _machine_hw_can_get_state(){ can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.tx_error_counter); + return status.state; } -STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in){ +// Get info about error states and TX/RX buffers +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { + //machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); //FIXME: Remove it if useless + mp_obj_list_t *list; + if (n_args == 1) { + list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); + } else { + if (!mp_obj_is_type(args[1], &mp_type_list)) { + mp_raise_TypeError(NULL); + } + list = MP_OBJ_TO_PTR(args[1]); + if (list->len < 8) { + mp_raise_ValueError(NULL); + } + } can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.rx_error_counter); -} - -STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in){ - return mp_obj_new_int(_machine_hw_can_get_state()); + list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); + list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); + //list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); //FIXME: + //list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); //FIXME: + //list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); //FIXME: + list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); + //list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); //FIXME: + //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: + return MP_OBJ_FROM_PTR(list); } //Clear TX Queue @@ -137,7 +161,8 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ case ESP_ERR_INVALID_STATE: ESP_LOGW(DEVICE_NAME, "Device is not initialized"); break; case ESP_ERR_NOT_SUPPORTED: ESP_LOGW(DEVICE_NAME, "Listen Only Mode active"); break; } - return machine_hw_can_get_tx_waiting_messages(pos_args[0]); + + return 0; //machine_hw_can_get_tx_waiting_messages(pos_args[0]); }else{ ESP_LOGW(DEVICE_NAME, "Unable to send the message"); return MP_OBJ_NEW_SMALL_INT(-1); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index fa67df93cca41..e65830d76a6ad 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -55,9 +55,6 @@ typedef struct _machine_can_obj_t { machine_can_config_t *config; } machine_can_obj_t; -//Internal functions -STATIC can_state_t _machine_hw_can_get_state(); - //Functions signature definition mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); @@ -66,27 +63,23 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_get_tec(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_rec(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_tx_waiting_messages(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_rx_waiting_messages(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_get_state(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); //Python function declarations MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tec_obj, machine_hw_can_get_tec); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rec_obj, machine_hw_can_get_rec); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_tx_waiting_messages_obj, machine_hw_can_get_tx_waiting_messages); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_rx_waiting_messages_obj, machine_hw_can_get_rx_waiting_messages); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_get_state_obj, machine_hw_can_get_state); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); +MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { @@ -95,13 +88,11 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { //CAN_FUNCTIONS { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_tec), MP_ROM_PTR(&machine_hw_can_get_tec_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_rec), MP_ROM_PTR(&machine_hw_can_get_rec_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_tx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_tx_waiting_messages_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_rx_waiting_messages), MP_ROM_PTR(&machine_hw_can_get_rx_waiting_messages_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_state), MP_ROM_PTR(&machine_hw_can_get_state_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, //CAN_MODE From 817dea53a777a61827b9509377e0c583457abe25 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:54:19 +0100 Subject: [PATCH 098/180] STM32 Harmonization: added restart() signature --- ports/esp32/machine_can.c | 4 ++++ ports/esp32/machine_can.h | 1 + 2 files changed, 5 insertions(+) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 081e3b159fb4d..a8df1cf6190bd 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -58,6 +58,10 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } +// Force a software restart of the controller, to allow transmission after a bus error +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ + mp_raise_NotImplementedError(""); //TODO: Implement this function + return self_in; } // any(fifo) - return `True` if any message waiting on the FIFO, else `False` diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index e65830d76a6ad..594c299da12bb 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -78,6 +78,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); +MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); From 617680d93c455ba09f791bc52a30f5a060ba4128 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:54:51 +0100 Subject: [PATCH 099/180] STM32 Harmonization: move private methods in c file --- ports/esp32/machine_can.c | 10 ++++++++++ ports/esp32/machine_can.h | 8 -------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index a8df1cf6190bd..57d86f412f13a 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -41,6 +41,16 @@ // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); + +//Python object definition +const mp_obj_type_t machine_can_type = { + { &mp_type_type }, + .name = MP_QSTR_CAN, + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members +}; + // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 594c299da12bb..3b8499acdfaf8 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -117,13 +117,5 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); -//Python object definition -const mp_obj_type_t machine_can_type = { - { &mp_type_type }, - .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members -}; #endif // MICROPY_INCLUDED_ESP32_CAN_H From 2b2fd9f26cdb54735574b782c835337f2aef219e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:55:30 +0100 Subject: [PATCH 100/180] Enabled compiler switch for module --- ports/esp32/machine_can.c | 4 ++-- ports/esp32/machine_can.h | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 57d86f412f13a..5f8bba2dab98e 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -36,7 +36,7 @@ #include -//#if MICROPY_HW_ENABLE_CAN +#if MICROPY_HW_ENABLE_CAN // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); @@ -372,4 +372,4 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ return mp_const_true; } -//#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file +#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3b8499acdfaf8..7c707c4fdb410 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -30,6 +30,8 @@ #include "py/obj.h" +#if MICROPY_HW_ENABLE_CAN + #define DEVICE_NAME "CAN" #define CAN_BAUDRATE_25k 25 @@ -118,4 +120,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); + +#endif // MICROPY_HW_ENABLE_CAN #endif // MICROPY_INCLUDED_ESP32_CAN_H From 3098d6590861d7171d663919c649346fa3fada8b Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 21:57:03 +0100 Subject: [PATCH 101/180] Code Cleaning: Reordered the function sequence --- ports/esp32/machine_can.h | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 7c707c4fdb410..eb818aa905b5a 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -60,15 +60,20 @@ typedef struct _machine_can_obj_t { //Functions signature definition mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +//Micropython Generic API +//FIXME: check init arguments and harmonize with pyBoard as well as the outputs +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + +//ESP32 specific API STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); @@ -84,29 +89,33 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); + //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { //CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, - //CAN_FUNCTIONS + //Micropython Generic API { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + //ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - //CAN_MODE - { MP_ROM_QSTR(MP_QSTR_MODE_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_MODE_NO_ACK), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_MODE_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + + //CAN_MODE + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, //CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STATE_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_STATE_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_STATE_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_STATE_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, //CAN_BAUDRATE { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, From caddb54176cbaa7a614bb054ced4c124d03b0aa4 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 10 Dec 2019 22:21:51 +0100 Subject: [PATCH 102/180] STM32 Harmonization: init() returns mp_const_none and raise exceptions instead Error Logs --- ports/esp32/machine_can.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5f8bba2dab98e..37b222e50c55d 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -265,19 +265,19 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ const machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized){ ESP_LOGW(DEVICE_NAME, "Device is already initialized"); - return mp_const_false; + return mp_const_none; } return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -// INTERNAL FUNCTION init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) +// INTERNAL FUNCTION init(mode, tx, rx, baudrate, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_tx, ARG_rx, ARG_baudrate, ARG_mode, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + enum { ARG_mode, ARG_tx, ARG_rx, ARG_baudrate, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, - { MP_QSTR_mode, MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, @@ -287,12 +287,13 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - //Check if device was already configured + // Check if device was already configured if (self->config->initialized){ - ESP_LOGE(DEVICE_NAME, "Device is already initialized: unable to re-init"); + //TODO: check if this condition is redundant compared to init() + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN device is already initialized")); return mp_const_none; } - //Configure device + // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int, .tx_io = args[ARG_tx].u_int, .rx_io = args[ARG_rx].u_int, @@ -336,7 +337,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); break; default: - ESP_LOGE(DEVICE_NAME, "Unable to set baudrate"); + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Unable to set baudrate")); self->config->baudrate = 0; return mp_const_none; } @@ -344,9 +345,9 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); if (status != ESP_OK){ - ESP_LOGE(DEVICE_NAME, "Unable to init the device. ErrCode: %u",status); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to init the device. ErrCode: %u",status)); }else if (can_start() != ESP_OK){ - ESP_LOGE(DEVICE_NAME, "Unable to start the device. ErrCode: %u",status); + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to start the device. ErrCode: %u",status)); }else{ self->config->initialized = true; } @@ -359,17 +360,17 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; if (self->config->initialized != true){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); - return mp_const_false; + return mp_const_none; } if(can_stop()!=ESP_OK){ - ESP_LOGW(DEVICE_NAME, "Unable to stop device"); + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); } if (can_driver_uninstall() != ESP_OK){ - ESP_LOGW(DEVICE_NAME, "Unable to uninstall device"); - return mp_const_false; + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); + return mp_const_none; } self->config->initialized = false; - return mp_const_true; + return mp_const_none; } #endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file From 1c80c6ef9158f674d62f05adeb5721eee33397fb Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 12 Dec 2019 22:48:40 +0100 Subject: [PATCH 103/180] STM32 Harmonization: Alignment of init function to pyCan. --- ports/esp32/machine_can.c | 82 +++++++++++++++++++++++++++------------ ports/esp32/machine_can.h | 13 +++++++ 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 37b222e50c55d..9ba8762452e53 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -20,8 +20,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#include #include "py/obj.h" +#include "py/objarray.h" +#include "py/binary.h" #include "py/runtime.h" #include "py/builtin.h" #include "py/mphal.h" @@ -38,6 +41,12 @@ #if MICROPY_HW_ENABLE_CAN +//Default baudrate: 500kb +#define CAN_DEFAULT_PRESCALER (8) +#define CAN_DEFAULT_SJW (3) +#define CAN_DEFAULT_BS1 (15) +#define CAN_DEFAULT_BS2 (4) + // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); @@ -57,7 +66,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA .timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()), .initialized = false}; -STATIC const machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; +STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; //Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ @@ -233,36 +242,41 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } -// CAN(...) No argument to get the object -// Any argument will be used to init the device through init function +// CAN(bus, ...) No argument to get the object +//If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){ - const machine_can_obj_t *self = &machine_can_obj; - - if (n_args > 0 || n_kw > 0) { + // check arguments + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + if (mp_obj_is_int(args[0])!=true){ + mp_raise_TypeError("bus must be a number"); + } + mp_uint_t can_idx = mp_obj_get_int(args[0]); + if (can_idx > 1) { //TODO: check naming convention + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); + } + machine_can_obj_t *self = &machine_can_obj; + if (n_args > 1 || n_kw > 0) { if (self->config->initialized) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); machine_hw_can_deinit(&self); } - //TODO: implement callback - /*self->rxcallback0 = mp_const_none; - self->rxcallback1 = mp_const_none; - self->rx_state0 = RX_STATE_FIFO_EMPTY; - self->rx_state1 = RX_STATE_FIFO_EMPTY;*/ + self->rxcallback = mp_const_none; + self->rx_state = RX_STATE_FIFO_EMPTY; // start the peripheral mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_hw_can_init_helper(self, n_args, args, &kw_args); + machine_hw_can_init_helper(self, n_args - 1, args + 1, &kw_args); } return MP_OBJ_FROM_PTR(self); } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - const machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized){ ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; @@ -270,20 +284,28 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -// INTERNAL FUNCTION init(mode, tx, rx, baudrate, tx_queue = 2, rx_queue = 5, filter_mask = 0xFFFFFFFF, filter_code = 0; single_filter = True) +// init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_tx, ARG_rx, ARG_baudrate, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, + ARG_auto_restart, ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, - { MP_QSTR_tx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_baudrate, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 500} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, + { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, + { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, + { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, + { MP_QSTR_auto_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, }; + //FIXME: auto_restart // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -295,8 +317,8 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t } // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int, - .tx_io = args[ARG_tx].u_int, - .rx_io = args[ARG_rx].u_int, + .tx_io = args[ARG_tx_io].u_int, + .rx_io = args[ARG_rx_io].u_int, .clkout_io = CAN_IO_UNUSED, .bus_off_io = CAN_IO_UNUSED, .tx_queue_len = args[ARG_tx_queue].u_int, @@ -312,6 +334,14 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ + case 0: + self->config->timing = &((can_timing_config_t){ + .brp = args[ARG_prescaler].u_int, + .sjw = args[ARG_sjw].u_int, + .tseg_1 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs1].u_int, + .triple_sampling = false}); + break; case CAN_BAUDRATE_25k: self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); break; @@ -345,13 +375,15 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); if (status != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to init the device. ErrCode: %u",status)); - }else if (can_start() != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_RuntimeError, "Unable to start the device. ErrCode: %u",status)); + mp_raise_OSError(-status); }else{ - self->config->initialized = true; + status = can_start() + if (status != ESP_OK){ + mp_raise_OSError(-status); + }else{ + self->config->initialized = true; + } } - return mp_const_none; } diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index eb818aa905b5a..e4275d79b24cd 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -55,8 +55,21 @@ typedef struct _machine_can_config_t { typedef struct _machine_can_obj_t { mp_obj_base_t base; machine_can_config_t *config; + mp_obj_t rxcallback; + byte rx_state; + bool extframe : 1; + uint16_t num_error_warning; //FIXME: populate this value somewhere + uint16_t num_error_passive; + uint16_t num_bus_off; } machine_can_obj_t; +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + //Functions signature definition mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); From cdcc19cfc14429b6e6493e1ebf441820201001fd Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 12 Dec 2019 22:50:24 +0100 Subject: [PATCH 104/180] STM32 Harmonization: Alignment of send(...) and recv(...) methods to pyBoard signature and return values --- ports/esp32/machine_can.c | 80 +++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 29 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 9ba8762452e53..5aae874708bc0 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -177,48 +177,70 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ tx_msg.data[i] = mp_obj_get_int(items[i]); } if (_machine_hw_can_get_state()==CAN_STATE_RUNNING){ - switch(can_transmit(&tx_msg, args[ARG_timeout].u_int)){ - case ESP_ERR_INVALID_ARG: ESP_LOGW(DEVICE_NAME, "Arguments are invalid"); break; - case ESP_ERR_TIMEOUT: //TX Queue is full - case ESP_FAIL: ESP_LOGW(DEVICE_NAME, "Message transmission failed"); break; - case ESP_ERR_INVALID_STATE: ESP_LOGW(DEVICE_NAME, "Device is not initialized"); break; - case ESP_ERR_NOT_SUPPORTED: ESP_LOGW(DEVICE_NAME, "Listen Only Mode active"); break; + int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); + if (status!=ESP_OK){ + mp_raise_OSError(-status); } - - return 0; //machine_hw_can_get_tx_waiting_messages(pos_args[0]); + return mp_const_none; }else{ - ESP_LOGW(DEVICE_NAME, "Unable to send the message"); - return MP_OBJ_NEW_SMALL_INT(-1); + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to send the message")); } } -// recv(timeout=5000) +// recv(list=None, *, timeout=5000) STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_timeout }; - mp_obj_t ret_obj = mp_obj_new_tuple(3, NULL); - mp_obj_t *items = ((mp_obj_tuple_t*)MP_OBJ_TO_PTR(ret_obj))->items; + enum { ARG_fifo, ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { + { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; + + // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); can_message_t rx_message; - switch(can_receive(&rx_message, 1)){ - case ESP_OK: - items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - items[2] = MP_OBJ_NEW_SMALL_INT(rx_message.flags); - return ret_obj; - case ESP_ERR_TIMEOUT: - mp_raise_ValueError("Timeout"); - case ESP_ERR_INVALID_ARG: - mp_raise_ValueError("Invalid Args"); - case ESP_ERR_INVALID_STATE: - mp_raise_ValueError("Invalid State"); - default: - mp_raise_ValueError(""); - }; + int status = can_receive(&rx_message, 1); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + //TODO: manage callback + // Create the tuple, or get the list, that will hold the return values + // Also populate the fourth element, either a new bytes or reuse existing memoryview + mp_obj_t ret_obj = args[ARG_list].u_obj; + mp_obj_t *items; + if (ret_obj == mp_const_none){ + ret_obj = mp_obj_new_tuple(4, NULL); + items = ((mp_obj_tuple_t*)MP_OBJ_TO_PTR(ret_obj))->items; + items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); + } else { + // User should provide a list of length at least 4 to hold the values + if (!mp_obj_is_type(ret_obj, &mp_type_list)) { + mp_raise_TypeError(NULL); + } + mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); + if (list->len < 4) { + mp_raise_ValueError(NULL); + } + items = list->items; + // Fourth element must be a memoryview which we assume points to a + // byte-like array which is large enough, and then we resize it inplace + if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { + mp_raise_TypeError(NULL); + } + mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) + || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { + mp_raise_ValueError(NULL); + } + mv->len = rx_message.data_length_code; + memcpy(mv->items, rx_message.data, rx_message.data_length_code); + + } + items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); + items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; + items[2] = 0; //TODO: check if Filter Mailbox Index is available for ESP32 + return ret_obj; } STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { From b0c68a73b8dc8c2977dc85e693afb0a0aebb320f Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 12 Dec 2019 22:58:51 +0100 Subject: [PATCH 105/180] removed auto_restart option since the esp32 framework doesn't have this feature. It could be implemented in the feature if needed --- ports/esp32/machine_can.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5aae874708bc0..d684a8bce34a4 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -309,7 +309,7 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ // init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, - ARG_auto_restart, ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, @@ -318,7 +318,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_auto_restart, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, @@ -327,7 +326,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, }; - //FIXME: auto_restart // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -399,7 +397,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t if (status != ESP_OK){ mp_raise_OSError(-status); }else{ - status = can_start() + status = can_start(); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ From dcb65b6c2f34c693e522bac70ac026064fbe6a6e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 08:03:30 +0100 Subject: [PATCH 106/180] Added signature for RX Callback; currently this method is not implemented --- ports/esp32/machine_can.c | 18 ++++++++++++++++++ ports/esp32/machine_can.h | 4 +++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index d684a8bce34a4..2eecd32048b7f 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -407,6 +407,24 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t return mp_const_none; } +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + mp_raise_NotImplementedError("IRQ not supported yet"); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (callback_in == mp_const_none) { + self->rxcallback = mp_const_none; + } else if (self->rxcallback != mp_const_none) { + // Rx call backs has already been initialized + // only the callback function should be changed + self->rxcallback = callback_in; + // TODO: disable interrupt + } else if (mp_obj_is_callable(callback_in)) { + self->rxcallback = callback_in; + // TODO: set interrupt + } + return mp_const_none; +} + //deinit() STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index e4275d79b24cd..3e05e204f16a6 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -85,6 +85,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in); //ESP32 specific API STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); @@ -101,7 +102,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clea MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); - +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); //Python objects list declaration STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { @@ -116,6 +117,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, //ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, From 5e8a6c6cca8f168bf20327f334b413bf00dbe635 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 08:32:00 +0100 Subject: [PATCH 107/180] Python Interface has been moved from header to source --- ports/esp32/machine_can.c | 167 ++++++++++++++++++++++++++------------ ports/esp32/machine_can.h | 76 +---------------- 2 files changed, 116 insertions(+), 127 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 2eecd32048b7f..81c957844294c 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -49,16 +49,12 @@ // Internal Functions STATIC can_state_t _machine_hw_can_get_state(); +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); + -//Python object definition -const mp_obj_type_t machine_can_type = { - { &mp_type_type }, - .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members -}; // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), @@ -82,6 +78,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ mp_raise_NotImplementedError(""); //TODO: Implement this function return self_in; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any(fifo) - return `True` if any message waiting on the FIFO, else `False` STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ @@ -92,6 +89,7 @@ STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ return mp_const_false; } } +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { @@ -103,6 +101,7 @@ STATIC can_state_t _machine_hw_can_get_state(){ can_status_info_t status = _machine_hw_can_get_status(); return status.state; } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { @@ -130,15 +129,20 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: return MP_OBJ_FROM_PTR(list); } +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); //Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); + //Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); + //send([data], id, timeout=0, rtr=False, self_flag=False) STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -186,6 +190,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to send the message")); } } +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); // recv(list=None, *, timeout=5000) STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -242,6 +247,27 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ items[2] = 0; //TODO: check if Filter Mailbox Index is available for ESP32 return ret_obj; } +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); + +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + mp_raise_NotImplementedError("IRQ not supported yet"); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (callback_in == mp_const_none) { + self->rxcallback = mp_const_none; + } else if (self->rxcallback != mp_const_none) { + // Rx call backs has already been initialized + // only the callback function should be changed + self->rxcallback = callback_in; + // TODO: disable interrupt + } else if (mp_obj_is_callable(callback_in)) { + self->rxcallback = callback_in; + // TODO: set interrupt + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); + STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -264,6 +290,37 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } + +// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized){ + ESP_LOGW(DEVICE_NAME, "Device is already initialized"); + return mp_const_none; + } + return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); + +//deinit() +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ + const machine_can_obj_t *self = &machine_can_obj; + if (self->config->initialized != true){ + ESP_LOGW(DEVICE_NAME, "Device is not initialized"); + return mp_const_none; + } + if(can_stop()!=ESP_OK){ + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); + } + if (can_driver_uninstall() != ESP_OK){ + nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); + return mp_const_none; + } + self->config->initialized = false; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); + // CAN(bus, ...) No argument to get the object //If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, @@ -296,16 +353,6 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized){ - ESP_LOGW(DEVICE_NAME, "Device is already initialized"); - return mp_const_none; - } - return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); -} - // init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, @@ -407,40 +454,56 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t return mp_const_none; } -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { - mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (callback_in == mp_const_none) { - self->rxcallback = mp_const_none; - } else if (self->rxcallback != mp_const_none) { - // Rx call backs has already been initialized - // only the callback function should be changed - self->rxcallback = callback_in; - // TODO: disable interrupt - } else if (mp_obj_is_callable(callback_in)) { - self->rxcallback = callback_in; - // TODO: set interrupt - } - return mp_const_none; -} -//deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ - const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true){ - ESP_LOGW(DEVICE_NAME, "Device is not initialized"); - return mp_const_none; - } - if(can_stop()!=ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); - } - if (can_driver_uninstall() != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); - return mp_const_none; - } - self->config->initialized = false; - return mp_const_none; -} +STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { + //CAN_ATTRIBUTES + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, + //Micropython Generic API + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + /* + { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, + */ + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, + //ESP32 Specific API + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + + //CAN_MODE + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + //CAN_STATE + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + //CAN_BAUDRATE + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); +//Python object definition +const mp_obj_type_t machine_can_type = { + { &mp_type_type }, + .name = MP_QSTR_CAN, + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members +}; #endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3e05e204f16a6..f1d0a22633a10 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,7 +43,6 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 - typedef struct _machine_can_config_t { const can_timing_config_t *timing; const can_filter_config_t *filter; @@ -70,80 +69,7 @@ typedef enum _rx_state_t { RX_STATE_FIFO_OVERFLOW, } rx_state_t; -//Functions signature definition -mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); - -//Micropython Generic API -//FIXME: check init arguments and harmonize with pyBoard as well as the outputs -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in); -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in); - -//ESP32 specific API -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in); -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in); - -//Python function declarations -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); -MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); -MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); -MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); - -//Python objects list declaration -STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { - //CAN_ATTRIBUTES - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, - //Micropython Generic API - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, - { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, - { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, - //ESP32 Specific API - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - - //CAN_MODE - { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, - //CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, - //CAN_BAUDRATE - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); - - +extern const mp_obj_type_t machine_can_type; #endif // MICROPY_HW_ENABLE_CAN #endif // MICROPY_INCLUDED_ESP32_CAN_H From d47fec44d8afca7b9fd163940a67ace435efea74 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 08:34:26 +0100 Subject: [PATCH 108/180] Removed redundant function --- ports/esp32/machine_can.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 81c957844294c..da72ded6caeb3 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -48,7 +48,6 @@ #define CAN_DEFAULT_BS2 (4) // Internal Functions -STATIC can_state_t _machine_hw_can_get_state(); mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); @@ -64,7 +63,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; -//Return status information +//INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; if(can_get_status_info(&status)!=ESP_OK){ @@ -96,11 +95,6 @@ STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } - -STATIC can_state_t _machine_hw_can_get_state(){ - can_status_info_t status = _machine_hw_can_get_status(); - return status.state; -} STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers @@ -180,7 +174,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ for (uint8_t i=0; i Date: Fri, 13 Dec 2019 08:37:00 +0100 Subject: [PATCH 109/180] beautify --- ports/esp32/machine_can.c | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index da72ded6caeb3..43b045fa869d8 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -31,7 +31,7 @@ #include "py/mperrno.h" #include "mpconfigport.h" -//Headers of ESP-IDF library +// Headers of ESP-IDF library #include "soc/dport_reg.h" #include "driver/can.h" #include "esp_err.h" @@ -41,20 +41,18 @@ #if MICROPY_HW_ENABLE_CAN -//Default baudrate: 500kb +// Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) #define CAN_DEFAULT_BS1 (15) #define CAN_DEFAULT_BS2 (4) + // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); - - - // singleton CAN device object machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), @@ -63,7 +61,7 @@ machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERA STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; -//INTERNAL FUNCTION Return status information +// INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; if(can_get_status_info(&status)!=ESP_OK){ @@ -125,20 +123,20 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); -//Clear TX Queue +// Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); -//Clear RX Queue +// Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); -//send([data], id, timeout=0, rtr=False, self_flag=False) +// send([data], id, timeout=0, rtr=False, self_flag=False) STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; static const mp_arg_t allowed_args[] = { @@ -296,7 +294,7 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); -//deinit() +// deinit() STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; if (self->config->initialized != true){ @@ -316,7 +314,7 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); // CAN(bus, ...) No argument to get the object -//If no arguments are provided, the initialized object will be returned +// If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args){ // check arguments @@ -450,9 +448,9 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { - //CAN_ATTRIBUTES + // CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, - //Micropython Generic API + // Micropython Generic API { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, @@ -467,20 +465,20 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, */ { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, - //ESP32 Specific API + // ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - //CAN_MODE + // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, - //CAN_STATE + // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, - //CAN_BAUDRATE + // CAN_BAUDRATE { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, @@ -492,7 +490,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); -//Python object definition +// Python object definition const mp_obj_type_t machine_can_type = { { &mp_type_type }, .name = MP_QSTR_CAN, From 39c1dae53e6e6f0f8a92cb3e4192356d6f0b673e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 13 Dec 2019 09:52:03 +0100 Subject: [PATCH 110/180] STM32 Harmonization: implemented same CAN_MODE --- ports/esp32/machine_can.c | 21 +++++++++++++-------- ports/esp32/machine_can.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 43b045fa869d8..ffebfc44fc469 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -136,7 +136,7 @@ STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); -// send([data], id, timeout=0, rtr=False, self_flag=False) +// send([data], id, *) STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; static const mp_arg_t allowed_args[] = { @@ -144,10 +144,10 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_self_flag, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; // parse args + machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); @@ -159,15 +159,17 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ mp_raise_ValueError("CAN data field too long"); } uint8_t flags = (args[ARG_rtr].u_bool==true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); - if (args[ARG_id].u_int>0x7ff){ + uint32_t id = args[ARG_id].u_int; + if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; + id &= 0x1FFFFFFF; } - if (args[ARG_self].u_bool){ + if (self->loopback){ flags += CAN_MSG_FLAG_SELF; + id &= 0x1FF; } - can_message_t tx_msg = {.data_length_code = length, - .identifier = args[ARG_id].u_int & 0x1FFFFFFF, + .identifier = id, .flags = flags}; for (uint8_t i=0; iconfig->general = &g_config; + self->loopback = (args[ARG_mode] && 0x10 > 0) can_filter_config_t f_config = { .acceptance_code = args[ARG_filter_code].u_int, .acceptance_mask = args[ARG_filter_mask].u_int, @@ -471,7 +474,9 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index f1d0a22633a10..3e91588682ab0 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -57,6 +57,7 @@ typedef struct _machine_can_obj_t { mp_obj_t rxcallback; byte rx_state; bool extframe : 1; + bool loopback : 1; uint16_t num_error_warning; //FIXME: populate this value somewhere uint16_t num_error_passive; uint16_t num_bus_off; From 08590f97f4390c80ece6add00a0331b2c1553c2f Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:06:55 +0100 Subject: [PATCH 111/180] minor fix --- ports/esp32/machine_can.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index ffebfc44fc469..8eb936508b42e 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -64,8 +64,9 @@ STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_co // INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; - if(can_get_status_info(&status)!=ESP_OK){ - mp_raise_ValueError("Unable to get CAN status"); + uint8_t err_code = can_get_status_info(&status); + if(err_code!=ESP_OK){ + mp_raise_OSError(-err_code); } return status; } @@ -97,7 +98,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { - //machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); //FIXME: Remove it if useless mp_obj_list_t *list; if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); @@ -113,9 +113,9 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { can_status_info_t status = _machine_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); - //list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); //FIXME: - //list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); //FIXME: - //list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); //FIXME: + list->items[2] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_warning + list->items[3] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_passive + list->items[4] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_bus_off list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); //list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); //FIXME: //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: @@ -303,12 +303,13 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } - if(can_stop()!=ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to stop the device")); + uint8_t status = can_stop(); + if(status!=ESP_OK){ + mp_raise_OSError(-status); } - if (can_driver_uninstall() != ESP_OK){ - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "Unable to uninstall the device")); - return mp_const_none; + status = can_driver_uninstall(); + if (status != ESP_OK){ + mp_raise_OSError(-status); } self->config->initialized = false; return mp_const_none; @@ -429,7 +430,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Unable to set baudrate")); + mp_raise_ValueError("Unable to set baudrate"); self->config->baudrate = 0; return mp_const_none; } From 07e172df26d4f7b2a01b579a494f31bcf4a1eca6 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:51:47 +0100 Subject: [PATCH 112/180] manage flags for loopback and extframe --- ports/esp32/machine_can.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 8eb936508b42e..6f9464a99caec 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -50,7 +50,7 @@ // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object @@ -349,7 +349,7 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; static const mp_arg_t allowed_args[] = { @@ -388,7 +388,8 @@ STATIC mp_obj_t machine_hw_can_init_helper(const machine_can_obj_t *self, size_t .alerts_enabled = CAN_ALERT_NONE, .clkout_divider = 0}; self->config->general = &g_config; - self->loopback = (args[ARG_mode] && 0x10 > 0) + self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); + self->extframe = args[ARG_extframe].u_bool; can_filter_config_t f_config = { .acceptance_code = args[ARG_filter_code].u_int, .acceptance_mask = args[ARG_filter_mask].u_int, From 84f41477902e81e6cde3ab3e7bba6d89b1eb8f84 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:52:45 +0100 Subject: [PATCH 113/180] removed unused input variable from any() --- ports/esp32/machine_can.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 6f9464a99caec..255ed7064b380 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -78,16 +78,12 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); -// any(fifo) - return `True` if any message waiting on the FIFO, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in, mp_obj_t fifo_in){ +// any() - return `True` if any message waiting, else `False` +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); - if(mp_obj_new_int(status.msgs_to_rx)>0){ - return mp_const_true; - }else{ - return mp_const_false; - } + return mp_obj_new_bool((status.msgs_to_rx)>0); } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_any_obj, machine_hw_can_any); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { From cf7d3497e250a6cff9da147bcb600de5a099a811 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:53:02 +0100 Subject: [PATCH 114/180] bugfix --- ports/esp32/machine_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 255ed7064b380..4f108d589e594 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -184,7 +184,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_sen // recv(list=None, *, timeout=5000) STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_fifo, ARG_list, ARG_timeout }; + enum { ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, From 5bfdd02a807dbb840cdd20a846b8125b4507a7c0 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 17 Dec 2019 23:53:15 +0100 Subject: [PATCH 115/180] Improved print function --- ports/esp32/machine_can.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 4f108d589e594..69de73a279338 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -270,10 +270,13 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p default: mode = MP_QSTR_UNKNOWN; break; } mp_printf(print, - "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q)", + "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", self->config->general->tx_io, self->config->general->rx_io, - self->config->baudrate, mode); + self->config->baudrate, + mode, + self->loopback, + self->extframe); }else{ mp_printf(print, "CAN Device is not initialized"); } From cbcb18f468162ad350bc09c8a948493f69fe4c6e Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Wed, 18 Dec 2019 23:35:00 +0100 Subject: [PATCH 116/180] Implementation of restart function --- ports/esp32/machine_can.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 69de73a279338..493ef0d8656f9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -73,8 +73,16 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ - mp_raise_NotImplementedError(""); //TODO: Implement this function - return self_in; + uint32_t status = can_initiate_recovery(); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution + status = can_start(); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); From dde3edfba212ef0a923f8b0f5aebcdf17a6d4e80 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Wed, 18 Dec 2019 23:35:39 +0100 Subject: [PATCH 117/180] data type bugfix --- ports/esp32/machine_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 493ef0d8656f9..f8dd96e5a731e 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -310,7 +310,7 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } - uint8_t status = can_stop(); + uint32_t status = can_stop(); if(status!=ESP_OK){ mp_raise_OSError(-status); } @@ -444,7 +444,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg } self->config->baudrate = args[ARG_baudrate].u_int; - uint8_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); + uint32_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ From 314c1134fed97a59af94345c59caf74199c5a5ed Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 22:20:52 +0100 Subject: [PATCH 118/180] Added alert function --- ports/esp32/machine_can.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f8dd96e5a731e..5a7473c8195cc 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -127,6 +127,16 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ + uint32_t alerts; + uint32_t status = can_read_alerts(&alerts, 0); + if (status != ESP_OK){ + mp_raise_OSError(-status); + } + return mp_obj_new_int(alerts); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); + // Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); @@ -392,7 +402,8 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .bus_off_io = CAN_IO_UNUSED, .tx_queue_len = args[ARG_tx_queue].u_int, .rx_queue_len = args[ARG_rx_queue].u_int, - .alerts_enabled = CAN_ALERT_NONE, + .alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || + CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF, .clkout_divider = 0}; self->config->general = &g_config; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); @@ -481,6 +492,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, @@ -501,6 +513,20 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, + // CAN_ALERT + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); From 3a540c7e4ca230c157d3b8c9ab0d5a02c5dd489c Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:01:04 +0100 Subject: [PATCH 119/180] Added docs for ESP32 CAN --- docs/library/esp32.CAN.rst | 326 +++++++++++++++++++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 docs/library/esp32.CAN.rst diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst new file mode 100644 index 0000000000000..e17e9f4a5598f --- /dev/null +++ b/docs/library/esp32.CAN.rst @@ -0,0 +1,326 @@ +.. currentmodule:: esp32 +.. _esp32.CAN: + +class CAN -- controller area network communication bus +====================================================== + +CAN implements the standard CAN communications protocol. At +the physical level it consists of 2 lines: RX and TX. Note that +to connect the ESP32 to a CAN bus you must use a CAN transceiver +to convert the CAN logic signals from the ESP32 to the correct +voltage levels on the bus. + +Example usage (works without anything connected):: + + from machine import CAN + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) + can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 + can.send([1,2,3], 123) # send a message with id 123 + can.recv() # receive message + + +Constructors +------------ + +.. class:: machine.CAN(bus, ...) + + Construct a CAN object on the given bus. *bus* can be 0 or 1 (for compatibility with STM32). It will point at the same device + With no additional parameters, the CAN object is created but not + initialised (it has the settings from the last initialisation of + the bus, if any). If extra arguments are given, the bus is initialised. + See :meth:`CAN.init` for parameters of initialisation. + + The physical pins of the CAN bus can be assigned during init. + +Class Methods +------------- +.. classmethod:: CAN.initfilterbanks(nr) TODO: + + Reset and disable all filter banks and assign how many banks should be available for CAN(1). + + STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. + This function configures how many filter banks should be assigned to each. *nr* is the number of banks + that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). + At boot, 14 banks are assigned to each controller. + +Methods +------- + +.. method:: CAN.init(mode, extframe=False, baudrate, prescaler, \*, sjw=1, bs1=6, bs2=8, auto_restart=False) + + Initialise the CAN bus with the given parameters: + + - *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK + - if *extframe* is True then the bus uses extended identifiers in the frames + (29 bits); otherwise it uses standard 11 bit identifiers + - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* + will be ignored. Standard speeds are available as CAN.BAUDRATE_* + - *prescaler* is used to set the duration of 1 time quanta; the time quanta + will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler + - *sjw* is the resynchronisation jump width in units of the time quanta; + it can be 1, 2, 3, 4 + - *bs1* defines the location of the sample point in units of the time quanta; + it can be between 1 and 1024 inclusive + - *bs2* defines the location of the transmit point in units of the time quanta; + it can be between 1 and 16 inclusive + - *tx_io* defines the gpio used for transmission + - *rx_io* defines the gpio used for receiving + - *tx_queue* defines the number of waiting tx messages can be stored + - *rx_queue* defines the number of received messages can be stored + - *auto_restart* sets whether the controller will automatically try and restart + communications after entering the bus-off state; if this is disabled then + :meth:`~CAN.restart()` can be used to leave the bus-off state. + This parameter is currently not implemented and it must be set to False + + +.. method:: CAN.deinit() + + Turn off the CAN bus. + +.. method:: CAN.restart() + + Force a software restart of the CAN controller without resetting its + configuration. + + If the controller enters the bus-off state then it will no longer participate + in bus activity. If the controller is not configured to automatically restart + (see :meth:`~CAN.init()`) then this method can be used to trigger a restart, + and the controller will follow the CAN protocol to leave the bus-off state and + go into the error active state. + +.. method:: CAN.state() + + Return the state of the controller. The return value can be one of: + + - ``CAN.STOPPED`` -- the controller is completely off and reset; + - ``CAN.ERROR_ACTIVE`` -- the controller is on and in the Error Active state + (both TEC and REC are less than 96); + - ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity + (TEC overflowed beyond 255). + - ``CAN.RECOVERING`` -- the controller is under recover from bus-off state; + + +.. method:: CAN.info([list]) + + Get information about the controller's error states and TX and RX buffers. + If *list* is provided then it should be a list object with at least 8 entries, + which will be filled in with the information. Otherwise a new list will be + created and filled in. In both cases the return value of the method is the + populated list. + + The values in the list are: + + - TEC value + - REC value + - number of times the controller enterted the Error Warning state (wrapped + around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED + - number of times the controller enterted the Error Passive state (wrapped + around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED + - number of times the controller enterted the Bus Off state (wrapped + around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED + - number of pending TX messages + - number of pending RX messages + - Reserved + +.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) TODO: + + Configure a filter bank: + + - *bank* is the filter bank that is to be configured. + - *mode* is the mode the filter should operate in. + - *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. + - *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument. + + +-----------+---------------------------------------------------------+ + |*mode* |contents of *params* array | + +===========+=========================================================+ + |CAN.LIST16 |Four 16 bit ids that will be accepted | + +-----------+---------------------------------------------------------+ + |CAN.LIST32 |Two 32 bit ids that will be accepted | + +-----------+---------------------------------------------------------+ + |CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | + | | | The first pair, 1 and 3 will accept all ids | + | | | that have bit 0 = 1 and bit 1 = 0. | + | | | The second pair, 4 and 4, will accept all ids | + | | | that have bit 2 = 1. | + +-----------+---------------------------------------------------------+ + |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| + +-----------+---------------------------------------------------------+ + + - *rtr* is an array of booleans that states if a filter should accept a + remote transmission request message. If this argument is not given + then it defaults to ``False`` for all entries. The length of the array + depends on the *mode* argument. + + +-----------+----------------------+ + |*mode* |length of *rtr* array | + +===========+======================+ + |CAN.LIST16 |4 | + +-----------+----------------------+ + |CAN.LIST32 |2 | + +-----------+----------------------+ + |CAN.MASK16 |2 | + +-----------+----------------------+ + |CAN.MASK32 |1 | + +-----------+----------------------+ + +.. method:: CAN.clearfilter(bank) TODO: + + Clear and disables a filter bank: + + - *bank* is the filter bank that is to be cleared. + +.. method:: CAN.any(fifo) + + Return ``True`` if any message waiting on the FIFO, else ``False``. + +.. method:: CAN.recv(list=None, \*, timeout=5000) + + Receive data on the bus: + + - *list* is an optional list object to be used as the return value + - *timeout* is the timeout in milliseconds to wait for the receive. + + Return value: A tuple containing four values. + + - The id of the message. + - A boolean that indicates if the message is an RTR message. + - Reserved. + - An array containing the data. + + If *list* is ``None`` then a new tuple will be allocated, as well as a new + bytes object to contain the data (as the fourth element in the tuple). + + If *list* is not ``None`` then it should be a list object with a least four + elements. The fourth element should be a memoryview object which is created + from either a bytearray or an array of type 'B' or 'b', and this array must + have enough room for at least 8 bytes. The list object will then be + populated with the first three return values above, and the memoryview object + will be resized inplace to the size of the data and filled in with that data. + The same list and memoryview objects can be reused in subsequent calls to + this method, providing a way of receiving data without using the heap. + For example:: + + buf = bytearray(8) + lst = [0, 0, 0, memoryview(buf)] + # No heap memory is allocated in the following call + can.recv(0, lst) + +.. method:: CAN.send(data, id, \*, timeout=0, rtr=False) + + Send a message on the bus: + + - *data* is the data to send (an integer to send, or a buffer object). + - *id* is the id of the message to be sent. + - *timeout* is the timeout in milliseconds to wait for the send. + - *rtr* is a boolean that specifies if the message shall be sent as + a remote transmission request. If *rtr* is True then only the length + of *data* is used to fill in the DLC slot of the frame; the actual + bytes in *data* are unused. + + If timeout is 0 the message is placed in a buffer and the method returns + immediately. If all three buffers are in use an exception is thrown. + If timeout is not 0, the method waits until the message is transmitted. + If the message can't be transmitted within the specified time an exception + is thrown. + + Return value: ``None``. + +.. method:: CAN.clear_tx_queue() + + Clear all messages from transmitting queue. + +.. method:: CAN.clear_rx_queue() + + Clear all messages from receiving queue. + +.. method:: CAN.get_alerts() + + Read the alert status word directly from hardware. + + +.. method:: CAN.rxcallback(fifo, fun) TODO: NOT YET IMPLEMENTED + + Register a function to be called when a message is accepted into a empty fifo: + + - *fifo* is the receiving fifo. + - *fun* is the function to be called when the fifo becomes non empty. + + The callback function takes two arguments the first is the can object it self the second is + a integer that indicates the reason for the callback. + + +--------+------------------------------------------------+ + | Reason | | + +========+================================================+ + | 0 | A message has been accepted into a empty FIFO. | + +--------+------------------------------------------------+ + | 1 | The FIFO is full | + +--------+------------------------------------------------+ + | 2 | A message has been lost due to a full FIFO | + +--------+------------------------------------------------+ + + Example use of rxcallback:: + + def cb0(bus, reason): + print('cb0') + if reason == 0: + print('pending') + if reason == 1: + print('full') + if reason == 2: + print('overflow') + + can = CAN(1, CAN.LOOPBACK) + can.rxcallback(0, cb0) + +Constants +--------- + +.. data:: CAN.NORMAL + CAN.LOOPBACK + CAN.SILENT + CAN.SILENT_LOOPBACK + CAN.LISTEN_ONLY + + The mode of the CAN bus used in :meth:`~CAN.init()`. + +.. data:: CAN.BAUDRATE_25k + CAN.BAUDRATE_50k + CAN.BAUDRATE_100k + CAN.BAUDRATE_125k + CAN.BAUDRATE_250k + CAN.BAUDRATE_500k + CAN.BAUDRATE_800k + CAN.BAUDRATE_1M + + The baudrate of the CAN bus used in :meth:`~CAN.init()`. + +.. data:: CAN.STOPPED + CAN.ERROR_ACTIVE + CAN.BUS_OFF + CAN.RECOVERING + + Possible states of the CAN controller returned from :meth:`~CAN.state()`. + +.. data:: CAN.LIST16 TODO: + CAN.MASK16 + CAN.LIST32 + CAN.MASK32 + + The operation mode of a filter used in :meth:`~CAN.setfilter()`. + +.. data:: CAN.ALERT_TX_IDLE + CAN.ALERT_TX_SUCCESS + CAN.ALERT_BELOW_ERR_WARN + CAN.ALERT_ERR_ACTIVE + CAN.ALERT_RECOVERY_IN_PROGRESS + CAN.ALERT_BUS_RECOVERED + CAN.ALERT_ARB_LOST + CAN.ALERT_ABOVE_ERR_WARN + CAN.ALERT_BUS_ERROR + CAN.ALERT_TX_FAILED + CAN.ALERT_RX_QUEUE_FULL + CAN.ALERT_ERR_PASS + CAN.ALERT_BUS_OFF + + Possibile bit position of alert mask returned by :meth:`~CAN.get_alerts()`. From f27aa393c0b235871ee7b292ea2eaa6bd00313b9 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:03:24 +0100 Subject: [PATCH 120/180] Removed filter setup from init. --- ports/esp32/machine_can.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5a7473c8195cc..d8233b7f31ced 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -368,7 +368,7 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, // init(mode, extframe=False, baudrate=500, *) STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, - ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_filter_mask, ARG_filter_code, ARG_single_filter}; + ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_auto_restart}; static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, @@ -381,9 +381,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_filter_mask, MP_ARG_INT, {.u_int = 0xFFFFFFFF} }, - { MP_QSTR_filter_code, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_single_filter, MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = true} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -408,11 +406,10 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general = &g_config; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - can_filter_config_t f_config = { - .acceptance_code = args[ARG_filter_code].u_int, - .acceptance_mask = args[ARG_filter_mask].u_int, - .single_filter = args[ARG_single_filter].u_bool - }; + if (args[ARG_auto_restart].u_bool){ + mp_raise_NotImplementedError("Auto-restart not supported"); + } + can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ From 2aa01853eecf0ec0bce2453cff05e1d4ee74fc21 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:08:09 +0100 Subject: [PATCH 121/180] STM32 Harmonization --- ports/esp32/machine_can.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index d8233b7f31ced..c8118de30b408 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -121,8 +121,8 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[3] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_passive list->items[4] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_bus_off list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); - //list->items[6] = MP_OBJ_NEW_SMALL_INT(can->RF0R >> CAN_RF0R_FMP0_Pos & 3); //FIXME: - //list->items[7] = MP_OBJ_NEW_SMALL_INT(can->RF1R >> CAN_RF1R_FMP1_Pos & 3); //FIXME: + list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); + list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); @@ -252,7 +252,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; - items[2] = 0; //TODO: check if Filter Mailbox Index is available for ESP32 + items[2] = 0; return ret_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); @@ -489,7 +489,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, @@ -498,7 +498,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_RUNNING), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, // CAN_BAUDRATE From c6997c0127470938fffe17cf5ba8969834a2b27f Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 19 Dec 2019 23:25:18 +0100 Subject: [PATCH 122/180] Integrated you docs with existing one --- docs/esp32/quickref.rst | 10 +++++---- docs/library/esp32.rst | 50 +++++------------------------------------ 2 files changed, 11 insertions(+), 49 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index 1b8f9a81a5f71..a394097708f81 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -406,6 +406,8 @@ ESP32 has two I2S buses with id=0 and id=1 CAN bus ------- +See :ref:`esp32.CAN ` :: + The CAN driver is based on hardware implementation. Any available output-capablepins can be used for SCL and SDA. The driver is accessed via the :ref:`machine.CAN ` class:: @@ -413,10 +415,10 @@ The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN # construct a CAN bus - bus = CAN(tx=4, rx=2, baudrate=500, mode=CAN.MODE_NO_ACK) - - bus.send([0,1,2,3], 0x86, self_flag=True) #Send a self message - bus.recv() #Read the message sent + bus = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) + + bus.send([0,1,2,3], 0x86) #Send the message + bus.recv() #Read the message sent Real time clock (RTC) diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index e3c25d2653db1..b905a916b68f5 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -279,50 +279,10 @@ Constants Selects the wake level for pins. -Non-Volatile Storage --------------------- +Classes +------- -This class gives access to the Non-Volatile storage managed by ESP-IDF. The NVS is partitioned -into namespaces and each namespace contains typed key-value pairs. The keys are strings and the -values may be various integer types, strings, and binary blobs. The driver currently only -supports 32-bit signed integers and blobs. +.. toctree:: + :maxdepth: 1 -.. warning:: - - Changes to NVS need to be committed to flash by calling the commit method. Failure - to call commit results in changes being lost at the next reset. - -.. class:: NVS(namespace) - - Create an object providing access to a namespace (which is automatically created if not - present). - -.. method:: NVS.set_i32(key, value) - - Sets a 32-bit signed integer value for the specified key. Remember to call *commit*! - -.. method:: NVS.get_i32(key) - - Returns the signed integer value for the specified key. Raises an OSError if the key does not - exist or has a different type. - -.. method:: NVS.set_blob(key, value) - - Sets a binary blob value for the specified key. The value passed in must support the buffer - protocol, e.g. bytes, bytearray, str. (Note that esp-idf distinguishes blobs and strings, this - method always writes a blob even if a string is passed in as value.) - Remember to call *commit*! - -.. method:: NVS.get_blob(key, buffer) - - Reads the value of the blob for the specified key into the buffer, which must be a bytearray. - Returns the actual length read. Raises an OSError if the key does not exist, has a different - type, or if the buffer is too small. - -.. method:: NVS.erase_key(key) - - Erases a key-value pair. - -.. method:: NVS.commit() - - Commits changes made by *set_xxx* methods to flash. + esp32.CAN.rst From 39f729533af09acf27abf5dc335a1021687be2c8 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 20 Dec 2019 18:52:51 +0100 Subject: [PATCH 123/180] Code cleaning --- ports/esp32/machine_can.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index c8118de30b408..d48c68b0093c3 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -117,9 +117,9 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { can_status_info_t status = _machine_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); - list->items[2] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_warning - list->items[3] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_error_passive - list->items[4] = MP_OBJ_NEW_SMALL_INT(0); // TODO: self->num_bus_off + list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); + list->items[3] = MP_OBJ_NEW_SMALL_INT(self->num_error_passive); + list->items[4] = MP_OBJ_NEW_SMALL_INT(self->num_bus_off); list->items[5] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_tx); list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); list->items[7] = mp_const_none; @@ -217,7 +217,6 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ if (status != ESP_OK){ mp_raise_OSError(-status); } - //TODO: manage callback // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; @@ -298,10 +297,8 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p }else{ mp_printf(print, "CAN Device is not initialized"); } - } - // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); @@ -343,7 +340,7 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) { //TODO: check naming convention + if (can_idx > 1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } machine_can_obj_t *self = &machine_can_obj; @@ -386,11 +383,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // Check if device was already configured - if (self->config->initialized){ - //TODO: check if this condition is redundant compared to init() - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN device is already initialized")); - return mp_const_none; + return mp_const_none; } // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int & 0x0F, @@ -466,7 +459,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg return mp_const_none; } - STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, From 158c6ef70c240d0e87f53cda4dc9ca87d1d154ed Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 20 Dec 2019 18:53:14 +0100 Subject: [PATCH 124/180] WIP: first implementation of filters --- ports/esp32/machine_can.c | 49 +++++++++++++++++++++++++++++++++++++++ ports/esp32/machine_can.h | 9 ++++++- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index d48c68b0093c3..97ddc7afb5f9f 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -275,6 +275,54 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +// bank: 1 or 2(only for std) +// mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL +// params: [id, mask] +// rtr: ignored if FILTER_RAW +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, + }; + + // parse args + machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + size_t len; + mp_obj_t *params; + mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); + if(len != 2){ + mp_raise_ValueError("params shall be a 2-values list"); + } + bool single_filter = (args[ARG_mode].u_int==FILTER_ADDR_SINGLE || args[ARG_mode].u_int==FILTER_RAW_SINGLE); + if (args[ARG_bank].u_int<0 || (args[ARG_bank].u_int > (single_filter ? 1 : 2))){ + mp_raise_ValueError("selected bank is not available"); + } + can_filter_config_t *filter = self->config->filter; + if (args[ARG_mode].u_int==FILTER_RAW_DUAL || args[ARG_mode].u_int==FILTER_RAW_DUAL){ + filter->single_filter = single_filter; + filter->acceptance_code = params[0]; + filter->acceptance_mask = params[1]; // FIXME: check if order is right + }else{ + if (self->extframe && !single_filter){ + mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL") + } + if (filter->single_filter==true & single_filter==false){ + // Switch to dual filter from single filter + filter->single_filter = single_filter; + filter->acceptance_code = 0; + filter->acceptance_mask = 0xFFFFFFFF; + } + + } + +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter);s STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -403,6 +451,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); + f_config->single_filter = self->extframe; self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 3e91588682ab0..704e6daa3f134 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,9 +43,16 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 +typedef enum _filter_mode_t{ + FILTER_RAW_SINGLE = 0, + FILTER_RAW_DUAL, + FILTER_ADDR_SINGLE, + FILTER_ADDR_DUAL +} + typedef struct _machine_can_config_t { const can_timing_config_t *timing; - const can_filter_config_t *filter; + can_filter_config_t *filter; //FIXME: point to this variable for setting const can_general_config_t *general; uint16_t baudrate; bool initialized; From c2904ebcdc991559e5c0c4b65281f1a2d8e116ea Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Fri, 20 Dec 2019 18:55:45 +0100 Subject: [PATCH 125/180] WIP --- ports/esp32/machine_can.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 97ddc7afb5f9f..913be60994d14 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -71,6 +71,10 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } +STATIC void _machine_hw_can_set_filter(uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ + //addr = addr & () +} + // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ uint32_t status = can_initiate_recovery(); @@ -318,7 +322,7 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args filter->acceptance_code = 0; filter->acceptance_mask = 0xFFFFFFFF; } - + uint32_t addr = params[0] & (self->extframe ? 0x1FFFFFFF : 0x7FF) } } From 513448d176414be1558691b7aa204f81e44a7810 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sat, 21 Dec 2019 11:41:37 +0100 Subject: [PATCH 126/180] Syntax Correction --- .gitignore | 7 +++---- ports/esp32/machine_can.c | 17 ++++++++--------- ports/esp32/machine_can.h | 2 +- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 7342489927888..ca9c98ae476d2 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,6 @@ user.props # Generated rst files ###################### genrst/ - -# MacOS desktop metadata files -###################### -.DS_Store +docs/_build +.vscode +esp-idf diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 913be60994d14..f2df6e41f20e1 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -106,6 +106,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); @@ -310,23 +311,23 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args can_filter_config_t *filter = self->config->filter; if (args[ARG_mode].u_int==FILTER_RAW_DUAL || args[ARG_mode].u_int==FILTER_RAW_DUAL){ filter->single_filter = single_filter; - filter->acceptance_code = params[0]; - filter->acceptance_mask = params[1]; // FIXME: check if order is right + filter->acceptance_code = mp_obj_get_int(params[0]); + filter->acceptance_mask = mp_obj_get_int(params[1]); // FIXME: check if order is right }else{ if (self->extframe && !single_filter){ - mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL") + mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL"); } - if (filter->single_filter==true & single_filter==false){ + if (filter->single_filter==true && single_filter==false){ // Switch to dual filter from single filter filter->single_filter = single_filter; filter->acceptance_code = 0; filter->acceptance_mask = 0xFFFFFFFF; } - uint32_t addr = params[0] & (self->extframe ? 0x1FFFFFFF : 0x7FF) + uint32_t addr = mp_obj_get_int(params[0]) & (self->extframe ? 0x1FFFFFFF : 0x7FF); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter);s +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -435,8 +436,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - return mp_const_none; - } // Configure device can_general_config_t g_config = {.mode = args[ARG_mode].u_int & 0x0F, .tx_io = args[ARG_tx_io].u_int, @@ -455,7 +454,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); - f_config->single_filter = self->extframe; + f_config.single_filter = self->extframe; self->config->filter = &f_config; switch ((int)args[ARG_baudrate].u_int){ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 704e6daa3f134..b5d1db38fa8e2 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -48,7 +48,7 @@ typedef enum _filter_mode_t{ FILTER_RAW_DUAL, FILTER_ADDR_SINGLE, FILTER_ADDR_DUAL -} +} filter_mode_t; typedef struct _machine_can_config_t { const can_timing_config_t *timing; From 673039b0648882fa1d97341e9aa3cf0f5c2bdeb5 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 22 Dec 2019 16:56:32 +0100 Subject: [PATCH 127/180] CAN configuration is stored in object struct --- ports/esp32/machine_can.c | 64 +++++++++++++++++++++------------------ ports/esp32/machine_can.h | 6 ++-- 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f2df6e41f20e1..0c77e552ef7d9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -54,9 +54,9 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = {.general = &((can_general_config_t)CAN_GENERAL_CONFIG_DEFAULT(2,4,0)), - .filter = &((can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()), - .timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()), +machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2,4,0), + .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), + .timing = CAN_TIMING_CONFIG_25KBITS(), .initialized = false}; STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; @@ -333,7 +333,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (self->config->initialized){ qstr mode; - switch(self->config->general->mode){ + switch(self->config->general.mode){ case CAN_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; case CAN_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; @@ -341,8 +341,8 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", - self->config->general->tx_io, - self->config->general->rx_io, + self->config->general.tx_io, + self->config->general.rx_io, self->config->baudrate, mode, self->loopback, @@ -437,29 +437,29 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // Configure device - can_general_config_t g_config = {.mode = args[ARG_mode].u_int & 0x0F, - .tx_io = args[ARG_tx_io].u_int, - .rx_io = args[ARG_rx_io].u_int, - .clkout_io = CAN_IO_UNUSED, - .bus_off_io = CAN_IO_UNUSED, - .tx_queue_len = args[ARG_tx_queue].u_int, - .rx_queue_len = args[ARG_rx_queue].u_int, - .alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || - CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF, - .clkout_divider = 0}; - self->config->general = &g_config; + self->config->general.mode = args[ARG_mode].u_int & 0x0F; + self->config->general.tx_io = args[ARG_tx_io].u_int; + self->config->general.rx_io = args[ARG_rx_io].u_int; + self->config->general.clkout_io = CAN_IO_UNUSED; + self->config->general.bus_off_io = CAN_IO_UNUSED; + self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; + self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; + self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || + CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; + self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; if (args[ARG_auto_restart].u_bool){ mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); - f_config.single_filter = self->extframe; - self->config->filter = &f_config; - + self->config->filter.single_filter = self->extframe; + self->config->filter.acceptance_code = f_config.acceptance_code; + self->config->filter.acceptance_mask = f_config.acceptance_mask; + can_timing_config_t *timing; switch ((int)args[ARG_baudrate].u_int){ case 0: - self->config->timing = &((can_timing_config_t){ + timing = &((can_timing_config_t){ .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, @@ -467,37 +467,41 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .triple_sampling = false}); break; case CAN_BAUDRATE_25k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); break; case CAN_BAUDRATE_50k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); break; case CAN_BAUDRATE_100k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); break; case CAN_BAUDRATE_125k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); break; case CAN_BAUDRATE_250k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); break; case CAN_BAUDRATE_500k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); break; case CAN_BAUDRATE_800k: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); break; case CAN_BAUDRATE_1M: - self->config->timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); break; default: mp_raise_ValueError("Unable to set baudrate"); self->config->baudrate = 0; return mp_const_none; } + self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - uint32_t status = can_driver_install(self->config->general, self->config->timing, self->config->filter); + uint32_t status = can_driver_install( + &self->config->general, + &self->config->timing, + &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); //self->config->filter); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index b5d1db38fa8e2..c4c9cc4c34c48 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -51,9 +51,9 @@ typedef enum _filter_mode_t{ } filter_mode_t; typedef struct _machine_can_config_t { - const can_timing_config_t *timing; - can_filter_config_t *filter; //FIXME: point to this variable for setting - const can_general_config_t *general; + can_timing_config_t timing; + can_filter_config_t filter; + can_general_config_t general; uint16_t baudrate; bool initialized; } machine_can_config_t; From 787fe8628caa1c28bd003d93e0a6394919852524 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 22 Dec 2019 16:59:27 +0100 Subject: [PATCH 128/180] Bugfixes --- ports/esp32/machine_can.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0c77e552ef7d9..2cee0bbd01348 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -64,7 +64,7 @@ STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_co // INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; - uint8_t err_code = can_get_status_info(&status); + uint32_t err_code = can_get_status_info(&status); if(err_code!=ESP_OK){ mp_raise_OSError(-err_code); } @@ -182,10 +182,11 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; + }else{ + id &= 0x1FF; } if (self->loopback){ flags += CAN_MSG_FLAG_SELF; - id &= 0x1FF; } can_message_t tx_msg = {.data_length_code = length, .identifier = id, @@ -431,7 +432,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = true} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; From 59b3127dbbcad26d762ce829e1d22f7e52b5ef64 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 22 Dec 2019 17:04:08 +0100 Subject: [PATCH 129/180] WIP: implementation of setfilter() --- ports/esp32/machine_can.c | 71 ++++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 2cee0bbd01348..cf5e8046f31a9 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -71,8 +71,29 @@ STATIC can_status_info_t _machine_hw_can_get_status(){ return status; } -STATIC void _machine_hw_can_set_filter(uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ - //addr = addr & () +//INTERNAL FUNCTION Populates the filter register according to inputs +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ + //Check if bank is allowed + if (bank<0 && bank>((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ + mp_raise_ValueError("CAN filter parameter error"); + } + uint32_t preserve_mask; + if (self->extframe){ + addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); + mask = (mask & 0x1FFFFFFF) << 3 | 0x04; + preserve_mask = 0; + }else{ + addr = ((addr & 0x7FF) | (rtr ? 0x800 : 0)) << (bank==1 ? 16 : 0); + mask = ((mask & 0x7FF) | 0x800) << (bank==1 ? 16 : 0); + preserve_mask = 0xFFFF << (bank==0 ? 16 : 0);; + } + ESP_LOGI(DEVICE_NAME, "Address: %08X",addr); + ESP_LOGI(DEVICE_NAME, "Mask: %08X", mask); + ESP_LOGI(DEVICE_NAME, "Preserve: %08X", preserve_mask); + self->config->filter.acceptance_code &= preserve_mask; + self->config->filter.acceptance_code |= addr; + self->config->filter.acceptance_mask &= preserve_mask; + self->config->filter.acceptance_mask |= mask; } // Force a software restart of the controller, to allow transmission after a bus error @@ -281,7 +302,7 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); -// bank: 1 or 2(only for std) +// bank: 0 or 1(only for std) // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW @@ -301,32 +322,31 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; - mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); + mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); if(len != 2){ mp_raise_ValueError("params shall be a 2-values list"); } - bool single_filter = (args[ARG_mode].u_int==FILTER_ADDR_SINGLE || args[ARG_mode].u_int==FILTER_RAW_SINGLE); - if (args[ARG_bank].u_int<0 || (args[ARG_bank].u_int > (single_filter ? 1 : 2))){ - mp_raise_ValueError("selected bank is not available"); - } - can_filter_config_t *filter = self->config->filter; - if (args[ARG_mode].u_int==FILTER_RAW_DUAL || args[ARG_mode].u_int==FILTER_RAW_DUAL){ - filter->single_filter = single_filter; - filter->acceptance_code = mp_obj_get_int(params[0]); - filter->acceptance_mask = mp_obj_get_int(params[1]); // FIXME: check if order is right + uint32_t id = mp_obj_get_int(params[0]); + uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask + if (args[ARG_mode].u_int==FILTER_RAW_SINGLE || args[ARG_mode].u_int==FILTER_RAW_DUAL){ + self->config->filter.single_filter = (args[ARG_mode].u_int==FILTER_RAW_SINGLE); + self->config->filter.acceptance_code = id; + self->config->filter.acceptance_mask = mask; }else{ - if (self->extframe && !single_filter){ - mp_raise_ValueError("Dual filter for Extd Msg is not supported. Use FILTER_RAW_DUAL"); - } - if (filter->single_filter==true && single_filter==false){ - // Switch to dual filter from single filter - filter->single_filter = single_filter; - filter->acceptance_code = 0; - filter->acceptance_mask = 0xFFFFFFFF; - } - uint32_t addr = mp_obj_get_int(params[0]) & (self->extframe ? 0x1FFFFFFF : 0x7FF); + _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } +ESP_LOGI(DEVICE_NAME, "New Code: %08X",self->config->filter.acceptance_code); +ESP_LOGI(DEVICE_NAME, "New Mask: %08X",self->config->filter.acceptance_mask); + ESP_STATUS_CHECK(can_stop()); + ESP_STATUS_CHECK(can_driver_uninstall()); + ESP_STATUS_CHECK(can_driver_install( + &self->config->general, + &self->config->timing, + &self->config->filter)); + ESP_STATUS_CHECK(can_start()); + ESP_LOGI(DEVICE_NAME, "Restarted"); + return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -528,6 +548,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, /* { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, @@ -559,6 +580,10 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, + // CAN_FILTER_MODE + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, // CAN_ALERT { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, From 6acf0ccf1dc9ab97ae966fccf0e39f9a5ed082f2 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:49:17 +0100 Subject: [PATCH 130/180] Completed setfilter() --- ports/esp32/machine_can.c | 32 ++++++++++++++++++++------------ ports/esp32/machine_can.h | 4 ++-- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index cf5e8046f31a9..272b05126cf72 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -80,16 +80,27 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u uint32_t preserve_mask; if (self->extframe){ addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); - mask = (mask & 0x1FFFFFFF) << 3 | 0x04; + mask = (mask & 0x1FFFFFFF) << 3 | 0x03; + preserve_mask = 0; + }else if(self->config->filter.single_filter){ + addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); + mask = ((mask & 0x7FF) << 5); + mask |= 0xFFFFF000; preserve_mask = 0; }else{ - addr = ((addr & 0x7FF) | (rtr ? 0x800 : 0)) << (bank==1 ? 16 : 0); - mask = ((mask & 0x7FF) | 0x800) << (bank==1 ? 16 : 0); - preserve_mask = 0xFFFF << (bank==0 ? 16 : 0);; + addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); + mask = ((mask & 0x7FF) << 5); + preserve_mask = 0xFFFF << (bank==0 ? 16 : 0); + if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank==0 ? 16 : 0))){ + // Other filter accepts all; it will replaced duplicating current filter + addr = addr | (addr << 16); + mask = mask | (mask << 16); + preserve_mask = 0; + }else{ + addr = addr << (bank==1 ? 16 : 0); + mask = mask << (bank==1 ? 16 : 0); + } } - ESP_LOGI(DEVICE_NAME, "Address: %08X",addr); - ESP_LOGI(DEVICE_NAME, "Mask: %08X", mask); - ESP_LOGI(DEVICE_NAME, "Preserve: %08X", preserve_mask); self->config->filter.acceptance_code &= preserve_mask; self->config->filter.acceptance_code |= addr; self->config->filter.acceptance_mask &= preserve_mask; @@ -333,11 +344,9 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; }else{ + self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - -ESP_LOGI(DEVICE_NAME, "New Code: %08X",self->config->filter.acceptance_code); -ESP_LOGI(DEVICE_NAME, "New Mask: %08X",self->config->filter.acceptance_mask); ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( @@ -345,7 +354,6 @@ ESP_LOGI(DEVICE_NAME, "New Mask: %08X",self->config->filter.acceptance_mask); &self->config->timing, &self->config->filter)); ESP_STATUS_CHECK(can_start()); - ESP_LOGI(DEVICE_NAME, "Restarted"); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -522,7 +530,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg uint32_t status = can_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); //self->config->filter); + &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); if (status != ESP_OK){ mp_raise_OSError(-status); }else{ diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index c4c9cc4c34c48..a79a23271345a 100644 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,11 +43,11 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 +#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, - FILTER_ADDR_SINGLE, - FILTER_ADDR_DUAL + FILTER_ADDRESS } filter_mode_t; typedef struct _machine_can_config_t { From 6130a68c64676338ae157d18f5d34a0f12d99aee Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:49:34 +0100 Subject: [PATCH 131/180] added clearfilter() --- ports/esp32/machine_can.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 272b05126cf72..fddba0ccc8778 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -313,6 +313,22 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->config->filter.single_filter = self->extframe; + self->config->filter.acceptance_code = 0; + self->config->filter.acceptance_mask = 0xFFFFFFFF; + ESP_STATUS_CHECK(can_stop()); + ESP_STATUS_CHECK(can_driver_uninstall()); + ESP_STATUS_CHECK(can_driver_install( + &self->config->general, + &self->config->timing, + &self->config->filter)); + ESP_STATUS_CHECK(can_start()); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); + // bank: 0 or 1(only for std) // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] @@ -557,12 +573,8 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, - /* - { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) }, - { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) }, - */ - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, // ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, From 13e41a5b36f8da252c7719f51637b5948669cd4a Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:50:07 +0100 Subject: [PATCH 132/180] Added unittest as example --- examples/esp32_can.py | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 examples/esp32_can.py diff --git a/examples/esp32_can.py b/examples/esp32_can.py new file mode 100644 index 0000000000000..b5c4966a04dbc --- /dev/null +++ b/examples/esp32_can.py @@ -0,0 +1,68 @@ +from machine import CAN +import time + +def sendAndCheck(dev, name, id, expectedLP = True): + dev.clear_tx_queue() + dev.clear_rx_queue() + dev.send([], id) + time.sleep_ms(100) + if dev.any() == expectedLP: + print("{}: OK".format(name)) + if expectedLP: + dev.recv() + else: + print("{}: FAILED".format(name)) + +dev = CAN(0, + extframe=False, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18,rx_io=19, auto_restart=False) + +#Test send/receive message +print("Loopback Test: no filter - STD") +sendAndCheck(dev, "No filter", 0x100, True) + +#Set filter1 +print("Loopback Test: one filter - STD") +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) +sendAndCheck(dev, "Passing Message", 0x101, True) +sendAndCheck(dev, "Blocked Message", 0x100, False) + +#Set filter2 +print("Loopback Test: second filter - STD") +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) +sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) +sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) +sendAndCheck(dev, "Blocked Message", 0x100, False) + +#Remove filter +print("Loopback Test: clear filter - STD") +dev.clearfilter() +sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) +sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) +sendAndCheck(dev, "Passing any Message", 0x100, True) + +#Move to Extended +dev = CAN(0, + extframe=True, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18,rx_io=19, auto_restart=False) + +#Test send/receive message +print("Loopback Test: no filter - Extd") +sendAndCheck(dev, "No filter", 0x100, True) + +#Set filter1 +print("Loopback Test: one filter - Extd") +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) +sendAndCheck(dev, "Passing Message", 0x101, True) +sendAndCheck(dev, "Blocked Message", 0x100, False) + +#Remove filter +print("Loopback Test: clear filter - Extd") +dev.clearfilter() +sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) +sendAndCheck(dev, "Passing any Message", 0x100, True) + From 8331ac9cd5f113e2ac885a35b1d06df6683cffe2 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 09:58:51 +0100 Subject: [PATCH 133/180] removed machine_can.h --- ports/esp32/machine_can.c | 49 ++++++++++++++++++++++- ports/esp32/machine_can.h | 83 --------------------------------------- 2 files changed, 47 insertions(+), 85 deletions(-) delete mode 100644 ports/esp32/machine_can.h diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index fddba0ccc8778..0ffbf7e88382a 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -37,10 +37,55 @@ #include "esp_err.h" #include "esp_log.h" -#include +#include "modmachine.h" #if MICROPY_HW_ENABLE_CAN +#define DEVICE_NAME "CAN" + +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 + +#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} +typedef enum _filter_mode_t{ + FILTER_RAW_SINGLE = 0, + FILTER_RAW_DUAL, + FILTER_ADDRESS +} filter_mode_t; + +typedef struct _machine_can_config_t { + can_timing_config_t timing; + can_filter_config_t filter; + can_general_config_t general; + uint16_t baudrate; + bool initialized; +} machine_can_config_t; + +typedef struct _machine_can_obj_t { + mp_obj_base_t base; + machine_can_config_t *config; + mp_obj_t rxcallback; + byte rx_state; + bool extframe : 1; + bool loopback : 1; + uint16_t num_error_warning; //FIXME: populate this value somewhere + uint16_t num_error_passive; + uint16_t num_bus_off; +} machine_can_obj_t; + +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + // Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) @@ -113,7 +158,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ if (status != ESP_OK){ mp_raise_OSError(-status); } - mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution + mp_hal_delay_ms(200); // TODO: replace it with a smarter solution status = can_start(); if (status != ESP_OK){ mp_raise_OSError(-status); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h deleted file mode 100644 index a79a23271345a..0000000000000 --- a/ports/esp32/machine_can.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Musumeci Salvatore - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#ifndef MICROPY_INCLUDED_ESP32_CAN_H -#define MICROPY_INCLUDED_ESP32_CAN_H - -#include "modmachine.h" - -#include "py/obj.h" - -#if MICROPY_HW_ENABLE_CAN - -#define DEVICE_NAME "CAN" - -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 - -#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} -typedef enum _filter_mode_t{ - FILTER_RAW_SINGLE = 0, - FILTER_RAW_DUAL, - FILTER_ADDRESS -} filter_mode_t; - -typedef struct _machine_can_config_t { - can_timing_config_t timing; - can_filter_config_t filter; - can_general_config_t general; - uint16_t baudrate; - bool initialized; -} machine_can_config_t; - -typedef struct _machine_can_obj_t { - mp_obj_base_t base; - machine_can_config_t *config; - mp_obj_t rxcallback; - byte rx_state; - bool extframe : 1; - bool loopback : 1; - uint16_t num_error_warning; //FIXME: populate this value somewhere - uint16_t num_error_passive; - uint16_t num_bus_off; -} machine_can_obj_t; - -typedef enum _rx_state_t { - RX_STATE_FIFO_EMPTY = 0, - RX_STATE_MESSAGE_PENDING, - RX_STATE_FIFO_FULL, - RX_STATE_FIFO_OVERFLOW, -} rx_state_t; - -extern const mp_obj_type_t machine_can_type; - -#endif // MICROPY_HW_ENABLE_CAN -#endif // MICROPY_INCLUDED_ESP32_CAN_H From d2f6bb692c370cef4619b53a3fd595d69c204f35 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 10:00:58 +0100 Subject: [PATCH 134/180] Bugfix --- ports/esp32/modmachine.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 7a78c8b9a1ffd..69a96e7547d91 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -296,7 +296,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #if MICROPY_PY_MACHINE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, + #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, From 53dfb9475cee4fae72d11e8561334258214e53b8 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 10:18:52 +0100 Subject: [PATCH 135/180] Docs updated --- docs/library/esp32.CAN.rst | 77 +++++++++++++------------------------- ports/esp32/machine_can.c | 6 ++- 2 files changed, 30 insertions(+), 53 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index e17e9f4a5598f..0a35accdf630a 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -32,17 +32,6 @@ Constructors The physical pins of the CAN bus can be assigned during init. -Class Methods -------------- -.. classmethod:: CAN.initfilterbanks(nr) TODO: - - Reset and disable all filter banks and assign how many banks should be available for CAN(1). - - STM32F405 has 28 filter banks that are shared between the two available CAN bus controllers. - This function configures how many filter banks should be assigned to each. *nr* is the number of banks - that will be assigned to CAN(1), the rest of the 28 are assigned to CAN(2). - At boot, 14 banks are assigned to each controller. - Methods ------- @@ -122,53 +111,37 @@ Methods - number of pending RX messages - Reserved -.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) TODO: +.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) Configure a filter bank: - - *bank* is the filter bank that is to be configured. + - *bank* is the filter bank that is to be configured (0 for extended, 0 or 1 for standard msg) - *mode* is the mode the filter should operate in. - - *fifo* is which fifo (0 or 1) a message should be stored in, if it is accepted by this filter. - - *params* is an array of values the defines the filter. The contents of the array depends on the *mode* argument. + - *params* is an array of two values that defines the filter. + The first element will be the id to filter and the second element will be the mask to apply. + mask bit implementation considers 1 as a don't care state and 0 as a check state. - +-----------+---------------------------------------------------------+ + +----------------------+----------------------------------------------+ |*mode* |contents of *params* array | - +===========+=========================================================+ - |CAN.LIST16 |Four 16 bit ids that will be accepted | - +-----------+---------------------------------------------------------+ - |CAN.LIST32 |Two 32 bit ids that will be accepted | - +-----------+---------------------------------------------------------+ - |CAN.MASK16 |Two 16 bit id/mask pairs. E.g. (1, 3, 4, 4) | - | | | The first pair, 1 and 3 will accept all ids | - | | | that have bit 0 = 1 and bit 1 = 0. | - | | | The second pair, 4 and 4, will accept all ids | - | | | that have bit 2 = 1. | - +-----------+---------------------------------------------------------+ - |CAN.MASK32 |As with CAN.MASK16 but with only one 32 bit id/mask pair.| - +-----------+---------------------------------------------------------+ - - - *rtr* is an array of booleans that states if a filter should accept a - remote transmission request message. If this argument is not given - then it defaults to ``False`` for all entries. The length of the array - depends on the *mode* argument. - - +-----------+----------------------+ - |*mode* |length of *rtr* array | - +===========+======================+ - |CAN.LIST16 |4 | - +-----------+----------------------+ - |CAN.LIST32 |2 | - +-----------+----------------------+ - |CAN.MASK16 |2 | - +-----------+----------------------+ - |CAN.MASK32 |1 | - +-----------+----------------------+ - -.. method:: CAN.clearfilter(bank) TODO: - - Clear and disables a filter bank: - - - *bank* is the filter bank that is to be cleared. + +======================+==============================================+ + |CAN.FILTER_RAW_SINGLE | *params* will be copied in hardware variable | + | | and single_filter_mode will be selected | + | | In this mode, *bank* will be ignored | + +----------------------+----------------------------------------------+ + |CAN.FILTER_RAW_DUAL | *params* will be copied in hardware variable | + | | and single_filter_mode will be cleared | + | | In this mode, *bank* will be ignored | + +----------------------+----------------------------------------------+ + |CAN.FILTER_ADDRESS | *params* will be set in hardware registers | + | | according to *bank* selection | + +----------------------+----------------------------------------------+ + + - *rtr* is bool that states if a filter should accept a remote transmission request message. + If this argument is not given then it defaults to ``False``. + +.. method:: CAN.clearfilter(bank) + + Clear and disables all filters .. method:: CAN.any(fifo) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0ffbf7e88382a..ac5455aaed451 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -209,6 +209,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); +// Get Alert info STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); @@ -358,6 +359,7 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in } STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +// Clear filters setting STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; @@ -378,6 +380,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW +// Set CAN HW filter STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr }; static const mp_arg_t allowed_args[] = { @@ -674,4 +677,5 @@ const mp_obj_type_t machine_can_type = { .make_new = machine_hw_can_make_new, // give it a constructor .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members }; -#endif // MICROPY_HW_ENABLE_CAN \ No newline at end of file +#endif // MICROPY_HW_ENABLE_CAN + \ No newline at end of file From 8977bd7cfca8bc0814ba1acac7987d09e7f43b23 Mon Sep 17 00:00:00 2001 From: Salvo Musumeci Date: Mon, 23 Dec 2019 10:23:12 +0100 Subject: [PATCH 136/180] Update Author name --- ports/esp32/machine_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index ac5455aaed451..dcdda0d2f7442 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -1,6 +1,6 @@ /* The MIT License (MIT) * - * Copyright (c) 2019 Damien P. George + * Copyright (c) 2019 Musumeci Salvatore * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -678,4 +678,4 @@ const mp_obj_type_t machine_can_type = { .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members }; #endif // MICROPY_HW_ENABLE_CAN - \ No newline at end of file + From 670f6fafbbae5b42a609ef30f31285113c09ba95 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Mon, 23 Dec 2019 10:25:52 +0100 Subject: [PATCH 137/180] remove .vscode folder --- .vscode/c_cpp_properties.json | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 .vscode/c_cpp_properties.json diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 5f0824b540e6b..0000000000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "configurations": [ - { - "name": "Mac", - "includePath": [ - "${workspaceFolder}/../esp-idf/components/**", - "${workspaceFolder}/ports/esp32/**", - "${workspaceFolder}/**" - ], - "defines": [], - "macFrameworkPath": [ - "/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/System/Library/Frameworks" - ], - "compilerPath": "/usr/bin/clang", - "cStandard": "c11", - "cppStandard": "c++17", - "intelliSenseMode": "clang-x64" - } - ], - "version": 4 -} \ No newline at end of file From ca754145b8d8da29e23aec713713d7a1db95f174 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:09:13 +0100 Subject: [PATCH 138/180] Formatting sources --- examples/esp32_can.py | 37 +-- ports/esp32/machine_can.c | 636 +++++++++++++++++++++++--------------- 2 files changed, 399 insertions(+), 274 deletions(-) diff --git a/examples/esp32_can.py b/examples/esp32_can.py index b5c4966a04dbc..495370bb1d5e8 100644 --- a/examples/esp32_can.py +++ b/examples/esp32_can.py @@ -1,7 +1,8 @@ from machine import CAN import time -def sendAndCheck(dev, name, id, expectedLP = True): + +def sendAndCheck(dev, name, id, expectedLP=True): dev.clear_tx_queue() dev.clear_rx_queue() dev.send([], id) @@ -13,56 +14,56 @@ def sendAndCheck(dev, name, id, expectedLP = True): else: print("{}: FAILED".format(name)) + dev = CAN(0, - extframe=False, - mode=CAN.SILENT_LOOPBACK, - baudrate=CAN.BAUDRATE_500k, - tx_io=18,rx_io=19, auto_restart=False) + extframe=False, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18, rx_io=19, auto_restart=False) -#Test send/receive message +# Test send/receive message print("Loopback Test: no filter - STD") sendAndCheck(dev, "No filter", 0x100, True) -#Set filter1 +# Set filter1 print("Loopback Test: one filter - STD") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) sendAndCheck(dev, "Passing Message", 0x101, True) sendAndCheck(dev, "Blocked Message", 0x100, False) -#Set filter2 +# Set filter2 print("Loopback Test: second filter - STD") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) sendAndCheck(dev, "Blocked Message", 0x100, False) -#Remove filter +# Remove filter print("Loopback Test: clear filter - STD") dev.clearfilter() sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) sendAndCheck(dev, "Passing any Message", 0x100, True) -#Move to Extended +# Move to Extended dev = CAN(0, - extframe=True, - mode=CAN.SILENT_LOOPBACK, - baudrate=CAN.BAUDRATE_500k, - tx_io=18,rx_io=19, auto_restart=False) + extframe=True, + mode=CAN.SILENT_LOOPBACK, + baudrate=CAN.BAUDRATE_500k, + tx_io=18, rx_io=19, auto_restart=False) -#Test send/receive message +# Test send/receive message print("Loopback Test: no filter - Extd") sendAndCheck(dev, "No filter", 0x100, True) -#Set filter1 +# Set filter1 print("Loopback Test: one filter - Extd") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) sendAndCheck(dev, "Passing Message", 0x101, True) sendAndCheck(dev, "Blocked Message", 0x100, False) -#Remove filter +# Remove filter print("Loopback Test: clear filter - Extd") dev.clearfilter() sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) sendAndCheck(dev, "Passing any Message", 0x100, True) - diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index dcdda0d2f7442..7dfc8729c6178 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -52,22 +52,29 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 -#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} -typedef enum _filter_mode_t{ +#define ESP_STATUS_CHECK(status) \ + if (status != ESP_OK) \ + { \ + mp_raise_OSError(-status); \ + } +typedef enum _filter_mode_t +{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t { +typedef struct _machine_can_config_t +{ can_timing_config_t timing; - can_filter_config_t filter; + can_filter_config_t filter; can_general_config_t general; uint16_t baudrate; bool initialized; } machine_can_config_t; -typedef struct _machine_can_obj_t { +typedef struct _machine_can_obj_t +{ mp_obj_base_t base; machine_can_config_t *config; mp_obj_t rxcallback; @@ -79,7 +86,8 @@ typedef struct _machine_can_obj_t { uint16_t num_bus_off; } machine_can_obj_t; -typedef enum _rx_state_t { +typedef enum _rx_state_t +{ RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, @@ -87,11 +95,10 @@ typedef enum _rx_state_t { } rx_state_t; // Default baudrate: 500kb -#define CAN_DEFAULT_PRESCALER (8) -#define CAN_DEFAULT_SJW (3) -#define CAN_DEFAULT_BS1 (15) -#define CAN_DEFAULT_BS2 (4) - +#define CAN_DEFAULT_PRESCALER (8) +#define CAN_DEFAULT_SJW (3) +#define CAN_DEFAULT_BS1 (15) +#define CAN_DEFAULT_BS2 (4) // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); @@ -99,51 +106,63 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2,4,0), +machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), .timing = CAN_TIMING_CONFIG_25KBITS(), .initialized = false}; - -STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config=&can_config}; + +STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config = &can_config}; // INTERNAL FUNCTION Return status information -STATIC can_status_info_t _machine_hw_can_get_status(){ +STATIC can_status_info_t _machine_hw_can_get_status() +{ can_status_info_t status; uint32_t err_code = can_get_status_info(&status); - if(err_code!=ESP_OK){ + if (err_code != ESP_OK) + { mp_raise_OSError(-err_code); } return status; } //INTERNAL FUNCTION Populates the filter register according to inputs -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) +{ //Check if bank is allowed - if (bank<0 && bank>((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ + if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)) + { mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; - if (self->extframe){ + if (self->extframe) + { addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - }else if(self->config->filter.single_filter){ + } + else if (self->config->filter.single_filter) + { addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); + mask = ((mask & 0x7FF) << 5); mask |= 0xFFFFF000; preserve_mask = 0; - }else{ + } + else + { addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); - preserve_mask = 0xFFFF << (bank==0 ? 16 : 0); - if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank==0 ? 16 : 0))){ + mask = ((mask & 0x7FF) << 5); + preserve_mask = 0xFFFF << (bank == 0 ? 16 : 0); + if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))) + { // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); preserve_mask = 0; - }else{ - addr = addr << (bank==1 ? 16 : 0); - mask = mask << (bank==1 ? 16 : 0); + } + else + { + addr = addr << (bank == 1 ? 16 : 0); + mask = mask << (bank == 1 ? 16 : 0); } } self->config->filter.acceptance_code &= preserve_mask; @@ -153,14 +172,17 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u } // Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) +{ uint32_t status = can_initiate_recovery(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } mp_hal_delay_ms(200); // TODO: replace it with a smarter solution status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } return mp_const_none; @@ -168,31 +190,39 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) +{ can_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_bool((status.msgs_to_rx)>0); + return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) +{ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) +{ machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; - if (n_args == 1) { + if (n_args == 1) + { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - } else { - if (!mp_obj_is_type(args[1], &mp_type_list)) { + } + else + { + if (!mp_obj_is_type(args[1], &mp_type_list)) + { mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); - if (list->len < 8) { + if (list->len < 8) + { mp_raise_ValueError(NULL); } } @@ -210,10 +240,12 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) +{ uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } return mp_obj_new_int(alerts); @@ -221,75 +253,99 @@ STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ - return mp_obj_new_bool(can_clear_transmit_queue()==ESP_OK); +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) +{ + return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ - return mp_obj_new_bool(can_clear_receive_queue()==ESP_OK); +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) +{ + return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); - // send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_self }; +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_data, + ARG_id, + ARG_timeout, + ARG_rtr, + ARG_self + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + {MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, }; - + // parse args machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args-1, pos_args+1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // populate message size_t length; mp_obj_t *items; - mp_obj_get_array(args[ARG_data].u_obj,&length, &items); - if (length>8){ + mp_obj_get_array(args[ARG_data].u_obj, &length, &items); + if (length > 8) + { mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool==true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + uint8_t flags = (args[ARG_rtr].u_bool == true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; - if (self->extframe){ + if (self->extframe) + { flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; - }else{ + } + else + { id &= 0x1FF; } - if (self->loopback){ + if (self->loopback) + { flags += CAN_MSG_FLAG_SELF; } - can_message_t tx_msg = {.data_length_code = length, - .identifier = id, + can_message_t tx_msg = {.data_length_code = length, + .identifier = id, .flags = flags}; - for (uint8_t i=0; iitems; + items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - } else { + } + else + { // User should provide a list of length at least 4 to hold the values - if (!mp_obj_is_type(ret_obj, &mp_type_list)) { + if (!mp_obj_is_type(ret_obj, &mp_type_list)) + { mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); - if (list->len < 4) { + if (list->len < 4) + { mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace - if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { + if (!mp_obj_is_type(items[3], &mp_type_memoryview)) + { mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); - if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) - || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) + { mp_raise_ValueError(NULL); } mv->len = rx_message.data_length_code; memcpy(mv->items, rx_message.data, rx_message.data_length_code); - } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; @@ -340,18 +402,24 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) +{ mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (callback_in == mp_const_none) { + if (callback_in == mp_const_none) + { self->rxcallback = mp_const_none; - } else if (self->rxcallback != mp_const_none) { + } + else if (self->rxcallback != mp_const_none) + { // Rx call backs has already been initialized // only the callback function should be changed self->rxcallback = callback_in; // TODO: disable interrupt - } else if (mp_obj_is_callable(callback_in)) { + } + else if (mp_obj_is_callable(callback_in)) + { self->rxcallback = callback_in; // TODO: set interrupt } @@ -360,7 +428,8 @@ STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) +{ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; @@ -368,8 +437,8 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( - &self->config->general, - &self->config->timing, + &self->config->general, + &self->config->timing, &self->config->filter)); ESP_STATUS_CHECK(can_start()); return mp_const_none; @@ -381,15 +450,22 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr }; +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_bank, + ARG_mode, + ARG_params, + ARG_rtr + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, + {MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false}}, }; - + // parse args machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -397,58 +473,77 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; - mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if(len != 2){ + mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); + if (len != 2) + { mp_raise_ValueError("params shall be a 2-values list"); } uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int==FILTER_RAW_SINGLE || args[ARG_mode].u_int==FILTER_RAW_DUAL){ - self->config->filter.single_filter = (args[ARG_mode].u_int==FILTER_RAW_SINGLE); + if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) + { + self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; - }else{ + } + else + { self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - ESP_STATUS_CHECK(can_stop()); + ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( - &self->config->general, - &self->config->timing, + &self->config->general, + &self->config->timing, &self->config->filter)); ESP_STATUS_CHECK(can_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) +{ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized){ + if (self->config->initialized) + { qstr mode; - switch(self->config->general.mode){ - case CAN_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; - case CAN_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; - case CAN_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; - default: mode = MP_QSTR_UNKNOWN; break; + switch (self->config->general.mode) + { + case CAN_MODE_LISTEN_ONLY: + mode = MP_QSTR_LISTEN; + break; + case CAN_MODE_NO_ACK: + mode = MP_QSTR_NO_ACK; + break; + case CAN_MODE_NORMAL: + mode = MP_QSTR_NORMAL; + break; + default: + mode = MP_QSTR_UNKNOWN; + break; } - mp_printf(print, - "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", - self->config->general.tx_io, - self->config->general.rx_io, - self->config->baudrate, - mode, - self->loopback, - self->extframe); - }else{ + mp_printf(print, + "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", + self->config->general.tx_io, + self->config->general.rx_io, + self->config->baudrate, + mode, + self->loopback, + self->extframe); + } + else + { mp_printf(print, "CAN Device is not initialized"); } } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized){ +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) +{ + machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized) + { ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; } @@ -457,18 +552,22 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); // deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ - const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true){ +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) +{ + const machine_can_obj_t *self = &machine_can_obj; + if (self->config->initialized != true) + { ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } uint32_t status = can_stop(); - if(status!=ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } status = can_driver_uninstall(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); } self->config->initialized = false; @@ -478,20 +577,25 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deini // CAN(bus, ...) No argument to get the object // If no arguments are provided, the initialized object will be returned -mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args){ +mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args) +{ // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0])!=true){ + if (mp_obj_is_int(args[0]) != true) + { mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) { + if (can_idx > 1) + { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } - machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0) { - if (self->config->initialized) { + machine_can_obj_t *self = &machine_can_obj; + if (n_args > 1 || n_kw > 0) + { + if (self->config->initialized) + { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); @@ -509,22 +613,36 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_mode, ARG_extframe, ARG_baudrate, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, - ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue, ARG_auto_restart}; +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) +{ + enum + { + ARG_mode, + ARG_extframe, + ARG_baudrate, + ARG_prescaler, + ARG_sjw, + ARG_bs1, + ARG_bs2, + ARG_tx_io, + ARG_rx_io, + ARG_tx_queue, + ARG_rx_queue, + ARG_auto_restart + }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, - { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, - { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, - { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, - { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, - { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, + {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL}}, + {MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false}}, + {MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER}}, + {MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW}}, + {MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1}}, + {MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2}}, + {MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4}}, + {MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2}}, + {MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0}}, + {MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5}}, + {MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false}}, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -537,12 +655,13 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.bus_off_io = CAN_IO_UNUSED; self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; - self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || - CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; + self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || + CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; self->config->general.clkout_divider = 0; - self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); + self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool){ + if (args[ARG_auto_restart].u_bool) + { mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); @@ -550,58 +669,65 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; can_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int){ - case 0: - timing = &((can_timing_config_t){ - .brp = args[ARG_prescaler].u_int, - .sjw = args[ARG_sjw].u_int, - .tseg_1 = args[ARG_bs1].u_int, - .tseg_2 = args[ARG_bs1].u_int, - .triple_sampling = false}); - break; - case CAN_BAUDRATE_25k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); - break; - case CAN_BAUDRATE_50k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); - break; - case CAN_BAUDRATE_100k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); - break; - case CAN_BAUDRATE_125k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); - break; - case CAN_BAUDRATE_250k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); - break; - case CAN_BAUDRATE_500k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); - break; - case CAN_BAUDRATE_800k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); - break; - case CAN_BAUDRATE_1M: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); - break; - default: - mp_raise_ValueError("Unable to set baudrate"); - self->config->baudrate = 0; - return mp_const_none; + switch ((int)args[ARG_baudrate].u_int) + { + case 0: + timing = &((can_timing_config_t){ + .brp = args[ARG_prescaler].u_int, + .sjw = args[ARG_sjw].u_int, + .tseg_1 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs1].u_int, + .triple_sampling = false}); + break; + case CAN_BAUDRATE_25k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + break; + case CAN_BAUDRATE_50k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + break; + case CAN_BAUDRATE_100k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + break; + case CAN_BAUDRATE_125k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + break; + case CAN_BAUDRATE_250k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + break; + case CAN_BAUDRATE_500k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + break; + case CAN_BAUDRATE_800k: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + break; + case CAN_BAUDRATE_1M: + timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + break; + default: + mp_raise_ValueError("Unable to set baudrate"); + self->config->baudrate = 0; + return mp_const_none; } self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - + uint32_t status = can_driver_install( - &self->config->general, - &self->config->timing, - &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); - if (status != ESP_OK){ + &self->config->general, + &self->config->timing, + &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); + if (status != ESP_OK) + { mp_raise_OSError(-status); - }else{ + } + else + { status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) + { mp_raise_OSError(-status); - }else{ + } + else + { self->config->initialized = true; } } @@ -610,72 +736,70 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_ATTRIBUTES - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, + {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN)}, // Micropython Generic API - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, - { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, - { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, - // ESP32 Specific API - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - - { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, - // CAN_MODE - { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, - { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, - { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj)}, + {MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj)}, + {MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj)}, + {MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj)}, + {MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj)}, + {MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj)}, + {MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, + {MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, + {MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj)}, + {MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj)}, + {MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj)}, + // ESP32 Specific API + {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, + {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, + + {MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, + // CAN_MODE + {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL)}, + {MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10)}, + {MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK)}, + {MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10)}, + {MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY)}, // CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + {MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED)}, + {MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING)}, + {MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF)}, + {MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING)}, // CAN_BAUDRATE - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k)}, + {MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M)}, // CAN_FILTER_MODE - { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, - { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, - { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, + {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE)}, + {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL)}, + {MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS)}, // CAN_ALERT - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } -}; + {MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS)}, + {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF)}}; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); // Python object definition const mp_obj_type_t machine_can_type = { - { &mp_type_type }, + {&mp_type_type}, .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t*)&machine_can_locals_dict, // and the global members + .print = machine_hw_can_print, // give it a print-function + .make_new = machine_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t *)&machine_can_locals_dict, // and the global members }; #endif // MICROPY_HW_ENABLE_CAN - From d407c3e0a9f392cf6720e6ed58b4e9a14411dfd7 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:27:47 +0100 Subject: [PATCH 139/180] Removed additional constants and added in documentation --- docs/library/esp32.CAN.rst | 20 +++++++++++++++++++- ports/esp32/machine_can.c | 25 +------------------------ 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index 0a35accdf630a..6c3ebe2f8679c 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -43,7 +43,7 @@ Methods - if *extframe* is True then the bus uses extended identifiers in the frames (29 bits); otherwise it uses standard 11 bit identifiers - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* - will be ignored. Standard speeds are available as CAN.BAUDRATE_* + will be ignored. Standard speeds are 25, 50, 100, 125, 250, 500, 1000 - *prescaler* is used to set the duration of 1 time quanta; the time quanta will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler - *sjw* is the resynchronisation jump width in units of the time quanta; @@ -210,6 +210,24 @@ Methods .. method:: CAN.get_alerts() Read the alert status word directly from hardware. + In order to save space in the firmware, the constants for the result decoding are not included on the :mod:`machine.CAN` module. Add the ones that you need from the list below to your program. + + The event codes are:: + + from micropython import const + CAN_ALERT_TX_IDLE = const(0x0001) + CAN_ALERT_TX_SUCCESS = const(0x0002) + CAN_ALERT_BELOW_ERR_WARN = const(0x0004) + CAN_ALERT_ERR_ACTIVE = const(0x0008) + CAN_ALERT_RECOVERY_IN_PROGRESS = const(0x0010) + CAN_ALERT_BUS_RECOVERED = const(0x0020) + CAN_ALERT_ARB_LOST = const(0x0040) + CAN_ALERT_ABOVE_ERR_WARN = const(0x0080) + CAN_ALERT_BUS_ERROR = const(0x0100) + CAN_ALERT_TX_FAILED = const(0x0200) + CAN_ALERT_RX_QUEUE_FULL = const(0x0400) + CAN_ALERT_ERR_PASS = const(0x0800) + CAN_ALERT_BUS_OFF = const(0x1000) .. method:: CAN.rxcallback(fifo, fun) TODO: NOT YET IMPLEMENTED diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 7dfc8729c6178..f607e140ea95f 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -752,7 +752,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // ESP32 Specific API {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, // CAN_MODE {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL)}, @@ -765,33 +764,11 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING)}, {MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF)}, {MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING)}, - // CAN_BAUDRATE - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k)}, - {MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M)}, // CAN_FILTER_MODE {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE)}, {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL)}, {MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS)}, - // CAN_ALERT - {MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS)}, - {MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF)}}; +}; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); // Python object definition From 51f021a893ccde9ac4f30200643a57b3f516ee91 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:39:10 +0100 Subject: [PATCH 140/180] Documentation bugfix --- docs/library/esp32.CAN.rst | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index 6c3ebe2f8679c..7c9152ba801fb 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -14,9 +14,9 @@ Example usage (works without anything connected):: from machine import CAN can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) - can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126)) # set a filter to receive messages with id=123, 124, 125 and 126 - can.send([1,2,3], 123) # send a message with id 123 - can.recv() # receive message + dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can.send([1,2,3], 0x102) # send a message with id 123 + can.recv() # receive message Constructors @@ -45,7 +45,7 @@ Methods - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* will be ignored. Standard speeds are 25, 50, 100, 125, 250, 500, 1000 - *prescaler* is used to set the duration of 1 time quanta; the time quanta - will be the input clock (PCLK1, see :meth:`pyb.freq()`) divided by the prescaler + will be the input clock divided by the prescaler - *sjw* is the resynchronisation jump width in units of the time quanta; it can be 1, 2, 3, 4 - *bs1* defines the location of the sample point in units of the time quanta; @@ -293,25 +293,9 @@ Constants Possible states of the CAN controller returned from :meth:`~CAN.state()`. -.. data:: CAN.LIST16 TODO: - CAN.MASK16 - CAN.LIST32 - CAN.MASK32 +.. data:: CAN.FILTER_RAW_SINGLE + CAN.FILTER_RAW_DUAL + CAN.FILTER_ADDRESS The operation mode of a filter used in :meth:`~CAN.setfilter()`. -.. data:: CAN.ALERT_TX_IDLE - CAN.ALERT_TX_SUCCESS - CAN.ALERT_BELOW_ERR_WARN - CAN.ALERT_ERR_ACTIVE - CAN.ALERT_RECOVERY_IN_PROGRESS - CAN.ALERT_BUS_RECOVERED - CAN.ALERT_ARB_LOST - CAN.ALERT_ABOVE_ERR_WARN - CAN.ALERT_BUS_ERROR - CAN.ALERT_TX_FAILED - CAN.ALERT_RX_QUEUE_FULL - CAN.ALERT_ERR_PASS - CAN.ALERT_BUS_OFF - - Possibile bit position of alert mask returned by :meth:`~CAN.get_alerts()`. From a383e56334546e42f33340e80db272016f8e8d4c Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 9 Jan 2020 22:39:39 +0100 Subject: [PATCH 141/180] removed implemented methods --- docs/library/esp32.CAN.rst | 47 +------------------------------------- ports/esp32/machine_can.c | 28 +---------------------- 2 files changed, 2 insertions(+), 73 deletions(-) diff --git a/docs/library/esp32.CAN.rst b/docs/library/esp32.CAN.rst index 7c9152ba801fb..299e0cc2010f0 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/esp32.CAN.rst @@ -87,7 +87,7 @@ Methods - ``CAN.BUS_OFF`` -- the controller is on but not participating in bus activity (TEC overflowed beyond 255). - ``CAN.RECOVERING`` -- the controller is under recover from bus-off state; - + .. method:: CAN.info([list]) @@ -228,41 +228,7 @@ Methods CAN_ALERT_RX_QUEUE_FULL = const(0x0400) CAN_ALERT_ERR_PASS = const(0x0800) CAN_ALERT_BUS_OFF = const(0x1000) - - -.. method:: CAN.rxcallback(fifo, fun) TODO: NOT YET IMPLEMENTED - - Register a function to be called when a message is accepted into a empty fifo: - - - *fifo* is the receiving fifo. - - *fun* is the function to be called when the fifo becomes non empty. - The callback function takes two arguments the first is the can object it self the second is - a integer that indicates the reason for the callback. - - +--------+------------------------------------------------+ - | Reason | | - +========+================================================+ - | 0 | A message has been accepted into a empty FIFO. | - +--------+------------------------------------------------+ - | 1 | The FIFO is full | - +--------+------------------------------------------------+ - | 2 | A message has been lost due to a full FIFO | - +--------+------------------------------------------------+ - - Example use of rxcallback:: - - def cb0(bus, reason): - print('cb0') - if reason == 0: - print('pending') - if reason == 1: - print('full') - if reason == 2: - print('overflow') - - can = CAN(1, CAN.LOOPBACK) - can.rxcallback(0, cb0) Constants --------- @@ -275,17 +241,6 @@ Constants The mode of the CAN bus used in :meth:`~CAN.init()`. -.. data:: CAN.BAUDRATE_25k - CAN.BAUDRATE_50k - CAN.BAUDRATE_100k - CAN.BAUDRATE_125k - CAN.BAUDRATE_250k - CAN.BAUDRATE_500k - CAN.BAUDRATE_800k - CAN.BAUDRATE_1M - - The baudrate of the CAN bus used in :meth:`~CAN.init()`. - .. data:: CAN.STOPPED CAN.ERROR_ACTIVE CAN.BUS_OFF diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f607e140ea95f..2c674debd3a6b 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -179,7 +179,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { mp_raise_OSError(-status); } - mp_hal_delay_ms(200); // TODO: replace it with a smarter solution + mp_hal_delay_ms(200); status = can_start(); if (status != ESP_OK) { @@ -402,31 +402,6 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) -{ - mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (callback_in == mp_const_none) - { - self->rxcallback = mp_const_none; - } - else if (self->rxcallback != mp_const_none) - { - // Rx call backs has already been initialized - // only the callback function should be changed - self->rxcallback = callback_in; - // TODO: disable interrupt - } - else if (mp_obj_is_callable(callback_in)) - { - self->rxcallback = callback_in; - // TODO: set interrupt - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); - // Clear filters setting STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { @@ -748,7 +723,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { {MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, {MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj)}, {MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj)}, - {MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj)}, // ESP32 Specific API {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, From ac1e238716e9ec8787e1a4fd3d440e898a827593 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 30 Jan 2020 19:01:23 +0100 Subject: [PATCH 142/180] beautify: brackets inline --- ports/esp32/machine_can.c | 227 ++++++++++++-------------------------- 1 file changed, 72 insertions(+), 155 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 2c674debd3a6b..e74636470da93 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -57,15 +57,13 @@ { \ mp_raise_OSError(-status); \ } -typedef enum _filter_mode_t -{ +typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t -{ +typedef struct _machine_can_config_t{ can_timing_config_t timing; can_filter_config_t filter; can_general_config_t general; @@ -73,8 +71,7 @@ typedef struct _machine_can_config_t bool initialized; } machine_can_config_t; -typedef struct _machine_can_obj_t -{ +typedef struct _machine_can_obj_t{ mp_obj_base_t base; machine_can_config_t *config; mp_obj_t rxcallback; @@ -86,8 +83,7 @@ typedef struct _machine_can_obj_t uint16_t num_bus_off; } machine_can_obj_t; -typedef enum _rx_state_t -{ +typedef enum _rx_state_t{ RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, @@ -114,8 +110,7 @@ machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0 STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config = &can_config}; // INTERNAL FUNCTION Return status information -STATIC can_status_info_t _machine_hw_can_get_status() -{ +STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; uint32_t err_code = can_get_status_info(&status); if (err_code != ESP_OK) @@ -126,41 +121,31 @@ STATIC can_status_info_t _machine_hw_can_get_status() } //INTERNAL FUNCTION Populates the filter register according to inputs -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) -{ +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ //Check if bank is allowed - if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)) - { + if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; - if (self->extframe) - { + if (self->extframe){ addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - } - else if (self->config->filter.single_filter) - { + }else if (self->config->filter.single_filter){ addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); mask = ((mask & 0x7FF) << 5); mask |= 0xFFFFF000; preserve_mask = 0; - } - else - { + }else{ addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); mask = ((mask & 0x7FF) << 5); preserve_mask = 0xFFFF << (bank == 0 ? 16 : 0); - if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))) - { + if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))){ // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); preserve_mask = 0; - } - else - { + }else{ addr = addr << (bank == 1 ? 16 : 0); mask = mask << (bank == 1 ? 16 : 0); } @@ -172,17 +157,14 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u } // Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ uint32_t status = can_initiate_recovery(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } mp_hal_delay_ms(200); status = can_start(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } return mp_const_none; @@ -190,39 +172,31 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in){ can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) -{ +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; - if (n_args == 1) - { + if (n_args == 1){ list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - } - else - { - if (!mp_obj_is_type(args[1], &mp_type_list)) - { + }else{ + if (!mp_obj_is_type(args[1], &mp_type_list)){ mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); - if (list->len < 8) - { + if (list->len < 8){ mp_raise_ValueError(NULL); } } @@ -240,12 +214,10 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } return mp_obj_new_int(alerts); @@ -253,24 +225,20 @@ STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); // send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum - { +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum{ ARG_data, ARG_id, ARG_timeout, @@ -293,53 +261,41 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ size_t length; mp_obj_t *items; mp_obj_get_array(args[ARG_data].u_obj, &length, &items); - if (length > 8) - { + if (length > 8){ mp_raise_ValueError("CAN data field too long"); } uint8_t flags = (args[ARG_rtr].u_bool == true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; - if (self->extframe) - { + if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; - } - else - { + }else{ id &= 0x1FF; } - if (self->loopback) - { + if (self->loopback){ flags += CAN_MSG_FLAG_SELF; } can_message_t tx_msg = {.data_length_code = length, .identifier = id, .flags = flags}; - for (uint8_t i = 0; i < length; i++) - { + for (uint8_t i = 0; i < length; i++){ tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) - { + if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING){ int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } return mp_const_none; - } - else - { + }else{ nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); // recv(list=None, *, timeout=5000) -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum - { +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum{ ARG_list, ARG_timeout }; @@ -354,42 +310,34 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ can_message_t rx_message; int status = can_receive(&rx_message, 1); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; mp_obj_t *items; - if (ret_obj == mp_const_none) - { + if (ret_obj == mp_const_none){ ret_obj = mp_obj_new_tuple(4, NULL); items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - } - else - { + }else{ // User should provide a list of length at least 4 to hold the values - if (!mp_obj_is_type(ret_obj, &mp_type_list)) - { + if (!mp_obj_is_type(ret_obj, &mp_type_list)){ mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); - if (list->len < 4) - { + if (list->len < 4){ mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace - if (!mp_obj_is_type(items[3], &mp_type_memoryview)) - { + if (!mp_obj_is_type(items[3], &mp_type_memoryview)){ mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); - if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) - { + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))){ mp_raise_ValueError(NULL); } mv->len = rx_message.data_length_code; @@ -403,8 +351,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in){ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; @@ -425,8 +372,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ enum { ARG_bank, @@ -449,20 +395,16 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if (len != 2) - { + if (len != 2){ mp_raise_ValueError("params shall be a 2-values list"); } uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) - { + if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL){ self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; - } - else - { + }else{ self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } @@ -477,11 +419,9 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) -{ +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind){ machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized) - { + if (self->config->initialized){ qstr mode; switch (self->config->general.mode) { @@ -506,19 +446,15 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p mode, self->loopback, self->extframe); - } - else - { + }else{ mp_printf(print, "CAN Device is not initialized"); } } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) -{ +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args){ machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized) - { + if (self->config->initialized){ ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; } @@ -527,22 +463,18 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); // deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) -{ +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true) - { + if (self->config->initialized != true){ ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } uint32_t status = can_stop(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } status = can_driver_uninstall(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); } self->config->initialized = false; @@ -553,24 +485,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deini // CAN(bus, ...) No argument to get the object // If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args) -{ + size_t n_kw, const mp_obj_t *args){ // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0]) != true) - { + if (mp_obj_is_int(args[0]) != true){ mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) - { + if (can_idx > 1){ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0) - { - if (self->config->initialized) - { + if (n_args > 1 || n_kw > 0){ + if (self->config->initialized){ // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); @@ -588,10 +515,8 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) -{ - enum - { +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ + enum{ ARG_mode, ARG_extframe, ARG_baudrate, @@ -635,8 +560,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool) - { + if (args[ARG_auto_restart].u_bool){ mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); @@ -644,8 +568,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; can_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int) - { + switch ((int)args[ARG_baudrate].u_int){ case 0: timing = &((can_timing_config_t){ .brp = args[ARG_prescaler].u_int, @@ -690,19 +613,13 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg &self->config->general, &self->config->timing, &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); - } - else - { + }else{ status = can_start(); - if (status != ESP_OK) - { + if (status != ESP_OK){ mp_raise_OSError(-status); - } - else - { + }else{ self->config->initialized = true; } } From 8ec3b94f99d0d9a90fee13c6ce5a6f7467339661 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 30 Jan 2020 19:02:17 +0100 Subject: [PATCH 143/180] documentation update: from esp32 specifc module to machine module --- docs/esp32/quickref.rst | 13 ++++++------- docs/library/{esp32.CAN.rst => machine.CAN.rst} | 11 ++++++----- 2 files changed, 12 insertions(+), 12 deletions(-) rename docs/library/{esp32.CAN.rst => machine.CAN.rst} (97%) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index a394097708f81..dbce97a33c9a5 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -406,19 +406,18 @@ ESP32 has two I2S buses with id=0 and id=1 CAN bus ------- -See :ref:`esp32.CAN ` :: +See :ref:`machine.CAN ` :: The CAN driver is based on hardware implementation. Any available output-capablepins can be used for SCL and SDA. The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN - - # construct a CAN bus - bus = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) - - bus.send([0,1,2,3], 0x86) #Send the message - bus.recv() #Read the message sent + BAUDRATE_500k = 500 + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) + dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can.send([1,2,3], 0x102) # send a message with id 123 + can.recv() # receive message Real time clock (RTC) diff --git a/docs/library/esp32.CAN.rst b/docs/library/machine.CAN.rst similarity index 97% rename from docs/library/esp32.CAN.rst rename to docs/library/machine.CAN.rst index 299e0cc2010f0..4b73f185da0ce 100644 --- a/docs/library/esp32.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -1,19 +1,20 @@ -.. currentmodule:: esp32 -.. _esp32.CAN: +.. currentmodule:: machine +.. _machine.CAN: class CAN -- controller area network communication bus ====================================================== CAN implements the standard CAN communications protocol. At the physical level it consists of 2 lines: RX and TX. Note that -to connect the ESP32 to a CAN bus you must use a CAN transceiver -to convert the CAN logic signals from the ESP32 to the correct +to connect the microcontroller to a CAN bus you must use a CAN transceiver +to convert the CAN logic signals from the microcontroller to the correct voltage levels on the bus. Example usage (works without anything connected):: from machine import CAN - can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=CAN.BAUDRATE_500k) + BAUDRATE_500k = 500 + can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 can.send([1,2,3], 0x102) # send a message with id 123 can.recv() # receive message From 27bd66650db40fd40f96bde625d7776cf41ff1de Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Thu, 30 Jan 2020 19:11:00 +0100 Subject: [PATCH 144/180] revert unnecessary changes --- .gitignore | 3 --- docs/library/esp32.rst | 10 +--------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index ca9c98ae476d2..c52f59eec74e6 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,3 @@ user.props # Generated rst files ###################### genrst/ -docs/_build -.vscode -esp-idf diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index b905a916b68f5..7a9b1c055a3c3 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -277,12 +277,4 @@ Constants .. data:: esp32.WAKEUP_ALL_LOW esp32.WAKEUP_ANY_HIGH - Selects the wake level for pins. - -Classes -------- - -.. toctree:: - :maxdepth: 1 - - esp32.CAN.rst + Selects the wake level for pins. \ No newline at end of file From 4ef5a43e326d225efd464c9c3434c504f7e77d95 Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Tue, 4 Feb 2020 23:07:03 +0100 Subject: [PATCH 145/180] code beautify --- ports/esp32/machine_can.c | 190 +++++++++++++++++++------------------- 1 file changed, 93 insertions(+), 97 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index e74636470da93..0974b7d37e32d 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -53,17 +53,16 @@ #define CAN_BAUDRATE_1M 1000 #define ESP_STATUS_CHECK(status) \ - if (status != ESP_OK) \ - { \ + if (status != ESP_OK) { \ mp_raise_OSError(-status); \ } -typedef enum _filter_mode_t{ +typedef enum _filter_mode_t { FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t{ +typedef struct _machine_can_config_t { can_timing_config_t timing; can_filter_config_t filter; can_general_config_t general; @@ -71,7 +70,7 @@ typedef struct _machine_can_config_t{ bool initialized; } machine_can_config_t; -typedef struct _machine_can_obj_t{ +typedef struct _machine_can_obj_t { mp_obj_base_t base; machine_can_config_t *config; mp_obj_t rxcallback; @@ -83,7 +82,7 @@ typedef struct _machine_can_obj_t{ uint16_t num_bus_off; } machine_can_obj_t; -typedef enum _rx_state_t{ +typedef enum _rx_state_t { RX_STATE_FIFO_EMPTY = 0, RX_STATE_MESSAGE_PENDING, RX_STATE_FIFO_FULL, @@ -102,28 +101,25 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = {.general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), - .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), - .timing = CAN_TIMING_CONFIG_25KBITS(), - .initialized = false}; +machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), + .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), + .timing = CAN_TIMING_CONFIG_25KBITS(), + .initialized = false }; -STATIC machine_can_obj_t machine_can_obj = {{&machine_can_type}, .config = &can_config}; +STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; -// INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status(){ can_status_info_t status; uint32_t err_code = can_get_status_info(&status); - if (err_code != ESP_OK) - { + if (err_code != ESP_OK){ mp_raise_OSError(-err_code); } return status; } -//INTERNAL FUNCTION Populates the filter register according to inputs STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ //Check if bank is allowed - if (bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1)){ + if ( bank < 0 && bank > ( (self->extframe && self->config->filter.single_filter) ? 0 : 1 ) ){ mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; @@ -131,21 +127,21 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - }else if (self->config->filter.single_filter){ - addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); + } else if (self->config->filter.single_filter){ + addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); + mask = ( (mask & 0x7FF) << 5 ); mask |= 0xFFFFF000; preserve_mask = 0; - }else{ - addr = (((addr & 0x7FF) << 5) | (rtr ? 0x10 : 0)); - mask = ((mask & 0x7FF) << 5); - preserve_mask = 0xFFFF << (bank == 0 ? 16 : 0); - if ((self->config->filter.acceptance_mask & preserve_mask) == (0xFFFF << (bank == 0 ? 16 : 0))){ + } else { + addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); + mask = ( (mask & 0x7FF) << 5 ); + preserve_mask = 0xFFFF << ( bank == 0 ? 16 : 0 ); + if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ){ // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); preserve_mask = 0; - }else{ + } else { addr = addr << (bank == 1 ? 16 : 0); mask = mask << (bank == 1 ? 16 : 0); } @@ -191,7 +187,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ mp_obj_list_t *list; if (n_args == 1){ list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - }else{ + } else{ if (!mp_obj_is_type(args[1], &mp_type_list)){ mp_raise_TypeError(NULL); } @@ -264,20 +260,20 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ if (length > 8){ mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool == true ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + uint8_t flags = (args[ARG_rtr].u_bool ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; if (self->extframe){ flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; - }else{ + } else { id &= 0x1FF; } if (self->loopback){ flags += CAN_MSG_FLAG_SELF; } - can_message_t tx_msg = {.data_length_code = length, - .identifier = id, - .flags = flags}; + can_message_t tx_msg = { .data_length_code = length, + .identifier = id, + .flags = flags }; for (uint8_t i = 0; i < length; i++){ tx_msg.data[i] = mp_obj_get_int(items[i]); } @@ -287,7 +283,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ mp_raise_OSError(-status); } return mp_const_none; - }else{ + } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); } } @@ -300,8 +296,8 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ ARG_timeout }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_PTR(&mp_const_none_obj)}}, - {MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000}}, + { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, }; // parse args @@ -319,9 +315,9 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_obj_t *items; if (ret_obj == mp_const_none){ ret_obj = mp_obj_new_tuple(4, NULL); - items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; + items = ( (mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj) )->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); - }else{ + } else { // User should provide a list of length at least 4 to hold the values if (!mp_obj_is_type(ret_obj, &mp_type_list)){ mp_raise_TypeError(NULL); @@ -344,7 +340,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ memcpy(mv->items, rx_message.data, rx_message.data_length_code); } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? mp_const_true : mp_const_false; + items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? true : false); items[2] = 0; return ret_obj; } @@ -381,10 +377,10 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args ARG_rtr }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false}}, + { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, }; // parse args @@ -404,17 +400,17 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; - }else{ + } else { self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - ESP_STATUS_CHECK(can_stop()); - ESP_STATUS_CHECK(can_driver_uninstall()); - ESP_STATUS_CHECK(can_driver_install( + ESP_STATUS_CHECK( can_stop() ); + ESP_STATUS_CHECK( can_driver_uninstall() ); + ESP_STATUS_CHECK( can_driver_install( &self->config->general, &self->config->timing, - &self->config->filter)); - ESP_STATUS_CHECK(can_start()); + &self->config->filter) ); + ESP_STATUS_CHECK( can_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -446,7 +442,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p mode, self->loopback, self->extframe); - }else{ + } else { mp_printf(print, "CAN Device is not initialized"); } } @@ -531,18 +527,18 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg ARG_auto_restart }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL}}, - {MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false}}, - {MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER}}, - {MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW}}, - {MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1}}, - {MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2}}, - {MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4}}, - {MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2}}, - {MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5}}, - {MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, + { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, + { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, + { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, + { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -578,28 +574,28 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .triple_sampling = false}); break; case CAN_BAUDRATE_25k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_25KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); break; case CAN_BAUDRATE_50k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_50KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS() ); break; case CAN_BAUDRATE_100k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_100KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS() ); break; case CAN_BAUDRATE_125k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_125KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS() ); break; case CAN_BAUDRATE_250k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_250KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS() ); break; case CAN_BAUDRATE_500k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_500KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS() ); break; case CAN_BAUDRATE_800k: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_800KBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_800KBITS() ); break; case CAN_BAUDRATE_1M: - timing = &((can_timing_config_t)CAN_TIMING_CONFIG_1MBITS()); + timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS() ); break; default: mp_raise_ValueError("Unable to set baudrate"); @@ -612,14 +608,14 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg uint32_t status = can_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t)CAN_FILTER_CONFIG_ACCEPT_ALL()); + &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); if (status != ESP_OK){ mp_raise_OSError(-status); - }else{ + } else { status = can_start(); if (status != ESP_OK){ mp_raise_OSError(-status); - }else{ + } else { self->config->initialized = true; } } @@ -628,37 +624,37 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { // CAN_ATTRIBUTES - {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN)}, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, // Micropython Generic API - {MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj)}, - {MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj)}, - {MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj)}, - {MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj)}, - {MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj)}, - {MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj)}, - {MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj)}, - {MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj)}, - {MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj)}, - {MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj)}, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, // ESP32 Specific API - {MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj)}, - {MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj)}, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, // CAN_MODE - {MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL)}, - {MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10)}, - {MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK)}, - {MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10)}, - {MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY)}, + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, + { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE - {MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED)}, - {MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING)}, - {MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF)}, - {MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING)}, + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, // CAN_FILTER_MODE - {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE)}, - {MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL)}, - {MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS)}, + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, + { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); From 9de1bf03a487fdbbb3056866f164c66a8e4c0bbb Mon Sep 17 00:00:00 2001 From: Salvatore Musumeci Date: Sun, 9 Feb 2020 15:53:13 +0100 Subject: [PATCH 146/180] Beautify --- ports/esp32/machine_can.c | 151 +++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0974b7d37e32d..56c806bd545c2 100644 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -104,30 +104,31 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), .timing = CAN_TIMING_CONFIG_25KBITS(), - .initialized = false }; + .initialized = false + }; STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; -STATIC can_status_info_t _machine_hw_can_get_status(){ +STATIC can_status_info_t _machine_hw_can_get_status() { can_status_info_t status; uint32_t err_code = can_get_status_info(&status); - if (err_code != ESP_OK){ + if (err_code != ESP_OK) { mp_raise_OSError(-err_code); } return status; } -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr){ +STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { //Check if bank is allowed - if ( bank < 0 && bank > ( (self->extframe && self->config->filter.single_filter) ? 0 : 1 ) ){ + if ( bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; - if (self->extframe){ + if (self->extframe) { addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); mask = (mask & 0x1FFFFFFF) << 3 | 0x03; preserve_mask = 0; - } else if (self->config->filter.single_filter){ + } else if (self->config->filter.single_filter) { addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); mask = ( (mask & 0x7FF) << 5 ); mask |= 0xFFFFF000; @@ -136,7 +137,7 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); mask = ( (mask & 0x7FF) << 5 ); preserve_mask = 0xFFFF << ( bank == 0 ? 16 : 0 ); - if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ){ + if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ) { // Other filter accepts all; it will replaced duplicating current filter addr = addr | (addr << 16); mask = mask | (mask << 16); @@ -153,14 +154,14 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u } // Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { uint32_t status = can_initiate_recovery(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } mp_hal_delay_ms(200); status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } return mp_const_none; @@ -168,31 +169,31 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { can_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); // Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ +STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; - if (n_args == 1){ + if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); - } else{ - if (!mp_obj_is_type(args[1], &mp_type_list)){ + } else { + if (!mp_obj_is_type(args[1], &mp_type_list)) { mp_raise_TypeError(NULL); } list = MP_OBJ_TO_PTR(args[1]); - if (list->len < 8){ + if (list->len < 8) { mp_raise_ValueError(NULL); } } @@ -210,10 +211,10 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args){ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } return mp_obj_new_int(alerts); @@ -221,20 +222,20 @@ STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in){ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) { return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) { return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); // send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum{ +STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_id, ARG_timeout, @@ -257,29 +258,30 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ size_t length; mp_obj_t *items; mp_obj_get_array(args[ARG_data].u_obj, &length, &items); - if (length > 8){ + if (length > 8) { mp_raise_ValueError("CAN data field too long"); } uint8_t flags = (args[ARG_rtr].u_bool ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; - if (self->extframe){ + if (self->extframe) { flags += CAN_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; } else { id &= 0x1FF; } - if (self->loopback){ + if (self->loopback) { flags += CAN_MSG_FLAG_SELF; } can_message_t tx_msg = { .data_length_code = length, .identifier = id, - .flags = flags }; - for (uint8_t i = 0; i < length; i++){ + .flags = flags + }; + for (uint8_t i = 0; i < length; i++) { tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING){ + if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } return mp_const_none; @@ -290,8 +292,8 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); // recv(list=None, *, timeout=5000) -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum{ +STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_list, ARG_timeout }; @@ -306,48 +308,48 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ can_message_t rx_message; int status = can_receive(&rx_message, 1); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; mp_obj_t *items; - if (ret_obj == mp_const_none){ + if (ret_obj == mp_const_none) { ret_obj = mp_obj_new_tuple(4, NULL); items = ( (mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj) )->items; items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); } else { // User should provide a list of length at least 4 to hold the values - if (!mp_obj_is_type(ret_obj, &mp_type_list)){ + if (!mp_obj_is_type(ret_obj, &mp_type_list)) { mp_raise_TypeError(NULL); } mp_obj_list_t *list = MP_OBJ_TO_PTR(ret_obj); - if (list->len < 4){ + if (list->len < 4) { mp_raise_ValueError(NULL); } items = list->items; // Fourth element must be a memoryview which we assume points to a // byte-like array which is large enough, and then we resize it inplace - if (!mp_obj_is_type(items[3], &mp_type_memoryview)){ + if (!mp_obj_is_type(items[3], &mp_type_memoryview)) { mp_raise_TypeError(NULL); } mp_obj_array_t *mv = MP_OBJ_TO_PTR(items[3]); - if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))){ + if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { mp_raise_ValueError(NULL); } mv->len = rx_message.data_length_code; memcpy(mv->items, rx_message.data, rx_message.data_length_code); } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0 ? true : false); + items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0); items[2] = 0; return ret_obj; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; @@ -355,9 +357,9 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in){ ESP_STATUS_CHECK(can_stop()); ESP_STATUS_CHECK(can_driver_uninstall()); ESP_STATUS_CHECK(can_driver_install( - &self->config->general, - &self->config->timing, - &self->config->filter)); + &self->config->general, + &self->config->timing, + &self->config->filter)); ESP_STATUS_CHECK(can_start()); return mp_const_none; } @@ -368,7 +370,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_ // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ +STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_bank, @@ -391,12 +393,12 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args size_t len; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if (len != 2){ + if (len != 2) { mp_raise_ValueError("params shall be a 2-values list"); } uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL){ + if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) { self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; @@ -407,17 +409,17 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args ESP_STATUS_CHECK( can_stop() ); ESP_STATUS_CHECK( can_driver_uninstall() ); ESP_STATUS_CHECK( can_driver_install( - &self->config->general, - &self->config->timing, - &self->config->filter) ); + &self->config->general, + &self->config->timing, + &self->config->filter) ); ESP_STATUS_CHECK( can_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind){ +STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized){ + if (self->config->initialized) { qstr mode; switch (self->config->general.mode) { @@ -448,9 +450,9 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } // init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args){ +STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized){ + if (self->config->initialized) { ESP_LOGW(DEVICE_NAME, "Device is already initialized"); return mp_const_none; } @@ -459,18 +461,18 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); // deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in){ +STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true){ + if (self->config->initialized != true) { ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } uint32_t status = can_stop(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } status = can_driver_uninstall(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } self->config->initialized = false; @@ -481,19 +483,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deini // CAN(bus, ...) No argument to get the object // If no arguments are provided, the initialized object will be returned mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args){ + size_t n_kw, const mp_obj_t *args) { // check arguments mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0]) != true){ + if (mp_obj_is_int(args[0]) != true) { mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1){ + if (can_idx > 1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); } machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0){ - if (self->config->initialized){ + if (n_args > 1 || n_kw > 0) { + if (self->config->initialized) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); @@ -511,8 +513,8 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, } // init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args){ - enum{ +STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_extframe, ARG_baudrate, @@ -556,7 +558,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool){ + if (args[ARG_auto_restart].u_bool) { mp_raise_NotImplementedError("Auto-restart not supported"); } can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); @@ -564,14 +566,15 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; can_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int){ + switch ((int)args[ARG_baudrate].u_int) { case 0: - timing = &((can_timing_config_t){ + timing = &((can_timing_config_t) { .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, .tseg_2 = args[ARG_bs1].u_int, - .triple_sampling = false}); + .triple_sampling = false + }); break; case CAN_BAUDRATE_25k: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); @@ -606,14 +609,14 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->baudrate = args[ARG_baudrate].u_int; uint32_t status = can_driver_install( - &self->config->general, - &self->config->timing, - &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); - if (status != ESP_OK){ + &self->config->general, + &self->config->timing, + &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); + if (status != ESP_OK) { mp_raise_OSError(-status); } else { status = can_start(); - if (status != ESP_OK){ + if (status != ESP_OK) { mp_raise_OSError(-status); } else { self->config->initialized = true; From efc173f5b0e85939df8bf61dbc83acf2ee61936e Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 02:35:29 -0700 Subject: [PATCH 147/180] esp32: modmachine.c Fix after merge from master --- ports/esp32/modmachine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 69a96e7547d91..6ff56d11281f2 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -299,7 +299,8 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, #endif - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) }, From 1b7e3b8b343acb7b682f55dfc88453d97db9cde6 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 02:38:35 -0700 Subject: [PATCH 148/180] esp32: Add machine_can.c to CMakeLists.txt --- ports/esp32/main/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/esp32/main/CMakeLists.txt b/ports/esp32/main/CMakeLists.txt index 0e7d6ff250eba..f7350fee6a216 100644 --- a/ports/esp32/main/CMakeLists.txt +++ b/ports/esp32/main/CMakeLists.txt @@ -63,6 +63,7 @@ set(MICROPY_SOURCE_PORT ${PROJECT_DIR}/machine_i2s.c ${PROJECT_DIR}/machine_pwm.c ${PROJECT_DIR}/machine_uart.c + ${PROJECT_DIR}/machine_can.c ${PROJECT_DIR}/modmachine.c ${PROJECT_DIR}/modnetwork.c ${PROJECT_DIR}/network_lan.c From 7a8fe5eea939ae144fdbb8d76dc59fec6c4b62d7 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 05:09:01 -0700 Subject: [PATCH 149/180] esp32:machine_can Merge https://github.com/nos86/micropython/tree/esp32-can-driver and https://github.com/nos86/micropython/tree/esp32-can-driver-harmonization --- ports/esp32/machine_can.c | 104 +++++++++++++++++++------------------- ports/esp32/machine_can.h | 83 ++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 53 deletions(-) mode change 100644 => 100755 ports/esp32/machine_can.c create mode 100755 ports/esp32/machine_can.h diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c old mode 100644 new mode 100755 index 56c806bd545c2..3500f2618cea8 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -1,6 +1,7 @@ /* The MIT License (MIT) * * Copyright (c) 2019 Musumeci Salvatore + * Copyright (c) 2021 Ihor Nehrutsa * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -37,58 +38,10 @@ #include "esp_err.h" #include "esp_log.h" -#include "modmachine.h" +#include #if MICROPY_HW_ENABLE_CAN -#define DEVICE_NAME "CAN" - -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 - -#define ESP_STATUS_CHECK(status) \ - if (status != ESP_OK) { \ - mp_raise_OSError(-status); \ - } -typedef enum _filter_mode_t { - FILTER_RAW_SINGLE = 0, - FILTER_RAW_DUAL, - FILTER_ADDRESS -} filter_mode_t; - -typedef struct _machine_can_config_t { - can_timing_config_t timing; - can_filter_config_t filter; - can_general_config_t general; - uint16_t baudrate; - bool initialized; -} machine_can_config_t; - -typedef struct _machine_can_obj_t { - mp_obj_base_t base; - machine_can_config_t *config; - mp_obj_t rxcallback; - byte rx_state; - bool extframe : 1; - bool loopback : 1; - uint16_t num_error_warning; //FIXME: populate this value somewhere - uint16_t num_error_passive; - uint16_t num_bus_off; -} machine_can_obj_t; - -typedef enum _rx_state_t { - RX_STATE_FIFO_EMPTY = 0, - RX_STATE_MESSAGE_PENDING, - RX_STATE_FIFO_FULL, - RX_STATE_FIFO_OVERFLOW, -} rx_state_t; - // Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) @@ -109,6 +62,7 @@ machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; +// INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status() { can_status_info_t status; uint32_t err_code = can_get_status_info(&status); @@ -118,6 +72,7 @@ STATIC can_status_info_t _machine_hw_can_get_status() { return status; } +//INTERNAL FUNCTION Populates the filter register according to inputs STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { //Check if bank is allowed if ( bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { @@ -159,7 +114,7 @@ STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { if (status != ESP_OK) { mp_raise_OSError(-status); } - mp_hal_delay_ms(200); + mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution status = can_start(); if (status != ESP_OK) { mp_raise_OSError(-status); @@ -348,6 +303,25 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); +STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + mp_raise_NotImplementedError("IRQ not supported yet"); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (callback_in == mp_const_none) { + self->rxcallback = mp_const_none; + } else if (self->rxcallback != mp_const_none) { + // Rx call backs has already been initialized + // only the callback function should be changed + self->rxcallback = callback_in; + // TODO: disable interrupt + } else if (mp_obj_is_callable(callback_in)) { + self->rxcallback = callback_in; + // TODO: set interrupt + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); + // Clear filters setting STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -379,9 +353,9 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args ARG_rtr }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT }, - { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, }; @@ -639,6 +613,7 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj) }, { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, // ESP32 Specific API { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, @@ -654,10 +629,33 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + // CAN_BAUDRATE + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, + { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, // CAN_FILTER_MODE { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, + // CAN_ALERT + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h new file mode 100755 index 0000000000000..a79a23271345a --- /dev/null +++ b/ports/esp32/machine_can.h @@ -0,0 +1,83 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Musumeci Salvatore + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ESP32_CAN_H +#define MICROPY_INCLUDED_ESP32_CAN_H + +#include "modmachine.h" + +#include "py/obj.h" + +#if MICROPY_HW_ENABLE_CAN + +#define DEVICE_NAME "CAN" + +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 + +#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} +typedef enum _filter_mode_t{ + FILTER_RAW_SINGLE = 0, + FILTER_RAW_DUAL, + FILTER_ADDRESS +} filter_mode_t; + +typedef struct _machine_can_config_t { + can_timing_config_t timing; + can_filter_config_t filter; + can_general_config_t general; + uint16_t baudrate; + bool initialized; +} machine_can_config_t; + +typedef struct _machine_can_obj_t { + mp_obj_base_t base; + machine_can_config_t *config; + mp_obj_t rxcallback; + byte rx_state; + bool extframe : 1; + bool loopback : 1; + uint16_t num_error_warning; //FIXME: populate this value somewhere + uint16_t num_error_passive; + uint16_t num_bus_off; +} machine_can_obj_t; + +typedef enum _rx_state_t { + RX_STATE_FIFO_EMPTY = 0, + RX_STATE_MESSAGE_PENDING, + RX_STATE_FIFO_FULL, + RX_STATE_FIFO_OVERFLOW, +} rx_state_t; + +extern const mp_obj_type_t machine_can_type; + +#endif // MICROPY_HW_ENABLE_CAN +#endif // MICROPY_INCLUDED_ESP32_CAN_H From f467fc1bf56375dc7ddeeb3d080ee8de4940053f Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 06:06:14 -0700 Subject: [PATCH 150/180] esp32:CAN Add TWAI block diagram Fix SCL, SDA to TX, RX --- docs/esp32/img/twai_blockdiag.png | Bin 0 -> 10157 bytes docs/esp32/quickref.rst | 26 ++++++++++++++++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) create mode 100755 docs/esp32/img/twai_blockdiag.png diff --git a/docs/esp32/img/twai_blockdiag.png b/docs/esp32/img/twai_blockdiag.png new file mode 100755 index 0000000000000000000000000000000000000000..183352ea610de1aa53b149730db94cf068661609 GIT binary patch literal 10157 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 class:: i2c.writeto(0x3a, '12') # write '12' to device with address 0x3a buf = bytearray(10) # create a buffer with 10 bytes - i2c.writeto(0x3a, buf) # write the given buffer to the peripheral + i2c.writeto(0x3a, buf) # write the given buffer to the slave + +CAN bus +------- + +See :ref:`machine.CAN ` :: + +The CAN driver is based on hardware implementation. +Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT signal lines. +.. image:: img/twai_blockdiag.png +The driver is accessed via the :ref:`machine.CAN ` class:: Hardware I2C bus ---------------- @@ -391,14 +401,14 @@ I2S bus See :ref:`machine.I2S `. :: from machine import I2S, Pin - + i2s = I2S(0, sck=Pin(13), ws=Pin(14), sd=Pin(34), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object i2s.write(buf) # write buffer of audio samples to I2S device - + i2s = I2S(1, sck=Pin(33), ws=Pin(25), sd=Pin(32), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object i2s.readinto(buf) # fill buffer with audio samples from I2S device - -The I2S class is currently available as a Technical Preview. During the preview period, feedback from + +The I2S class is currently available as a Technical Preview. During the preview period, feedback from users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. ESP32 has two I2S buses with id=0 and id=1 @@ -408,8 +418,8 @@ CAN bus See :ref:`machine.CAN ` :: -The CAN driver is based on hardware implementation. -Any available output-capablepins can be used for SCL and SDA. +The CAN driver is based on hardware implementation. +Any available output-capablepins can be used for SCL and SDA. The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN @@ -418,7 +428,7 @@ The driver is accessed via the :ref:`machine.CAN ` class:: dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 can.send([1,2,3], 0x102) # send a message with id 123 can.recv() # receive message - + Real time clock (RTC) --------------------- From ad45ac1466854ede99e91166507314ce0d32e168 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 06:49:06 -0700 Subject: [PATCH 151/180] esp32:machine_can Replace ESP_STATUS_CHECK() to check_esp_err() --- ports/esp32/machine_can.c | 16 ++++++++-------- ports/esp32/machine_can.h | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 3500f2618cea8..77974f437a91a 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -328,13 +328,13 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; self->config->filter.acceptance_mask = 0xFFFFFFFF; - ESP_STATUS_CHECK(can_stop()); - ESP_STATUS_CHECK(can_driver_uninstall()); - ESP_STATUS_CHECK(can_driver_install( + check_esp_err(can_stop()); + check_esp_err(can_driver_uninstall()); + check_esp_err(can_driver_install( &self->config->general, &self->config->timing, &self->config->filter)); - ESP_STATUS_CHECK(can_start()); + check_esp_err(can_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); @@ -380,13 +380,13 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - ESP_STATUS_CHECK( can_stop() ); - ESP_STATUS_CHECK( can_driver_uninstall() ); - ESP_STATUS_CHECK( can_driver_install( + check_esp_err( can_stop() ); + check_esp_err( can_driver_uninstall() ); + check_esp_err( can_driver_install( &self->config->general, &self->config->timing, &self->config->filter) ); - ESP_STATUS_CHECK( can_start() ); + check_esp_err( can_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index a79a23271345a..9ed50a504f791 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -43,7 +43,6 @@ #define CAN_BAUDRATE_800k 800 #define CAN_BAUDRATE_1M 1000 -#define ESP_STATUS_CHECK(status) if (status != ESP_OK){ mp_raise_OSError(-status);} typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, From d4fe9bf2a920e426c2b97d1c079a087131068f78 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 07:10:19 -0700 Subject: [PATCH 152/180] esp32:machine_can.c Replace mp_raise_OSError(-status) to check_esp_err() --- ports/esp32/machine_can.c | 57 +++++++++------------------------------ 1 file changed, 13 insertions(+), 44 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 77974f437a91a..428fb6132f2d9 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -65,10 +65,7 @@ STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can // INTERNAL FUNCTION Return status information STATIC can_status_info_t _machine_hw_can_get_status() { can_status_info_t status; - uint32_t err_code = can_get_status_info(&status); - if (err_code != ESP_OK) { - mp_raise_OSError(-err_code); - } + check_esp_err(can_get_status_info(&status)); return status; } @@ -110,15 +107,9 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { - uint32_t status = can_initiate_recovery(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_initiate_recovery()); mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution - status = can_start(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); @@ -168,10 +159,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machin // Get Alert info STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; - uint32_t status = can_read_alerts(&alerts, 0); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_read_alerts(&alerts, 0)); return mp_obj_new_int(alerts); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); @@ -235,10 +223,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ tx_msg.data[i] = mp_obj_get_int(items[i]); } if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { - int status = can_transmit(&tx_msg, args[ARG_timeout].u_int); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_transmit(&tx_msg, args[ARG_timeout].u_int)); return mp_const_none; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); @@ -262,10 +247,8 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); can_message_t rx_message; - int status = can_receive(&rx_message, 1); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + //int status = + check_esp_err(can_receive(&rx_message, 1)); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; @@ -441,14 +424,8 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { ESP_LOGW(DEVICE_NAME, "Device is not initialized"); return mp_const_none; } - uint32_t status = can_stop(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } - status = can_driver_uninstall(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } + check_esp_err(can_stop()); + check_esp_err(can_driver_uninstall()); self->config->initialized = false; return mp_const_none; } @@ -582,20 +559,12 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - uint32_t status = can_driver_install( + check_esp_err(can_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL() ); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } else { - status = can_start(); - if (status != ESP_OK) { - mp_raise_OSError(-status); - } else { - self->config->initialized = true; - } - } + &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL())); + check_esp_err(can_start()); + self->config->initialized = true; return mp_const_none; } From 5a27f0ffa669462df95c58dfbcd63b9af3170031 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 07:12:44 -0700 Subject: [PATCH 153/180] Update esp32.rst Remove duplicate lines. --- docs/library/esp32.rst | 50 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 7a9b1c055a3c3..e3c25d2653db1 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -277,4 +277,52 @@ Constants .. data:: esp32.WAKEUP_ALL_LOW esp32.WAKEUP_ANY_HIGH - Selects the wake level for pins. \ No newline at end of file + Selects the wake level for pins. + +Non-Volatile Storage +-------------------- + +This class gives access to the Non-Volatile storage managed by ESP-IDF. The NVS is partitioned +into namespaces and each namespace contains typed key-value pairs. The keys are strings and the +values may be various integer types, strings, and binary blobs. The driver currently only +supports 32-bit signed integers and blobs. + +.. warning:: + + Changes to NVS need to be committed to flash by calling the commit method. Failure + to call commit results in changes being lost at the next reset. + +.. class:: NVS(namespace) + + Create an object providing access to a namespace (which is automatically created if not + present). + +.. method:: NVS.set_i32(key, value) + + Sets a 32-bit signed integer value for the specified key. Remember to call *commit*! + +.. method:: NVS.get_i32(key) + + Returns the signed integer value for the specified key. Raises an OSError if the key does not + exist or has a different type. + +.. method:: NVS.set_blob(key, value) + + Sets a binary blob value for the specified key. The value passed in must support the buffer + protocol, e.g. bytes, bytearray, str. (Note that esp-idf distinguishes blobs and strings, this + method always writes a blob even if a string is passed in as value.) + Remember to call *commit*! + +.. method:: NVS.get_blob(key, buffer) + + Reads the value of the blob for the specified key into the buffer, which must be a bytearray. + Returns the actual length read. Raises an OSError if the key does not exist, has a different + type, or if the buffer is too small. + +.. method:: NVS.erase_key(key) + + Erases a key-value pair. + +.. method:: NVS.commit() + + Commits changes made by *set_xxx* methods to flash. From 773b4569afe6f86f989bdffc3b435d145c1be864 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 07:15:22 -0700 Subject: [PATCH 154/180] Update machine.CAN.rst Correct GPOI connected to CAN signal lines. --- docs/library/machine.CAN.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst index 4b73f185da0ce..f481ad7f1b69d 100644 --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -53,8 +53,10 @@ Methods it can be between 1 and 1024 inclusive - *bs2* defines the location of the transmit point in units of the time quanta; it can be between 1 and 16 inclusive - - *tx_io* defines the gpio used for transmission - - *rx_io* defines the gpio used for receiving + - *tx* defines the gpio used for transmission + - *rx* defines the gpio used for receiving + - *bus_off* defines the gpio used for BUS-OFF signal line(optional) + - *clkout* defines the gpio used for CLKOUT signal line(optional) - *tx_queue* defines the number of waiting tx messages can be stored - *rx_queue* defines the number of received messages can be stored - *auto_restart* sets whether the controller will automatically try and restart From bd9fea83f1dfd80b669b4160c3aa0dd12945058c Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 11 Jun 2021 16:26:51 -0700 Subject: [PATCH 155/180] esp32: CAN docs fix --- docs/esp32/quickref.rst | 34 ++++------------------------------ docs/library/machine.CAN.rst | 28 ++++++++++++++-------------- docs/library/machine.rst | 2 +- 3 files changed, 19 insertions(+), 45 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index dc3d4c4702808..d0810ddb88661 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -363,16 +363,6 @@ accessed via the :ref:`machine.SoftI2C ` class:: buf = bytearray(10) # create a buffer with 10 bytes i2c.writeto(0x3a, buf) # write the given buffer to the slave -CAN bus -------- - -See :ref:`machine.CAN ` :: - -The CAN driver is based on hardware implementation. -Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT signal lines. -.. image:: img/twai_blockdiag.png -The driver is accessed via the :ref:`machine.CAN ` class:: - Hardware I2C bus ---------------- @@ -395,31 +385,16 @@ has the same methods as software I2C above:: i2c = I2C(0) i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000) -I2S bus -------- - -See :ref:`machine.I2S `. :: - - from machine import I2S, Pin - - i2s = I2S(0, sck=Pin(13), ws=Pin(14), sd=Pin(34), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object - i2s.write(buf) # write buffer of audio samples to I2S device - - i2s = I2S(1, sck=Pin(33), ws=Pin(25), sd=Pin(32), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object - i2s.readinto(buf) # fill buffer with audio samples from I2S device - -The I2S class is currently available as a Technical Preview. During the preview period, feedback from -users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. - -ESP32 has two I2S buses with id=0 and id=1 - CAN bus ------- See :ref:`machine.CAN ` :: The CAN driver is based on hardware implementation. -Any available output-capablepins can be used for SCL and SDA. +Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT signal lines. + +.. image:: img/twai_blockdiag.png + The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN @@ -429,7 +404,6 @@ The driver is accessed via the :ref:`machine.CAN ` class:: can.send([1,2,3], 0x102) # send a message with id 123 can.recv() # receive message - Real time clock (RTC) --------------------- diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst index f481ad7f1b69d..1e025b7fa99f7 100644 --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -124,20 +124,20 @@ Methods The first element will be the id to filter and the second element will be the mask to apply. mask bit implementation considers 1 as a don't care state and 0 as a check state. - +----------------------+----------------------------------------------+ - |*mode* |contents of *params* array | - +======================+==============================================+ - |CAN.FILTER_RAW_SINGLE | *params* will be copied in hardware variable | - | | and single_filter_mode will be selected | - | | In this mode, *bank* will be ignored | - +----------------------+----------------------------------------------+ - |CAN.FILTER_RAW_DUAL | *params* will be copied in hardware variable | - | | and single_filter_mode will be cleared | - | | In this mode, *bank* will be ignored | - +----------------------+----------------------------------------------+ - |CAN.FILTER_ADDRESS | *params* will be set in hardware registers | - | | according to *bank* selection | - +----------------------+----------------------------------------------+ + +-----------------------+----------------------------------------------+ + | *mode* | contents of *params* array | + +=======================+==============================================+ + | CAN.FILTER_RAW_SINGLE | *params* will be copied in hardware variable | + | | and single_filter_mode will be selected | + | | In this mode, *bank* will be ignored | + +-----------------------+----------------------------------------------+ + | CAN.FILTER_RAW_DUAL | *params* will be copied in hardware variable | + | | and single_filter_mode will be cleared | + | | In this mode, *bank* will be ignored | + +-----------------------+----------------------------------------------+ + | CAN.FILTER_ADDRESS | *params* will be set in hardware registers | + | | according to *bank* selection | + +-----------------------+----------------------------------------------+ - *rtr* is bool that states if a filter should accept a remote transmission request message. If this argument is not given then it defaults to ``False``. diff --git a/docs/library/machine.rst b/docs/library/machine.rst index c2a6b39001626..5f45168ed6972 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -203,7 +203,7 @@ Classes machine.UART.rst machine.SPI.rst machine.I2C.rst - machine.I2S.rst + machine.I2S.rst machine.RTC.rst machine.Timer.rst machine.WDT.rst From 834d96636d3ee2dd9ebbeb8cb82bfc777de49498 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Tue, 15 Jun 2021 18:43:21 +0300 Subject: [PATCH 156/180] .gitignore: Add docs/_build directory under Windows --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c52f59eec74e6..5d668f7e3e76a 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ # Build directories ###################### build/ +_build/ build-*/ # Test failure outputs From 012ccba9f65a6b396c6248fffb0c7bf11e0350c6 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Mon, 14 Jun 2021 14:59:01 -0700 Subject: [PATCH 157/180] docs: machine.CAN.rst: Add CAN modes images. --- docs/library/img/can_mode_listen_only.png | Bin 0 -> 3572 bytes docs/library/img/can_mode_loopback.png | Bin 0 -> 3669 bytes docs/library/img/can_mode_normal.png | Bin 0 -> 3513 bytes docs/library/img/can_mode_silent.png | Bin 0 -> 3632 bytes docs/library/img/can_mode_silent_loopback.png | Bin 0 -> 3646 bytes docs/library/machine.CAN.rst | 40 ++++++++++++------ 6 files changed, 28 insertions(+), 12 deletions(-) create mode 100755 docs/library/img/can_mode_listen_only.png create mode 100755 docs/library/img/can_mode_loopback.png create mode 100755 docs/library/img/can_mode_normal.png create mode 100755 docs/library/img/can_mode_silent.png create mode 100755 docs/library/img/can_mode_silent_loopback.png mode change 100644 => 100755 docs/library/machine.CAN.rst diff --git a/docs/library/img/can_mode_listen_only.png b/docs/library/img/can_mode_listen_only.png new file mode 100755 index 0000000000000000000000000000000000000000..45fb05f57f62c3429b2c4ba1cf67336b71035718 GIT binary patch literal 3572 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 AvH$=8 literal 0 HcmV?d00001 diff --git a/docs/library/img/can_mode_loopback.png b/docs/library/img/can_mode_loopback.png new file mode 100755 index 0000000000000000000000000000000000000000..73c3290fc5864a75e951f8af85389ccdc503969e GIT binary patch literal 3669 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 literal 0 HcmV?d00001 diff --git a/docs/library/img/can_mode_normal.png b/docs/library/img/can_mode_normal.png new file mode 100755 index 0000000000000000000000000000000000000000..4ac218a2aafe1dd3567ed8778b245d6dd97e7575 GIT binary patch literal 3513 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 UXY@q@FL{u;skKR+k!Rw+0hLWxivR!s literal 0 HcmV?d00001 diff --git a/docs/library/img/can_mode_silent.png b/docs/library/img/can_mode_silent.png new file mode 100755 index 0000000000000000000000000000000000000000..5b74491be0bfe1a0468dedb7b2b9ce1cf5c6ac41 GIT binary patch literal 3632 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 UDQ)f#{7!%{Cf3H)hHlaS1ADxUtN;K2 literal 0 HcmV?d00001 diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst old mode 100644 new mode 100755 index 1e025b7fa99f7..8ca920fbbfafd --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -25,7 +25,7 @@ Constructors .. class:: machine.CAN(bus, ...) - Construct a CAN object on the given bus. *bus* can be 0 or 1 (for compatibility with STM32). It will point at the same device + Construct a CAN object on the given bus(controller). *bus* can be 0 or 1 for STM32 and 0 for ESP32. With no additional parameters, the CAN object is created but not initialised (it has the settings from the last initialisation of the bus, if any). If extra arguments are given, the bus is initialised. @@ -73,7 +73,7 @@ Methods Force a software restart of the CAN controller without resetting its configuration. - + If the controller enters the bus-off state then it will no longer participate in bus activity. If the controller is not configured to automatically restart (see :meth:`~CAN.init()`) then this method can be used to trigger a restart, @@ -114,13 +114,13 @@ Methods - number of pending RX messages - Reserved -.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) +.. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) Configure a filter bank: - *bank* is the filter bank that is to be configured (0 for extended, 0 or 1 for standard msg) - *mode* is the mode the filter should operate in. - - *params* is an array of two values that defines the filter. + - *params* is an array of two values that defines the filter. The first element will be the id to filter and the second element will be the mask to apply. mask bit implementation considers 1 as a don't care state and 0 as a check state. @@ -139,8 +139,8 @@ Methods | | according to *bank* selection | +-----------------------+----------------------------------------------+ - - *rtr* is bool that states if a filter should accept a remote transmission request message. - If this argument is not given then it defaults to ``False``. + - *rtr* is bool that states if a filter should accept a remote transmission request message. + If this argument is not given then it defaults to ``False``. .. method:: CAN.clearfilter(bank) @@ -180,7 +180,7 @@ Methods buf = bytearray(8) lst = [0, 0, 0, memoryview(buf)] # No heap memory is allocated in the following call - can.recv(0, lst) + can.recv(lst, timeout=0) .. method:: CAN.send(data, id, \*, timeout=0, rtr=False) @@ -194,10 +194,10 @@ Methods of *data* is used to fill in the DLC slot of the frame; the actual bytes in *data* are unused. - If timeout is 0 the message is placed in a buffer and the method returns - immediately. If all three buffers are in use an exception is thrown. - If timeout is not 0, the method waits until the message is transmitted. - If the message can't be transmitted within the specified time an exception + If timeout is 0 the message is placed in a buffer and the method returns + immediately. If all three buffers are in use an exception is thrown. + If timeout is not 0, the method waits until the message is transmitted. + If the message can't be transmitted within the specified time an exception is thrown. Return value: ``None``. @@ -208,7 +208,7 @@ Methods .. method:: CAN.clear_rx_queue() - Clear all messages from receiving queue. + Clear all messages from receiving queue. .. method:: CAN.get_alerts() @@ -242,8 +242,24 @@ Constants CAN.SILENT_LOOPBACK CAN.LISTEN_ONLY + The mode of the CAN bus used in :meth:`~CAN.init()`. + +---------------------+---------------------------------------------+-------+-------+ + | *mode* | \ | STM32 | ESP32 | + +=====================+=============================================+=======+=======+ + | CAN.NORMAL | .. image:: img/can_mode_normal.png | + | + | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.LOOPBACK | .. image:: img/can_mode_loopback.png | + | + | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.SILENT | .. image:: img/can_mode_silent.png | + | + | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.SILENT_LOOPBACK | .. image:: img/can_mode_silent_loopback.png | + | | + +---------------------+---------------------------------------------+-------+-------+ + | CAN.LISTEN_ONLY | .. image:: img/can_mode_listen_only.png | | + | + +---------------------+---------------------------------------------+-------+-------+ + + .. data:: CAN.STOPPED CAN.ERROR_ACTIVE CAN.BUS_OFF From 5e8df297a4ff82b1aa0aa3901f8c9686edd7ff6d Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:32:32 +0300 Subject: [PATCH 158/180] ESP32: machine_can.c: Remove meaningless comparison --- ports/esp32/machine_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 428fb6132f2d9..0f9d403b17ede 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -72,7 +72,7 @@ STATIC can_status_info_t _machine_hw_can_get_status() { //INTERNAL FUNCTION Populates the filter register according to inputs STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { //Check if bank is allowed - if ( bank < 0 && bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { + if (bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { mp_raise_ValueError("CAN filter parameter error"); } uint32_t preserve_mask; From 870d451f285296a53a53df54c8ee554cfa325f34 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:36:21 +0300 Subject: [PATCH 159/180] ESP32: machine_can.c: Convert timeout in ms to RTOS ticks pdMS_TO_TICKS() --- ports/esp32/machine_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 0f9d403b17ede..f9d897eb97814 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -223,7 +223,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ tx_msg.data[i] = mp_obj_get_int(items[i]); } if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { - check_esp_err(can_transmit(&tx_msg, args[ARG_timeout].u_int)); + check_esp_err(can_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); return mp_const_none; } else { nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); @@ -248,7 +248,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ can_message_t rx_message; //int status = - check_esp_err(can_receive(&rx_message, 1)); + check_esp_err(can_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; From 954a0999048cfc02bc4523b730ceda7f1aa2bdb2 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:46:54 +0300 Subject: [PATCH 160/180] ESP32: machine_can.c: Simplify error messages --- ports/esp32/machine_can.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index f9d897eb97814..e0084d54511ee 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -226,7 +226,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ check_esp_err(can_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); return mp_const_none; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "CAN Device is not ready")); + mp_raise_msg(&mp_type_RuntimeError, "Device is not ready"); } } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); @@ -402,7 +402,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p self->loopback, self->extframe); } else { - mp_printf(print, "CAN Device is not initialized"); + mp_printf(print, "Device is not initialized"); } } @@ -410,7 +410,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized) { - ESP_LOGW(DEVICE_NAME, "Device is already initialized"); + mp_raise_msg(&mp_type_RuntimeError, "Device is already initialized"); return mp_const_none; } return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); @@ -421,7 +421,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_ini STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { const machine_can_obj_t *self = &machine_can_obj; if (self->config->initialized != true) { - ESP_LOGW(DEVICE_NAME, "Device is not initialized"); + mp_raise_msg(&mp_type_RuntimeError, "Device is not initialized"); return mp_const_none; } check_esp_err(can_stop()); @@ -441,15 +441,15 @@ mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, mp_raise_TypeError("bus must be a number"); } mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx > 1) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx)); + if (can_idx != 0) { + mp_raise_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx); } machine_can_obj_t *self = &machine_can_obj; if (n_args > 1 || n_kw > 0) { if (self->config->initialized) { // The caller is requesting a reconfiguration of the hardware // this can only be done if the hardware is in init mode - ESP_LOGW(DEVICE_NAME, "Device is going to be reconfigured"); + //mp_raise_msg(&mp_type_RuntimeError, "Device is going to be reconfigured"); machine_hw_can_deinit(&self); } self->rxcallback = mp_const_none; From 7908d714e33dbcc9a988b7a15401529c8f243c7e Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:50:44 +0300 Subject: [PATCH 161/180] ESP32: machine_can.c: Use LOOPBACK_MASK instead of magic 0x10 --- ports/esp32/machine_can.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index e0084d54511ee..8140b776ab1d1 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -42,6 +42,8 @@ #if MICROPY_HW_ENABLE_CAN +#define LOOPBACK_MASK 0x10 + // Default baudrate: 500kb #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) @@ -507,7 +509,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; self->config->general.clkout_divider = 0; - self->loopback = ((args[ARG_mode].u_int & 0x10) > 0); + self->loopback = ((args[ARG_mode].u_int & LOOPBACK_MASK) > 0); self->extframe = args[ARG_extframe].u_bool; if (args[ARG_auto_restart].u_bool) { mp_raise_NotImplementedError("Auto-restart not supported"); @@ -589,9 +591,9 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | 0x10) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | LOOPBACK_MASK) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, - { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | 0x10) }, +// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, From 519ee682e4cf4c182471c9381c0ad8dfc5644c52 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 23:58:39 +0300 Subject: [PATCH 162/180] ESP32: machine_can.c: Use direct baudrate values in bit/s instead of CAN_BAUDRATE_Xk const's --- ports/esp32/machine_can.c | 25 ++++++++----------------- ports/esp32/machine_can.h | 11 +---------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 8140b776ab1d1..b65cbaf49b5ed 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -529,28 +529,28 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .triple_sampling = false }); break; - case CAN_BAUDRATE_25k: + case 25000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); break; - case CAN_BAUDRATE_50k: + case 50000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS() ); break; - case CAN_BAUDRATE_100k: + case 100000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS() ); break; - case CAN_BAUDRATE_125k: + case 125000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS() ); break; - case CAN_BAUDRATE_250k: + case 250000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS() ); break; - case CAN_BAUDRATE_500k: + case 500000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS() ); break; - case CAN_BAUDRATE_800k: + case 800000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_800KBITS() ); break; - case CAN_BAUDRATE_1M: + case 1000000: timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS() ); break; default: @@ -600,15 +600,6 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, - // CAN_BAUDRATE - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_25k), MP_ROM_INT(CAN_BAUDRATE_25k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_50k), MP_ROM_INT(CAN_BAUDRATE_50k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_100k), MP_ROM_INT(CAN_BAUDRATE_100k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_125k), MP_ROM_INT(CAN_BAUDRATE_125k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_250k), MP_ROM_INT(CAN_BAUDRATE_250k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_500k), MP_ROM_INT(CAN_BAUDRATE_500k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_800k), MP_ROM_INT(CAN_BAUDRATE_800k) }, - { MP_ROM_QSTR(MP_QSTR_BAUDRATE_1M), MP_ROM_INT(CAN_BAUDRATE_1M) }, // CAN_FILTER_MODE { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 9ed50a504f791..10f7f07abea40 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -34,15 +34,6 @@ #define DEVICE_NAME "CAN" -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 - typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, @@ -53,7 +44,7 @@ typedef struct _machine_can_config_t { can_timing_config_t timing; can_filter_config_t filter; can_general_config_t general; - uint16_t baudrate; + uint32_t baudrate; // bit/s bool initialized; } machine_can_config_t; From 7a3c239cdfed01eb9e0b4f084917c30aedd924b8 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 19 Jun 2021 00:06:27 +0300 Subject: [PATCH 163/180] ESP32: machine_can.c: Dict more informative than list --- ports/esp32/machine_can.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index b65cbaf49b5ed..8a3fb9391d73c 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -132,6 +132,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { +#if 0 machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { @@ -155,6 +156,23 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); +#else + can_status_info_t status = _machine_hw_can_get_status(); + mp_obj_t dict = mp_obj_new_dict(0); + #define dict_key(key) mp_obj_new_str(#key, strlen(#key)) + #define dict_value(key) MP_OBJ_NEW_SMALL_INT(status.key) + #define dict_store(key) mp_obj_dict_store(dict, dict_key(key), dict_value(key)); + dict_store(state); + dict_store(msgs_to_tx); + dict_store(msgs_to_rx); + dict_store(tx_error_counter); + dict_store(rx_error_counter); + dict_store(tx_failed_count); + dict_store(rx_missed_count); + dict_store(arb_lost_count); + dict_store(bus_error_count); + return dict; +#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); From 7e545a2f671028a83a0ebf57b3c32557e7d6f386 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 19 Jun 2021 00:08:35 +0300 Subject: [PATCH 164/180] ESP32: machine_can.c: Add some comments --- ports/esp32/machine_can.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 8a3fb9391d73c..27904d577168d 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -203,7 +203,7 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ ARG_id, ARG_timeout, ARG_rtr, - ARG_self + //ARG_self }; static const mp_arg_t allowed_args[] = { {MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, @@ -342,7 +342,7 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); -// bank: 0 or 1(only for std) +// bank: 0 only // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW @@ -613,6 +613,17 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, // { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, +/* esp32 can modes +CAN_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages +CAN_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). +CAN_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. +*/ +/* stm32 can modes +#define CAN_MODE_NORMAL FDCAN_MODE_NORMAL +#define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK +#define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING +#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK +*/ // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, From 54ea3cbcc4bce1afc0d6deebf0eec8417c7fbc0c Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 19 Jun 2021 00:09:29 +0300 Subject: [PATCH 165/180] ESP32: machine_can.c: Set default inits --- ports/esp32/machine_can.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 27904d577168d..a3606bc140e71 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -502,15 +502,15 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg static const mp_arg_t allowed_args[] = { { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_tx_io, MP_ARG_INT, {.u_int = 4} }, - { MP_QSTR_rx_io, MP_ARG_INT, {.u_int = 2} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_tx, MP_ARG_INT, {.u_int = 17} }, + { MP_QSTR_rx, MP_ARG_INT, {.u_int = 15} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 1} }, { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args From d6ac9761bce1259f64cc2b9de77747c30e12212b Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 14:55:33 -0700 Subject: [PATCH 166/180] esp32: CAN: Use twai.h --- ports/esp32/machine_can.c | 166 +++++++++++++++++++------------------- ports/esp32/machine_can.h | 6 +- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index a3606bc140e71..81c62c170980c 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -34,7 +34,7 @@ // Headers of ESP-IDF library #include "soc/dport_reg.h" -#include "driver/can.h" +#include "driver/twai.h" #include "esp_err.h" #include "esp_log.h" @@ -56,18 +56,18 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); // singleton CAN device object -machine_can_config_t can_config = { .general = CAN_GENERAL_CONFIG_DEFAULT(2, 4, 0), - .filter = CAN_FILTER_CONFIG_ACCEPT_ALL(), - .timing = CAN_TIMING_CONFIG_25KBITS(), +machine_can_config_t can_config = { .general = TWAI_GENERAL_CONFIG_DEFAULT(2, 4, 0), + .filter = TWAI_FILTER_CONFIG_ACCEPT_ALL(), + .timing = TWAI_TIMING_CONFIG_25KBITS(), .initialized = false }; STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; // INTERNAL FUNCTION Return status information -STATIC can_status_info_t _machine_hw_can_get_status() { - can_status_info_t status; - check_esp_err(can_get_status_info(&status)); +STATIC twai_status_info_t _machine_hw_can_get_status() { + twai_status_info_t status; + check_esp_err(twai_get_status_info(&status)); return status; } @@ -109,23 +109,23 @@ STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, u // Force a software restart of the controller, to allow transmission after a bus error STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { - check_esp_err(can_initiate_recovery()); + check_esp_err(twai_initiate_recovery()); mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution - check_esp_err(can_start()); + check_esp_err(twai_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); // any() - return `True` if any message waiting, else `False` STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) { - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_bool((status.msgs_to_rx) > 0); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); // Get the state of the controller STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); return mp_obj_new_int(status.state); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); @@ -146,7 +146,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { mp_raise_ValueError(NULL); } } - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); @@ -157,7 +157,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); #else - can_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _machine_hw_can_get_status(); mp_obj_t dict = mp_obj_new_dict(0); #define dict_key(key) mp_obj_new_str(#key, strlen(#key)) #define dict_value(key) MP_OBJ_NEW_SMALL_INT(status.key) @@ -179,20 +179,20 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machin // Get Alert info STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; - check_esp_err(can_read_alerts(&alerts, 0)); + check_esp_err(twai_read_alerts(&alerts, 0)); return mp_obj_new_int(alerts); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); // Clear TX Queue STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) { - return mp_obj_new_bool(can_clear_transmit_queue() == ESP_OK); + return mp_obj_new_bool(twai_clear_transmit_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); // Clear RX Queue STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) { - return mp_obj_new_bool(can_clear_receive_queue() == ESP_OK); + return mp_obj_new_bool(twai_clear_receive_queue() == ESP_OK); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); @@ -224,26 +224,26 @@ STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_ if (length > 8) { mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool ? CAN_MSG_FLAG_RTR : CAN_MSG_FLAG_NONE); + uint8_t flags = (args[ARG_rtr].u_bool ? TWAI_MSG_FLAG_RTR : TWAI_MSG_FLAG_NONE); uint32_t id = args[ARG_id].u_int; if (self->extframe) { - flags += CAN_MSG_FLAG_EXTD; + flags += TWAI_MSG_FLAG_EXTD; id &= 0x1FFFFFFF; } else { id &= 0x1FF; } if (self->loopback) { - flags += CAN_MSG_FLAG_SELF; + flags += TWAI_MSG_FLAG_SELF; } - can_message_t tx_msg = { .data_length_code = length, + twai_message_t tx_msg = { .data_length_code = length, .identifier = id, .flags = flags }; for (uint8_t i = 0; i < length; i++) { tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == CAN_STATE_RUNNING) { - check_esp_err(can_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + if (_machine_hw_can_get_status().state == TWAI_STATE_RUNNING) { + check_esp_err(twai_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); return mp_const_none; } else { mp_raise_msg(&mp_type_RuntimeError, "Device is not ready"); @@ -266,9 +266,9 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - can_message_t rx_message; + twai_message_t rx_message; //int status = - check_esp_err(can_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + check_esp_err(twai_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; @@ -300,7 +300,7 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ memcpy(mv->items, rx_message.data, rx_message.data_length_code); } items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bool(rx_message.flags && CAN_MSG_FLAG_RTR > 0); + items[1] = mp_obj_new_bool(rx_message.flags && TWAI_MSG_FLAG_RTR > 0); items[2] = 0; return ret_obj; } @@ -331,13 +331,13 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = 0; self->config->filter.acceptance_mask = 0xFFFFFFFF; - check_esp_err(can_stop()); - check_esp_err(can_driver_uninstall()); - check_esp_err(can_driver_install( + check_esp_err(twai_stop()); + check_esp_err(twai_driver_uninstall()); + check_esp_err(twai_driver_install( &self->config->general, &self->config->timing, &self->config->filter)); - check_esp_err(can_start()); + check_esp_err(twai_start()); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); @@ -383,13 +383,13 @@ STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args self->config->filter.single_filter = self->extframe; _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); } - check_esp_err( can_stop() ); - check_esp_err( can_driver_uninstall() ); - check_esp_err( can_driver_install( + check_esp_err( twai_stop() ); + check_esp_err( twai_driver_uninstall() ); + check_esp_err( twai_driver_install( &self->config->general, &self->config->timing, &self->config->filter) ); - check_esp_err( can_start() ); + check_esp_err( twai_start() ); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); @@ -400,13 +400,13 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p qstr mode; switch (self->config->general.mode) { - case CAN_MODE_LISTEN_ONLY: + case TWAI_MODE_LISTEN_ONLY: mode = MP_QSTR_LISTEN; break; - case CAN_MODE_NO_ACK: + case TWAI_MODE_NO_ACK: mode = MP_QSTR_NO_ACK; break; - case CAN_MODE_NORMAL: + case TWAI_MODE_NORMAL: mode = MP_QSTR_NORMAL; break; default: @@ -426,7 +426,7 @@ STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_p } } -// init(tx, rx, baudrate, mode = CAN_MODE_NORMAL, tx_queue = 2, rx_queue = 5) +// init(tx, rx, baudrate, mode = TWAI_MODE_NORMAL, tx_queue = 2, rx_queue = 5) STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); if (self->config->initialized) { @@ -444,8 +444,8 @@ STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { mp_raise_msg(&mp_type_RuntimeError, "Device is not initialized"); return mp_const_none; } - check_esp_err(can_stop()); - check_esp_err(can_driver_uninstall()); + check_esp_err(twai_stop()); + check_esp_err(twai_driver_uninstall()); self->config->initialized = false; return mp_const_none; } @@ -500,7 +500,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg ARG_auto_restart }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = CAN_MODE_NORMAL} }, + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = TWAI_MODE_NORMAL} }, { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000} }, { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, @@ -520,26 +520,26 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->general.mode = args[ARG_mode].u_int & 0x0F; self->config->general.tx_io = args[ARG_tx_io].u_int; self->config->general.rx_io = args[ARG_rx_io].u_int; - self->config->general.clkout_io = CAN_IO_UNUSED; - self->config->general.bus_off_io = CAN_IO_UNUSED; + self->config->general.clkout_io = TWAI_IO_UNUSED; + self->config->general.bus_off_io = TWAI_IO_UNUSED; self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; - self->config->general.alerts_enabled = CAN_ALERT_AND_LOG || CAN_ALERT_BELOW_ERR_WARN || CAN_ALERT_ERR_ACTIVE || CAN_ALERT_BUS_RECOVERED || - CAN_ALERT_ABOVE_ERR_WARN || CAN_ALERT_BUS_ERROR || CAN_ALERT_ERR_PASS || CAN_ALERT_BUS_OFF; + self->config->general.alerts_enabled = TWAI_ALERT_AND_LOG || TWAI_ALERT_BELOW_ERR_WARN || TWAI_ALERT_ERR_ACTIVE || TWAI_ALERT_BUS_RECOVERED || + TWAI_ALERT_ABOVE_ERR_WARN || TWAI_ALERT_BUS_ERROR || TWAI_ALERT_ERR_PASS || TWAI_ALERT_BUS_OFF; self->config->general.clkout_divider = 0; self->loopback = ((args[ARG_mode].u_int & LOOPBACK_MASK) > 0); self->extframe = args[ARG_extframe].u_bool; if (args[ARG_auto_restart].u_bool) { mp_raise_NotImplementedError("Auto-restart not supported"); } - can_filter_config_t f_config = CAN_FILTER_CONFIG_ACCEPT_ALL(); + twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); self->config->filter.single_filter = self->extframe; self->config->filter.acceptance_code = f_config.acceptance_code; self->config->filter.acceptance_mask = f_config.acceptance_mask; - can_timing_config_t *timing; + twai_timing_config_t *timing; switch ((int)args[ARG_baudrate].u_int) { case 0: - timing = &((can_timing_config_t) { + timing = &((twai_timing_config_t) { .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, @@ -548,28 +548,28 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg }); break; case 25000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_25KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_25KBITS() ); break; case 50000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_50KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_50KBITS() ); break; case 100000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_100KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_100KBITS() ); break; case 125000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_125KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_125KBITS() ); break; case 250000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_250KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_250KBITS() ); break; case 500000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_500KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_500KBITS() ); break; case 800000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_800KBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_800KBITS() ); break; case 1000000: - timing = &( (can_timing_config_t) CAN_TIMING_CONFIG_1MBITS() ); + timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_1MBITS() ); break; default: mp_raise_ValueError("Unable to set baudrate"); @@ -579,11 +579,11 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg self->config->timing = *timing; self->config->baudrate = args[ARG_baudrate].u_int; - check_esp_err(can_driver_install( + check_esp_err(twai_driver_install( &self->config->general, &self->config->timing, - &(can_filter_config_t) CAN_FILTER_CONFIG_ACCEPT_ALL())); - check_esp_err(can_start()); + &(twai_filter_config_t) TWAI_FILTER_CONFIG_ACCEPT_ALL())); + check_esp_err(twai_start()); self->config->initialized = true; return mp_const_none; } @@ -608,15 +608,15 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, // CAN_MODE - { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_NORMAL | LOOPBACK_MASK) }, - { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_NO_ACK) }, -// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact - { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(CAN_MODE_LISTEN_ONLY) }, + { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(TWAI_MODE_NORMAL) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(TWAI_MODE_NORMAL | LOOPBACK_MASK) }, + { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(TWAI_MODE_NO_ACK) }, +// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(TWAI_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact + { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(TWAI_MODE_LISTEN_ONLY) }, /* esp32 can modes -CAN_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages -CAN_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). -CAN_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. +TWAI_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages +TWAI_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). +TWAI_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. */ /* stm32 can modes #define CAN_MODE_NORMAL FDCAN_MODE_NORMAL @@ -625,28 +625,28 @@ CAN_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transm #define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK */ // CAN_STATE - { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(CAN_STATE_STOPPED) }, - { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(CAN_STATE_RUNNING) }, - { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(CAN_STATE_BUS_OFF) }, - { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(CAN_STATE_RECOVERING) }, + { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(TWAI_STATE_STOPPED) }, + { MP_ROM_QSTR(MP_QSTR_ERROR_ACTIVE), MP_ROM_INT(TWAI_STATE_RUNNING) }, + { MP_ROM_QSTR(MP_QSTR_BUS_OFF), MP_ROM_INT(TWAI_STATE_BUS_OFF) }, + { MP_ROM_QSTR(MP_QSTR_RECOVERING), MP_ROM_INT(TWAI_STATE_RECOVERING) }, // CAN_FILTER_MODE { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_SINGLE), MP_ROM_INT(FILTER_RAW_SINGLE) }, { MP_ROM_QSTR(MP_QSTR_FILTER_RAW_DUAL), MP_ROM_INT(FILTER_RAW_DUAL) }, { MP_ROM_QSTR(MP_QSTR_FILTER_ADDRESS), MP_ROM_INT(FILTER_ADDRESS) }, // CAN_ALERT - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(CAN_ALERT_TX_IDLE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(CAN_ALERT_TX_SUCCESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(CAN_ALERT_BELOW_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(CAN_ALERT_ERR_ACTIVE) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(CAN_ALERT_RECOVERY_IN_PROGRESS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(CAN_ALERT_BUS_RECOVERED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(CAN_ALERT_ARB_LOST) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(CAN_ALERT_ABOVE_ERR_WARN) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(CAN_ALERT_BUS_ERROR) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(CAN_ALERT_TX_FAILED) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(CAN_ALERT_RX_QUEUE_FULL) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(CAN_ALERT_ERR_PASS) }, - { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(CAN_ALERT_BUS_OFF) } + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_IDLE), MP_ROM_INT(TWAI_ALERT_TX_IDLE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_SUCCESS), MP_ROM_INT(TWAI_ALERT_TX_SUCCESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BELOW_ERR_WARN), MP_ROM_INT(TWAI_ALERT_BELOW_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_ACTIVE), MP_ROM_INT(TWAI_ALERT_ERR_ACTIVE) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RECOVERY_IN_PROGRESS), MP_ROM_INT(TWAI_ALERT_RECOVERY_IN_PROGRESS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_RECOVERED), MP_ROM_INT(TWAI_ALERT_BUS_RECOVERED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ARB_LOST), MP_ROM_INT(TWAI_ALERT_ARB_LOST) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ABOVE_ERR_WARN), MP_ROM_INT(TWAI_ALERT_ABOVE_ERR_WARN) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_ERROR), MP_ROM_INT(TWAI_ALERT_BUS_ERROR) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_TX_FAILED), MP_ROM_INT(TWAI_ALERT_TX_FAILED) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_RX_QUEUE_FULL), MP_ROM_INT(TWAI_ALERT_RX_QUEUE_FULL) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(TWAI_ALERT_ERR_PASS) }, + { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(TWAI_ALERT_BUS_OFF) } }; STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 10f7f07abea40..f4bbc00eb38d3 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -41,9 +41,9 @@ typedef enum _filter_mode_t{ } filter_mode_t; typedef struct _machine_can_config_t { - can_timing_config_t timing; - can_filter_config_t filter; - can_general_config_t general; + twai_timing_config_t timing; + twai_filter_config_t filter; + twai_general_config_t general; uint32_t baudrate; // bit/s bool initialized; } machine_can_config_t; From 4204497d6ccd346ec656e1b921a2ae140d436440 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Fri, 18 Jun 2021 14:59:53 -0700 Subject: [PATCH 167/180] esp32: CAN: Remove trailing spaces --- ports/esp32/machine_can.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 81c62c170980c..dbee251fc0838 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -172,7 +172,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { dict_store(arb_lost_count); dict_store(bus_error_count); return dict; -#endif +#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); @@ -267,7 +267,6 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); twai_message_t rx_message; - //int status = check_esp_err(twai_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview @@ -308,7 +307,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_rec STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); if (callback_in == mp_const_none) { self->rxcallback = mp_const_none; @@ -613,16 +612,16 @@ STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(TWAI_MODE_NO_ACK) }, // { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(TWAI_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(TWAI_MODE_LISTEN_ONLY) }, -/* esp32 can modes +/* esp32 can modes TWAI_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages TWAI_MODE_NO_ACK - Transmission does not require acknowledgment. Use this mode for self testing. // This mode is useful when self testing the TWAI controller (loopback of transmissions). TWAI_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No transmissions or acknowledgments) but can receive messages. // This mode is suited for bus monitor applications. */ -/* stm32 can modes +/* stm32 can modes #define CAN_MODE_NORMAL FDCAN_MODE_NORMAL #define CAN_MODE_LOOPBACK FDCAN_MODE_EXTERNAL_LOOPBACK #define CAN_MODE_SILENT FDCAN_MODE_BUS_MONITORING -#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK +#define CAN_MODE_SILENT_LOOPBACK FDCAN_MODE_INTERNAL_LOOPBACK */ // CAN_STATE { MP_ROM_QSTR(MP_QSTR_STOPPED), MP_ROM_INT(TWAI_STATE_STOPPED) }, From bea5e267695f2f0a1817fe00bb46f460dd9b65a8 Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Thu, 8 Jul 2021 10:07:42 +0300 Subject: [PATCH 168/180] esp32: machine_can.c fix initialisation argument ARG_bs2 https://github.com/micropython/micropython/pull/7381#issuecomment-876154663 Thanks to @kdschlosser --- ports/esp32/machine_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index dbee251fc0838..5bb7741d7837c 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -542,7 +542,7 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg .brp = args[ARG_prescaler].u_int, .sjw = args[ARG_sjw].u_int, .tseg_1 = args[ARG_bs1].u_int, - .tseg_2 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs2].u_int, .triple_sampling = false }); break; From 111247b948a47bb2c77f555e22ac7fbff3312551 Mon Sep 17 00:00:00 2001 From: Andrew Wingate <1464801+anfroholic@users.noreply.github.com> Date: Tue, 13 Jul 2021 00:51:37 -0500 Subject: [PATCH 169/180] Add to can docs Add more commands and fix some errors in docs --- docs/esp32/quickref.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index d0810ddb88661..bf474e246b935 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -398,11 +398,16 @@ Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT sig The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN - BAUDRATE_500k = 500 - can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) - dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 - can.send([1,2,3], 0x102) # send a message with id 123 - can.recv() # receive message + can = CAN(0, tx=4, rx=16, extframe=True, mode=CAN.LOOPBACK, baudrate=500000) + can.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can.send([1,2,3], 0x102) # send a message with id 123 + can.recv() # receive message + + can.any() # returns True if FIFO is not empty, else False + can.info() # get information about the controller’s error states and TX and RX buffers + can.deinit() # turn off the can bus + can.clear_rx_queue() # clear messages in the FIFO + can.clear_tx_queue() # clear messages in the transmit buffer Real time clock (RTC) --------------------- From 0f870cb80ebd2a612dee8d073f8e42f437a30aa9 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Tue, 7 Sep 2021 05:43:13 -0700 Subject: [PATCH 170/180] Fix #endif after rebase --- ports/esp32/modmachine.c | 1 + ports/esp32/mpconfigport.h | 1 + 2 files changed, 2 insertions(+) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 6ff56d11281f2..00c47af5dc59a 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -296,6 +296,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #if MICROPY_PY_MACHINE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, + #endif #if MICROPY_HW_ENABLE_CAN { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&machine_can_type) }, #endif diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index 96b20c50aa038..c28358ba52971 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -170,6 +170,7 @@ #endif #ifndef MICROPY_HW_ENABLE_SDCARD #define MICROPY_HW_ENABLE_SDCARD (1) +#endif #define MICROPY_HW_ENABLE_CAN (1) #define MICROPY_HW_SOFTSPI_MIN_DELAY (0) #define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly From 4d1d644faaf878c0bd05971410bda89d80b7007e Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Tue, 7 Sep 2021 07:08:57 -0700 Subject: [PATCH 171/180] WIP --- ports/esp32/machine_can.c | 9 +++++---- ports/esp32/machine_can.h | 11 +++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 5bb7741d7837c..89175d6ad02db 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -50,6 +50,8 @@ #define CAN_DEFAULT_BS1 (15) #define CAN_DEFAULT_BS2 (4) +#define LOOPBACK_MASK 0x10 + // Internal Functions mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); @@ -132,7 +134,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state) // Get info about error states and TX/RX buffers STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { -#if 0 +/* machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { @@ -156,7 +158,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); -#else +*/ twai_status_info_t status = _machine_hw_can_get_status(); mp_obj_t dict = mp_obj_new_dict(0); #define dict_key(key) mp_obj_new_str(#key, strlen(#key)) @@ -172,7 +174,6 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { dict_store(arb_lost_count); dict_store(bus_error_count); return dict; -#endif } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); @@ -432,6 +433,7 @@ STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_ mp_raise_msg(&mp_type_RuntimeError, "Device is already initialized"); return mp_const_none; } + return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); @@ -576,7 +578,6 @@ STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_arg return mp_const_none; } self->config->timing = *timing; - self->config->baudrate = args[ARG_baudrate].u_int; check_esp_err(twai_driver_install( &self->config->general, diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index f4bbc00eb38d3..2a0d2a948a09f 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -34,6 +34,17 @@ #define DEVICE_NAME "CAN" +/* +#define CAN_BAUDRATE_25k 25 +#define CAN_BAUDRATE_50k 50 +#define CAN_BAUDRATE_100k 100 +#define CAN_BAUDRATE_125k 125 +#define CAN_BAUDRATE_250k 250 +#define CAN_BAUDRATE_500k 500 +#define CAN_BAUDRATE_800k 800 +#define CAN_BAUDRATE_1M 1000 +*/ + typedef enum _filter_mode_t{ FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, From b2181e6bd42f0cf183204a9435a6a7a3f83258fb Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Wed, 8 Sep 2021 10:27:15 +0300 Subject: [PATCH 172/180] Update .gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 5d668f7e3e76a..7b5f2241147db 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,7 @@ user.props # Generated rst files ###################### genrst/ + +# MacOS desktop metadata files +###################### +.DS_Store From 51046cef6ad1a358c00acfbd6f0b9bed3e811d61 Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Wed, 8 Sep 2021 10:33:37 +0300 Subject: [PATCH 173/180] Update quickref.rst --- docs/esp32/quickref.rst | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index bf474e246b935..9040712104314 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -361,7 +361,7 @@ accessed via the :ref:`machine.SoftI2C ` class:: i2c.writeto(0x3a, '12') # write '12' to device with address 0x3a buf = bytearray(10) # create a buffer with 10 bytes - i2c.writeto(0x3a, buf) # write the given buffer to the slave + i2c.writeto(0x3a, buf) # write the given buffer to the peripheral Hardware I2C bus ---------------- @@ -385,6 +385,24 @@ has the same methods as software I2C above:: i2c = I2C(0) i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000) +I2S bus +------- + +See :ref:`machine.I2S `. :: + + from machine import I2S, Pin + + i2s = I2S(0, sck=Pin(13), ws=Pin(14), sd=Pin(34), mode=I2S.TX, bits=16, format=I2S.STEREO, rate=44100, ibuf=40000) # create I2S object + i2s.write(buf) # write buffer of audio samples to I2S device + + i2s = I2S(1, sck=Pin(33), ws=Pin(25), sd=Pin(32), mode=I2S.RX, bits=16, format=I2S.MONO, rate=22050, ibuf=40000) # create I2S object + i2s.readinto(buf) # fill buffer with audio samples from I2S device + +The I2S class is currently available as a Technical Preview. During the preview period, feedback from +users is encouraged. Based on this feedback, the I2S class API and implementation may be changed. + +ESP32 has two I2S buses with id=0 and id=1 + CAN bus ------- From 17f22561086570e0d41c82d4f8bd9d86b4e57699 Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Wed, 8 Sep 2021 10:54:36 +0300 Subject: [PATCH 174/180] Update machine.rst --- docs/library/machine.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/library/machine.rst b/docs/library/machine.rst index e0bf580aac17b..09ebe44af41c5 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -203,8 +203,8 @@ Classes machine.UART.rst machine.SPI.rst machine.I2C.rst - machine.CAN.rst machine.I2S.rst + machine.CAN.rst machine.RTC.rst machine.Timer.rst machine.WDT.rst From c55a7c580792f17e491607736c2c862eb426d87d Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Wed, 8 Sep 2021 10:56:47 +0300 Subject: [PATCH 175/180] Update Makefile --- ports/esp32/Makefile | 214 +------------------------------------------ 1 file changed, 1 insertion(+), 213 deletions(-) diff --git a/ports/esp32/Makefile b/ports/esp32/Makefile index 5950efbe37f10..403b698a32335 100644 --- a/ports/esp32/Makefile +++ b/ports/esp32/Makefile @@ -11,168 +11,6 @@ BUILD ?= build-$(BOARD) # Device serial settings. PORT ?= /dev/ttyUSB0 BAUD ?= 460800 -FLASH_MODE ?= dio -FLASH_FREQ ?= 40m -FLASH_SIZE ?= 4MB -CROSS_COMPILE ?= xtensa-esp32-elf- -OBJDUMP = $(CROSS_COMPILE)objdump - -SDKCONFIG_COMBINED = $(BUILD)/sdkconfig.combined -SDKCONFIG_H = $(BUILD)/sdkconfig.h - -# the git hash of the currently supported ESP IDF version -ESPIDF_SUPHASH_V3 := 6ccb4cf5b7d1fdddb8c2492f9cbc926abaf230df -ESPIDF_SUPHASH_V4 := 310beae373446ceb9a4ad9b36b5428d7fdf2705f - -define print_supported_git_hash -$(info Supported git hash (v3.3): $(ESPIDF_SUPHASH_V3)) -$(info Supported git hash (v4.0-beta1) (experimental): $(ESPIDF_SUPHASH_V4)) -endef - -# paths to ESP IDF and its components -ifeq ($(ESPIDF),) -ifneq ($(IDF_PATH),) -ESPIDF = $(IDF_PATH) -else -$(info The ESPIDF variable has not been set, please set it to the root of the esp-idf repository.) -$(info See README.md for installation instructions.) -$(call print_supported_git_hash) -$(error ESPIDF not set) -endif -endif - -ESPCOMP = $(ESPIDF)/components -ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py -ESPCOMP_KCONFIGS = $(shell find $(ESPCOMP) -name Kconfig) -ESPCOMP_KCONFIGS_PROJBUILD = $(shell find $(ESPCOMP) -name Kconfig.projbuild) - -# verify the ESP IDF version -ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H') - -ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V3)) -$(info Building with ESP IDF v3) -else ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) -$(info Building with ESP IDF v4) - -PYPARSING_VERSION = $(shell python3 -c 'import pyparsing; print(pyparsing.__version__)') -ifneq ($(PYPARSING_VERSION),2.3.1) -$(info ** ERROR **) -$(info EDP IDF requires pyparsing version less than 2.4) -$(info You will need to set up a Python virtual environment with pyparsing 2.3.1) -$(info Please see README.md for more information) -$(error Incorrect pyparsing version) -endif -else -$(info ** WARNING **) -$(info The git hash of ESP IDF does not match the supported version) -$(info The build may complete and the firmware may work but it is not guaranteed) -$(info ESP IDF path: $(ESPIDF)) -$(info Current git hash: $(ESPIDF_CURHASH)) -$(call print_supported_git_hash) -endif - -# pretty format of ESP IDF version, used internally by the IDF -IDF_VER := $(shell git -C $(ESPIDF) describe) - -ifeq ($(shell which $(CC) 2> /dev/null),) -$(info ** ERROR **) -$(info Cannot find C compiler $(CC)) -$(info Add the xtensa toolchain to your PATH. See README.md) -$(error C compiler missing) -endif - -# include sdkconfig to get needed configuration values -include $(SDKCONFIG) - -################################################################################ -# Compiler and linker flags - -INC += -I. -INC += -I$(TOP) -INC += -I$(TOP)/lib/mp-readline -INC += -I$(TOP)/lib/netutils -INC += -I$(TOP)/lib/timeutils -INC += -I$(BUILD) - -INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include -INC_ESPCOMP += -I$(ESPCOMP)/bootloader_support/include_bootloader -INC_ESPCOMP += -I$(ESPCOMP)/console -INC_ESPCOMP += -I$(ESPCOMP)/driver/include -INC_ESPCOMP += -I$(ESPCOMP)/driver/include/driver -INC_ESPCOMP += -I$(ESPCOMP)/efuse/include -INC_ESPCOMP += -I$(ESPCOMP)/efuse/esp32/include -INC_ESPCOMP += -I$(ESPCOMP)/esp32/include -INC_ESPCOMP += -I$(ESPCOMP)/espcoredump/include -INC_ESPCOMP += -I$(ESPCOMP)/soc/include -INC_ESPCOMP += -I$(ESPCOMP)/soc/esp32/include -INC_ESPCOMP += -I$(ESPCOMP)/heap/include -INC_ESPCOMP += -I$(ESPCOMP)/log/include -INC_ESPCOMP += -I$(ESPCOMP)/newlib/platform_include -INC_ESPCOMP += -I$(ESPCOMP)/newlib/include -INC_ESPCOMP += -I$(ESPCOMP)/nvs_flash/include -INC_ESPCOMP += -I$(ESPCOMP)/freertos/include -INC_ESPCOMP += -I$(ESPCOMP)/esp_ringbuf/include -INC_ESPCOMP += -I$(ESPCOMP)/esp_event/include -INC_ESPCOMP += -I$(ESPCOMP)/tcpip_adapter/include -INC_ESPCOMP += -I$(ESPCOMP)/lwip/lwip/src/include -INC_ESPCOMP += -I$(ESPCOMP)/lwip/port/esp32/include -INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps -INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/mbedtls/include -INC_ESPCOMP += -I$(ESPCOMP)/mbedtls/port/include -INC_ESPCOMP += -I$(ESPCOMP)/mdns/include -INC_ESPCOMP += -I$(ESPCOMP)/mdns/private_include -INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/include -INC_ESPCOMP += -I$(ESPCOMP)/ulp/include -INC_ESPCOMP += -I$(ESPCOMP)/vfs/include -INC_ESPCOMP += -I$(ESPCOMP)/xtensa-debug-module/include -INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include -INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/port/include -INC_ESPCOMP += -I$(ESPCOMP)/app_trace/include -INC_ESPCOMP += -I$(ESPCOMP)/app_update/include -INC_ESPCOMP += -I$(ESPCOMP)/pthread/include -INC_ESPCOMP += -I$(ESPCOMP)/smartconfig_ack/include -INC_ESPCOMP += -I$(ESPCOMP)/sdmmc/include -INC_ESPCOMP += -I$(ESPCOMP)/can/include - -ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) -INC_ESPCOMP += -I$(ESPCOMP)/esp_common/include -INC_ESPCOMP += -I$(ESPCOMP)/esp_eth/include -INC_ESPCOMP += -I$(ESPCOMP)/esp_event/private_include -INC_ESPCOMP += -I$(ESPCOMP)/esp_rom/include -INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/include -INC_ESPCOMP += -I$(ESPCOMP)/esp_wifi/esp32/include -INC_ESPCOMP += -I$(ESPCOMP)/lwip/include/apps/sntp -INC_ESPCOMP += -I$(ESPCOMP)/spi_flash/private_include -INC_ESPCOMP += -I$(ESPCOMP)/wpa_supplicant/include/esp_supplicant -INC_ESPCOMP += -I$(ESPCOMP)/xtensa/include -INC_ESPCOMP += -I$(ESPCOMP)/xtensa/esp32/include -else -INC_ESPCOMP += -I$(ESPCOMP)/ethernet/include -INC_ESPCOMP += -I$(ESPCOMP)/expat/expat/expat/lib -INC_ESPCOMP += -I$(ESPCOMP)/expat/port/include -INC_ESPCOMP += -I$(ESPCOMP)/json/include -INC_ESPCOMP += -I$(ESPCOMP)/json/port/include -INC_ESPCOMP += -I$(ESPCOMP)/micro-ecc/micro-ecc -INC_ESPCOMP += -I$(ESPCOMP)/nghttp/port/include -INC_ESPCOMP += -I$(ESPCOMP)/nghttp/nghttp2/lib/includes -endif - -# these flags are common to C and C++ compilation -CFLAGS_COMMON = -Os -ffunction-sections -fdata-sections -fstrict-volatile-bitfields \ - -mlongcalls -nostdlib \ - -Wall -Werror -Wno-error=unused-function -Wno-error=unused-but-set-variable \ - -Wno-error=unused-variable -Wno-error=deprecated-declarations \ - -DESP_PLATFORM - -CFLAGS_BASE = -std=gnu99 $(CFLAGS_COMMON) -DMBEDTLS_CONFIG_FILE='"mbedtls/esp_config.h"' -DHAVE_CONFIG_H -CFLAGS = $(CFLAGS_BASE) $(INC) $(INC_ESPCOMP) -CFLAGS += -DIDF_VER=\"$(IDF_VER)\" -CFLAGS += $(CFLAGS_MOD) $(CFLAGS_EXTRA) -CFLAGS += -I$(BOARD_DIR) - -ifeq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH_V4)) -CFLAGS += -DMICROPY_ESP_IDF_4=1 -endif PYTHON ?= python3 @@ -186,57 +24,7 @@ ifdef USER_C_MODULES CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES} endif -################################################################################ -# List of MicroPython source and object files - -SRC_C = \ - main.c \ - uart.c \ - gccollect.c \ - mphalport.c \ - fatfs_port.c \ - help.c \ - modutime.c \ - moduos.c \ - machine_timer.c \ - machine_pin.c \ - machine_touchpad.c \ - machine_adc.c \ - machine_dac.c \ - machine_i2c.c \ - machine_pwm.c \ - machine_uart.c \ - machine_can.c \ - modmachine.c \ - modnetwork.c \ - network_lan.c \ - network_ppp.c \ - modsocket.c \ - modesp.c \ - esp32_partition.c \ - esp32_ulp.c \ - modesp32.c \ - espneopixel.c \ - machine_hw_spi.c \ - machine_wdt.c \ - mpthreadport.c \ - machine_rtc.c \ - machine_sdcard.c \ - $(wildcard $(BOARD_DIR)/*.c) \ - $(SRC_MOD) - -EXTMOD_SRC_C = $(addprefix extmod/,\ - modonewire.c \ - ) - -LIB_SRC_C = $(addprefix lib/,\ - mp-readline/readline.c \ - netutils/netutils.c \ - timeutils/timeutils.c \ - utils/pyexec.c \ - utils/interrupt_char.c \ - utils/sys_stdio_mphal.c \ - ) +IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD) $(CMAKE_ARGS) ifdef FROZEN_MANIFEST IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST) From b6bbae339781373cce4e7a87e4f4389df573b79e Mon Sep 17 00:00:00 2001 From: Ihor Nehrutsa Date: Wed, 8 Sep 2021 10:58:31 +0300 Subject: [PATCH 176/180] Update modmachine.c --- ports/esp32/modmachine.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 00c47af5dc59a..3fae2ec594c1a 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -53,6 +53,7 @@ #include "extmod/machine_mem.h" #include "extmod/machine_signal.h" #include "extmod/machine_pulse.h" +#include "extmod/machine_pwm.h" #include "extmod/machine_i2c.h" #include "extmod/machine_spi.h" #include "modmachine.h" @@ -302,6 +303,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #endif { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) }, + #if MICROPY_PY_MACHINE_I2S + { MP_ROM_QSTR(MP_QSTR_I2S), MP_ROM_PTR(&machine_i2s_type) }, + #endif { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) }, { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) }, { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) }, From e6baddfc6ba77a58118ee71c79ba7d0f01322be1 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sun, 13 Nov 2022 19:46:44 +0200 Subject: [PATCH 177/180] WIP --- docs/esp32/quickref.rst | 4 +- examples/esp32_can.py | 52 ++- ports/esp32/machine_can.c | 905 ++++++++++++++++++++++---------------- ports/esp32/machine_can.h | 29 +- 4 files changed, 567 insertions(+), 423 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index eb4929ec2f240..d8eae3c28cf4e 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -507,12 +507,12 @@ Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT sig The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN - can = CAN(0, tx=4, rx=16, extframe=True, mode=CAN.LOOPBACK, baudrate=500000) + can = CAN(0, tx=5, rx=4, extframe=True, mode=CAN.NORMAL, baudrate=500000) can.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 can.send([1,2,3], 0x102) # send a message with id 123 can.recv() # receive message - can.any() # returns True if FIFO is not empty, else False + can.any() # returns True if there are any message to receive can.info() # get information about the controller’s error states and TX and RX buffers can.deinit() # turn off the can bus can.clear_rx_queue() # clear messages in the FIFO diff --git a/examples/esp32_can.py b/examples/esp32_can.py index 495370bb1d5e8..6ef0ebc213059 100644 --- a/examples/esp32_can.py +++ b/examples/esp32_can.py @@ -2,49 +2,47 @@ import time -def sendAndCheck(dev, name, id, expectedLP=True): - dev.clear_tx_queue() - dev.clear_rx_queue() - dev.send([], id) +def send_and_check(can_bus, name, id, expected_result=True, extended=False): + can_bus.clear_tx_queue() + can_bus.clear_rx_queue() + can_bus.send([], id, extframe=extended) time.sleep_ms(100) - if dev.any() == expectedLP: + if can_bus.any() == expected_result: print("{}: OK".format(name)) - if expectedLP: - dev.recv() + if expected_result: + can_bus.recv() else: print("{}: FAILED".format(name)) -dev = CAN(0, - extframe=False, - mode=CAN.SILENT_LOOPBACK, - baudrate=CAN.BAUDRATE_500k, - tx_io=18, rx_io=19, auto_restart=False) +# 4 and 5 pins must be connected to each other, see documentation +dev = CAN(0, extframe=False, tx=5, rx=4, mode=CAN.SILENT_LOOPBACK, baudrate=50000, auto_restart=False) # Test send/receive message print("Loopback Test: no filter - STD") -sendAndCheck(dev, "No filter", 0x100, True) +send_and_check(dev, "No filter", 0x100, True) # Set filter1 print("Loopback Test: one filter - STD") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) -sendAndCheck(dev, "Passing Message", 0x101, True) -sendAndCheck(dev, "Blocked Message", 0x100, False) +send_and_check(dev, "Passing Message", 0x101, True) +send_and_check(dev, "Blocked Message", 0x100, False) # Set filter2 print("Loopback Test: second filter - STD") dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) -sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) -sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) -sendAndCheck(dev, "Blocked Message", 0x100, False) +send_and_check(dev, "Passing Message - Bank 1", 0x102, True) +send_and_check(dev, "Passing Message - Bank 0", 0x101, True) +send_and_check(dev, "Blocked Message", 0x100, False) # Remove filter print("Loopback Test: clear filter - STD") dev.clearfilter() -sendAndCheck(dev, "Passing Message - Bank 1", 0x102, True) -sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) -sendAndCheck(dev, "Passing any Message", 0x100, True) +send_and_check(dev, "Passing Message - Bank 1", 0x102, True) +send_and_check(dev, "Passing Message - Bank 0", 0x101, True) +send_and_check(dev, "Passing any Message", 0x100, True) +# Extended message tests # Move to Extended dev = CAN(0, extframe=True, @@ -54,16 +52,16 @@ def sendAndCheck(dev, name, id, expectedLP=True): # Test send/receive message print("Loopback Test: no filter - Extd") -sendAndCheck(dev, "No filter", 0x100, True) +send_and_check(dev, "No filter", 0x100, True, extended=True) # Set filter1 print("Loopback Test: one filter - Extd") -dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0]) -sendAndCheck(dev, "Passing Message", 0x101, True) -sendAndCheck(dev, "Blocked Message", 0x100, False) +dev.setfilter(0, CAN.FILTER_ADDRESS, [0x101, 0], extframe=True) +send_and_check(dev, "Passing Message", 0x101, True, extended=True) +send_and_check(dev, "Blocked Message", 0x100, False, extended=True) # Remove filter print("Loopback Test: clear filter - Extd") dev.clearfilter() -sendAndCheck(dev, "Passing Message - Bank 0", 0x101, True) -sendAndCheck(dev, "Passing any Message", 0x100, True) +send_and_check(dev, "Passing Message - Bank 0", 0x101, True, extended=True) +send_and_check(dev, "Passing any Message", 0x100, True, extended=True) diff --git a/ports/esp32/machine_can.c b/ports/esp32/machine_can.c index 89175d6ad02db..326b1ce20b474 100755 --- a/ports/esp32/machine_can.c +++ b/ports/esp32/machine_can.c @@ -2,6 +2,7 @@ * * Copyright (c) 2019 Musumeci Salvatore * Copyright (c) 2021 Ihor Nehrutsa + * Copyright (c) 2022 Yuriy Makarov * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,111 +32,382 @@ #include "py/mphal.h" #include "py/mperrno.h" #include "mpconfigport.h" +#include "freertos/task.h" +#include "esp_idf_version.h" +// CAN only for ESP-IDF v4.2 and higher because of "driver/twai.h" +#if (ESP_IDF_VERSION_MAJOR == 4) && (ESP_IDF_VERSION_MINOR >= 2) // Headers of ESP-IDF library #include "soc/dport_reg.h" -#include "driver/twai.h" #include "esp_err.h" #include "esp_log.h" -#include +#include "driver/twai.h" +#include "esp_task.h" +#include "machine_can.h" #if MICROPY_HW_ENABLE_CAN -#define LOOPBACK_MASK 0x10 +#define CAN_MODE_SILENT_LOOPBACK (0x10) // Default baudrate: 500kb +#define CAN_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1) +#define CAN_TASK_STACK_SIZE (1024) #define CAN_DEFAULT_PRESCALER (8) #define CAN_DEFAULT_SJW (3) #define CAN_DEFAULT_BS1 (15) #define CAN_DEFAULT_BS2 (4) +#define CAN_MAX_DATA_FRAME (8) -#define LOOPBACK_MASK 0x10 - +#define CAN_MODE_SILENT_LOOPBACK 0x10 +/* // Internal Functions -mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +mp_obj_t esp32_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args); +STATIC mp_obj_t esp32_hw_can_init_helper(esp32_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); +STATIC void esp32_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); +*/ +// INTERNAL Deinitialize can +void can_deinit(const esp32_can_obj_t *self) { + check_esp_err(twai_stop()); + check_esp_err(twai_driver_uninstall()); + if (self->irq_handler != NULL) { + vTaskDelete(self->irq_handler); + } + self->config->initialized = false; +} // singleton CAN device object -machine_can_config_t can_config = { .general = TWAI_GENERAL_CONFIG_DEFAULT(2, 4, 0), - .filter = TWAI_FILTER_CONFIG_ACCEPT_ALL(), - .timing = TWAI_TIMING_CONFIG_25KBITS(), - .initialized = false - }; +esp32_can_config_t can_config = { + .general = TWAI_GENERAL_CONFIG_DEFAULT(GPIO_NUM_2, GPIO_NUM_4, CAN_MODE_NORMAL), + .filter = TWAI_FILTER_CONFIG_ACCEPT_ALL(), + .timing = TWAI_TIMING_CONFIG_25KBITS(), + .initialized = false +}; -STATIC machine_can_obj_t machine_can_obj = { {&machine_can_type}, .config = &can_config }; +STATIC esp32_can_obj_t esp32_can_obj = { + {&esp32_can_type}, + .config = &can_config +}; // INTERNAL FUNCTION Return status information -STATIC twai_status_info_t _machine_hw_can_get_status() { +STATIC twai_status_info_t _esp32_hw_can_get_status() { twai_status_info_t status; check_esp_err(twai_get_status_info(&status)); return status; } -//INTERNAL FUNCTION Populates the filter register according to inputs -STATIC void _machine_hw_can_set_filter(machine_can_obj_t *self, uint32_t addr, uint32_t mask, uint8_t bank, bool rtr) { - //Check if bank is allowed - if (bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { - mp_raise_ValueError("CAN filter parameter error"); - } - uint32_t preserve_mask; - if (self->extframe) { - addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); - mask = (mask & 0x1FFFFFFF) << 3 | 0x03; - preserve_mask = 0; - } else if (self->config->filter.single_filter) { - addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); - mask = ( (mask & 0x7FF) << 5 ); - mask |= 0xFFFFF000; - preserve_mask = 0; +STATIC void esp32_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + esp32_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->config->initialized) { + qstr mode; + switch (self->config->general.mode) { + case TWAI_MODE_LISTEN_ONLY: + mode = MP_QSTR_LISTEN; + break; + case TWAI_MODE_NO_ACK: + mode = MP_QSTR_NO_ACK; + break; + case TWAI_MODE_NORMAL: + mode = MP_QSTR_NORMAL; + break; + default: + mode = MP_QSTR_UNKNOWN; + break; + } + mp_printf(print, "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", + self->config->general.tx_io, + self->config->general.rx_io, + self->config->baudrate, + mode, + self->loopback, + self->extframe); } else { - addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); - mask = ( (mask & 0x7FF) << 5 ); - preserve_mask = 0xFFFF << ( bank == 0 ? 16 : 0 ); - if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ) { - // Other filter accepts all; it will replaced duplicating current filter - addr = addr | (addr << 16); - mask = mask | (mask << 16); - preserve_mask = 0; - } else { - addr = addr << (bank == 1 ? 16 : 0); - mask = mask << (bank == 1 ? 16 : 0); + mp_printf(print, "Device is not initialized"); + } +} + +// INTERNAL FUNCTION FreeRTOS IRQ task +STATIC void esp32_hw_can_irq_task(void *self_in) { + esp32_can_obj_t *self = (esp32_can_obj_t *)self_in; + uint32_t alerts; + + twai_reconfigure_alerts( + TWAI_ALERT_RX_DATA | TWAI_ALERT_RX_QUEUE_FULL | TWAI_ALERT_BUS_OFF | TWAI_ALERT_ERR_PASS | + TWAI_ALERT_ABOVE_ERR_WARN | TWAI_ALERT_TX_FAILED | TWAI_ALERT_TX_SUCCESS | TWAI_ALERT_BUS_RECOVERED, + NULL + ); + + while (1) { + check_esp_err(twai_read_alerts(&alerts, portMAX_DELAY)); + + if (alerts & TWAI_ALERT_BUS_OFF) { + ++self->num_bus_off; + } + if (alerts & TWAI_ALERT_ERR_PASS) { + ++self->num_error_passive; + } + if (alerts & TWAI_ALERT_ABOVE_ERR_WARN) { + ++self->num_error_warning; + } + + if (alerts & (TWAI_ALERT_TX_FAILED | TWAI_ALERT_TX_SUCCESS)) { + self->last_tx_success = (alerts & TWAI_ALERT_TX_SUCCESS) > 0; + } + + if (alerts & (TWAI_ALERT_BUS_RECOVERED)) { + self->bus_recovery_success = true; + } + + if (self->rxcallback != mp_const_none) { + if (alerts & TWAI_ALERT_RX_DATA) { + uint32_t msgs_to_rx = _esp32_hw_can_get_status().msgs_to_rx; + + if (msgs_to_rx == 1) { + // first message in queue + mp_sched_schedule(self->rxcallback, MP_OBJ_NEW_SMALL_INT(0)); + } else if (msgs_to_rx >= self->config->general.rx_queue_len) { + // queue is full + mp_sched_schedule(self->rxcallback, MP_OBJ_NEW_SMALL_INT(1)); + } + } + if (alerts & TWAI_ALERT_RX_QUEUE_FULL) { + // queue overflow + mp_sched_schedule(self->rxcallback, MP_OBJ_NEW_SMALL_INT(2)); + } } } - self->config->filter.acceptance_code &= preserve_mask; - self->config->filter.acceptance_code |= addr; - self->config->filter.acceptance_mask &= preserve_mask; - self->config->filter.acceptance_mask |= mask; } -// Force a software restart of the controller, to allow transmission after a bus error -STATIC mp_obj_t machine_hw_can_restart(mp_obj_t self_in) { - check_esp_err(twai_initiate_recovery()); - mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution +// init(mode, tx=5, rx=4, baudrate=500000, prescaler=8, sjw=3, bs1=15, bs2=4, auto_restart=False, tx_queue=1, rx_queue=1) +STATIC mp_obj_t esp32_hw_can_init_helper(esp32_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_mode, ARG_prescaler, ARG_sjw, ARG_bs1, ARG_bs2, ARG_auto_restart, ARG_baudrate, ARG_extframe, + ARG_tx_io, ARG_rx_io, ARG_tx_queue, ARG_rx_queue}; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = TWAI_MODE_NORMAL} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, + { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, + { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, + { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, + { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000} }, + { MP_QSTR_tx, MP_ARG_INT, {.u_int = 4} }, + { MP_QSTR_rx, MP_ARG_INT, {.u_int = 5} }, + { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 1} }, + { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 1} }, + }; + + // parse args + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // Configure device + self->config->general.mode = args[ARG_mode].u_int & 0x0F; + self->config->general.tx_io = args[ARG_tx_io].u_int; + self->config->general.rx_io = args[ARG_rx_io].u_int; + self->config->general.clkout_io = TWAI_IO_UNUSED; + self->config->general.bus_off_io = TWAI_IO_UNUSED; + self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; + self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; + self->config->general.alerts_enabled = TWAI_ALERT_AND_LOG || TWAI_ALERT_BELOW_ERR_WARN || TWAI_ALERT_ERR_ACTIVE || TWAI_ALERT_BUS_RECOVERED || + TWAI_ALERT_ABOVE_ERR_WARN || TWAI_ALERT_BUS_ERROR || TWAI_ALERT_ERR_PASS || TWAI_ALERT_BUS_OFF; + self->config->general.clkout_divider = 0; + self->loopback = ((args[ARG_mode].u_int & CAN_MODE_SILENT_LOOPBACK) > 0); + self->extframe = args[ARG_extframe].u_bool; + if (args[ARG_auto_restart].u_bool) { + mp_raise_NotImplementedError("Auto-restart not supported"); + } + self->config->filter = TWAI_FILTER_CONFIG_ACCEPT_ALL(); + + // clear errors + self->num_error_warning = 0; + self->num_error_passive = 0; + self->num_bus_off = 0; + + // Calculate CAN nominal bit timing from baudrate if provided + twai_timing_config_t *timing; + switch ((int)args[ARG_baudrate].u_int) { + case 0: + timing = &((twai_timing_config_t) { + .brp = args[ARG_prescaler].u_int, + .sjw = args[ARG_sjw].u_int, + .tseg_1 = args[ARG_bs1].u_int, + .tseg_2 = args[ARG_bs2].u_int, + .triple_sampling = false + }); + break; + #ifdef TWAI_TIMING_CONFIG_1KBITS + case 1000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_1KBITS()); + break; + #endif + #ifdef TWAI_TIMING_CONFIG_5KBITS + case 5000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_5KBITS()); + break; + #endif + #ifdef TWAI_TIMING_CONFIG_10KBITS + case 10000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_10KBITS()); + break; + #endif + #ifdef TWAI_TIMING_CONFIG_12_5KBITS + case 12500: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_12_5KBITS()); + break; + #endif + #ifdef TWAI_TIMING_CONFIG_16KBITS + case 16000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_16KBITS()); + break; + #endif + #ifdef TWAI_TIMING_CONFIG_20KBITS + case 20000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_20KBITS()); + break; + #endif + case 25000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_25KBITS()); + break; + case 50000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_50KBITS()); + break; + case 100000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_100KBITS()); + break; + case 125000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_125KBITS()); + break; + case 250000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_250KBITS()); + break; + case 500000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_500KBITS()); + break; + case 800000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_800KBITS()); + break; + case 1000000: + timing = &((twai_timing_config_t)TWAI_TIMING_CONFIG_1MBITS()); + break; + default: + mp_raise_ValueError("Unable to set baudrate"); + self->config->baudrate = 0; + return mp_const_none; + } + self->config->timing = *timing; + + check_esp_err(twai_driver_install(&self->config->general, &self->config->timing, &self->config->filter)); check_esp_err(twai_start()); + if (xTaskCreatePinnedToCore(esp32_hw_can_irq_task, "can_irq_task", CAN_TASK_STACK_SIZE, self, CAN_TASK_PRIORITY, (TaskHandle_t *)&self->irq_handler, MP_TASK_COREID) != pdPASS) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("failed to create can irq task handler")); + } + self->config->initialized = true; + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_restart_obj, machine_hw_can_restart); -// any() - return `True` if any message waiting, else `False` -STATIC mp_obj_t machine_hw_can_any(mp_obj_t self_in) { - twai_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_bool((status.msgs_to_rx) > 0); +// CAN(bus, ...) No argument to get the object +// If no arguments are provided, the initialized object will be returned +STATIC mp_obj_t esp32_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + if (mp_obj_is_int(args[0]) != true) { + mp_raise_TypeError("bus must be a number"); + } + + // work out port + mp_uint_t can_idx = mp_obj_get_int(args[0]); + if (can_idx != 0) { + mp_raise_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx); + } + + esp32_can_obj_t *self = &esp32_can_obj; + if (!self->config->initialized || n_args > 1 || n_kw > 0) { + if (self->config->initialized) { + // The caller is requesting a reconfiguration of the hardware + // this can only be done if the hardware is in init mode + can_deinit(self); + } + self->rxcallback = mp_const_none; + self->irq_handler = NULL; + self->rx_state = RX_STATE_FIFO_EMPTY; + + if (n_args > 1 || n_kw > 0) { + // start the peripheral + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + esp32_hw_can_init_helper(self, n_args - 1, args + 1, &kw_args); + } + } + return MP_OBJ_FROM_PTR(self); +} + +// init(tx, rx, baudrate, mode=CAN_MODE_NORMAL, tx_queue=2, rx_queue=5) +STATIC mp_obj_t esp32_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + esp32_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + if (self->config->initialized) { + mp_raise_msg(&mp_type_RuntimeError, "Device is already initialized"); + return mp_const_none; + } + + return esp32_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_any_obj, machine_hw_can_any); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_hw_can_init_obj, 4, esp32_hw_can_init); + +// deinit() +STATIC mp_obj_t esp32_hw_can_deinit(const mp_obj_t self_in) { + const esp32_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (self->config->initialized != true) { + mp_raise_msg(&mp_type_RuntimeError, "Device is not initialized"); + return mp_const_none; + } + can_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_deinit_obj, esp32_hw_can_deinit); + +// Force a software restart of the controller, to allow transmission after a bus error +STATIC mp_obj_t esp32_hw_can_restart(mp_obj_t self_in) { + esp32_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + twai_status_info_t status = _esp32_hw_can_get_status(); + if (!self->config->initialized || status.state != TWAI_STATE_BUS_OFF) { + mp_raise_ValueError(NULL); + } + + self->bus_recovery_success = -1; + check_esp_err(twai_initiate_recovery()); + mp_hal_delay_ms(200); // FIXME: replace it with a smarter solution + + while (self->bus_recovery_success < 0) { + MICROPY_EVENT_POLL_HOOK + } + + if (self->bus_recovery_success) { + check_esp_err(twai_start()); + } else { + mp_raise_OSError(MP_EIO); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_restart_obj, esp32_hw_can_restart); // Get the state of the controller -STATIC mp_obj_t machine_hw_can_state(mp_obj_t self_in) { - twai_status_info_t status = _machine_hw_can_get_status(); - return mp_obj_new_int(status.state); +STATIC mp_obj_t esp32_hw_can_state(mp_obj_t self_in) { + esp32_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t state = TWAI_STATE_STOPPED; + if (self->config->initialized) { + state = _esp32_hw_can_get_status().state; + } + return mp_obj_new_int(state); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_state_obj, machine_hw_can_state); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_state_obj, esp32_hw_can_state); -// Get info about error states and TX/RX buffers -STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { +// info() -- Get info about error states and TX/RX buffers +STATIC mp_obj_t esp32_hw_can_info(size_t n_args, const mp_obj_t *args) { /* - machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); + esp32_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_list_t *list; if (n_args == 1) { list = MP_OBJ_TO_PTR(mp_obj_new_list(8, NULL)); @@ -148,7 +420,7 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { mp_raise_ValueError(NULL); } } - twai_status_info_t status = _machine_hw_can_get_status(); + twai_status_info_t status = _esp32_hw_can_get_status(); list->items[0] = MP_OBJ_NEW_SMALL_INT(status.tx_error_counter); list->items[1] = MP_OBJ_NEW_SMALL_INT(status.rx_error_counter); list->items[2] = MP_OBJ_NEW_SMALL_INT(self->num_error_warning); @@ -158,8 +430,8 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { list->items[6] = MP_OBJ_NEW_SMALL_INT(status.msgs_to_rx); list->items[7] = mp_const_none; return MP_OBJ_FROM_PTR(list); -*/ - twai_status_info_t status = _machine_hw_can_get_status(); +*/ + twai_status_info_t status = _esp32_hw_can_get_status(); mp_obj_t dict = mp_obj_new_dict(0); #define dict_key(key) mp_obj_new_str(#key, strlen(#key)) #define dict_value(key) MP_OBJ_NEW_SMALL_INT(status.key) @@ -175,89 +447,98 @@ STATIC mp_obj_t machine_hw_can_info(size_t n_args, const mp_obj_t *args) { dict_store(bus_error_count); return dict; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_hw_can_info_obj, 1, 2, machine_hw_can_info); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp32_hw_can_info_obj, 1, 2, esp32_hw_can_info); // Get Alert info -STATIC mp_obj_t machine_hw_can_alert(mp_obj_t self_in) { +STATIC mp_obj_t esp32_hw_can_alert(mp_obj_t self_in) { uint32_t alerts; check_esp_err(twai_read_alerts(&alerts, 0)); return mp_obj_new_int(alerts); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_alert_obj, machine_hw_can_alert); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_alert_obj, esp32_hw_can_alert); -// Clear TX Queue -STATIC mp_obj_t machine_hw_can_clear_tx_queue(mp_obj_t self_in) { - return mp_obj_new_bool(twai_clear_transmit_queue() == ESP_OK); +// any() - return `True` if any message waiting, else `False` +STATIC mp_obj_t esp32_hw_can_any(mp_obj_t self_in) { + twai_status_info_t status = _esp32_hw_can_get_status(); + return mp_obj_new_bool((status.msgs_to_rx) > 0); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_tx_queue_obj, machine_hw_can_clear_tx_queue); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_any_obj, esp32_hw_can_any); -// Clear RX Queue -STATIC mp_obj_t machine_hw_can_clear_rx_queue(mp_obj_t self_in) { - return mp_obj_new_bool(twai_clear_receive_queue() == ESP_OK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clear_rx_queue_obj, machine_hw_can_clear_rx_queue); - -// send([data], id, *) -STATIC mp_obj_t machine_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { - ARG_data, - ARG_id, - ARG_timeout, - ARG_rtr, - //ARG_self - }; +// send([data], id, *, timeout=0, rtr=false, extframe=false) +STATIC mp_obj_t esp32_hw_can_send(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_data, ARG_id, ARG_timeout, ARG_rtr, ARG_extframe }; static const mp_arg_t allowed_args[] = { - {MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, - {MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0}}, - {MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false}}, + { MP_QSTR_data, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args - machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + esp32_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); // populate message + twai_message_t tx_msg; + size_t length; mp_obj_t *items; mp_obj_get_array(args[ARG_data].u_obj, &length, &items); - if (length > 8) { + if (length > CAN_MAX_DATA_FRAME) { mp_raise_ValueError("CAN data field too long"); } - uint8_t flags = (args[ARG_rtr].u_bool ? TWAI_MSG_FLAG_RTR : TWAI_MSG_FLAG_NONE); - uint32_t id = args[ARG_id].u_int; - if (self->extframe) { - flags += TWAI_MSG_FLAG_EXTD; - id &= 0x1FFFFFFF; + tx_msg.data_length_code = length; + tx_msg.flags = (args[ARG_rtr].u_bool ? TWAI_MSG_FLAG_RTR : TWAI_MSG_FLAG_NONE); + + if (args[ARG_extframe].u_bool) { + tx_msg.identifier = args[ARG_id].u_int & 0x1FFFFFFF; + tx_msg.flags += TWAI_MSG_FLAG_EXTD; } else { - id &= 0x1FF; + tx_msg.identifier = args[ARG_id].u_int & 0x7FF; } if (self->loopback) { - flags += TWAI_MSG_FLAG_SELF; + tx_msg.flags += TWAI_MSG_FLAG_SELF; } - twai_message_t tx_msg = { .data_length_code = length, - .identifier = id, - .flags = flags - }; + for (uint8_t i = 0; i < length; i++) { tx_msg.data[i] = mp_obj_get_int(items[i]); } - if (_machine_hw_can_get_status().state == TWAI_STATE_RUNNING) { - check_esp_err(twai_transmit(&tx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + + if (_esp32_hw_can_get_status().state == TWAI_STATE_RUNNING) { + uint32_t timeout_ms = args[ARG_timeout].u_int; + + if (timeout_ms != 0) { + self->last_tx_success = -1; + uint32_t start = mp_hal_ticks_us(); + check_esp_err(twai_transmit(&tx_msg, pdMS_TO_TICKS(timeout_ms))); + while (self->last_tx_success < 0) { + if (timeout_ms != portMAX_DELAY) { + if (mp_hal_ticks_us() - start >= timeout_ms) { + mp_raise_OSError(MP_ETIMEDOUT); + } + } + MICROPY_EVENT_POLL_HOOK + } + + if (!self->last_tx_success) { + mp_raise_OSError(MP_EIO); + } + } else { + check_esp_err(twai_transmit(&tx_msg, portMAX_DELAY)); + } + return mp_const_none; } else { mp_raise_msg(&mp_type_RuntimeError, "Device is not ready"); } } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_send_obj, 3, machine_hw_can_send); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_hw_can_send_obj, 3, esp32_hw_can_send); // recv(list=None, *, timeout=5000) -STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { - ARG_list, - ARG_timeout - }; +STATIC mp_obj_t esp32_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_list, ARG_timeout }; static const mp_arg_t allowed_args[] = { { MP_QSTR_list, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} }, { MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} }, @@ -267,16 +548,19 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - twai_message_t rx_message; - check_esp_err(twai_receive(&rx_message, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + // receive the data + twai_message_t rx_msg; + check_esp_err(twai_receive(&rx_msg, pdMS_TO_TICKS(args[ARG_timeout].u_int))); + uint32_t rx_dlc = rx_msg.data_length_code; + // Create the tuple, or get the list, that will hold the return values // Also populate the fourth element, either a new bytes or reuse existing memoryview mp_obj_t ret_obj = args[ARG_list].u_obj; mp_obj_t *items; if (ret_obj == mp_const_none) { ret_obj = mp_obj_new_tuple(4, NULL); - items = ( (mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj) )->items; - items[3] = mp_obj_new_bytes(rx_message.data, rx_message.data_length_code); + items = ((mp_obj_tuple_t *)MP_OBJ_TO_PTR(ret_obj))->items; + items[3] = mp_obj_new_bytes(rx_msg.data, rx_dlc); } else { // User should provide a list of length at least 4 to hold the values if (!mp_obj_is_type(ret_obj, &mp_type_list)) { @@ -296,41 +580,26 @@ STATIC mp_obj_t machine_hw_can_recv(size_t n_args, const mp_obj_t *pos_args, mp_ if (!(mv->typecode == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | BYTEARRAY_TYPECODE) || (mv->typecode | 0x20) == (MP_OBJ_ARRAY_TYPECODE_FLAG_RW | 'b'))) { mp_raise_ValueError(NULL); } - mv->len = rx_message.data_length_code; - memcpy(mv->items, rx_message.data, rx_message.data_length_code); + mv->len = rx_dlc; + memcpy(mv->items, rx_msg.data, rx_dlc); } - items[0] = MP_OBJ_NEW_SMALL_INT(rx_message.identifier); - items[1] = mp_obj_new_bool(rx_message.flags && TWAI_MSG_FLAG_RTR > 0); - items[2] = 0; - return ret_obj; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_recv_obj, 0, machine_hw_can_recv); - -STATIC mp_obj_t machine_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { - mp_raise_NotImplementedError("IRQ not supported yet"); - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + items[0] = MP_OBJ_NEW_SMALL_INT(rx_msg.identifier); + items[1] = rx_msg.extd ? mp_const_true : mp_const_false; + items[2] = rx_msg.rtr ? mp_const_true : mp_const_false; - if (callback_in == mp_const_none) { - self->rxcallback = mp_const_none; - } else if (self->rxcallback != mp_const_none) { - // Rx call backs has already been initialized - // only the callback function should be changed - self->rxcallback = callback_in; - // TODO: disable interrupt - } else if (mp_obj_is_callable(callback_in)) { - self->rxcallback = callback_in; - // TODO: set interrupt - } - return mp_const_none; + // Return the result + return ret_obj; } -STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_hw_can_rxcallback_obj, machine_hw_can_rxcallback); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_hw_can_recv_obj, 0, esp32_hw_can_recv); // Clear filters setting -STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - self->config->filter.single_filter = self->extframe; - self->config->filter.acceptance_code = 0; - self->config->filter.acceptance_mask = 0xFFFFFFFF; +STATIC mp_obj_t esp32_hw_can_clearfilter(mp_obj_t self_in) { + esp32_can_obj_t *self = MP_OBJ_TO_PTR(self_in); + + // Defaults from TWAI_FILTER_CONFIG_ACCEPT_ALL + self->config->filter = TWAI_FILTER_CONFIG_ACCEPT_ALL(); + + // Apply filter check_esp_err(twai_stop()); check_esp_err(twai_driver_uninstall()); check_esp_err(twai_driver_install( @@ -340,278 +609,149 @@ STATIC mp_obj_t machine_hw_can_clearfilter(mp_obj_t self_in) { check_esp_err(twai_start()); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_clearfilter_obj, machine_hw_can_clearfilter); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_clearfilter_obj, esp32_hw_can_clearfilter); // bank: 0 only // mode: FILTER_RAW_SINGLE, FILTER_RAW_DUAL or FILTER_ADDR_SINGLE or FILTER_ADDR_DUAL // params: [id, mask] // rtr: ignored if FILTER_RAW // Set CAN HW filter -STATIC mp_obj_t machine_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum - { - ARG_bank, - ARG_mode, - ARG_params, - ARG_rtr - }; +STATIC mp_obj_t esp32_hw_can_setfilter(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_bank, ARG_mode, ARG_params, ARG_rtr, ARG_extframe }; static const mp_arg_t allowed_args[] = { { MP_QSTR_bank, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, { MP_QSTR_params, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, + { MP_QSTR_rtr, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_bool = false} }, + { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, }; // parse args - machine_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + esp32_can_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + const int can_idx = args[ARG_bank].u_int; + + if (can_idx != 0) { + mp_raise_msg_varg(&mp_type_ValueError, "Bank (%d) doesn't exist", can_idx); + } size_t len; mp_obj_t *params; mp_obj_get_array(args[ARG_params].u_obj, &len, ¶ms); - if (len != 2) { - mp_raise_ValueError("params shall be a 2-values list"); - } + const int mode = args[ARG_mode].u_int; + uint32_t id = mp_obj_get_int(params[0]); uint32_t mask = mp_obj_get_int(params[1]); // FIXME: Overflow in case 0xFFFFFFFF for mask - if (args[ARG_mode].u_int == FILTER_RAW_SINGLE || args[ARG_mode].u_int == FILTER_RAW_DUAL) { - self->config->filter.single_filter = (args[ARG_mode].u_int == FILTER_RAW_SINGLE); + if (mode == FILTER_RAW_SINGLE || mode == FILTER_RAW_DUAL) { + if (len != 2) { + mp_raise_ValueError("params must be a 2-values list"); + } + self->config->filter.single_filter = (mode == FILTER_RAW_SINGLE); self->config->filter.acceptance_code = id; self->config->filter.acceptance_mask = mask; } else { self->config->filter.single_filter = self->extframe; - _machine_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); + _esp32_hw_can_set_filter(self, id, mask, args[ARG_bank].u_int, args[ARG_rtr].u_int); + //Check if bank is allowed + if (bank > ((self->extframe && self->config->filter.single_filter) ? 0 : 1 )) { + mp_raise_ValueError("CAN filter parameter error"); + } + uint32_t preserve_mask; + if (self->extframe) { + addr = (addr & 0x1FFFFFFF) << 3 | (rtr ? 0x04 : 0); + mask = (mask & 0x1FFFFFFF) << 3 | 0x03; + preserve_mask = 0; + } else if (self->config->filter.single_filter) { + addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); + mask = ( (mask & 0x7FF) << 5 ); + mask |= 0xFFFFF000; + preserve_mask = 0; + } else { + addr = ( ( (addr & 0x7FF) << 5 ) | (rtr ? 0x10 : 0) ); + mask = ( (mask & 0x7FF) << 5 ); + preserve_mask = 0xFFFF << ( bank == 0 ? 16 : 0 ); + if ( (self->config->filter.acceptance_mask & preserve_mask) == ( 0xFFFF << (bank == 0 ? 16 : 0) ) ) { + // Other filter accepts all; it will replaced duplicating current filter + addr = addr | (addr << 16); + mask = mask | (mask << 16); + preserve_mask = 0; + } else { + addr = addr << (bank == 1 ? 16 : 0); + mask = mask << (bank == 1 ? 16 : 0); + } + } + self->config->filter.acceptance_code &= preserve_mask; + self->config->filter.acceptance_code |= addr; + self->config->filter.acceptance_mask &= preserve_mask; + self->config->filter.acceptance_mask |= mask; } - check_esp_err( twai_stop() ); - check_esp_err( twai_driver_uninstall() ); - check_esp_err( twai_driver_install( + // Apply filter + check_esp_err(twai_stop()); + check_esp_err(twai_driver_uninstall()); + check_esp_err(twai_driver_install( &self->config->general, &self->config->timing, - &self->config->filter) ); - check_esp_err( twai_start() ); + &self->config->filter + )); + check_esp_err(twai_start()); + return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_setfilter_obj, 1, machine_hw_can_setfilter); +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_hw_can_setfilter_obj, 1, esp32_hw_can_setfilter); -STATIC void machine_hw_can_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (self->config->initialized) { - qstr mode; - switch (self->config->general.mode) - { - case TWAI_MODE_LISTEN_ONLY: - mode = MP_QSTR_LISTEN; - break; - case TWAI_MODE_NO_ACK: - mode = MP_QSTR_NO_ACK; - break; - case TWAI_MODE_NORMAL: - mode = MP_QSTR_NORMAL; - break; - default: - mode = MP_QSTR_UNKNOWN; - break; - } - mp_printf(print, - "CAN(tx=%u, rx=%u, baudrate=%ukb, mode=%q, loopback=%u, extframe=%u)", - self->config->general.tx_io, - self->config->general.rx_io, - self->config->baudrate, - mode, - self->loopback, - self->extframe); - } else { - mp_printf(print, "Device is not initialized"); - } -} +// rxcallback(callable) +STATIC mp_obj_t esp32_hw_can_rxcallback(mp_obj_t self_in, mp_obj_t callback_in) { + esp32_can_obj_t *self = MP_OBJ_TO_PTR(self_in); -// init(tx, rx, baudrate, mode = TWAI_MODE_NORMAL, tx_queue = 2, rx_queue = 5) -STATIC mp_obj_t machine_hw_can_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - machine_can_obj_t *self = MP_OBJ_TO_PTR(args[0]); - if (self->config->initialized) { - mp_raise_msg(&mp_type_RuntimeError, "Device is already initialized"); - return mp_const_none; + if (callback_in == mp_const_none) { + // disable callback + self->rxcallback = mp_const_none; + } else if (mp_obj_is_callable(callback_in)) { + // set up interrupt + self->rxcallback = callback_in; } - return machine_hw_can_init_helper(self, n_args - 1, args + 1, kw_args); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_hw_can_init_obj, 4, machine_hw_can_init); - -// deinit() -STATIC mp_obj_t machine_hw_can_deinit(const mp_obj_t self_in) { - const machine_can_obj_t *self = &machine_can_obj; - if (self->config->initialized != true) { - mp_raise_msg(&mp_type_RuntimeError, "Device is not initialized"); - return mp_const_none; - } - check_esp_err(twai_stop()); - check_esp_err(twai_driver_uninstall()); - self->config->initialized = false; return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_hw_can_deinit_obj, machine_hw_can_deinit); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp32_hw_can_rxcallback_obj, esp32_hw_can_rxcallback); -// CAN(bus, ...) No argument to get the object -// If no arguments are provided, the initialized object will be returned -mp_obj_t machine_hw_can_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - if (mp_obj_is_int(args[0]) != true) { - mp_raise_TypeError("bus must be a number"); - } - mp_uint_t can_idx = mp_obj_get_int(args[0]); - if (can_idx != 0) { - mp_raise_msg_varg(&mp_type_ValueError, "CAN(%d) doesn't exist", can_idx); - } - machine_can_obj_t *self = &machine_can_obj; - if (n_args > 1 || n_kw > 0) { - if (self->config->initialized) { - // The caller is requesting a reconfiguration of the hardware - // this can only be done if the hardware is in init mode - //mp_raise_msg(&mp_type_RuntimeError, "Device is going to be reconfigured"); - machine_hw_can_deinit(&self); - } - self->rxcallback = mp_const_none; - self->rx_state = RX_STATE_FIFO_EMPTY; - - // start the peripheral - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - machine_hw_can_init_helper(self, n_args - 1, args + 1, &kw_args); - } - return MP_OBJ_FROM_PTR(self); +// Clear TX Queue +STATIC mp_obj_t esp32_hw_can_clear_tx_queue(mp_obj_t self_in) { + return mp_obj_new_bool(twai_clear_transmit_queue() == ESP_OK); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_clear_tx_queue_obj, esp32_hw_can_clear_tx_queue); -// init(mode, extframe=False, baudrate=500, *) -STATIC mp_obj_t machine_hw_can_init_helper(machine_can_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { - ARG_mode, - ARG_extframe, - ARG_baudrate, - ARG_prescaler, - ARG_sjw, - ARG_bs1, - ARG_bs2, - ARG_tx_io, - ARG_rx_io, - ARG_tx_queue, - ARG_rx_queue, - ARG_auto_restart - }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = TWAI_MODE_NORMAL} }, - { MP_QSTR_extframe, MP_ARG_BOOL, {.u_bool = false} }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 500000} }, - { MP_QSTR_prescaler, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_PRESCALER} }, - { MP_QSTR_sjw, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_SJW} }, - { MP_QSTR_bs1, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS1} }, - { MP_QSTR_bs2, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = CAN_DEFAULT_BS2} }, - { MP_QSTR_tx, MP_ARG_INT, {.u_int = 17} }, - { MP_QSTR_rx, MP_ARG_INT, {.u_int = 15} }, - { MP_QSTR_tx_queue, MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_rx_queue, MP_ARG_INT, {.u_int = 1} }, - { MP_QSTR_auto_restart, MP_ARG_BOOL, {.u_bool = false} }, - }; - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - // Configure device - self->config->general.mode = args[ARG_mode].u_int & 0x0F; - self->config->general.tx_io = args[ARG_tx_io].u_int; - self->config->general.rx_io = args[ARG_rx_io].u_int; - self->config->general.clkout_io = TWAI_IO_UNUSED; - self->config->general.bus_off_io = TWAI_IO_UNUSED; - self->config->general.tx_queue_len = args[ARG_tx_queue].u_int; - self->config->general.rx_queue_len = args[ARG_rx_queue].u_int; - self->config->general.alerts_enabled = TWAI_ALERT_AND_LOG || TWAI_ALERT_BELOW_ERR_WARN || TWAI_ALERT_ERR_ACTIVE || TWAI_ALERT_BUS_RECOVERED || - TWAI_ALERT_ABOVE_ERR_WARN || TWAI_ALERT_BUS_ERROR || TWAI_ALERT_ERR_PASS || TWAI_ALERT_BUS_OFF; - self->config->general.clkout_divider = 0; - self->loopback = ((args[ARG_mode].u_int & LOOPBACK_MASK) > 0); - self->extframe = args[ARG_extframe].u_bool; - if (args[ARG_auto_restart].u_bool) { - mp_raise_NotImplementedError("Auto-restart not supported"); - } - twai_filter_config_t f_config = TWAI_FILTER_CONFIG_ACCEPT_ALL(); - self->config->filter.single_filter = self->extframe; - self->config->filter.acceptance_code = f_config.acceptance_code; - self->config->filter.acceptance_mask = f_config.acceptance_mask; - twai_timing_config_t *timing; - switch ((int)args[ARG_baudrate].u_int) { - case 0: - timing = &((twai_timing_config_t) { - .brp = args[ARG_prescaler].u_int, - .sjw = args[ARG_sjw].u_int, - .tseg_1 = args[ARG_bs1].u_int, - .tseg_2 = args[ARG_bs2].u_int, - .triple_sampling = false - }); - break; - case 25000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_25KBITS() ); - break; - case 50000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_50KBITS() ); - break; - case 100000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_100KBITS() ); - break; - case 125000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_125KBITS() ); - break; - case 250000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_250KBITS() ); - break; - case 500000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_500KBITS() ); - break; - case 800000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_800KBITS() ); - break; - case 1000000: - timing = &( (twai_timing_config_t) TWAI_TIMING_CONFIG_1MBITS() ); - break; - default: - mp_raise_ValueError("Unable to set baudrate"); - self->config->baudrate = 0; - return mp_const_none; - } - self->config->timing = *timing; - - check_esp_err(twai_driver_install( - &self->config->general, - &self->config->timing, - &(twai_filter_config_t) TWAI_FILTER_CONFIG_ACCEPT_ALL())); - check_esp_err(twai_start()); - self->config->initialized = true; - return mp_const_none; +// Clear RX Queue +STATIC mp_obj_t esp32_hw_can_clear_rx_queue(mp_obj_t self_in) { + return mp_obj_new_bool(twai_clear_receive_queue() == ESP_OK); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_hw_can_clear_rx_queue_obj, esp32_hw_can_clear_rx_queue); -STATIC const mp_rom_map_elem_t machine_can_locals_dict_table[] = { +STATIC const mp_rom_map_elem_t esp32_can_locals_dict_table[] = { // CAN_ATTRIBUTES { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_CAN) }, // Micropython Generic API - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_hw_can_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_hw_can_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&machine_hw_can_restart_obj) }, - { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&machine_hw_can_state_obj) }, - { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_hw_can_info_obj) }, - { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&machine_hw_can_any_obj) }, - { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&machine_hw_can_send_obj) }, - { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&machine_hw_can_recv_obj) }, - { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&machine_hw_can_setfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&machine_hw_can_clearfilter_obj) }, - { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&machine_hw_can_rxcallback_obj) }, + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&esp32_hw_can_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_hw_can_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&esp32_hw_can_restart_obj) }, + { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&esp32_hw_can_state_obj) }, + { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&esp32_hw_can_info_obj) }, + { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&esp32_hw_can_any_obj) }, + { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&esp32_hw_can_send_obj) }, + { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&esp32_hw_can_recv_obj) }, + { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&esp32_hw_can_setfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&esp32_hw_can_clearfilter_obj) }, + { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&esp32_hw_can_rxcallback_obj) }, // ESP32 Specific API - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&machine_hw_can_clear_tx_queue_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&machine_hw_can_clear_rx_queue_obj) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&machine_hw_can_alert_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_tx_queue), MP_ROM_PTR(&esp32_hw_can_clear_tx_queue_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_clear_rx_queue), MP_ROM_PTR(&esp32_hw_can_clear_rx_queue_obj) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_get_alerts), MP_ROM_PTR(&esp32_hw_can_alert_obj) }, // CAN_MODE { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(TWAI_MODE_NORMAL) }, - { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(TWAI_MODE_NORMAL | LOOPBACK_MASK) }, + { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(TWAI_MODE_NORMAL | CAN_MODE_SILENT_LOOPBACK) }, { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(TWAI_MODE_NO_ACK) }, -// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(TWAI_MODE_NO_ACK | LOOPBACK_MASK) }, // ESP32 not silent in fact +// { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(TWAI_MODE_NO_ACK | CAN_MODE_SILENT_LOOPBACK) }, // ESP32 not silent in fact { MP_ROM_QSTR(MP_QSTR_LISTEN_ONLY), MP_ROM_INT(TWAI_MODE_LISTEN_ONLY) }, /* esp32 can modes TWAI_MODE_NORMAL - Normal operating mode where TWAI controller can send/receive/acknowledge messages @@ -648,14 +788,27 @@ TWAI_MODE_LISTEN_ONLY - The TWAI controller will not influence the bus (No trans { MP_ROM_QSTR(MP_QSTR_ALERT_ERR_PASS), MP_ROM_INT(TWAI_ALERT_ERR_PASS) }, { MP_ROM_QSTR(MP_QSTR_ALERT_BUS_OFF), MP_ROM_INT(TWAI_ALERT_BUS_OFF) } }; -STATIC MP_DEFINE_CONST_DICT(machine_can_locals_dict, machine_can_locals_dict_table); +STATIC MP_DEFINE_CONST_DICT(esp32_can_locals_dict, esp32_can_locals_dict_table); // Python object definition -const mp_obj_type_t machine_can_type = { +MP_DEFINE_CONST_OBJ_TYPE( + esp32_can_type, + MP_QSTR_CAN, + MP_TYPE_FLAG_NONE, + make_new, esp32_hw_can_make_new, + print, esp32_hw_can_print, + locals_dict, (mp_obj_dict_t *)&esp32_can_locals_dict + ); +/* +const mp_obj_type_t esp32_can_type = { {&mp_type_type}, .name = MP_QSTR_CAN, - .print = machine_hw_can_print, // give it a print-function - .make_new = machine_hw_can_make_new, // give it a constructor - .locals_dict = (mp_obj_dict_t *)&machine_can_locals_dict, // and the global members + .print = esp32_hw_can_print, // give it a print-function + .make_new = esp32_hw_can_make_new, // give it a constructor + .locals_dict = (mp_obj_dict_t *)&esp32_can_locals_dict, // and the global members }; +*/ + #endif // MICROPY_HW_ENABLE_CAN + +#endif // ESP_IDF_VERSION diff --git a/ports/esp32/machine_can.h b/ports/esp32/machine_can.h index 2a0d2a948a09f..de5921690b659 100755 --- a/ports/esp32/machine_can.h +++ b/ports/esp32/machine_can.h @@ -27,6 +27,7 @@ #define MICROPY_INCLUDED_ESP32_CAN_H #include "modmachine.h" +#include "freertos/task.h" #include "py/obj.h" @@ -34,42 +35,34 @@ #define DEVICE_NAME "CAN" -/* -#define CAN_BAUDRATE_25k 25 -#define CAN_BAUDRATE_50k 50 -#define CAN_BAUDRATE_100k 100 -#define CAN_BAUDRATE_125k 125 -#define CAN_BAUDRATE_250k 250 -#define CAN_BAUDRATE_500k 500 -#define CAN_BAUDRATE_800k 800 -#define CAN_BAUDRATE_1M 1000 -*/ - -typedef enum _filter_mode_t{ +typedef enum _filter_mode_t { FILTER_RAW_SINGLE = 0, FILTER_RAW_DUAL, FILTER_ADDRESS } filter_mode_t; -typedef struct _machine_can_config_t { +typedef struct _esp32_can_config_t { twai_timing_config_t timing; twai_filter_config_t filter; twai_general_config_t general; uint32_t baudrate; // bit/s bool initialized; -} machine_can_config_t; +} esp32_can_config_t; -typedef struct _machine_can_obj_t { +typedef struct _esp32_can_obj_t { mp_obj_base_t base; - machine_can_config_t *config; + esp32_can_config_t *config; mp_obj_t rxcallback; + TaskHandle_t irq_handler; byte rx_state; bool extframe : 1; bool loopback : 1; + byte last_tx_success : 1; + byte bus_recovery_success : 1; uint16_t num_error_warning; //FIXME: populate this value somewhere uint16_t num_error_passive; uint16_t num_bus_off; -} machine_can_obj_t; +} esp32_can_obj_t; typedef enum _rx_state_t { RX_STATE_FIFO_EMPTY = 0, @@ -78,7 +71,7 @@ typedef enum _rx_state_t { RX_STATE_FIFO_OVERFLOW, } rx_state_t; -extern const mp_obj_type_t machine_can_type; +extern const mp_obj_type_t esp32_can_type; #endif // MICROPY_HW_ENABLE_CAN #endif // MICROPY_INCLUDED_ESP32_CAN_H From 110790f9b454ce02c3532bae6542d1c997a8b280 Mon Sep 17 00:00:00 2001 From: IhorNehrutsa Date: Sat, 25 Feb 2023 02:50:40 +0200 Subject: [PATCH 178/180] quickref.rst --- docs/esp32/quickref.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/esp32/quickref.rst b/docs/esp32/quickref.rst index d8eae3c28cf4e..04e57a5f3ba40 100644 --- a/docs/esp32/quickref.rst +++ b/docs/esp32/quickref.rst @@ -507,8 +507,8 @@ Any available output-capablepins can be used for TX, RX, BUS-OFF, and CLKOUT sig The driver is accessed via the :ref:`machine.CAN ` class:: from machine import CAN - can = CAN(0, tx=5, rx=4, extframe=True, mode=CAN.NORMAL, baudrate=500000) - can.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + can = CAN(0, tx=5, rx=4, mode=CAN.NORMAL, baudrate=500000) + can.setfilter(0, CAN.FILTER_ADDRESS, [0x102]) # set a filter to receive messages with id = 0x102 can.send([1,2,3], 0x102) # send a message with id 123 can.recv() # receive message From c0268d2881f21a38c44f131af8c838f4213f9bb4 Mon Sep 17 00:00:00 2001 From: Andrew Wingate <1464801+anfroholic@users.noreply.github.com> Date: Sat, 4 Mar 2023 07:39:24 -0600 Subject: [PATCH 179/180] Update machine.CAN.rst --- docs/library/machine.CAN.rst | 68 ++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst index 8ca920fbbfafd..47f179f49ff98 100755 --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -10,14 +10,22 @@ to connect the microcontroller to a CAN bus you must use a CAN transceiver to convert the CAN logic signals from the microcontroller to the correct voltage levels on the bus. -Example usage (works without anything connected):: +Example usage (must have transceiver connected):: from machine import CAN - BAUDRATE_500k = 500 - can = CAN(0, extframe=True, mode=CAN.LOOPBACK, baudrate=BAUDRATE_500k) - dev.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 - can.send([1,2,3], 0x102) # send a message with id 123 - can.recv() # receive message + can = CAN(0, tx=4, rx=16, extframe=True, mode=CAN.LOOPBACK, baudrate=500000) + can.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + + can.send([1,2,3], 123) # send a message with id 123 + + + can.recv() # receive message + + can.any() # returns True if FIFO is not empty, else False + can.info() # get information about the controller’s error states and TX and RX buffers + can.deinit() # turn off the can bus + can.clear_rx_queue() # clear messages in the receive buffer + can.clear_tx_queue() # clear messages in the transmit buffer Constructors @@ -36,33 +44,22 @@ Constructors Methods ------- -.. method:: CAN.init(mode, extframe=False, baudrate, prescaler, \*, sjw=1, bs1=6, bs2=8, auto_restart=False) +.. method:: CAN.init(bus, *, tx, rx, baudrate, prescaler, mode, extframe=False) Initialise the CAN bus with the given parameters: - + + - *bus* ESP32 has only one bus, but still must be defined - *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK - if *extframe* is True then the bus uses extended identifiers in the frames (29 bits); otherwise it uses standard 11 bit identifiers - - *baudrate* is used to define a standard speed. If it is defined, the *prescaler*, *sjw*, *bs1*, *bs2* - will be ignored. Standard speeds are 25, 50, 100, 125, 250, 500, 1000 - - *prescaler* is used to set the duration of 1 time quanta; the time quanta - will be the input clock divided by the prescaler - - *sjw* is the resynchronisation jump width in units of the time quanta; - it can be 1, 2, 3, 4 - - *bs1* defines the location of the sample point in units of the time quanta; - it can be between 1 and 1024 inclusive - - *bs2* defines the location of the transmit point in units of the time quanta; - it can be between 1 and 16 inclusive + - *baudrate* is used to define a standard speed. Standard speeds are 25000, 50000, 100000, 125000, 250000, 500000, 1000000 - *tx* defines the gpio used for transmission - *rx* defines the gpio used for receiving - *bus_off* defines the gpio used for BUS-OFF signal line(optional) - *clkout* defines the gpio used for CLKOUT signal line(optional) - *tx_queue* defines the number of waiting tx messages can be stored - *rx_queue* defines the number of received messages can be stored - - *auto_restart* sets whether the controller will automatically try and restart - communications after entering the bus-off state; if this is disabled then - :meth:`~CAN.restart()` can be used to leave the bus-off state. - This parameter is currently not implemented and it must be set to False + .. method:: CAN.deinit() @@ -92,27 +89,22 @@ Methods - ``CAN.RECOVERING`` -- the controller is under recover from bus-off state; -.. method:: CAN.info([list]) +.. method:: CAN.info() Get information about the controller's error states and TX and RX buffers. - If *list* is provided then it should be a list object with at least 8 entries, - which will be filled in with the information. Otherwise a new list will be - created and filled in. In both cases the return value of the method is the - populated list. + Returns a dict The values in the list are: - - TEC value - - REC value - - number of times the controller enterted the Error Warning state (wrapped - around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED - - number of times the controller enterted the Error Passive state (wrapped - around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED - - number of times the controller enterted the Bus Off state (wrapped - around to 0 after 65535) - CURRENTLY NOT IMPLEMENTED - - number of pending TX messages - - number of pending RX messages - - Reserved + - state: current state of the bus + - tx_failed_count: number of failed transmissions + - msgs_to_tx: messages in outbox ready to transmit + - rx_error_counter: number of errors on message recieve + - msgs_to_rx: number of messages in outbox + - arb_lost_count: number of times controller has lost arbitration + - rx_missed_count: number of times inbox has overflowed and message was lost + - bus_error_count: number of times there was an error on the bus + - tx_error_counter: number of times there was an error on message transmission .. method:: CAN.setfilter(bank, mode, fifo, params, \*, rtr) From 33eaf25e92925090831f1d8bec9991decaea5f7a Mon Sep 17 00:00:00 2001 From: Andrew Wingate <1464801+anfroholic@users.noreply.github.com> Date: Sat, 4 Mar 2023 08:00:06 -0600 Subject: [PATCH 180/180] Update machine.CAN.rst --- docs/library/machine.CAN.rst | 41 +++++++----------------------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/docs/library/machine.CAN.rst b/docs/library/machine.CAN.rst index 47f179f49ff98..331f64434da5e 100755 --- a/docs/library/machine.CAN.rst +++ b/docs/library/machine.CAN.rst @@ -12,15 +12,12 @@ voltage levels on the bus. Example usage (must have transceiver connected):: - from machine import CAN - can = CAN(0, tx=4, rx=16, extframe=True, mode=CAN.LOOPBACK, baudrate=500000) - can.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 - - can.send([1,2,3], 123) # send a message with id 123 - - - can.recv() # receive message - + from machine import CAN + can = CAN(0, tx=4, rx=16, extframe=True, mode=CAN.LOOPBACK, baudrate=500000) + can.setfilter(0, CAN.FILTER_ADDRESS, [0x102, 0]) # set a filter to receive messages with id = 0x102 + + can.send([1,2,3], 123) # send a message with id 123 and payload b'\x01\x02\x03' + can.recv() # receive message can.any() # returns True if FIFO is not empty, else False can.info() # get information about the controller’s error states and TX and RX buffers can.deinit() # turn off the can bus @@ -48,7 +45,7 @@ Methods Initialise the CAN bus with the given parameters: - - *bus* ESP32 has only one bus, but still must be defined + - *bus* ESP32 has only one bus, but still must be defined - *mode* is one of: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK - if *extframe* is True then the bus uses extended identifiers in the frames (29 bits); otherwise it uses standard 11 bit identifiers @@ -94,7 +91,7 @@ Methods Get information about the controller's error states and TX and RX buffers. Returns a dict - The values in the list are: + The values in the dict are: - state: current state of the bus - tx_failed_count: number of failed transmissions @@ -202,28 +199,6 @@ Methods Clear all messages from receiving queue. -.. method:: CAN.get_alerts() - - Read the alert status word directly from hardware. - In order to save space in the firmware, the constants for the result decoding are not included on the :mod:`machine.CAN` module. Add the ones that you need from the list below to your program. - - The event codes are:: - - from micropython import const - CAN_ALERT_TX_IDLE = const(0x0001) - CAN_ALERT_TX_SUCCESS = const(0x0002) - CAN_ALERT_BELOW_ERR_WARN = const(0x0004) - CAN_ALERT_ERR_ACTIVE = const(0x0008) - CAN_ALERT_RECOVERY_IN_PROGRESS = const(0x0010) - CAN_ALERT_BUS_RECOVERED = const(0x0020) - CAN_ALERT_ARB_LOST = const(0x0040) - CAN_ALERT_ABOVE_ERR_WARN = const(0x0080) - CAN_ALERT_BUS_ERROR = const(0x0100) - CAN_ALERT_TX_FAILED = const(0x0200) - CAN_ALERT_RX_QUEUE_FULL = const(0x0400) - CAN_ALERT_ERR_PASS = const(0x0800) - CAN_ALERT_BUS_OFF = const(0x1000) - Constants ---------