From 7847c5e98d7ec7ca81b0b6dd5dfbd694ef3ba512 Mon Sep 17 00:00:00 2001 From: Kevin Liu <50488882+klmchp@users.noreply.github.com> Date: Tue, 19 Apr 2022 14:32:02 +0800 Subject: [PATCH] =?UTF-8?q?Microchip=20SAM=20MCU=E6=96=B0=E5=A2=9Eethernet?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=92=8C=E9=A9=B1=E5=8A=A8=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20(#5821)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Microchip SAM MCU BSP update and add ethernet driver 1. Update Microchip SAM MCU BSP, add I2C, GMAC, ADC driver support. 2. Add ethernet driver support of SAM MCU for RT-Thread. * Add GMAC and I2C driver support 1. Update MCU BSP to support I2C/ADC/GMAC peripherals. 2. Add I2C and ethernet driver and LWIP support. 3. Update serial driver. * Add I2C driver and move some files to the common folder 1. Add I2C driver. 2. Move the same drivers and demo code to same folder to reduce duplicated code. --- bsp/microchip/README.md | 3 + bsp/microchip/common/applications/SConscript | 23 + bsp/microchip/common/applications/adc_demo.c | 74 ++ .../applications/adc_demo.h} | 10 +- .../applications/can_demo.c | 17 +- .../applications/can_demo.h | 0 bsp/microchip/common/applications/i2c_demo.c | 65 + bsp/microchip/common/applications/i2c_demo.h | 22 + bsp/microchip/common/applications/lwip_demo.c | 211 ++++ bsp/microchip/common/applications/lwip_demo.h | 22 + bsp/microchip/common/board/SConscript | 21 + bsp/microchip/common/board/sam_gmac.c | 428 +++++++ bsp/microchip/common/board/sam_gmac.h | 36 + bsp/microchip/common/board/sam_i2c.c | 122 ++ .../board/serial.h => common/board/sam_i2c.h} | 10 +- .../{same54 => common}/board/serial.c | 93 +- .../{samc21 => common}/board/serial.h | 0 .../doc/2-1-1-atmel-start-online - Copy.png | Bin 306632 -> 0 bytes .../doc/2-1-4-atmel-start-driver-stdio.png | Bin 205487 -> 87863 bytes .../doc/2-2-6-atmel-start-modify-file2.png | Bin 26533 -> 45179 bytes .../doc/3-1-9-atmel-start-rt-thread-run.png | Bin 0 -> 21886 bytes bsp/microchip/samc21/.config | 38 +- bsp/microchip/samc21/SConstruct | 19 + bsp/microchip/samc21/applications/can_demo.c | 333 ------ bsp/microchip/samc21/applications/main.c | 18 +- bsp/microchip/samc21/board/Kconfig | 11 + bsp/microchip/samc21/board/board.c | 5 +- bsp/microchip/samc21/board/serial.c | 199 ---- bsp/microchip/samc21/bsp/AtmelStart.gpdsc | 21 +- bsp/microchip/samc21/bsp/SConscript | 5 + bsp/microchip/samc21/bsp/armcc/Makefile | 218 ---- .../samc21/bsp/atmel_start_config.atstart | 122 +- bsp/microchip/samc21/bsp/atmel_start_pins.h | 3 + .../samc21/bsp/config/hpl_adc_config.h | 317 +++++ .../samc21/bsp/config/hpl_sercom_config.h | 137 ++- .../samc21/bsp/config/peripheral_clk_config.h | 96 ++ bsp/microchip/samc21/bsp/driver_init.c | 103 +- bsp/microchip/samc21/bsp/driver_init.h | 20 +- .../samc21/bsp/examples/driver_examples.c | 47 +- .../samc21/bsp/examples/driver_examples.h | 4 + .../samc21/bsp/hal/documentation/adc_sync.rst | 74 ++ .../bsp/hal/documentation/i2c_master_sync.rst | 87 ++ .../{usart_sync.rst => usart_async.rst} | 20 +- .../samc21/bsp/hal/include/hal_adc_sync.h | 277 +++++ .../samc21/bsp/hal/include/hal_i2c_m_sync.h | 244 ++++ .../samc21/bsp/hal/include/hal_usart_async.h | 339 ++++++ .../samc21/bsp/hal/include/hal_usart_sync.h | 247 ---- .../samc21/bsp/hal/include/hpl_adc_async.h | 264 +++++ .../samc21/bsp/hal/include/hpl_adc_dma.h | 243 ++++ .../samc21/bsp/hal/include/hpl_adc_sync.h | 271 +++++ .../samc21/bsp/hal/src/hal_adc_sync.c | 244 ++++ .../samc21/bsp/hal/src/hal_i2c_m_sync.c | 258 ++++ .../samc21/bsp/hal/src/hal_usart_async.c | 420 +++++++ .../samc21/bsp/hal/src/hal_usart_sync.c | 276 ----- .../bsp/hal/utils/include/utils_ringbuffer.h | 116 ++ .../bsp/hal/utils/src/utils_ringbuffer.c | 118 ++ bsp/microchip/samc21/bsp/hpl/adc/hpl_adc.c | 771 ++++++++++++ .../bsp/hpl/adc/hpl_adc_base.h} | 50 +- .../samc21/bsp/hpl/sercom/hpl_sercom.c | 45 + .../samc21/bsp/iar-project-connection.ipcf | 21 +- .../bsp/samc21/gcc/gcc/samc21j18a_flash.ld | 25 + bsp/microchip/samc21/rtconfig.h | 26 + bsp/microchip/same54/.config | 143 ++- bsp/microchip/same54/SConstruct | 19 + bsp/microchip/same54/applications/can_demo.h | 24 - bsp/microchip/same54/applications/main.c | 26 +- bsp/microchip/same54/board/Kconfig | 22 + bsp/microchip/same54/board/board.c | 7 +- bsp/microchip/same54/bsp/AtmelStart.gpdsc | 37 +- bsp/microchip/same54/bsp/SConscript | 11 +- bsp/microchip/same54/bsp/armcc/Makefile | 225 ---- bsp/microchip/same54/bsp/atmel_start.c | 1 + bsp/microchip/same54/bsp/atmel_start.h | 1 + .../same54/bsp/atmel_start_config.atstart | 345 +++++- bsp/microchip/same54/bsp/atmel_start_pins.h | 13 + .../same54/bsp/config/hpl_adc_config.h | 302 +++++ .../same54/bsp/config/hpl_gmac_config.h | 483 ++++++++ .../same54/bsp/config/hpl_sercom_config.h | 137 ++- .../bsp/config/ieee8023_mii_standard_config.h | 106 ++ .../same54/bsp/config/peripheral_clk_config.h | 120 ++ .../same54/bsp/documentation/ethernet_phy.rst | 56 + bsp/microchip/same54/bsp/driver_init.c | 159 ++- bsp/microchip/same54/bsp/driver_init.h | 30 +- .../same54/bsp/ethernet_phy/ethernet_phy.c | 184 +++ .../same54/bsp/ethernet_phy/ethernet_phy.h | 230 ++++ .../ieee8023_mii_standard_register.h | 137 +++ bsp/microchip/same54/bsp/ethernet_phy_main.c | 43 + bsp/microchip/same54/bsp/ethernet_phy_main.h | 30 + .../same54/bsp/examples/driver_examples.c | 47 +- .../same54/bsp/examples/driver_examples.h | 4 + .../same54/bsp/gcc/gcc/same54p20a_flash.ld | 25 + .../same54/bsp/hal/documentation/adc_sync.rst | 74 ++ .../bsp/hal/documentation/i2c_master_sync.rst | 87 ++ .../bsp/hal/documentation/mac_async.rst | 43 + .../bsp/hal/documentation/usart_async.rst} | 20 +- .../same54/bsp/hal/include/hal_adc_sync.h | 277 +++++ .../same54/bsp/hal/include/hal_i2c_m_sync.h | 244 ++++ .../same54/bsp/hal/include/hal_mac_async.h | 260 ++++ .../same54/bsp/hal/include/hal_usart_async.h | 339 ++++++ .../same54/bsp/hal/include/hal_usart_sync.h | 247 ---- .../same54/bsp/hal/include/hpl_adc_async.h | 264 +++++ .../same54/bsp/hal/include/hpl_adc_dma.h | 243 ++++ .../same54/bsp/hal/include/hpl_adc_sync.h | 271 +++++ .../same54/bsp/hal/include/hpl_mac_async.h | 280 +++++ .../same54/bsp/hal/src/hal_adc_sync.c | 244 ++++ .../same54/bsp/hal/src/hal_i2c_m_sync.c | 258 ++++ .../same54/bsp/hal/src/hal_mac_async.c | 222 ++++ bsp/microchip/same54/bsp/hal/src/hal_sleep.c | 4 +- .../same54/bsp/hal/src/hal_usart_async.c | 420 +++++++ .../same54/bsp/hal/src/hal_usart_sync.c | 276 ----- .../bsp/hal/utils/include/utils_ringbuffer.h | 116 ++ .../bsp/hal/utils/src/utils_ringbuffer.c | 118 ++ bsp/microchip/same54/bsp/hpl/adc/hpl_adc.c | 769 ++++++++++++ .../same54/bsp/hpl/adc/hpl_adc_base.h | 72 ++ bsp/microchip/same54/bsp/hpl/gmac/hpl_gmac.c | 538 +++++++++ .../same54/bsp/hpl/sercom/hpl_sercom.c | 69 ++ .../same54/bsp/iar-project-connection.ipcf | 44 +- bsp/microchip/same54/rtconfig.h | 100 +- bsp/microchip/same70/.config | 144 ++- bsp/microchip/same70/SConstruct | 19 + bsp/microchip/same70/applications/can_demo.c | 333 ------ bsp/microchip/same70/applications/can_demo.h | 24 - bsp/microchip/same70/applications/main.c | 26 +- bsp/microchip/same70/board/Kconfig | 22 + bsp/microchip/same70/board/board.c | 5 +- bsp/microchip/same70/board/serial.c | 199 ---- bsp/microchip/same70/bsp/AtmelStart.gpdsc | 49 +- bsp/microchip/same70/bsp/SConscript | 10 +- bsp/microchip/same70/bsp/atmel_start.c | 1 + bsp/microchip/same70/bsp/atmel_start.h | 1 + .../same70/bsp/atmel_start_config.atstart | 433 ++++++- bsp/microchip/same70/bsp/atmel_start_pins.h | 13 + .../same70/bsp/config/hpl_afec_config.h | 1042 +++++++++++++++++ .../same70/bsp/config/hpl_gmac_config.h | 492 ++++++++ .../bsp/config/hpl_systick_ARMv7_config.h | 18 - .../same70/bsp/config/hpl_twihs_config.h | 213 ++++ .../bsp/config/ieee8023_mii_standard_config.h | 106 ++ .../same70/bsp/config/peripheral_clk_config.h | 54 + .../same70/bsp/documentation/ethernet_phy.rst | 56 + bsp/microchip/same70/bsp/driver_init.c | 119 +- bsp/microchip/same70/bsp/driver_init.h | 29 +- .../same70/bsp/ethernet_phy/ethernet_phy.c | 184 +++ .../same70/bsp/ethernet_phy/ethernet_phy.h | 230 ++++ .../ieee8023_mii_standard_register.h | 137 +++ bsp/microchip/same70/bsp/ethernet_phy_main.c | 43 + bsp/microchip/same70/bsp/ethernet_phy_main.h | 30 + .../same70/bsp/examples/driver_examples.c | 52 +- .../same70/bsp/examples/driver_examples.h | 6 +- .../same70/bsp/hal/documentation/adc_sync.rst | 74 ++ .../bsp/hal/documentation/i2c_master_sync.rst | 87 ++ .../bsp/hal/documentation/mac_async.rst | 43 + .../bsp/hal/documentation/usart_async.rst} | 20 +- .../same70/bsp/hal/include/hal_adc_sync.h | 277 +++++ .../same70/bsp/hal/include/hal_i2c_m_sync.h | 244 ++++ .../same70/bsp/hal/include/hal_mac_async.h | 260 ++++ .../same70/bsp/hal/include/hal_usart_async.h | 339 ++++++ .../same70/bsp/hal/include/hal_usart_sync.h | 247 ---- .../same70/bsp/hal/include/hpl_adc_async.h | 264 +++++ .../same70/bsp/hal/include/hpl_adc_sync.h | 271 +++++ .../same70/bsp/hal/include/hpl_i2c_m_async.h | 205 ++++ .../same70/bsp/hal/include/hpl_i2c_m_sync.h | 185 +++ .../same70/bsp/hal/include/hpl_i2c_s_async.h | 184 +++ .../same70/bsp/hal/include/hpl_i2c_s_sync.h | 184 +++ .../same70/bsp/hal/include/hpl_mac_async.h | 280 +++++ .../same70/bsp/hal/src/hal_adc_sync.c | 244 ++++ .../same70/bsp/hal/src/hal_i2c_m_sync.c | 258 ++++ .../same70/bsp/hal/src/hal_mac_async.c | 222 ++++ bsp/microchip/same70/bsp/hal/src/hal_sleep.c | 4 +- .../same70/bsp/hal/src/hal_usart_async.c | 420 +++++++ .../same70/bsp/hal/src/hal_usart_sync.c | 276 ----- bsp/microchip/same70/bsp/hpl/afec/hpl_afec.c | 638 ++++++++++ .../same70/bsp/hpl/core/hpl_core_m7_base.c | 57 +- bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac.c | 567 +++++++++ .../same70/bsp/hpl/gmac/hpl_gmac_base.h | 102 ++ .../bsp/hpl/systick/hpl_systick_ARMv7_base.c | 106 -- .../same70/bsp/hpl/twihs/hpl_twihs.c | 307 +++++ .../same70/bsp/hpl/usart/hpl_usart.c | 137 ++- .../same70/bsp/iar-project-connection.ipcf | 60 +- .../bsp/same70b/gcc/gcc/same70q21b_flash.ld | 25 + bsp/microchip/same70/rtconfig.h | 106 +- 180 files changed, 23396 insertions(+), 3562 deletions(-) create mode 100644 bsp/microchip/common/applications/SConscript create mode 100644 bsp/microchip/common/applications/adc_demo.c rename bsp/microchip/{same54/board/serial.h => common/applications/adc_demo.h} (54%) rename bsp/microchip/{same54 => common}/applications/can_demo.c (96%) rename bsp/microchip/{samc21 => common}/applications/can_demo.h (100%) create mode 100644 bsp/microchip/common/applications/i2c_demo.c create mode 100644 bsp/microchip/common/applications/i2c_demo.h create mode 100644 bsp/microchip/common/applications/lwip_demo.c create mode 100644 bsp/microchip/common/applications/lwip_demo.h create mode 100644 bsp/microchip/common/board/SConscript create mode 100644 bsp/microchip/common/board/sam_gmac.c create mode 100644 bsp/microchip/common/board/sam_gmac.h create mode 100644 bsp/microchip/common/board/sam_i2c.c rename bsp/microchip/{same70/board/serial.h => common/board/sam_i2c.h} (55%) rename bsp/microchip/{same54 => common}/board/serial.c (53%) rename bsp/microchip/{samc21 => common}/board/serial.h (100%) delete mode 100644 bsp/microchip/doc/2-1-1-atmel-start-online - Copy.png create mode 100644 bsp/microchip/doc/3-1-9-atmel-start-rt-thread-run.png delete mode 100644 bsp/microchip/samc21/applications/can_demo.c delete mode 100644 bsp/microchip/samc21/board/serial.c delete mode 100644 bsp/microchip/samc21/bsp/armcc/Makefile create mode 100644 bsp/microchip/samc21/bsp/config/hpl_adc_config.h create mode 100644 bsp/microchip/samc21/bsp/hal/documentation/adc_sync.rst create mode 100644 bsp/microchip/samc21/bsp/hal/documentation/i2c_master_sync.rst rename bsp/microchip/samc21/bsp/hal/documentation/{usart_sync.rst => usart_async.rst} (62%) create mode 100644 bsp/microchip/samc21/bsp/hal/include/hal_adc_sync.h create mode 100644 bsp/microchip/samc21/bsp/hal/include/hal_i2c_m_sync.h create mode 100644 bsp/microchip/samc21/bsp/hal/include/hal_usart_async.h delete mode 100644 bsp/microchip/samc21/bsp/hal/include/hal_usart_sync.h create mode 100644 bsp/microchip/samc21/bsp/hal/include/hpl_adc_async.h create mode 100644 bsp/microchip/samc21/bsp/hal/include/hpl_adc_dma.h create mode 100644 bsp/microchip/samc21/bsp/hal/include/hpl_adc_sync.h create mode 100644 bsp/microchip/samc21/bsp/hal/src/hal_adc_sync.c create mode 100644 bsp/microchip/samc21/bsp/hal/src/hal_i2c_m_sync.c create mode 100644 bsp/microchip/samc21/bsp/hal/src/hal_usart_async.c delete mode 100644 bsp/microchip/samc21/bsp/hal/src/hal_usart_sync.c create mode 100644 bsp/microchip/samc21/bsp/hal/utils/include/utils_ringbuffer.h create mode 100644 bsp/microchip/samc21/bsp/hal/utils/src/utils_ringbuffer.c create mode 100644 bsp/microchip/samc21/bsp/hpl/adc/hpl_adc.c rename bsp/microchip/{same70/bsp/hal/include/hpl_time_measure.h => samc21/bsp/hpl/adc/hpl_adc_base.h} (56%) delete mode 100644 bsp/microchip/same54/applications/can_demo.h delete mode 100644 bsp/microchip/same54/bsp/armcc/Makefile create mode 100644 bsp/microchip/same54/bsp/config/hpl_adc_config.h create mode 100644 bsp/microchip/same54/bsp/config/hpl_gmac_config.h create mode 100644 bsp/microchip/same54/bsp/config/ieee8023_mii_standard_config.h create mode 100644 bsp/microchip/same54/bsp/documentation/ethernet_phy.rst create mode 100644 bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.c create mode 100644 bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.h create mode 100644 bsp/microchip/same54/bsp/ethernet_phy/ieee8023_mii_standard_register.h create mode 100644 bsp/microchip/same54/bsp/ethernet_phy_main.c create mode 100644 bsp/microchip/same54/bsp/ethernet_phy_main.h create mode 100644 bsp/microchip/same54/bsp/hal/documentation/adc_sync.rst create mode 100644 bsp/microchip/same54/bsp/hal/documentation/i2c_master_sync.rst create mode 100644 bsp/microchip/same54/bsp/hal/documentation/mac_async.rst rename bsp/microchip/{same70/bsp/hal/documentation/usart_sync.rst => same54/bsp/hal/documentation/usart_async.rst} (62%) create mode 100644 bsp/microchip/same54/bsp/hal/include/hal_adc_sync.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hal_i2c_m_sync.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hal_mac_async.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hal_usart_async.h delete mode 100644 bsp/microchip/same54/bsp/hal/include/hal_usart_sync.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hpl_adc_async.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hpl_adc_dma.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hpl_adc_sync.h create mode 100644 bsp/microchip/same54/bsp/hal/include/hpl_mac_async.h create mode 100644 bsp/microchip/same54/bsp/hal/src/hal_adc_sync.c create mode 100644 bsp/microchip/same54/bsp/hal/src/hal_i2c_m_sync.c create mode 100644 bsp/microchip/same54/bsp/hal/src/hal_mac_async.c create mode 100644 bsp/microchip/same54/bsp/hal/src/hal_usart_async.c delete mode 100644 bsp/microchip/same54/bsp/hal/src/hal_usart_sync.c create mode 100644 bsp/microchip/same54/bsp/hal/utils/include/utils_ringbuffer.h create mode 100644 bsp/microchip/same54/bsp/hal/utils/src/utils_ringbuffer.c create mode 100644 bsp/microchip/same54/bsp/hpl/adc/hpl_adc.c create mode 100644 bsp/microchip/same54/bsp/hpl/adc/hpl_adc_base.h create mode 100644 bsp/microchip/same54/bsp/hpl/gmac/hpl_gmac.c delete mode 100644 bsp/microchip/same70/applications/can_demo.c delete mode 100644 bsp/microchip/same70/applications/can_demo.h delete mode 100644 bsp/microchip/same70/board/serial.c create mode 100644 bsp/microchip/same70/bsp/config/hpl_afec_config.h create mode 100644 bsp/microchip/same70/bsp/config/hpl_gmac_config.h delete mode 100644 bsp/microchip/same70/bsp/config/hpl_systick_ARMv7_config.h create mode 100644 bsp/microchip/same70/bsp/config/hpl_twihs_config.h create mode 100644 bsp/microchip/same70/bsp/config/ieee8023_mii_standard_config.h create mode 100644 bsp/microchip/same70/bsp/documentation/ethernet_phy.rst create mode 100644 bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.c create mode 100644 bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.h create mode 100644 bsp/microchip/same70/bsp/ethernet_phy/ieee8023_mii_standard_register.h create mode 100644 bsp/microchip/same70/bsp/ethernet_phy_main.c create mode 100644 bsp/microchip/same70/bsp/ethernet_phy_main.h create mode 100644 bsp/microchip/same70/bsp/hal/documentation/adc_sync.rst create mode 100644 bsp/microchip/same70/bsp/hal/documentation/i2c_master_sync.rst create mode 100644 bsp/microchip/same70/bsp/hal/documentation/mac_async.rst rename bsp/microchip/{same54/bsp/hal/documentation/usart_sync.rst => same70/bsp/hal/documentation/usart_async.rst} (62%) create mode 100644 bsp/microchip/same70/bsp/hal/include/hal_adc_sync.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hal_i2c_m_sync.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hal_mac_async.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hal_usart_async.h delete mode 100644 bsp/microchip/same70/bsp/hal/include/hal_usart_sync.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_adc_async.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_adc_sync.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_async.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_sync.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_async.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_sync.h create mode 100644 bsp/microchip/same70/bsp/hal/include/hpl_mac_async.h create mode 100644 bsp/microchip/same70/bsp/hal/src/hal_adc_sync.c create mode 100644 bsp/microchip/same70/bsp/hal/src/hal_i2c_m_sync.c create mode 100644 bsp/microchip/same70/bsp/hal/src/hal_mac_async.c create mode 100644 bsp/microchip/same70/bsp/hal/src/hal_usart_async.c delete mode 100644 bsp/microchip/same70/bsp/hal/src/hal_usart_sync.c create mode 100644 bsp/microchip/same70/bsp/hpl/afec/hpl_afec.c create mode 100644 bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac.c create mode 100644 bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac_base.h delete mode 100644 bsp/microchip/same70/bsp/hpl/systick/hpl_systick_ARMv7_base.c create mode 100644 bsp/microchip/same70/bsp/hpl/twihs/hpl_twihs.c diff --git a/bsp/microchip/README.md b/bsp/microchip/README.md index b88d64ad75..23aafff20e 100644 --- a/bsp/microchip/README.md +++ b/bsp/microchip/README.md @@ -183,6 +183,9 @@ About RT-Thread env tools, click [Here](https://github.com/RT-Thread/rt-thread/b ![](doc/3-1-8-atmel-start-Studio7-start-debugging3.png) + * Debugging message output. + +![](doc/3-1-9-atmel-start-rt-thread-run.png) # 4. Reconfigure MCU BSP diff --git a/bsp/microchip/common/applications/SConscript b/bsp/microchip/common/applications/SConscript new file mode 100644 index 0000000000..9bc4192bd2 --- /dev/null +++ b/bsp/microchip/common/applications/SConscript @@ -0,0 +1,23 @@ +import rtconfig +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +#remove other no use files +if GetDepend('SAM_CAN_EXAMPLE') == False: + SrcRemove(src, ['can_demo.c']) + +if GetDepend('SAM_I2C_EXAMPLE') == False: + SrcRemove(src, ['i2c_demo.c']) + +if GetDepend('SAM_ADC_EXAMPLE') == False: + SrcRemove(src, ['adc_demo.c']) + +if GetDepend('SAM_LWIP_EXAMPLE') == False: + SrcRemove(src, ['lwip_demo.c']) + +group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/microchip/common/applications/adc_demo.c b/bsp/microchip/common/applications/adc_demo.c new file mode 100644 index 0000000000..900719f97e --- /dev/null +++ b/bsp/microchip/common/applications/adc_demo.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#include + +#include + +#include "adc_demo.h" + +#ifdef SAM_ADC_EXAMPLE + +#if defined(SOC_SAMC21) +#define ADC_RESOLUTION_12BIT ADC_CTRLC_RESSEL_12BIT_Val +#define ADC_RESOLUTION_16BIT ADC_CTRLC_RESSEL_16BIT_Val +#elif defined(SOC_SAME54) +#define ADC_RESOLUTION_12BIT ADC_CTRLB_RESSEL_12BIT_Val +#define ADC_RESOLUTION_16BIT ADC_CTRLB_RESSEL_16BIT_Val +#elif defined(SOC_SAME70) +#define ADC_RESOLUTION_12BIT AFEC_EMR_RES_NO_AVERAGE_Val +#define ADC_RESOLUTION_16BIT AFEC_EMR_RES_OSR256_Val +#else +#error "ADC undefined SOC Platform" +#endif + +/** + * @brief Call this function will run ADC test code. + * + * @note Test code will try to read ADC conversion result. + * + * @param None. + * + * @return RT_OK or -RT_ERROR. + */ + +rt_err_t adc_demo_run(void) +{ + rt_uint8_t buffer[2]; + + /* enable ADC driver module */ + adc_sync_enable_channel(&ADC_0, 0); + + adc_sync_read_channel(&ADC_0, 0, buffer, 2); +#ifndef RT_USING_FINSH + rt_kprintf("buf[0]=0x%02X buf[1]=0x%02X\r\n", buffer[0], buffer[1]); +#endif + + /* ADC 16-bit resolution */ + adc_sync_disable_channel(&ADC_0, 0); + adc_sync_set_resolution(&ADC_0, ADC_RESOLUTION_16BIT); + adc_sync_enable_channel(&ADC_0, 0); +#ifndef RT_USING_FINSH + rt_kprintf("buf[0]=0x%02X buf[1]=0x%02X\r\n", buffer[0], buffer[1]); +#endif + + /* ADC 12-bit resolution */ + adc_sync_disable_channel(&ADC_0, 0); + adc_sync_set_resolution(&ADC_0, ADC_RESOLUTION_12BIT); + adc_sync_enable_channel(&ADC_0, 0); +#ifndef RT_USING_FINSH + rt_kprintf("buf[0]=0x%02X buf[1]=0x%02X\r\n", buffer[0], buffer[1]); +#endif + + return RT_EOK; +} +#endif + +/*@}*/ diff --git a/bsp/microchip/same54/board/serial.h b/bsp/microchip/common/applications/adc_demo.h similarity index 54% rename from bsp/microchip/same54/board/serial.h rename to bsp/microchip/common/applications/adc_demo.h index 12e6811231..5819343be8 100644 --- a/bsp/microchip/same54/board/serial.h +++ b/bsp/microchip/common/applications/adc_demo.h @@ -5,11 +5,11 @@ * * Change Logs: * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + * 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release */ -#ifndef __BOARD_SERIAL_H_ -#define __BOARD_SERIAL_H_ +#ifndef __APPLICATION_ADC_H_ +#define __APPLICATION_ADC_H_ #include @@ -17,6 +17,6 @@ * @brief External function definitions * */ -int rt_hw_uart_init(void); +rt_err_t adc_demo_run(void); -#endif // __BOARD_SERIAL_H_ +#endif // __APPLICATION_I2C_H_ diff --git a/bsp/microchip/same54/applications/can_demo.c b/bsp/microchip/common/applications/can_demo.c similarity index 96% rename from bsp/microchip/same54/applications/can_demo.c rename to bsp/microchip/common/applications/can_demo.c index a21f755725..25a009f769 100644 --- a/bsp/microchip/same54/applications/can_demo.c +++ b/bsp/microchip/common/applications/can_demo.c @@ -5,16 +5,11 @@ * * Change Logs: * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + * 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release */ #include -#ifdef RT_USING_FINSH -#include -#include -#endif - #include "atmel_start.h" #include "driver_init.h" #include "utils.h" @@ -23,6 +18,14 @@ #ifdef SAM_CAN_EXAMPLE +#if defined(SOC_SAMC21) || defined(SOC_SAME54) +#define CAN_HARDWARE (void *)CAN1 +#elif defined(SOC_SAME70) +#define CAN_HARDWARE (void *)MCAN1 +#else +#error "CAN undefined SOC Platform" +#endif + static volatile enum can_async_interrupt_type can_errors; static rt_sem_t can_txdone; static rt_sem_t can_rxdone; @@ -251,7 +254,7 @@ static void can_thread_entry(void* parameter) /* CAN task got CAN error message, handler CAN Error Status */ if ((can_errors == CAN_IRQ_BO) || (can_errors == CAN_IRQ_DO)) { - can_async_init(&CAN_0, CAN1); + can_async_init(&CAN_0, CAN_HARDWARE); } } } diff --git a/bsp/microchip/samc21/applications/can_demo.h b/bsp/microchip/common/applications/can_demo.h similarity index 100% rename from bsp/microchip/samc21/applications/can_demo.h rename to bsp/microchip/common/applications/can_demo.h diff --git a/bsp/microchip/common/applications/i2c_demo.c b/bsp/microchip/common/applications/i2c_demo.c new file mode 100644 index 0000000000..6e6d132286 --- /dev/null +++ b/bsp/microchip/common/applications/i2c_demo.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#include + +#include + +#include "i2c_demo.h" + +#ifdef SAM_I2C_EXAMPLE + +#define I2C_AT24MAC_PGMAXSZ (16+1) +#define CONF_AT24MAC_ADDRESS 0x57 + +/** + * @brief Call this function will run I2C test code. + * + * @note Test code will try to read/write external EEPROM. + * + * @param None. + * + * @return RT_OK or -RT_ERROR. + */ + +rt_err_t i2c_demo_run(void) +{ + rt_uint8_t addr = 0x20; + rt_int32_t len; + rt_uint8_t i2ctx[I2C_AT24MAC_PGMAXSZ]; + rt_uint8_t i2crx[I2C_AT24MAC_PGMAXSZ]; + + for (len = 1; len < I2C_AT24MAC_PGMAXSZ; len++) + { + i2ctx[len] = (rt_uint8_t)(len + 0x20); + } + + /* enable I2C master and set slave address before use I2C driver module */ + i2c_m_sync_enable(&I2C_0); + i2c_m_sync_set_slaveaddr(&I2C_0, CONF_AT24MAC_ADDRESS, I2C_M_SEVEN); + + /* write 16bytes data to address 0x20 - I2C slave address + random address + write data[0]...[n] */ + i2ctx[0] = addr; /* Refer to AT24MAC data sheet, first byte is page address. */ + io_write(&(I2C_0.io), i2ctx, I2C_AT24MAC_PGMAXSZ); + + /* Refer to data sheet, for random read, should send read address first. */ + io_write(&(I2C_0.io), &addr, 1); + + /* Then start I2C read after send I2C slave address first */ + io_read(&(I2C_0.io), &i2crx[1], 16); +#ifndef RT_USING_FINSH + rt_kprintf("i2crx[0]=0x%02X i2crx[15]=0x%02X\r\n", i2crx[0], i2crx[15]); +#endif + + return RT_EOK; +} +#endif + +/*@}*/ diff --git a/bsp/microchip/common/applications/i2c_demo.h b/bsp/microchip/common/applications/i2c_demo.h new file mode 100644 index 0000000000..7fc4b4af6e --- /dev/null +++ b/bsp/microchip/common/applications/i2c_demo.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#ifndef __APPLICATION_I2C_H_ +#define __APPLICATION_I2C_H_ + +#include + +/** + * @brief External function definitions + * + */ +rt_err_t i2c_demo_run(void); + +#endif // __APPLICATION_I2C_H_ diff --git a/bsp/microchip/common/applications/lwip_demo.c b/bsp/microchip/common/applications/lwip_demo.c new file mode 100644 index 0000000000..85c6a97d93 --- /dev/null +++ b/bsp/microchip/common/applications/lwip_demo.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2006-2022, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2022-01-24 ChungHsuan improve code comments + */ + +#include +#include + +#if !defined(SAL_USING_POSIX) +#error "Please enable SAL_USING_POSIX!" +#else +#include +#include +#endif +#include /* socket.h header file is needed when using BSD socket */ /* 使用BSD socket,需要包含socket.h头文件 */ +#include "netdb.h" + +#define DEBUG_TCP_CLIENT + +#define DBG_TAG "TCP" +#ifdef DEBUG_TCP_CLIENT +#define DBG_LVL DBG_LOG +#else +#define DBG_LVL DBG_INFO /* DBG_ERROR */ +#endif +#include + +#include "lwip_demo.h" + +#ifdef SAM_LWIP_EXAMPLE + +#define BUFSZ 1024 + +static int started = 0; +static int is_running = 0; +static char url[256] = "www.baidu.com"; +static int port = 8080; +static const char send_data[] = "This is TCP Client from RT-Thread."; /* The message be sent */ /* 发送用到的数据 */ + +/** +* @brief This function is for creating a tcp client on RT-Thread +*/ +static void tcpclient(void *arg) +{ + int ret; + char *recv_data; + int bytes_received; + int sock = -1; + struct hostent *host = RT_NULL; + struct sockaddr_in server_addr; + + struct timeval timeout; + fd_set readset; + /* Get host address by parameter url(Domain name resolution if input domain) */ + /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ + host = gethostbyname(url); + if (host == RT_NULL) + { + LOG_E("Get host by name failed!"); + return; + } + /* Allocate space for recv_data */ + /* 分配用于存放接收数据的缓冲 */ + recv_data = rt_malloc(BUFSZ); + if (recv_data == RT_NULL) + { + LOG_E("No memory"); + return; + } + /* Create a socket and set it to SOCK_STREAM(TCP) */ + /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) + { + /* Failed on creatinf socket */ + /* 创建socket失败 */ + LOG_E("Create socket error"); + goto __exit; + } + /* Initialize server side address */ + /* 初始化预连接的服务端地址 */ + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(port); + server_addr.sin_addr = *((struct in_addr *)host->h_addr); + rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); + /* Connect to server */ + /* 连接到服务端 */ + if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) + { + /*Failed on connecting to server*/ + /* 连接失败 */ + LOG_E("Connect fail!"); + goto __exit; + } + + started = 1; + is_running = 1; + + timeout.tv_sec = 3; + timeout.tv_usec = 0; + + while (is_running) + { + FD_ZERO(&readset); + FD_SET(sock, &readset); + + /* Wait for read */ + if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0) + continue; + /* Receive the maximum size 1024 bytes from socket */ + /* 从sock连接中接收最大BUFSZ - 1字节数据 */ + bytes_received = recv(sock, recv_data, BUFSZ - 1, 0); + if (bytes_received < 0) + { + /* Receive failed and close the connection */ + /* 接收失败,关闭这个连接 */ + LOG_E("Received error, close the socket."); + goto __exit; + } + else if (bytes_received == 0) + { + /* Print warning message when recv function return 0 */ + /* 打印recv函数返回值为0的警告信息 */ + LOG_W("Received warning, recv function return 0."); + continue; + } + else + { + /* Receive data sucessfully and append '\0' at the end of message */ + /* 有接收到数据,把末端清零 */ + recv_data[bytes_received] = '\0'; + + if (rt_strcmp(recv_data, "q") == 0 || rt_strcmp(recv_data, "Q") == 0) + { + /* If the first letter is 'q' or 'Q', close the connection */ + /* 如果是首字母是q或Q,关闭这个连接 */ + LOG_I("Got a 'q' or 'Q', close the socket."); + goto __exit; + } + else + { + /* Show the message in terminal */ + /* 在控制终端显示收到的数据 */ + LOG_D("Received data = %s", recv_data); + } + } + /* Send message to connected socket */ + /* 发送数据到sock连接 */ + ret = send(sock, send_data, rt_strlen(send_data), 0); + if (ret < 0) + { + /* Send failed, close the connection */ + /* 发送失败,关闭这个连接 */ + LOG_I("send error, close the socket."); + goto __exit; + } + else if (ret == 0) + { + /* Print warning message when send function return 0 */ + /* 打印send函数返回值为0的警告信息 */ + LOG_W("Send warning, send function return 0."); + } + } + +__exit: + if (recv_data) + { + rt_free(recv_data); + recv_data = RT_NULL; + } + if (sock >= 0) + { + closesocket(sock); + sock = -1; + } + started = 0; + is_running = 0; + return; +} + +/** + * @brief Call this function will run LWIP example code. + * + * @note . + * + * @param None. + * + * @return RT_OK or -RT_ERROR. + */ + +rt_err_t lwip_demo_run(void) +{ + rt_thread_t tid; + + tid = rt_thread_create("tcp_client", + tcpclient, RT_NULL, + 2048, RT_THREAD_PRIORITY_MAX/3, 20); + if (tid != RT_NULL) + { + rt_thread_startup(tid); + } + + return RT_EOK; +} +#endif + +/*@}*/ diff --git a/bsp/microchip/common/applications/lwip_demo.h b/bsp/microchip/common/applications/lwip_demo.h new file mode 100644 index 0000000000..9c2abd3989 --- /dev/null +++ b/bsp/microchip/common/applications/lwip_demo.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#ifndef __APPLICATION_LWIP_H_ +#define __APPLICATION_LWIP_H_ + +#include + +/** + * @brief External function definitions + * + */ +rt_err_t lwip_demo_run(void); + +#endif // __APPLICATION_LWIP_H_ diff --git a/bsp/microchip/common/board/SConscript b/bsp/microchip/common/board/SConscript new file mode 100644 index 0000000000..a32002a272 --- /dev/null +++ b/bsp/microchip/common/board/SConscript @@ -0,0 +1,21 @@ +Import('RTT_ROOT') +Import('rtconfig') +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd] + +#remove other no use files +if GetDepend('SAM_I2C_EXAMPLE') == False: + SrcRemove(src, ['sam_i2c.c']) + +if GetDepend('SAM_LWIP_EXAMPLE') == False: + SrcRemove(src, ['sam_gmac.c']) + +# You can select chips from the list above +CPPDEFINES = [] + +group = DefineGroup('Drivers', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES) + +Return('group') \ No newline at end of file diff --git a/bsp/microchip/common/board/sam_gmac.c b/bsp/microchip/common/board/sam_gmac.c new file mode 100644 index 0000000000..953c3430f4 --- /dev/null +++ b/bsp/microchip/common/board/sam_gmac.c @@ -0,0 +1,428 @@ +/* + * Copyright (c) + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-06 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "board.h" +#include "sam_gmac.h" + +#ifdef RT_USING_LWIP + +struct rt_sam_eth +{ + /* inherit from ethernet device */ + struct eth_device parent; + + struct mac_async_descriptor *macif; + struct ethernet_phy_descriptor *phyif; + +#ifdef RT_USING_TIMER_SOFT + rt_timer_t phy_monitor_timer; +#else + rt_thread_t phy_monitor_tid; +#endif + + /* ethernet MAC address */ + rt_uint8_t mac_addr[NETIF_MAX_HWADDR_LEN]; + + /* GMAC Link Speed */ + gmac_speed_type link_speed; + /* GMAC Link Mode */ + gmac_duplex_type link_mode; +}; + +static struct rt_sam_eth sam_eth_device; + +/** + * @brief Called by GMAC RX interrupt, will notify RX task + * + * @note Will call eth_device_ready to notify RX task. + * + * @param + * + * @return + */ +static void rt_sam_gmac_rxcb(void) +{ + rt_err_t result; + + /* enter interrupt */ + rt_interrupt_enter(); + + result = eth_device_ready(&sam_eth_device.parent); + if (result != RT_EOK) + LOG_E("rt_sam_gmac_rxcb error"); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +/** + * @brief Initialize the MAC hardware + * + * @note Will set MAC filter by using input MAC address. + * + * @param gmac_dev GMAC device description. + * + * @return + */ +static inline void rt_sam_gmac_init(struct rt_sam_eth *gmac_dev) +{ + struct mac_async_filter filter; + + /* set MAC hardware address */ + rt_memcpy(filter.mac, sam_eth_device.mac_addr, NETIF_MAX_HWADDR_LEN); + filter.tid_enable = false; + mac_async_set_filter(gmac_dev->macif, 0, &filter); + mac_async_register_callback(gmac_dev->macif, MAC_ASYNC_RECEIVE_CB, (FUNC_PTR)rt_sam_gmac_rxcb); +} + +static rt_err_t rt_sam_eth_init(rt_device_t dev) +{ + LOG_D("gmac init"); + return RT_EOK; +} + +static rt_err_t rt_sam_eth_open(rt_device_t dev, rt_uint16_t oflag) +{ + LOG_D("gmac open"); + return RT_EOK; +} + +static rt_err_t rt_sam_eth_close(rt_device_t dev) +{ + LOG_D("gmac close"); + return RT_EOK; +} + +static rt_size_t rt_sam_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + LOG_D("gmac read"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_size_t rt_sam_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + LOG_D("gmac write"); + rt_set_errno(-RT_ENOSYS); + return 0; +} + +static rt_err_t rt_sam_eth_control(rt_device_t dev, int cmd, void *args) +{ + rt_err_t ret = RT_EOK; + + switch (cmd) + { + case NIOCTL_GADDR: + /* get mac address */ + if (args) + rt_memcpy(args, sam_eth_device.mac_addr, 6); + break; + + default : + break; + } + + return ret; +} + +/** + * @brief Transmission packet though the MAC hardware + * + * @note Send package to MAC. + * + * @param dev the RT net device input. + * + * @param p stored message will be sent to MAC. + * + * @return RT_EOK. + */ +rt_err_t rt_sam_eth_tx(rt_device_t dev, struct pbuf *p) +{ + struct rt_sam_eth *gmac_dev = (struct rt_sam_eth *)dev->user_data; + struct pbuf * q; + void * tbuf; + uint8_t * pos; + +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + if (p->tot_len == p->len) + { + mac_async_write(gmac_dev->macif, p->payload, p->tot_len); + } + else + { + tbuf = mem_malloc(LWIP_MEM_ALIGN_SIZE(p->tot_len)); + pos = tbuf; + if (tbuf == NULL) + { + return ERR_MEM; + } + for (q = p; q != NULL; q = q->next) + { + rt_memcpy(pos, q->payload, q->len); + pos += q->len; + } + mac_async_write(gmac_dev->macif, tbuf, p->tot_len); + mem_free(tbuf); + } + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.xmit); + + return ERR_OK; +} + +/** + * @brief Receive packet from the MAC hardware + * + * @note Returned pbuf filled with the received packet (including MAC header) + * + * @param dev the RT net device input. + * + * @return NULL on memory error + */ +struct pbuf *rt_sam_eth_rx(rt_device_t dev) +{ + struct rt_sam_eth *gmac_dev = (struct rt_sam_eth *)dev->user_data; + struct pbuf * p; + u16_t len; + + len = mac_async_read_len(gmac_dev->macif); /* Obtain the size of the packet */ + if (len == 0) + { + return NULL; + } + +#if ETH_PAD_SIZE + len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ +#endif + + /* Allocate a pbuf as one large chunk, This include protocol header */ + p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); + + if (p != NULL) + { +#if ETH_PAD_SIZE + pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ +#endif + + /* Read the entire packet into the pbuf. */ + mac_async_read(gmac_dev->macif, p->payload, p->len); + +#if ETH_PAD_SIZE + pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ +#endif + + LINK_STATS_INC(link.recv); + } + else + { + mac_async_read(gmac_dev->macif, NULL, 0); + LINK_STATS_INC(link.memerr); + LINK_STATS_INC(link.drop); + } + + return p; +} + +/** + * @brief PHY link status monitor task - timer task or thread + * + * @note Will check link status, link mode and link speed + * + * @param parameter input parameter passing to the function. + * + * @return + */ +static void rt_sam_eth_monitor(void *parameter) +{ + struct rt_sam_eth *sam_eth = (struct rt_sam_eth *)parameter; + bool link_up; + int32_t ret; + uint16_t val; + static rt_uint8_t link_count = 0; + +#ifndef RT_USING_TIMER_SOFT + while (1) + { +#endif + ret = ethernet_phy_get_link_status(sam_eth->phyif, &link_up); + if (ERR_NONE == ret) + { + if (link_up) + { + /* send link up. */ + eth_device_linkchange(&sam_eth->parent, RT_TRUE); + } + else + { + /* send link down. */ + eth_device_linkchange(&sam_eth->parent, RT_FALSE);; + } + } + + ret = ethernet_phy_read_reg(sam_eth->phyif, MDIO_REG1_BMSR, &val); + if (ERR_NONE == ret) + { + if (val & (MDIO_REG1_BIT_100BASE_TX_FD | MDIO_REG1_BIT_100BASE_TX_HD)) + { + LOG_D("100Mbps"); + sam_eth_device.link_speed = GMAC_SPEED_100MBPS; + } + else + { + LOG_D("10Mbps"); + sam_eth_device.link_speed = GMAC_SPEED_10MBPS; + } + + if (val & (MDIO_REG1_BIT_100BASE_TX_FD | MDIO_REG1_BIT_10BASE_T_FD)) + { + LOG_D("100Mbps"); + sam_eth_device.link_mode = GMAC_FULL_DUPLEX; + } + else + { + LOG_D("10Mbps"); + sam_eth_device.link_mode = GMAC_HALF_DUPLEX; + } + } + + if (link_count >= 10) + { + link_count = 0; + + /* Restart an auto-negotiation */ + ethernet_phy_restart_autoneg(sam_eth->phyif); + } + +#ifndef RT_USING_TIMER_SOFT + rt_thread_mdelay(1000); + } +#endif +} + +/** + * @brief Register the GMAC Ethernet device. + * + * @note + * + * @param + * + * @return RT_OK or RT_ERROR. + */ + +static int rt_hw_sam_eth_init(void) +{ + rt_err_t state = RT_EOK; +#if CONF_AT24MAC_ADDRESS != 0 + rt_uint8_t addr = 0x9A; +#endif + + sam_eth_device.macif = &MACIF; + sam_eth_device.phyif = &MACIF_PHY_desc; + + sam_eth_device.link_speed = GMAC_SPEED_100MBPS; + sam_eth_device.link_mode = GMAC_FULL_DUPLEX; + +#if CONF_AT24MAC_ADDRESS != 0 + i2c_m_sync_enable(&I2C_0); + i2c_m_sync_set_slaveaddr(&I2C_0, CONF_AT24MAC_ADDRESS, I2C_M_SEVEN); + io_write(&(I2C_0.io), &addr, 1); + io_read(&(I2C_0.io), sam_eth_device.mac_addr, 6); +#else + /* set mac to 0x11 if no EEPROM mounted */ + memset(sam_eth_device.mac_addr, 0x11, 6); +#endif + + sam_eth_device.parent.parent.init = rt_sam_eth_init; + sam_eth_device.parent.parent.open = rt_sam_eth_open; + sam_eth_device.parent.parent.close = rt_sam_eth_close; + sam_eth_device.parent.parent.read = rt_sam_eth_read; + sam_eth_device.parent.parent.write = rt_sam_eth_write; + sam_eth_device.parent.parent.control = rt_sam_eth_control; + sam_eth_device.parent.parent.user_data = (void *)&sam_eth_device; + + sam_eth_device.parent.eth_rx = rt_sam_eth_rx; + sam_eth_device.parent.eth_tx = rt_sam_eth_tx; + + rt_sam_gmac_init(&sam_eth_device); + + /* register eth device */ + state = eth_device_init(&(sam_eth_device.parent), "e0"); + + if (RT_EOK == state) + { + LOG_D("gmac device init success"); + } + else + { + LOG_E("gmac device init faild: %d", state); + state = -RT_ERROR; + goto outs; + } + + /* start SAM PHY monitor */ +#ifdef RT_USING_TIMER_SOFT + sam_eth_device.phy_monitor_timer = rt_timer_create("phylnk", + rt_sam_eth_monitor, + (void *)&sam_eth_device, + 10*RT_TICK_PER_SECOND, + RT_TIMER_FLAG_PERIODIC); + + if (RT_NULL != sam_eth_device.phy_monitor_timer) + { + rt_timer_start(sam_eth_device.phy_monitor_timer); + } + else + { + state = -RT_ERROR; + LOG_E("gmac rt_timer_create faild: %d", state); + } +#else + sam_eth_device.phy_monitor_tid = rt_thread_create("phy", + rt_sam_eth_monitor, + (void *)&sam_eth_device, + 1024, + RT_THREAD_PRIORITY_MAX - 2, + 2); + if (sam_eth_device.phy_monitor_tid != RT_NULL) + { + rt_thread_startup(sam_eth_device.phy_monitor_tid); + } + else + { + state = -RT_ERROR; + LOG_E("gmac rt_thread_create faild: %d", state); + } +#endif + +outs: + return state; +} +INIT_DEVICE_EXPORT(rt_hw_sam_eth_init); + +#endif /* BSP_USING_ETH_ARTPI */ diff --git a/bsp/microchip/common/board/sam_gmac.h b/bsp/microchip/common/board/sam_gmac.h new file mode 100644 index 0000000000..6c4d90658a --- /dev/null +++ b/bsp/microchip/common/board/sam_gmac.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#ifndef __BOARD_SAM_GMAC_H_ +#define __BOARD_SAM_GMAC_H_ + +#include + +/** + * @brief GMAC duplex type + */ +typedef enum +{ + GMAC_HALF_DUPLEX = 0x00, /*!< half duplex */ + GMAC_FULL_DUPLEX = 0x01 /*!< full duplex */ +} gmac_duplex_type; + +/** + * @brief GMAC speed type + */ +typedef enum +{ + GMAC_SPEED_10MBPS = 0x00, /*!< 10 mbps */ + GMAC_SPEED_100MBPS = 0x01 /*!< 100 mbps */ +} gmac_speed_type; + +#define CONF_AT24MAC_ADDRESS 0x57 + +#endif // __BOARD_SAM_GMAC_H_ diff --git a/bsp/microchip/common/board/sam_i2c.c b/bsp/microchip/common/board/sam_i2c.c new file mode 100644 index 0000000000..7196e0c87d --- /dev/null +++ b/bsp/microchip/common/board/sam_i2c.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Email Notes + * 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release + */ + +#include +#include + +#include + +#ifdef SAM_I2C_EXAMPLE + +struct sam_i2c_bus +{ + struct rt_i2c_bus_device parent; + struct i2c_m_sync_desc *i2c_desc; + char *device_name; +}; + +#define I2CBUS_NAME "i2c0" + +static struct sam_i2c_bus sam_i2c0 = +{ + .i2c_desc = &I2C_0, + .device_name = I2CBUS_NAME, +}; + +static rt_size_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_size_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num); +static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t, rt_uint32_t); + +static const struct rt_i2c_bus_device_ops sam_i2c_ops = +{ + .master_xfer = sam_i2c_master_xfer, + .slave_xfer = sam_i2c_slave_xfer, + .i2c_bus_control = sam_i2c_bus_control, +}; + +static inline void sam_i2c_update_control(struct rt_i2c_msg *src, + struct _i2c_m_msg *dest) +{ + dest->len = (int32_t)src->len; + dest->addr = src->addr; + dest->buffer = src->buf; + + /* Get I2C message R/W attribute first */ + dest->flags = dest->flags & 0x0001; + + if (dest->flags & RT_I2C_ADDR_10BIT) + dest->flags |= I2C_M_TEN; + else + dest->flags |= I2C_M_SEVEN; +} + +static rt_size_t sam_i2c_master_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus; + struct _i2c_m_msg i2c_msg; + rt_size_t i; + + RT_ASSERT(bus != RT_NULL); + + for (i = 0; i < num; i++) + { + sam_i2c_update_control(&msgs[i], &i2c_msg); + if (i2c_m_sync_transfer(sam_i2c->i2c_desc, &i2c_msg) != 0) + break; + } + + return i; +} + +static rt_size_t sam_i2c_slave_xfer(struct rt_i2c_bus_device *bus, + struct rt_i2c_msg msgs[], + rt_uint32_t num) +{ + return 0; +} + +static rt_err_t sam_i2c_bus_control(struct rt_i2c_bus_device *bus, + rt_uint32_t cmd, + rt_uint32_t arg) +{ + return RT_ERROR; + struct sam_i2c_bus *sam_i2c = (struct sam_i2c_bus *)bus; + + RT_ASSERT(bus != RT_NULL); + + switch (cmd) + { + case RT_I2C_DEV_CTRL_CLK: + i2c_m_sync_set_baudrate(sam_i2c->i2c_desc, 0, arg); + break; + default: + return -RT_EIO; + } + + return RT_EOK; +} + +int rt_hw_i2c_init(void) +{ + rt_i2c_bus_device_register(&sam_i2c0.parent, sam_i2c0.device_name); + return 0; +} +#ifdef RT_USING_COMPONENTS_INIT +INIT_BOARD_EXPORT(rt_hw_i2c_init); +#endif +#endif +/*@}*/ diff --git a/bsp/microchip/same70/board/serial.h b/bsp/microchip/common/board/sam_i2c.h similarity index 55% rename from bsp/microchip/same70/board/serial.h rename to bsp/microchip/common/board/sam_i2c.h index 12e6811231..5ea3149ced 100644 --- a/bsp/microchip/same70/board/serial.h +++ b/bsp/microchip/common/board/sam_i2c.h @@ -5,11 +5,11 @@ * * Change Logs: * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + * 2022-04-11 Kevin.Liu kevin.liu.mchp@gmail.com First Release */ -#ifndef __BOARD_SERIAL_H_ -#define __BOARD_SERIAL_H_ +#ifndef __BOARD_SAM_I2C_H_ +#define __BOARD_SAM_I2C_H_ #include @@ -17,6 +17,6 @@ * @brief External function definitions * */ -int rt_hw_uart_init(void); +int rt_hw_i2c_init(void); -#endif // __BOARD_SERIAL_H_ +#endif // __BOARD_SAM_I2C_H_ diff --git a/bsp/microchip/same54/board/serial.c b/bsp/microchip/common/board/serial.c similarity index 53% rename from bsp/microchip/same54/board/serial.c rename to bsp/microchip/common/board/serial.c index 28ba104dbe..9878bc468a 100644 --- a/bsp/microchip/same54/board/serial.c +++ b/bsp/microchip/common/board/serial.c @@ -16,6 +16,34 @@ /* SAM MCU serial device */ static struct rt_serial_device sam_serial; +static void serial_rxcallback(const struct usart_async_descriptor *const io_descr) +{ + (void)io_descr; + + /* enter interrupt */ + rt_interrupt_enter(); + + /* Notify Serial driver to process RX data */ + rt_hw_serial_isr(&sam_serial, RT_SERIAL_EVENT_RX_IND); + + /* leave interrupt */ + rt_interrupt_leave(); +} + +static void serial_txcallback(const struct usart_async_descriptor *const io_descr) +{ + (void)io_descr; + + /* enter interrupt */ + rt_interrupt_enter(); + + /* Notify Serial driver to process TX done event */ + rt_hw_serial_isr(&sam_serial, RT_SERIAL_EVENT_TX_DONE); + + /* leave interrupt */ + rt_interrupt_leave(); +} + /** * @brief Configure serial port * @@ -25,61 +53,61 @@ static struct rt_serial_device sam_serial; */ static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { - struct usart_sync_descriptor* desc; + struct usart_async_descriptor* desc; RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; + desc = (struct usart_async_descriptor *)serial->parent.user_data; RT_ASSERT(desc != RT_NULL); RT_ASSERT(cfg != RT_NULL); - usart_sync_disable(desc); + usart_async_disable(desc); /* Set baudrate */ - usart_sync_set_baud_rate(desc, (const uint32_t)cfg->baud_rate); + usart_async_set_baud_rate(desc, (const uint32_t)cfg->baud_rate); /* Set stop bit */ if (cfg->stop_bits == STOP_BITS_1) - usart_sync_set_stopbits(desc, USART_STOP_BITS_ONE); + usart_async_set_stopbits(desc, USART_STOP_BITS_ONE); else if (cfg->stop_bits == STOP_BITS_2) - usart_sync_set_stopbits(desc, USART_STOP_BITS_TWO); + usart_async_set_stopbits(desc, USART_STOP_BITS_TWO); if (cfg->bit_order == BIT_ORDER_LSB) - usart_sync_set_data_order(desc, USART_DATA_ORDER_LSB); + usart_async_set_data_order(desc, USART_DATA_ORDER_LSB); else if (cfg->bit_order == BIT_ORDER_MSB) - usart_sync_set_data_order(desc, USART_DATA_ORDER_MSB); + usart_async_set_data_order(desc, USART_DATA_ORDER_MSB); /* Set character size */ switch (cfg->data_bits) { case DATA_BITS_5: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_5BITS); + usart_async_set_character_size(desc, USART_CHARACTER_SIZE_5BITS); break; case DATA_BITS_6: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_6BITS); + usart_async_set_character_size(desc, USART_CHARACTER_SIZE_6BITS); break; case DATA_BITS_7: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_7BITS); + usart_async_set_character_size(desc, USART_CHARACTER_SIZE_7BITS); break; case DATA_BITS_8: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_8BITS); + usart_async_set_character_size(desc, USART_CHARACTER_SIZE_8BITS); break; case DATA_BITS_9: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_9BITS); + usart_async_set_character_size(desc, USART_CHARACTER_SIZE_9BITS); break; default: break; } if (cfg->parity == PARITY_NONE) - usart_sync_set_parity(desc, USART_PARITY_NONE); + usart_async_set_parity(desc, USART_PARITY_NONE); else if (cfg->parity == PARITY_ODD) - usart_sync_set_parity(desc, USART_PARITY_ODD); + usart_async_set_parity(desc, USART_PARITY_ODD); else if (cfg->parity == PARITY_EVEN) - usart_sync_set_parity(desc, USART_PARITY_EVEN); + usart_async_set_parity(desc, USART_PARITY_EVEN); - usart_sync_enable(desc); + usart_async_enable(desc); return RT_EOK; } @@ -93,10 +121,10 @@ static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_ */ static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg) { - struct usart_sync_descriptor* desc; + struct usart_async_descriptor* desc; RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; + desc = (struct usart_async_descriptor *)serial->parent.user_data; RT_ASSERT(desc != RT_NULL); @@ -104,11 +132,11 @@ static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *a { /* disable interrupt */ case RT_DEVICE_CTRL_CLR_INT: - usart_sync_disable(desc); + usart_async_disable(desc); break; /* enable interrupt */ case RT_DEVICE_CTRL_SET_INT: - usart_sync_enable(desc); + usart_async_enable(desc); break; /* UART config */ case RT_DEVICE_CTRL_CONFIG : @@ -127,14 +155,15 @@ static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *a */ static int serial_putc(struct rt_serial_device *serial, char c) { - struct usart_sync_descriptor* desc; + struct usart_async_descriptor* desc; RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; + desc = (struct usart_async_descriptor *)serial->parent.user_data; RT_ASSERT(desc != RT_NULL); - io_write(&desc->io, (const uint8_t *)&c, 1); + while (usart_async_is_tx_empty(desc) == 0); + _usart_async_write_byte(&TARGET_IO.device, (uint8_t)c); return 1; } @@ -150,17 +179,17 @@ static int serial_getc(struct rt_serial_device *serial) { char c; int ch; - struct usart_sync_descriptor* desc; + struct usart_async_descriptor* desc; RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; + desc = (struct usart_async_descriptor *)serial->parent.user_data; RT_ASSERT(desc != RT_NULL); ch = -1; - if (usart_sync_is_rx_not_empty(desc)) + if (usart_async_is_rx_not_empty(desc)) { - io_read(&desc->io, (uint8_t *)&c, 1);; + io_read(&desc->io, (uint8_t *)&c, 1); ch = c & 0xff; } @@ -190,8 +219,12 @@ int rt_hw_uart_init(void) sam_serial.config = config; sam_serial.serial_rx = RT_NULL; sam_serial.serial_rx = RT_NULL; - rt_hw_serial_register(&sam_serial, "uart0", - RT_DEVICE_FLAG_RDWR, (void *)&TARGET_IO); + rt_hw_serial_register(&sam_serial, RT_CONSOLE_DEVICE_NAME, + RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | + RT_DEVICE_FLAG_INT_TX, (void *)&TARGET_IO); + + usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, serial_txcallback); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, serial_rxcallback); return 0; } diff --git a/bsp/microchip/samc21/board/serial.h b/bsp/microchip/common/board/serial.h similarity index 100% rename from bsp/microchip/samc21/board/serial.h rename to bsp/microchip/common/board/serial.h diff --git a/bsp/microchip/doc/2-1-1-atmel-start-online - Copy.png b/bsp/microchip/doc/2-1-1-atmel-start-online - Copy.png deleted file mode 100644 index 8442172d0991db96391e5a0cec51363a5db04114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 306632 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 FV1h(uveN(n diff --git a/bsp/microchip/doc/2-1-4-atmel-start-driver-stdio.png b/bsp/microchip/doc/2-1-4-atmel-start-driver-stdio.png index ece51e970a4bf9000de8fb51628f3cc97638b8ce..a65859ee2f0174f8c7c74072a2fd95e925607ccd 100644 GIT binary patch literal 87863 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%0DijthPe*O|4Aw39zR~ zroyQA7njnS1qHPvL2z`NcUKSxE(Lp)j4%GIL7IhTUdv7jdGJ-7Y_WEtqF%K5FCX&W zCcz3+OQuB!&bvmin3DXx{-# zN?IA%;*4kp2R56Ml)cXdR+3gsteE?wX``wFQ;*j69R8m7nI7Ss*SvcP!@|F zCL;x=-%`gUT*t0yt}uc$o;LI&+SA&0Jfg z#gO7UOTFjf-L5n<0%V@X`dhBkc$f^m)zz9Vv zByr>mch+@XV-n{6mL5@0%$N(J>NI;_K3+mkaUE8@6wwxc77p2Se#kK` z4vX)iaS(Zp_neH^JLU5zPI8I_0;q@NL#{}ygBO(8B<0Q}6-8N#pU2~5V*)Kun75Ac z9GZ@Y==U|FsCHuIAB~u|bG9HFwFW|}(!I%FmEa`2&wkNY*75R&4qPNi=v2+Uvi9j( zbMAINpAL4|)q)F)X-0CsK4f@gfALhtQ8u51;YY|Y4X7)bF=Vbr4(=D#71yPOGw5=} z3P#KB50w91bbWQKOfFi>XD3@o^{KdDV|3Btv8s7|yUh_j*n;Pe%I}Qf#kd-4tt~jws zYnsZWMe~)Q_gm}bploT1@*F9eBM0KdFafdcZ@A6LQVynqYwc|@j<)Tw9l&WRdHLMu zUx&??b)!%2Hx42`bUOQ*#QX2Hh7XKnr*&dcXoKS5Jy#DT7W>~z& z6E0gi8Ho61#|bh>Ng}biK}^vwH*S2NcS??0+z2t*<9^I3Ek z%R?pt1cyY9>&$p=X9;Z{d&rtA)KgexG9977?v^G;0 zfes0OLvlI_9rSMB#9&Vik_q^2>`J@XR#I74H>#|G{kkPk;bU>Tv_0&17A4PEprKDr#B231<6+I`mC@ zvDwqr|pw72em@hEBv1z73;;`?s?u1Q1$qhmkta@*zNeiZ@p*yV zgL%8qQUlX^_wd!~OA=SXxPcKr&tKWP`9xJei` zXY4BFhKS>&H7N-uy?K4l6qxiky(%u1wN=SMr@i#g&+zoO$ZsjYC0_nY9VJhyQ0l?o zR}^?yU@f&Gh#=Q+R`F4fp_6grNcLy`_&-=daTYu8cW3=l-eRE?@u5m-{%9qot~PrX za*@8HyD91kVB{xIUa;j+5)ohQZQ`85EpS+Rzbnoz8B)lIeIr#~mjw=cTuW}$JqhNO z!3c^LkTQ?69`igy@c~H_;F(G3J*~!s264YrAv&A|bGt|>e`9DW0%!EIF|S2< zr|1nKFNQzY;bohmioGV|gaX6Vb%t~iEW*u3r!NwjC79|?@t-6p99MKL} zjiWVdk{T^K{L$z_N}yfjJw5|dH%;3h8S$AHC7S=aSpU(Vp5ge1ZtRW4Q+$=tdeTT=0g(@2uNa$rLXEHj@Mw%P3v04z4L_@GYIjd->HTK^ z_balAOe1lpr1=D0Sh$+NLC#Ic;VOJDvvImnSf?{9LGG*`mwsw2(zolU&7Mz zhcFJc?gY#IH$UG zW-Pg%$E2?Ziu4gdecjqulf(EX(7WOm1biUNWR&`vt$&b8$i@tGOnm=WIXmU!*R+(Y zkV(v=;1?Lx^MPT$!CDtSjK9P7>O#ZY-ZnF+|Btk{jEXbZ(zcU8Ab5b_ZjHNp2=4A~ zO>lQhaCdiicPGKEA-L1HyE|`Z=A4-`XJ&nWzF)moucxb?s@k=ydROi1uK0pFOQq7T z5nN%sw@H{)+6MVYog^WYofWsK!aDnCxbd{PNL}`4@t96&ro)z zbw2N8BT7m^9O9;m)ku7~K?o#gE~ zT2fPjrO@XTLINAfkEufB6ox;{bej}D?7&^UH0o0?RiHpFe4H~^Kq--}-lo^8>RN3e zSsUmzY_!0*m%tEPG?xpePGDRf(Hkz&JRI9;h@&82IaJ@taY~>Gc3Tn&PO{RTKy&1Q zYjS%g>29d!d(417qhF&AbavC7Qt=ae!HifBEq)Vub8e2^lmRYeZk2Mh+G!SaF3BG2 z2&ztXL>osRLsL9RPNh~$23VXOAXuCc|csm(OU|-r^j7KIsc(s^V zp{kh@Z$Re(wRWA0u9jwx!{(Ga3d2Og8yqKb%0L5;S`|oXCpKQwuj86n&uRU)hB~|@ zA72N)($Ry3XAMbOE$Z?t@|A4RQf5>uc1jW`2|WQ1*{}Z9c(PogKpQPKq4BvX{_esE z!5IRO;!TD~80E)w(Sxs&={%JHHR*PeyvNi&k`3Mp(qYx*7@1&B&`!Al^1;-ev2`!w zC42m-Fuhl;NBNh?)DzzM&mg(q^tfLS3V$pKH=X>@SogDFG_@2oJR}=53?FsA*-WYL z4oYk<$UjT=hU9=;O`A`th@&zS&mMogQA|kTuO}PK@}!UMI_JyJCIC53bpJxQe0bQ) zGQQq7bHBCq-L6RE=~bA8T#jx4`hE68y}H04aX@lyY)5S zJcr`(Wf}=><`*v4?;f$x=XPxNC?&EZC19CRU_)vb9E(pk-XP%W@p|Z!Bp)Rhs9-Yw z3<4nFHnYgvjxNKDx$k+bwU+sHsYKxJ+|mau!Ss z7(y||$T!@2mS0Ra*qXFIySVFq4m5jxX3HOx*_dPgrpxeLjqz#prBju9PpEk3gAhbx&_$krXnzS@3q1G3yzwG| zwaGY?o%0dhX_^^{B4S!^ouDjQn=T@~bbw>En;(A}J~Gb$>)2YzaD0ezKhrS)mTz~b5g8NRGpTu*DuIEp!)hssXZpmXtztdp3%tBNn2oWTa1u>f6 zGM9vVmsq3Ac_p79=zM8iiKoPA7(jVu5K{O(8?DHIx%cq{)5tOUF+eVBo(0ZMe2 zVes?(>CWq9xx0Z7KT^9ZjwhqHS2FoL9*P92{HUSgIEE$Wpw0syUOq`v7uOHYCkocX zOf;Q~R2*6N#pnyoR+hAwv&%PBi?Of#_WRC>gGF>@#LE1oDp_o4ac*8u(Nhn6J~Cx& zTD>NTj^azKBcCQi2G8~Tm=WEDZTgaW*!xQ}77sny@L473jj(+$wn0u0tK}V6WBLzA z`mZDUdf2_ejEKQ$7jz361llkaA6yHkY50R(ddIhG>shFu&QWAmzOXd$-`AGlxI(t8 zl`N~wduqoO3FV1nNlNVRRZBopvWbE16yDqUAyY397D7r%m4=YF6d64~oP$`Re_N+J zb*bZJHhlg;L>r+i6&ot;)qV0k>tWx|7^8XPQSU9+p}}2modYBagLKN(Pg`Gqi4T;t zII(Q&Cl20|*I{E)hDPeM&^#!)WO9o4Ak^4TDq;FQek$H&M+;#SEg`fbbZ1pTA2}J4 z*r8H;V3I3aRQDOVW&1-{xk0HwXPDS#&&Z_d;ak?5H4xBH08FnBy?Q${QikQjlPzR$#x#l}t_%HTiOu_ThwOC{a5-?u+lS z!Hi_Me?!JM53vtZCTWjFX|PK}nczQAwV2u1`8E{QaF zz;Vv6iUW5O>FO!hkxxw*IWgE~^n@UYftD@hT#IhGs3L_~a7aV`w@b%k*iEI4(eBbk zbMm78B@w#JDI0PW3{#8>DLUfOZPMR6afV9A6dE8!uuL9fvuDuN>yqe7!?uUmvopP1 zH0v4+${@)}^@G`szxD<{-BZWMy^tu&*!eV1v)jE%N2^ufmtIZnu?>=mbJ9=5^zyn(1vR{yWhOp zCbS>?e82qea3(_QZ!9hqUo+^HPGnZ&c_tCFwz?o9Zc{1j4uj}|ikc?B;X48(xwQuJ znC*a7uC<{c+OF4VM;Mb_GG6qc|LD@tsp~+E$+{?_OhhOBRWTaU16(uCxanT!Kz;RC zE^|kua?l;g@1x}R!1t6ZRy&dEz;%pe(mY^aAQao&oPsWa_N9^CehWvQ-uM^t0-&oX zLB#VaqJa0z1h~jH#|DfWw#pH7V~f|#Jv7ePWdg(Ta0bhyS?l3i`&|m|XP;;5{+JLV zz8&Hqetwjpj`IyvLdOjW9te5t5bO260#ms>mao~1bk9p5D$p62_bTF%#S%s%&9AKI zot5gEF&b%#t7u`&Ay)>UglEel_K> zLcIf;y_hSrw^oSbl55=WHp35nXM%_W6bQp7SKnh>Vkj&-7Wm-MqVSYYz6fMxjg&%7 z_k9gDNNU4|`K2^i&b>&H+EyH{W~RXRmo0=Z7&pb4oCi@q^bgIs&r+ZCbp%TZ^w|U@aVq{ zM5LCYloLgjJ<|M?kZEl(j?~q*M)^_+9}Wwgq`+zduTlc9``(Fp16GVTM$GI_H3of9 zbXg7`!BOed-Ylp>ALf`>Oo08%*GB8P<%k zyUGxSe~KNJ(U#syt!-*5?Krv>oDLUX4WEO;q~O#cI0CuV#p~lE)2FsVD_W#YC(i-` zasw1ea9V57;S~D5*7x8%6t~-6>DG-A$9+z_cm4(4D93^^%8ae?UB3~NDi%aK`;54F zRkUN@aB;1ic(0HjHICe#dWRDvvo;r>gk<8t2JY;lyWh}epfiB(N~TH+M{IQ2@&=9z zLV0oBa*bxCX+PD!zAfu|Jq*kEam=2f*=f>f)RrV=cMQ9wcjij>@ZP(` zrPg~oacp0pVC74tM_xyz7HD9FWnCGnw~5dYYuzB}kAaLt1leVkA>oZ{ubiJXDs|GU z#t5ui@va5$2XHl21`vM#*hgbmo>|P22CwwhYZ^ZoHLAETx~Rc$#=GCVyPUBabDOD6 z4Foeec1Ad&&C;3kZbXizq^AkXWzp{HN8|_bQa|{cD}N~GI3rnCc^rd^?5A6832558 zBS+%2mK!n!Ww9TZA+D?0R=RMD1P!v4r7`_6eI!H)&bBJ`j zh?`rn|>$NS4XS~Tpsi$^6fqI^Yh4j zefD>@03z^fGFM5b$_on%nb0Rlw^5zBr4y+;LgPgbfpV2M>p3*q z;VJudJmuny=@c~Y{&HfgQLmo5ik6fXH+!vS6sT3C-5igjAF&t72?nlUOYT|vnq3Bc zsXCncAiwbyhT>zYz$wKVK5tUAfLkP1zs3Pg>0SAC=ufokhl}uwC94YCif`p>wP6n! z%fo!tj5t5Va9>6gcZzE##ixF3;ix{**veJs00+Igyq;9od_3`u2fBK}+0P;CKkE0_ zG5yJ@U}Oi4Tj}cJll3%z(HCD+DsHkHg-hU)>%9F`UxincL~)R_2}>C|a>pEO1{rT& z`EEbVllvO$@7$<&<@cBm7G&MI!x3)FL|_Y_rVvR+ATxh{@yTA0m%S6&#=+WqeN;so ze2Ws-_sDczbB|Zg_DW!;*t731?W|2V{lRbt3#Hfr>+W7?EumRjI3L!aM#jCN&VPUT zAdd4g#~VR(2asQRrMs%~j(6sqH$|-q>CF^5)$kG7axUkNpqr)ey^Z@Ib)w7gZ|wdNjKEI^kBHs?2?%TH=8b*Wxb zc-9PTpfz0~aFW8UV*DI&<2Z|~%B$uMvFo_CpsaBVpw~4AW7i|gXgC>5mxI#6p$Klb z$4@NqV@m6&tHS)HN|x`h(PnwR-_wj;WY)@$S4WH&7X^V|9ukB#Zg42H({^@<3k1b= z5P8`{O|$7^4KrlZ(lRV%OxJHXT1GHQS`(n0*H^+ ze6x|%5sf5@8eW1@RxUk{E{dDBRv1hxQg{+&F{W&0vtqgoDhRjhIa_%-^}tcO`kg%i z?oT1OquUrt$+2!kd?ndwOww-*THSt;1mn48Y8q98jBsVy7+EjcKIjC!w!XY+oCBS` z>9!ps^9aofs+L;?U>~VB+t)rQ#*Ps;>iqfFTk>kgk*yT;i9FRZ3nHm1Y9ft#u0leu z$lAiIr_eCeQ_F=ne-W;I_QUfZ(*PP(dX@<+?K&Lc;rHh>?-{L^vgU$*(m&N2KZD(c zMx2j5v(Ik@0kr_3oB4Zm!5Nq>a}{X>JPHP5+JKs1Mvh4mZWVMlbuz?$41Ir0r|Ft(1D}!cU)rGADyo(hDSSydTbTEaDyYRD(bm zYd$k5XqN%C1pXcpCg1Cy`(x^^!p5)`=bkHA^sOc>=Efe=n%6>ZdhO3Tda^0m?WRJ; z7kWt!#(f-~^rea~sreq%1e&9djp-^?*oI5}r!m+^=8JLF*kZ@Y7y+DSL~oxxcXyfx zm~SJK-Hw(|0tkSU<#~hNq`t@_mKD*1Dxr^xqK#X?lV2%;>HV#oFBn%X!S0)doF*CP zfNH*1&w)9;K~S;lmqk?ODa>is?Pq*{TTXN{c(~9JdEL{TO(4bPBvncIUM5?cKEg6yJ*LMsHxIJB zR+^=laih3L(3hLlT6;^6@26VQ8LviLXbcintgSpqY&JI3l6X}vFy^Th@GS9Ckwx1aUUbP}@6z{1^WH+*mNW^U3> zYbnj(^=ZaAMN13<;tO^*HVMINR7vjOI|1AwR>+xu@Nxm6=@_cQqw00KqSD2!YYn{G z7PqN&bGeWc4=y~p%hgDXEn2nRxLDU!WzJOElnnRI@(NRlalZ1X|jW6ql5JnY0YipV;8LwBXO8$ zB_!ot5Oy^G+cT@@-KlAB5K;-K&6m((9oQeAAZ3xZbkBB>jXz9I+0Hz?PHgh(Ue7w? z^gVgBKS#)a(+oK}tuV)@^3DD!1_JB=$$y3Up{6eFaZ429x#tC#NE@wV$D>AeUcW5P z-g;bfIrJK^(?En3+$~UZI$lUs2}Z;=H7LDZhfi2GRp1KKG5ZSBC{U4_c`(=Xxmh(r z8C9Fml~hty!R@L)<4+Hvb{v^MNI{IKN`O5bBfEQW=Ht;qjX9$aT(|xkg9)YkC-&1q zI#=kuCiyTtUO)wl#9EyRO?=T9@ZgZ$YGLiykMh?Z(4d*I+*qMwTQ~t&)^MOl)#|Eo zE6R+hFdMs-KI%xiD1}5XJ2fJT;5(ROb>T@W7q~a0de*x=y0MMgE73#+TVy}{%L3Gs zgq1t8mb6xCI+l8kp}bdZa+BtK%yPH&bKW*TSQL@poyuaOZ~7kQO=C7(+lDWgBh<)F zQe%V(J`KOYMlglpU~b{7zE!~2RXHV(EV=CKPd?f_{EsexRtxU<;xWUEGFcTd9{bA! zT|24PAo|dTQ=XU(Xl4P`MQMWjCd_!>L-z(}*uL+GezfVgnVxY6Vcbb79Z@Sj_{)`9 zIOqaqb9pyk7I_@EdYhT^tm780M{1NknP=k{ZMgg$3w%_T`qnOhLbY~%)VMRnV5@LI#B7eq*8 zOie`GrSOQuLYXwSVAJyX`g|&>qukzoZDMP&k?yk}$XsEV%;rlvNmWZS{+(Eq87nZw z6oGo3k8#?aev-;&^(H$WO$i_O`K-RYT;VIhyswo<|2}_;%~PadRL`gEKt-o3Df=eg zVj&XL5Ub%H=m+P-@A!qlYt-GfM@6ktdt#i0NK-c|*KE)Vt=GrGj~d_63)W!K0NGK`kR6N6L9W0ZVXnzZn@_xzqNzX1bk8!>ucik2cSzKJ0I zs<@r1&Pz`fa1Xkk?p%m!_s6O}6AH~IGm{d$pdAe7&#XG}RF3%`it|uJ^%|t4bzCP4wozE27tqHpV@$`ZaE=Fiod7v1?U~-fg?F-!GN*_X@T`y@&2n zP+T=nG>_Xpqb|aYE)rF6 z$CIgtqr{2Uz>b^8u%Fw09oW;bkRaTcz=K~K3x45RDwN8$wdz}|BKlV`pXj5g2yd8`nB=+&eUsguvw zPbv`I{*Ah9aHi-a&53@^iFO%MarP%r#xq3X)L?x7#OxGHpUE-w`T&i#($guwMwv(q zIY5-O9Z0t<(OA!lwPr_8##0oxSjUPJ^*NLvn5o2`+17_GJns?zF?%L6;A_fu)5-pV z-X-d#AuV5QJ-q8hKc#-n_X7aUN@vSSlqHvF51e!s{p7nwh%@l?@SPGVE?ue>^`C)> z-{&oWat|#-!EH3n3EDF34oF{3JUxLw=gPmgaE+UNLLAOc$cHvi@?4pPkv!s0iF%M! zf|h-s!ldo5QlUFk5E`#Z^qFRJYRta;X|$z{rI@-Umk{q8EUMFy6KsZJm?ZP@P3U`Waynl6P&}lY=#W^{=O=(@ zrQUx%(Pc8XiIgD0y>_#0jSucIACfi(_|7m`A8WwJ8+pJ77gV;yVfM)n5;EBsSw zi4{kK#bUoHlT^Ki;BB+rDK6iCpgJy0dr;XHn?CicM-t3pd!Ti@0DHO5+N`9pmph7c za>15R16(r!$R&1l+8|lp0vu2EU;92*3MZVF_Jdu>dts%z*WRGw;G}DQc6L^6T)c{Q zyp0!+X|@IT{hW7vi!__+p}#483~A8yHNunQqs9uK|K{^X@lM#w*&mO4V z2(4%&9Q?x}cj%3I$NTJ7XHAFdI6MoY@t~aWC~uyr*2GYD+m7LJ zAOGQ+z{u7m4jcsQv=?SuYkP;|Up6M(rV&lup`wM+LQ+RfPWuV;s>IIUT|(r*A?2Wh z2s%4lQDZdjjhjWPeQ@NQCPRK?^D$Qn;q9!~O}|M})qXd=NU?i@T zbg;$Xh0|Xml)Q-3!F%TpyNz!EnG^%A86QFm;~kktB*CPt6J_S|Yz!0(g}jTzDfOq8 zk{vDpjmBj(ipH+}ONHhSi~Oyb8I{wnr_=k?UUc|UQ%a;-B&WZqFRWiCwV}@{j2{%l z@-WgxBe1)%Z0m8{faU0ovKmx>j*~5zZ8G5)dXSuhgnNz9-M>ezquk%2T*|1y5+-Mc zV0%Y`%&y@8aMN38TT&pKnleM{Puc2-61DhrQ6ejDrB{PM0c=Q$h>nf%u9gIvVeN4J zd&bDaWE;uO*^O_NHE`ne8ry`~oIf;sP&nP-L{0zD9n^$;w0&kFL{TzqTBu#@Pf@BT zNWYv581ifnu*4u6rZnA(V@k-azCEqeB(ILNP>XB>iTMqVHaD;JwHzbdkLni38)1?O ziJBxi)P<7}T72hF9t;3w{$N*#=Jb*46kR0o7^4Z&l#qFsP9Y(jDGzhTA?e?T7t)W> z8_}zgq!O$ZTYPEI9J)xnV{b>;cdxiZIzJP1W-(waarn(TfG}M3a_`yzfs-wrfY|gv z<`<#4n%QMeFSRM-fT)!%HM?+;yAE13=;vteW^5DjO%6~;tUz|X9Nk~I(|j>-x(s+G zktwyBI#YKh)=Ej(^Bx)97rl%weT0hC^n1J-*@L-7c^Q3qGm|zsYAp+*1kS+bf_~Sf zEPZC(NWG!2e;+Dy7553Ud3fY~gp_jM$O55aJvVaJN3#S7-%7cfe)NJW0rp4Yt;`(eY1LJmq%MnQ zDR&NAVa(uKnYvQMNM)B<RNMtU zn6%53CshX>Vbdf#M96HXuIDt|YP@$YVlNDR<>>l(!J;>T3yr%ab*|he0~}C_2Yh9j zZr;ph3ByHtE5vnjv#FvZDxfvxlQFl;CkK&6%4Y4UT;O|l)q)I1u1qoSk}9L2|i)5)-XgioXi!v4M{vs$!z%k&9^;kh1IP-`W?LQ z9KF+r3evuXrqVAd1xUEwl4xamMeFt{u?!^Mx{twAu%z*`h#eYpV^eZ`8sCJrU>|CR z@Z)tmr!_%o0t(G)!QxAu1?t?l6sxdHeg<&@2?k^eU@DKE7G2d(gw(w`OLdz}C-RN< z?bKd<0y$HrS1q+AZ9FPL!|de^p2_qUV;QWaK2&uzLYpiyh?C)PNd(UiJ)TtU`-X%9 z?d{h$8vNA!TM5siB60)^PxP4Gg_?K@o>6T`x)=abXWMX(LZtG`FZ{XqL6M;C)EUjZ zW%4qSCC?554N+g1j@nz-ch0gm>aoso3XOpxLzI^+YXdXOnJ1tn4a8E<*jzyMerXGh zZCtO^S}9IL5s-z-$3Gzdy2F7~N;9H?@3W47*(%8(TMCSNE(yYPxdO`xmKLjM?Z!xd^yqI zrDqw~QS;V&;Fbfx-vyb+ z%5=!1En1rpJ5I^Aeep#Zz@X!pP*An9`BX zFzsbg-UBqPd0wag6IuEI{t9|i^prnIz4)Te-BNYz>|l=X{4*&jwFG-*o_ia|+Q-HEee|r>J@zIi{ISO7Rik55Gc-@3 z^0>G16sBd_`#JgD#bmJA@PN_>AeJPz^}gftaEAL7(~{}3QTg=WYl^-Zf9a|aNbk}o zcESqi>NTmw&vnxt=QuhJQi64>m|IG{Ne3N#K$u30!#19XdO@WBph%>>q0XR)4mb$G z+62pXS?*I-`vA;%B#BDge;%@;P(DGZZYf*_KTK-=0xi`v^#GC0@yCwkakv%d_ktYO9pr9b;di0 z0zOx!dT(wF7y{@V@g7GiF$M~qnsR>|208cmua9Rmd{bD100rXETd0ZkvT(UP$F{(> zOEk#T1jU(JmO3=#I93xno&NcGd$Kg$sz zcuGrCGtd+PaVM%@7ZY_hx-SIChCU`A}#ES zf3vsmQJCVZ@3G+@_WzXgdM_1@HuKDZ()z~SkEp^^h7Z|dd_JC>Lko)-HA9Z_{%4Qs z$3Q#^B0BuuG*A0SxXVhbU9kJp@}kVcp(CK99+gP4!8%dS<6A(;KP7bjyXtN($g)t9 zbPGW~WnRt?R+S2nq6xEUiTb;8ush7f0tb#E|)|2KPTJer>0iuUU zqu!@xOMTKeeov`y|DMuGngl;e0=kw~Q6{AlAcGnb&})!10jSSd9ZYxlOBViI3B3PK5_+NjB#Ii^!WKc+dqe;_kp zG3*iF*HnV(jww376U$fZ*{HEEnRq*H-~4m-KP?cls_om);Qtu; zX~vN*DJe<9&W;g3Y?2`@EltMHzj|L41>uZuwYRBrzs|fI5|+=FW&T4>-ust?|9NUk1HqOe7fQ|v6G~2LqbO850QGSYTd=P z>9`QnYP1lg`VtoWPvxF}TG;m}7;$H~nzY$HJFc4LlL0Hi@O~pNwY}Ng@zOJnbkKbj zegI+gV2k|3Urf{gXi}8G8^m{TpUjMP7LlQaVh?U~m23LRf@k*(nB4x{>`wgK^N=Ml z(|7p&0-G@-CucH5Z+SXT6u}sfowk~soNPvSWSs_Aa;msDgZMSDty#C-Wx(0FTT7s# zN8zqiGvNQ28%Ge4hPhP+ot79lbilep>!z7cN|E@ifNyGQ>VRuwhdTF-mq7N#>WK@U z?~6~jz3p_IfwL~?gNpQz*_*G#20GPcWt&$Mf@Tw0{6VZ2*||Lmj0CMur|nyR4-+&O z{`@iM`+FwwuZ@1z-!OCUote_z`J*hyccadYm}o2yT2V&k*m%4CD%zLJWVHr0W>lq)vHd%pjCrN>{`*P_J)NM0;9T4H_t_%Z0JO7o9khzEd@G8pnL9ymR?wB>HiQ&LJQ%$FDY zKQ>bT<6Wc1ju#B^Et0anac|Agb@lXo>xC=P`*3L-m5`9&-$O-1 zW3=34eZ0~dABo5LTGILN3l%Qt?qQhq-Ry~lzQ9h6GGruVI$?>t{6%fy4N(C`pIvus;a1$uj9jr+~`EPfdg=Ruf7C3m|5{!}4#MaK-g7^T&R zOGQIAtwItO|1>tg%rY$y)pPvQeTcdB6z!qM^h+?Diy&(2#U~*g{DeKXmZ!7iA1Jfl z%-aHq&18ClKj2wuT=5ysWU=r1wjy`-)}P<5E~EITzYOHE@q-fr$mS|n49t^=*fF_v zydVQ`rF<{My&OSQ?Qc}44%c~(GE@TKcPlwoxnLXS?vFJ&^4Z?qt-FA|GU$5{Hdo)k zr>jn%a;E}K-%MP8rHgdX-AsJD1N(~j5TnSlRYwco{FJKZNjrKFR(!CK@^9PoG*7k^ zTidbFpm<~|IXXP(-QiAxNem%N2t5~`;M~h;cnzt8SU-4=lJ{L=FFh^os7BoK^*;Ar zhOw6*F7mIoHXa}-O;l4e)n1PKbY^Ok4D{jImFr!iK_gmTEwhX@ahQBV3do|zx;bV) z&I#w6PC!gS|6X`sL|=;?ONh;>Y_t zNEbR&sp`G$JKyck{bUoRH0R{pH6btvFv4yxMm;5TWtI-r%2OqqssoniOy8DGAW{ec zpF%k5c&%EtZLgMPiatf&2>GFvC{G>5)TC2Dpmg6~X%!q+01h2h0wS^sCS{)_qGgd| zH*Ct?yS>=9y;ZgwI7J$VrhjC(4&9JPCyK-tzmHv&Wl_RG@v;4kdJr_^+Co5DpV%jW z9X_=9xb&F>bsZ2MSExpA(eslyGEe!IY|lyxIBJ;0_)}P{M=f@uNFl~zQWPmJIAms*7wN*S&}Aj#?M}v+mZFGwHc>(M{)N3L;t48NM+f)r*NUx1F>C?4Cwe>|>2M#e}nA8O6j%$a#xO zN1psn8?!ZdBHw-r|S=iyKN5@RH^iE{2+dR`K3uy z%z8~9qTFPno@9W9x=Z@UDdbn8k)VhqAXGXi(vr08G)ZU!V&XPZ@;c=n zX(#QSQ{lk!4Cdp!7*uhQLT}!MD^z-JEiTnluYT2 zKPTgt$>gyV!AZW{7rY}=A{=HxR@eb&luSM3Z3}bIQXjV7y9Z81lChI2z}%sO1I3NK%#1K}-7_&^rp&Vnt7!e7x}WkO-m;ihNSJx>Z z1uRRfYK74L#y3v8%#FT$q+ZkPOP?Om#8f~N05l|CBZkgdEHj4-MvqYD<|RzB-my5l zh6K!UcX)X)xCocfh@gs=JvcoQ4pc-s3_53WF$@E-L*u*khRgfy^J_~7$gOOD{gy_# z&B@%h?ms-?!C0<*P!PwI;a|?DG zLX7@`IwgBY)vqzyUTwYUXi3T$dDwGdZp1`L)A~2KE{GleX*_1=0*7?4TT8JwBJZ;& z8PLOI;b4&=^$2!nnqLy8Q0i@Fp2UZnMxAkiuIzj zP3L`^xKbi!RK3G=kAQYlQg6q2u2O6GN|D#{pG|Q?9F_rPtFvB>r4iMTEkOmHNNT_; zj4VVSlwgHS%qvwLvj_%<; z?`9{%kZHf}--GkyOLOzgzWpwGTIT%+}UO5Lk&>3ip+RX$l6Tp4cotH0hSlJJu&Vokd2baOO6La z!VFC}=0RZj_jWBQBBZh$B^}me z_ol|YO@2j_IdV}nRhp4(VU-s#9oxHXZ)_2R)xFranPBDPt0TP>Vrbf=di7gd8yoz+ z(D=y7hMNS-9GPLSD?BmgSmZRN5z6(|NPNtN;`jF+Z6Hp zWH`$qeA&~@*tOq%_g~FBdasUcYl2s zWe8z?KnX*s+4wk%fTq@<-|Bk{d|+Ex72X0#%XT{O-y23B<~yT?kuppaw%a;Mwa*=$fbsEnTmU z{iIyna&w&l$`f?I_O5DePSnIEE|kqtJ;e^-Cu=JyWTALWm{hJ!(nSyi3K>;&pclG| z!_4tSII1q{TKFO~owTCoLNlf)GN&ns0txFk$d!;qZDrxM0LR90;E@;s`qnOao?!>Q zP!rRMAUtm`0eg0IiJd6)OPq|2p3`Me{?@2Q(e+O$c{+pu3j2eTI`_>M%myj@n*I7f zzPimhNv#+jT4rs-$EdCJu(th)VwKGFi>x z>PZ2u&vnQVUoz1~3-*PEg+wJOra4rZyp{7KF#L|Mgxm3XSG6gaJG43Wnx*?JF6(@L z+vw?NPE^H2YBQYnrIunIZn?8))2mc1j}z@BZJaHHVFjCFxA6zTaW=|)Zohqr6ga$O zx!=$DK&ON%yJN=J?L#T=t^Un;@Pi(HnkbjR>0Y${*b(ufA-uY%x4eyXXenjTL>xSU4#5PC*~0&?f&r30Cl^YL=?gdOth z+gG?k2}L**@48S&feI6^!oZHG(hO%Am>2DKswM4FR%r{7uz`rQ5Y8Se#SHLFT1kVp zxm_5^ew`vElxwyuXz#Nkm7i-Bwhj0g>1rdx``OqLijWx|iTpD~OgN37%nGWQ4RaB9 zIvJoT2|85;&9pv+UJv#BMr=XNVyBvAW{i}^63@@86(SD#p0&{^269<`m#%!hjg!Ov zXvW)U2v>47x*u6}w9L(1KR~j*BSKeuFe|5Zk>7|smF##G-NX+YqNM<$`73mL1@@D? z4lZp-0EglWKJ~&2TygI&^7|urQp9hBoj+zcsLci1hor&HCSDDgEpt7^I}E5T9?Y<3 zIz|r{Xk&KVo#+L1w+GI1vVV>ob*#q*tX+OazlC|QGW(&fo`BjQ?NwWXRB_AXxvP3H zne|!!1Y=Pjmn}oZqUfuH*dL-(cqVoON=iXRL`>H3Idz9Y&t>knqt1#_1l;a(ZP9EM ztEGPDGuz!DYUc_^kG}7*?|rJtAvbCWUkqsXcGFzixm1I`KP zp&vP{79!q9WAoEQz`#{&ZDw^*{@PPjAl<{;(aFSD zDu5-sbN|rT!E4HE=A{D4DrbE4zOqEIM=&Wh*yRfu`lh(OF<2-DaIegVFjpmP>)Nl`{ zIE0&HwI5d-_c6wbWS4&aO?IH<-qcXHDxIihi}Tsj#i(k z>7a>F{bHhWoD24D`x!1+X$0((%wEg$e=Ja1N4(mzb+tcy(tfb2j_zy0uM0!e)g@{B zy1iLIPg?K#D2i8->Lgo2BzTz8sJH!`^jSZIFcZKd38zwMc6hY2a{F1DUJlK1RbvIX z%TUc`mBw3)RX@S#A#)wji)L_ixVmyXE@zWE4_z4oqgLAF>@|VvP|jl1Omw&zleLRe>?O)CQG-AxiLBRHkqo!bEHb zIPs9Qhp1I`RZNqz{YOqw!7kFvb`B$EATiBYUbWw>5HMVqUGq9$Da9up^oMaoPbI2b z-X#=7;ZZz^-b^O?7BCyFc)|2#BowEr8n~j)+hXCt&#M&ARp<*ScD@eLtKL9ir9GEQ zt5AwEO%&={zyVr*y>1>!=d1R4x7=#T+1$~cSq_jQ2q3sVj0J3EBJuz=BkhOoWg}U9 z!Va##I)_Y9oW;9x*zF~ImNt*L5hs1w^3ZUafgYY-842lgC$40PAXZoz;>E)g-4jcp z+hK0TG-lUCKYWl7PMMgw!eBA_o}~zdE*GC12)5okMxnWHm>m8?G9~6&wEpQHr@bKT zW8#!pdLSf(=#!GYqH9H3vOAtR>Uq{V2>CbvE11aVJKZwBR*9yEa*@m;Q5R2!oZ0hX zH!3?5N;2zXylzLsbdRKP-NT{ZT!*6?iEZ{`Sgje><=TVw{qa~5*R#cYI~iiyLiQSK z0AuE2(A@<6_NpWN!+FLW-y&mT2{S7h;J9wO!elw0@A*N_1)84i;oU5f1x?rGVX5GN z`GdGOVDUHq;NHcBdu5~@IMI$$Cq=qQgZOX|bL+Jv)$!4US#Iift+n#uI*yNF^v7a) z+5J;f&;p|j3~)u|{Pf$Tm82Zuv5ldwBLCH`d!!~Vtitqy>WA&n-Qxe)X%eCnN@Ji4 zEcYWUgAfG(gE3oM3HZsz8AFp3jMk%p?k>;2-?8o;Z_ZniHXO#0u&8XmELKK5t#LQg zpJirAl+zHQOstGvqh;3yDCcf-17OW|#Wd^7vrO5GfR`%~v|7K#%lk@(o0-2Id~%nw zidj&7utd+CEcfOyCf7X+vwFKe);T>iF?}hM5?DT<_}&y2t1>d3opdgn8Oa*lWZ+j| zJ*HXP&`CSdxd0v>r)OVzwMH#;=#FLMPGF8px1ms`s|9=2#%JaN+r(bWcJgK006rrU z@$9q1wsK=z`7Kq7ZQGrW+A#;=pOcO(PzWva0>5#0X*UGBy4>4wDu1T&HEK3s6^HwX z?<;$(5-2GnGHw%$S#tHaDK?!`OkMirih_MqgZ(5Ml~ zZPrP1+e}TW2Zn9$hv&zTBq#Y=ocj9+o|vr$f!eyoY9dA&1Gl)qh^kh!=rH|5Cll#$ z`LLLj(~U{g2QR8U!L}SES7*Cva|JwsWVW(%Fm{5JzFEMW`)~)~qHJ$4TlJUw1G1M9 zK2O1)37j8C{C3NWBK0MMiWltF-UH^GJF}= zoQT#KF>&G|E|`&#-b5tqF?B-Zq^a}Sy*bcEce-$G8T$^$I2K`v#ncVir%_KA5>@bl z2B2o-hT)3I({7x3u78OQmXeFMj1#sLszjKo*uSlXFdtg+s^Jti z6>U7OR@eCv#l@k!w4d<}WH&5pjNIPw&emHKfdk`t&y!9JY(aa`zxAASdtyn@`}v|B!R6r{79)*Z)Y)q zd_fIG8sTuJ9BkL=J;tZN~ zlaSyV+;)-R?havbcemgU!C5pAY$3S2TX1&>?jGENyDhG{oA2DZ=hV6TXREf}d1t0) zrnjg2>8BIk#~HZ0O*cy+T_#nidNzJf@!P%8=P#6Y{ncG3iQez2ib|mrxPqt@To(01 z9b?Zzt&mcMPNXS*IK zMR`b&;@1Z*1BK-I{7m z_$n&A?1PmbrfzeKqZObSpE^wVBN)hz?Mme`G6e!0+vGVZ2?49h@;h5HP+>$xG4awG zlt72dZU=3Vn)@ZyeqdQ|#sUju{*^W~odu{&E@7`NB;$G%H_>m9xf2{%&J3BNg;(~R z6E-ZVj!8=&%T^pNl>4a$-)4gp1*hds&6Axzk(&1*>7-pT)4q99IZC796>#tAeEdWC0aTT)4K))h>x z!-x?fx2u+=VeEM_aDrsVJ-rVQ%Ptc;EhNy|-4J84AC-2y`o*S5)Tn+nf28}fpl5r0 z^Gm@G`@*?rYX!JAqH#fYL*mM#Sjn`}043-W*=cuTR!@z6T;y$mtgtQ%mfpBoF|T#} z5&Id6?pnQ7eE%d4>{ljp!8)y=)J5~E48339>@Y;BihC$%W@nl`)#1Aon>N?f#*c}QocfDROPLry z?ylSF@|Ucr3}^6T-!^a6>pt79X!QoFq6{|G#F?pK^i^`vFg`BhyZyQNG}Gw~=;F3Z zV@2^;i14|sbv9s9lM{12m<^-}wU`E-RPZMvOyi~oGl9P-(|62nuA~;0BaTu!fk_Zk z2^QzanKDo83^jY2DUbK<*0YHlsLS8( z8pnsCK@S8zD(zHnLZoK}te#=^vR?}Ds5MmLbdtyO;tO-f zwW=x0FBF#ci?FAw7m|ct$NP&-edl2+7`Ls20`m_Linurk+`=0l{B!o*>w1W&B9 z+W-qWyA^)^gaekTC=wN6A5b?8mNm(~s(IqvEaV*4y$c~WLvC1lgc4!*PD*d8dM7-L zM%;g~{1()!i-e$@K1)-Ew$MMt-lH+tEz;D7NoY+#OI`O2EC5xQ$5pRLd)XbOjb!Hs zP@xdh;+uOaZ0I|y&hpXqPtL4Go>W3ulxF^6j7-Ys$vZdM-XP^5xmmIt<_NXmf87QgY+C5hw?xXcs6> zaU3!AcJ!(0V=}%yu`_E}*2`C5Z^CW8{F&S+{oVqpmwX#F{RfMD-e4i0jIKhn9-kG9 zo1mpHp(Aru-(llsY;~{6fi(>Cl>aatHc|KRY)5-n+i$zqes;JMUaj6b7~}0s3ohO% zA3iZ1t$gF%|0&Py9b8=b_;txpf6RfD67_zWf|C6OG|5J6kM4JNrWLy zbn%1**S{m1aK*MnZH3Tm*{M%VkYoT*F8dm8p}`Wb%yICJVmp>KNejLNQJc5Rn`qeC zXx4E5h|qruB-4^92VNO+DlZ})J0Q{Av%*4 zu&AcsC5hh9AsK(m;a3UKrX3pH=2;snH&mUF67YGCVaoE8@q9r*wxuuP^9$s#Z1Lg# z@I^fTXcr%_Tqu#k$h{*sDreSiOsz7Ld)+Pi)By}C=vJS|&@g#6U*v03qX(;UMyj5V zWHk()>Y0`{){<{4(dA(Q6AvrEra2I0C%CRGL-~%y#Enrkk_awwYim-MCiuf8?%?N> zB>ibwS62n0_$CCEmE~7j^%gU2!oq}>rU2sg63 z_F-@jG7gUTj0_T35pib2-Wh*a<%u0Inp?(Pk{t&wBbM zc*VzdH3p*Tx!1T}IV3qQjn^tXmGD3?!{ua(34pVBc9fg3A5sANVTW(|{JMe=G`R@^ zb&Q{h5vOAo(~^}M#dN-H__d|`+5jPxw1C2D3iF$c%Ncqk9>8tK6c#CcuZSJvGOog^fNS<m{6+J+4BU+sV{J^nn&tf@y3M_Hx2Z7?m869e))LispX#cKqNc{J{ zKGvHRSx>MbTp~L0T3x?Y?ci3euy#VPNvfqD47`ukod=wK-hfA0b zNl=j8e->Xol3;KaCPG)Ox21{T=^rE@_NXnDT}~z_t4tyVdnY9RnvirL=z^dtvFxvn zbA1YX>-B!442HQQ!HZz&Ssq{|x2qqn{yA(FinT(GRY6WKzE4*?Q^ORGUM3|*PW)jc z{*!a1MYcy5I{Pc`!~V&iE$Ub`HN1pr+S(Orr#W@6)H*8Z?1@rW`37Q{EZ)~K~lV9!TDbg137Hep3D(4AdaXBPJ%{ z6ZG>U`d)!W%}n2a`P9F9`G9W2WMK^qbt<=k`F(e2?g$$gJ;qYlR{j6Jta@zt4s6uc zHW#1J{(~sEObQJO-L0Aiz5Ig1h>0PSoa`c`O1QhJRae@YY;;9vu7C` zV!KZi8oSf|y@LwZ5KuO2y>*YnQCy%)5Nl)M86K=33l2SM%%R=r+q4HWh>Xpj&IxiC zB61mQeoZtHq*rZD9vmy-M4>6Go*hG##i8pG(Z@!bU}b^D{}v2Jo&GxU^zOqSER!cD zdbpW~$>B7w+G4F#Ih(^d&cV|OQfEfxV!mxkea(zJ$j5;)i%4u*gv95zEP=ZYiom3 zmOs&y#f*tbV19cjj9&S4=JsrPyWag4;bXCX@WY|Aqb2O)VX>cnzT#-1NM)-VOq$5m z5mbIi9!gE>Vc)e9!IKN`(grEsa-QBEJ>4PRwYi~6<>L`#4m(*)$&f08T4<0~QeY^( zwntADFR&TQb#ilRwjrdlI1P(OWW5Fm-eG|q@GEH~Y4vG-mibfWwP&njE;p2peII8! z(Q``KZ(6Ch)SY*wV?VBS7rBrrAd(&i5<%%Z&8PmqNFFf86j{g(v0 z|GXFQaS-h$7#f>6sT6vx?WX8XB5xYN6vjNqsLuM(@Ng6*A(b*^z5eQMTjSGijvImj zUBq_SI&;uyuBp^Pgyb*K>z#xNf8$l2;RdiYac#%(q!}moIr-vJ+FG1%ALHbvXO19& z3Z@x~vSaJCF)B>_D$j-l`wOSDVi(PXcO6@f?~Ym1Gwtq~6oxX)_~mhG zr4AYmip;Bf3q|-@@_wCT7n+rHub6_u6r3)O&P(m+p|)!F36g#!Zb+mquX_}B4WL7< zZuu}V9L+lEENm}_*IRu&yrZat3IE{9?cP}JWb?^|Kk4w2ff5_rnN)OrBAp?j$!32z z=_zwSPShE5PajE0_UF#uP4g8MLBowzvxqYzZeAN%s85{Yk#`MQrg}>4D?LvRh#r46!*hlLLuyVnR zl|T|ksibIW>MSXMv?EOtIu|4Bvp7QmD9PSK+qNPQ|1#_@Bx=Ut>y71J98kT(Sn2IA zwBX+!S&Y9Tjj_PyA%)k*PP%N?w6B?l91Obr+k4JKk{ZpT(kCtVUbHa^*C>SG0j7PX7Rhkna+(gIxcl z*8c+WZU_mxA2b+YNg#=)31MK4F6@Z0#9pwhBU_OR{2ea7Ix}5}AHv6+kX&i)EIvPm zUAx!xniw6+Mb%8|mG`KzH%>s>DFzm-6AZ2Xf?ZhDAw;w4juD(Y*L=RteScos(`?Z# z4qjd5`HNYH&Q~w9%q8B5psyNj1Yn%F$_QPlg|>QeM$#M7?qv6!-)y0w?YDAIyH=Qd zdEV);s|G`6g%>{n!i}oHA4WDiS{#%jss32_&B1Yn;<`ZGI#B9)eZ_54vb~LZWOcBO&Y%(s#6+OTI z;$uD{#rLcs^)>j54f4ZchtqqWrby#8gGhoEs;EE;@@Vm_zykT-EyE4A#Uv3{yl4-A zM!6-bM>v&Sik?fSb_cKLh4iSRlJVlx#bLp?Um)--L-`EuN zQr6o>Y<{bt*N}yZ?sTRblEuW)Ag-BAriCn;nK@46K`<$|^n?BF!`}wzycrV*ttvH@f`& zGZgtQ`$Qm^Az5FS=WwE>I1{=Yl)5dsbFPTODs&+MLPt(IRocr#P7>y{c+9z0dyA`! zC~Kh4ka239k$7YtmZC-RtV4&M)PzYr|D8C7AbV*tN$Y1&H6Eh*5W~#;Ok#SSE4*26 zd9mM%EQP;Y%OO-&5VLeUolnNceM+LlYS=Ar+5<>yV$+EE8w;;TEb_UOr_R7~@0+q< zULI;QI&RIU(eHAcTR-_UXmS23Jm&#PBxjHE>X?>0vOV^`%qGs|;<8Cx*_9HBD`iFt zwJ^0hbw=jN02io`>L%k$NUS22uCX0!mBZi+jab>U6FaK z^#*s61w|GE=9OnbyVXK1^2(WGcTpP=$Jq$KYXymHfWDJf5}wzLPkZr2VC}27a!Wk?X~d_&ceCX;Yfn({o>tO`U9`2p$4?#wO9T=c6+IauUu=Ziq7(;{)!CU-n8qKzzq=q)M zJHL$)Y-=-{g9zqjWmkj5ya;&Zc9)pZN}zv4q6bT9+Eqv_ zw}9D+M7R}wp@+Q9G|@s1r9Ymgb;dXy^`grjsb{)0F|jBdWQ5{@6uTW>YXB!l_`st% zpDZacTR3%xyrO7pnAG9Ov(yMg}$RT#&ydV}f81wa!aRIUggD-sN8^q|L1YQ)0shm7ry|c0jJ>&7Pg#I^|lP_Nt$*y zd7{_5&5I`3_^fG%1T4FHf4D z{KL)Ih&5`?XXj4vOD|K=h~E09yJal1$|1!JJIkOGeOi(7{R_MQ?>e zr+#w(2r5F-H-YSD?LzFAv{OA49b+y`pfSaonMwK-S5w#oEVvH&8k)V~z8}9M4akAkku=;;lIdnYAMz$-eADSpz8d zO1sl5#2haEjEyYyUR$CSemWYHE>_N(LriMF_BI9W-l` z%L$og^H?)3IvJso9!dE8L}(Gak&BCBxHM$s<fzOIx4IG_W;w-q!Pb8{f_^PBZJr5k(Yi-EO71koo z`AurTt-n>3fS@WIA@VNQ(Z)JLIP@StBkWogbvy4?^!;wjy_Xm~2gZs-OT^U<+IxO_ zUDe`W+qf^0i{Y!Qd^j%703}Cyvo1BSR|o@2>W-_$)s+`MIj$JkQrbSrK l0;4F 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 diff --git a/bsp/microchip/doc/2-2-6-atmel-start-modify-file2.png b/bsp/microchip/doc/2-2-6-atmel-start-modify-file2.png index 0eda392d525fe27992a7a794cdc446f5022526b7..273cba0422a5f3e2850179991a1931492260fe24 100644 GIT binary patch literal 45179 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 uC$O}?d-emOI1@H>A^gt&diaenG11f+`sp+}_m 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 Hapyk(OWv@i diff --git a/bsp/microchip/doc/3-1-9-atmel-start-rt-thread-run.png b/bsp/microchip/doc/3-1-9-atmel-start-rt-thread-run.png new file mode 100644 index 0000000000000000000000000000000000000000..875df4441a2cf5c98e0178c3112fb7345954fbbc GIT binary patch literal 21886 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 literal 0 HcmV?d00001 diff --git a/bsp/microchip/samc21/.config b/bsp/microchip/samc21/.config index 9d2bd72f81..b2f9aef839 100644 --- a/bsp/microchip/samc21/.config +++ b/bsp/microchip/samc21/.config @@ -93,8 +93,32 @@ CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # CONFIG_RT_USING_LEGACY is not set -# CONFIG_RT_USING_MSH is not set -# CONFIG_RT_USING_DFS is not set +CONFIG_RT_USING_MSH=y +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=4 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set # CONFIG_RT_USING_FAL is not set # CONFIG_RT_USING_LWP is not set @@ -102,7 +126,9 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set @@ -111,7 +137,9 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +# CONFIG_RT_USING_I2C_BITOPS is not set # CONFIG_RT_USING_PHY is not set # CONFIG_RT_USING_PIN is not set # CONFIG_RT_USING_ADC is not set @@ -639,10 +667,12 @@ CONFIG_SOC_SAMC21J18=y # CONFIG_SAMC21_CAN0=y CONFIG_SAMC21_ADC0=y +CONFIG_SAMC21_I2C0=y # # Application Demo Config # CONFIG_SAM_CAN_EXAMPLE=y CONFIG_SAM_ADC_EXAMPLE=y +CONFIG_SAM_I2C_EXAMPLE=y CONFIG_SOC_SAMC21=y diff --git a/bsp/microchip/samc21/SConstruct b/bsp/microchip/samc21/SConstruct index 4d91cd5ba5..9f8b13d9cf 100644 --- a/bsp/microchip/samc21/SConstruct +++ b/bsp/microchip/samc21/SConstruct @@ -34,8 +34,27 @@ if rtconfig.PLATFORM == 'iar': Export('RTT_ROOT') Export('rtconfig') +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/common'): + common_path_prefix = SDK_ROOT + '/common' +else: + common_path_prefix = os.path.dirname(SDK_ROOT) + '/common' + +SDK_LIB = common_path_prefix +Export('SDK_LIB') + # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) +sam_board = 'board' +rtconfig.BSP_LIBRARY_TYPE = sam_board + +# include libraries +objs.extend(SConscript(os.path.join(common_path_prefix, sam_board, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(common_path_prefix, 'applications', 'SConscript'))) + # make a building DoBuilding(TARGET, objs) diff --git a/bsp/microchip/samc21/applications/can_demo.c b/bsp/microchip/samc21/applications/can_demo.c deleted file mode 100644 index a21f755725..0000000000 --- a/bsp/microchip/samc21/applications/can_demo.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release - */ - -#include - -#ifdef RT_USING_FINSH -#include -#include -#endif - -#include "atmel_start.h" -#include "driver_init.h" -#include "utils.h" - -#include "can_demo.h" - -#ifdef SAM_CAN_EXAMPLE - -static volatile enum can_async_interrupt_type can_errors; -static rt_sem_t can_txdone; -static rt_sem_t can_rxdone; -static rt_uint8_t can_stack[ 512 ]; -static struct rt_thread can_thread; - -/** - * @brief Callback function and should be invoked after call can_async_write. - * - * @note - * - * @param descr is CAN device description. - * - * @return None. - */ - -static void can_tx_callback(struct can_async_descriptor *const descr) -{ - rt_err_t result; - - rt_interrupt_enter(); - result = rt_sem_release(can_txdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); -} - -/** - * @brief Callback function and should be invoked after remote device send. - * - * @note This callback function will be called in CAN interrupt function - * - * @param descr is CAN device description. - * - * @return None. - */ - -static void can_rx_callback(struct can_async_descriptor *const descr) -{ - rt_err_t result; - - rt_interrupt_enter(); - result = rt_sem_release(can_rxdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); -} - -/** - * @brief Callback function and should be invoked after CAN device IRQ handler detects errors happened. - * - * @note This callback function will be called in CAN interrupt function - * - * @param descr is CAN device description. - * - * @return None. - */ - -static void can_err_callback(struct can_async_descriptor *const descr, - enum can_async_interrupt_type type) -{ - rt_err_t result; - - if (type == CAN_IRQ_EW) - { - /* Error warning, Error counter has reached the error warning limit of 96, - * An error count value greater than about 96 indicates a heavily disturbed - * bus. It may be of advantage to provide means to test for this condition. - */ - } - else if (type == CAN_IRQ_EA) - { - /* Error Active State, The CAN node normally take part in bus communication - * and sends an ACTIVE ERROR FLAG when an error has been detected. - */ - } - else if (type == CAN_IRQ_EP) - { - /* Error Passive State, The Can node goes into error passive state if at least - * one of its error counters is greater than 127. It still takes part in bus - * activities, but it sends a passive error frame only, on errors. - */ - } - else if (type == CAN_IRQ_BO) - { - /* Bus Off State, The CAN node is 'bus off' when the TRANSMIT ERROR COUNT is - * greater than or equal to 256. - */ - - /* Suspend CAN task and re-initialize CAN module. */ - can_errors = type; - rt_interrupt_enter(); - result = rt_sem_release(can_rxdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); - } - else if (type == CAN_IRQ_DO) - { - /* Data Overrun in receive queue. A message was lost because the messages in - * the queue was not reading and releasing fast enough. There is not enough - * space for a new message in receive queue. - */ - - /* Suggest to delete CAN task and re-initialize it. */ - can_errors = type; - rt_interrupt_enter(); - result = rt_sem_release(can_rxdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); - } -}; - -/** - * @brief Initialize CAN module before task run. - * - * @note This function will set CAN Tx/Rx callback function and filters. - * - * @param None. - * - * @return None. - */ - -static inline void can_demo_init(void) -{ - struct can_filter filter; - - /** - * CAN_Node0_tx_callback callback should be invoked after call - * can_async_write, and remote device should receive message with ID=0x45A - */ - can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)can_tx_callback); - - /** - * CAN_0_rx_callback callback should be invoked after call - * can_async_set_filter and remote device send CAN Message with the same - * content as the filter. - */ - can_async_register_callback(&CAN_0, CAN_ASYNC_RX_CB, (FUNC_PTR)can_rx_callback); - - - /* Should set at least one CAN standard & message filter before enable it. */ - - filter.id = 0x469; - filter.mask = 0; - can_async_set_filter(&CAN_0, 0, CAN_FMT_STDID, &filter); - - /* If set second standard message filter, should increase filter index - * and filter algorithm - * For example: index should set to 1, otherwise it will replace filter 0. - * can_async_set_filter(&CAN_0, 1, CAN_FMT_STDID, &filter); */ - - filter.id = 0x10000096; - filter.mask = 0; - can_async_set_filter(&CAN_0, 0, CAN_FMT_EXTID, &filter); - - can_async_enable(&CAN_0); -} - -/** - * @brief CAN task. - * - * @note This task will waiting for CAN RX semaphore and then process input. - * - * @param parameter - task input parameter. - * - * @return None. - */ - -static void can_thread_entry(void* parameter) -{ - int32_t ret; - rt_err_t result; - uint8_t data[64]; - uint32_t count=0; - struct can_message msg; - - while (1) - { -#ifndef RT_USING_FINSH - rt_kprintf("can task run count : %d\r\n",count); -#endif - count++; - - result = rt_sem_take(can_rxdone, RT_WAITING_FOREVER); - if (RT_EOK != result) - continue; - - do - { - /* Process the incoming packet. */ - ret = can_async_read(&CAN_0, &msg); - if (ret == ERR_NONE) - { -#ifndef RT_USING_FINSH - rt_kprintf("CAN RX Message is % frame\r\n", - msg.type == CAN_TYPE_DATA ? "data" : "remote"); - rt_kprintf("CAN RX Message is % frame\r\n", - msg.type == CAN_FMT_STDID ? "Standard" : "Extended"); - rt_kprintf("can RX Message ID: 0x%X length: %d\r\n", msg.id, msg.len); - rt_kprintf("CAN RX Message content: "); - for (uint8_t i = 0; i < msg.len; i++) - rt_kprintf("0x%02X ", data[i]); - rt_kprintf("\r\n"); -#endif - } - } while (ret == ERR_NONE); /* Get all data stored in CAN RX FIFO */ - - /* CAN task got CAN error message, handler CAN Error Status */ - if ((can_errors == CAN_IRQ_BO) || (can_errors == CAN_IRQ_DO)) - { - can_async_init(&CAN_0, CAN1); - } - } -} - -/** - * @brief Call this function will to send a CAN message. - * - * @note - * - * @param msg - message to be sent, timeouts - wait timeouts for Tx completion. - * - * @return RT_OK or RT_ERROR. - */ - -rt_err_t can_send_message(struct can_message *msg, rt_uint32_t timeouts) -{ - rt_err_t result; - - if (RT_NULL == msg) - { - rt_kprintf("can_send_message input message error\r\n"); - return RT_ERROR; - } - - can_async_write(&CAN_0, msg); - result = rt_sem_take(can_rxdone, timeouts); - - return result; -} - -/** - * @brief Call this function will create a CAN task. - * - * @note Should create Tx/Rx semaphore before run task. - * - * @param None. - * - * @return RT_OK or -RT_ERROR. - */ - -rt_err_t can_demo_run(void) -{ - rt_err_t result; - - can_rxdone = rt_sem_create("can_rx", 0, RT_IPC_FLAG_FIFO); - if (RT_NULL == can_rxdone) - { - rt_kprintf("can_rx semaphore create failed\r\n"); - return (-RT_ERROR); - } - - can_txdone = rt_sem_create("can_tx", 0, RT_IPC_FLAG_FIFO); - if (RT_NULL == can_txdone) - { - rt_kprintf("can_tx semaphore create failed\r\n"); - return (-RT_ERROR); - } - - can_demo_init(); - - /* initialize CAN thread */ - result = rt_thread_init(&can_thread, - "can", - can_thread_entry, - RT_NULL, - (rt_uint8_t*)&can_stack[0], - sizeof(can_stack), - RT_THREAD_PRIORITY_MAX/3, - 5); - if (result == RT_EOK) - { - rt_thread_startup(&can_thread); - } - - return result; -} -#endif - -/*@}*/ diff --git a/bsp/microchip/samc21/applications/main.c b/bsp/microchip/samc21/applications/main.c index 8985159058..e055ad0ab1 100644 --- a/bsp/microchip/samc21/applications/main.c +++ b/bsp/microchip/samc21/applications/main.c @@ -5,7 +5,7 @@ * * Change Logs: * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + * 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release */ #include @@ -22,6 +22,14 @@ #include "can_demo.h" #endif +#ifdef SAM_I2C_EXAMPLE +#include "i2c_demo.h" +#endif + +#ifdef SAM_ADC_EXAMPLE +#include "adc_demo.h" +#endif + static rt_uint8_t led_stack[ 512 ]; static struct rt_thread led_thread; @@ -63,6 +71,14 @@ int main(void) can_demo_run(); #endif +#ifdef SAM_I2C_EXAMPLE + i2c_demo_run(); +#endif + +#ifdef SAM_ADC_EXAMPLE + adc_demo_run(); +#endif + return 0; } diff --git a/bsp/microchip/samc21/board/Kconfig b/bsp/microchip/samc21/board/Kconfig index 6004fe8fc7..a612480864 100644 --- a/bsp/microchip/samc21/board/Kconfig +++ b/bsp/microchip/samc21/board/Kconfig @@ -32,6 +32,11 @@ menu "Onboard Peripheral Drivers" config SAMC21_ADC0 bool "Enable ADC0" default false + + config SAMC21_I2C0 + bool "Enable I2C0" + default false + endmenu menu "Application Demo Config" @@ -49,4 +54,10 @@ menu "Application Demo Config" help Add ADC example task to project + config SAM_I2C_EXAMPLE + bool "Enable SAM I2C Example" + depends on SAMC21_I2C0 + default true + help + Add I2C example task to project endmenu diff --git a/bsp/microchip/samc21/board/board.c b/bsp/microchip/samc21/board/board.c index 457492ad51..cc49de728e 100644 --- a/bsp/microchip/samc21/board/board.c +++ b/bsp/microchip/samc21/board/board.c @@ -25,13 +25,14 @@ static struct io_descriptor* g_stdio; void rt_hw_console_output(const char *str) { io_write(g_stdio, (uint8_t *)str, strlen(str)); + while (TARGET_IO.stat != 0); } RTM_EXPORT(rt_hw_console_output); static inline void hw_board_init_usart(void) { - usart_sync_get_io_descriptor(&TARGET_IO, &g_stdio); - usart_sync_enable(&TARGET_IO); + usart_async_get_io_descriptor(&TARGET_IO, &g_stdio); + usart_async_enable(&TARGET_IO); } /** diff --git a/bsp/microchip/samc21/board/serial.c b/bsp/microchip/samc21/board/serial.c deleted file mode 100644 index 28ba104dbe..0000000000 --- a/bsp/microchip/samc21/board/serial.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release - */ - -#include -#include - -#include - -/* SAM MCU serial device */ -static struct rt_serial_device sam_serial; - -/** - * @brief Configure serial port - * - * This function will configure UART baudrate, parity and so on. - * - * @return RT_EOK. - */ -static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg) -{ - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - RT_ASSERT(cfg != RT_NULL); - - usart_sync_disable(desc); - - /* Set baudrate */ - usart_sync_set_baud_rate(desc, (const uint32_t)cfg->baud_rate); - - /* Set stop bit */ - if (cfg->stop_bits == STOP_BITS_1) - usart_sync_set_stopbits(desc, USART_STOP_BITS_ONE); - else if (cfg->stop_bits == STOP_BITS_2) - usart_sync_set_stopbits(desc, USART_STOP_BITS_TWO); - - if (cfg->bit_order == BIT_ORDER_LSB) - usart_sync_set_data_order(desc, USART_DATA_ORDER_LSB); - else if (cfg->bit_order == BIT_ORDER_MSB) - usart_sync_set_data_order(desc, USART_DATA_ORDER_MSB); - - /* Set character size */ - switch (cfg->data_bits) - { - case DATA_BITS_5: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_5BITS); - break; - case DATA_BITS_6: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_6BITS); - break; - case DATA_BITS_7: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_7BITS); - break; - case DATA_BITS_8: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_8BITS); - break; - case DATA_BITS_9: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_9BITS); - break; - default: - break; - } - - if (cfg->parity == PARITY_NONE) - usart_sync_set_parity(desc, USART_PARITY_NONE); - else if (cfg->parity == PARITY_ODD) - usart_sync_set_parity(desc, USART_PARITY_ODD); - else if (cfg->parity == PARITY_EVEN) - usart_sync_set_parity(desc, USART_PARITY_EVEN); - - usart_sync_enable(desc); - - return RT_EOK; -} - -/** - * @brief Control serial port - * - * This function provide UART enable/disable control. - * - * @return RT_EOK. - */ -static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg) -{ - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - - switch (cmd) - { - /* disable interrupt */ - case RT_DEVICE_CTRL_CLR_INT: - usart_sync_disable(desc); - break; - /* enable interrupt */ - case RT_DEVICE_CTRL_SET_INT: - usart_sync_enable(desc); - break; - /* UART config */ - case RT_DEVICE_CTRL_CONFIG : - break; - } - - return RT_EOK; -} - -/** - * @brief Serial sends a char - * - * This function will send a char to the UART - * - * @return 1. - */ -static int serial_putc(struct rt_serial_device *serial, char c) -{ - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - - io_write(&desc->io, (const uint8_t *)&c, 1); - - return 1; -} - -/** - * @brief Serial gets a char - * - * This function will get a char from the UART - * - * @return received char character or -1 if no char received. - */ -static int serial_getc(struct rt_serial_device *serial) -{ - char c; - int ch; - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - - ch = -1; - if (usart_sync_is_rx_not_empty(desc)) - { - io_read(&desc->io, (uint8_t *)&c, 1);; - ch = c & 0xff; - } - - return ch; -} - -static const struct rt_uart_ops sam_serial_ops = -{ - serial_configure, - serial_control, - serial_putc, - serial_getc, -}; - -/** - * @brief Initialize the UART - * - * This function initialize the UART - * - * @return None. - */ -int rt_hw_uart_init(void) -{ - struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; - - sam_serial.ops = &sam_serial_ops; - sam_serial.config = config; - sam_serial.serial_rx = RT_NULL; - sam_serial.serial_rx = RT_NULL; - rt_hw_serial_register(&sam_serial, "uart0", - RT_DEVICE_FLAG_RDWR, (void *)&TARGET_IO); - - return 0; -} - -/*@}*/ diff --git a/bsp/microchip/samc21/bsp/AtmelStart.gpdsc b/bsp/microchip/samc21/bsp/AtmelStart.gpdsc index 53c65dde79..0b97dd3fe8 100644 --- a/bsp/microchip/samc21/bsp/AtmelStart.gpdsc +++ b/bsp/microchip/samc21/bsp/AtmelStart.gpdsc @@ -42,17 +42,21 @@ Atmel Start Framework #define ATMEL_START + - + + + + @@ -78,6 +82,7 @@ + @@ -90,9 +95,11 @@ + + @@ -138,7 +145,10 @@ - + + + + @@ -148,8 +158,11 @@ - + + + + @@ -168,6 +181,7 @@ + @@ -183,6 +197,7 @@ + diff --git a/bsp/microchip/samc21/bsp/SConscript b/bsp/microchip/samc21/bsp/SConscript index 08c10b1d21..558922007f 100644 --- a/bsp/microchip/samc21/bsp/SConscript +++ b/bsp/microchip/samc21/bsp/SConscript @@ -11,8 +11,10 @@ CPPDEFINES = [] CPPDEFINES += [rtconfig.DEVICE_TYPE] # The set of source files associated with this SConscript file. + src = Glob('hal/src/*.c') src += Glob('hal/utils/src/*.c') +src += Glob('hpl/adc/*.c') src += Glob('hpl/can/*.c') src += Glob('hpl/core/*.c') src += Glob('hpl/divas/*.c') @@ -45,12 +47,15 @@ path = [ cwd + '/config', cwd + '/hal/include', cwd + '/hal/utils/include', + cwd + '/hpl/adc', cwd + '/hpl/can', cwd + '/hpl/core', cwd + '/hpl/gclk', cwd + '/hpl/pm', cwd + '/hpl/port', cwd + '/hri', + cwd + '/../board', + cwd + '/../../common/applications', cwd + '/samc21/include'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/microchip/samc21/bsp/armcc/Makefile b/bsp/microchip/samc21/bsp/armcc/Makefile deleted file mode 100644 index c756181f09..0000000000 --- a/bsp/microchip/samc21/bsp/armcc/Makefile +++ /dev/null @@ -1,218 +0,0 @@ - -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -ifdef SystemRoot - SHELL = cmd.exe - MK_DIR = mkdir -else - ifeq ($(shell uname), Linux) - MK_DIR = mkdir -p - endif - - ifeq ($(shell uname | cut -d _ -f 1), CYGWIN) - MK_DIR = mkdir -p - endif - - ifeq ($(shell uname | cut -d _ -f 1), MINGW32) - MK_DIR = mkdir -p - endif - - ifeq ($(shell uname | cut -d _ -f 1), MINGW64) - MK_DIR = mkdir -p - endif -endif - -# List the subdirectories for creating object files -SUB_DIRS += \ - \ -hpl/pm \ -hpl/osc32kctrl \ -hpl/can \ -hpl/dmac \ -samc21/armcc/Device/SAMC21/Source/ARM \ -hal/src \ -hpl/mclk \ -hal/utils/src \ -hpl/sercom \ -examples \ -hpl/gclk \ -hpl/oscctrl \ -samc21/armcc/Device/SAMC21/Source \ -hpl/nvmctrl \ -hpl/core \ -hpl/divas - -# List the object files -OBJS += \ -hal/src/hal_io.o \ -hal/src/hal_can_async.o \ -hpl/can/hpl_can.o \ -hpl/nvmctrl/hpl_nvmctrl.o \ -samc21/armcc/Device/SAMC21/Source/ARM/startup_SAMC21.o \ -hal/src/hal_delay.o \ -hpl/oscctrl/hpl_oscctrl.o \ -hpl/core/hpl_init.o \ -hal/utils/src/utils_list.o \ -hpl/core/hpl_core_m0plus_base.o \ -hal/utils/src/utils_assert.o \ -hpl/dmac/hpl_dmac.o \ -hpl/pm/hpl_pm.o \ -hal/src/hal_usart_sync.o \ -hpl/mclk/hpl_mclk.o \ -hpl/gclk/hpl_gclk.o \ -hal/src/hal_flash.o \ -hal/src/hal_init.o \ -main.o \ -hpl/osc32kctrl/hpl_osc32kctrl.o \ -examples/driver_examples.o \ -driver_init.o \ -samc21/armcc/Device/SAMC21/Source/system_samc21.o \ -hpl/sercom/hpl_sercom.o \ -hal/src/hal_gpio.o \ -hpl/divas/hpl_divas.o \ -hal/utils/src/utils_event.o \ -hal/src/hal_sleep.o \ -atmel_start.o \ -hal/src/hal_atomic.o - -OBJS_AS_ARGS += \ -"hal/src/hal_io.o" \ -"hal/src/hal_can_async.o" \ -"hpl/can/hpl_can.o" \ -"hpl/nvmctrl/hpl_nvmctrl.o" \ -"samc21/armcc/Device/SAMC21/Source/ARM/startup_SAMC21.o" \ -"hal/src/hal_delay.o" \ -"hpl/oscctrl/hpl_oscctrl.o" \ -"hpl/core/hpl_init.o" \ -"hal/utils/src/utils_list.o" \ -"hpl/core/hpl_core_m0plus_base.o" \ -"hal/utils/src/utils_assert.o" \ -"hpl/dmac/hpl_dmac.o" \ -"hpl/pm/hpl_pm.o" \ -"hal/src/hal_usart_sync.o" \ -"hpl/mclk/hpl_mclk.o" \ -"hpl/gclk/hpl_gclk.o" \ -"hal/src/hal_flash.o" \ -"hal/src/hal_init.o" \ -"main.o" \ -"hpl/osc32kctrl/hpl_osc32kctrl.o" \ -"examples/driver_examples.o" \ -"driver_init.o" \ -"samc21/armcc/Device/SAMC21/Source/system_samc21.o" \ -"hpl/sercom/hpl_sercom.o" \ -"hal/src/hal_gpio.o" \ -"hpl/divas/hpl_divas.o" \ -"hal/utils/src/utils_event.o" \ -"hal/src/hal_sleep.o" \ -"atmel_start.o" \ -"hal/src/hal_atomic.o" - -# List the dependency files -DEPS := $(OBJS:%.o=%.d) - -DEPS_AS_ARGS += \ -"hal/utils/src/utils_event.d" \ -"hal/src/hal_io.d" \ -"hal/src/hal_can_async.d" \ -"hpl/can/hpl_can.d" \ -"samc21/armcc/Device/SAMC21/Source/ARM/startup_SAMC21.d" \ -"hpl/nvmctrl/hpl_nvmctrl.d" \ -"hpl/core/hpl_core_m0plus_base.d" \ -"hal/utils/src/utils_list.d" \ -"hpl/dmac/hpl_dmac.d" \ -"hal/utils/src/utils_assert.d" \ -"hal/src/hal_delay.d" \ -"hpl/core/hpl_init.d" \ -"hpl/pm/hpl_pm.d" \ -"hal/src/hal_flash.d" \ -"hpl/gclk/hpl_gclk.d" \ -"hal/src/hal_init.d" \ -"hal/src/hal_usart_sync.d" \ -"hpl/mclk/hpl_mclk.d" \ -"driver_init.d" \ -"samc21/armcc/Device/SAMC21/Source/system_samc21.d" \ -"hpl/osc32kctrl/hpl_osc32kctrl.d" \ -"main.d" \ -"examples/driver_examples.d" \ -"hpl/divas/hpl_divas.d" \ -"hal/src/hal_sleep.d" \ -"hpl/sercom/hpl_sercom.d" \ -"hal/src/hal_gpio.d" \ -"hal/src/hal_atomic.d" \ -"hpl/oscctrl/hpl_oscctrl.d" \ -"atmel_start.d" - -OUTPUT_FILE_NAME :=AtmelStart -QUOTE := " -OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf -OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf - -vpath %.c ../ -vpath %.s ../ -vpath %.S ../ - -# All Target -all: $(SUB_DIRS) $(OUTPUT_FILE_PATH) - -# Linker target - -$(OUTPUT_FILE_PATH): $(OBJS) - @echo Building target: $@ - @echo Invoking: ARMCC Linker - $(QUOTE)armlink$(QUOTE) --ro-base 0x00000000 --entry 0x00000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors \ ---strict --summary_stderr --info summarysizes --map --xref --callgraph --symbols \ ---info sizes --info totals --info unused --info veneers --list $(OUTPUT_FILE_NAME).map \ --o $(OUTPUT_FILE_NAME).elf --cpu Cortex-M0+ \ -$(OBJS_AS_ARGS) - - @echo Finished building target: $@ - -# Compiler target(s) - - - - -%.o: %.c - @echo Building file: $< - @echo ARMCC Compiler - $(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M0+ -D__SAMC21J18A__ \ --I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/can" -I"../hpl/core" -I"../hpl/divas" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../samc21/include" \ ---depend "$@" -o "$@" "$<" - - @echo Finished building: $< - -%.o: %.s - @echo Building file: $< - @echo ARMCC Assembler - $(QUOTE)armasm$(QUOTE) -g --apcs=interwork --cpu Cortex-M0+ --pd "D__SAMC21J18A__ SETA 1" \ --I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/can" -I"../hpl/core" -I"../hpl/divas" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../samc21/include" \ ---depend "$(@:%.o=%.d)" -o "$@" "$<" - - @echo Finished building: $< - -%.o: %.S - @echo Building file: $< - @echo ARMCC Preprocessing Assembler - $(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M0+ -D__SAMC21J18A__ \ --I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/can" -I"../hpl/core" -I"../hpl/divas" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../samc21/include" \ ---depend "$@" -o "$@" "$<" - - @echo Finished building: $< - -# Detect changes in the dependent files and recompile the respective object files. -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(strip $(DEPS)),) --include $(DEPS) -endif -endif - -$(SUB_DIRS): - $(MK_DIR) "$@" - -clean: - rm -f $(OBJS_AS_ARGS) - rm -f $(OUTPUT_FILE_PATH) - rm -f $(DEPS_AS_ARGS) - rm -f $(OUTPUT_FILE_NAME).map $(OUTPUT_FILE_NAME).elf diff --git a/bsp/microchip/samc21/bsp/atmel_start_config.atstart b/bsp/microchip/samc21/bsp/atmel_start_config.atstart index 726b284ec9..fcbc4c9730 100644 --- a/bsp/microchip/samc21/bsp/atmel_start_config.atstart +++ b/bsp/microchip/samc21/bsp/atmel_start_config.atstart @@ -22,6 +22,64 @@ application: configuration: null middlewares: {} drivers: + ADC_0: + user_label: ADC_0 + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::ADC0::driver_config_definition::ADC::HAL:Driver:ADC.Sync + functionality: ADC + api: HAL:Driver:ADC_Sync + configuration: + adc_advanced_settings: true + adc_arch_adjres: 0 + adc_arch_corren: false + adc_arch_dbgrun: false + adc_arch_dualsel: BOTH + adc_arch_event_settings: false + adc_arch_flushei: false + adc_arch_flushinv: false + adc_arch_gaincorr: 0 + adc_arch_leftadj: false + adc_arch_offcomp: false + adc_arch_offsetcorr: 0 + adc_arch_ondemand: false + adc_arch_r2r: false + adc_arch_refcomp: false + adc_arch_resrdyeo: false + adc_arch_runstdby: false + adc_arch_samplen: 0 + adc_arch_samplenum: 1 sample + adc_arch_seqen: 0 + adc_arch_slaveen: false + adc_arch_startei: false + adc_arch_startinv: false + adc_arch_winlt: 0 + adc_arch_winmode: No window mode + adc_arch_winmoneo: false + adc_arch_winut: 0 + adc_differential_mode: false + adc_freerunning_mode: false + adc_pinmux_negative: I/O ground + adc_pinmux_positive: ADC AIN0 pin + adc_prescaler: Peripheral clock divided by 2 + adc_reference: Internal bandgap reference + adc_resolution: 16-bit (averaging must be enabled) + optional_signals: + - identifier: ADC_0:AIN/10 + pad: PA10 + mode: Enabled + configuration: null + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::optional_signal_definition::ADC0.AIN.10 + name: ADC0/AIN/10 + label: AIN/10 + variant: null + clocks: + domain_group: + nodes: + - name: ADC + input: Generic clock generator 0 + external: false + external_frequency: 0 + configuration: + adc_gclk_selection: Generic clock generator 0 DMAC: user_label: DMAC definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::DMAC::driver_config_definition::DMAC::HAL:HPL:DMAC @@ -589,13 +647,53 @@ drivers: variant: null clocks: domain_group: null + I2C_0: + user_label: I2C_0 + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::SERCOM0::driver_config_definition::I2C.Master.Standard~2FFast-mode::HAL:Driver:I2C.Master.Sync + functionality: I2C + api: HAL:Driver:I2C_Master_Sync + configuration: + i2c_master_advanced: true + i2c_master_arch_dbgstop: Keep running + i2c_master_arch_inactout: 20-21 SCL cycle time-out(200-210us) + i2c_master_arch_lowtout: true + i2c_master_arch_mexttoen: true + i2c_master_arch_runstdby: false + i2c_master_arch_sdahold: 300-600ns hold time + i2c_master_arch_sexttoen: false + i2c_master_arch_trise: 215 + i2c_master_baud_rate: 100000 + optional_signals: [] + variant: + specification: SDA=0, SCL=1 + required_signals: + - name: SERCOM0/PAD/0 + pad: PA08 + label: SDA + - name: SERCOM0/PAD/1 + pad: PA09 + label: SCL + clocks: + domain_group: + nodes: + - name: Core + input: Generic clock generator 0 + external: false + external_frequency: 0 + - name: Slow + input: Generic clock generator 1 + external: false + external_frequency: 0 + configuration: + core_gclk_selection: Generic clock generator 0 + slow_gclk_selection: Generic clock generator 1 TARGET_IO: user_label: TARGET_IO - definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::SERCOM4::driver_config_definition::UART::HAL:Driver:USART.Sync + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::SERCOM4::driver_config_definition::UART::HAL:Driver:USART.Async functionality: USART - api: HAL:Driver:USART_Sync + api: HAL:Driver:USART_Async configuration: - usart_advanced: false + usart_advanced: true usart_arch_clock_mode: USART with internal clock usart_arch_cloden: false usart_arch_dbgstop: Keep running @@ -703,6 +801,24 @@ drivers: configuration: can_gclk_selection: Generic clock generator 0 pads: + PA08: + name: PA08 + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PA08 + mode: I2C + user_label: PA08 + configuration: null + PA09: + name: PA09 + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PA09 + mode: I2C + user_label: PA09 + configuration: null + PA10: + name: PA10 + definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PA10 + mode: Analog + user_label: PA10 + configuration: null PB10: name: PB10 definition: Atmel:SAMC21_Drivers:0.0.1::SAMC21J18A-AN::pad::PB10 diff --git a/bsp/microchip/samc21/bsp/atmel_start_pins.h b/bsp/microchip/samc21/bsp/atmel_start_pins.h index 93a0d0d7c5..315b19652f 100644 --- a/bsp/microchip/samc21/bsp/atmel_start_pins.h +++ b/bsp/microchip/samc21/bsp/atmel_start_pins.h @@ -22,6 +22,9 @@ #define GPIO_PIN_FUNCTION_H 7 #define GPIO_PIN_FUNCTION_I 8 +#define PA08 GPIO(GPIO_PORTA, 8) +#define PA09 GPIO(GPIO_PORTA, 9) +#define PA10 GPIO(GPIO_PORTA, 10) #define LED0 GPIO(GPIO_PORTA, 15) #define PA24 GPIO(GPIO_PORTA, 24) #define PA25 GPIO(GPIO_PORTA, 25) diff --git a/bsp/microchip/samc21/bsp/config/hpl_adc_config.h b/bsp/microchip/samc21/bsp/config/hpl_adc_config.h new file mode 100644 index 0000000000..62e61d968f --- /dev/null +++ b/bsp/microchip/samc21/bsp/config/hpl_adc_config.h @@ -0,0 +1,317 @@ +/* Auto-generated config file hpl_adc_config.h */ +#ifndef HPL_ADC_CONFIG_H +#define HPL_ADC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#ifndef CONF_ADC_0_ENABLE +#define CONF_ADC_0_ENABLE 1 +#endif + +// Basic Configuration + +// Conversion Result Resolution +// <0x0=>12-bit +// <0x1=>16-bit (averaging must be enabled) +// <0x2=>10-bit +// <0x3=>8-bit +// Defines the bit resolution for the ADC sample values (RESSEL) +// adc_resolution +#ifndef CONF_ADC_0_RESSEL +#define CONF_ADC_0_RESSEL 0x1 +#endif + +// Reference Selection +// <0x0=>Internal bandgap reference +// <0x1=>1/1.6 VDDANA +// <0x2=>1/2 VDDANA (only for VDDANA > 2.0V) +// <0x3=>External reference A +// <0x4=>DAC internal output +// <0x5=>VDDANA +// Select the reference for the ADC (REFSEL) +// adc_reference +#ifndef CONF_ADC_0_REFSEL +#define CONF_ADC_0_REFSEL 0x0 +#endif + +// Prescaler configuration +// <0x0=>Peripheral clock divided by 2 +// <0x1=>Peripheral clock divided by 4 +// <0x2=>Peripheral clock divided by 8 +// <0x3=>Peripheral clock divided by 16 +// <0x4=>Peripheral clock divided by 32 +// <0x5=>Peripheral clock divided by 64 +// <0x6=>Peripheral clock divided by 128 +// <0x7=>Peripheral clock divided by 256 +// These bits define the ADC clock relative to the peripheral clock (PRESCALER) +// adc_prescaler +#ifndef CONF_ADC_0_PRESCALER +#define CONF_ADC_0_PRESCALER 0x0 +#endif + +// Free Running Mode +// When enabled, the ADC is in free running mode and a new conversion will be initiated when a previous conversion completes. (FREERUN) +// adc_freerunning_mode +#ifndef CONF_ADC_0_FREERUN +#define CONF_ADC_0_FREERUN 0 +#endif + +// Differential Mode +// In differential mode, the voltage difference between the MUXPOS and MUXNEG inputs will be converted by the ADC. (DIFFMODE) +// adc_differential_mode +#ifndef CONF_ADC_0_DIFFMODE +#define CONF_ADC_0_DIFFMODE 0 +#endif + +// Positive Mux Input Selection +// <0x00=>ADC AIN0 pin +// <0x01=>ADC AIN1 pin +// <0x02=>ADC AIN2 pin +// <0x03=>ADC AIN3 pin +// <0x04=>ADC AIN4 pin +// <0x05=>ADC AIN5 pin +// <0x06=>ADC AIN6 pin +// <0x07=>ADC AIN7 pin +// <0x08=>ADC AIN8 pin +// <0x09=>ADC AIN9 pin +// <0x0A=>ADC AIN10 pin +// <0x0B=>ADC AIN11 pin +// <0x19=>Bandgap voltage +// <0x1A=>1/4 scaled core supply +// <0x1B=>1/4 scaled I/O supply +// <0x1C=>DAC output +// These bits define the Mux selection for the positive ADC input. (MUXPOS) +// adc_pinmux_positive +#ifndef CONF_ADC_0_MUXPOS +#define CONF_ADC_0_MUXPOS 0x0 +#endif + +// Negative Mux Input Selection +// <0x00=>ADC AIN0 pin +// <0x01=>ADC AIN1 pin +// <0x02=>ADC AIN2 pin +// <0x03=>ADC AIN3 pin +// <0x04=>ADC AIN4 pin +// <0x05=>ADC AIN5 pin +// <0x18=>Internal ground +// <0x19=>I/O ground +// These bits define the Mux selection for the negative ADC input. (MUXNEG) +// adc_pinmux_negative +#ifndef CONF_ADC_0_MUXNEG +#define CONF_ADC_0_MUXNEG 0x19 +#endif + +// + +// Advanced Configuration +// adc_advanced_settings +#ifndef CONF_ADC_0_ADVANCED +#define CONF_ADC_0_ADVANCED 1 +#endif + +// Slave enable +// Will enable master/slave operation and only available in slave instance +// adc_arch_slaveen +#ifndef CONF_ADC_0_SLAVEEN +#define CONF_ADC_0_SLAVEEN 0 +#endif + +// Dual mode trigger selection +// <0x0=>BOTH +// <0x1=>INTERLEAVE +// These bits define the trigger mode. (DUALSEL) +// adc_arch_dualsel +#ifndef CONF_ADC_0_DUALSEL +#define CONF_ADC_0_DUALSEL 0x0 +#endif + +// Rail-to-Rail operation +// This bit enable R2R operation (R2R) +// adc_arch_r2r +#ifndef CONF_ADC_0_R2R +#define CONF_ADC_0_R2R 0 +#endif + +// Run in standby +// Indicates whether the ADC will continue running in standby sleep mode or not (RUNSTDBY) +// adc_arch_runstdby +#ifndef CONF_ADC_0_RUNSTDBY +#define CONF_ADC_0_RUNSTDBY 0 +#endif + +// Debug Run +// If enabled, the ADC is running if the CPU is halted by an external debugger. (DBGRUN) +// adc_arch_dbgrun +#ifndef CONF_ADC_0_DBGRUN +#define CONF_ADC_0_DBGRUN 0 +#endif + +// On Demand Control +// Will keep the ADC peripheral running if requested by other peripherals (ONDEMAND) +// adc_arch_ondemand +#ifndef CONF_ADC_0_ONDEMAND +#define CONF_ADC_0_ONDEMAND 0 +#endif + +// Left-Adjusted Result +// When enabled, the ADC conversion result is left-adjusted in the RESULT register. The high byte of the 12-bit result will be present in the upper part of the result register. (LEFTADJ) +// adc_arch_leftadj +#ifndef CONF_ADC_0_LEFTADJ +#define CONF_ADC_0_LEFTADJ 0 +#endif + +// Reference Buffer Offset Compensation Enable +// The accuracy of the gain stage can be increased by enabling the reference buffer offset compensation. This will decrease the input impedance and thus increase the start-up time of the reference. (REFCOMP) +// adc_arch_refcomp +#ifndef CONF_ADC_0_REFCOMP +#define CONF_ADC_0_REFCOMP 0 +#endif + +// Comparator Offset Compensation Enable +// This bit indicates whether the Comparator Offset Compensation is enabled or not (OFFCOMP) +// adc_arch_offcomp +#ifndef CONF_ADC_0_OFFCOMP +#define CONF_ADC_0_OFFCOMP 0 +#endif + +// Digital Correction Logic Enabled +// When enabled, the ADC conversion result in the RESULT register is then corrected for gain and offset based on the values in the GAINCAL and OFFSETCAL registers. (CORREN) +// adc_arch_corren +#ifndef CONF_ADC_0_CORREN +#define CONF_ADC_0_CORREN 0 +#endif + +// Offset Correction Value <0-4095> +// If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for offset error before being written to the Result register. (OFFSETCORR) +// adc_arch_offsetcorr +#ifndef CONF_ADC_0_OFFSETCORR +#define CONF_ADC_0_OFFSETCORR 0 +#endif + +// Gain Correction Value <0-4095> +// If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for gain error before being written to the result register. (GAINCORR) +// adc_arch_gaincorr +#ifndef CONF_ADC_0_GAINCORR +#define CONF_ADC_0_GAINCORR 0 +#endif + +// Adjusting Result / Division Coefficient <0-7> +// These bits define the division coefficient in 2n steps. (ADJRES) +// adc_arch_adjres +#ifndef CONF_ADC_0_ADJRES +#define CONF_ADC_0_ADJRES 0x0 +#endif + +// Number of Samples to be Collected +// <0x0=>1 sample +// <0x1=>2 samples +// <0x2=>4 samples +// <0x3=>8 samples +// <0x4=>16 samples +// <0x5=>32 samples +// <0x6=>64 samples +// <0x7=>128 samples +// <0x8=>256 samples +// <0x9=>512 samples +// <0xA=>1024 samples +// Define how many samples should be added together.The result will be available in the Result register (SAMPLENUM) +// adc_arch_samplenum +#ifndef CONF_ADC_0_SAMPLENUM +#define CONF_ADC_0_SAMPLENUM 0x0 +#endif + +// Sampling Time Length <0-63> +// These bits control the ADC sampling time in number of CLK_ADC cycles, depending of the prescaler value, thus controlling the ADC input impedance. (SAMPLEN) +// adc_arch_samplen +#ifndef CONF_ADC_0_SAMPLEN +#define CONF_ADC_0_SAMPLEN 0 +#endif + +// Window Monitor Mode +// <0x0=>No window mode +// <0x1=>Mode 1: RESULT above lower threshold +// <0x2=>Mode 2: RESULT beneath upper threshold +// <0x3=>Mode 3: RESULT inside lower and upper threshold +// <0x4=>Mode 4: RESULT outside lower and upper threshold +// These bits enable and define the window monitor mode. (WINMODE) +// adc_arch_winmode +#ifndef CONF_ADC_0_WINMODE +#define CONF_ADC_0_WINMODE 0x0 +#endif + +// Window Monitor Lower Threshold <0-65535> +// If the window monitor is enabled, these bits define the lower threshold value. (WINLT) +// adc_arch_winlt +#ifndef CONF_ADC_0_WINLT +#define CONF_ADC_0_WINLT 0 +#endif + +// Window Monitor Upper Threshold <0-65535> +// If the window monitor is enabled, these bits define the lower threshold value. (WINUT) +// adc_arch_winut +#ifndef CONF_ADC_0_WINUT +#define CONF_ADC_0_WINUT 0 +#endif + +// Bitmask for positive input sequence <0-4294967295> +// Use this parameter to input the bitmask for positive input sequence control (refer to datasheet for the device). +// adc_arch_seqen +#ifndef CONF_ADC_0_SEQEN +#define CONF_ADC_0_SEQEN 0x0 +#endif + +// + +// Event Control +// adc_arch_event_settings +#ifndef CONF_ADC_0_EVENT_CONTROL +#define CONF_ADC_0_EVENT_CONTROL 0 +#endif + +// Window Monitor Event Out +// Enables event output on window event (WINMONEO) +// adc_arch_winmoneo +#ifndef CONF_ADC_0_WINMONEO +#define CONF_ADC_0_WINMONEO 0 +#endif + +// Result Ready Event Out +// Enables event output on result ready event (RESRDEO) +// adc_arch_resrdyeo +#ifndef CONF_ADC_0_RESRDYEO +#define CONF_ADC_0_RESRDYEO 0 +#endif + +// Invert flush Event Signal +// Invert the flush event input signal (FLUSHINV) +// adc_arch_flushinv +#ifndef CONF_ADC_0_FLUSHINV +#define CONF_ADC_0_FLUSHINV 0 +#endif + +// Trigger Flush On Event +// Trigger an ADC pipeline flush on event (FLUSHEI) +// adc_arch_flushei +#ifndef CONF_ADC_0_FLUSHEI +#define CONF_ADC_0_FLUSHEI 0 +#endif + +// Invert Start Conversion Event Signal +// Invert the start conversion event input signal (STARTINV) +// adc_arch_startinv +#ifndef CONF_ADC_0_STARTINV +#define CONF_ADC_0_STARTINV 0 +#endif + +// Trigger Conversion On Event +// Trigger a conversion on event. (STARTEI) +// adc_arch_startei +#ifndef CONF_ADC_0_STARTEI +#define CONF_ADC_0_STARTEI 0 +#endif + +// + +// <<< end of configuration section >>> + +#endif // HPL_ADC_CONFIG_H diff --git a/bsp/microchip/samc21/bsp/config/hpl_sercom_config.h b/bsp/microchip/samc21/bsp/config/hpl_sercom_config.h index a310177cd5..3bf58d68da 100644 --- a/bsp/microchip/samc21/bsp/config/hpl_sercom_config.h +++ b/bsp/microchip/samc21/bsp/config/hpl_sercom_config.h @@ -6,6 +6,141 @@ #include +#ifndef SERCOM_I2CM_CTRLA_MODE_I2C_MASTER +#define SERCOM_I2CM_CTRLA_MODE_I2C_MASTER (5 << 2) +#endif + +#ifndef CONF_SERCOM_0_I2CM_ENABLE +#define CONF_SERCOM_0_I2CM_ENABLE 1 +#endif + +// Basic + +// I2C Bus clock speed (Hz) <1-400000> +// I2C Bus clock (SCL) speed measured in Hz +// i2c_master_baud_rate +#ifndef CONF_SERCOM_0_I2CM_BAUD +#define CONF_SERCOM_0_I2CM_BAUD 100000 +#endif + +// + +// Advanced +// i2c_master_advanced +#ifndef CONF_SERCOM_0_I2CM_ADVANCED_CONFIG +#define CONF_SERCOM_0_I2CM_ADVANCED_CONFIG 1 +#endif + +// TRise (ns) <0-300> +// Determined by the bus impedance, check electric characteristics in the datasheet +// Standard Fast Mode: typical 215ns, max 300ns +// Fast Mode +: typical 60ns, max 100ns +// High Speed Mode: typical 20ns, max 40ns +// i2c_master_arch_trise + +#ifndef CONF_SERCOM_0_I2CM_TRISE +#define CONF_SERCOM_0_I2CM_TRISE 215 +#endif + +// Master SCL Low Extended Time-Out (MEXTTOEN) +// This enables the master SCL low extend time-out +// i2c_master_arch_mexttoen +#ifndef CONF_SERCOM_0_I2CM_MEXTTOEN +#define CONF_SERCOM_0_I2CM_MEXTTOEN 1 +#endif + +// Slave SCL Low Extend Time-Out (SEXTTOEN) +// Enables the slave SCL low extend time-out. If SCL is cumulatively held low for greater than 25ms from the initial START to a STOP, the slave will release its clock hold if enabled and reset the internal state machine +// i2c_master_arch_sexttoen +#ifndef CONF_SERCOM_0_I2CM_SEXTTOEN +#define CONF_SERCOM_0_I2CM_SEXTTOEN 0 +#endif + +// SCL Low Time-Out (LOWTOUT) +// Enables SCL low time-out. If SCL is held low for 25ms-35ms, the master will release it's clock hold +// i2c_master_arch_lowtout +#ifndef CONF_SERCOM_0_I2CM_LOWTOUT +#define CONF_SERCOM_0_I2CM_LOWTOUT 1 +#endif + +// Inactive Time-Out (INACTOUT) +// <0x0=>Disabled +// <0x1=>5-6 SCL cycle time-out(50-60us) +// <0x2=>10-11 SCL cycle time-out(100-110us) +// <0x3=>20-21 SCL cycle time-out(200-210us) +// Defines if inactivity time-out should be enabled, and how long the time-out should be +// i2c_master_arch_inactout +#ifndef CONF_SERCOM_0_I2CM_INACTOUT +#define CONF_SERCOM_0_I2CM_INACTOUT 0x3 +#endif + +// SDA Hold Time (SDAHOLD) +// <0=>Disabled +// <1=>50-100ns hold time +// <2=>300-600ns hold time +// <3=>400-800ns hold time +// Defines the SDA hold time with respect to the negative edge of SCL +// i2c_master_arch_sdahold +#ifndef CONF_SERCOM_0_I2CM_SDAHOLD +#define CONF_SERCOM_0_I2CM_SDAHOLD 0x2 +#endif + +// Run in stand-by +// Determine if the module shall run in standby sleep mode +// i2c_master_arch_runstdby +#ifndef CONF_SERCOM_0_I2CM_RUNSTDBY +#define CONF_SERCOM_0_I2CM_RUNSTDBY 0 +#endif + +// Debug Stop Mode +// Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// i2c_master_arch_dbgstop +#ifndef CONF_SERCOM_0_I2CM_DEBUG_STOP_MODE +#define CONF_SERCOM_0_I2CM_DEBUG_STOP_MODE 0 +#endif + +// + +#ifndef CONF_SERCOM_0_I2CM_SPEED +#define CONF_SERCOM_0_I2CM_SPEED 0x00 // Speed: Standard/Fast mode +#endif +#if CONF_SERCOM_0_I2CM_TRISE < 215 || CONF_SERCOM_0_I2CM_TRISE > 300 +#warning Bad I2C Rise time for Standard/Fast mode, reset to 215ns +#undef CONF_SERCOM_0_I2CM_TRISE +#define CONF_SERCOM_0_I2CM_TRISE 215U +#endif + +// gclk_freq - (i2c_scl_freq * 10) - (gclk_freq * i2c_scl_freq * Trise) +// BAUD + BAUDLOW = -------------------------------------------------------------------- +// i2c_scl_freq +// BAUD: register value low [7:0] +// BAUDLOW: register value high [15:8], only used for odd BAUD + BAUDLOW +#define CONF_SERCOM_0_I2CM_BAUD_BAUDLOW \ + (((CONF_GCLK_SERCOM0_CORE_FREQUENCY - (CONF_SERCOM_0_I2CM_BAUD * 10U) \ + - (CONF_SERCOM_0_I2CM_TRISE * (CONF_SERCOM_0_I2CM_BAUD / 100U) * (CONF_GCLK_SERCOM0_CORE_FREQUENCY / 10000U) \ + / 1000U)) \ + * 10U \ + + 5U) \ + / (CONF_SERCOM_0_I2CM_BAUD * 10U)) +#ifndef CONF_SERCOM_0_I2CM_BAUD_RATE +#if CONF_SERCOM_0_I2CM_BAUD_BAUDLOW > (0xFF * 2) +#warning Requested I2C baudrate too low, please check +#define CONF_SERCOM_0_I2CM_BAUD_RATE 0xFF +#elif CONF_SERCOM_0_I2CM_BAUD_BAUDLOW <= 1 +#warning Requested I2C baudrate too high, please check +#define CONF_SERCOM_0_I2CM_BAUD_RATE 1 +#else +#define CONF_SERCOM_0_I2CM_BAUD_RATE \ + ((CONF_SERCOM_0_I2CM_BAUD_BAUDLOW & 0x1) \ + ? (CONF_SERCOM_0_I2CM_BAUD_BAUDLOW / 2) + ((CONF_SERCOM_0_I2CM_BAUD_BAUDLOW / 2 + 1) << 8) \ + : (CONF_SERCOM_0_I2CM_BAUD_BAUDLOW / 2)) +#endif +#endif + +#include + #ifndef CONF_SERCOM_4_USART_ENABLE #define CONF_SERCOM_4_USART_ENABLE 1 #endif @@ -69,7 +204,7 @@ // Advanced configuration // usart_advanced #ifndef CONF_SERCOM_4_USART_ADVANCED_CONFIG -#define CONF_SERCOM_4_USART_ADVANCED_CONFIG 0 +#define CONF_SERCOM_4_USART_ADVANCED_CONFIG 1 #endif // Run in stand-by diff --git a/bsp/microchip/samc21/bsp/config/peripheral_clk_config.h b/bsp/microchip/samc21/bsp/config/peripheral_clk_config.h index 94f49f8193..bb0552eba9 100644 --- a/bsp/microchip/samc21/bsp/config/peripheral_clk_config.h +++ b/bsp/microchip/samc21/bsp/config/peripheral_clk_config.h @@ -4,6 +4,38 @@ // <<< Use Configuration Wizard in Context Menu >>> +// ADC Clock Source +// adc_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Select the clock source for ADC. +#ifndef CONF_GCLK_ADC0_SRC +#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#endif + +/** + * \def CONF_GCLK_ADC0_FREQUENCY + * \brief ADC0's Clock frequency + */ +#ifndef CONF_GCLK_ADC0_FREQUENCY +#define CONF_GCLK_ADC0_FREQUENCY 40001536 +#endif + /** * \def CONF_CPU_FREQUENCY * \brief CPU's Clock frequency @@ -31,6 +63,70 @@ // Generic clock generator 7 +// Select the clock source for CORE. +#ifndef CONF_GCLK_SERCOM0_CORE_SRC +#define CONF_GCLK_SERCOM0_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#endif + +// Slow Clock Source +// slow_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Select the slow clock source. +#ifndef CONF_GCLK_SERCOM0_SLOW_SRC +#define CONF_GCLK_SERCOM0_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK1_Val +#endif + +/** + * \def CONF_GCLK_SERCOM0_CORE_FREQUENCY + * \brief SERCOM0's Core Clock frequency + */ +#ifndef CONF_GCLK_SERCOM0_CORE_FREQUENCY +#define CONF_GCLK_SERCOM0_CORE_FREQUENCY 40001536 +#endif + +/** + * \def CONF_GCLK_SERCOM0_SLOW_FREQUENCY + * \brief SERCOM0's Slow Clock frequency + */ +#ifndef CONF_GCLK_SERCOM0_SLOW_FREQUENCY +#define CONF_GCLK_SERCOM0_SLOW_FREQUENCY 4000000 +#endif + +// Core Clock Source +// core_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + // Select the clock source for CORE. #ifndef CONF_GCLK_SERCOM4_CORE_SRC #define CONF_GCLK_SERCOM4_CORE_SRC GCLK_PCHCTRL_GEN_GCLK0_Val diff --git a/bsp/microchip/samc21/bsp/driver_init.c b/bsp/microchip/samc21/bsp/driver_init.c index aba61963fe..fc5b3416b3 100644 --- a/bsp/microchip/samc21/bsp/driver_init.c +++ b/bsp/microchip/samc21/bsp/driver_init.c @@ -11,11 +11,43 @@ #include #include -struct can_async_descriptor CAN_0; +#include + +/*! The buffer size for USART */ +#define TARGET_IO_BUFFER_SIZE 16 + +struct usart_async_descriptor TARGET_IO; +struct can_async_descriptor CAN_0; + +static uint8_t TARGET_IO_buffer[TARGET_IO_BUFFER_SIZE]; + +struct adc_sync_descriptor ADC_0; struct flash_descriptor FLASH_0; -struct usart_sync_descriptor TARGET_IO; +struct i2c_m_sync_desc I2C_0; + +void ADC_0_PORT_init(void) +{ + + // Disable digital pin circuitry + gpio_set_pin_direction(PA10, GPIO_DIRECTION_OFF); + + gpio_set_pin_function(PA10, PINMUX_PA10B_ADC0_AIN10); +} + +void ADC_0_CLOCK_init(void) +{ + hri_mclk_set_APBCMASK_ADC0_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, CONF_GCLK_ADC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); +} + +void ADC_0_init(void) +{ + ADC_0_CLOCK_init(); + ADC_0_PORT_init(); + adc_sync_init(&ADC_0, ADC0, _adc_get_adc_sync()); +} void FLASH_0_CLOCK_init(void) { @@ -29,25 +61,79 @@ void FLASH_0_init(void) flash_init(&FLASH_0, NVMCTRL); } -void TARGET_IO_PORT_init(void) +void I2C_0_PORT_init(void) { - gpio_set_pin_function(PB10, PINMUX_PB10D_SERCOM4_PAD2); + gpio_set_pin_pull_mode(PA08, + // Pull configuration + // pad_pull_config + // Off + // Pull-up + // Pull-down + GPIO_PULL_OFF); + + gpio_set_pin_function(PA08, PINMUX_PA08C_SERCOM0_PAD0); + + gpio_set_pin_pull_mode(PA09, + // Pull configuration + // pad_pull_config + // Off + // Pull-up + // Pull-down + GPIO_PULL_OFF); + + gpio_set_pin_function(PA09, PINMUX_PA09C_SERCOM0_PAD1); +} - gpio_set_pin_function(PB11, PINMUX_PB11D_SERCOM4_PAD3); +void I2C_0_CLOCK_init(void) +{ + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_CORE, CONF_GCLK_SERCOM0_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM0_GCLK_ID_SLOW, CONF_GCLK_SERCOM0_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_mclk_set_APBCMASK_SERCOM0_bit(MCLK); +} + +void I2C_0_init(void) +{ + I2C_0_CLOCK_init(); + i2c_m_sync_init(&I2C_0, SERCOM0); + I2C_0_PORT_init(); } -void TARGET_IO_CLOCK_init(void) +/** + * \brief USART Clock initialization function + * + * Enables register interface and peripheral clock + */ +void TARGET_IO_CLOCK_init() { + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM4_GCLK_ID_CORE, CONF_GCLK_SERCOM4_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM4_GCLK_ID_SLOW, CONF_GCLK_SERCOM4_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); hri_mclk_set_APBCMASK_SERCOM4_bit(MCLK); } +/** + * \brief USART pinmux initialization function + * + * Set each required pin to USART functionality + */ +void TARGET_IO_PORT_init() +{ + + gpio_set_pin_function(PB10, PINMUX_PB10D_SERCOM4_PAD2); + + gpio_set_pin_function(PB11, PINMUX_PB11D_SERCOM4_PAD3); +} + +/** + * \brief USART initialization function + * + * Enables USART peripheral, clocks and initializes USART driver + */ void TARGET_IO_init(void) { TARGET_IO_CLOCK_init(); - usart_sync_init(&TARGET_IO, SERCOM4, (void *)NULL); + usart_async_init(&TARGET_IO, SERCOM4, TARGET_IO_buffer, TARGET_IO_BUFFER_SIZE, (void *)NULL); TARGET_IO_PORT_init(); } @@ -89,8 +175,11 @@ void system_init(void) gpio_set_pin_function(LED0, GPIO_PIN_FUNCTION_OFF); + ADC_0_init(); + FLASH_0_init(); + I2C_0_init(); TARGET_IO_init(); CAN_0_init(); } diff --git a/bsp/microchip/samc21/bsp/driver_init.h b/bsp/microchip/samc21/bsp/driver_init.h index e5e5ba5d1c..edd464fab5 100644 --- a/bsp/microchip/samc21/bsp/driver_init.h +++ b/bsp/microchip/samc21/bsp/driver_init.h @@ -21,19 +21,33 @@ extern "C" { #include #include +#include + #include -#include +#include +#include #include +extern struct adc_sync_descriptor ADC_0; + extern struct flash_descriptor FLASH_0; -extern struct usart_sync_descriptor TARGET_IO; -extern struct can_async_descriptor CAN_0; +extern struct i2c_m_sync_desc I2C_0; +extern struct usart_async_descriptor TARGET_IO; +extern struct can_async_descriptor CAN_0; + +void ADC_0_PORT_init(void); +void ADC_0_CLOCK_init(void); +void ADC_0_init(void); void FLASH_0_init(void); void FLASH_0_CLOCK_init(void); +void I2C_0_CLOCK_init(void); +void I2C_0_init(void); +void I2C_0_PORT_init(void); + void TARGET_IO_PORT_init(void); void TARGET_IO_CLOCK_init(void); void TARGET_IO_init(void); diff --git a/bsp/microchip/samc21/bsp/examples/driver_examples.c b/bsp/microchip/samc21/bsp/examples/driver_examples.c index bbce78ed06..e9a35ed6b1 100644 --- a/bsp/microchip/samc21/bsp/examples/driver_examples.c +++ b/bsp/microchip/samc21/bsp/examples/driver_examples.c @@ -10,6 +10,20 @@ #include "driver_init.h" #include "utils.h" +/** + * Example of using ADC_0 to generate waveform. + */ +void ADC_0_example(void) +{ + uint8_t buffer[2]; + + adc_sync_enable_channel(&ADC_0, 0); + + while (1) { + adc_sync_read_channel(&ADC_0, 0, buffer, 2); + } +} + static uint8_t src_data[128]; static uint8_t chk_data[128]; /** @@ -70,16 +84,43 @@ void RWW_FLASH_0_example(void) } } +void I2C_0_example(void) +{ + struct io_descriptor *I2C_0_io; + + i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io); + i2c_m_sync_enable(&I2C_0); + i2c_m_sync_set_slaveaddr(&I2C_0, 0x12, I2C_M_SEVEN); + io_write(I2C_0_io, (uint8_t *)"Hello World!", 12); +} + /** * Example of using TARGET_IO to write "Hello World" using the IO abstraction. + * + * Since the driver is asynchronous we need to use statically allocated memory for string + * because driver initiates transfer and then returns before the transmission is completed. + * + * Once transfer has been completed the tx_cb function will be called. */ + +static uint8_t example_TARGET_IO[12] = "Hello World!"; + +static void tx_cb_TARGET_IO(const struct usart_async_descriptor *const io_descr) +{ + /* Transfer completed */ +} + void TARGET_IO_example(void) { struct io_descriptor *io; - usart_sync_get_io_descriptor(&TARGET_IO, &io); - usart_sync_enable(&TARGET_IO); - io_write(io, (uint8_t *)"Hello World!", 12); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, tx_cb_TARGET_IO); + /*usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, rx_cb); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_ERROR_CB, err_cb);*/ + usart_async_get_io_descriptor(&TARGET_IO, &io); + usart_async_enable(&TARGET_IO); + + io_write(io, example_TARGET_IO, 12); } void CAN_0_tx_callback(struct can_async_descriptor *const descr) diff --git a/bsp/microchip/samc21/bsp/examples/driver_examples.h b/bsp/microchip/samc21/bsp/examples/driver_examples.h index fab317f6f0..6624e03d09 100644 --- a/bsp/microchip/samc21/bsp/examples/driver_examples.h +++ b/bsp/microchip/samc21/bsp/examples/driver_examples.h @@ -12,9 +12,13 @@ extern "C" { #endif +void ADC_0_example(void); + void FLASH_0_example(void); void RWW_FLASH_0_example(void); +void I2C_0_example(void); + void TARGET_IO_example(void); void CAN_0_example(void); diff --git a/bsp/microchip/samc21/bsp/hal/documentation/adc_sync.rst b/bsp/microchip/samc21/bsp/hal/documentation/adc_sync.rst new file mode 100644 index 0000000000..d189565ad8 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/documentation/adc_sync.rst @@ -0,0 +1,74 @@ +====================== +ADC Synchronous driver +====================== + +An ADC (Analog-to-Digital Converter) converts analog signals to digital values. +A reference signal with a known voltage level is quantified into equally +sized chunks, each representing a digital value from 0 to the highest number +possible with the bit resolution supported by the ADC. The input voltage +measured by the ADC is compared against these chunks and the chunk with the +closest voltage level defines the digital value that can be used to represent +the analog input voltage level. + +Usually an ADC can operate in either differential or single-ended mode. +In differential mode two signals (V+ and V-) are compared against each other +and the resulting digital value represents the relative voltage level between +V+ and V-. This means that if the input voltage level on V+ is lower than on +V- the digital value is negative, which also means that in differential +mode one bit is lost to the sign. In single-ended mode only V+ is compared +against the reference voltage, and the resulting digital value can only be +positive, but the full bit-range of the ADC can be used. + +Usually multiple resolutions are supported by the ADC, lower resolution can +reduce the conversion time, but lose accuracy. + +Some ADCs has a gain stage on the input lines which can be used to increase the +dynamic range. The default gain value is usually x1, which means that the +conversion range is from 0V to the reference voltage. +Applications can change the gain stage, to increase or reduce the conversion +range. + +The window mode allows the conversion result to be compared to a set of +predefined threshold values. Applications can use callback function to monitor +if the conversion result exceeds predefined threshold value. + +Usually multiple reference voltages are supported by the ADC, both internal and +external with difference voltage levels. The reference voltage have an impact +on the accuracy, and should be selected to cover the full range of the analog +input signal and never less than the expected maximum input voltage. + +There are two conversion modes supported by ADC, single shot and free running. +In single shot mode the ADC only make one conversion when triggered by the +application, in free running mode it continues to make conversion from it +is triggered until it is stopped by the application. When window monitoring, +the ADC should be set to free running mode. + +Features +-------- +* Initialization and de-initialization +* Support multiple Conversion Mode, Single or Free run +* Start ADC Conversion +* Read Conversion Result + +Applications +------------ +* Measurement of internal sensor. E.g., MCU internal temperature sensor value. +* Measurement of external sensor. E.g., Temperature, humidity sensor value. +* Sampling and measurement of a signal. E.g., sinusoidal wave, square wave. + +Dependencies +------------ +* ADC hardware + +Concurrency +----------- +N/A + +Limitations +----------- +N/A + +Knows issues and workarounds +---------------------------- +N/A + diff --git a/bsp/microchip/samc21/bsp/hal/documentation/i2c_master_sync.rst b/bsp/microchip/samc21/bsp/hal/documentation/i2c_master_sync.rst new file mode 100644 index 0000000000..77b4f6e9c4 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/documentation/i2c_master_sync.rst @@ -0,0 +1,87 @@ +============================= +I2C Master synchronous driver +============================= + +I2C (Inter-Integrated Circuit) is a two wire serial interface usually used +for on-board low-speed bi-directional communication between controllers and +peripherals. The master device is responsible for initiating and controlling +all transfers on the I2C bus. Only one master device can be active on the I2C +bus at the time, but the master role can be transferred between devices on the +same I2C bus. I2C uses only two bidirectional open-drain lines, usually +designated SDA (Serial Data Line) and SCL (Serial Clock Line), with pull up +resistors. + +The stop condition is automatically controlled by the driver if the I/O write and +read functions are used, but can be manually controlled by using the +i2c_m_sync_transfer function. + +Often a master accesses different information in the slave by accessing +different registers in the slave. This is done by first sending a message to +the target slave containing the register address, followed by a repeated start +condition (no stop condition between) ending with transferring register data. +This scheme is supported by the i2c_m_sync_cmd_write and i2c_m_sync_cmd_read +function, but limited to 8-bit register addresses. + +I2C Modes (standard mode/fastmode+/highspeed mode) can only be selected in +Atmel Start. If the SCL frequency (baudrate) has changed run-time, make sure to +stick within the SCL clock frequency range supported by the selected mode. +The requested SCL clock frequency is not validated by the +i2c_m_sync_set_baudrate function against the selected I2C mode. + +Features +-------- + + * I2C Master support + * Initialization and de-initialization + * Enabling and disabling + * Run-time bus speed configuration + * Write and read I2C messages + * Slave register access functions (limited to 8-bit address) + * Manual or automatic stop condition generation + * 10- and 7- bit addressing + * I2C Modes supported + +----------------------+-------------------+ + |* Standard/Fast mode | (SCL: 1 - 400kHz) | + +----------------------+-------------------+ + |* Fastmode+ | (SCL: 1 - 1000kHz)| + +----------------------+-------------------+ + |* Highspeed mode | (SCL: 1 - 3400kHz)| + +----------------------+-------------------+ + +Applications +------------ + +* Transfer data to and from one or multiple I2C slaves like I2C connected sensors, data storage or other I2C capable peripherals +* Data communication between micro controllers +* Controlling displays + +Dependencies +------------ + +* I2C Master capable hardware + +Concurrency +----------- + +N/A + +Limitations +----------- + +General +^^^^^^^ + + * System Managmenet Bus (SMBus) not supported. + * Power Management Bus (PMBus) not supported. + +Clock considerations +^^^^^^^^^^^^^^^^^^^^ + +The register value for the requested I2C speed is calculated and placed in the correct register, but not validated if it works correctly with the clock/prescaler settings used for the module. To validate the I2C speed setting use the formula found in the configuration file for the module. Selectable speed is automatically limited within the speed range defined by the I2C mode selected. + +Known issues and workarounds +---------------------------- + +N/A + + diff --git a/bsp/microchip/samc21/bsp/hal/documentation/usart_sync.rst b/bsp/microchip/samc21/bsp/hal/documentation/usart_async.rst similarity index 62% rename from bsp/microchip/samc21/bsp/hal/documentation/usart_sync.rst rename to bsp/microchip/samc21/bsp/hal/documentation/usart_async.rst index 15e4b13885..6bf4a23e92 100644 --- a/bsp/microchip/samc21/bsp/hal/documentation/usart_sync.rst +++ b/bsp/microchip/samc21/bsp/hal/documentation/usart_async.rst @@ -1,9 +1,20 @@ -The USART Synchronous Driver -============================ +The USART Asynchronous Driver +============================= The universal synchronous and asynchronous receiver and transmitter (USART) is usually used to transfer data from one device to the other. +The USART driver use a ring buffer to store received data. When the USART +raise the data received interrupt, this data will be stored in the ring buffer +at the next free location. When the ring buffer is full, the next reception +will overwrite the oldest data stored in the ring buffer. There is one +USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro +is called SERCOM0_USART_BUFFER_SIZE. + +On the other hand, when sending data over USART, the data is not copied to an +internal buffer, but the data buffer supplied by the user is used. The callback +will only be generated at the end of the buffer and not for each byte. + User can set action for flow control pins by function usart_set_flow_control, if the flow control is enabled. All the available states are defined in union usart_flow_control_state. @@ -24,6 +35,8 @@ Features * Data order * Flow control * Data transfer: transmission, reception +* Notifications about transfer done or error case via callbacks +* Status information with busy state and transfer count Applications ------------ @@ -34,7 +47,8 @@ between devices. Dependencies ------------ -USART capable hardware. +USART capable hardware, with interrupt on each character is sent or +received. Concurrency ----------- diff --git a/bsp/microchip/samc21/bsp/hal/include/hal_adc_sync.h b/bsp/microchip/samc21/bsp/hal/include/hal_adc_sync.h new file mode 100644 index 0000000000..1b66e3df7c --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/include/hal_adc_sync.h @@ -0,0 +1,277 @@ +/** + * \file + * + * \brief ADC functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_ADC_SYNC_H_INCLUDED +#define _HAL_ADC_SYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_adc_sync + * + * @{ + */ + +/** + * \brief ADC descriptor + * + * The ADC descriptor forward declaration. + */ +struct adc_sync_descriptor; + +/** + * \brief ADC descriptor + */ +struct adc_sync_descriptor { + /** ADC device */ + struct _adc_sync_device device; +}; + +/** + * \brief Initialize ADC + * + * This function initializes the given ADC descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[out] descr An ADC descriptor to initialize + * \param[in] hw The pointer to hardware instance + * \param[in] func The pointer to a set of functions pointers + * + * \return Initialization status. + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func); + +/** + * \brief Deinitialize ADC + * + * This function deinitializes the given ADC descriptor. + * It checks if the given hardware is initialized and if the given hardware is + * permitted to be deinitialized. + * + * \param[in] descr An ADC descriptor to deinitialize + * + * \return De-initialization status. + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr); + +/** + * \brief Enable ADC + * + * Use this function to set the ADC peripheral to enabled state. + * + * \param[in] descr Pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return Operation status + * + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Disable ADC + * + * Use this function to set the ADC peripheral to disabled state. + * + * \param[in] descr Pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return Operation status + * + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Read data from ADC + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] buf A buffer to read data to + * \param[in] length The size of a buffer + * + * \return The number of bytes read. + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length); + +/** + * \brief Set ADC reference source + * + * This function sets ADC reference source. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] reference A reference source to set + * + * \return Status of the ADC reference source setting. + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference); + +/** + * \brief Set ADC resolution + * + * This function sets ADC resolution. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] resolution A resolution to set + * + * \return Status of the ADC resolution setting. + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * This function sets ADC positive and negative input sources. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + * + * \return Status of the ADC channels setting. + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set ADC conversion mode + * + * This function sets ADC conversion mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] mode A conversion mode to set + * + * \return Status of the ADC conversion mode setting. + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode); + +/** + * \brief Set ADC differential mode + * + * This function sets ADC differential mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + * + * \return Status of the ADC differential mode setting. + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set ADC channel gain + * + * This function sets ADC channel gain. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] gain A gain to set + * + * \return Status of the ADC gain setting. + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, + const adc_gain_t gain); + +/** + * \brief Set ADC window mode + * + * This function sets ADC window mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] mode A window mode to set + * + * \return Status of the ADC window mode setting. + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode); + +/** + * \brief Set ADC thresholds + * + * This function sets ADC positive and negative thresholds. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] low_threshold A lower thresholds to set + * \param[in] up_threshold An upper thresholds to set + * + * \return Status of the ADC thresholds setting. + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * This function retrieves ADC threshold state. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[out] state The threshold state + * + * \return The state of ADC thresholds state retrieving. + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, + adc_threshold_status_t *const state); + +/** + * \brief Check if conversion is complete + * + * This function checks if the ADC has finished the conversion. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return The status of ADC conversion completion checking. + * \retval 1 The conversion is complete + * \retval 0 The conversion is not complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t adc_sync_get_version(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* _HAL_ADC_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/include/hal_i2c_m_sync.h b/bsp/microchip/samc21/bsp/hal/include/hal_i2c_m_sync.h new file mode 100644 index 0000000000..24afd63933 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/include/hal_i2c_m_sync.h @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief Sync I2C Hardware Abstraction Layer(HAL) declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_I2C_M_SYNC_H_INCLUDED +#define _HAL_I2C_M_SYNC_H_INCLUDED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_i2c_master_sync + * + * @{ + */ + +#define I2C_M_MAX_RETRY 1 + +/** + * \brief I2C descriptor structure, embed i2c_device & i2c_interface + */ +struct i2c_m_sync_desc { + struct _i2c_m_sync_device device; + struct io_descriptor io; + uint16_t slave_addr; +}; + +/** + * \brief Initialize synchronous I2C interface + * + * This function initializes the given I/O descriptor to be used as a + * synchronous I2C interface descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] hw The pointer to hardware instance + * + * \return Initialization status. + * \retval -1 The passed parameters were invalid or the interface is already initialized + * \retval 0 The initialization is completed successfully + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw); + +/** + * \brief Deinitialize I2C interface + * + * This function deinitializes the given I/O descriptor. + * It checks if the given hardware is initialized and if the given hardware is permitted to be deinitialized. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Uninitialization status. + * \retval -1 The passed parameters were invalid or the interface is already deinitialized + * \retval 0 The de-initialization is completed successfully + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c); + +/** + * \brief Set the slave device address + * + * This function sets the next transfer target slave I2C device address. + * It takes no effect to any already started access. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] addr The slave address to access + * \param[in] addr_len The slave address length, can be I2C_M_TEN or I2C_M_SEVEN + * + * \return Masked slave address. The mask is a maximum 10-bit address, and 10th + * bit is set if a 10-bit address is used + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len); + +/** + * \brief Set baudrate + * + * This function sets the I2C device to the specified baudrate. + * It only takes effect when the hardware is disabled. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] clkrate Unused parameter. Should always be 0 + * \param[in] baudrate The baudrate value set to master + * + * \return Whether successfully set the baudrate + * \retval -1 The passed parameters were invalid or the device is already enabled + * \retval 0 The baudrate set is completed successfully + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate); + +/** + * \brief Sync version of enable hardware + * + * This function enables the I2C device, and then waits for this enabling operation to be done + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Whether successfully enable the device + * \retval -1 The passed parameters were invalid or the device enable failed + * \retval 0 The hardware enabling is completed successfully + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c); + +/** + * \brief Sync version of disable hardware + * + * This function disables the I2C device and then waits for this disabling operation to be done + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Whether successfully disable the device + * \retval -1 The passed parameters were invalid or the device disable failed + * \retval 0 The hardware disabling is completed successfully + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c); + +/** + * \brief Sync version of write command to I2C slave + * + * This function will write the value to a specified register in the I2C slave device and + * then wait for this operation to be done. + * + * The sequence of this routine is + * sta->address(write)->ack->reg address->ack->resta->address(write)->ack->reg value->nack->stt + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] reg The internal address/register of the I2C slave device + * \param[in] buffer The buffer holding data to write to the I2C slave device + * \param[in] length The length (in bytes) to write to the I2C slave device + * + * \return Whether successfully write to the device + * \retval <0 The passed parameters were invalid or write fail + * \retval 0 Writing to register is completed successfully + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length); + +/** + * \brief Sync version of read register value from I2C slave + * + * This function will read a byte value from a specified register in the I2C slave device and + * then wait for this operation to be done. + * + * The sequence of this routine is + * sta->address(write)->ack->reg address->ack->resta->address(read)->ack->reg value->nack->stt + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] reg The internal address/register of the I2C slave device + * \param[in] buffer The buffer to hold the read data from the I2C slave device + * \param[in] length The length (in bytes) to read from the I2C slave device + * + * \return Whether successfully read from the device + * \retval <0 The passed parameters were invalid or read fail + * \retval 0 Reading from register is completed successfully + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length); + +/** + * \brief Sync version of transfer message to/from the I2C slave + * + * This function will transfer a message between the I2C slave and the master. This function will wait for the operation + * to be done. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] msg An i2c_m_msg struct + * + * \return The status of the operation + * \retval 0 Operation completed successfully + * \retval <0 Operation failed + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg); + +/** + * \brief Sync version of send stop condition on the i2c bus + * + * This function will create a stop condition on the i2c bus to release the bus + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return The status of the operation + * \retval 0 Operation completed successfully + * \retval <0 Operation failed + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c); + +/** + * \brief Return I/O descriptor for this I2C instance + * + * This function will return a I/O instance for this I2C driver instance + * + * \param[in] i2c_m_sync_desc An I2C descriptor, which is used to communicate through I2C + * \param[in] io_descriptor A pointer to an I/O descriptor pointer type + * + * \return Error code + * \retval 0 No error detected + * \retval <0 Error code + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t i2c_m_sync_get_version(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/microchip/samc21/bsp/hal/include/hal_usart_async.h b/bsp/microchip/samc21/bsp/hal/include/hal_usart_async.h new file mode 100644 index 0000000000..3a6de391db --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/include/hal_usart_async.h @@ -0,0 +1,339 @@ +/** + * \file + * + * \brief USART related functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_USART_ASYNC_H_INCLUDED +#define _HAL_USART_ASYNC_H_INCLUDED + +#include "hal_io.h" +#include +#include + +/** + * \addtogroup doc_driver_hal_usart_async + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief USART descriptor + * + * The USART descriptor forward declaration. + */ +struct usart_async_descriptor; + +/** + * \brief USART callback type + */ +typedef void (*usart_cb_t)(const struct usart_async_descriptor *const descr); + +/** + * \brief USART callback types + */ +enum usart_async_callback_type { USART_ASYNC_RXC_CB, USART_ASYNC_TXC_CB, USART_ASYNC_ERROR_CB }; + +/** + * \brief USART callbacks + */ +struct usart_async_callbacks { + usart_cb_t tx_done; + usart_cb_t rx_done; + usart_cb_t error; +}; + +/** \brief USART status + * Status descriptor holds the current status of transfer. + */ +struct usart_async_status { + /** Status flags */ + uint32_t flags; + /** Number of characters transmitted */ + uint16_t txcnt; + /** Number of characters receviced */ + uint16_t rxcnt; +}; + +/** + * \brief Asynchronous USART descriptor structure + */ +struct usart_async_descriptor { + struct io_descriptor io; + struct _usart_async_device device; + struct usart_async_callbacks usart_cb; + uint32_t stat; + + struct ringbuffer rx; + uint16_t tx_por; + uint8_t * tx_buffer; + uint16_t tx_buffer_length; +}; + +/** USART write busy */ +#define USART_ASYNC_STATUS_BUSY 0x0001 + +/** + * \brief Initialize USART interface + * + * This function initializes the given I/O descriptor to be used as USART + * interface descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[out] descr A USART descriptor which is used to communicate via the USART + * \param[in] hw The pointer to the hardware instance + * \param[in] rx_buffer An RX buffer + * \param[in] rx_buffer_length The length of the buffer above + * \param[in] func The pointer to a set of function pointers + * + * \return Initialization status. + * \retval -1 Passed parameters were invalid or the interface is already + * initialized + * \retval 0 The initialization is completed successfully + */ +int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *const rx_buffer, + const uint16_t rx_buffer_length, void *const func); + +/** + * \brief Deinitialize USART interface + * + * This function deinitializes the given I/O descriptor. + * It checks if the given hardware is initialized and if the given hardware + * is permitted to be deinitialized. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return De-initialization status. + */ +int32_t usart_async_deinit(struct usart_async_descriptor *const descr); + +/** + * \brief Enable USART interface + * + * Enables the USART interface + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return Enabling status. + */ +int32_t usart_async_enable(struct usart_async_descriptor *const descr); + +/** + * \brief Disable USART interface + * + * Disables the USART interface + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return Disabling status. + */ +int32_t usart_async_disable(struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve I/O descriptor + * + * This function retrieves the I/O descriptor of the given USART descriptor. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] io An I/O descriptor to retrieve + * + * \return The status of I/O descriptor retrieving. + */ +int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io); + +/** + * \brief Register USART callback + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] type Callback type + * \param[in] cb A callback function + * + * \return The status of callback assignment. + * \retval -1 Passed parameters were invalid or the interface is not initialized + * \retval 0 A callback is registered successfully + */ +int32_t usart_async_register_callback(struct usart_async_descriptor *const descr, + const enum usart_async_callback_type type, usart_cb_t cb); + +/** + * \brief Specify action for flow control pins + * + * This function sets action (or state) for flow control pins if + * the flow control is enabled. + * It sets state of flow control pins only if automatic support of + * the flow control is not supported by the hardware. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] state A state to set the flow control pins + * + * \return The status of flow control action setup. + */ +int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr, + const union usart_flow_control_state state); + +/** + * \brief Set USART baud rate + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] baud_rate A baud rate to set + * + * \return The status of baud rate setting. + */ +int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate); + +/** + * \brief Set USART data order + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] data_order A data order to set + * + * \return The status of data order setting. + */ +int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order); + +/** + * \brief Set USART mode + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] mode A mode to set + * + * \return The status of mode setting. + */ +int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode); + +/** + * \brief Set USART parity + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] parity A parity to set + * + * \return The status of parity setting. + */ +int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity); + +/** + * \brief Set USART stop bits + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] stop_bits Stop bits to set + * + * \return The status of stop bits setting. + */ +int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits); + +/** + * \brief Set USART character size + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] size A character size to set + * + * \return The status of character size setting. + */ +int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, + const enum usart_character_size size); + +/** + * \brief Retrieve the state of flow control pins + * + * This function retrieves the flow control pins + * if the flow control is enabled. + * + * The function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case + * if the flow control is done by the hardware + * and the pins state cannot be read out. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] state The state of flow control pins + * + * \return The status of flow control state reading. + */ +int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr, + union usart_flow_control_state *const state); + +/** + * \brief Check if the USART transmitter is empty + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return The status of USART TX empty checking. + * \retval 0 The USART transmitter is not empty + * \retval 1 The USART transmitter is empty + */ +int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr); + +/** + * \brief Check if the USART receiver is not empty + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return The status of the USART RX empty checking. + * \retval 1 The USART receiver is not empty + * \retval 0 The USART receiver is empty + */ +int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve the current interface status + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] status The state of USART + * + * \return The status of USART status retrieving. + */ +int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status); + +/** + * \brief flush USART ringbuf + * + * This function flush USART RX ringbuf. + * + * \param[in] descr The pointer to USART descriptor + * + * \return ERR_NONE + */ +int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t usart_async_get_version(void); + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HAL_USART_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/include/hal_usart_sync.h b/bsp/microchip/samc21/bsp/hal/include/hal_usart_sync.h deleted file mode 100644 index 1ef22fc63f..0000000000 --- a/bsp/microchip/samc21/bsp/hal/include/hal_usart_sync.h +++ /dev/null @@ -1,247 +0,0 @@ -/** - * \file - * - * \brief USART related functionality declaration. - * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#ifndef _HAL_SYNC_USART_H_INCLUDED -#define _HAL_SYNC_USART_H_INCLUDED - -#include "hal_io.h" -#include - -/** - * \addtogroup doc_driver_hal_usart_sync - * - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Synchronous USART descriptor - */ -struct usart_sync_descriptor { - struct io_descriptor io; - struct _usart_sync_device device; -}; - -/** - * \brief Initialize USART interface - * - * This function initializes the given I/O descriptor to be used - * as USART interface descriptor. - * It checks if the given hardware is not initialized and - * if the given hardware is permitted to be initialized. - * - * \param[out] descr A USART descriptor which is used to communicate via USART - * \param[in] hw The pointer to hardware instance - * \param[in] func The pointer to as set of functions pointers - * - * \return Initialization status. - */ -int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func); - -/** - * \brief Deinitialize USART interface - * - * This function deinitializes the given I/O descriptor. - * It checks if the given hardware is initialized and - * if the given hardware is permitted to be deinitialized. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return De-initialization status. - */ -int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr); - -/** - * \brief Enable USART interface - * - * Enables the USART interface - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return Enabling status. - */ -int32_t usart_sync_enable(struct usart_sync_descriptor *const descr); - -/** - * \brief Disable USART interface - * - * Disables the USART interface - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return Disabling status. - */ -int32_t usart_sync_disable(struct usart_sync_descriptor *const descr); - -/** - * \brief Retrieve I/O descriptor - * - * This function retrieves the I/O descriptor of the given USART descriptor. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[out] io An I/O descriptor to retrieve - * - * \return The status of the I/O descriptor retrieving. - */ -int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io); - -/** - * \brief Specify action for flow control pins - * - * This function sets the action (or state) for the flow control pins - * if the flow control is enabled. - * It sets the state of flow control pins only if the automatic support of - * the flow control is not supported by the hardware. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] state A state to set the flow control pins - * - * \return The status of flow control action setup. - */ -int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr, - const union usart_flow_control_state state); - -/** - * \brief Set USART baud rate - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] baud_rate A baud rate to set - * - * \return The status of baud rate setting. - */ -int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate); - -/** - * \brief Set USART data order - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] data_order A data order to set - * - * \return The status of data order setting. - */ -int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order); - -/** - * \brief Set USART mode - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] mode A mode to set - * - * \return The status of mode setting. - */ -int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode); - -/** - * \brief Set USART parity - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] parity A parity to set - * - * \return The status of parity setting. - */ -int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity); - -/** - * \brief Set USART stop bits - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] stop_bits Stop bits to set - * - * \return The status of stop bits setting. - */ -int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits); - -/** - * \brief Set USART character size - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] size A character size to set - * - * \return The status of character size setting. - */ -int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size); - -/** - * \brief Retrieve the state of flow control pins - * - * This function retrieves the of flow control pins - * if the flow control is enabled. - * Function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case - * if the flow control is done by the hardware - * and the pins state cannot be read out. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[out] state The state of flow control pins - * - * \return The status of flow control state reading. - */ -int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr, - union usart_flow_control_state *const state); - -/** - * \brief Check if the USART transmitter is empty - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return The status of USART TX empty checking. - * \retval 0 The USART transmitter is not empty - * \retval 1 The USART transmitter is empty - */ -int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr); - -/** - * \brief Check if the USART receiver is not empty - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return The status of USART RX empty checking. - * \retval 1 The USART receiver is not empty - * \retval 0 The USART receiver is empty - */ -int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr); - -/** - * \brief Retrieve the current driver version - * - * \return Current driver version. - */ -uint32_t usart_sync_get_version(void); - -#ifdef __cplusplus -} -#endif -/**@}*/ -#endif /* _HAL_SYNC_USART_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/include/hpl_adc_async.h b/bsp/microchip/samc21/bsp/hal/include/hpl_adc_async.h new file mode 100644 index 0000000000..1aa4162409 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/include/hpl_adc_async.h @@ -0,0 +1,264 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_ASYNC_H_INCLUDED +#define _HPL_ADC_ASYNC_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_async_adc_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include "hpl_adc_sync.h" +#include "hpl_irq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC device structure + * + * The ADC device structure forward declaration. + */ +struct _adc_async_device; + +/** + * \brief ADC callback types + */ +enum _adc_async_callback_type { ADC_ASYNC_DEVICE_CONVERT_CB, ADC_ASYNC_DEVICE_MONITOR_CB, ADC_ASYNC_DEVICE_ERROR_CB }; + +/** + * \brief ADC interrupt callbacks + */ +struct _adc_async_callbacks { + void (*window_cb)(struct _adc_async_device *device, const uint8_t channel); + void (*error_cb)(struct _adc_async_device *device, const uint8_t channel); +}; + +/** + * \brief ADC channel interrupt callbacks + */ +struct _adc_async_ch_callbacks { + void (*convert_done)(struct _adc_async_device *device, const uint8_t channel, const uint16_t data); +}; + +/** + * \brief ADC descriptor device structure + */ +struct _adc_async_device { + struct _adc_async_callbacks adc_async_cb; + struct _adc_async_ch_callbacks adc_async_ch_cb; + struct _irq_descriptor irq; + void * hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_async_deinit(struct _adc_async_device *const device); + +/** + * \brief Enable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_async_convert(struct _adc_async_device *const device); + +/** + * \brief Retrieve the conversion result + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * The result value + */ +uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set lower threshold + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower threshold to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state); + +/** + * \brief Enable/disable ADC channel interrupt + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] type The type of interrupt to disable/enable if applicable + * \param[in] state Enable or disable + */ +void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel, + const enum _adc_async_callback_type type, const bool state); + +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/include/hpl_adc_dma.h b/bsp/microchip/samc21/bsp/hal/include/hpl_adc_dma.h new file mode 100644 index 0000000000..bb3a054106 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/include/hpl_adc_dma.h @@ -0,0 +1,243 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_DMA_H_INCLUDED +#define _HPL_ADC_DMA_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_dma_adc_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC device structure + * + * The ADC device structure forward declaration. + */ +struct _adc_dma_device; + +/** + * \brief ADC callback types + */ +enum _adc_dma_callback_type { ADC_DMA_DEVICE_COMPLETE_CB, ADC_DMA_DEVICE_ERROR_CB }; + +/** + * \brief ADC interrupt callbacks + */ +struct _adc_dma_callbacks { + void (*complete)(struct _adc_dma_device *device, const uint16_t data); + void (*error)(struct _adc_dma_device *device); +}; + +/** + * \brief ADC descriptor device structure + */ +struct _adc_dma_device { + struct _adc_dma_callbacks adc_dma_cb; + struct _irq_descriptor irq; + void * hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_dma_init(struct _adc_dma_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_dma_deinit(struct _adc_dma_device *const device); + +/** + * \brief Enable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_dma_enable_channel(struct _adc_dma_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_dma_disable_channel(struct _adc_dma_device *const device, const uint8_t channel); + +/** + * \brief Return address of ADC DMA source + * + * \param[in] device The pointer to ADC device instance + * + * \return ADC DMA source address + */ +uint32_t _adc_get_source_for_dma(struct _adc_dma_device *const device); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_dma_get_data_size(const struct _adc_dma_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_dma_is_conversion_done(const struct _adc_dma_device *const device); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_dma_convert(struct _adc_dma_device *const device); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_dma_set_reference_source(struct _adc_dma_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_dma_set_resolution(struct _adc_dma_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_dma_set_inputs(struct _adc_dma_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_dma_set_conversion_mode(struct _adc_dma_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_dma_set_channel_differential_mode(struct _adc_dma_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_dma_set_channel_gain(struct _adc_dma_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_dma_set_window_mode(struct _adc_dma_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set thresholds + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower thresholds to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_dma_set_thresholds(struct _adc_dma_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_dma_get_threshold_state(const struct _adc_dma_device *const device, adc_threshold_status_t *const state); + +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_DMA_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/include/hpl_adc_sync.h b/bsp/microchip/samc21/bsp/hal/include/hpl_adc_sync.h new file mode 100644 index 0000000000..3bfbc61d9c --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/include/hpl_adc_sync.h @@ -0,0 +1,271 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_SYNC_H_INCLUDED +#define _HPL_ADC_SYNC_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_adc_sync_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include "compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC reference source + */ +typedef uint8_t adc_reference_t; + +/** + * \brief ADC resolution + */ +typedef uint8_t adc_resolution_t; + +/** + * \brief ADC positive input for channel + */ +typedef uint8_t adc_pos_input_t; + +/** + * \brief ADC negative input for channel + */ +typedef uint8_t adc_neg_input_t; + +/** + * \brief ADC threshold + */ +typedef uint16_t adc_threshold_t; + +/** + * \brief ADC gain + */ +typedef uint8_t adc_gain_t; + +/** + * \brief ADC conversion mode + */ +enum adc_conversion_mode { ADC_CONVERSION_MODE_SINGLE_CONVERSION = 0, ADC_CONVERSION_MODE_FREERUN }; + +/** + * \brief ADC differential mode + */ +enum adc_differential_mode { ADC_DIFFERENTIAL_MODE_SINGLE_ENDED = 0, ADC_DIFFERENTIAL_MODE_DIFFERENTIAL }; + +/** + * \brief ADC window mode + */ +typedef uint8_t adc_window_mode_t; + +/** + * \brief ADC threshold status + */ +typedef bool adc_threshold_status_t; + +/** + * \brief ADC sync descriptor device structure + */ +struct _adc_sync_device { + void *hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_sync_deinit(struct _adc_sync_device *const device); + +/** + * \brief Enable ADC + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_sync_convert(struct _adc_sync_device *const device); + +/** + * \brief Retrieve the conversion result + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The result value of channel + */ +uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set threshold + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower threshold to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state); +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/src/hal_adc_sync.c b/bsp/microchip/samc21/bsp/hal/src/hal_adc_sync.c new file mode 100644 index 0000000000..33e0d92976 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/src/hal_adc_sync.c @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief ADC functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +/** + * \brief Indicates HAL being compiled. Must be defined before including. + */ +#define _COMPILING_HAL + +#include "hal_adc_sync.h" +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Maximum amount of ADC interface instances + */ +#define MAX_ADC_AMOUNT ADC_INST_NUM + +/** + * \brief Initialize ADC + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func) +{ + ASSERT(descr && hw); + + return _adc_sync_init(&descr->device, hw); +} + +/** + * \brief Deinitialize ADC + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr) +{ + ASSERT(descr); + _adc_sync_deinit(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Enable ADC + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_enable_channel(&descr->device, channel); + + return ERR_NONE; +} + +/** + * \brief Disable ADC + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_disable_channel(&descr->device, channel); + return ERR_NONE; +} + +/* + * \brief Read data from ADC + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length) +{ + uint8_t data_size; + uint16_t offset = 0; + + ASSERT(descr && buffer && length); + data_size = _adc_sync_get_data_size(&descr->device); + ASSERT(!(length % data_size)); + + do { + uint16_t result; + _adc_sync_convert(&descr->device); + + while (!_adc_sync_is_channel_conversion_done(&descr->device, channel)) + ; + + result = _adc_sync_read_channel_data(&descr->device, channel); + buffer[offset] = result; + if (1 < data_size) { + buffer[offset + 1] = result >> 8; + } + offset += data_size; + } while (offset < length); + + return offset; +} + +/** + * \brief Set ADC reference source + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference) +{ + ASSERT(descr); + _adc_sync_set_reference_source(&descr->device, reference); + + return ERR_NONE; +} + +/** + * \brief Set ADC resolution + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution) +{ + ASSERT(descr); + _adc_sync_set_resolution(&descr->device, resolution); + + return ERR_NONE; +} + +/** + * \brief Set ADC input source of a channel + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_set_inputs(&descr->device, pos_input, neg_input, channel); + + return ERR_NONE; +} + +/** + * \brief Set ADC thresholds + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + ASSERT(descr); + _adc_sync_set_thresholds(&descr->device, low_threshold, up_threshold); + + return ERR_NONE; +} + +/** + * \brief Set ADC gain + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, const adc_gain_t gain) +{ + ASSERT(descr); + _adc_sync_set_channel_gain(&descr->device, channel, gain); + + return ERR_NONE; +} + +/** + * \brief Set ADC conversion mode + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode) +{ + ASSERT(descr); + _adc_sync_set_conversion_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC differential mode + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode) +{ + ASSERT(descr); + _adc_sync_set_channel_differential_mode(&descr->device, channel, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC window mode + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode) +{ + ASSERT(descr); + _adc_sync_set_window_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Retrieve threshold state + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, adc_threshold_status_t *const state) +{ + ASSERT(descr && state); + _adc_sync_get_threshold_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Check if conversion is complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + return _adc_sync_is_channel_conversion_done(&descr->device, channel); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t adc_sync_get_version(void) +{ + return DRIVER_VERSION; +} + +//@} diff --git a/bsp/microchip/samc21/bsp/hal/src/hal_i2c_m_sync.c b/bsp/microchip/samc21/bsp/hal/src/hal_i2c_m_sync.c new file mode 100644 index 0000000000..30821a27c3 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/src/hal_i2c_m_sync.c @@ -0,0 +1,258 @@ +/** + * \file + * + * \brief I/O I2C related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include +#include +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Sync version of I2C I/O read + */ +static int32_t i2c_m_sync_read(struct io_descriptor *io, uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of I2C I/O write + */ +static int32_t i2c_m_sync_write(struct io_descriptor *io, const uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP; + msg.buffer = (uint8_t *)buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of i2c initialize + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw) +{ + int32_t init_status; + ASSERT(i2c); + + init_status = _i2c_m_sync_init(&i2c->device, hw); + if (init_status) { + return init_status; + } + + /* Init I/O */ + i2c->io.read = i2c_m_sync_read; + i2c->io.write = i2c_m_sync_write; + + return ERR_NONE; +} + +/** + * \brief deinitialize + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c) +{ + int32_t status; + ASSERT(i2c); + + status = _i2c_m_sync_deinit(&i2c->device); + if (status) { + return status; + } + + i2c->io.read = NULL; + i2c->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c enable + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_enable(&i2c->device); +} + +/** + * \brief Sync version of i2c disable + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_disable(&i2c->device); +} + +/** + * \brief Sync version of i2c set slave address + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len) +{ + return i2c->slave_addr = (addr & 0x3ff) | (addr_len & I2C_M_TEN); +} + +/** + * \brief Sync version of i2c set baudrate + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate) +{ + return _i2c_m_sync_set_baudrate(&i2c->device, clkrate, baudrate); +} + +/** + * \brief Sync version of i2c write command + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c read command + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c transfer command + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg) +{ + return _i2c_m_sync_transfer(&i2c->device, msg); +} + +/** + * \brief Sync version of i2c send stop condition command + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c) +{ + return _i2c_m_sync_send_stop(&i2c->device); +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io) +{ + *io = &i2c->io; + return ERR_NONE; +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t i2c_m_sync_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/bsp/microchip/samc21/bsp/hal/src/hal_usart_async.c b/bsp/microchip/samc21/bsp/hal/src/hal_usart_async.c new file mode 100644 index 0000000000..f07b266124 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/src/hal_usart_async.c @@ -0,0 +1,420 @@ +/** + * \file + * + * \brief I/O USART related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_usart_async.h" +#include +#include +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length); +static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length); +static void usart_process_byte_sent(struct _usart_async_device *device); +static void usart_transmission_complete(struct _usart_async_device *device); +static void usart_error(struct _usart_async_device *device); +static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data); + +/** + * \brief Initialize usart interface + */ +int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *rx_buffer, + uint16_t rx_buffer_length, void *const func) +{ + int32_t init_status; + ASSERT(descr && hw && rx_buffer && rx_buffer_length); + + if (ERR_NONE != ringbuffer_init(&descr->rx, rx_buffer, rx_buffer_length)) { + return ERR_INVALID_ARG; + } + init_status = _usart_async_init(&descr->device, hw); + if (init_status) { + return init_status; + } + + descr->io.read = usart_async_read; + descr->io.write = usart_async_write; + + descr->device.usart_cb.tx_byte_sent = usart_process_byte_sent; + descr->device.usart_cb.rx_done_cb = usart_fill_rx_buffer; + descr->device.usart_cb.tx_done_cb = usart_transmission_complete; + descr->device.usart_cb.error_cb = usart_error; + + return ERR_NONE; +} + +/** + * \brief Deinitialize usart interface + */ +int32_t usart_async_deinit(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_deinit(&descr->device); + descr->io.read = NULL; + descr->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Enable usart interface + */ +int32_t usart_async_enable(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_enable(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Disable usart interface + */ +int32_t usart_async_disable(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_disable(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io) +{ + ASSERT(descr && io); + + *io = &descr->io; + return ERR_NONE; +} + +/** + * \brief Register usart callback + */ +int32_t usart_async_register_callback(struct usart_async_descriptor *const descr, + const enum usart_async_callback_type type, usart_cb_t cb) +{ + ASSERT(descr); + + switch (type) { + case USART_ASYNC_RXC_CB: + descr->usart_cb.rx_done = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_RX_DONE, NULL != cb); + break; + case USART_ASYNC_TXC_CB: + descr->usart_cb.tx_done = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_TX_DONE, NULL != cb); + break; + case USART_ASYNC_ERROR_CB: + descr->usart_cb.error = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_ERROR, NULL != cb); + break; + default: + return ERR_INVALID_ARG; + } + + return ERR_NONE; +} + +/** + * \brief Specify action for flow control pins + */ +int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr, + const union usart_flow_control_state state) +{ + ASSERT(descr); + _usart_async_set_flow_control_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Set usart baud rate + */ +int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate) +{ + ASSERT(descr); + _usart_async_set_baud_rate(&descr->device, baud_rate); + + return ERR_NONE; +} + +/** + * \brief Set usart data order + */ +int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order) +{ + ASSERT(descr); + _usart_async_set_data_order(&descr->device, data_order); + + return ERR_NONE; +} + +/** + * \brief Set usart mode + */ +int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode) +{ + ASSERT(descr); + _usart_async_set_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set usart parity + */ +int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity) +{ + ASSERT(descr); + _usart_async_set_parity(&descr->device, parity); + + return ERR_NONE; +} + +/** + * \brief Set usart stop bits + */ +int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits) +{ + ASSERT(descr); + _usart_async_set_stop_bits(&descr->device, stop_bits); + + return ERR_NONE; +} + +/** + * \brief Set usart character size + */ +int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, const enum usart_character_size size) +{ + ASSERT(descr); + _usart_async_set_character_size(&descr->device, size); + + return ERR_NONE; +} + +/** + * \brief Retrieve the state of flow control pins + */ +int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr, + union usart_flow_control_state *const state) +{ + ASSERT(descr && state); + *state = _usart_async_get_flow_control_state(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Check if the usart transmitter is empty + */ +int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + return _usart_async_is_byte_sent(&descr->device); +} + +/** + * \brief Check if the usart receiver is not empty + */ +int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + + return ringbuffer_num(&descr->rx) > 0; +} + +/** + * \brief Retrieve the current interface status + */ +int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status) +{ + ASSERT(descr); + + volatile uint32_t *tmp_stat = &(descr->stat); + volatile uint16_t *tmp_txcnt = &(descr->tx_por); + + if (status) { + status->flags = *tmp_stat; + status->txcnt = *tmp_txcnt; + status->rxcnt = ringbuffer_num(&descr->rx); + } + if (*tmp_stat & USART_ASYNC_STATUS_BUSY) { + return ERR_BUSY; + } + + return ERR_NONE; +} + +/** + * \brief flush usart rx ringbuf + */ +int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + + return ringbuffer_flush(&descr->rx); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t usart_async_get_version(void) +{ + return DRIVER_VERSION; +} + +/* + * \internal Write the given data to usart interface + * + * \param[in] descr The pointer to an io descriptor + * \param[in] buf Data to write to usart + * \param[in] length The number of bytes to write + * + * \return The number of bytes written. + */ +static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io); + + ASSERT(descr && buf && length); + + if (descr->tx_por != descr->tx_buffer_length) { + return ERR_NO_RESOURCE; + } + descr->tx_buffer = (uint8_t *)buf; + descr->tx_buffer_length = length; + descr->tx_por = 0; + descr->stat = USART_ASYNC_STATUS_BUSY; + _usart_async_enable_byte_sent_irq(&descr->device); + + return (int32_t)length; +} + +/* + * \internal Read data from usart interface + * + * \param[in] descr The pointer to an io descriptor + * \param[in] buf A buffer to read data to + * \param[in] length The size of a buffer + * + * \return The number of bytes read. + */ +static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) +{ + uint16_t was_read = 0; + uint32_t num; + struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io); + + ASSERT(descr && buf && length); + + CRITICAL_SECTION_ENTER() + num = ringbuffer_num(&descr->rx); + CRITICAL_SECTION_LEAVE() + + while ((was_read < num) && (was_read < length)) { + ringbuffer_get(&descr->rx, &buf[was_read++]); + } + + return (int32_t)was_read; +} + +/** + * \brief Process "byte is sent" interrupt + * + * \param[in] device The pointer to device structure + */ +static void usart_process_byte_sent(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + if (descr->tx_por != descr->tx_buffer_length) { + _usart_async_write_byte(&descr->device, descr->tx_buffer[descr->tx_por++]); + _usart_async_enable_byte_sent_irq(&descr->device); + } else { + _usart_async_enable_tx_done_irq(&descr->device); + } +} + +/** + * \brief Process completion of data sending + * + * \param[in] device The pointer to device structure + */ +static void usart_transmission_complete(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + descr->stat = 0; + if (descr->usart_cb.tx_done) { + descr->usart_cb.tx_done(descr); + } +} + +/** + * \brief Process byte reception + * + * \param[in] device The pointer to device structure + * \param[in] data Data read + */ +static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + ringbuffer_put(&descr->rx, data); + + if (descr->usart_cb.rx_done) { + descr->usart_cb.rx_done(descr); + } +} + +/** + * \brief Process error interrupt + * + * \param[in] device The pointer to device structure + */ +static void usart_error(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + descr->stat = 0; + if (descr->usart_cb.error) { + descr->usart_cb.error(descr); + } +} + +//@} diff --git a/bsp/microchip/samc21/bsp/hal/src/hal_usart_sync.c b/bsp/microchip/samc21/bsp/hal/src/hal_usart_sync.c deleted file mode 100644 index ab99c1d166..0000000000 --- a/bsp/microchip/samc21/bsp/hal/src/hal_usart_sync.c +++ /dev/null @@ -1,276 +0,0 @@ -/** - * \file - * - * \brief I/O USART related functionality implementation. - * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#include "hal_usart_sync.h" -#include -#include - -/** - * \brief Driver version - */ -#define DRIVER_VERSION 0x00000001u - -static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length); -static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length); - -/** - * \brief Initialize usart interface - */ -int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func) -{ - int32_t init_status; - ASSERT(descr && hw); - init_status = _usart_sync_init(&descr->device, hw); - if (init_status) { - return init_status; - } - - descr->io.read = usart_sync_read; - descr->io.write = usart_sync_write; - - return ERR_NONE; -} - -/** - * \brief Uninitialize usart interface - */ -int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_deinit(&descr->device); - - descr->io.read = NULL; - descr->io.write = NULL; - - return ERR_NONE; -} - -/** - * \brief Enable usart interface - */ -int32_t usart_sync_enable(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_enable(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Disable usart interface - */ -int32_t usart_sync_disable(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_disable(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Retrieve I/O descriptor - */ -int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io) -{ - ASSERT(descr && io); - - *io = &descr->io; - return ERR_NONE; -} - -/** - * \brief Specify action for flow control pins - */ -int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr, - const union usart_flow_control_state state) -{ - ASSERT(descr); - _usart_sync_set_flow_control_state(&descr->device, state); - - return ERR_NONE; -} - -/** - * \brief Set usart baud rate - */ -int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate) -{ - ASSERT(descr); - _usart_sync_set_baud_rate(&descr->device, baud_rate); - - return ERR_NONE; -} - -/** - * \brief Set usart data order - */ -int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order) -{ - ASSERT(descr); - _usart_sync_set_data_order(&descr->device, data_order); - - return ERR_NONE; -} - -/** - * \brief Set usart mode - */ -int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode) -{ - ASSERT(descr); - _usart_sync_set_mode(&descr->device, mode); - - return ERR_NONE; -} - -/** - * \brief Set usart parity - */ -int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity) -{ - ASSERT(descr); - _usart_sync_set_parity(&descr->device, parity); - - return ERR_NONE; -} - -/** - * \brief Set usart stop bits - */ -int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits) -{ - ASSERT(descr); - _usart_sync_set_stop_bits(&descr->device, stop_bits); - - return ERR_NONE; -} - -/** - * \brief Set usart character size - */ -int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size) -{ - ASSERT(descr); - _usart_sync_set_character_size(&descr->device, size); - - return ERR_NONE; -} - -/** - * \brief Retrieve the state of flow control pins - */ -int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr, - union usart_flow_control_state *const state) -{ - ASSERT(descr && state); - *state = _usart_sync_get_flow_control_state(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Check if the usart transmitter is empty - */ -int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - return _usart_sync_is_ready_to_send(&descr->device); -} - -/** - * \brief Check if the usart receiver is not empty - */ -int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - return _usart_sync_is_byte_received(&descr->device); -} - -/** - * \brief Retrieve the current driver version - */ -uint32_t usart_sync_get_version(void) -{ - return DRIVER_VERSION; -} - -/* - * \internal Write the given data to usart interface - * - * \param[in] descr The pointer to an io descriptor - * \param[in] buf Data to write to usart - * \param[in] length The number of bytes to write - * - * \return The number of bytes written. - */ -static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) -{ - uint32_t offset = 0; - struct usart_sync_descriptor *descr = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io); - - ASSERT(io_descr && buf && length); - while (!_usart_sync_is_ready_to_send(&descr->device)) - ; - do { - _usart_sync_write_byte(&descr->device, buf[offset]); - while (!_usart_sync_is_ready_to_send(&descr->device)) - ; - } while (++offset < length); - while (!_usart_sync_is_transmit_done(&descr->device)) - ; - return (int32_t)offset; -} - -/* - * \internal Read data from usart interface - * - * \param[in] descr The pointer to an io descriptor - * \param[in] buf A buffer to read data to - * \param[in] length The size of a buffer - * - * \return The number of bytes read. - */ -static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) -{ - uint32_t offset = 0; - struct usart_sync_descriptor *descr = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io); - - ASSERT(io_descr && buf && length); - do { - while (!_usart_sync_is_byte_received(&descr->device)) - ; - buf[offset] = _usart_sync_read_byte(&descr->device); - } while (++offset < length); - - return (int32_t)offset; -} diff --git a/bsp/microchip/samc21/bsp/hal/utils/include/utils_ringbuffer.h b/bsp/microchip/samc21/bsp/hal/utils/include/utils_ringbuffer.h new file mode 100644 index 0000000000..401d557246 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/utils/include/utils_ringbuffer.h @@ -0,0 +1,116 @@ +/** + * \file + * + * \brief Ringbuffer declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#ifndef _UTILS_RINGBUFFER_H_INCLUDED +#define _UTILS_RINGBUFFER_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_utils_ringbuffer + * + * @{ + */ + +#include "compiler.h" +#include "utils_assert.h" + +/** + * \brief Ring buffer element type + */ +struct ringbuffer { + uint8_t *buf; /** Buffer base address */ + uint32_t size; /** Buffer size */ + uint32_t read_index; /** Buffer read index */ + uint32_t write_index; /** Buffer write index */ +}; + +/** + * \brief Ring buffer init + * + * \param[in] rb The pointer to a ring buffer structure instance + * \param[in] buf Space to store the data + * \param[in] size The buffer length, must be aligned with power of 2 + * + * \return ERR_NONE on success, or an error code on failure. + */ +int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size); + +/** + * \brief Get one byte from ring buffer, the user needs to handle the concurrent + * access on buffer via put/get/flush + * + * \param[in] rb The pointer to a ring buffer structure instance + * \param[in] data One byte space to store the read data + * + * \return ERR_NONE on success, or an error code on failure. + */ +int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data); + +/** + * \brief Put one byte to ring buffer, the user needs to handle the concurrent access + * on buffer via put/get/flush + * + * \param[in] rb The pointer to a ring buffer structure instance + * \param[in] data One byte data to be put into ring buffer + * + * \return ERR_NONE on success, or an error code on failure. + */ +int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data); + +/** + * \brief Return the element number of ring buffer + * + * \param[in] rb The pointer to a ring buffer structure instance + * + * \return The number of elements in ring buffer [0, rb->size] + */ +uint32_t ringbuffer_num(const struct ringbuffer *const rb); + +/** + * \brief Flush ring buffer, the user needs to handle the concurrent access on buffer + * via put/get/flush + * + * \param[in] rb The pointer to a ring buffer structure instance + * + * \return ERR_NONE on success, or an error code on failure. + */ +uint32_t ringbuffer_flush(struct ringbuffer *const rb); + +/**@}*/ + +#ifdef __cplusplus +} +#endif +#endif /* _UTILS_RINGBUFFER_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hal/utils/src/utils_ringbuffer.c b/bsp/microchip/samc21/bsp/hal/utils/src/utils_ringbuffer.c new file mode 100644 index 0000000000..45cac83fc6 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hal/utils/src/utils_ringbuffer.c @@ -0,0 +1,118 @@ +/** + * \file + * + * \brief Ringbuffer functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include "utils_ringbuffer.h" + +/** + * \brief Ringbuffer init + */ +int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size) +{ + ASSERT(rb && buf && size); + + /* + * buf size must be aligned to power of 2 + */ + if ((size & (size - 1)) != 0) { + return ERR_INVALID_ARG; + } + + /* size - 1 is faster in calculation */ + rb->size = size - 1; + rb->read_index = 0; + rb->write_index = rb->read_index; + rb->buf = (uint8_t *)buf; + + return ERR_NONE; +} + +/** + * \brief Get one byte from ringbuffer + * + */ +int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data) +{ + ASSERT(rb && data); + + if (rb->write_index != rb->read_index) { + *data = rb->buf[rb->read_index & rb->size]; + rb->read_index++; + return ERR_NONE; + } + + return ERR_NOT_FOUND; +} + +/** + * \brief Put one byte to ringbuffer + * + */ +int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data) +{ + ASSERT(rb); + + rb->buf[rb->write_index & rb->size] = data; + + /* + * buffer full strategy: new data will overwrite the oldest data in + * the buffer + */ + if ((rb->write_index - rb->read_index) > rb->size) { + rb->read_index = rb->write_index - rb->size; + } + + rb->write_index++; + + return ERR_NONE; +} + +/** + * \brief Return the element number of ringbuffer + */ +uint32_t ringbuffer_num(const struct ringbuffer *const rb) +{ + ASSERT(rb); + + return rb->write_index - rb->read_index; +} + +/** + * \brief Flush ringbuffer + */ +uint32_t ringbuffer_flush(struct ringbuffer *const rb) +{ + ASSERT(rb); + + rb->read_index = rb->write_index; + + return ERR_NONE; +} diff --git a/bsp/microchip/samc21/bsp/hpl/adc/hpl_adc.c b/bsp/microchip/samc21/bsp/hpl/adc/hpl_adc.c new file mode 100644 index 0000000000..0784c4cf91 --- /dev/null +++ b/bsp/microchip/samc21/bsp/hpl/adc/hpl_adc.c @@ -0,0 +1,771 @@ + +/** + * \file + * + * \brief SAM Analog Digital Converter + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +#include +#include +#include +#include + +#ifndef CONF_ADC_0_ENABLE +#define CONF_ADC_0_ENABLE 0 +#endif +#ifndef CONF_ADC_1_ENABLE +#define CONF_ADC_1_ENABLE 0 +#endif + +/** + * \brief Macro is used to fill ADC configuration structure based on its number + * + * \param[in] n The number of structures + */ + +#define ADC_CONFIGURATION(n) \ + { \ + (n), \ + (CONF_ADC_##n##_RUNSTDBY << ADC_CTRLA_RUNSTDBY_Pos) | (CONF_ADC_##n##_ONDEMAND << ADC_CTRLA_ONDEMAND_Pos) \ + | (CONF_ADC_##n##_SLAVEEN << ADC_CTRLA_SLAVEEN_Pos), \ + ADC_CTRLB_PRESCALER(CONF_ADC_##n##_PRESCALER), \ + (CONF_ADC_##n##_REFCOMP << ADC_REFCTRL_REFCOMP_Pos) | ADC_REFCTRL_REFSEL(CONF_ADC_##n##_REFSEL), \ + (CONF_ADC_##n##_WINMONEO << ADC_EVCTRL_WINMONEO_Pos) \ + | (CONF_ADC_##n##_RESRDYEO << ADC_EVCTRL_RESRDYEO_Pos) \ + | (CONF_ADC_##n##_STARTINV << ADC_EVCTRL_STARTINV_Pos) \ + | (CONF_ADC_##n##_FLUSHINV << ADC_EVCTRL_FLUSHINV_Pos) \ + | (CONF_ADC_##n##_STARTEI << ADC_EVCTRL_STARTEI_Pos) \ + | (CONF_ADC_##n##_FLUSHEI << ADC_EVCTRL_FLUSHEI_Pos), \ + ADC_INPUTCTRL_MUXNEG(CONF_ADC_##n##_MUXNEG) | ADC_INPUTCTRL_MUXPOS(CONF_ADC_##n##_MUXPOS), \ + ADC_CTRLC_DUALSEL(CONF_ADC_##n##_DUALSEL) | ADC_CTRLC_WINMODE(CONF_ADC_##n##_WINMODE) \ + | (CONF_ADC_##n##_R2R << ADC_CTRLC_R2R_Pos) | ADC_CTRLC_RESSEL(CONF_ADC_##n##_RESSEL) \ + | (CONF_ADC_##n##_CORREN << ADC_CTRLC_CORREN_Pos) | (CONF_ADC_##n##_FREERUN << ADC_CTRLC_FREERUN_Pos) \ + | (CONF_ADC_##n##_LEFTADJ << ADC_CTRLC_LEFTADJ_Pos) \ + | (CONF_ADC_##n##_DIFFMODE << ADC_CTRLC_DIFFMODE_Pos), \ + ADC_AVGCTRL_ADJRES(CONF_ADC_##n##_ADJRES) | ADC_AVGCTRL_SAMPLENUM(CONF_ADC_##n##_SAMPLENUM), \ + (CONF_ADC_##n##_OFFCOMP << ADC_SAMPCTRL_OFFCOMP_Pos) | ADC_SAMPCTRL_SAMPLEN(CONF_ADC_##n##_SAMPLEN), \ + ADC_WINLT_WINLT(CONF_ADC_##n##_WINLT), ADC_WINUT_WINUT(CONF_ADC_##n##_WINUT), \ + ADC_GAINCORR_GAINCORR(CONF_ADC_##n##_GAINCORR), ADC_OFFSETCORR_OFFSETCORR(CONF_ADC_##n##_OFFSETCORR), \ + CONF_ADC_##n##_DBGRUN << ADC_DBGCTRL_DBGRUN_Pos, ADC_SEQCTRL_SEQEN(CONF_ADC_##n##_SEQEN), \ + } + +/** + * \brief ADC configuration + */ +struct adc_configuration { + uint8_t number; + hri_adc_ctrla_reg_t ctrl_a; + hri_adc_ctrlb_reg_t ctrl_b; + hri_adc_refctrl_reg_t ref_ctrl; + hri_adc_evctrl_reg_t ev_ctrl; + hri_adc_inputctrl_reg_t input_ctrl; + hri_adc_ctrlc_reg_t ctrl_c; + hri_adc_avgctrl_reg_t avg_ctrl; + hri_adc_sampctrl_reg_t samp_ctrl; + hri_adc_winlt_reg_t win_lt; + hri_adc_winut_reg_t win_ut; + hri_adc_gaincorr_reg_t gain_corr; + hri_adc_offsetcorr_reg_t offset_corr; + hri_adc_dbgctrl_reg_t dbg_ctrl; + hri_adc_seqctrl_reg_t seq_ctrl; +}; + +#define ADC_AMOUNT (CONF_ADC_0_ENABLE + CONF_ADC_1_ENABLE) + +/** + * \brief Array of ADC configurations + */ +static const struct adc_configuration _adcs[] = { +#if CONF_ADC_0_ENABLE == 1 + ADC_CONFIGURATION(0), +#endif +#if CONF_ADC_1_ENABLE == 1 + ADC_CONFIGURATION(1), +#endif +}; + +static void _adc_set_reference_source(void *const hw, const adc_reference_t reference); + +/** + * \brief Retrieve ordinal number of the given adc hardware instance + */ +static uint8_t _adc_get_hardware_index(const void *const hw) +{ + return ((uint32_t)hw - (uint32_t)ADC0) >> 10; +} + +/** \brief Return the pointer to register settings of specific ADC + * \param[in] hw_addr The hardware register base address. + * \return Pointer to register settings of specific ADC. + */ +static uint8_t _adc_get_regs(const uint32_t hw_addr) +{ + uint8_t n = _adc_get_hardware_index((const void *)hw_addr); + uint8_t i; + + for (i = 0; i < sizeof(_adcs) / sizeof(struct adc_configuration); i++) { + if (_adcs[i].number == n) { + return i; + } + } + + ASSERT(false); + return 0; +} + +/** + * \brief Retrieve IRQ number for the given hardware instance + */ +static uint8_t _adc_get_irq_num(const struct _adc_async_device *const device) +{ + return ADC0_IRQn + _adc_get_hardware_index(device->hw); +} + +/** + * \brief Init irq param with the given afec hardware instance + */ +static void _adc_init_irq_param(const void *const hw, struct _adc_async_device *dev) +{ +} + +/** + * \brief Initialize ADC + * + * \param[in] hw The pointer to hardware instance + * \param[in] i The number of hardware instance + */ +static int32_t _adc_init(void *const hw, const uint8_t i) +{ + uint16_t calib_reg = 0; + if (hw == ADC0) { + calib_reg = ADC_CALIB_BIASREFBUF((*(uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR >> ADC0_FUSES_BIASREFBUF_Pos)) + | ADC_CALIB_BIASCOMP((*(uint32_t *)ADC0_FUSES_BIASCOMP_ADDR >> ADC0_FUSES_BIASCOMP_Pos)); + } else if (hw == ADC1) { + calib_reg = ADC_CALIB_BIASREFBUF((*(uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR >> ADC1_FUSES_BIASREFBUF_Pos)) + | ADC_CALIB_BIASCOMP((*(uint32_t *)ADC1_FUSES_BIASCOMP_ADDR >> ADC1_FUSES_BIASCOMP_Pos)); + } + + if (!hri_adc_is_syncing(hw, ADC_SYNCBUSY_SWRST)) { + if (hri_adc_get_CTRLA_reg(hw, ADC_CTRLA_ENABLE)) { + hri_adc_clear_CTRLA_ENABLE_bit(hw); + hri_adc_wait_for_sync(hw, ADC_SYNCBUSY_ENABLE); + } + hri_adc_write_CTRLA_reg(hw, ADC_CTRLA_SWRST); + } + hri_adc_wait_for_sync(hw, ADC_SYNCBUSY_SWRST); + + hri_adc_write_CALIB_reg(hw, calib_reg); + hri_adc_write_CTRLB_reg(hw, _adcs[i].ctrl_b); + hri_adc_write_REFCTRL_reg(hw, _adcs[i].ref_ctrl); + hri_adc_write_EVCTRL_reg(hw, _adcs[i].ev_ctrl); + hri_adc_write_INPUTCTRL_reg(hw, _adcs[i].input_ctrl); + hri_adc_write_CTRLC_reg(hw, _adcs[i].ctrl_c); + hri_adc_write_AVGCTRL_reg(hw, _adcs[i].avg_ctrl); + hri_adc_write_SAMPCTRL_reg(hw, _adcs[i].samp_ctrl); + hri_adc_write_WINLT_reg(hw, _adcs[i].win_lt); + hri_adc_write_WINUT_reg(hw, _adcs[i].win_ut); + hri_adc_write_GAINCORR_reg(hw, _adcs[i].gain_corr); + hri_adc_write_OFFSETCORR_reg(hw, _adcs[i].offset_corr); + hri_adc_write_DBGCTRL_reg(hw, _adcs[i].dbg_ctrl); + hri_adc_write_SEQCTRL_reg(hw, _adcs[i].seq_ctrl); + hri_adc_write_CTRLA_reg(hw, _adcs[i].ctrl_a); + + return ERR_NONE; +} + +/** + * \brief De-initialize ADC + * + * \param[in] hw The pointer to hardware instance + */ +static inline void _adc_deinit(void *hw) +{ + hri_adc_clear_CTRLA_ENABLE_bit(hw); + hri_adc_set_CTRLA_SWRST_bit(hw); +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw) +{ + ASSERT(device); + + device->hw = hw; + + return _adc_init(hw, _adc_get_regs((uint32_t)hw)); +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw) +{ + int32_t init_status; + + ASSERT(device); + + init_status = _adc_init(hw, _adc_get_regs((uint32_t)hw)); + if (init_status) { + return init_status; + } + device->hw = hw; + _adc_init_irq_param(hw, device); + NVIC_DisableIRQ(_adc_get_irq_num(device)); + NVIC_ClearPendingIRQ(_adc_get_irq_num(device)); + NVIC_EnableIRQ(_adc_get_irq_num(device)); + + return ERR_NONE; +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_dma_init(struct _adc_dma_device *const device, void *const hw) +{ + ASSERT(device); + + device->hw = hw; + + return _adc_init(hw, _adc_get_regs((uint32_t)hw)); +} + +/** + * \brief De-initialize ADC + */ +void _adc_sync_deinit(struct _adc_sync_device *const device) +{ + _adc_deinit(device->hw); +} + +/** + * \brief De-initialize ADC + */ +void _adc_async_deinit(struct _adc_async_device *const device) +{ + NVIC_DisableIRQ(_adc_get_irq_num(device)); + NVIC_ClearPendingIRQ(_adc_get_irq_num(device)); + + _adc_deinit(device->hw); +} + +/** + * \brief De-initialize ADC + */ +void _adc_dma_deinit(struct _adc_dma_device *const device) +{ + _adc_deinit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_dma_enable_channel(struct _adc_dma_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable ADC + */ +void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable ADC + */ +void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable ADC + */ +void _adc_dma_disable_channel(struct _adc_dma_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Return address of ADC DMA source + */ +uint32_t _adc_get_source_for_dma(struct _adc_dma_device *const device) +{ + return (uint32_t) & (((Adc *)(device->hw))->RESULT.reg); +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device) +{ + return hri_adc_read_CTRLC_RESSEL_bf(device->hw) == ADC_CTRLC_RESSEL_8BIT_Val ? 1 : 2; +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device) +{ + return hri_adc_read_CTRLC_RESSEL_bf(device->hw) == ADC_CTRLC_RESSEL_8BIT_Val ? 1 : 2; +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_dma_get_data_size(const struct _adc_dma_device *const device) +{ + return hri_adc_read_CTRLC_RESSEL_bf(device->hw) == ADC_CTRLC_RESSEL_8BIT_Val ? 1 : 2; +} + +/** + * \brief Check if conversion is done + */ +bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_get_interrupt_RESRDY_bit(device->hw); +} + +/** + * \brief Check if conversion is done + */ +bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_get_interrupt_RESRDY_bit(device->hw); +} + +/** + * \brief Check if conversion is done + */ +bool _adc_dma_is_conversion_done(const struct _adc_dma_device *const device) +{ + return hri_adc_get_interrupt_RESRDY_bit(device->hw); +} + +/** + * \brief Make conversion + */ +void _adc_sync_convert(struct _adc_sync_device *const device) +{ + hri_adc_set_SWTRIG_START_bit(device->hw); +} + +/** + * \brief Make conversion + */ +void _adc_async_convert(struct _adc_async_device *const device) +{ + hri_adc_set_SWTRIG_START_bit(device->hw); +} + +/** + * \brief Make conversion + */ +void _adc_dma_convert(struct _adc_dma_device *const device) +{ + hri_adc_set_SWTRIG_START_bit(device->hw); +} + +/** + * \brief Retrieve the conversion result + */ +uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_read_RESULT_reg(device->hw); +} + +/** + * \brief Retrieve the conversion result + */ +uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_read_RESULT_reg(device->hw); +} + +/** + * \brief Set reference source + */ +void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference) +{ + _adc_set_reference_source(device->hw, reference); +} + +/** + * \brief Set reference source + */ +void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference) +{ + _adc_set_reference_source(device->hw, reference); +} + +/** + * \brief Set reference source + */ +void _adc_dma_set_reference_source(struct _adc_dma_device *const device, const adc_reference_t reference) +{ + _adc_set_reference_source(device->hw, reference); +} + +/** + * \brief Set resolution + */ +void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution) +{ + hri_adc_write_CTRLC_RESSEL_bf(device->hw, resolution); +} + +/** + * \brief Set resolution + */ +void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution) +{ + hri_adc_write_CTRLC_RESSEL_bf(device->hw, resolution); +} + +/** + * \brief Set resolution + */ +void _adc_dma_set_resolution(struct _adc_dma_device *const device, const adc_resolution_t resolution) +{ + hri_adc_write_CTRLC_RESSEL_bf(device->hw, resolution); +} + +/** + * \brief Set channels input sources + */ +void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)channel; + + hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input); + hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input); +} + +/** + * \brief Set channels input sources + */ +void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)channel; + + hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input); + hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input); +} + +/** + * \brief Set channels input source + */ +void _adc_dma_set_inputs(struct _adc_dma_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)channel; + + hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input); + hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input); +} + +/** + * \brief Set thresholds + */ +void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_adc_write_WINLT_reg(device->hw, low_threshold); + hri_adc_write_WINUT_reg(device->hw, up_threshold); +} + +/** + * \brief Set thresholds + */ +void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_adc_write_WINLT_reg(device->hw, low_threshold); + hri_adc_write_WINUT_reg(device->hw, up_threshold); +} + +/** + * \brief Set thresholds + */ +void _adc_dma_set_thresholds(struct _adc_dma_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_adc_write_WINLT_reg(device->hw, low_threshold); + hri_adc_write_WINUT_reg(device->hw, up_threshold); +} + +/** + * \brief Set gain + */ +void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + (void)device, (void)channel, (void)gain; +} + +/** + * \brief Set gain + */ +void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + (void)device, (void)channel, (void)gain; +} + +/** + * \brief Set gain + */ +void _adc_dma_set_channel_gain(struct _adc_dma_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + (void)device, (void)channel, (void)gain; +} + +/** + * \brief Set conversion mode + */ +void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_adc_set_CTRLC_FREERUN_bit(device->hw); + } else { + hri_adc_clear_CTRLC_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set conversion mode + */ +void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_adc_set_CTRLC_FREERUN_bit(device->hw); + } else { + hri_adc_clear_CTRLC_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set conversion mode + */ +void _adc_dma_set_conversion_mode(struct _adc_dma_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_adc_set_CTRLC_FREERUN_bit(device->hw); + } else { + hri_adc_clear_CTRLC_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + (void)channel; + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_adc_set_CTRLC_DIFFMODE_bit(device->hw); + } else { + hri_adc_clear_CTRLC_DIFFMODE_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + (void)channel; + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_adc_set_CTRLC_DIFFMODE_bit(device->hw); + } else { + hri_adc_clear_CTRLC_DIFFMODE_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_dma_set_channel_differential_mode(struct _adc_dma_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + (void)channel; + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_adc_set_CTRLC_DIFFMODE_bit(device->hw); + } else { + hri_adc_clear_CTRLC_DIFFMODE_bit(device->hw); + } +} + +/** + * \brief Set window mode + */ +void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode) +{ + hri_adc_write_CTRLC_WINMODE_bf(device->hw, mode); +} + +/** + * \brief Set window mode + */ +void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode) +{ + hri_adc_write_CTRLC_WINMODE_bf(device->hw, mode); +} + +/** + * \brief Set window mode + */ +void _adc_dma_set_window_mode(struct _adc_dma_device *const device, const adc_window_mode_t mode) +{ + hri_adc_write_CTRLC_WINMODE_bf(device->hw, mode); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_adc_get_interrupt_WINMON_bit(device->hw); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_adc_get_interrupt_WINMON_bit(device->hw); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_dma_get_threshold_state(const struct _adc_dma_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_adc_get_interrupt_WINMON_bit(device->hw); +} + +/** + * \brief Enable/disable ADC channel interrupt + */ +void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel, + const enum _adc_async_callback_type type, const bool state) +{ + (void)channel; + + void *const hw = device->hw; + + if (ADC_ASYNC_DEVICE_MONITOR_CB == type) { + hri_adc_write_INTEN_WINMON_bit(hw, state); + } else if (ADC_ASYNC_DEVICE_ERROR_CB == type) { + hri_adc_write_INTEN_OVERRUN_bit(hw, state); + } else if (ADC_ASYNC_DEVICE_CONVERT_CB == type) { + hri_adc_write_INTEN_RESRDY_bit(hw, state); + } +} + +/** + * \brief Retrieve ADC sync helper functions + */ +void *_adc_get_adc_sync(void) +{ + return (void *)NULL; +} + +/** + * \brief Retrieve ADC async helper functions + */ +void *_adc_get_adc_async(void) +{ + return (void *)NULL; +} + +/** + * \brief Set ADC reference source + * + * \param[in] hw The pointer to hardware instance + * \param[in] reference The reference to set + */ +static void _adc_set_reference_source(void *const hw, const adc_reference_t reference) +{ + bool enabled = hri_adc_get_CTRLA_ENABLE_bit(hw); + + hri_adc_clear_CTRLA_ENABLE_bit(hw); + hri_adc_write_REFCTRL_REFSEL_bf(hw, reference); + + if (enabled) { + hri_adc_set_CTRLA_ENABLE_bit(hw); + } +} diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_time_measure.h b/bsp/microchip/samc21/bsp/hpl/adc/hpl_adc_base.h similarity index 56% rename from bsp/microchip/same70/bsp/hal/include/hpl_time_measure.h rename to bsp/microchip/samc21/bsp/hpl/adc/hpl_adc_base.h index 5d688df5f5..e9b95283aa 100644 --- a/bsp/microchip/same70/bsp/hal/include/hpl_time_measure.h +++ b/bsp/microchip/samc21/bsp/hpl/adc/hpl_adc_base.h @@ -1,9 +1,9 @@ /** * \file * - * \brief Time measure related functionality declaration. + * \brief ADC related functionality declaration. * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. * * \asf_license_start * @@ -31,64 +31,42 @@ * */ -#ifndef _HPL_TIME_MEASURE_H_INCLUDED -#define _HPL_TIME_MEASURE_H_INCLUDED +#ifndef _HPL_ADC_ADC_H_INCLUDED +#define _HPL_ADC_ADC_H_INCLUDED + +#include +#include /** - * \addtogroup HPL Time measure + * \addtogroup HPL ADC * - * \section hpl_time_measure_rev Revision History + * \section hpl_adc_rev Revision History * - v1.0.0 Initial Release * *@{ */ -#include - #ifdef __cplusplus extern "C" { #endif -/** - * \brief System time type - */ -typedef uint32_t system_time_t; - /** * \name HPL functions */ //@{ -/** - * \brief Initialize system time module - * - * \param[in] hw The pointer to hardware instance to initialize - */ -void _system_time_init(void *const hw); /** - * \brief Deinitialize system time module + * \brief Retrieve ADC helper functions * - * \param[in] hw The pointer to hardware instance to initialize + * \return A pointer to set of ADC helper functions */ -void _system_time_deinit(void *const hw); +void *_adc_get_adc_sync(void); +void *_adc_get_adc_async(void); -/** - * \brief Get system time - * - * \param[in] hw The pointer to hardware instance to initialize - */ -system_time_t _system_time_get(const void *const hw); - -/** - * \brief Get maximum possible system time - * - * \param[in] hw The pointer to hardware instance to initialize - */ -system_time_t _system_time_get_max_time_value(const void *const hw); //@} #ifdef __cplusplus } #endif /**@}*/ -#endif /* _HPL_TIME_MEASURE_H_INCLUDED */ +#endif /* _HPL_USART_UART_H_INCLUDED */ diff --git a/bsp/microchip/samc21/bsp/hpl/sercom/hpl_sercom.c b/bsp/microchip/samc21/bsp/hpl/sercom/hpl_sercom.c index ee57a1112b..1f911c211e 100644 --- a/bsp/microchip/samc21/bsp/hpl/sercom/hpl_sercom.c +++ b/bsp/microchip/samc21/bsp/hpl/sercom/hpl_sercom.c @@ -156,6 +156,8 @@ static struct usart_configuration _usarts[] = { }; #endif +static struct _usart_async_device *_sercom4_dev = NULL; + static uint8_t _get_sercom_index(const void *const hw); static uint8_t _sercom_get_irq_num(const void *const hw); static void _sercom_init_irq_param(const void *const hw, void *dev); @@ -549,6 +551,40 @@ void _usart_async_set_irq_state(struct _usart_async_device *const device, const } } +/** + * \internal Sercom interrupt handler + * + * \param[in] p The pointer to interrupt parameter + */ +static void _sercom_usart_interrupt_handler(struct _usart_async_device *device) +{ + void *hw = device->hw; + + if (hri_sercomusart_get_interrupt_DRE_bit(hw) && hri_sercomusart_get_INTEN_DRE_bit(hw)) { + hri_sercomusart_clear_INTEN_DRE_bit(hw); + device->usart_cb.tx_byte_sent(device); + } else if (hri_sercomusart_get_interrupt_TXC_bit(hw) && hri_sercomusart_get_INTEN_TXC_bit(hw)) { + hri_sercomusart_clear_INTEN_TXC_bit(hw); + device->usart_cb.tx_done_cb(device); + } else if (hri_sercomusart_get_interrupt_RXC_bit(hw)) { + if (hri_sercomusart_read_STATUS_reg(hw) + & (SERCOM_USART_STATUS_PERR | SERCOM_USART_STATUS_FERR | SERCOM_USART_STATUS_BUFOVF + | SERCOM_USART_STATUS_ISF | SERCOM_USART_STATUS_COLL)) { + hri_sercomusart_clear_STATUS_reg(hw, SERCOM_USART_STATUS_MASK); + return; + } + + device->usart_cb.rx_done_cb(device, hri_sercomusart_read_DATA_reg(hw)); + } else if (hri_sercomusart_get_interrupt_ERROR_bit(hw)) { + uint32_t status; + + hri_sercomusart_clear_interrupt_ERROR_bit(hw); + device->usart_cb.error_cb(device); + status = hri_sercomusart_read_STATUS_reg(hw); + hri_sercomusart_clear_STATUS_reg(hw, status); + } +} + /** * \internal Retrieve ordinal number of the given sercom hardware instance * @@ -576,6 +612,10 @@ static uint8_t _get_sercom_index(const void *const hw) */ static void _sercom_init_irq_param(const void *const hw, void *dev) { + + if (hw == SERCOM4) { + _sercom4_dev = (struct _usart_async_device *)dev; + } } /** @@ -2407,6 +2447,11 @@ static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_a return NULL; } +void SERCOM4_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom4_dev); +} + int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw) { const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw); diff --git a/bsp/microchip/samc21/bsp/iar-project-connection.ipcf b/bsp/microchip/samc21/bsp/iar-project-connection.ipcf index f7a1ebb377..d6d1ddcbd0 100644 --- a/bsp/microchip/samc21/bsp/iar-project-connection.ipcf +++ b/bsp/microchip/samc21/bsp/iar-project-connection.ipcf @@ -10,6 +10,7 @@ $PROJ_DIR$\examples $PROJ_DIR$\hal\include $PROJ_DIR$\hal\utils\include + $PROJ_DIR$\hpl\adc $PROJ_DIR$\hpl\can $PROJ_DIR$\hpl\core $PROJ_DIR$\hpl\divas @@ -34,6 +35,7 @@ $PROJ_DIR$\examples $PROJ_DIR$\hal\include $PROJ_DIR$\hal\utils\include + $PROJ_DIR$\hpl\adc $PROJ_DIR$\hpl\can $PROJ_DIR$\hpl\core $PROJ_DIR$\hpl\divas @@ -101,6 +103,7 @@ + config/hpl_adc_config.h config/hpl_can_config.h config/hpl_divas_config.h config/hpl_dmac_config.h @@ -120,15 +123,20 @@ + hal/include/hal_adc_sync.h hal/include/hal_atomic.h hal/include/hal_can_async.h hal/include/hal_delay.h hal/include/hal_flash.h hal/include/hal_gpio.h + hal/include/hal_i2c_m_sync.h hal/include/hal_init.h hal/include/hal_io.h hal/include/hal_sleep.h - hal/include/hal_usart_sync.h + hal/include/hal_usart_async.h + hal/include/hpl_adc_async.h + hal/include/hpl_adc_dma.h + hal/include/hpl_adc_sync.h hal/include/hpl_can.h hal/include/hpl_can_async.h hal/include/hpl_core.h @@ -161,15 +169,17 @@ + hal/src/hal_adc_sync.c hal/src/hal_atomic.c hal/src/hal_can_async.c hal/src/hal_delay.c hal/src/hal_flash.c hal/src/hal_gpio.c + hal/src/hal_i2c_m_sync.c hal/src/hal_init.c hal/src/hal_io.c hal/src/hal_sleep.c - hal/src/hal_usart_sync.c + hal/src/hal_usart_async.c @@ -183,12 +193,19 @@ hal/utils/include/utils_increment_macro.h hal/utils/include/utils_list.h hal/utils/include/utils_repeat_macro.h + hal/utils/include/utils_ringbuffer.h hal/utils/src/utils_assert.c hal/utils/src/utils_event.c hal/utils/src/utils_list.c + hal/utils/src/utils_ringbuffer.c + + + + hpl/adc/hpl_adc.c + hpl/adc/hpl_adc_base.h diff --git a/bsp/microchip/samc21/bsp/samc21/gcc/gcc/samc21j18a_flash.ld b/bsp/microchip/samc21/bsp/samc21/gcc/gcc/samc21j18a_flash.ld index 42ae9c9797..6be606901a 100644 --- a/bsp/microchip/samc21/bsp/samc21/gcc/gcc/samc21j18a_flash.ld +++ b/bsp/microchip/samc21/bsp/samc21/gcc/gcc/samc21j18a_flash.ld @@ -58,6 +58,31 @@ SECTIONS *(.rodata .rodata* .gnu.linkonce.r.*) *(.ARM.extab* .gnu.linkonce.armextab.*) + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ . = ALIGN(4); diff --git a/bsp/microchip/samc21/rtconfig.h b/bsp/microchip/samc21/rtconfig.h index f9df6f8303..8f41fd1d20 100644 --- a/bsp/microchip/samc21/rtconfig.h +++ b/bsp/microchip/samc21/rtconfig.h @@ -54,14 +54,38 @@ #define RT_USING_USER_MAIN #define RT_MAIN_THREAD_STACK_SIZE 2048 #define RT_MAIN_THREAD_PRIORITY 10 +#define RT_USING_MSH +#define RT_USING_FINSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 +#define RT_USING_DFS +#define DFS_USING_POSIX +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 4 +#define DFS_FILESYSTEM_TYPES_MAX 4 +#define DFS_FD_MAX 16 +#define RT_USING_DFS_DEVFS /* Device Drivers */ #define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 +#define RT_USING_I2C /* Using USB */ @@ -170,11 +194,13 @@ #define SAMC21_CAN0 #define SAMC21_ADC0 +#define SAMC21_I2C0 /* Application Demo Config */ #define SAM_CAN_EXAMPLE #define SAM_ADC_EXAMPLE +#define SAM_I2C_EXAMPLE #define SOC_SAMC21 #endif diff --git a/bsp/microchip/same54/.config b/bsp/microchip/same54/.config index 1d00d6b9d6..f6c06d463c 100644 --- a/bsp/microchip/same54/.config +++ b/bsp/microchip/same54/.config @@ -21,7 +21,9 @@ CONFIG_RT_HOOK_USING_FUNC_PTR=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=256 -# CONFIG_RT_USING_TIMER_SOFT is not set +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 # # kservice optimization @@ -93,8 +95,33 @@ CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # CONFIG_RT_USING_LEGACY is not set -# CONFIG_RT_USING_MSH is not set -# CONFIG_RT_USING_DFS is not set +CONFIG_RT_USING_MSH=y +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=4 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_NFS is not set # CONFIG_RT_USING_FAL is not set # CONFIG_RT_USING_LWP is not set @@ -102,7 +129,9 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set @@ -111,9 +140,11 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +# CONFIG_RT_USING_I2C_BITOPS is not set # CONFIG_RT_USING_PHY is not set -CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_PIN is not set # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set @@ -147,11 +178,20 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # POSIX (Portable Operating System Interface) layer # -# CONFIG_RT_USING_POSIX_FS is not set -# CONFIG_RT_USING_POSIX_DELAY is not set -# CONFIG_RT_USING_POSIX_CLOCK is not set -# CONFIG_RT_USING_POSIX_TIMER is not set -# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +# CONFIG_RT_USING_POSIX_STDIO is not set +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y +CONFIG_RT_USING_POSIX_SOCKET=y +# CONFIG_RT_USING_POSIX_TERMIOS is not set +CONFIG_RT_USING_POSIX_AIO=y +# CONFIG_RT_USING_POSIX_MMAN is not set +CONFIG_RT_USING_POSIX_DELAY=y +CONFIG_RT_USING_POSIX_CLOCK=y +CONFIG_RT_USING_POSIX_TIMER=y +CONFIG_RT_USING_PTHREADS=y +CONFIG_PTHREAD_NUM_MAX=8 # CONFIG_RT_USING_MODULE is not set # @@ -169,9 +209,80 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # Network # -# CONFIG_RT_USING_SAL is not set -# CONFIG_RT_USING_NETDEV is not set -# CONFIG_RT_USING_LWIP is not set +CONFIG_RT_USING_SAL=y +CONFIG_SAL_INTERNET_CHECK=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +CONFIG_SAL_USING_POSIX=y +CONFIG_RT_USING_NETDEV=y +CONFIG_NETDEV_USING_IFCONFIG=y +CONFIG_NETDEV_USING_PING=y +CONFIG_NETDEV_USING_NETSTAT=y +CONFIG_NETDEV_USING_AUTO_DEFAULT=y +# CONFIG_NETDEV_USING_IPV6 is not set +CONFIG_NETDEV_IPV4=1 +CONFIG_NETDEV_IPV6=0 +# CONFIG_NETDEV_IPV6_SCOPES is not set +CONFIG_RT_USING_LWIP=y +CONFIG_RT_USING_LWIP_LOCAL_VERSION=y +# CONFIG_RT_USING_LWIP141 is not set +# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP212=y +CONFIG_RT_USING_LWIP_VER_NUM=0x20102 +# CONFIG_RT_USING_LWIP_IPV6 is not set +CONFIG_RT_LWIP_MEM_ALIGNMENT=4 +CONFIG_RT_LWIP_IGMP=y +CONFIG_RT_LWIP_ICMP=y +# CONFIG_RT_LWIP_SNMP is not set +CONFIG_RT_LWIP_DNS=y +CONFIG_RT_LWIP_DHCP=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_MSKADDR="255.255.255.0" +CONFIG_RT_LWIP_UDP=y +CONFIG_RT_LWIP_TCP=y +CONFIG_RT_LWIP_RAW=y +# CONFIG_RT_LWIP_PPP is not set +CONFIG_RT_MEMP_NUM_NETCONN=8 +CONFIG_RT_LWIP_PBUF_NUM=16 +CONFIG_RT_LWIP_RAW_PCB_NUM=4 +CONFIG_RT_LWIP_UDP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_SEG_NUM=40 +CONFIG_RT_LWIP_TCP_SND_BUF=8196 +CONFIG_RT_LWIP_TCP_WND=8196 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=1024 +# CONFIG_LWIP_NO_RX_THREAD is not set +# CONFIG_LWIP_NO_TX_THREAD is not set +CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8 +# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 +CONFIG_LWIP_NETIF_LINK_CALLBACK=1 +CONFIG_SO_REUSE=1 +CONFIG_LWIP_SO_RCVTIMEO=1 +CONFIG_LWIP_SO_SNDTIMEO=1 +CONFIG_LWIP_SO_RCVBUF=1 +CONFIG_LWIP_SO_LINGER=0 +# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=0 +# CONFIG_RT_LWIP_STATS is not set +# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set +CONFIG_RT_LWIP_USING_PING=y +# CONFIG_LWIP_USING_DHCPD is not set +# CONFIG_RT_LWIP_DEBUG is not set # CONFIG_RT_USING_AT is not set # @@ -640,10 +751,14 @@ CONFIG_SOC_SAME54P20=y # CONFIG_SAME5X_CAN0=y CONFIG_SAME5X_ADC0=y +CONFIG_SAME5X_I2C0=y +CONFIG_SAME5X_GMAC=y # # Application Demo Config # CONFIG_SAM_CAN_EXAMPLE=y CONFIG_SAM_ADC_EXAMPLE=y +CONFIG_SAM_I2C_EXAMPLE=y +CONFIG_SAM_LWIP_EXAMPLE=y CONFIG_SOC_SAME54=y diff --git a/bsp/microchip/same54/SConstruct b/bsp/microchip/same54/SConstruct index 4d91cd5ba5..9f8b13d9cf 100644 --- a/bsp/microchip/same54/SConstruct +++ b/bsp/microchip/same54/SConstruct @@ -34,8 +34,27 @@ if rtconfig.PLATFORM == 'iar': Export('RTT_ROOT') Export('rtconfig') +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/common'): + common_path_prefix = SDK_ROOT + '/common' +else: + common_path_prefix = os.path.dirname(SDK_ROOT) + '/common' + +SDK_LIB = common_path_prefix +Export('SDK_LIB') + # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) +sam_board = 'board' +rtconfig.BSP_LIBRARY_TYPE = sam_board + +# include libraries +objs.extend(SConscript(os.path.join(common_path_prefix, sam_board, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(common_path_prefix, 'applications', 'SConscript'))) + # make a building DoBuilding(TARGET, objs) diff --git a/bsp/microchip/same54/applications/can_demo.h b/bsp/microchip/same54/applications/can_demo.h deleted file mode 100644 index 499d0390f8..0000000000 --- a/bsp/microchip/same54/applications/can_demo.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release - */ - -#ifndef __APPLICATION_CAN_H_ -#define __APPLICATION_CAN_H_ - -#include - -/** - * @brief External function definitions - * - */ -rt_err_t can_demo_run(void); - -rt_err_t can_send_message(struct can_message *msg, rt_uint32_t timeouts); - -#endif // __APPLICATION_CAN_H_ diff --git a/bsp/microchip/same54/applications/main.c b/bsp/microchip/same54/applications/main.c index 8985159058..d08200f628 100644 --- a/bsp/microchip/same54/applications/main.c +++ b/bsp/microchip/same54/applications/main.c @@ -5,7 +5,7 @@ * * Change Logs: * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + * 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release */ #include @@ -22,6 +22,18 @@ #include "can_demo.h" #endif +#ifdef SAM_I2C_EXAMPLE +#include "i2c_demo.h" +#endif + +#ifdef SAM_ADC_EXAMPLE +#include "adc_demo.h" +#endif + +#ifdef SAM_LWIP_EXAMPLE +#include "lwip_demo.h" +#endif + static rt_uint8_t led_stack[ 512 ]; static struct rt_thread led_thread; @@ -63,6 +75,18 @@ int main(void) can_demo_run(); #endif +#ifdef SAM_I2C_EXAMPLE + i2c_demo_run(); +#endif + +#ifdef SAM_ADC_EXAMPLE + adc_demo_run(); +#endif + +#ifdef SAM_LWIP_EXAMPLE + lwip_demo_run(); +#endif + return 0; } diff --git a/bsp/microchip/same54/board/Kconfig b/bsp/microchip/same54/board/Kconfig index 33a8121227..b39630d703 100644 --- a/bsp/microchip/same54/board/Kconfig +++ b/bsp/microchip/same54/board/Kconfig @@ -32,6 +32,14 @@ menu "Onboard Peripheral Drivers" config SAME5X_ADC0 bool "Enable ADC0" default false + + config SAME5X_I2C0 + bool "Enable I2C0" + default false + + config SAME5X_GMAC + bool "Enable GMAC" + default false endmenu menu "Application Demo Config" @@ -49,4 +57,18 @@ menu "Application Demo Config" help Add ADC example task to project + config SAM_I2C_EXAMPLE + bool "Enable SAM I2C Example" + depends on SAME5X_I2C0 + default true + help + Add I2C example task to project + + config SAM_LWIP_EXAMPLE + bool "Enable SAM LWIP Example" + depends on SAME5X_GMAC + default false + help + Add GMAC LWIP example task to project + endmenu diff --git a/bsp/microchip/same54/board/board.c b/bsp/microchip/same54/board/board.c index 72f31efa6b..bd620e6e31 100644 --- a/bsp/microchip/same54/board/board.c +++ b/bsp/microchip/same54/board/board.c @@ -21,17 +21,20 @@ extern int rt_hw_uart_init(void); #endif static struct io_descriptor* g_stdio; +static uint8_t board_info[16] = "Microchip SAME54"; void rt_hw_console_output(const char *str) { io_write(g_stdio, (uint8_t *)str, strlen(str)); + while (TARGET_IO.stat != 0); } RTM_EXPORT(rt_hw_console_output); static inline void hw_board_init_usart(void) { - usart_sync_get_io_descriptor(&TARGET_IO, &g_stdio); - usart_sync_enable(&TARGET_IO); + usart_async_get_io_descriptor(&TARGET_IO, &g_stdio); + usart_async_enable(&TARGET_IO); + io_write(g_stdio, board_info, 16); } /** diff --git a/bsp/microchip/same54/bsp/AtmelStart.gpdsc b/bsp/microchip/same54/bsp/AtmelStart.gpdsc index 0c0dab608c..91c0348b11 100644 --- a/bsp/microchip/same54/bsp/AtmelStart.gpdsc +++ b/bsp/microchip/same54/bsp/AtmelStart.gpdsc @@ -42,18 +42,24 @@ Atmel Start Framework #define ATMEL_START + - + + + + + + @@ -69,6 +75,7 @@ + @@ -81,8 +88,10 @@ + + @@ -93,9 +102,11 @@ + + @@ -136,6 +147,10 @@ + + + + @@ -143,7 +158,10 @@ - + + + + @@ -153,8 +171,11 @@ - + + + + @@ -165,6 +186,7 @@ + @@ -173,24 +195,30 @@ + + + + + + @@ -206,6 +234,9 @@ + + + diff --git a/bsp/microchip/same54/bsp/SConscript b/bsp/microchip/same54/bsp/SConscript index fa2e7a16c1..fe928e7559 100644 --- a/bsp/microchip/same54/bsp/SConscript +++ b/bsp/microchip/same54/bsp/SConscript @@ -11,14 +11,17 @@ CPPDEFINES = [] CPPDEFINES += [rtconfig.DEVICE_TYPE] # The set of source files associated with this SConscript file. + src = Glob('hal/src/*.c') src += Glob('hal/utils/src/*.c') +src += Glob('hpl/adc/*.c') src += Glob('hpl/aes/*.c') src += Glob('hpl/can/*.c') src += Glob('hpl/cmcc/*.c') src += Glob('hpl/core/*.c') src += Glob('hpl/dmac/*.c') src += Glob('hpl/gclk/*.c') +src += Glob('hpl/gmac/*.c') src += Glob('hpl/mclk/*.c') src += Glob('hpl/osc32kctrl/*.c') src += Glob('hpl/oscctrl/*.c') @@ -26,8 +29,10 @@ src += Glob('hpl/pm/*.c') src += Glob('hpl/port/*.c') src += Glob('hpl/ramecc/*.c') src += Glob('hpl/sercom/*.c') +src += Glob('ethernet_phy/*.c') src += [cwd + '/atmel_start.c'] src += [cwd + '/driver_init.c'] +src += [cwd + '/ethernet_phy_main.c'] #add for startup script if rtconfig.CROSS_TOOL == 'gcc': @@ -44,15 +49,19 @@ path = [ cwd, cwd + '/CMSIS/Core/Include', cwd + '/config', + cwd + '/ethernet_phy', cwd + '/hal/include', cwd + '/hal/utils/include', + cwd + '/hpl/adc', cwd + '/hpl/can', cwd + '/hpl/core', cwd + '/hpl/gclk', cwd + '/hpl/pm', cwd + '/hpl/port', cwd + '/hri', - cwd + '/include',] + cwd + '/include', + cwd + '/../board', + cwd + '/../../common/applications'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/microchip/same54/bsp/armcc/Makefile b/bsp/microchip/same54/bsp/armcc/Makefile deleted file mode 100644 index 2c08b246d7..0000000000 --- a/bsp/microchip/same54/bsp/armcc/Makefile +++ /dev/null @@ -1,225 +0,0 @@ - -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -ifdef SystemRoot - SHELL = cmd.exe - MK_DIR = mkdir -else - ifeq ($(shell uname), Linux) - MK_DIR = mkdir -p - endif - - ifeq ($(shell uname | cut -d _ -f 1), CYGWIN) - MK_DIR = mkdir -p - endif - - ifeq ($(shell uname | cut -d _ -f 1), MINGW32) - MK_DIR = mkdir -p - endif - - ifeq ($(shell uname | cut -d _ -f 1), MINGW64) - MK_DIR = mkdir -p - endif -endif - -# List the subdirectories for creating object files -SUB_DIRS += \ - \ -hpl/pm \ -hpl/osc32kctrl \ -hpl/can \ -hpl/ramecc \ -hpl/dmac \ -hal/src \ -hpl/mclk \ -hpl/aes \ -hpl/sercom \ -examples \ -hpl/gclk \ -hpl/oscctrl \ -hal/utils/src \ -armcc/arm_addon/armcc/arm \ -armcc/arm_addon/armcc \ -hpl/core \ -hpl/cmcc - -# List the object files -OBJS += \ -hal/src/hal_io.o \ -hal/src/hal_can_async.o \ -armcc/arm_addon/armcc/system_same54.o \ -hpl/can/hpl_can.o \ -hpl/core/hpl_core_m4.o \ -hal/src/hal_cache.o \ -hpl/aes/hpl_aes.o \ -hal/src/hal_delay.o \ -hpl/pm/hpl_pm.o \ -hpl/core/hpl_init.o \ -hpl/gclk/hpl_gclk.o \ -hal/utils/src/utils_list.o \ -hal/utils/src/utils_assert.o \ -hpl/dmac/hpl_dmac.o \ -hpl/oscctrl/hpl_oscctrl.o \ -hal/src/hal_usart_sync.o \ -hpl/mclk/hpl_mclk.o \ -hpl/ramecc/hpl_ramecc.o \ -hal/src/hal_init.o \ -main.o \ -hpl/osc32kctrl/hpl_osc32kctrl.o \ -examples/driver_examples.o \ -driver_init.o \ -hpl/sercom/hpl_sercom.o \ -hal/src/hal_gpio.o \ -hal/utils/src/utils_event.o \ -hal/src/hal_sleep.o \ -hal/src/hal_aes_sync.o \ -hpl/cmcc/hpl_cmcc.o \ -atmel_start.o \ -hal/src/hal_atomic.o \ -armcc/arm_addon/armcc/arm/startup_same54.o - -OBJS_AS_ARGS += \ -"hal/src/hal_io.o" \ -"hal/src/hal_can_async.o" \ -"armcc/arm_addon/armcc/system_same54.o" \ -"hpl/can/hpl_can.o" \ -"hpl/core/hpl_core_m4.o" \ -"hal/src/hal_cache.o" \ -"hpl/aes/hpl_aes.o" \ -"hal/src/hal_delay.o" \ -"hpl/pm/hpl_pm.o" \ -"hpl/core/hpl_init.o" \ -"hpl/gclk/hpl_gclk.o" \ -"hal/utils/src/utils_list.o" \ -"hal/utils/src/utils_assert.o" \ -"hpl/dmac/hpl_dmac.o" \ -"hpl/oscctrl/hpl_oscctrl.o" \ -"hal/src/hal_usart_sync.o" \ -"hpl/mclk/hpl_mclk.o" \ -"hpl/ramecc/hpl_ramecc.o" \ -"hal/src/hal_init.o" \ -"main.o" \ -"hpl/osc32kctrl/hpl_osc32kctrl.o" \ -"examples/driver_examples.o" \ -"driver_init.o" \ -"hpl/sercom/hpl_sercom.o" \ -"hal/src/hal_gpio.o" \ -"hal/utils/src/utils_event.o" \ -"hal/src/hal_sleep.o" \ -"hal/src/hal_aes_sync.o" \ -"hpl/cmcc/hpl_cmcc.o" \ -"atmel_start.o" \ -"hal/src/hal_atomic.o" \ -"armcc/arm_addon/armcc/arm/startup_same54.o" - -# List the dependency files -DEPS := $(OBJS:%.o=%.d) - -DEPS_AS_ARGS += \ -"hal/utils/src/utils_event.d" \ -"hal/src/hal_io.d" \ -"armcc/arm_addon/armcc/system_same54.d" \ -"hal/src/hal_can_async.d" \ -"hpl/core/hpl_core_m4.d" \ -"hpl/can/hpl_can.d" \ -"hpl/aes/hpl_aes.d" \ -"hal/utils/src/utils_list.d" \ -"hpl/cmcc/hpl_cmcc.d" \ -"hpl/dmac/hpl_dmac.d" \ -"hal/utils/src/utils_assert.d" \ -"hal/src/hal_delay.d" \ -"hpl/core/hpl_init.d" \ -"hpl/pm/hpl_pm.d" \ -"hpl/ramecc/hpl_ramecc.d" \ -"hpl/gclk/hpl_gclk.d" \ -"hal/src/hal_init.d" \ -"hal/src/hal_usart_sync.d" \ -"hpl/mclk/hpl_mclk.d" \ -"driver_init.d" \ -"hpl/osc32kctrl/hpl_osc32kctrl.d" \ -"hal/src/hal_cache.d" \ -"main.d" \ -"examples/driver_examples.d" \ -"hal/src/hal_aes_sync.d" \ -"hal/src/hal_sleep.d" \ -"hpl/sercom/hpl_sercom.d" \ -"hal/src/hal_gpio.d" \ -"hal/src/hal_atomic.d" \ -"hpl/oscctrl/hpl_oscctrl.d" \ -"armcc/arm_addon/armcc/arm/startup_same54.d" \ -"atmel_start.d" - -OUTPUT_FILE_NAME :=AtmelStart -QUOTE := " -OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf -OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf - -vpath %.c ../ -vpath %.s ../ -vpath %.S ../ - -# All Target -all: $(SUB_DIRS) $(OUTPUT_FILE_PATH) - -# Linker target - -$(OUTPUT_FILE_PATH): $(OBJS) - @echo Building target: $@ - @echo Invoking: ARMCC Linker - $(QUOTE)armlink$(QUOTE) --ro-base 0x00000000 --entry 0x00000000 --rw-base 0x20000000 --entry Reset_Handler --first __Vectors \ ---strict --summary_stderr --info summarysizes --map --xref --callgraph --symbols \ ---info sizes --info totals --info unused --info veneers --list $(OUTPUT_FILE_NAME).map \ --o $(OUTPUT_FILE_NAME).elf --cpu Cortex-M4 \ -$(OBJS_AS_ARGS) - - @echo Finished building target: $@ - -# Compiler target(s) - - - - -%.o: %.c - @echo Building file: $< - @echo ARMCC Compiler - $(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M4 -D__SAME54P20A__ \ --I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/aes" -I"../hpl/can" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../include" \ ---depend "$@" -o "$@" "$<" - - @echo Finished building: $< - -%.o: %.s - @echo Building file: $< - @echo ARMCC Assembler - $(QUOTE)armasm$(QUOTE) -g --apcs=interwork --cpu Cortex-M4 --pd "D__SAME54P20A__ SETA 1" \ --I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/aes" -I"../hpl/can" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../include" \ ---depend "$(@:%.o=%.d)" -o "$@" "$<" - - @echo Finished building: $< - -%.o: %.S - @echo Building file: $< - @echo ARMCC Preprocessing Assembler - $(QUOTE)armcc$(QUOTE) --c99 -c -DDEBUG -O1 -g --apcs=interwork --split_sections --cpu Cortex-M4 -D__SAME54P20A__ \ --I"../" -I"../config" -I"../examples" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/aes" -I"../hpl/can" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/sercom" -I"../hri" -I"../" -I"../CMSIS/Core/Include" -I"../include" \ ---depend "$@" -o "$@" "$<" - - @echo Finished building: $< - -# Detect changes in the dependent files and recompile the respective object files. -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(strip $(DEPS)),) --include $(DEPS) -endif -endif - -$(SUB_DIRS): - $(MK_DIR) "$@" - -clean: - rm -f $(OBJS_AS_ARGS) - rm -f $(OUTPUT_FILE_PATH) - rm -f $(DEPS_AS_ARGS) - rm -f $(OUTPUT_FILE_NAME).map $(OUTPUT_FILE_NAME).elf diff --git a/bsp/microchip/same54/bsp/atmel_start.c b/bsp/microchip/same54/bsp/atmel_start.c index 79f252aed9..2faf66d653 100644 --- a/bsp/microchip/same54/bsp/atmel_start.c +++ b/bsp/microchip/same54/bsp/atmel_start.c @@ -6,4 +6,5 @@ void atmel_start_init(void) { system_init(); + ethernet_phys_init(); } diff --git a/bsp/microchip/same54/bsp/atmel_start.h b/bsp/microchip/same54/bsp/atmel_start.h index 0de62f528d..0793962b7a 100644 --- a/bsp/microchip/same54/bsp/atmel_start.h +++ b/bsp/microchip/same54/bsp/atmel_start.h @@ -6,6 +6,7 @@ extern "C" { #endif #include "driver_init.h" +#include "ethernet_phy_main.h" /** * Initializes MCU, drivers and middleware in the project diff --git a/bsp/microchip/same54/bsp/atmel_start_config.atstart b/bsp/microchip/same54/bsp/atmel_start_config.atstart index 00521a1385..aaa569011e 100644 --- a/bsp/microchip/same54/bsp/atmel_start_config.atstart +++ b/bsp/microchip/same54/bsp/atmel_start_config.atstart @@ -20,8 +20,79 @@ details: null application: definition: 'Atmel:Application_Examples:0.0.1::Application:AES_Demo:' configuration: null -middlewares: {} +middlewares: + MACIF_PHY: + user_label: MACIF_PHY + configuration: + ieee8023_mii_control_autoneg_en: true + ieee8023_mii_control_duplex_mode: full duplex + ieee8023_mii_control_isolate_en: false + ieee8023_mii_control_loopback_en: false + ieee8023_mii_control_powerdown_en: false + ieee8023_mii_control_reg0_setting: true + ieee8023_mii_control_speed_lsb: 100 Mb/s + ieee8023_mii_phy_address: 0 + definition: Atmel:Ethernet_PHY:0.0.1::Generic_Ethernet_PHY_Driver + functionality: Ethernet_PHY + api: Ethernet:GenericPHY:Driver + dependencies: + Communication IO: MACIF drivers: + ADC_0: + user_label: ADC_0 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::ADC0::driver_config_definition::ADC::HAL:Driver:ADC.Sync + functionality: ADC + api: HAL:Driver:ADC_Sync + configuration: + adc_advanced_settings: true + adc_arch_adjres: 0 + adc_arch_corren: false + adc_arch_dbgrun: false + adc_arch_event_settings: false + adc_arch_flushei: false + adc_arch_flushinv: false + adc_arch_gaincorr: 0 + adc_arch_leftadj: false + adc_arch_offcomp: false + adc_arch_offsetcorr: 0 + adc_arch_ondemand: false + adc_arch_refcomp: false + adc_arch_resrdyeo: false + adc_arch_runstdby: false + adc_arch_samplen: 2 + adc_arch_samplenum: 4 samples + adc_arch_seqen: 0 + adc_arch_startei: false + adc_arch_startinv: false + adc_arch_winlt: 0 + adc_arch_winmode: No window mode + adc_arch_winmoneo: false + adc_arch_winut: 0 + adc_differential_mode: false + adc_freerunning_mode: false + adc_pinmux_negative: Internal ground + adc_pinmux_positive: ADC AIN0 pin + adc_prescaler: Peripheral clock divided by 2 + adc_reference: VDDANA + adc_resolution: 16-bit (averaging must be enabled) + optional_signals: + - identifier: ADC_0:AIN/0 + pad: PA02 + mode: Enabled + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::ADC0.AIN.0 + name: ADC0/AIN/0 + label: AIN/0 + variant: null + clocks: + domain_group: + nodes: + - name: ADC + input: Generic clock generator 0 + external: false + external_frequency: 0 + configuration: + adc_gclk_selection: Generic clock generator 0 CRYPTOGRAPHY_0: user_label: CRYPTOGRAPHY_0 definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::AES::driver_config_definition::AES::HAL:Driver:AES.Sync @@ -591,10 +662,10 @@ drivers: functionality: System api: HAL:HPL:GCLK configuration: - $input: 120000000 - $input_id: Digital Phase Locked Loop (DPLL0) - RESERVED_InputFreq: 120000000 - RESERVED_InputFreq_id: Digital Phase Locked Loop (DPLL0) + $input: 12000000 + $input_id: External Crystal Oscillator 8-48MHz (XOSC1) + RESERVED_InputFreq: 12000000 + RESERVED_InputFreq_id: External Crystal Oscillator 8-48MHz (XOSC1) _$freq_output_Generic clock generator 0: 120000000 _$freq_output_Generic clock generator 1: 3000000 _$freq_output_Generic clock generator 10: 12000000 @@ -798,10 +869,10 @@ drivers: functionality: System api: HAL:HPL:OSCCTRL configuration: - $input: 40000000 - $input_id: Generic clock generator 3 - RESERVED_InputFreq: 40000000 - RESERVED_InputFreq_id: Generic clock generator 3 + $input: 32768 + $input_id: 32kHz External Crystal Oscillator (XOSC32K) + RESERVED_InputFreq: 32768 + RESERVED_InputFreq_id: 32kHz External Crystal Oscillator (XOSC32K) _$freq_output_Digital Frequency Locked Loop (DFLL48M): 48000000 _$freq_output_Digital Phase Locked Loop (DPLL0): 120000000 _$freq_output_Digital Phase Locked Loop (DPLL1): 47985664 @@ -956,11 +1027,11 @@ drivers: domain_group: null TARGET_IO: user_label: TARGET_IO - definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM2::driver_config_definition::UART::HAL:Driver:USART.Sync + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM2::driver_config_definition::UART::HAL:Driver:USART.Async functionality: USART - api: HAL:Driver:USART_Sync + api: HAL:Driver:USART_Async configuration: - usart_advanced: false + usart_advanced: true usart_arch_clock_mode: USART with internal clock usart_arch_cloden: false usart_arch_dbgstop: Keep running @@ -1003,6 +1074,46 @@ drivers: configuration: core_gclk_selection: Generic clock generator 0 slow_gclk_selection: Generic clock generator 1 + I2C_0: + user_label: I2C_0 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::SERCOM7::driver_config_definition::I2C.Master.Standard~2FFast-mode::HAL:Driver:I2C.Master.Sync + functionality: I2C + api: HAL:Driver:I2C_Master_Sync + configuration: + i2c_master_advanced: true + i2c_master_arch_dbgstop: Keep running + i2c_master_arch_inactout: 20-21 SCL cycle time-out(200-210us) + i2c_master_arch_lowtout: true + i2c_master_arch_mexttoen: true + i2c_master_arch_runstdby: false + i2c_master_arch_sdahold: 300-600ns hold time + i2c_master_arch_sexttoen: false + i2c_master_arch_trise: 215 + i2c_master_baud_rate: 100000 + optional_signals: [] + variant: + specification: SDA=0, SCL=1 + required_signals: + - name: SERCOM7/PAD/0 + pad: PD08 + label: SDA + - name: SERCOM7/PAD/1 + pad: PD09 + label: SCL + clocks: + domain_group: + nodes: + - name: Core + input: Generic clock generator 3 + external: false + external_frequency: 0 + - name: Slow + input: Generic clock generator 1 + external: false + external_frequency: 0 + configuration: + core_gclk_selection: Generic clock generator 3 + slow_gclk_selection: Generic clock generator 1 CAN_0: user_label: CAN_0 definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::CAN1::driver_config_definition::CAN::HAL:Driver:CAN.Async @@ -1067,7 +1178,145 @@ drivers: external_frequency: 0 configuration: can_gclk_selection: Generic clock generator 3 + MACIF: + user_label: MACIF + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::GMAC::driver_config_definition::GMAC::HAL:Driver:GMAC.Async + functionality: Ethernet_MAC + api: HAL:Driver:GMAC_Async + configuration: + gmac_arch_adv_cfg: true + gmac_arch_cltto: Clause 22 Operation + gmac_arch_dcfgr_ddrp: false + gmac_arch_dcfgr_drbs: 2 + gmac_arch_dcfgr_esma: false + gmac_arch_dcfgr_espa: false + gmac_arch_dcfgr_fbldo: Always use INCR4 AHB bursts + gmac_arch_dcfgr_rxbms: 4 Kbytes + gmac_arch_dcfgr_txcoen: false + gmac_arch_dcfgr_txpbms: 4 Kbytes + gmac_arch_dma_cfg: true + gmac_arch_ipgs_fl_div: 1 + gmac_arch_ipgs_fl_mul: 1 + gmac_arch_mii_cfg: true + gmac_arch_ncfgr_caf: false + gmac_arch_ncfgr_clk: '64' + gmac_arch_ncfgr_dcpf: false + gmac_arch_ncfgr_df: true + gmac_arch_ncfgr_dnvlan: false + gmac_arch_ncfgr_efrhd: false + gmac_arch_ncfgr_ipgsen: false + gmac_arch_ncfgr_irxer: false + gmac_arch_ncfgr_irxfcs: false + gmac_arch_ncfgr_jframe: false + gmac_arch_ncfgr_lferd: false + gmac_arch_ncfgr_maxfs: true + gmac_arch_ncfgr_mtihen: false + gmac_arch_ncfgr_nbc: false + gmac_arch_ncfgr_pen: false + gmac_arch_ncfgr_rfcs: false + gmac_arch_ncfgr_rty: false + gmac_arch_ncfgr_rxbp: false + gmac_arch_ncfgr_rxbufo: 0 + gmac_arch_ncfgr_rxcoen: false + gmac_arch_ncfgr_spd: true + gmac_arch_ncfgr_unihen: false + gmac_arch_ncr_bp: false + gmac_arch_ncr_enpbpr: false + gmac_arch_ncr_lbl: false + gmac_arch_ncr_mpe: true + gmac_arch_ncr_txpbpf: false + gmac_arch_ncr_westat: false + gmac_arch_rpsf_en: false + gmac_arch_rpsf_wm: 100 + gmac_arch_rxdescr_num: 16 + gmac_arch_svlan_enable: false + gmac_arch_svlan_type: 33024 + gmac_arch_tpsf_en: false + gmac_arch_tpsf_wm: 100 + gmac_arch_txbuf_size: 1500 + gmac_arch_txdescr_num: 2 + gmac_arch_ur_mii: RMII + optional_signals: + - identifier: MACIF:GMDC + pad: PC11 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GMDC + name: GMAC/GMDC + label: GMDC + - identifier: MACIF:GMDIO + pad: PC12 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GMDIO + name: GMAC/GMDIO + label: GMDIO + - identifier: MACIF:GRX/0 + pad: PA13 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GRX.0 + name: GMAC/GRX/0 + label: GRX/0 + - identifier: MACIF:GRX/1 + pad: PA12 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GRX.1 + name: GMAC/GRX/1 + label: GRX/1 + - identifier: MACIF:GRXDV + pad: PC20 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GRXDV + name: GMAC/GRXDV + label: GRXDV + - identifier: MACIF:GRXER + pad: PA15 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GRXER + name: GMAC/GRXER + label: GRXER + - identifier: MACIF:GTX/0 + pad: PA18 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GTX.0 + name: GMAC/GTX/0 + label: GTX/0 + - identifier: MACIF:GTX/1 + pad: PA19 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GTX.1 + name: GMAC/GTX/1 + label: GTX/1 + - identifier: MACIF:GTXCK + pad: PA14 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GTXCK + name: GMAC/GTXCK + label: GTXCK + - identifier: MACIF:GTXEN + pad: PA17 + mode: Enable + configuration: null + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::optional_signal_definition::GMAC.GTXEN + name: GMAC/GTXEN + label: GTXEN + variant: null + clocks: + domain_group: null pads: + PA02: + name: PA02 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA02 + mode: Analog + user_label: PA02 + configuration: null PB12: name: PB12 definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PB12 @@ -1080,12 +1329,84 @@ pads: mode: Peripheral IO user_label: PB13 configuration: null + PD08: + name: PD08 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PD08 + mode: I2C + user_label: PD08 + configuration: null + PD09: + name: PD09 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PD09 + mode: I2C + user_label: PD09 + configuration: null + PC11: + name: PC11 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PC11 + mode: Peripheral IO + user_label: PC11 + configuration: null + PC12: + name: PC12 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PC12 + mode: Peripheral IO + user_label: PC12 + configuration: null + PA12: + name: PA12 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA12 + mode: Peripheral IO + user_label: PA12 + configuration: null + PA13: + name: PA13 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA13 + mode: Peripheral IO + user_label: PA13 + configuration: null + PA14: + name: PA14 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA14 + mode: Peripheral IO + user_label: PA14 + configuration: null + PA15: + name: PA15 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA15 + mode: Peripheral IO + user_label: PA15 + configuration: null + PA17: + name: PA17 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA17 + mode: Peripheral IO + user_label: PA17 + configuration: null + PA18: + name: PA18 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA18 + mode: Peripheral IO + user_label: PA18 + configuration: null + PA19: + name: PA19 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PA19 + mode: Peripheral IO + user_label: PA19 + configuration: null LED0: name: PC18 definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PC18 mode: Digital output user_label: LED0 configuration: null + PC20: + name: PC20 + definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PC20 + mode: Peripheral IO + user_label: PC20 + configuration: null PB24: name: PB24 definition: Atmel:SAME54_Drivers:0.0.1::SAME54P20A-AU::pad::PB24 diff --git a/bsp/microchip/same54/bsp/atmel_start_pins.h b/bsp/microchip/same54/bsp/atmel_start_pins.h index 170b507e0c..b533f2611a 100644 --- a/bsp/microchip/same54/bsp/atmel_start_pins.h +++ b/bsp/microchip/same54/bsp/atmel_start_pins.h @@ -27,10 +27,23 @@ #define GPIO_PIN_FUNCTION_M 12 #define GPIO_PIN_FUNCTION_N 13 +#define PA02 GPIO(GPIO_PORTA, 2) +#define PA12 GPIO(GPIO_PORTA, 12) +#define PA13 GPIO(GPIO_PORTA, 13) +#define PA14 GPIO(GPIO_PORTA, 14) +#define PA15 GPIO(GPIO_PORTA, 15) +#define PA17 GPIO(GPIO_PORTA, 17) +#define PA18 GPIO(GPIO_PORTA, 18) +#define PA19 GPIO(GPIO_PORTA, 19) #define PB12 GPIO(GPIO_PORTB, 12) #define PB13 GPIO(GPIO_PORTB, 13) #define PB24 GPIO(GPIO_PORTB, 24) #define PB25 GPIO(GPIO_PORTB, 25) +#define PC11 GPIO(GPIO_PORTC, 11) +#define PC12 GPIO(GPIO_PORTC, 12) #define LED0 GPIO(GPIO_PORTC, 18) +#define PC20 GPIO(GPIO_PORTC, 20) +#define PD08 GPIO(GPIO_PORTD, 8) +#define PD09 GPIO(GPIO_PORTD, 9) #endif // ATMEL_START_PINS_H_INCLUDED diff --git a/bsp/microchip/same54/bsp/config/hpl_adc_config.h b/bsp/microchip/same54/bsp/config/hpl_adc_config.h new file mode 100644 index 0000000000..bfd5296f46 --- /dev/null +++ b/bsp/microchip/same54/bsp/config/hpl_adc_config.h @@ -0,0 +1,302 @@ +/* Auto-generated config file hpl_adc_config.h */ +#ifndef HPL_ADC_CONFIG_H +#define HPL_ADC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#ifndef CONF_ADC_0_ENABLE +#define CONF_ADC_0_ENABLE 1 +#endif + +// Basic Configuration + +// Conversion Result Resolution +// <0x0=>12-bit +// <0x1=>16-bit (averaging must be enabled) +// <0x2=>10-bit +// <0x3=>8-bit +// Defines the bit resolution for the ADC sample values (RESSEL) +// adc_resolution +#ifndef CONF_ADC_0_RESSEL +#define CONF_ADC_0_RESSEL 0x1 +#endif + +// Reference Selection +// <0x0=>Internal bandgap reference +// <0x2=>1/2 VDDANA (only for VDDANA > 2.0V) +// <0x3=>VDDANA +// <0x4=>External reference A +// <0x5=>External reference B +// <0x6=>External reference C +// Select the reference for the ADC (REFSEL) +// adc_reference +#ifndef CONF_ADC_0_REFSEL +#define CONF_ADC_0_REFSEL 0x3 +#endif + +// Prescaler configuration +// <0x0=>Peripheral clock divided by 2 +// <0x1=>Peripheral clock divided by 4 +// <0x2=>Peripheral clock divided by 8 +// <0x3=>Peripheral clock divided by 16 +// <0x4=>Peripheral clock divided by 32 +// <0x5=>Peripheral clock divided by 64 +// <0x6=>Peripheral clock divided by 128 +// <0x7=>Peripheral clock divided by 256 +// These bits define the ADC clock relative to the peripheral clock (PRESCALER) +// adc_prescaler +#ifndef CONF_ADC_0_PRESCALER +#define CONF_ADC_0_PRESCALER 0x0 +#endif + +// Free Running Mode +// When enabled, the ADC is in free running mode and a new conversion will be initiated when a previous conversion completes. (FREERUN) +// adc_freerunning_mode +#ifndef CONF_ADC_0_FREERUN +#define CONF_ADC_0_FREERUN 0 +#endif + +// Differential Mode +// In differential mode, the voltage difference between the MUXPOS and MUXNEG inputs will be converted by the ADC. (DIFFMODE) +// adc_differential_mode +#ifndef CONF_ADC_0_DIFFMODE +#define CONF_ADC_0_DIFFMODE 0 +#endif + +// Positive Mux Input Selection +// <0x00=>ADC AIN0 pin +// <0x01=>ADC AIN1 pin +// <0x02=>ADC AIN2 pin +// <0x03=>ADC AIN3 pin +// <0x04=>ADC AIN4 pin +// <0x05=>ADC AIN5 pin +// <0x06=>ADC AIN6 pin +// <0x07=>ADC AIN7 pin +// <0x08=>ADC AIN8 pin +// <0x09=>ADC AIN9 pin +// <0x0A=>ADC AIN10 pin +// <0x0B=>ADC AIN11 pin +// <0x0C=>ADC AIN12 pin +// <0x0D=>ADC AIN13 pin +// <0x0E=>ADC AIN14 pin +// <0x0F=>ADC AIN15 pin +// <0x18=>1/4 scaled core supply +// <0x19=>1/4 Scaled VBAT Supply +// <0x1A=>1/4 scaled I/O supply +// <0x1B=>Bandgap voltage +// <0x1C=>Temperature reference (PTAT) +// <0x1D=>Temperature reference (CTAT) +// <0x1E=>DAC Output +// These bits define the Mux selection for the positive ADC input. (MUXPOS) +// adc_pinmux_positive +#ifndef CONF_ADC_0_MUXPOS +#define CONF_ADC_0_MUXPOS 0x0 +#endif + +// Negative Mux Input Selection +// <0x00=>ADC AIN0 pin +// <0x01=>ADC AIN1 pin +// <0x02=>ADC AIN2 pin +// <0x03=>ADC AIN3 pin +// <0x04=>ADC AIN4 pin +// <0x05=>ADC AIN5 pin +// <0x06=>ADC AIN6 pin +// <0x07=>ADC AIN7 pin +// <0x18=>Internal ground +// These bits define the Mux selection for the negative ADC input. (MUXNEG) +// adc_pinmux_negative +#ifndef CONF_ADC_0_MUXNEG +#define CONF_ADC_0_MUXNEG 0x18 +#endif + +// + +// Advanced Configuration +// adc_advanced_settings +#ifndef CONF_ADC_0_ADVANCED +#define CONF_ADC_0_ADVANCED 1 +#endif + +// Run in standby +// Indicates whether the ADC will continue running in standby sleep mode or not (RUNSTDBY) +// adc_arch_runstdby +#ifndef CONF_ADC_0_RUNSTDBY +#define CONF_ADC_0_RUNSTDBY 0 +#endif + +// Debug Run +// If enabled, the ADC is running if the CPU is halted by an external debugger. (DBGRUN) +// adc_arch_dbgrun +#ifndef CONF_ADC_0_DBGRUN +#define CONF_ADC_0_DBGRUN 0 +#endif + +// On Demand Control +// Will keep the ADC peripheral running if requested by other peripherals (ONDEMAND) +// adc_arch_ondemand +#ifndef CONF_ADC_0_ONDEMAND +#define CONF_ADC_0_ONDEMAND 0 +#endif + +// Left-Adjusted Result +// When enabled, the ADC conversion result is left-adjusted in the RESULT register. The high byte of the 12-bit result will be present in the upper part of the result register. (LEFTADJ) +// adc_arch_leftadj +#ifndef CONF_ADC_0_LEFTADJ +#define CONF_ADC_0_LEFTADJ 0 +#endif + +// Reference Buffer Offset Compensation Enable +// The accuracy of the gain stage can be increased by enabling the reference buffer offset compensation. This will decrease the input impedance and thus increase the start-up time of the reference. (REFCOMP) +// adc_arch_refcomp +#ifndef CONF_ADC_0_REFCOMP +#define CONF_ADC_0_REFCOMP 0 +#endif + +// Comparator Offset Compensation Enable +// This bit indicates whether the Comparator Offset Compensation is enabled or not (OFFCOMP) +// adc_arch_offcomp +#ifndef CONF_ADC_0_OFFCOMP +#define CONF_ADC_0_OFFCOMP 0 +#endif + +// Digital Correction Logic Enabled +// When enabled, the ADC conversion result in the RESULT register is then corrected for gain and offset based on the values in the GAINCAL and OFFSETCAL registers. (CORREN) +// adc_arch_corren +#ifndef CONF_ADC_0_CORREN +#define CONF_ADC_0_CORREN 0 +#endif + +// Offset Correction Value <0-4095> +// If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for offset error before being written to the Result register. (OFFSETCORR) +// adc_arch_offsetcorr +#ifndef CONF_ADC_0_OFFSETCORR +#define CONF_ADC_0_OFFSETCORR 0 +#endif + +// Gain Correction Value <0-4095> +// If the digital correction logic is enabled (CTRLB.CORREN = 1), these bits define how the ADC conversion result is compensated for gain error before being written to the result register. (GAINCORR) +// adc_arch_gaincorr +#ifndef CONF_ADC_0_GAINCORR +#define CONF_ADC_0_GAINCORR 0 +#endif + +// Adjusting Result / Division Coefficient <0-7> +// These bits define the division coefficient in 2n steps. (ADJRES) +// adc_arch_adjres +#ifndef CONF_ADC_0_ADJRES +#define CONF_ADC_0_ADJRES 0x0 +#endif + +// Number of Samples to be Collected +// <0x0=>1 sample +// <0x1=>2 samples +// <0x2=>4 samples +// <0x3=>8 samples +// <0x4=>16 samples +// <0x5=>32 samples +// <0x6=>64 samples +// <0x7=>128 samples +// <0x8=>256 samples +// <0x9=>512 samples +// <0xA=>1024 samples +// Define how many samples should be added together.The result will be available in the Result register (SAMPLENUM) +// adc_arch_samplenum +#ifndef CONF_ADC_0_SAMPLENUM +#define CONF_ADC_0_SAMPLENUM 0x2 +#endif + +// Sampling Time Length <0-63> +// These bits control the ADC sampling time in number of CLK_ADC cycles, depending of the prescaler value, thus controlling the ADC input impedance. (SAMPLEN) +// adc_arch_samplen +#ifndef CONF_ADC_0_SAMPLEN +#define CONF_ADC_0_SAMPLEN 2 +#endif + +// Window Monitor Mode +// <0x0=>No window mode +// <0x1=>Mode 1: RESULT above lower threshold +// <0x2=>Mode 2: RESULT beneath upper threshold +// <0x3=>Mode 3: RESULT inside lower and upper threshold +// <0x4=>Mode 4: RESULT outside lower and upper threshold +// These bits enable and define the window monitor mode. (WINMODE) +// adc_arch_winmode +#ifndef CONF_ADC_0_WINMODE +#define CONF_ADC_0_WINMODE 0x0 +#endif + +// Window Monitor Lower Threshold <0-65535> +// If the window monitor is enabled, these bits define the lower threshold value. (WINLT) +// adc_arch_winlt +#ifndef CONF_ADC_0_WINLT +#define CONF_ADC_0_WINLT 0 +#endif + +// Window Monitor Upper Threshold <0-65535> +// If the window monitor is enabled, these bits define the lower threshold value. (WINUT) +// adc_arch_winut +#ifndef CONF_ADC_0_WINUT +#define CONF_ADC_0_WINUT 0 +#endif + +// Bitmask for positive input sequence <0-4294967295> +// Use this parameter to input the bitmask for positive input sequence control (refer to datasheet for the device). +// adc_arch_seqen +#ifndef CONF_ADC_0_SEQEN +#define CONF_ADC_0_SEQEN 0x0 +#endif + +// + +// Event Control +// adc_arch_event_settings +#ifndef CONF_ADC_0_EVENT_CONTROL +#define CONF_ADC_0_EVENT_CONTROL 0 +#endif + +// Window Monitor Event Out +// Enables event output on window event (WINMONEO) +// adc_arch_winmoneo +#ifndef CONF_ADC_0_WINMONEO +#define CONF_ADC_0_WINMONEO 0 +#endif + +// Result Ready Event Out +// Enables event output on result ready event (RESRDEO) +// adc_arch_resrdyeo +#ifndef CONF_ADC_0_RESRDYEO +#define CONF_ADC_0_RESRDYEO 0 +#endif + +// Invert flush Event Signal +// Invert the flush event input signal (FLUSHINV) +// adc_arch_flushinv +#ifndef CONF_ADC_0_FLUSHINV +#define CONF_ADC_0_FLUSHINV 0 +#endif + +// Trigger Flush On Event +// Trigger an ADC pipeline flush on event (FLUSHEI) +// adc_arch_flushei +#ifndef CONF_ADC_0_FLUSHEI +#define CONF_ADC_0_FLUSHEI 0 +#endif + +// Invert Start Conversion Event Signal +// Invert the start conversion event input signal (STARTINV) +// adc_arch_startinv +#ifndef CONF_ADC_0_STARTINV +#define CONF_ADC_0_STARTINV 0 +#endif + +// Trigger Conversion On Event +// Trigger a conversion on event. (STARTEI) +// adc_arch_startei +#ifndef CONF_ADC_0_STARTEI +#define CONF_ADC_0_STARTEI 0 +#endif + +// + +// <<< end of configuration section >>> + +#endif // HPL_ADC_CONFIG_H diff --git a/bsp/microchip/same54/bsp/config/hpl_gmac_config.h b/bsp/microchip/same54/bsp/config/hpl_gmac_config.h new file mode 100644 index 0000000000..a1db387f2e --- /dev/null +++ b/bsp/microchip/same54/bsp/config/hpl_gmac_config.h @@ -0,0 +1,483 @@ +/* Auto-generated config file hpl_gmac_config.h */ +#ifndef HPL_GMAC_CONFIG_H +#define HPL_GMAC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include + +// Network Control configuration + +// Enable LoopBack Local +// Connects GTX to GRX, GTXEN to GRXDV and forces full duplex mode. +// gmac_arch_ncr_lbl +#ifndef CONF_GMAC_NCR_LBL +#define CONF_GMAC_NCR_LBL 0 +#endif + +// Management Port Enable +// Enable the Management port +// gmac_arch_ncr_mpe +#ifndef CONF_GMAC_NCR_MPE +#define CONF_GMAC_NCR_MPE 1 +#endif + +// Enable write for Static Register +// Make the statistics registers writable for functional test proposes. +// gmac_arch_ncr_westat +#ifndef CONF_GMAC_NCR_WESTAT +#define CONF_GMAC_NCR_WESTAT 0 +#endif + +// Enable Back pressure +// If set in 10M or 100M half duplex mode, forces collisions on all received frames. +// gmac_arch_ncr_bp +#ifndef CONF_GMAC_NCR_BP +#define CONF_GMAC_NCR_BP 0 +#endif + +// Enable PFC Priority-based Pause Reception +// Enables PFC negotiation and recognition of priority-based pause frames. +// gmac_arch_ncr_enpbpr +#ifndef CONF_GMAC_NCR_ENPBPR +#define CONF_GMAC_NCR_ENPBPR 0 +#endif + +// Enable PFC Priority-based Pause Frame +// Takes the values stored in the Transmit PFC Pause Register. +// gmac_arch_ncr_txpbpf +#ifndef CONF_GMAC_NCR_TXPBPF +#define CONF_GMAC_NCR_TXPBPF 0 +#endif + +// + +// Network Configuration + +// 100Mbps Speed +// Set to one to indicate 100 Mbps operation, zero for 10 Mbps. +// gmac_arch_ncfgr_spd +#ifndef CONF_GMAC_NCFGR_SPD +#define CONF_GMAC_NCFGR_SPD 1 +#endif + +// Enable Full Duplex +// Enable Full duplex +// gmac_arch_ncfgr_df +#ifndef CONF_GMAC_NCFGR_FD +#define CONF_GMAC_NCFGR_FD 1 +#endif + +// Discard Non-VLAN Frames +// Discard Non-VLAN Frames +// gmac_arch_ncfgr_dnvlan +#ifndef CONF_GMAC_NCFGR_DNVLAN +#define CONF_GMAC_NCFGR_DNVLAN 0 +#endif + +// Enable Jumbo Frame +// Enable jumbo frames up to 10240 bytes to be accepted. +// gmac_arch_ncfgr_jframe +#ifndef CONF_GMAC_NCFGR_JFRAME +#define CONF_GMAC_NCFGR_JFRAME 0 +#endif + +// Copy All Frames +// All valid frames will be accepted +// gmac_arch_ncfgr_caf +#ifndef CONF_GMAC_NCFGR_CAF +#define CONF_GMAC_NCFGR_CAF 0 +#endif + +// No broadcast +// Frames addressed to the broadcast address of all ones will not be accepted. +// gmac_arch_ncfgr_nbc +#ifndef CONF_GMAC_NCFGR_NBC +#define CONF_GMAC_NCFGR_NBC 0 +#endif + +// Multicast Hash Enable +// Multicast frames will be accepted when the 6-bit hash function of the destination address points to a bit that is set in the Hash Register. +// gmac_arch_ncfgr_mtihen +#ifndef CONF_GMAC_NCFGR_MTIHEN +#define CONF_GMAC_NCFGR_MTIHEN 0 +#endif + +// Unicast Hash Enable +// Unicast frames will be accepted when the 6-bit hash function of the destination address points to a bit that is set in the Hash Register. +// gmac_arch_ncfgr_unihen +#ifndef CONF_GMAC_NCFGR_UNIHEN +#define CONF_GMAC_NCFGR_UNIHEN 0 +#endif + +// 1536 Maximum Frame Size +// Accept frames up to 1536 bytes in length. +// gmac_arch_ncfgr_maxfs +#ifndef CONF_GMAC_NCFGR_MAXFS +#define CONF_GMAC_NCFGR_MAXFS 1 +#endif + +// Retry Test +// Must be set to zero for normal operation. If set to one the backoff +// between collisions will always be one slot time. Setting this bit to +// one helps test the too many retries condition. Also used in the pause +// frame tests to reduce the pause counter's decrement time from 512 bit +// times, to every GRXCK cycle. +// gmac_arch_ncfgr_rty +#ifndef CONF_GMAC_NCFGR_RTY +#define CONF_GMAC_NCFGR_RTY 0 +#endif + +// Pause Enable +// When set, transmission will pause if a non-zero 802.3 classic pause +// frame is received and PFC has not been negotiated +// gmac_arch_ncfgr_pen +#ifndef CONF_GMAC_NCFGR_PEN +#define CONF_GMAC_NCFGR_PEN 0 +#endif + +// Receive Buffer Offset <0-3> +// Indicates the number of bytes by which the received data is offset from +// the start of the receive buffer. +// gmac_arch_ncfgr_rxbufo +#ifndef CONF_GMAC_NCFGR_RXBUFO +#define CONF_GMAC_NCFGR_RXBUFO 0 +#endif + +// Length Field Error Frame Discard +// Setting this bit causes frames with a measured length shorter than the +// extracted length field (as indicated by bytes 13 and 14 in a non-VLAN +// tagged frame) to be discarded. This only applies to frames with a length +// field less than 0x0600. +// gmac_arch_ncfgr_lferd +#ifndef CONF_GMAC_NCFGR_LFERD +#define CONF_GMAC_NCFGR_LFERD 0 +#endif + +// Remove FCS +// Setting this bit will cause received frames to be written to memory +// without their frame check sequence (last 4 bytes). The frame length +// indicated will be reduced by four bytes in this mode. +// gmac_arch_ncfgr_rfcs +#ifndef CONF_GMAC_NCFGR_RFCS +#define CONF_GMAC_NCFGR_RFCS 0 +#endif + +// MDC Clock Division +// Set according to MCK speed. These three bits determine the number MCK +// will be divided by to generate Management Data Clock (MDC). For +// conformance with the 802.3 specification, MDC must not exceed 2.5 MHz +// (MDC is only active during MDIO read and write operations). +// <0=> 8 +// <1=> 16 +// <2=> 32 +// <3=> 48 +// <4=> 64 +// <5=> 96 +// gmac_arch_ncfgr_clk +#ifndef CONF_GMAC_NCFGR_CLK +#define CONF_GMAC_NCFGR_CLK 4 +#endif + +/** + * For conformance with the 802.3 specification, MDC must not exceed 2.5 MHz + **/ +#ifndef CONF_GMAC_MCK_FREQUENCY +#if CONF_GMAC_NCFGR_CLK == 0 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 8) +#elif CONF_GMAC_NCFGR_CLK == 1 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 16) +#elif CONF_GMAC_NCFGR_CLK == 2 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 32) +#elif CONF_GMAC_NCFGR_CLK == 3 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 48) +#elif CONF_GMAC_NCFGR_CLK == 4 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 64) +#elif CONF_GMAC_NCFGR_CLK == 5 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 96) +#endif +#endif + +#if CONF_GMAC_MCK_FREQUENCY > 2500000 +#warning For conformance with the 802.3 specification, MDC must not exceed 2.5 MHz +#endif +// Disable Copy of Pause Frames +// Set to one to prevent valid pause frames being copied to memory. When +// set, pause frames are not copied to memory regardless of the state of +// the Copy All Frames bit, whether a hash match is found or whether a +// type ID match is identified. If a destination address match is found, +// the pause frame will be copied to memory. Note that valid pause frames +// received will still increment pause statistics and pause the +// transmission of frames as required. +// gmac_arch_ncfgr_dcpf +#ifndef CONF_GMAC_NCFGR_DCPF +#define CONF_GMAC_NCFGR_DCPF 0 +#endif + +// Receive Checksum Offload Enable +// When set, the receive checksum engine is enabled. Frames with bad IP, +// TCP or UDP checksums are discarded. +// gmac_arch_ncfgr_rxcoen +#ifndef CONF_GMAC_NCFGR_RXCOEN +#define CONF_GMAC_NCFGR_RXCOEN 0 +#endif + +// Enable Frames Received in Half Duplex +// Enable frames to be received in half-duplex mode while transmittinga. +// gmac_arch_ncfgr_efrhd +#ifndef CONF_GMAC_NCFGR_EFRHD +#define CONF_GMAC_NCFGR_EFRHD 0 +#endif + +// Ignore RX FCS +// When set, frames with FCS/CRC errors will not be rejected. FCS error +// statistics will still be collected for frames with bad FCS and FCS +// status will be recorded in frame's DMA descriptor. For normal operation +// this bit must be set to zero. +// gmac_arch_ncfgr_irxfcs +#ifndef CONF_GMAC_NCFGR_IRXFCS +#define CONF_GMAC_NCFGR_IRXFCS 0 +#endif + +// IP Stretch Enable +// When set, the transmit IPG can be increased above 96 bit times depending +// on the previous frame length using the IPG Stretch Register. +// gmac_arch_ncfgr_ipgsen +#ifndef CONF_GMAC_NCFGR_IPGSEN +#define CONF_GMAC_NCFGR_IPGSEN 0 +#endif + +// Receive Bad Preamble +// When set, frames with non-standard preamble are not rejected. +// gmac_arch_ncfgr_rxbp +#ifndef CONF_GMAC_NCFGR_RXBP +#define CONF_GMAC_NCFGR_RXBP 0 +#endif + +// Ignore IPG GRXER +// When set, GRXER has no effect on the GMAC's operation when GRXDV is low. +// gmac_arch_ncfgr_irxer +#ifndef CONF_GMAC_NCFGR_IRXER +#define CONF_GMAC_NCFGR_IRXER 0 +#endif + +// + +// MII Configuration +// gmac_arch_mii_cfg + +// MII Mode +// Select MII or RMII mode +// <0=> RMII +// <1=> MII +// gmac_arch_ur_mii +#ifndef CONF_GMAC_ur_mii +#define CONF_GMAC_UR_MII 0 +#endif + +// PHY Clause Operation +// Chose which Clause operation will be used +// <0=>Clause 45 Operation +// <1=>Clause 22 Operation +// gmac_arch_cltto +#ifndef CONF_GMAC_CLTTO +#define CONF_GMAC_CLTTO 1 +#endif + +// + +// Stacked VLAN Processing +// When enabled, the first VLAN tag in a received frame will only be +// accepted if the VLAN type field is equal to the User defined VLAN Type, +// OR equal to the standard VLAN type (0x8100). Note that the second VLAN +// tag of a Stacked VLAN packet will only be matched correctly if its +// VLAN_TYPE field equals 0x8100. +// gmac_arch_svlan_enable +#ifndef CONF_GMAC_SVLAN_ENABLE +#define CONF_GMAC_SVLAN_ENABLE 0 +#endif + +// User Defined VLAN Type <0x0-0xFFFF> +// User defined VLAN TYPE +// gmac_arch_svlan_type +#ifndef CONF_GMAC_SVLAN_TYPE +#define CONF_GMAC_SVLAN_TYPE 0x8100 +#endif +// + +// DMA Configuration +// The GMAC DMA controller is connected to the MAC FIFO interface and +// provides a scatter-gather type capability for packet data storage. +// The DMA implements packet buffering where dual-port memories are used +// to buffer multiple frames. +// gmac_arch_dma_cfg +#ifndef CONF_GMAC_DMA_CFG +#define CONF_GMAC_DMACFG 1 +#endif + +// Fixed Burst Length for DMA Data Operations +// Selects the burst length to attempt to use on the AHB when transferring +// frame data. Not used for DMA management operations and only used where +// space and data size allow. Otherwise SINGLE type AHB transfers are used. +// <1=> Always use SINGLE AHB bursts +// <4=> Always use INCR4 AHB bursts +// <8=> Always use INCR8 AHB bursts +// <16=> Always use INCR16 AHB bursts +// gmac_arch_dcfgr_fbldo +#ifndef CONF_GMAC_DCFGR_FBLDO +#define CONF_GMAC_DCFGR_FBLDO 4 +#endif + +// Endian Swap Mode Enable for Management Descriptor Accesses +// When set, selects swapped endianism for AHB transfers. When clear, +// selects little endian mode. +// gmac_arch_dcfgr_esma +#ifndef CONF_GMAC_DCFGR_ESMA +#define CONF_GMAC_DCFGR_ESMA 0 +#endif + +// Endian Swap Mode Enable for Packet Data Accesses +// When set, selects swapped endianism for AHB transfers. When clear, +// selects little endian mode. +// gmac_arch_dcfgr_espa +#ifndef CONF_GMAC_DCFGR_ESPA +#define CONF_GMAC_DCFGR_ESPA 0 +#endif + +// Receiver Packet Buffer Memory Size Select +// Select the receive packet buffer size +// <0=> 0.5 Kbytes +// <1=> 1 Kbytes +// <2=> 2 Kbytes +// <3=> 4 Kbytes +// gmac_arch_dcfgr_rxbms +#ifndef CONF_GMAC_DCFGR_RXBMS +#define CONF_GMAC_DCFGR_RXBMS 3 +#endif + +// Transmitter Packet Buffer Memory Size Select +// Select the Transmitter packet buffer size +// <0=> 2 Kbytes +// <1=> 4 Kbytes +// gmac_arch_dcfgr_txpbms +#ifndef CONF_GMAC_DCFGR_TXPBMS +#define CONF_GMAC_DCFGR_TXPBMS 1 +#endif + +// Transmitter Checksum Generation Offload Enable +// Transmitter IP, TCP and UDP checksum generation offload enable. When +// set, the transmitter checksum generation engine is enabled to calculate +// and substitute checksums for transmit frames. When clear, frame data is +// unaffected +// gmac_arch_dcfgr_txcoen +#ifndef CONF_GMAC_DCFGR_TXCOEN +#define CONF_GMAC_DCFGR_TXCOEN 0 +#endif + +// DMA Receive Buffer Size <1-255> +// DMA receive buffer size in AHB system memory. The value defined by these +// bits determines the size of buffer to use in main AHB system memory when +// writing received data. The value is defined in multiples of 64 bytes, +// thus a value of 0x01 corresponds to buffers of 64 bytes, 0x02 +// corresponds to 128 bytes etc. +// gmac_arch_dcfgr_drbs +#ifndef CONF_GMAC_DCFGR_DRBS +#define CONF_GMAC_DCFGR_DRBS 2 +#endif + +// DMA Discard Received Packets +// When set, the GMAC DMA will automatically discard receive packets from +// the receiver packet buffer memory when no AHB resource is available. +// When low, the received packets will remain to be stored in the SRAM +// based packet buffer until AHB buffer resource next becomes available. +// Note: packet buffer full store and forward mode should be enabled. +// gmac_arch_dcfgr_ddrp +#ifndef CONF_GMAC_DCFGR_DDRP +#define CONF_GMAC_DCFGR_DDRP 0 +#endif +// + +// Advanced configuration +// gmac_arch_adv_cfg +#ifndef CONF_GMAC_ADV_CFG +#define CONF_GMAC_ADV_CFG 1 +#endif + +// Number of Transmit Buffer Descriptor <1-255> +// Number of Transmit Buffer Descriptor +// gmac_arch_txdescr_num +#ifndef CONF_GMAC_TXDESCR_NUM +#define CONF_GMAC_TXDESCR_NUM 2 +#endif + +// Number of Receive Buffer Descriptor <1-255> +// Number of Receive Buffer Descriptor +// gmac_arch_rxdescr_num +#ifndef CONF_GMAC_RXDESCR_NUM +#define CONF_GMAC_RXDESCR_NUM 16 +#endif + +// Byte size of Transmit Buffer <64-10240> +// Byte size of buffer for each transmit buffer descriptor. +// gmac_arch_txbuf_size +#ifndef CONF_GMAC_TXBUF_SIZE +#define CONF_GMAC_TXBUF_SIZE 1500 +#endif + +#ifndef CONF_GMAC_RXBUF_SIZE +#define CONF_GMAC_RXBUF_SIZE (CONF_GMAC_DCFGR_DRBS * 64) +#endif + +// Enable Transmit Partial Store and Forward +// This allows for a reduced latency but there are performance implications. +// gmac_arch_tpsf_en +#ifndef CONF_GMAC_TPSF_EN +#define CONF_GMAC_TPSF_EN 0 +#endif + +// Watermark <20-4095> +// Byte size of buffer for each transmit buffer descriptor. +// gmac_arch_tpsf_wm +#ifndef CONF_GMAC_TPSF_WM +#define CONF_GMAC_TPSF_WM 100 +#endif +// + +// Enable Receive Partial Store and Forward +// This allows for a reduced latency but there are performance implications. +// gmac_arch_rpsf_en +#ifndef CONF_GMAC_RPSF_EN +#define CONF_GMAC_RPSF_EN 0 +#endif + +// Watermark <20-4095> +// Byte size of buffer for each transmite buffer descriptor. +// gmac_arch_rpsf_wm +#ifndef CONF_GMAC_RPSF_WM +#define CONF_GMAC_RPSF_WM 100 +#endif + +// IPG Stretch Multiple <0-15> +// This value will multiplied with the previously transmitted frame length +// (including preamble) +// gmac_arch_ipgs_fl_mul +#ifndef CONF_GMAC_IPGS_FL_MUL +#define CONF_GMAC_IPGS_FL_MUL 1 +#endif + +// IPG Stretch Divide <1-16> +// Divide the frame length. If the resulting number is greater than 96 and +// IP Stretch Enabled then the resulting number is used for the transmit +// inter-packet-gap +// gmac_arch_ipgs_fl_div +#ifndef CONF_GMAC_IPGS_FL_DIV +#define CONF_GMAC_IPGS_FL_DIV 1 +#endif + +// + +// + +// <<< end of configuration section >>> + +#endif // HPL_GMAC_CONFIG_H diff --git a/bsp/microchip/same54/bsp/config/hpl_sercom_config.h b/bsp/microchip/same54/bsp/config/hpl_sercom_config.h index c5ccfe82d1..3ed890eb82 100644 --- a/bsp/microchip/same54/bsp/config/hpl_sercom_config.h +++ b/bsp/microchip/same54/bsp/config/hpl_sercom_config.h @@ -69,7 +69,7 @@ // Advanced configuration // usart_advanced #ifndef CONF_SERCOM_2_USART_ADVANCED_CONFIG -#define CONF_SERCOM_2_USART_ADVANCED_CONFIG 0 +#define CONF_SERCOM_2_USART_ADVANCED_CONFIG 1 #endif // Run in stand-by @@ -273,6 +273,141 @@ #endif #endif +#include + +#ifndef SERCOM_I2CM_CTRLA_MODE_I2C_MASTER +#define SERCOM_I2CM_CTRLA_MODE_I2C_MASTER (5 << 2) +#endif + +#ifndef CONF_SERCOM_7_I2CM_ENABLE +#define CONF_SERCOM_7_I2CM_ENABLE 1 +#endif + +// Basic + +// I2C Bus clock speed (Hz) <1-400000> +// I2C Bus clock (SCL) speed measured in Hz +// i2c_master_baud_rate +#ifndef CONF_SERCOM_7_I2CM_BAUD +#define CONF_SERCOM_7_I2CM_BAUD 100000 +#endif + +// + +// Advanced +// i2c_master_advanced +#ifndef CONF_SERCOM_7_I2CM_ADVANCED_CONFIG +#define CONF_SERCOM_7_I2CM_ADVANCED_CONFIG 1 +#endif + +// TRise (ns) <0-300> +// Determined by the bus impedance, check electric characteristics in the datasheet +// Standard Fast Mode: typical 215ns, max 300ns +// Fast Mode +: typical 60ns, max 100ns +// High Speed Mode: typical 20ns, max 40ns +// i2c_master_arch_trise + +#ifndef CONF_SERCOM_7_I2CM_TRISE +#define CONF_SERCOM_7_I2CM_TRISE 215 +#endif + +// Master SCL Low Extended Time-Out (MEXTTOEN) +// This enables the master SCL low extend time-out +// i2c_master_arch_mexttoen +#ifndef CONF_SERCOM_7_I2CM_MEXTTOEN +#define CONF_SERCOM_7_I2CM_MEXTTOEN 1 +#endif + +// Slave SCL Low Extend Time-Out (SEXTTOEN) +// Enables the slave SCL low extend time-out. If SCL is cumulatively held low for greater than 25ms from the initial START to a STOP, the slave will release its clock hold if enabled and reset the internal state machine +// i2c_master_arch_sexttoen +#ifndef CONF_SERCOM_7_I2CM_SEXTTOEN +#define CONF_SERCOM_7_I2CM_SEXTTOEN 0 +#endif + +// SCL Low Time-Out (LOWTOUT) +// Enables SCL low time-out. If SCL is held low for 25ms-35ms, the master will release it's clock hold +// i2c_master_arch_lowtout +#ifndef CONF_SERCOM_7_I2CM_LOWTOUT +#define CONF_SERCOM_7_I2CM_LOWTOUT 1 +#endif + +// Inactive Time-Out (INACTOUT) +// <0x0=>Disabled +// <0x1=>5-6 SCL cycle time-out(50-60us) +// <0x2=>10-11 SCL cycle time-out(100-110us) +// <0x3=>20-21 SCL cycle time-out(200-210us) +// Defines if inactivity time-out should be enabled, and how long the time-out should be +// i2c_master_arch_inactout +#ifndef CONF_SERCOM_7_I2CM_INACTOUT +#define CONF_SERCOM_7_I2CM_INACTOUT 0x3 +#endif + +// SDA Hold Time (SDAHOLD) +// <0=>Disabled +// <1=>50-100ns hold time +// <2=>300-600ns hold time +// <3=>400-800ns hold time +// Defines the SDA hold time with respect to the negative edge of SCL +// i2c_master_arch_sdahold +#ifndef CONF_SERCOM_7_I2CM_SDAHOLD +#define CONF_SERCOM_7_I2CM_SDAHOLD 0x2 +#endif + +// Run in stand-by +// Determine if the module shall run in standby sleep mode +// i2c_master_arch_runstdby +#ifndef CONF_SERCOM_7_I2CM_RUNSTDBY +#define CONF_SERCOM_7_I2CM_RUNSTDBY 0 +#endif + +// Debug Stop Mode +// Behavior of the baud-rate generator when CPU is halted by external debugger. +// <0=>Keep running +// <1=>Halt +// i2c_master_arch_dbgstop +#ifndef CONF_SERCOM_7_I2CM_DEBUG_STOP_MODE +#define CONF_SERCOM_7_I2CM_DEBUG_STOP_MODE 0 +#endif + +// + +#ifndef CONF_SERCOM_7_I2CM_SPEED +#define CONF_SERCOM_7_I2CM_SPEED 0x00 // Speed: Standard/Fast mode +#endif +#if CONF_SERCOM_7_I2CM_TRISE < 215 || CONF_SERCOM_7_I2CM_TRISE > 300 +#warning Bad I2C Rise time for Standard/Fast mode, reset to 215ns +#undef CONF_SERCOM_7_I2CM_TRISE +#define CONF_SERCOM_7_I2CM_TRISE 215U +#endif + +// gclk_freq - (i2c_scl_freq * 10) - (gclk_freq * i2c_scl_freq * Trise) +// BAUD + BAUDLOW = -------------------------------------------------------------------- +// i2c_scl_freq +// BAUD: register value low [7:0] +// BAUDLOW: register value high [15:8], only used for odd BAUD + BAUDLOW +#define CONF_SERCOM_7_I2CM_BAUD_BAUDLOW \ + (((CONF_GCLK_SERCOM7_CORE_FREQUENCY - (CONF_SERCOM_7_I2CM_BAUD * 10U) \ + - (CONF_SERCOM_7_I2CM_TRISE * (CONF_SERCOM_7_I2CM_BAUD / 100U) * (CONF_GCLK_SERCOM7_CORE_FREQUENCY / 10000U) \ + / 1000U)) \ + * 10U \ + + 5U) \ + / (CONF_SERCOM_7_I2CM_BAUD * 10U)) +#ifndef CONF_SERCOM_7_I2CM_BAUD_RATE +#if CONF_SERCOM_7_I2CM_BAUD_BAUDLOW > (0xFF * 2) +#warning Requested I2C baudrate too low, please check +#define CONF_SERCOM_7_I2CM_BAUD_RATE 0xFF +#elif CONF_SERCOM_7_I2CM_BAUD_BAUDLOW <= 1 +#warning Requested I2C baudrate too high, please check +#define CONF_SERCOM_7_I2CM_BAUD_RATE 1 +#else +#define CONF_SERCOM_7_I2CM_BAUD_RATE \ + ((CONF_SERCOM_7_I2CM_BAUD_BAUDLOW & 0x1) \ + ? (CONF_SERCOM_7_I2CM_BAUD_BAUDLOW / 2) + ((CONF_SERCOM_7_I2CM_BAUD_BAUDLOW / 2 + 1) << 8) \ + : (CONF_SERCOM_7_I2CM_BAUD_BAUDLOW / 2)) +#endif +#endif + // <<< end of configuration section >>> #endif // HPL_SERCOM_CONFIG_H diff --git a/bsp/microchip/same54/bsp/config/ieee8023_mii_standard_config.h b/bsp/microchip/same54/bsp/config/ieee8023_mii_standard_config.h new file mode 100644 index 0000000000..e60cd8a250 --- /dev/null +++ b/bsp/microchip/same54/bsp/config/ieee8023_mii_standard_config.h @@ -0,0 +1,106 @@ +/* Auto-generated config file ieee8023_mii_standard_config.h */ +#ifndef IEEE8023_MII_STANDARD_CONFIG_H +#define IEEE8023_MII_STANDARD_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +// Basic configuration + +// PHY Address <0-31> +// The PHY Address is five bits, allowing 32 unique PHY addresses. A PHY +// that is connected to the station management entity via the mechanical +// interface defined in IEEE 802.3 22.6 shall always respond to +// transactions addressed to PHY Address zero b00000. A station management +// entity that is attached to multiple PHYs must have prior knowledge of +// the appropriate PHY Address for each PHY. +// ieee8023_mii_phy_address +#ifndef CONF_MACIF_PHY_IEEE8023_MII_PHY_ADDRESS +#define CONF_MACIF_PHY_IEEE8023_MII_PHY_ADDRESS 0 +#endif + +// + +// Control Register (Register 0) Settings +// The MII Management Interface Control Register (Register 0) Setting. +// Full details about the can be found in Clause 22.2.4 of the IEEE 802.3 +// Specification. +// ieee8023_mii_control_reg0_setting +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING 1 +#endif + +// Loopback Enable +// Set PHY be placed in a loopback mode of operation. +// ieee8023_mii_control_loopback_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_LOOPBACK_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_LOOPBACK_EN 0 +#endif + +// Speed Selection +// These bits select the PHY speed. +// <0x0=> 10 Mb/s +// <0x1=> 100 Mb/s +// <0x2=> 1000 Mb/s +// ieee8023_mii_control_speed_lsb +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED 1 +#endif + +// Auto-Negotiation Enable +// Indicates whether the Auto-Negotiation enable or not +// ieee8023_mii_control_autoneg_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_AUTONEG_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_AUTONEG_EN 1 +#endif + +// Power Down Enable +// Set PHY in a low-power consumption state, The specific behavior of a +// PHY in the power-down state is implementation specific. While in the +// power-down state, the PHY shall respond to management transactions. +// During the transition to the power-down state and while in the +// power-down state, the PHY shall not generate spurious signals on the +// MII or GMII. +// ieee8023_mii_control_powerdown_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_POWER_DOWN_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_POWER_DOWN_EN 0 +#endif + +// Isolate Enable +// Set PHY forced to electrically isolate its data paths from the MII or +// GMII. When the PHY is isolated from the MII or GMII it shall not +// respond to the TXD data bundle, TX_EN, TX_ER and GTX_CLK inputs, and it +// shall present a high impedance on its TX_CLK, RX_CLK, RX_DV, RX_ER, RXD +// data bundle, COL, and CRS outputs. When the PHY is isolated from the +// MII or GMII it shall respond to management transactions. +// ieee8023_mii_control_isolate_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_ISOLATE_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_ISOLATE_EN 0 +#endif + +// Duplex Mode Selection +// The duplex mode can be selected via either the Auto-Negotiation enable, +// or manual duplex selection. Manual duplex selection is allowed when +// Auto-Negotiation is disabled. When Auto-Negotiation is enabled, this +// setting has no effect on the link configuration. +// <0x0=> half duplex +// <0x1=> full duplex +// ieee8023_mii_control_duplex_mode +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_DUPLEX_MODE +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_DUPLEX_MODE 1 +#endif + +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0 +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0 \ + (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_LOOPBACK_EN ? MDIO_REG0_BIT_RESET : 0) \ + | ((CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED & 0x1) ? MDIO_REG0_BIT_SPEED_SELECT_LSB : 0) \ + | ((CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED & 0x2) ? MDIO_REG0_BIT_SPEED_SELECT_MSB : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_AUTONEG_EN ? MDIO_REG0_BIT_AUTONEG : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_POWER_DOWN_EN ? MDIO_REG0_BIT_POWER_DOWN : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_ISOLATE_EN ? MDIO_REG0_BIT_ISOLATE : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_DUPLEX_MODE ? MDIO_REG0_BIT_DUPLEX_MODE : 0) +#endif +// + +// <<< end of configuration section >>> + +#endif // IEEE8023_MII_STANDARD_CONFIG_H diff --git a/bsp/microchip/same54/bsp/config/peripheral_clk_config.h b/bsp/microchip/same54/bsp/config/peripheral_clk_config.h index 46f79b4eb0..1a84e935c5 100644 --- a/bsp/microchip/same54/bsp/config/peripheral_clk_config.h +++ b/bsp/microchip/same54/bsp/config/peripheral_clk_config.h @@ -4,6 +4,46 @@ // <<< Use Configuration Wizard in Context Menu >>> +// ADC Clock Source +// adc_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + +// Select the clock source for ADC. +#ifndef CONF_GCLK_ADC0_SRC +#define CONF_GCLK_ADC0_SRC GCLK_PCHCTRL_GEN_GCLK0_Val +#endif + +/** + * \def CONF_GCLK_ADC0_FREQUENCY + * \brief ADC0's Clock frequency + */ +#ifndef CONF_GCLK_ADC0_FREQUENCY +#define CONF_GCLK_ADC0_FREQUENCY 120000000 +#endif + /** * \def CONF_CPU_FREQUENCY * \brief CPU's Clock frequency @@ -92,6 +132,86 @@ #define CONF_GCLK_SERCOM2_SLOW_FREQUENCY 3000000 #endif +// Core Clock Source +// core_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + +// Select the clock source for CORE. +#ifndef CONF_GCLK_SERCOM7_CORE_SRC +#define CONF_GCLK_SERCOM7_CORE_SRC GCLK_PCHCTRL_GEN_GCLK3_Val +#endif + +// Slow Clock Source +// slow_gclk_selection + +// Generic clock generator 0 + +// Generic clock generator 1 + +// Generic clock generator 2 + +// Generic clock generator 3 + +// Generic clock generator 4 + +// Generic clock generator 5 + +// Generic clock generator 6 + +// Generic clock generator 7 + +// Generic clock generator 8 + +// Generic clock generator 9 + +// Generic clock generator 10 + +// Generic clock generator 11 + +// Select the slow clock source. +#ifndef CONF_GCLK_SERCOM7_SLOW_SRC +#define CONF_GCLK_SERCOM7_SLOW_SRC GCLK_PCHCTRL_GEN_GCLK1_Val +#endif + +/** + * \def CONF_GCLK_SERCOM7_CORE_FREQUENCY + * \brief SERCOM7's Core Clock frequency + */ +#ifndef CONF_GCLK_SERCOM7_CORE_FREQUENCY +#define CONF_GCLK_SERCOM7_CORE_FREQUENCY 40000000 +#endif + +/** + * \def CONF_GCLK_SERCOM7_SLOW_FREQUENCY + * \brief SERCOM7's Slow Clock frequency + */ +#ifndef CONF_GCLK_SERCOM7_SLOW_FREQUENCY +#define CONF_GCLK_SERCOM7_SLOW_FREQUENCY 3000000 +#endif + // CAN1 Clock Source // can_gclk_selection diff --git a/bsp/microchip/same54/bsp/documentation/ethernet_phy.rst b/bsp/microchip/same54/bsp/documentation/ethernet_phy.rst new file mode 100644 index 0000000000..b8bfcf20fa --- /dev/null +++ b/bsp/microchip/same54/bsp/documentation/ethernet_phy.rst @@ -0,0 +1,56 @@ +====================================== +Generic IEEE 802.3 Ethernet PHY Driver +====================================== + +This software component supply a generic IEEE802.3 Ethernet PHY driver. +The PHY chip should be compliant IEEE 802.3 Ethernet Standard that +supports MDC/MDIO management interface for PHY register configuration. + +The management interface specified here provides a simple, two-wire, serial +interface to connect a management entity and a managed PHY for the purposes of +controlling the PHY and gathering status from the PHY. This interface is +referred to as the MII Management Interface. + +The management interface consists of a pair of signals that physically +transport the management information across the MII or GMII, a frame format +and a protocol specification for exchanging management frames, and a register +set that can be read and written using these frames. The register definition +specifies a basic register set with an extension mechanism. The MII uses two +basic registers. The GMII also uses the same two basic registers and adds a +third basic register. + +The MII basic register set consists of two registers referred to as the Control +register (Register 0) and the Status register (Register 1). All PHYs that +provide an MII shall incorporate the basic register set. All PHYs that provide +a GMII shall incorporate an extended basic register set consisting of the +Control register (Register 0), Status register (Register 1), and Extended +Status register (Register 15). The status and control functions defined here +are considered basic and fundamental to 100 Mb/s and 1000 Mb/s PHYs. +Registers 2 through 14 are part of the extended register set. The format of +Registers 4 through 10 are defined for the specific Auto-Negotiation protocol +used (Clause 28 or Clause 37). The format of these registers is selected by +the bit settings of Registers 1 and 15. +More information please refer to IEEE Std 802.3 Chapter 22.2.4 + +Features +-------- + +* Initialization the Ethernet PHY driver with Ethernet MAC communication +* Setting PHY address +* Reading/Writing register from PHY device +* Setting/Clearing register bit from PHY device +* Enabling/Disabling Power Down +* Restart Auto Negotiation +* Enabling/Disabling Loop Back +* Getting Link Status +* Reset PHY device + +Dependencies +------------ + +* An instance of the Ethernet MAC driver is used by this driver. + +Limitations +----------- + +N/A diff --git a/bsp/microchip/same54/bsp/driver_init.c b/bsp/microchip/same54/bsp/driver_init.c index b44c15af7a..7fb7edce2d 100644 --- a/bsp/microchip/same54/bsp/driver_init.c +++ b/bsp/microchip/same54/bsp/driver_init.c @@ -11,10 +11,44 @@ #include #include -struct aes_sync_descriptor CRYPTOGRAPHY_0; -struct can_async_descriptor CAN_0; +#include -struct usart_sync_descriptor TARGET_IO; +/*! The buffer size for USART */ +#define TARGET_IO_BUFFER_SIZE 16 + +struct aes_sync_descriptor CRYPTOGRAPHY_0; +struct usart_async_descriptor TARGET_IO; +struct can_async_descriptor CAN_0; + +static uint8_t TARGET_IO_buffer[TARGET_IO_BUFFER_SIZE]; + +struct adc_sync_descriptor ADC_0; + +struct i2c_m_sync_desc I2C_0; + +struct mac_async_descriptor MACIF; + +void ADC_0_PORT_init(void) +{ + + // Disable digital pin circuitry + gpio_set_pin_direction(PA02, GPIO_DIRECTION_OFF); + + gpio_set_pin_function(PA02, PINMUX_PA02B_ADC0_AIN0); +} + +void ADC_0_CLOCK_init(void) +{ + hri_mclk_set_APBDMASK_ADC0_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, ADC0_GCLK_ID, CONF_GCLK_ADC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); +} + +void ADC_0_init(void) +{ + ADC_0_CLOCK_init(); + ADC_0_PORT_init(); + adc_sync_init(&ADC_0, ADC0, (void *)NULL); +} /** * \brief AES initialization function @@ -27,29 +61,84 @@ void CRYPTOGRAPHY_0_init(void) aes_sync_init(&CRYPTOGRAPHY_0, AES); } -void TARGET_IO_PORT_init(void) +/** + * \brief USART Clock initialization function + * + * Enables register interface and peripheral clock + */ +void TARGET_IO_CLOCK_init() { - gpio_set_pin_function(PB25, PINMUX_PB25D_SERCOM2_PAD0); + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); - gpio_set_pin_function(PB24, PINMUX_PB24D_SERCOM2_PAD1); + hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK); } -void TARGET_IO_CLOCK_init(void) +/** + * \brief USART pinmux initialization function + * + * Set each required pin to USART functionality + */ +void TARGET_IO_PORT_init() { - hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_CORE, CONF_GCLK_SERCOM2_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); - hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM2_GCLK_ID_SLOW, CONF_GCLK_SERCOM2_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); - hri_mclk_set_APBBMASK_SERCOM2_bit(MCLK); + gpio_set_pin_function(PB25, PINMUX_PB25D_SERCOM2_PAD0); + + gpio_set_pin_function(PB24, PINMUX_PB24D_SERCOM2_PAD1); } +/** + * \brief USART initialization function + * + * Enables USART peripheral, clocks and initializes USART driver + */ void TARGET_IO_init(void) { TARGET_IO_CLOCK_init(); - usart_sync_init(&TARGET_IO, SERCOM2, (void *)NULL); + usart_async_init(&TARGET_IO, SERCOM2, TARGET_IO_buffer, TARGET_IO_BUFFER_SIZE, (void *)NULL); TARGET_IO_PORT_init(); } +void I2C_0_PORT_init(void) +{ + + gpio_set_pin_pull_mode(PD08, + // Pull configuration + // pad_pull_config + // Off + // Pull-up + // Pull-down + GPIO_PULL_OFF); + + gpio_set_pin_function(PD08, PINMUX_PD08C_SERCOM7_PAD0); + + gpio_set_pin_pull_mode(PD09, + // Pull configuration + // pad_pull_config + // Off + // Pull-up + // Pull-down + GPIO_PULL_OFF); + + gpio_set_pin_function(PD09, PINMUX_PD09C_SERCOM7_PAD1); +} + +void I2C_0_CLOCK_init(void) +{ + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM7_GCLK_ID_CORE, CONF_GCLK_SERCOM7_CORE_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + hri_gclk_write_PCHCTRL_reg(GCLK, SERCOM7_GCLK_ID_SLOW, CONF_GCLK_SERCOM7_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos)); + + hri_mclk_set_APBDMASK_SERCOM7_bit(MCLK); +} + +void I2C_0_init(void) +{ + I2C_0_CLOCK_init(); + i2c_m_sync_init(&I2C_0, SERCOM7); + I2C_0_PORT_init(); +} + void CAN_0_PORT_init(void) { @@ -70,6 +159,49 @@ void CAN_0_init(void) CAN_0_PORT_init(); } +void MACIF_PORT_init(void) +{ + + gpio_set_pin_function(PC11, PINMUX_PC11L_GMAC_GMDC); + + gpio_set_pin_function(PC12, PINMUX_PC12L_GMAC_GMDIO); + + gpio_set_pin_function(PA13, PINMUX_PA13L_GMAC_GRX0); + + gpio_set_pin_function(PA12, PINMUX_PA12L_GMAC_GRX1); + + gpio_set_pin_function(PC20, PINMUX_PC20L_GMAC_GRXDV); + + gpio_set_pin_function(PA15, PINMUX_PA15L_GMAC_GRXER); + + gpio_set_pin_function(PA18, PINMUX_PA18L_GMAC_GTX0); + + gpio_set_pin_function(PA19, PINMUX_PA19L_GMAC_GTX1); + + gpio_set_pin_function(PA14, PINMUX_PA14L_GMAC_GTXCK); + + gpio_set_pin_function(PA17, PINMUX_PA17L_GMAC_GTXEN); +} + +void MACIF_CLOCK_init(void) +{ + hri_mclk_set_AHBMASK_GMAC_bit(MCLK); + hri_mclk_set_APBCMASK_GMAC_bit(MCLK); +} + +void MACIF_init(void) +{ + MACIF_CLOCK_init(); + mac_async_init(&MACIF, GMAC); + MACIF_PORT_init(); +} + +void MACIF_example(void) +{ + mac_async_enable(&MACIF); + mac_async_write(&MACIF, (uint8_t *)"Hello World!", 12); +} + void system_init(void) { init_mcu(); @@ -88,8 +220,13 @@ void system_init(void) gpio_set_pin_function(LED0, GPIO_PIN_FUNCTION_OFF); + ADC_0_init(); CRYPTOGRAPHY_0_init(); TARGET_IO_init(); + + I2C_0_init(); CAN_0_init(); + + MACIF_init(); } diff --git a/bsp/microchip/same54/bsp/driver_init.h b/bsp/microchip/same54/bsp/driver_init.h index c043185dc9..3a9f18ed04 100644 --- a/bsp/microchip/same54/bsp/driver_init.h +++ b/bsp/microchip/same54/bsp/driver_init.h @@ -21,20 +21,42 @@ extern "C" { #include #include +#include #include -#include +#include + +#include #include -extern struct aes_sync_descriptor CRYPTOGRAPHY_0; +#include + +extern struct adc_sync_descriptor ADC_0; +extern struct aes_sync_descriptor CRYPTOGRAPHY_0; +extern struct usart_async_descriptor TARGET_IO; + +extern struct i2c_m_sync_desc I2C_0; +extern struct can_async_descriptor CAN_0; -extern struct usart_sync_descriptor TARGET_IO; -extern struct can_async_descriptor CAN_0; +extern struct mac_async_descriptor MACIF; + +void ADC_0_PORT_init(void); +void ADC_0_CLOCK_init(void); +void ADC_0_init(void); void TARGET_IO_PORT_init(void); void TARGET_IO_CLOCK_init(void); void TARGET_IO_init(void); +void I2C_0_CLOCK_init(void); +void I2C_0_init(void); +void I2C_0_PORT_init(void); + +void MACIF_CLOCK_init(void); +void MACIF_init(void); +void MACIF_PORT_init(void); +void MACIF_example(void); + /** * \brief Perform system initialization, initialize pins and clocks for * peripherals diff --git a/bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.c b/bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.c new file mode 100644 index 0000000000..a4f5caecc6 --- /dev/null +++ b/bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.c @@ -0,0 +1,184 @@ +/** + * \file + * + * \brief Ethernet PHY functionality implementation. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +/** + * \brief Perform a HW initialization to the PHY + */ +int32_t ethernet_phy_init(struct ethernet_phy_descriptor *const descr, struct mac_async_descriptor *const mac, + uint16_t addr) +{ + ASSERT(descr && mac && (addr <= 0x1F)); + + descr->mac = mac; + descr->addr = addr; + return ERR_NONE; +} + +/** + * \brief Set PHY address + */ +int32_t ethernet_phy_set_address(struct ethernet_phy_descriptor *const descr, uint16_t addr) +{ + ASSERT(descr && (addr <= 0x1F)); + + descr->addr = addr; + return ERR_NONE; +} + +/** + * \brief Read PHY Register value. + */ +int32_t ethernet_phy_read_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t *val) +{ + ASSERT(descr && descr->mac && (reg <= 0x1F) && val); + + return mac_async_read_phy_reg(descr->mac, descr->addr, reg, val); +} + +/** + * \brief Write PHY Register value. + */ +int32_t ethernet_phy_write_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t val) +{ + ASSERT(descr && descr->mac && (reg <= 0x1F)); + return mac_async_write_phy_reg(descr->mac, descr->addr, reg, val); +} + +/** + * \brief Setting bit for a PHY Register + */ +int32_t ethernet_phy_set_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst) +{ + int32_t rst; + uint16_t val; + + ASSERT(descr && descr->mac && (reg <= 0x1F)); + + rst = mac_async_read_phy_reg(descr->mac, descr->addr, reg, &val); + if (rst == ERR_NONE) { + val |= ofst; + rst = mac_async_write_phy_reg(descr->mac, descr->addr, reg, val); + } + return rst; +} +/** + * \brief Clear bit for a PHY Register + */ +int32_t ethernet_phy_clear_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst) +{ + int32_t rst; + uint16_t val; + + ASSERT(descr && (reg <= 0x1F)); + + rst = mac_async_read_phy_reg(descr->mac, descr->addr, reg, &val); + if (rst == ERR_NONE) { + val &= ~ofst; + rst = mac_async_write_phy_reg(descr->mac, descr->addr, reg, val); + } + return rst; +} +/** + * \brief Set PHY low-power consumption state. + */ +int32_t ethernet_phy_set_powerdown(struct ethernet_phy_descriptor *const descr, bool state) +{ + ASSERT(descr); + if (state) { + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_POWER_DOWN); + } else { + return ethernet_phy_clear_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_POWER_DOWN); + } +} + +/** + * \brief Set PHY electrically isolate state. + */ +int32_t ethernet_phy_set_isolate(struct ethernet_phy_descriptor *const descr, bool state) +{ + ASSERT(descr); + if (state) { + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_ISOLATE); + } else { + return ethernet_phy_clear_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_ISOLATE); + } +} + +/** + * \brief Restart an auto negotiation of the PHY. + */ +int32_t ethernet_phy_restart_autoneg(struct ethernet_phy_descriptor *const descr) +{ + ASSERT(descr); + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_RESTART_AUTONEG); +} + +/** + * \brief Set PHY placed in a loopback mode of operation. + */ +int32_t ethernet_phy_set_loopback(struct ethernet_phy_descriptor *const descr, bool state) +{ + ASSERT(descr); + if (state) { + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_LOOPBACK); + } else { + return ethernet_phy_clear_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_LOOPBACK); + } +} + +/** + * \brief Get PHY link status + */ +int32_t ethernet_phy_get_link_status(struct ethernet_phy_descriptor *const descr, bool *status) +{ + int32_t rst; + uint16_t val; + + ASSERT(descr && descr->mac && status); + rst = mac_async_read_phy_reg(descr->mac, descr->addr, MDIO_REG1_BMSR, &val); + if (rst == ERR_NONE) { + *status = (val & MDIO_REG1_BIT_LINK_STATUS) ? true : false; + } + return rst; +} + +/** + * \brief Reset PHY. + */ +int32_t ethernet_phy_reset(struct ethernet_phy_descriptor *const descr) +{ + ASSERT(descr); + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_RESET); +} diff --git a/bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.h b/bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.h new file mode 100644 index 0000000000..65ad5afecc --- /dev/null +++ b/bsp/microchip/same54/bsp/ethernet_phy/ethernet_phy.h @@ -0,0 +1,230 @@ +/** + * \file + * + * \brief Ethernet PHY functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef ETHERNET_PHY_H_INCLUDED +#define ETHERNET_PHY_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "compiler.h" +#include "hal_mac_async.h" +#include "ieee8023_mii_standard_register.h" + +struct ethernet_phy_descriptor { + struct mac_async_descriptor *mac; /* MAC descriptor handler */ + uint16_t addr; /* PHY address, defined by IEEE802.3 + section 22.2.4.5.5 */ +}; + +/** + * \brief Perform a HW initialization to the PHY + * + * This should be called only once to initialize the PHY pre-settings. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] mac MAC descriptor, the descriptor should be initialized. + * \param[in] addr Ethernet PHY 5 bits address. + * + * \return Operation result + * \retval ERR_NONE initializing successful. + */ +int32_t ethernet_phy_init(struct ethernet_phy_descriptor *const descr, struct mac_async_descriptor *const mac, + uint16_t addr); + +/** + * \brief Set PHY address + * + * Set PHY management PHY address which defined by IEEE802.3 section 22.2.4.5.5 + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] addr PHY address + * + * \return Operation result + * \retval ERR_NONE Set address successful. + */ +int32_t ethernet_phy_set_address(struct ethernet_phy_descriptor *const descr, uint16_t addr); + +/** + * \brief Read PHY Register value. + * + * Read PHY Register value from PHY. + * + * \note For conformance with the 802.3 specification, MDC must not exceed + * 2.5 MHz (MDC is only active during MDIO read and write operations). + * The function execution time depend on MDC frequency. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address + * \param[out] val Register value + * + * \return Operation result. + * \retval ERR_NONE Read register successful. + */ +int32_t ethernet_phy_read_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t *val); + +/** + * \brief Write PHY Register value. + * + * Read PHY Register value from PHY. + * + * \note For conformance with the 802.3 specification, MDC must not exceed + * 2.5 MHz (MDC is only active during MDIO read and write operations). + * The function execution time depend on MDC frequency. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address + * \param[out] val Register value + * + * \return Operation result. + * \retval ERR_NONE Write register successful. + */ +int32_t ethernet_phy_write_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t val); + +/** + * \brief Setting bit for a PHY Register + * + * Bit setting for a PHY Register. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address. + * \param[in] ofst Register bit mask. + * + * \return Operation result. + * \retval ERR_NONE Set register bit successful. + */ +int32_t ethernet_phy_set_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst); + +/** + * \brief Clear bit for a PHY Register + * + * Clear bit for a PHY Register. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address. + * \param[in] ofst Register bit mask. + * + * \return Operation result. + * \retval ERR_NONE Clear register bit successful. + */ +int32_t ethernet_phy_clear_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst); + +/** + * \brief Set PHY low-power consumption state. + * + * The specific behavior of a PHY in the power-down state is implementation + * specific. While in the power-down state, the PHY shall respond to management + * transactions. During the transition to the power-down state and while in the + * power-down state, the PHY shall not generate spurious signals on the MII or + * GMII. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] state The state of the power-down mode. + * + * \return Operation result. + * \retval ERR_NONE Power-Down has been config successful. + */ +int32_t ethernet_phy_set_powerdown(struct ethernet_phy_descriptor *const descr, bool state); + +/** + * \brief Set PHY electrically isolate state. + * + * When the PHY is isolated from the MII or RMII it shall not respond to the + * data bundle. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] state The state of the isolate mode. + * + * \return Operation result. + * \retval ERR_NONE Isolate has been config successful. + */ +int32_t ethernet_phy_set_isolate(struct ethernet_phy_descriptor *const descr, bool state); + +/** + * \brief Restart an auto negotiation of the PHY. + * + * Restart Auto_Negotantion process + * + * \param[in] descr Ethernet PHY descriptor. + * + * \return Operation result + * \retval ERR_NONE Auto-Negotiation has been initiated. + */ +int32_t ethernet_phy_restart_autoneg(struct ethernet_phy_descriptor *const descr); + +/** + * \brief Set PHY placed in a loopback mode of operation. + * + * When in loopback mode, the PHY shall accept data from the MII/RMII transmit + * data path and return it to the MII/RMII receive data path. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] state State of the loopback mode. + * + * \return Operation result + * \retval ERR_NONE Loopback has been set successful. + */ +int32_t ethernet_phy_set_loopback(struct ethernet_phy_descriptor *const descr, bool state); + +/** + * \brief Get PHY link status + * + * Get PHY link status + * + * \param[in] descr Ethernet PHY descriptor. + * \param[out] status Pointer to the Link Status. + * + * \return ERR_NONE if successfully + */ +int32_t ethernet_phy_get_link_status(struct ethernet_phy_descriptor *const descr, bool *status); + +/** + * \brief Reset PHY. + * + * Resetting PHY, this action set all the status and control register to their + * default states. As a consequence this action may change the internal state + * of the PHY and the state of the physical link associated with the PHY. The + * reset process shall be completed within 0.5 second. + * + * \param[in] descr Ethernet PHY descriptor. + * + * \return ERR_NONE if successfully + */ +int32_t ethernet_phy_reset(struct ethernet_phy_descriptor *const descr); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/ethernet_phy/ieee8023_mii_standard_register.h b/bsp/microchip/same54/bsp/ethernet_phy/ieee8023_mii_standard_register.h new file mode 100644 index 0000000000..e36caddf24 --- /dev/null +++ b/bsp/microchip/same54/bsp/ethernet_phy/ieee8023_mii_standard_register.h @@ -0,0 +1,137 @@ +/** + * \file + * + * \brief IEEE802.3 MII Management Standard Register Set + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef ETHERNET_MII_REGISTER_H_INCLUDED +#define ETHERNET_MII_REGISTER_H_INCLUDED + +/* IEEE 802.3 Clause22.2.4 defined Standard Registers. + * The MII basic register set consists of two registers referred to as the + * Control register (Register 0) and the Status register (Register 1). All + * PHYs that provide an MII shall incorporate the basic register set. All PHYs + * that provide a GMII shall incorporate an extended basic register set + * consisting of the Control register (Register 0), Status register + * (Register 1), and Extended Status register (Register 15). The status and + * control functions defined here are considered basic and fundamental to + * 100 Mb/s and 1000 Mb/s PHYs. Registers 2 through 14 are part of the + * extended register set. The format of Registers 4 through 10 are defined for + * the specific Auto-Negotiation protocol used (Clause 28 or Clause 37). The + * format of these registers is selected by the bit settings of Registers 1 + * and 15. + **/ +#define MDIO_REG0_BMCR 0x00 /* Basic Control */ +#define MDIO_REG1_BMSR 0x01 /* Basic Status */ +#define MDIO_REG2_PHYID1 0x02 /* PHY Idendifier 1 */ +#define MDIO_REG3_PHYID2 0x03 /* PHY Idendifier 2 */ +#define MDIO_REG4_ANA 0x04 /* Auto_Negotiation Advertisement */ +#define MDIO_REG5_ANLPA 0x05 /* Auto_negotiation Link Partner Base Page Ability */ +#define MDIO_REG6_ANE 0x06 /* Auto-negotiation Expansion */ +#define MDIO_REG7_ANNPT 0x07 /* Auto-negotiation Next Page Transmit */ +#define MDIO_REG8_ANLPRNP 0x08 /* Auto-Negotiation Link Partner Received Next Page */ +#define MDIO_REG9_MSC 0x09 /* MASTER-SLAVE Control Register */ +#define MDIO_REG10_MSS 0x0A /* MASTER-SLAVE Status Register */ +#define MDIO_REG11_PSEC 0x0B /* PSE Control Register */ +#define MDIO_REG12_PSES 0x0C /* PSE Status Register */ +#define MDIO_REG13_MMDAC 0x0D /* MMD Access Control Register */ +#define MDIO_REG14_MMDAAD 0x0E /* MMD Access Address Data Register */ +#define MDIO_REG15_EXTS 0x0F /* Extended Status */ +/* Register 16 to 31 are Reserved for Vendor Specific */ + +/* Bit definitions: MDIO_REG0_BMCR 0x00 Basic Control */ +#define MDIO_REG0_BIT_RESET (1 << 15) /* 1 = Software Reset; 0 = Normal Operation */ +#define MDIO_REG0_BIT_LOOPBACK (1 << 14) /* 1 = loopback Enabled; 0 = Normal Operation */ +#define MDIO_REG0_BIT_SPEED_SELECT_LSB (1 << 13) /* 1 = 100Mbps; 0=10Mbps */ +#define MDIO_REG0_BIT_AUTONEG (1 << 12) /* 1 = Auto-negotiation Enable */ +#define MDIO_REG0_BIT_POWER_DOWN (1 << 11) /* 1 = Power down 0=Normal operation */ +#define MDIO_REG0_BIT_ISOLATE (1 << 10) /* 1 = Isolates 0 = Normal operation */ +#define MDIO_REG0_BIT_RESTART_AUTONEG (1 << 9) /* 1 = Restart auto-negotiation 0 = Normal operation */ +#define MDIO_REG0_BIT_DUPLEX_MODE (1 << 8) /* 1 = Full duplex operation 0 = Normal operation */ +#define MDIO_REG0_BIT_COLLISION_TEST (1 << 7) /* 1 = Enable COL test; 0 = Disable COL test */ +#define MDIO_REG0_BIT_SPEED_SELECT_MSB (1 << 6) /* 1 with LSB0 = 1000Mbps */ +#define MDIO_REG0_BIT_UNIDIR_ENABLE (1 << 5) /* Unidirectional Enable */ +/* Reserved 4 to 0 Read as 0, ignore on write */ + +/* Bit definitions: MDIO_BMSR 0x01 Basic Status */ +#define MDIO_REG1_BIT_100BASE_T4 (1 << 15) /* 100BASE-T4 Capable */ +#define MDIO_REG1_BIT_100BASE_TX_FD (1 << 14) /* 100BASE-TX Full Duplex Capable */ +#define MDIO_REG1_BIT_100BASE_TX_HD (1 << 13) /* 100BASE-TX Half Duplex Capable */ +#define MDIO_REG1_BIT_10BASE_T_FD (1 << 12) /* 10BASE-T Full Duplex Capable */ +#define MDIO_REG1_BIT_10BASE_T_HD (1 << 11) /* 10BASE-T Half Duplex Capable */ +#define MDIO_REG1_BIT_100BASE_T2_FD (1 << 10) /* 1000BASE-T2 Full Duplex Capable */ +#define MDIO_REG1_BIT_100BASE_T2_HD (1 << 9) /* 1000BASE-T2 Half Duplex Capable */ +#define MDIO_REG1_BIT_EXTEND_STATUS (1 << 8) /* 1 = Extend Status Information In Reg 15 */ +#define MDIO_REG1_BIT_UNIDIR_ABILITY (1 << 7) /* Unidirectional ability */ +#define MDIO_REG1_BIT_MF_PREAMB_SUPPR (1 << 6) /* MII Frame Preamble Suppression */ +#define MDIO_REG1_BIT_AUTONEG_COMP (1 << 5) /* Auto-negotiation Complete */ +#define MDIO_REG1_BIT_REMOTE_FAULT (1 << 4) /* Remote Fault */ +#define MDIO_REG1_BIT_AUTONEG_ABILITY (1 << 3) /* Auto Configuration Ability */ +#define MDIO_REG1_BIT_LINK_STATUS (1 << 2) /* Link Status */ +#define MDIO_REG1_BIT_JABBER_DETECT (1 << 1) /* Jabber Detect */ +#define MDIO_REG1_BIT_EXTEND_CAPAB (1 << 0) /* Extended Capability */ + +/* Bit definitions: MDIO_PHYID1 0x02 PHY Idendifier 1 */ +/* Bit definitions: MDIO_PHYID2 0x03 PHY Idendifier 2 */ +#define MDIO_LSB_MASK 0x3F +#define MDIO_OUI_MSB 0x0022 +#define MDIO_OUI_LSB 0x1572 + +/* Bit definitions: MDIO_REG4_ANA 0x04 Auto-Negotiation advertisement */ +#define MDIO_REG4_BIT_NEXTPAGE (15 << 0) /* Next Page */ +#define MDIO_REG4_BIT_REMOTE_FAULT (13 << 0) /* Remote Fault */ +#define MDIO_REG4_BIT_EXT_NEXTPAGE (12 << 0) /* Extended Next Page */ + +/* Bit definitions: MDIO_ANAR 0x04 Auto_Negotiation Advertisement */ +/* Bit definitions: MDIO_ANLPAR 0x05 Auto_negotiation Link Partner Ability */ +#define MDIO_NP (1 << 15) /* Next page Indication */ +#define MDIO_RF (1 << 13) /* Remote Fault */ +#define MDIO_PAUSE_MASK (3 << 10) /* 0,0 = No Pause 1,0 = Asymmetric Pause(link partner) */ + /* 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device) */ +#define MDIO_100T4 (1 << 9) /* 100BASE-T4 Support */ +#define MDIO_100TX_FDX (1 << 8) /* 100BASE-TX Full Duplex Support */ +#define MDIO_100TX_HDX (1 << 7) /* 100BASE-TX Half Duplex Support */ +#define MDIO_10_FDX (1 << 6) /* 10BASE-T Full Duplex Support */ +#define MDIO_10_HDX (1 << 5) /* 10BASE-T Half Duplex Support */ +#define MDIO_AN_IEEE_802_3 0x0001 /* [00001] = IEEE 802.3 */ + +/* Bit definitions: MDIO_ANER 0x06 Auto-negotiation Expansion */ +#define MDIO_PDF (1 << 4) /* Local Device Parallel Detection Fault */ +#define MDIO_LP_NP_ABLE (1 << 3) /* Link Partner Next Page Able */ +#define MDIO_NP_ABLE (1 << 2) /* Local Device Next Page Able */ +#define MDIO_PAGE_RX (1 << 1) /* New Page Received */ +#define MDIO_LP_AN_ABLE (1 << 0) /* Link Partner Auto-negotiation Able */ + +/* Bit definitions: MDIO_PCR1 0x1E PHY Control 1 */ +#define MDIO_OMI_10BASE_T_HD 0x0001 +#define MDIO_OMI_100BASE_TX_HD 0x0002 +#define MDIO_OMI_10BASE_T_FD 0x0005 + +#endif /* #ifndef ETHERNET_MII_REGISTER_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/ethernet_phy_main.c b/bsp/microchip/same54/bsp/ethernet_phy_main.c new file mode 100644 index 0000000000..7ece274706 --- /dev/null +++ b/bsp/microchip/same54/bsp/ethernet_phy_main.c @@ -0,0 +1,43 @@ +/* + * Code generated from Atmel Start. + * + * This file will be overwritten when reconfiguring your Atmel Start project. + * Please copy examples or other code you want to keep to a separate file or main.c + * to avoid loosing it when reconfiguring. + */ + +#include +#include +#include + +struct ethernet_phy_descriptor MACIF_PHY_desc; + +void MACIF_PHY_init(void) +{ + mac_async_enable(&MACIF); + ethernet_phy_init(&MACIF_PHY_desc, &MACIF, CONF_MACIF_PHY_IEEE8023_MII_PHY_ADDRESS); +#if CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING == 1 + ethernet_phy_write_reg(&MACIF_PHY_desc, MDIO_REG0_BMCR, CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0); +#endif /* CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING */ +} + +void MACIF_PHY_example(void) +{ + bool link_state; + int32_t rst; + /* Restart an auto-negotiation */ + rst = ethernet_phy_restart_autoneg(&MACIF_PHY_desc); + while (rst != ERR_NONE) { + } + + /* Wait for PHY link up */ + do { + rst = ethernet_phy_get_link_status(&MACIF_PHY_desc, &link_state); + } while (rst == ERR_NONE && link_state == true); +} + +void ethernet_phys_init(void) +{ + + MACIF_PHY_init(); +} diff --git a/bsp/microchip/same54/bsp/ethernet_phy_main.h b/bsp/microchip/same54/bsp/ethernet_phy_main.h new file mode 100644 index 0000000000..e55c9706e4 --- /dev/null +++ b/bsp/microchip/same54/bsp/ethernet_phy_main.h @@ -0,0 +1,30 @@ +/* + * Code generated from Atmel Start. + * + * This file will be overwritten when reconfiguring your Atmel Start project. + * Please copy examples or other code you want to keep to a separate file or main.c + * to avoid loosing it when reconfiguring. + */ +#ifndef ETHERNET_PHY_MAIN_H +#define ETHERNET_PHY_MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif +#include + +extern struct ethernet_phy_descriptor MACIF_PHY_desc; + +void ethernet_phys_init(void); +void MACIF_PHY_example(void); + +/** + * \brief Ethernet PHY devices + */ +void ethernet_phys_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ETHERNET_PHY_MAIN_H */ diff --git a/bsp/microchip/same54/bsp/examples/driver_examples.c b/bsp/microchip/same54/bsp/examples/driver_examples.c index fef41e889e..d5b9ada7e3 100644 --- a/bsp/microchip/same54/bsp/examples/driver_examples.c +++ b/bsp/microchip/same54/bsp/examples/driver_examples.c @@ -10,6 +10,20 @@ #include "driver_init.h" #include "utils.h" +/** + * Example of using ADC_0 to generate waveform. + */ +void ADC_0_example(void) +{ + uint8_t buffer[2]; + + adc_sync_enable_channel(&ADC_0, 0); + + while (1) { + adc_sync_read_channel(&ADC_0, 0, buffer, 2); + } +} + static uint8_t aes_plain_text[16] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}; static uint8_t aes_key[16] @@ -34,14 +48,41 @@ void CRYPTOGRAPHY_0_example(void) /** * Example of using TARGET_IO to write "Hello World" using the IO abstraction. + * + * Since the driver is asynchronous we need to use statically allocated memory for string + * because driver initiates transfer and then returns before the transmission is completed. + * + * Once transfer has been completed the tx_cb function will be called. */ + +static uint8_t example_TARGET_IO[12] = "Hello World!"; + +static void tx_cb_TARGET_IO(const struct usart_async_descriptor *const io_descr) +{ + /* Transfer completed */ +} + void TARGET_IO_example(void) { struct io_descriptor *io; - usart_sync_get_io_descriptor(&TARGET_IO, &io); - usart_sync_enable(&TARGET_IO); - io_write(io, (uint8_t *)"Hello World!", 12); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, tx_cb_TARGET_IO); + /*usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, rx_cb); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_ERROR_CB, err_cb);*/ + usart_async_get_io_descriptor(&TARGET_IO, &io); + usart_async_enable(&TARGET_IO); + + io_write(io, example_TARGET_IO, 12); +} + +void I2C_0_example(void) +{ + struct io_descriptor *I2C_0_io; + + i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io); + i2c_m_sync_enable(&I2C_0); + i2c_m_sync_set_slaveaddr(&I2C_0, 0x12, I2C_M_SEVEN); + io_write(I2C_0_io, (uint8_t *)"Hello World!", 12); } void CAN_0_tx_callback(struct can_async_descriptor *const descr) diff --git a/bsp/microchip/same54/bsp/examples/driver_examples.h b/bsp/microchip/same54/bsp/examples/driver_examples.h index 54c2aa1b5a..1cfb1d09fd 100644 --- a/bsp/microchip/same54/bsp/examples/driver_examples.h +++ b/bsp/microchip/same54/bsp/examples/driver_examples.h @@ -12,10 +12,14 @@ extern "C" { #endif +void ADC_0_example(void); + void CRYPTOGRAPHY_0_example(void); void TARGET_IO_example(void); +void I2C_0_example(void); + void CAN_0_example(void); #ifdef __cplusplus diff --git a/bsp/microchip/same54/bsp/gcc/gcc/same54p20a_flash.ld b/bsp/microchip/same54/bsp/gcc/gcc/same54p20a_flash.ld index fe3748b716..89144e415e 100644 --- a/bsp/microchip/same54/bsp/gcc/gcc/same54p20a_flash.ld +++ b/bsp/microchip/same54/bsp/gcc/gcc/same54p20a_flash.ld @@ -60,6 +60,31 @@ SECTIONS *(.rodata .rodata* .gnu.linkonce.r.*) *(.ARM.extab* .gnu.linkonce.armextab.*) + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ . = ALIGN(4); diff --git a/bsp/microchip/same54/bsp/hal/documentation/adc_sync.rst b/bsp/microchip/same54/bsp/hal/documentation/adc_sync.rst new file mode 100644 index 0000000000..d189565ad8 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/documentation/adc_sync.rst @@ -0,0 +1,74 @@ +====================== +ADC Synchronous driver +====================== + +An ADC (Analog-to-Digital Converter) converts analog signals to digital values. +A reference signal with a known voltage level is quantified into equally +sized chunks, each representing a digital value from 0 to the highest number +possible with the bit resolution supported by the ADC. The input voltage +measured by the ADC is compared against these chunks and the chunk with the +closest voltage level defines the digital value that can be used to represent +the analog input voltage level. + +Usually an ADC can operate in either differential or single-ended mode. +In differential mode two signals (V+ and V-) are compared against each other +and the resulting digital value represents the relative voltage level between +V+ and V-. This means that if the input voltage level on V+ is lower than on +V- the digital value is negative, which also means that in differential +mode one bit is lost to the sign. In single-ended mode only V+ is compared +against the reference voltage, and the resulting digital value can only be +positive, but the full bit-range of the ADC can be used. + +Usually multiple resolutions are supported by the ADC, lower resolution can +reduce the conversion time, but lose accuracy. + +Some ADCs has a gain stage on the input lines which can be used to increase the +dynamic range. The default gain value is usually x1, which means that the +conversion range is from 0V to the reference voltage. +Applications can change the gain stage, to increase or reduce the conversion +range. + +The window mode allows the conversion result to be compared to a set of +predefined threshold values. Applications can use callback function to monitor +if the conversion result exceeds predefined threshold value. + +Usually multiple reference voltages are supported by the ADC, both internal and +external with difference voltage levels. The reference voltage have an impact +on the accuracy, and should be selected to cover the full range of the analog +input signal and never less than the expected maximum input voltage. + +There are two conversion modes supported by ADC, single shot and free running. +In single shot mode the ADC only make one conversion when triggered by the +application, in free running mode it continues to make conversion from it +is triggered until it is stopped by the application. When window monitoring, +the ADC should be set to free running mode. + +Features +-------- +* Initialization and de-initialization +* Support multiple Conversion Mode, Single or Free run +* Start ADC Conversion +* Read Conversion Result + +Applications +------------ +* Measurement of internal sensor. E.g., MCU internal temperature sensor value. +* Measurement of external sensor. E.g., Temperature, humidity sensor value. +* Sampling and measurement of a signal. E.g., sinusoidal wave, square wave. + +Dependencies +------------ +* ADC hardware + +Concurrency +----------- +N/A + +Limitations +----------- +N/A + +Knows issues and workarounds +---------------------------- +N/A + diff --git a/bsp/microchip/same54/bsp/hal/documentation/i2c_master_sync.rst b/bsp/microchip/same54/bsp/hal/documentation/i2c_master_sync.rst new file mode 100644 index 0000000000..77b4f6e9c4 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/documentation/i2c_master_sync.rst @@ -0,0 +1,87 @@ +============================= +I2C Master synchronous driver +============================= + +I2C (Inter-Integrated Circuit) is a two wire serial interface usually used +for on-board low-speed bi-directional communication between controllers and +peripherals. The master device is responsible for initiating and controlling +all transfers on the I2C bus. Only one master device can be active on the I2C +bus at the time, but the master role can be transferred between devices on the +same I2C bus. I2C uses only two bidirectional open-drain lines, usually +designated SDA (Serial Data Line) and SCL (Serial Clock Line), with pull up +resistors. + +The stop condition is automatically controlled by the driver if the I/O write and +read functions are used, but can be manually controlled by using the +i2c_m_sync_transfer function. + +Often a master accesses different information in the slave by accessing +different registers in the slave. This is done by first sending a message to +the target slave containing the register address, followed by a repeated start +condition (no stop condition between) ending with transferring register data. +This scheme is supported by the i2c_m_sync_cmd_write and i2c_m_sync_cmd_read +function, but limited to 8-bit register addresses. + +I2C Modes (standard mode/fastmode+/highspeed mode) can only be selected in +Atmel Start. If the SCL frequency (baudrate) has changed run-time, make sure to +stick within the SCL clock frequency range supported by the selected mode. +The requested SCL clock frequency is not validated by the +i2c_m_sync_set_baudrate function against the selected I2C mode. + +Features +-------- + + * I2C Master support + * Initialization and de-initialization + * Enabling and disabling + * Run-time bus speed configuration + * Write and read I2C messages + * Slave register access functions (limited to 8-bit address) + * Manual or automatic stop condition generation + * 10- and 7- bit addressing + * I2C Modes supported + +----------------------+-------------------+ + |* Standard/Fast mode | (SCL: 1 - 400kHz) | + +----------------------+-------------------+ + |* Fastmode+ | (SCL: 1 - 1000kHz)| + +----------------------+-------------------+ + |* Highspeed mode | (SCL: 1 - 3400kHz)| + +----------------------+-------------------+ + +Applications +------------ + +* Transfer data to and from one or multiple I2C slaves like I2C connected sensors, data storage or other I2C capable peripherals +* Data communication between micro controllers +* Controlling displays + +Dependencies +------------ + +* I2C Master capable hardware + +Concurrency +----------- + +N/A + +Limitations +----------- + +General +^^^^^^^ + + * System Managmenet Bus (SMBus) not supported. + * Power Management Bus (PMBus) not supported. + +Clock considerations +^^^^^^^^^^^^^^^^^^^^ + +The register value for the requested I2C speed is calculated and placed in the correct register, but not validated if it works correctly with the clock/prescaler settings used for the module. To validate the I2C speed setting use the formula found in the configuration file for the module. Selectable speed is automatically limited within the speed range defined by the I2C mode selected. + +Known issues and workarounds +---------------------------- + +N/A + + diff --git a/bsp/microchip/same54/bsp/hal/documentation/mac_async.rst b/bsp/microchip/same54/bsp/hal/documentation/mac_async.rst new file mode 100644 index 0000000000..688dc3797a --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/documentation/mac_async.rst @@ -0,0 +1,43 @@ +================================ +Ethernet MAC Asynchronous Driver +================================ + +The Ethernet MAC driver implements a 10/100 Mbps Ethernet MAC compatible with +the IEEE 802.3 standard. + +Features +-------- + +* Initialization/de-initialization +* Enabling/disabling +* Data transfer: transmission, reception +* Enabling/disabling Interrupt +* Notifications about transfer completion and frame received via callbacks +* Address Filter for Specific 48-bit Addresses and Type ID +* Address Filter for Unicast and Multicase Addresses +* Reading/writing PHY registers + +Applications +------------ + +Co-works with thirdpart TCP/IP stacks. E.g., Lwip, Cyclone IP stack. + +Dependencies +------------ + +MAC capable hardware compatible with the IEEE 802.3 standard. + +Concurrency +----------- + +N/A + +Limitations +----------- + +N/A + +Known issues and workarounds +---------------------------- + +N/A diff --git a/bsp/microchip/same70/bsp/hal/documentation/usart_sync.rst b/bsp/microchip/same54/bsp/hal/documentation/usart_async.rst similarity index 62% rename from bsp/microchip/same70/bsp/hal/documentation/usart_sync.rst rename to bsp/microchip/same54/bsp/hal/documentation/usart_async.rst index 15e4b13885..6bf4a23e92 100644 --- a/bsp/microchip/same70/bsp/hal/documentation/usart_sync.rst +++ b/bsp/microchip/same54/bsp/hal/documentation/usart_async.rst @@ -1,9 +1,20 @@ -The USART Synchronous Driver -============================ +The USART Asynchronous Driver +============================= The universal synchronous and asynchronous receiver and transmitter (USART) is usually used to transfer data from one device to the other. +The USART driver use a ring buffer to store received data. When the USART +raise the data received interrupt, this data will be stored in the ring buffer +at the next free location. When the ring buffer is full, the next reception +will overwrite the oldest data stored in the ring buffer. There is one +USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro +is called SERCOM0_USART_BUFFER_SIZE. + +On the other hand, when sending data over USART, the data is not copied to an +internal buffer, but the data buffer supplied by the user is used. The callback +will only be generated at the end of the buffer and not for each byte. + User can set action for flow control pins by function usart_set_flow_control, if the flow control is enabled. All the available states are defined in union usart_flow_control_state. @@ -24,6 +35,8 @@ Features * Data order * Flow control * Data transfer: transmission, reception +* Notifications about transfer done or error case via callbacks +* Status information with busy state and transfer count Applications ------------ @@ -34,7 +47,8 @@ between devices. Dependencies ------------ -USART capable hardware. +USART capable hardware, with interrupt on each character is sent or +received. Concurrency ----------- diff --git a/bsp/microchip/same54/bsp/hal/include/hal_adc_sync.h b/bsp/microchip/same54/bsp/hal/include/hal_adc_sync.h new file mode 100644 index 0000000000..1b66e3df7c --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hal_adc_sync.h @@ -0,0 +1,277 @@ +/** + * \file + * + * \brief ADC functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_ADC_SYNC_H_INCLUDED +#define _HAL_ADC_SYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_adc_sync + * + * @{ + */ + +/** + * \brief ADC descriptor + * + * The ADC descriptor forward declaration. + */ +struct adc_sync_descriptor; + +/** + * \brief ADC descriptor + */ +struct adc_sync_descriptor { + /** ADC device */ + struct _adc_sync_device device; +}; + +/** + * \brief Initialize ADC + * + * This function initializes the given ADC descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[out] descr An ADC descriptor to initialize + * \param[in] hw The pointer to hardware instance + * \param[in] func The pointer to a set of functions pointers + * + * \return Initialization status. + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func); + +/** + * \brief Deinitialize ADC + * + * This function deinitializes the given ADC descriptor. + * It checks if the given hardware is initialized and if the given hardware is + * permitted to be deinitialized. + * + * \param[in] descr An ADC descriptor to deinitialize + * + * \return De-initialization status. + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr); + +/** + * \brief Enable ADC + * + * Use this function to set the ADC peripheral to enabled state. + * + * \param[in] descr Pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return Operation status + * + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Disable ADC + * + * Use this function to set the ADC peripheral to disabled state. + * + * \param[in] descr Pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return Operation status + * + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Read data from ADC + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] buf A buffer to read data to + * \param[in] length The size of a buffer + * + * \return The number of bytes read. + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length); + +/** + * \brief Set ADC reference source + * + * This function sets ADC reference source. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] reference A reference source to set + * + * \return Status of the ADC reference source setting. + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference); + +/** + * \brief Set ADC resolution + * + * This function sets ADC resolution. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] resolution A resolution to set + * + * \return Status of the ADC resolution setting. + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * This function sets ADC positive and negative input sources. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + * + * \return Status of the ADC channels setting. + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set ADC conversion mode + * + * This function sets ADC conversion mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] mode A conversion mode to set + * + * \return Status of the ADC conversion mode setting. + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode); + +/** + * \brief Set ADC differential mode + * + * This function sets ADC differential mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + * + * \return Status of the ADC differential mode setting. + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set ADC channel gain + * + * This function sets ADC channel gain. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] gain A gain to set + * + * \return Status of the ADC gain setting. + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, + const adc_gain_t gain); + +/** + * \brief Set ADC window mode + * + * This function sets ADC window mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] mode A window mode to set + * + * \return Status of the ADC window mode setting. + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode); + +/** + * \brief Set ADC thresholds + * + * This function sets ADC positive and negative thresholds. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] low_threshold A lower thresholds to set + * \param[in] up_threshold An upper thresholds to set + * + * \return Status of the ADC thresholds setting. + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * This function retrieves ADC threshold state. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[out] state The threshold state + * + * \return The state of ADC thresholds state retrieving. + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, + adc_threshold_status_t *const state); + +/** + * \brief Check if conversion is complete + * + * This function checks if the ADC has finished the conversion. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return The status of ADC conversion completion checking. + * \retval 1 The conversion is complete + * \retval 0 The conversion is not complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t adc_sync_get_version(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* _HAL_ADC_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hal_i2c_m_sync.h b/bsp/microchip/same54/bsp/hal/include/hal_i2c_m_sync.h new file mode 100644 index 0000000000..24afd63933 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hal_i2c_m_sync.h @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief Sync I2C Hardware Abstraction Layer(HAL) declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_I2C_M_SYNC_H_INCLUDED +#define _HAL_I2C_M_SYNC_H_INCLUDED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_i2c_master_sync + * + * @{ + */ + +#define I2C_M_MAX_RETRY 1 + +/** + * \brief I2C descriptor structure, embed i2c_device & i2c_interface + */ +struct i2c_m_sync_desc { + struct _i2c_m_sync_device device; + struct io_descriptor io; + uint16_t slave_addr; +}; + +/** + * \brief Initialize synchronous I2C interface + * + * This function initializes the given I/O descriptor to be used as a + * synchronous I2C interface descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] hw The pointer to hardware instance + * + * \return Initialization status. + * \retval -1 The passed parameters were invalid or the interface is already initialized + * \retval 0 The initialization is completed successfully + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw); + +/** + * \brief Deinitialize I2C interface + * + * This function deinitializes the given I/O descriptor. + * It checks if the given hardware is initialized and if the given hardware is permitted to be deinitialized. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Uninitialization status. + * \retval -1 The passed parameters were invalid or the interface is already deinitialized + * \retval 0 The de-initialization is completed successfully + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c); + +/** + * \brief Set the slave device address + * + * This function sets the next transfer target slave I2C device address. + * It takes no effect to any already started access. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] addr The slave address to access + * \param[in] addr_len The slave address length, can be I2C_M_TEN or I2C_M_SEVEN + * + * \return Masked slave address. The mask is a maximum 10-bit address, and 10th + * bit is set if a 10-bit address is used + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len); + +/** + * \brief Set baudrate + * + * This function sets the I2C device to the specified baudrate. + * It only takes effect when the hardware is disabled. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] clkrate Unused parameter. Should always be 0 + * \param[in] baudrate The baudrate value set to master + * + * \return Whether successfully set the baudrate + * \retval -1 The passed parameters were invalid or the device is already enabled + * \retval 0 The baudrate set is completed successfully + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate); + +/** + * \brief Sync version of enable hardware + * + * This function enables the I2C device, and then waits for this enabling operation to be done + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Whether successfully enable the device + * \retval -1 The passed parameters were invalid or the device enable failed + * \retval 0 The hardware enabling is completed successfully + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c); + +/** + * \brief Sync version of disable hardware + * + * This function disables the I2C device and then waits for this disabling operation to be done + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Whether successfully disable the device + * \retval -1 The passed parameters were invalid or the device disable failed + * \retval 0 The hardware disabling is completed successfully + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c); + +/** + * \brief Sync version of write command to I2C slave + * + * This function will write the value to a specified register in the I2C slave device and + * then wait for this operation to be done. + * + * The sequence of this routine is + * sta->address(write)->ack->reg address->ack->resta->address(write)->ack->reg value->nack->stt + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] reg The internal address/register of the I2C slave device + * \param[in] buffer The buffer holding data to write to the I2C slave device + * \param[in] length The length (in bytes) to write to the I2C slave device + * + * \return Whether successfully write to the device + * \retval <0 The passed parameters were invalid or write fail + * \retval 0 Writing to register is completed successfully + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length); + +/** + * \brief Sync version of read register value from I2C slave + * + * This function will read a byte value from a specified register in the I2C slave device and + * then wait for this operation to be done. + * + * The sequence of this routine is + * sta->address(write)->ack->reg address->ack->resta->address(read)->ack->reg value->nack->stt + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] reg The internal address/register of the I2C slave device + * \param[in] buffer The buffer to hold the read data from the I2C slave device + * \param[in] length The length (in bytes) to read from the I2C slave device + * + * \return Whether successfully read from the device + * \retval <0 The passed parameters were invalid or read fail + * \retval 0 Reading from register is completed successfully + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length); + +/** + * \brief Sync version of transfer message to/from the I2C slave + * + * This function will transfer a message between the I2C slave and the master. This function will wait for the operation + * to be done. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] msg An i2c_m_msg struct + * + * \return The status of the operation + * \retval 0 Operation completed successfully + * \retval <0 Operation failed + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg); + +/** + * \brief Sync version of send stop condition on the i2c bus + * + * This function will create a stop condition on the i2c bus to release the bus + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return The status of the operation + * \retval 0 Operation completed successfully + * \retval <0 Operation failed + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c); + +/** + * \brief Return I/O descriptor for this I2C instance + * + * This function will return a I/O instance for this I2C driver instance + * + * \param[in] i2c_m_sync_desc An I2C descriptor, which is used to communicate through I2C + * \param[in] io_descriptor A pointer to an I/O descriptor pointer type + * + * \return Error code + * \retval 0 No error detected + * \retval <0 Error code + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t i2c_m_sync_get_version(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/microchip/same54/bsp/hal/include/hal_mac_async.h b/bsp/microchip/same54/bsp/hal/include/hal_mac_async.h new file mode 100644 index 0000000000..8d54d7ec32 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hal_mac_async.h @@ -0,0 +1,260 @@ +/** + * \file + * + * \brief MAC functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef HAL_MAC_ASYNC_H_INCLUDED +#define HAL_MAC_ASYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_mac_async + * + *@{ + */ + +/** + * \brief MAC descriptor + * + * The MAC descriptor forward declaration. + */ +struct mac_async_descriptor; + +/** + * \brief MAC callback type + * + * \param[in] descr A MAC descriptor + */ +typedef void (*mac_async_cb_t)(struct mac_async_descriptor *const descr); + +/** + * \brief MAC callbacks + */ +struct mac_async_callbacks { + mac_async_cb_t receive; + mac_async_cb_t transmit; +}; + +/** + * \brief MAC descriptor + */ +struct mac_async_descriptor { + struct _mac_async_device dev; /*!< MAC HPL device descriptor */ + struct mac_async_callbacks cb; /*!< MAC Callback handlers */ +}; + +/** + * Callback for MAC interrupt + */ +typedef void (*mac_cb)(struct mac_async_descriptor *const descr); + +/** + * \brief Initialize the MAC driver + * + * \param[in] descr A MAC descriptor to init. + * \param[in] hw Hardware instance pointer. + * + * \return Operation status. + * \retval ERR_NONE Success. + + */ +int32_t mac_async_init(struct mac_async_descriptor *const descr, void *const dev); + +/** + * \brief Deinitialize the MAC driver + * + * \param[in] descr A MAC descriptor to deinitialize. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_deinit(struct mac_async_descriptor *const descr); + +/** \brief Enable the MAC + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_enable(struct mac_async_descriptor *const descr); + +/** + * \brief Disable the MAC + * + * \param[in] descr Pointer to the HAL MAC descriptor + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_disable(struct mac_async_descriptor *const descr); + +/** + * \brief Write raw data to MAC + * + * Write the raw data to the MAC that will be transmitted + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] buf Pointer to the data buffer. + * \param[in] len Length of the data buffer. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_write(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len); + +/** + * \brief Read raw data from MAC + * + * Read received raw data from MAC + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] buffer Pointer to the data buffer. If the pointer is NULL, then the + * frame will be discarded. + * \param[in] length The max. length of the data buffer to be read. If the length is zero, + * then the frame will be discard + * + * \return Number of bytes that received + */ +uint32_t mac_async_read(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len); + +/** + * \brief Get next valid package length + * + * Get next valid package length from the MAC. The application can use this function + * to fetch the length of the next package, malloc a buffer with this + * length, and then invoke mac_async_read to read out the package data. + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * + * \return The number of bytes in the next package that can be read. + */ +uint32_t mac_async_read_len(struct mac_async_descriptor *const descr); + +/** + * \brief Enable the MAC IRQ + * + * \param[in] descr Pointer to the HAL MAC descriptor + */ +void mac_async_enable_irq(struct mac_async_descriptor *const descr); + +/** + * \brief Disable the MAC IRQ + * + * \param[in] descr Pointer to the HAL MAC descriptor + */ +void mac_async_disable_irq(struct mac_async_descriptor *const descr); + +/** + * \brief Register the MAC callback function + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] type Callback function type. + * \param[in] func A callback function. Passing NULL will de-register any + * registered callback. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_register_callback(struct mac_async_descriptor *const descr, const enum mac_async_cb_type type, + const FUNC_PTR func); + +/** + * \brief Set MAC filter + * + * Set MAC filter. Ethernet frames matching the filter, will be received. + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] index MAC filter index. Start from 0. The maximum value depends on + * the hardware specifications. + * \param[in] filter Pointer to the filter descriptor. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_set_filter(struct mac_async_descriptor *const descr, uint8_t index, struct mac_async_filter *filter); + +/** + * \brief Set MAC filter (expanded). + * + * Set MAC filter. The Ethernet frames matching the filter, will be received. + * + * \param[in] descr Pointer to the HAL MAC descriptor + * \param[in] mac MAC address + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_set_filter_ex(struct mac_async_descriptor *const descr, uint8_t mac[6]); + +/** + * \brief Write PHY register + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] val Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_write_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t val); + +/** + * \brief Read PHY register + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] val Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_read_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t *val); + +/** + * \brief Get the MAC driver version + */ +uint32_t mac_async_get_version(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_MAC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hal_usart_async.h b/bsp/microchip/same54/bsp/hal/include/hal_usart_async.h new file mode 100644 index 0000000000..3a6de391db --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hal_usart_async.h @@ -0,0 +1,339 @@ +/** + * \file + * + * \brief USART related functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_USART_ASYNC_H_INCLUDED +#define _HAL_USART_ASYNC_H_INCLUDED + +#include "hal_io.h" +#include +#include + +/** + * \addtogroup doc_driver_hal_usart_async + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief USART descriptor + * + * The USART descriptor forward declaration. + */ +struct usart_async_descriptor; + +/** + * \brief USART callback type + */ +typedef void (*usart_cb_t)(const struct usart_async_descriptor *const descr); + +/** + * \brief USART callback types + */ +enum usart_async_callback_type { USART_ASYNC_RXC_CB, USART_ASYNC_TXC_CB, USART_ASYNC_ERROR_CB }; + +/** + * \brief USART callbacks + */ +struct usart_async_callbacks { + usart_cb_t tx_done; + usart_cb_t rx_done; + usart_cb_t error; +}; + +/** \brief USART status + * Status descriptor holds the current status of transfer. + */ +struct usart_async_status { + /** Status flags */ + uint32_t flags; + /** Number of characters transmitted */ + uint16_t txcnt; + /** Number of characters receviced */ + uint16_t rxcnt; +}; + +/** + * \brief Asynchronous USART descriptor structure + */ +struct usart_async_descriptor { + struct io_descriptor io; + struct _usart_async_device device; + struct usart_async_callbacks usart_cb; + uint32_t stat; + + struct ringbuffer rx; + uint16_t tx_por; + uint8_t * tx_buffer; + uint16_t tx_buffer_length; +}; + +/** USART write busy */ +#define USART_ASYNC_STATUS_BUSY 0x0001 + +/** + * \brief Initialize USART interface + * + * This function initializes the given I/O descriptor to be used as USART + * interface descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[out] descr A USART descriptor which is used to communicate via the USART + * \param[in] hw The pointer to the hardware instance + * \param[in] rx_buffer An RX buffer + * \param[in] rx_buffer_length The length of the buffer above + * \param[in] func The pointer to a set of function pointers + * + * \return Initialization status. + * \retval -1 Passed parameters were invalid or the interface is already + * initialized + * \retval 0 The initialization is completed successfully + */ +int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *const rx_buffer, + const uint16_t rx_buffer_length, void *const func); + +/** + * \brief Deinitialize USART interface + * + * This function deinitializes the given I/O descriptor. + * It checks if the given hardware is initialized and if the given hardware + * is permitted to be deinitialized. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return De-initialization status. + */ +int32_t usart_async_deinit(struct usart_async_descriptor *const descr); + +/** + * \brief Enable USART interface + * + * Enables the USART interface + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return Enabling status. + */ +int32_t usart_async_enable(struct usart_async_descriptor *const descr); + +/** + * \brief Disable USART interface + * + * Disables the USART interface + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return Disabling status. + */ +int32_t usart_async_disable(struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve I/O descriptor + * + * This function retrieves the I/O descriptor of the given USART descriptor. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] io An I/O descriptor to retrieve + * + * \return The status of I/O descriptor retrieving. + */ +int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io); + +/** + * \brief Register USART callback + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] type Callback type + * \param[in] cb A callback function + * + * \return The status of callback assignment. + * \retval -1 Passed parameters were invalid or the interface is not initialized + * \retval 0 A callback is registered successfully + */ +int32_t usart_async_register_callback(struct usart_async_descriptor *const descr, + const enum usart_async_callback_type type, usart_cb_t cb); + +/** + * \brief Specify action for flow control pins + * + * This function sets action (or state) for flow control pins if + * the flow control is enabled. + * It sets state of flow control pins only if automatic support of + * the flow control is not supported by the hardware. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] state A state to set the flow control pins + * + * \return The status of flow control action setup. + */ +int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr, + const union usart_flow_control_state state); + +/** + * \brief Set USART baud rate + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] baud_rate A baud rate to set + * + * \return The status of baud rate setting. + */ +int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate); + +/** + * \brief Set USART data order + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] data_order A data order to set + * + * \return The status of data order setting. + */ +int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order); + +/** + * \brief Set USART mode + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] mode A mode to set + * + * \return The status of mode setting. + */ +int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode); + +/** + * \brief Set USART parity + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] parity A parity to set + * + * \return The status of parity setting. + */ +int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity); + +/** + * \brief Set USART stop bits + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] stop_bits Stop bits to set + * + * \return The status of stop bits setting. + */ +int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits); + +/** + * \brief Set USART character size + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] size A character size to set + * + * \return The status of character size setting. + */ +int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, + const enum usart_character_size size); + +/** + * \brief Retrieve the state of flow control pins + * + * This function retrieves the flow control pins + * if the flow control is enabled. + * + * The function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case + * if the flow control is done by the hardware + * and the pins state cannot be read out. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] state The state of flow control pins + * + * \return The status of flow control state reading. + */ +int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr, + union usart_flow_control_state *const state); + +/** + * \brief Check if the USART transmitter is empty + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return The status of USART TX empty checking. + * \retval 0 The USART transmitter is not empty + * \retval 1 The USART transmitter is empty + */ +int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr); + +/** + * \brief Check if the USART receiver is not empty + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return The status of the USART RX empty checking. + * \retval 1 The USART receiver is not empty + * \retval 0 The USART receiver is empty + */ +int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve the current interface status + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] status The state of USART + * + * \return The status of USART status retrieving. + */ +int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status); + +/** + * \brief flush USART ringbuf + * + * This function flush USART RX ringbuf. + * + * \param[in] descr The pointer to USART descriptor + * + * \return ERR_NONE + */ +int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t usart_async_get_version(void); + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HAL_USART_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hal_usart_sync.h b/bsp/microchip/same54/bsp/hal/include/hal_usart_sync.h deleted file mode 100644 index 1ef22fc63f..0000000000 --- a/bsp/microchip/same54/bsp/hal/include/hal_usart_sync.h +++ /dev/null @@ -1,247 +0,0 @@ -/** - * \file - * - * \brief USART related functionality declaration. - * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#ifndef _HAL_SYNC_USART_H_INCLUDED -#define _HAL_SYNC_USART_H_INCLUDED - -#include "hal_io.h" -#include - -/** - * \addtogroup doc_driver_hal_usart_sync - * - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Synchronous USART descriptor - */ -struct usart_sync_descriptor { - struct io_descriptor io; - struct _usart_sync_device device; -}; - -/** - * \brief Initialize USART interface - * - * This function initializes the given I/O descriptor to be used - * as USART interface descriptor. - * It checks if the given hardware is not initialized and - * if the given hardware is permitted to be initialized. - * - * \param[out] descr A USART descriptor which is used to communicate via USART - * \param[in] hw The pointer to hardware instance - * \param[in] func The pointer to as set of functions pointers - * - * \return Initialization status. - */ -int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func); - -/** - * \brief Deinitialize USART interface - * - * This function deinitializes the given I/O descriptor. - * It checks if the given hardware is initialized and - * if the given hardware is permitted to be deinitialized. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return De-initialization status. - */ -int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr); - -/** - * \brief Enable USART interface - * - * Enables the USART interface - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return Enabling status. - */ -int32_t usart_sync_enable(struct usart_sync_descriptor *const descr); - -/** - * \brief Disable USART interface - * - * Disables the USART interface - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return Disabling status. - */ -int32_t usart_sync_disable(struct usart_sync_descriptor *const descr); - -/** - * \brief Retrieve I/O descriptor - * - * This function retrieves the I/O descriptor of the given USART descriptor. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[out] io An I/O descriptor to retrieve - * - * \return The status of the I/O descriptor retrieving. - */ -int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io); - -/** - * \brief Specify action for flow control pins - * - * This function sets the action (or state) for the flow control pins - * if the flow control is enabled. - * It sets the state of flow control pins only if the automatic support of - * the flow control is not supported by the hardware. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] state A state to set the flow control pins - * - * \return The status of flow control action setup. - */ -int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr, - const union usart_flow_control_state state); - -/** - * \brief Set USART baud rate - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] baud_rate A baud rate to set - * - * \return The status of baud rate setting. - */ -int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate); - -/** - * \brief Set USART data order - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] data_order A data order to set - * - * \return The status of data order setting. - */ -int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order); - -/** - * \brief Set USART mode - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] mode A mode to set - * - * \return The status of mode setting. - */ -int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode); - -/** - * \brief Set USART parity - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] parity A parity to set - * - * \return The status of parity setting. - */ -int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity); - -/** - * \brief Set USART stop bits - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] stop_bits Stop bits to set - * - * \return The status of stop bits setting. - */ -int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits); - -/** - * \brief Set USART character size - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] size A character size to set - * - * \return The status of character size setting. - */ -int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size); - -/** - * \brief Retrieve the state of flow control pins - * - * This function retrieves the of flow control pins - * if the flow control is enabled. - * Function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case - * if the flow control is done by the hardware - * and the pins state cannot be read out. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[out] state The state of flow control pins - * - * \return The status of flow control state reading. - */ -int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr, - union usart_flow_control_state *const state); - -/** - * \brief Check if the USART transmitter is empty - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return The status of USART TX empty checking. - * \retval 0 The USART transmitter is not empty - * \retval 1 The USART transmitter is empty - */ -int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr); - -/** - * \brief Check if the USART receiver is not empty - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return The status of USART RX empty checking. - * \retval 1 The USART receiver is not empty - * \retval 0 The USART receiver is empty - */ -int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr); - -/** - * \brief Retrieve the current driver version - * - * \return Current driver version. - */ -uint32_t usart_sync_get_version(void); - -#ifdef __cplusplus -} -#endif -/**@}*/ -#endif /* _HAL_SYNC_USART_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hpl_adc_async.h b/bsp/microchip/same54/bsp/hal/include/hpl_adc_async.h new file mode 100644 index 0000000000..1aa4162409 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hpl_adc_async.h @@ -0,0 +1,264 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_ASYNC_H_INCLUDED +#define _HPL_ADC_ASYNC_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_async_adc_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include "hpl_adc_sync.h" +#include "hpl_irq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC device structure + * + * The ADC device structure forward declaration. + */ +struct _adc_async_device; + +/** + * \brief ADC callback types + */ +enum _adc_async_callback_type { ADC_ASYNC_DEVICE_CONVERT_CB, ADC_ASYNC_DEVICE_MONITOR_CB, ADC_ASYNC_DEVICE_ERROR_CB }; + +/** + * \brief ADC interrupt callbacks + */ +struct _adc_async_callbacks { + void (*window_cb)(struct _adc_async_device *device, const uint8_t channel); + void (*error_cb)(struct _adc_async_device *device, const uint8_t channel); +}; + +/** + * \brief ADC channel interrupt callbacks + */ +struct _adc_async_ch_callbacks { + void (*convert_done)(struct _adc_async_device *device, const uint8_t channel, const uint16_t data); +}; + +/** + * \brief ADC descriptor device structure + */ +struct _adc_async_device { + struct _adc_async_callbacks adc_async_cb; + struct _adc_async_ch_callbacks adc_async_ch_cb; + struct _irq_descriptor irq; + void * hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_async_deinit(struct _adc_async_device *const device); + +/** + * \brief Enable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_async_convert(struct _adc_async_device *const device); + +/** + * \brief Retrieve the conversion result + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * The result value + */ +uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set lower threshold + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower threshold to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state); + +/** + * \brief Enable/disable ADC channel interrupt + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] type The type of interrupt to disable/enable if applicable + * \param[in] state Enable or disable + */ +void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel, + const enum _adc_async_callback_type type, const bool state); + +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hpl_adc_dma.h b/bsp/microchip/same54/bsp/hal/include/hpl_adc_dma.h new file mode 100644 index 0000000000..bb3a054106 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hpl_adc_dma.h @@ -0,0 +1,243 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_DMA_H_INCLUDED +#define _HPL_ADC_DMA_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_dma_adc_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC device structure + * + * The ADC device structure forward declaration. + */ +struct _adc_dma_device; + +/** + * \brief ADC callback types + */ +enum _adc_dma_callback_type { ADC_DMA_DEVICE_COMPLETE_CB, ADC_DMA_DEVICE_ERROR_CB }; + +/** + * \brief ADC interrupt callbacks + */ +struct _adc_dma_callbacks { + void (*complete)(struct _adc_dma_device *device, const uint16_t data); + void (*error)(struct _adc_dma_device *device); +}; + +/** + * \brief ADC descriptor device structure + */ +struct _adc_dma_device { + struct _adc_dma_callbacks adc_dma_cb; + struct _irq_descriptor irq; + void * hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_dma_init(struct _adc_dma_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_dma_deinit(struct _adc_dma_device *const device); + +/** + * \brief Enable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_dma_enable_channel(struct _adc_dma_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_dma_disable_channel(struct _adc_dma_device *const device, const uint8_t channel); + +/** + * \brief Return address of ADC DMA source + * + * \param[in] device The pointer to ADC device instance + * + * \return ADC DMA source address + */ +uint32_t _adc_get_source_for_dma(struct _adc_dma_device *const device); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_dma_get_data_size(const struct _adc_dma_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_dma_is_conversion_done(const struct _adc_dma_device *const device); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_dma_convert(struct _adc_dma_device *const device); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_dma_set_reference_source(struct _adc_dma_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_dma_set_resolution(struct _adc_dma_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_dma_set_inputs(struct _adc_dma_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_dma_set_conversion_mode(struct _adc_dma_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_dma_set_channel_differential_mode(struct _adc_dma_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_dma_set_channel_gain(struct _adc_dma_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_dma_set_window_mode(struct _adc_dma_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set thresholds + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower thresholds to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_dma_set_thresholds(struct _adc_dma_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_dma_get_threshold_state(const struct _adc_dma_device *const device, adc_threshold_status_t *const state); + +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_DMA_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hpl_adc_sync.h b/bsp/microchip/same54/bsp/hal/include/hpl_adc_sync.h new file mode 100644 index 0000000000..3bfbc61d9c --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hpl_adc_sync.h @@ -0,0 +1,271 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_SYNC_H_INCLUDED +#define _HPL_ADC_SYNC_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_adc_sync_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include "compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC reference source + */ +typedef uint8_t adc_reference_t; + +/** + * \brief ADC resolution + */ +typedef uint8_t adc_resolution_t; + +/** + * \brief ADC positive input for channel + */ +typedef uint8_t adc_pos_input_t; + +/** + * \brief ADC negative input for channel + */ +typedef uint8_t adc_neg_input_t; + +/** + * \brief ADC threshold + */ +typedef uint16_t adc_threshold_t; + +/** + * \brief ADC gain + */ +typedef uint8_t adc_gain_t; + +/** + * \brief ADC conversion mode + */ +enum adc_conversion_mode { ADC_CONVERSION_MODE_SINGLE_CONVERSION = 0, ADC_CONVERSION_MODE_FREERUN }; + +/** + * \brief ADC differential mode + */ +enum adc_differential_mode { ADC_DIFFERENTIAL_MODE_SINGLE_ENDED = 0, ADC_DIFFERENTIAL_MODE_DIFFERENTIAL }; + +/** + * \brief ADC window mode + */ +typedef uint8_t adc_window_mode_t; + +/** + * \brief ADC threshold status + */ +typedef bool adc_threshold_status_t; + +/** + * \brief ADC sync descriptor device structure + */ +struct _adc_sync_device { + void *hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_sync_deinit(struct _adc_sync_device *const device); + +/** + * \brief Enable ADC + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_sync_convert(struct _adc_sync_device *const device); + +/** + * \brief Retrieve the conversion result + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The result value of channel + */ +uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set threshold + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower threshold to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state); +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/include/hpl_mac_async.h b/bsp/microchip/same54/bsp/hal/include/hpl_mac_async.h new file mode 100644 index 0000000000..20802ef9d6 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/include/hpl_mac_async.h @@ -0,0 +1,280 @@ +/** + * \file + * + * \brief MAC functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef HPL_MAC_ASYNC_H_INCLUDED +#define HPL_MAC_ASYNC_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +/** + * \addtogroup hpl__mac__async__group MAC HPL APIs + * + *@{ + */ + +/** + * \brief MAC device descriptor Forward declaration + */ +struct _mac_async_device; + +/** + * \brief MAC callback type + * + * \param[in] dev An MAC device descriptor + */ +typedef void (*_mac_async_cb_t)(struct _mac_async_device *const dev); + +/** + * \brief MAC callbacks + */ +struct _mac_async_callbacks { + _mac_async_cb_t transmited; /*!< Frame received */ + _mac_async_cb_t received; /*!< Frame transmited */ +}; + +/** + * \brief MAC device descriptor + */ +struct _mac_async_device { + void * hw; /*!< Hardware module instance handler */ + struct _mac_async_callbacks cb; /*!< Callback handler */ + struct _irq_descriptor irq; /*!< IRQ handler */ +}; + +/** + * \brief MAC callback types + */ +enum mac_async_cb_type { + MAC_ASYNC_RECEIVE_CB, /*!< One or more frame been received */ + MAC_ASYNC_TRANSMIT_CB /*!< One or more frame been transmited */ +}; + +struct mac_async_filter { + uint8_t mac[6]; /*!< Destination address */ + uint8_t tid[2]; /*!< Type ID, 0x0600 IP package */ + bool tid_enable; /*!< Enable TID matching */ +}; +/** + * \brief Initialize the MAC driver + * + * Initialize the MAC driver + * + * \param[in] dev A MAC device descriptor to deinit + * \param[in] hw Hardware module instance + * + * \return Operation status. + * \retval ERR_NONE Success. + + */ +int32_t _mac_async_init(struct _mac_async_device *const dev, void *const hw); + +/** + * \brief Deinitialize the MAC driver + * + * Deinitialize the MAC driver + * + * \param[in] descr A MAC device descriptor to deinit + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_deinit(struct _mac_async_device *const dev); + +/** \brief Enable the MAC + * + * Enable the MAC + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_enable(struct _mac_async_device *const dev); + +/** + * \brief Disable the MAC + * + * Disable the MAC + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_disable(struct _mac_async_device *const dev); + +/** + * \brief Write raw data to MAC + * + * Write raw data to MAC that will be transmitted. + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] buffer Pointer to the data buffer + * \param[in] length Length of the data buffer + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_write(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len); + +/** + * \brief Read received raw data from MAC + * + * Read received raw data from MAC + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] buffer Pointer to the data buffer. if pointer is null, then the + * frame will be discard. + * \param[in] length Max Length of the data buffer to be read. if len is zero, + * then the frame will be discard + * + * \return Number of bytes that have been received + */ +uint32_t _mac_async_read(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len); + +/** + * \brief Get next valid package length + * + * Get next valid package length from MAC. Application can use this function + * to fetch the length of the next package, malloc the a buffer whit this + * length, and then invoke mac_async_read to read out the package data. + * + * \param[in] dev Pointer to the HPL MAC device descriptor. + * + * \return Number of bytes that next package can be read. + */ +uint32_t _mac_async_read_len(struct _mac_async_device *const dev); + +/** + * \brief Enable the MAC IRQ + * + * Enable the MAC IRQ + * + * \param[in] dev Pointer to the HPL MAC device descriptor + */ +void _mac_async_enable_irq(struct _mac_async_device *const dev); + +/** + * \brief Disable the MAC IRQ + * + * Disable the MAC IRQ + * + * \param[in] dev Pointer to the HPL MAC device descriptor + */ +void _mac_async_disable_irq(struct _mac_async_device *const dev); + +/** + * \brief Register the MAC callback + * + * Register the MAC callback + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] type Callback function type. + * \param[in] func A callback function, passing NULL will de-register + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_register_callback(struct _mac_async_device *const dev, const enum mac_async_cb_type type, + const FUNC_PTR func); + +/** + * \brief Set MAC filter + * + * Set MAC filter, ethernet frames which match the filter will be received. + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] index Mac filter index, start from 0, max value depends on + * hardware specificaions. + * \param[in] filter Pointer to the filter descriptor. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_set_filter(struct _mac_async_device *const dev, uint8_t index, struct mac_async_filter *filter); + +/** + * \brief Set MAC filter (expaneded) + * + * Set MAC filter, ethernet frames which match the filter will be received. + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] mac Mac address + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_set_filter_ex(struct _mac_async_device *const dev, uint8_t mac[6]); + +/** + * \brief Write PHY register + * + * Write PHY register + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] data Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_write_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t data); + +/** + * \brief Read PHY register + * + * Read PHY register + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] data Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_read_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t *val); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* HPL_MAC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/src/hal_adc_sync.c b/bsp/microchip/same54/bsp/hal/src/hal_adc_sync.c new file mode 100644 index 0000000000..33e0d92976 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/src/hal_adc_sync.c @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief ADC functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +/** + * \brief Indicates HAL being compiled. Must be defined before including. + */ +#define _COMPILING_HAL + +#include "hal_adc_sync.h" +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Maximum amount of ADC interface instances + */ +#define MAX_ADC_AMOUNT ADC_INST_NUM + +/** + * \brief Initialize ADC + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func) +{ + ASSERT(descr && hw); + + return _adc_sync_init(&descr->device, hw); +} + +/** + * \brief Deinitialize ADC + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr) +{ + ASSERT(descr); + _adc_sync_deinit(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Enable ADC + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_enable_channel(&descr->device, channel); + + return ERR_NONE; +} + +/** + * \brief Disable ADC + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_disable_channel(&descr->device, channel); + return ERR_NONE; +} + +/* + * \brief Read data from ADC + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length) +{ + uint8_t data_size; + uint16_t offset = 0; + + ASSERT(descr && buffer && length); + data_size = _adc_sync_get_data_size(&descr->device); + ASSERT(!(length % data_size)); + + do { + uint16_t result; + _adc_sync_convert(&descr->device); + + while (!_adc_sync_is_channel_conversion_done(&descr->device, channel)) + ; + + result = _adc_sync_read_channel_data(&descr->device, channel); + buffer[offset] = result; + if (1 < data_size) { + buffer[offset + 1] = result >> 8; + } + offset += data_size; + } while (offset < length); + + return offset; +} + +/** + * \brief Set ADC reference source + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference) +{ + ASSERT(descr); + _adc_sync_set_reference_source(&descr->device, reference); + + return ERR_NONE; +} + +/** + * \brief Set ADC resolution + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution) +{ + ASSERT(descr); + _adc_sync_set_resolution(&descr->device, resolution); + + return ERR_NONE; +} + +/** + * \brief Set ADC input source of a channel + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_set_inputs(&descr->device, pos_input, neg_input, channel); + + return ERR_NONE; +} + +/** + * \brief Set ADC thresholds + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + ASSERT(descr); + _adc_sync_set_thresholds(&descr->device, low_threshold, up_threshold); + + return ERR_NONE; +} + +/** + * \brief Set ADC gain + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, const adc_gain_t gain) +{ + ASSERT(descr); + _adc_sync_set_channel_gain(&descr->device, channel, gain); + + return ERR_NONE; +} + +/** + * \brief Set ADC conversion mode + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode) +{ + ASSERT(descr); + _adc_sync_set_conversion_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC differential mode + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode) +{ + ASSERT(descr); + _adc_sync_set_channel_differential_mode(&descr->device, channel, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC window mode + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode) +{ + ASSERT(descr); + _adc_sync_set_window_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Retrieve threshold state + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, adc_threshold_status_t *const state) +{ + ASSERT(descr && state); + _adc_sync_get_threshold_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Check if conversion is complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + return _adc_sync_is_channel_conversion_done(&descr->device, channel); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t adc_sync_get_version(void) +{ + return DRIVER_VERSION; +} + +//@} diff --git a/bsp/microchip/same54/bsp/hal/src/hal_i2c_m_sync.c b/bsp/microchip/same54/bsp/hal/src/hal_i2c_m_sync.c new file mode 100644 index 0000000000..30821a27c3 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/src/hal_i2c_m_sync.c @@ -0,0 +1,258 @@ +/** + * \file + * + * \brief I/O I2C related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include +#include +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Sync version of I2C I/O read + */ +static int32_t i2c_m_sync_read(struct io_descriptor *io, uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of I2C I/O write + */ +static int32_t i2c_m_sync_write(struct io_descriptor *io, const uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP; + msg.buffer = (uint8_t *)buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of i2c initialize + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw) +{ + int32_t init_status; + ASSERT(i2c); + + init_status = _i2c_m_sync_init(&i2c->device, hw); + if (init_status) { + return init_status; + } + + /* Init I/O */ + i2c->io.read = i2c_m_sync_read; + i2c->io.write = i2c_m_sync_write; + + return ERR_NONE; +} + +/** + * \brief deinitialize + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c) +{ + int32_t status; + ASSERT(i2c); + + status = _i2c_m_sync_deinit(&i2c->device); + if (status) { + return status; + } + + i2c->io.read = NULL; + i2c->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c enable + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_enable(&i2c->device); +} + +/** + * \brief Sync version of i2c disable + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_disable(&i2c->device); +} + +/** + * \brief Sync version of i2c set slave address + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len) +{ + return i2c->slave_addr = (addr & 0x3ff) | (addr_len & I2C_M_TEN); +} + +/** + * \brief Sync version of i2c set baudrate + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate) +{ + return _i2c_m_sync_set_baudrate(&i2c->device, clkrate, baudrate); +} + +/** + * \brief Sync version of i2c write command + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c read command + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c transfer command + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg) +{ + return _i2c_m_sync_transfer(&i2c->device, msg); +} + +/** + * \brief Sync version of i2c send stop condition command + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c) +{ + return _i2c_m_sync_send_stop(&i2c->device); +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io) +{ + *io = &i2c->io; + return ERR_NONE; +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t i2c_m_sync_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/bsp/microchip/same54/bsp/hal/src/hal_mac_async.c b/bsp/microchip/same54/bsp/hal/src/hal_mac_async.c new file mode 100644 index 0000000000..a7512c8bee --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/src/hal_mac_async.c @@ -0,0 +1,222 @@ +/** + * \file + * + * \brief MAC functionality implementation. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include +#include +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/* Private function */ +static void mac_read_cb(struct _mac_async_device *dev); +static void mac_write_cb(struct _mac_async_device *dev); + +/** + * \brief Initialize the MAC driver + */ +int32_t mac_async_init(struct mac_async_descriptor *const descr, void *const hw) +{ + ASSERT(descr && hw); + + return _mac_async_init(&descr->dev, hw); +} + +/** + * \brief Deinitialize the MAC driver + */ +int32_t mac_async_deinit(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_deinit(&descr->dev); +} + +/** + * \brief Enable the MAC + */ +int32_t mac_async_enable(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_enable(&descr->dev); +} +/** + * \brief Disable the MAC + */ +int32_t mac_async_disable(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_disable(&descr->dev); +} +/** + * \brief Write raw data to MAC + */ +int32_t mac_async_write(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len) +{ + ASSERT(descr && buf && len); + + return _mac_async_write(&descr->dev, buf, len); +} + +/** + * \brief Read raw data from MAC + */ +uint32_t mac_async_read(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len) +{ + ASSERT(descr); + + return _mac_async_read(&descr->dev, buf, len); +} + +/** + * \brief Get next valid package length + */ +uint32_t mac_async_read_len(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_read_len(&descr->dev); +} +/** + * \brief Enable the MAC IRQ + */ +void mac_async_enable_irq(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + _mac_async_enable_irq(&descr->dev); +} + +/** + * \brief Disable the MAC IRQ + */ +void mac_async_disable_irq(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + _mac_async_disable_irq(&descr->dev); +} + +/** + * \brief Register the MAC callback function + */ +int32_t mac_async_register_callback(struct mac_async_descriptor *const descr, const enum mac_async_cb_type type, + const FUNC_PTR func) +{ + ASSERT(descr); + + switch (type) { + case MAC_ASYNC_RECEIVE_CB: + descr->cb.receive = (mac_async_cb_t)func; + return _mac_async_register_callback(&descr->dev, type, (func == NULL) ? NULL : (FUNC_PTR)mac_read_cb); + case MAC_ASYNC_TRANSMIT_CB: + descr->cb.transmit = (mac_async_cb_t)func; + return _mac_async_register_callback(&descr->dev, type, (func == NULL) ? NULL : (FUNC_PTR)mac_write_cb); + default: + return ERR_INVALID_ARG; + } +} +/** + * \brief Set MAC filter + */ +int32_t mac_async_set_filter(struct mac_async_descriptor *const descr, uint8_t index, struct mac_async_filter *filter) +{ + ASSERT(descr && filter); + + return _mac_async_set_filter(&descr->dev, index, filter); +} + +/** + * \brief Set MAC filter (expaneded) + */ +int32_t mac_async_set_filter_ex(struct mac_async_descriptor *const descr, uint8_t mac[6]) +{ + ASSERT(descr && mac); + + return _mac_async_set_filter_ex(&descr->dev, mac); +} + +/** + * \brief Write PHY register + */ +int32_t mac_async_write_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t val) +{ + ASSERT(descr); + + return _mac_async_write_phy_reg(&descr->dev, addr, reg, val); +} +/** + * \brief Read PHY register + */ +int32_t mac_async_read_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t *val) +{ + ASSERT(descr && val); + + return _mac_async_read_phy_reg(&descr->dev, addr, reg, val); +} +/** + * \brief Get MAC driver version + */ +uint32_t mac_async_get_version(void) +{ + return DRIVER_VERSION; +} + +/** + * \internal data receivced handler + * + * \param[in] dev The pointer to MAC device structure + */ +static void mac_read_cb(struct _mac_async_device *dev) +{ + struct mac_async_descriptor *const descr = CONTAINER_OF(dev, struct mac_async_descriptor, dev); + + if (descr->cb.receive) { + descr->cb.receive(descr); + } +} + +/** + * \internal data transmit handler + * + * \param[in] dev The pointer to MAC device structure + */ +static void mac_write_cb(struct _mac_async_device *dev) +{ + struct mac_async_descriptor *const descr = CONTAINER_OF(dev, struct mac_async_descriptor, dev); + + if (descr->cb.transmit) { + descr->cb.transmit(descr); + } +} diff --git a/bsp/microchip/same54/bsp/hal/src/hal_sleep.c b/bsp/microchip/same54/bsp/hal/src/hal_sleep.c index 89472f156a..5decfb6c9c 100644 --- a/bsp/microchip/same54/bsp/hal/src/hal_sleep.c +++ b/bsp/microchip/same54/bsp/hal/src/hal_sleep.c @@ -38,7 +38,7 @@ * \brief Driver version */ #define DRIVER_VERSION 0x00000001u - +#if 0 /** * \brief Set the sleep mode of the device and put the MCU to sleep * @@ -61,7 +61,7 @@ int sleep(const uint8_t mode) return ERR_NONE; } - +#endif /** * \brief Retrieve the current driver version * diff --git a/bsp/microchip/same54/bsp/hal/src/hal_usart_async.c b/bsp/microchip/same54/bsp/hal/src/hal_usart_async.c new file mode 100644 index 0000000000..f07b266124 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/src/hal_usart_async.c @@ -0,0 +1,420 @@ +/** + * \file + * + * \brief I/O USART related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_usart_async.h" +#include +#include +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length); +static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length); +static void usart_process_byte_sent(struct _usart_async_device *device); +static void usart_transmission_complete(struct _usart_async_device *device); +static void usart_error(struct _usart_async_device *device); +static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data); + +/** + * \brief Initialize usart interface + */ +int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *rx_buffer, + uint16_t rx_buffer_length, void *const func) +{ + int32_t init_status; + ASSERT(descr && hw && rx_buffer && rx_buffer_length); + + if (ERR_NONE != ringbuffer_init(&descr->rx, rx_buffer, rx_buffer_length)) { + return ERR_INVALID_ARG; + } + init_status = _usart_async_init(&descr->device, hw); + if (init_status) { + return init_status; + } + + descr->io.read = usart_async_read; + descr->io.write = usart_async_write; + + descr->device.usart_cb.tx_byte_sent = usart_process_byte_sent; + descr->device.usart_cb.rx_done_cb = usart_fill_rx_buffer; + descr->device.usart_cb.tx_done_cb = usart_transmission_complete; + descr->device.usart_cb.error_cb = usart_error; + + return ERR_NONE; +} + +/** + * \brief Deinitialize usart interface + */ +int32_t usart_async_deinit(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_deinit(&descr->device); + descr->io.read = NULL; + descr->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Enable usart interface + */ +int32_t usart_async_enable(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_enable(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Disable usart interface + */ +int32_t usart_async_disable(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_disable(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io) +{ + ASSERT(descr && io); + + *io = &descr->io; + return ERR_NONE; +} + +/** + * \brief Register usart callback + */ +int32_t usart_async_register_callback(struct usart_async_descriptor *const descr, + const enum usart_async_callback_type type, usart_cb_t cb) +{ + ASSERT(descr); + + switch (type) { + case USART_ASYNC_RXC_CB: + descr->usart_cb.rx_done = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_RX_DONE, NULL != cb); + break; + case USART_ASYNC_TXC_CB: + descr->usart_cb.tx_done = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_TX_DONE, NULL != cb); + break; + case USART_ASYNC_ERROR_CB: + descr->usart_cb.error = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_ERROR, NULL != cb); + break; + default: + return ERR_INVALID_ARG; + } + + return ERR_NONE; +} + +/** + * \brief Specify action for flow control pins + */ +int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr, + const union usart_flow_control_state state) +{ + ASSERT(descr); + _usart_async_set_flow_control_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Set usart baud rate + */ +int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate) +{ + ASSERT(descr); + _usart_async_set_baud_rate(&descr->device, baud_rate); + + return ERR_NONE; +} + +/** + * \brief Set usart data order + */ +int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order) +{ + ASSERT(descr); + _usart_async_set_data_order(&descr->device, data_order); + + return ERR_NONE; +} + +/** + * \brief Set usart mode + */ +int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode) +{ + ASSERT(descr); + _usart_async_set_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set usart parity + */ +int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity) +{ + ASSERT(descr); + _usart_async_set_parity(&descr->device, parity); + + return ERR_NONE; +} + +/** + * \brief Set usart stop bits + */ +int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits) +{ + ASSERT(descr); + _usart_async_set_stop_bits(&descr->device, stop_bits); + + return ERR_NONE; +} + +/** + * \brief Set usart character size + */ +int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, const enum usart_character_size size) +{ + ASSERT(descr); + _usart_async_set_character_size(&descr->device, size); + + return ERR_NONE; +} + +/** + * \brief Retrieve the state of flow control pins + */ +int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr, + union usart_flow_control_state *const state) +{ + ASSERT(descr && state); + *state = _usart_async_get_flow_control_state(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Check if the usart transmitter is empty + */ +int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + return _usart_async_is_byte_sent(&descr->device); +} + +/** + * \brief Check if the usart receiver is not empty + */ +int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + + return ringbuffer_num(&descr->rx) > 0; +} + +/** + * \brief Retrieve the current interface status + */ +int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status) +{ + ASSERT(descr); + + volatile uint32_t *tmp_stat = &(descr->stat); + volatile uint16_t *tmp_txcnt = &(descr->tx_por); + + if (status) { + status->flags = *tmp_stat; + status->txcnt = *tmp_txcnt; + status->rxcnt = ringbuffer_num(&descr->rx); + } + if (*tmp_stat & USART_ASYNC_STATUS_BUSY) { + return ERR_BUSY; + } + + return ERR_NONE; +} + +/** + * \brief flush usart rx ringbuf + */ +int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + + return ringbuffer_flush(&descr->rx); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t usart_async_get_version(void) +{ + return DRIVER_VERSION; +} + +/* + * \internal Write the given data to usart interface + * + * \param[in] descr The pointer to an io descriptor + * \param[in] buf Data to write to usart + * \param[in] length The number of bytes to write + * + * \return The number of bytes written. + */ +static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io); + + ASSERT(descr && buf && length); + + if (descr->tx_por != descr->tx_buffer_length) { + return ERR_NO_RESOURCE; + } + descr->tx_buffer = (uint8_t *)buf; + descr->tx_buffer_length = length; + descr->tx_por = 0; + descr->stat = USART_ASYNC_STATUS_BUSY; + _usart_async_enable_byte_sent_irq(&descr->device); + + return (int32_t)length; +} + +/* + * \internal Read data from usart interface + * + * \param[in] descr The pointer to an io descriptor + * \param[in] buf A buffer to read data to + * \param[in] length The size of a buffer + * + * \return The number of bytes read. + */ +static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) +{ + uint16_t was_read = 0; + uint32_t num; + struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io); + + ASSERT(descr && buf && length); + + CRITICAL_SECTION_ENTER() + num = ringbuffer_num(&descr->rx); + CRITICAL_SECTION_LEAVE() + + while ((was_read < num) && (was_read < length)) { + ringbuffer_get(&descr->rx, &buf[was_read++]); + } + + return (int32_t)was_read; +} + +/** + * \brief Process "byte is sent" interrupt + * + * \param[in] device The pointer to device structure + */ +static void usart_process_byte_sent(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + if (descr->tx_por != descr->tx_buffer_length) { + _usart_async_write_byte(&descr->device, descr->tx_buffer[descr->tx_por++]); + _usart_async_enable_byte_sent_irq(&descr->device); + } else { + _usart_async_enable_tx_done_irq(&descr->device); + } +} + +/** + * \brief Process completion of data sending + * + * \param[in] device The pointer to device structure + */ +static void usart_transmission_complete(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + descr->stat = 0; + if (descr->usart_cb.tx_done) { + descr->usart_cb.tx_done(descr); + } +} + +/** + * \brief Process byte reception + * + * \param[in] device The pointer to device structure + * \param[in] data Data read + */ +static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + ringbuffer_put(&descr->rx, data); + + if (descr->usart_cb.rx_done) { + descr->usart_cb.rx_done(descr); + } +} + +/** + * \brief Process error interrupt + * + * \param[in] device The pointer to device structure + */ +static void usart_error(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + descr->stat = 0; + if (descr->usart_cb.error) { + descr->usart_cb.error(descr); + } +} + +//@} diff --git a/bsp/microchip/same54/bsp/hal/src/hal_usart_sync.c b/bsp/microchip/same54/bsp/hal/src/hal_usart_sync.c deleted file mode 100644 index ab99c1d166..0000000000 --- a/bsp/microchip/same54/bsp/hal/src/hal_usart_sync.c +++ /dev/null @@ -1,276 +0,0 @@ -/** - * \file - * - * \brief I/O USART related functionality implementation. - * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#include "hal_usart_sync.h" -#include -#include - -/** - * \brief Driver version - */ -#define DRIVER_VERSION 0x00000001u - -static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length); -static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length); - -/** - * \brief Initialize usart interface - */ -int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func) -{ - int32_t init_status; - ASSERT(descr && hw); - init_status = _usart_sync_init(&descr->device, hw); - if (init_status) { - return init_status; - } - - descr->io.read = usart_sync_read; - descr->io.write = usart_sync_write; - - return ERR_NONE; -} - -/** - * \brief Uninitialize usart interface - */ -int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_deinit(&descr->device); - - descr->io.read = NULL; - descr->io.write = NULL; - - return ERR_NONE; -} - -/** - * \brief Enable usart interface - */ -int32_t usart_sync_enable(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_enable(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Disable usart interface - */ -int32_t usart_sync_disable(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_disable(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Retrieve I/O descriptor - */ -int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io) -{ - ASSERT(descr && io); - - *io = &descr->io; - return ERR_NONE; -} - -/** - * \brief Specify action for flow control pins - */ -int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr, - const union usart_flow_control_state state) -{ - ASSERT(descr); - _usart_sync_set_flow_control_state(&descr->device, state); - - return ERR_NONE; -} - -/** - * \brief Set usart baud rate - */ -int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate) -{ - ASSERT(descr); - _usart_sync_set_baud_rate(&descr->device, baud_rate); - - return ERR_NONE; -} - -/** - * \brief Set usart data order - */ -int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order) -{ - ASSERT(descr); - _usart_sync_set_data_order(&descr->device, data_order); - - return ERR_NONE; -} - -/** - * \brief Set usart mode - */ -int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode) -{ - ASSERT(descr); - _usart_sync_set_mode(&descr->device, mode); - - return ERR_NONE; -} - -/** - * \brief Set usart parity - */ -int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity) -{ - ASSERT(descr); - _usart_sync_set_parity(&descr->device, parity); - - return ERR_NONE; -} - -/** - * \brief Set usart stop bits - */ -int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits) -{ - ASSERT(descr); - _usart_sync_set_stop_bits(&descr->device, stop_bits); - - return ERR_NONE; -} - -/** - * \brief Set usart character size - */ -int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size) -{ - ASSERT(descr); - _usart_sync_set_character_size(&descr->device, size); - - return ERR_NONE; -} - -/** - * \brief Retrieve the state of flow control pins - */ -int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr, - union usart_flow_control_state *const state) -{ - ASSERT(descr && state); - *state = _usart_sync_get_flow_control_state(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Check if the usart transmitter is empty - */ -int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - return _usart_sync_is_ready_to_send(&descr->device); -} - -/** - * \brief Check if the usart receiver is not empty - */ -int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - return _usart_sync_is_byte_received(&descr->device); -} - -/** - * \brief Retrieve the current driver version - */ -uint32_t usart_sync_get_version(void) -{ - return DRIVER_VERSION; -} - -/* - * \internal Write the given data to usart interface - * - * \param[in] descr The pointer to an io descriptor - * \param[in] buf Data to write to usart - * \param[in] length The number of bytes to write - * - * \return The number of bytes written. - */ -static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) -{ - uint32_t offset = 0; - struct usart_sync_descriptor *descr = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io); - - ASSERT(io_descr && buf && length); - while (!_usart_sync_is_ready_to_send(&descr->device)) - ; - do { - _usart_sync_write_byte(&descr->device, buf[offset]); - while (!_usart_sync_is_ready_to_send(&descr->device)) - ; - } while (++offset < length); - while (!_usart_sync_is_transmit_done(&descr->device)) - ; - return (int32_t)offset; -} - -/* - * \internal Read data from usart interface - * - * \param[in] descr The pointer to an io descriptor - * \param[in] buf A buffer to read data to - * \param[in] length The size of a buffer - * - * \return The number of bytes read. - */ -static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) -{ - uint32_t offset = 0; - struct usart_sync_descriptor *descr = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io); - - ASSERT(io_descr && buf && length); - do { - while (!_usart_sync_is_byte_received(&descr->device)) - ; - buf[offset] = _usart_sync_read_byte(&descr->device); - } while (++offset < length); - - return (int32_t)offset; -} diff --git a/bsp/microchip/same54/bsp/hal/utils/include/utils_ringbuffer.h b/bsp/microchip/same54/bsp/hal/utils/include/utils_ringbuffer.h new file mode 100644 index 0000000000..401d557246 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/utils/include/utils_ringbuffer.h @@ -0,0 +1,116 @@ +/** + * \file + * + * \brief Ringbuffer declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#ifndef _UTILS_RINGBUFFER_H_INCLUDED +#define _UTILS_RINGBUFFER_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_utils_ringbuffer + * + * @{ + */ + +#include "compiler.h" +#include "utils_assert.h" + +/** + * \brief Ring buffer element type + */ +struct ringbuffer { + uint8_t *buf; /** Buffer base address */ + uint32_t size; /** Buffer size */ + uint32_t read_index; /** Buffer read index */ + uint32_t write_index; /** Buffer write index */ +}; + +/** + * \brief Ring buffer init + * + * \param[in] rb The pointer to a ring buffer structure instance + * \param[in] buf Space to store the data + * \param[in] size The buffer length, must be aligned with power of 2 + * + * \return ERR_NONE on success, or an error code on failure. + */ +int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size); + +/** + * \brief Get one byte from ring buffer, the user needs to handle the concurrent + * access on buffer via put/get/flush + * + * \param[in] rb The pointer to a ring buffer structure instance + * \param[in] data One byte space to store the read data + * + * \return ERR_NONE on success, or an error code on failure. + */ +int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data); + +/** + * \brief Put one byte to ring buffer, the user needs to handle the concurrent access + * on buffer via put/get/flush + * + * \param[in] rb The pointer to a ring buffer structure instance + * \param[in] data One byte data to be put into ring buffer + * + * \return ERR_NONE on success, or an error code on failure. + */ +int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data); + +/** + * \brief Return the element number of ring buffer + * + * \param[in] rb The pointer to a ring buffer structure instance + * + * \return The number of elements in ring buffer [0, rb->size] + */ +uint32_t ringbuffer_num(const struct ringbuffer *const rb); + +/** + * \brief Flush ring buffer, the user needs to handle the concurrent access on buffer + * via put/get/flush + * + * \param[in] rb The pointer to a ring buffer structure instance + * + * \return ERR_NONE on success, or an error code on failure. + */ +uint32_t ringbuffer_flush(struct ringbuffer *const rb); + +/**@}*/ + +#ifdef __cplusplus +} +#endif +#endif /* _UTILS_RINGBUFFER_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hal/utils/src/utils_ringbuffer.c b/bsp/microchip/same54/bsp/hal/utils/src/utils_ringbuffer.c new file mode 100644 index 0000000000..45cac83fc6 --- /dev/null +++ b/bsp/microchip/same54/bsp/hal/utils/src/utils_ringbuffer.c @@ -0,0 +1,118 @@ +/** + * \file + * + * \brief Ringbuffer functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include "utils_ringbuffer.h" + +/** + * \brief Ringbuffer init + */ +int32_t ringbuffer_init(struct ringbuffer *const rb, void *buf, uint32_t size) +{ + ASSERT(rb && buf && size); + + /* + * buf size must be aligned to power of 2 + */ + if ((size & (size - 1)) != 0) { + return ERR_INVALID_ARG; + } + + /* size - 1 is faster in calculation */ + rb->size = size - 1; + rb->read_index = 0; + rb->write_index = rb->read_index; + rb->buf = (uint8_t *)buf; + + return ERR_NONE; +} + +/** + * \brief Get one byte from ringbuffer + * + */ +int32_t ringbuffer_get(struct ringbuffer *const rb, uint8_t *data) +{ + ASSERT(rb && data); + + if (rb->write_index != rb->read_index) { + *data = rb->buf[rb->read_index & rb->size]; + rb->read_index++; + return ERR_NONE; + } + + return ERR_NOT_FOUND; +} + +/** + * \brief Put one byte to ringbuffer + * + */ +int32_t ringbuffer_put(struct ringbuffer *const rb, uint8_t data) +{ + ASSERT(rb); + + rb->buf[rb->write_index & rb->size] = data; + + /* + * buffer full strategy: new data will overwrite the oldest data in + * the buffer + */ + if ((rb->write_index - rb->read_index) > rb->size) { + rb->read_index = rb->write_index - rb->size; + } + + rb->write_index++; + + return ERR_NONE; +} + +/** + * \brief Return the element number of ringbuffer + */ +uint32_t ringbuffer_num(const struct ringbuffer *const rb) +{ + ASSERT(rb); + + return rb->write_index - rb->read_index; +} + +/** + * \brief Flush ringbuffer + */ +uint32_t ringbuffer_flush(struct ringbuffer *const rb) +{ + ASSERT(rb); + + rb->read_index = rb->write_index; + + return ERR_NONE; +} diff --git a/bsp/microchip/same54/bsp/hpl/adc/hpl_adc.c b/bsp/microchip/same54/bsp/hpl/adc/hpl_adc.c new file mode 100644 index 0000000000..29f7da5634 --- /dev/null +++ b/bsp/microchip/same54/bsp/hpl/adc/hpl_adc.c @@ -0,0 +1,769 @@ + +/** + * \file + * + * \brief SAM Analog Digital Converter + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +#include +#include +#include +#include + +#ifndef CONF_ADC_0_ENABLE +#define CONF_ADC_0_ENABLE 0 +#endif +#ifndef CONF_ADC_1_ENABLE +#define CONF_ADC_1_ENABLE 0 +#endif + +/** + * \brief Macro is used to fill ADC configuration structure based on its number + * + * \param[in] n The number of structures + */ +#define ADC_CONFIGURATION(n) \ + { \ + (n), \ + (CONF_ADC_##n##_RUNSTDBY << ADC_CTRLA_RUNSTDBY_Pos) | (CONF_ADC_##n##_ONDEMAND << ADC_CTRLA_ONDEMAND_Pos) \ + | ADC_CTRLA_PRESCALER(CONF_ADC_##n##_PRESCALER), \ + ADC_CTRLB_RESSEL(CONF_ADC_##n##_RESSEL) | (CONF_ADC_##n##_CORREN << ADC_CTRLB_CORREN_Pos) \ + | (CONF_ADC_##n##_FREERUN << ADC_CTRLB_FREERUN_Pos) \ + | (CONF_ADC_##n##_LEFTADJ << ADC_CTRLB_LEFTADJ_Pos) | ADC_CTRLB_WINMODE(CONF_ADC_##n##_WINMODE), \ + (CONF_ADC_##n##_REFCOMP << ADC_REFCTRL_REFCOMP_Pos) | ADC_REFCTRL_REFSEL(CONF_ADC_##n##_REFSEL), \ + (CONF_ADC_##n##_WINMONEO << ADC_EVCTRL_WINMONEO_Pos) \ + | (CONF_ADC_##n##_RESRDYEO << ADC_EVCTRL_RESRDYEO_Pos) \ + | (CONF_ADC_##n##_STARTINV << ADC_EVCTRL_STARTINV_Pos) \ + | (CONF_ADC_##n##_FLUSHINV << ADC_EVCTRL_FLUSHINV_Pos) \ + | (CONF_ADC_##n##_STARTEI << ADC_EVCTRL_STARTEI_Pos) \ + | (CONF_ADC_##n##_FLUSHEI << ADC_EVCTRL_FLUSHEI_Pos), \ + (CONF_ADC_##n##_DIFFMODE << ADC_INPUTCTRL_DIFFMODE_Pos) | ADC_INPUTCTRL_MUXNEG(CONF_ADC_##n##_MUXNEG) \ + | ADC_INPUTCTRL_MUXPOS(CONF_ADC_##n##_MUXPOS), \ + ADC_AVGCTRL_ADJRES(CONF_ADC_##n##_ADJRES) | ADC_AVGCTRL_SAMPLENUM(CONF_ADC_##n##_SAMPLENUM), \ + (CONF_ADC_##n##_OFFCOMP << ADC_SAMPCTRL_OFFCOMP_Pos) | ADC_SAMPCTRL_SAMPLEN(CONF_ADC_##n##_SAMPLEN), \ + ADC_WINLT_WINLT(CONF_ADC_##n##_WINLT), ADC_WINUT_WINUT(CONF_ADC_##n##_WINUT), \ + ADC_GAINCORR_GAINCORR(CONF_ADC_##n##_GAINCORR), ADC_OFFSETCORR_OFFSETCORR(CONF_ADC_##n##_OFFSETCORR), \ + CONF_ADC_##n##_DBGRUN << ADC_DBGCTRL_DBGRUN_Pos, \ + } + +/** + * \brief ADC configuration + */ +struct adc_configuration { + uint8_t number; + hri_adc_ctrla_reg_t ctrl_a; + hri_adc_ctrlb_reg_t ctrl_b; + hri_adc_refctrl_reg_t ref_ctrl; + hri_adc_evctrl_reg_t ev_ctrl; + hri_adc_inputctrl_reg_t input_ctrl; + hri_adc_avgctrl_reg_t avg_ctrl; + hri_adc_sampctrl_reg_t samp_ctrl; + hri_adc_winlt_reg_t win_lt; + hri_adc_winut_reg_t win_ut; + hri_adc_gaincorr_reg_t gain_corr; + hri_adc_offsetcorr_reg_t offset_corr; + hri_adc_dbgctrl_reg_t dbg_ctrl; +}; + +#define ADC_AMOUNT (CONF_ADC_0_ENABLE + CONF_ADC_1_ENABLE) + +/** + * \brief Array of ADC configurations + */ +static const struct adc_configuration _adcs[] = { +#if CONF_ADC_0_ENABLE == 1 + ADC_CONFIGURATION(0), +#endif +#if CONF_ADC_1_ENABLE == 1 + ADC_CONFIGURATION(1), +#endif +}; + +static void _adc_set_reference_source(void *const hw, const adc_reference_t reference); + +/** + * \brief Retrieve ordinal number of the given adc hardware instance + */ +static uint8_t _adc_get_hardware_index(const void *const hw) +{ + return ((uint32_t)hw - (uint32_t)ADC0) >> 10; +} + +/** \brief Return the pointer to register settings of specific ADC + * \param[in] hw_addr The hardware register base address. + * \return Pointer to register settings of specific ADC. + */ +static uint8_t _adc_get_regs(const uint32_t hw_addr) +{ + uint8_t n = _adc_get_hardware_index((const void *)hw_addr); + uint8_t i; + + for (i = 0; i < sizeof(_adcs) / sizeof(struct adc_configuration); i++) { + if (_adcs[i].number == n) { + return i; + } + } + + ASSERT(false); + return 0; +} + +/** + * \brief Retrieve IRQ number for the given hardware instance + */ +static uint8_t _adc_get_irq_num(const struct _adc_async_device *const device) +{ + + return ADC0_0_IRQn + (_adc_get_hardware_index(device->hw) << 1); +} + +/** + * \brief Init irq param with the given afec hardware instance + */ +static void _adc_init_irq_param(const void *const hw, struct _adc_async_device *dev) +{ +} + +/** + * \brief Initialize ADC + * + * \param[in] hw The pointer to hardware instance + * \param[in] i The number of hardware instance + */ +static int32_t _adc_init(void *const hw, const uint8_t i) +{ + uint16_t calib_reg = 0; + if (hw == ADC0) { + calib_reg = ADC_CALIB_BIASREFBUF((*(uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR >> ADC0_FUSES_BIASREFBUF_Pos)) + | ADC_CALIB_BIASR2R((*(uint32_t *)ADC0_FUSES_BIASR2R_ADDR >> ADC0_FUSES_BIASR2R_Pos)) + | ADC_CALIB_BIASCOMP((*(uint32_t *)ADC0_FUSES_BIASCOMP_ADDR >> ADC0_FUSES_BIASCOMP_Pos)); + } else if (hw == ADC1) { + calib_reg = ADC_CALIB_BIASREFBUF((*(uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR >> ADC1_FUSES_BIASREFBUF_Pos)) + | ADC_CALIB_BIASR2R((*(uint32_t *)ADC1_FUSES_BIASR2R_ADDR >> ADC1_FUSES_BIASR2R_Pos)) + | ADC_CALIB_BIASCOMP((*(uint32_t *)ADC1_FUSES_BIASCOMP_ADDR >> ADC1_FUSES_BIASCOMP_Pos)); + } + + if (!hri_adc_is_syncing(hw, ADC_SYNCBUSY_SWRST)) { + if (hri_adc_get_CTRLA_reg(hw, ADC_CTRLA_ENABLE)) { + hri_adc_clear_CTRLA_ENABLE_bit(hw); + hri_adc_wait_for_sync(hw, ADC_SYNCBUSY_ENABLE); + } + hri_adc_write_CTRLA_reg(hw, ADC_CTRLA_SWRST); + } + hri_adc_wait_for_sync(hw, ADC_SYNCBUSY_SWRST); + + hri_adc_write_CALIB_reg(hw, calib_reg); + hri_adc_write_CTRLB_reg(hw, _adcs[i].ctrl_b); + hri_adc_write_REFCTRL_reg(hw, _adcs[i].ref_ctrl); + hri_adc_write_EVCTRL_reg(hw, _adcs[i].ev_ctrl); + hri_adc_write_INPUTCTRL_reg(hw, _adcs[i].input_ctrl); + hri_adc_write_AVGCTRL_reg(hw, _adcs[i].avg_ctrl); + hri_adc_write_SAMPCTRL_reg(hw, _adcs[i].samp_ctrl); + hri_adc_write_WINLT_reg(hw, _adcs[i].win_lt); + hri_adc_write_WINUT_reg(hw, _adcs[i].win_ut); + hri_adc_write_GAINCORR_reg(hw, _adcs[i].gain_corr); + hri_adc_write_OFFSETCORR_reg(hw, _adcs[i].offset_corr); + hri_adc_write_DBGCTRL_reg(hw, _adcs[i].dbg_ctrl); + hri_adc_write_CTRLA_reg(hw, _adcs[i].ctrl_a); + + return ERR_NONE; +} + +/** + * \brief De-initialize ADC + * + * \param[in] hw The pointer to hardware instance + */ +static inline void _adc_deinit(void *hw) +{ + hri_adc_clear_CTRLA_ENABLE_bit(hw); + hri_adc_set_CTRLA_SWRST_bit(hw); +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw) +{ + ASSERT(device); + + device->hw = hw; + + return _adc_init(hw, _adc_get_regs((uint32_t)hw)); +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw) +{ + int32_t init_status; + + ASSERT(device); + + init_status = _adc_init(hw, _adc_get_regs((uint32_t)hw)); + if (init_status) { + return init_status; + } + device->hw = hw; + _adc_init_irq_param(hw, device); + NVIC_DisableIRQ(_adc_get_irq_num(device) + 0); + NVIC_ClearPendingIRQ(_adc_get_irq_num(device) + 0); + NVIC_EnableIRQ(_adc_get_irq_num(device) + 0); + NVIC_DisableIRQ(_adc_get_irq_num(device) + 1); + NVIC_ClearPendingIRQ(_adc_get_irq_num(device) + 1); + NVIC_EnableIRQ(_adc_get_irq_num(device) + 1); + return ERR_NONE; +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_dma_init(struct _adc_dma_device *const device, void *const hw) +{ + ASSERT(device); + + device->hw = hw; + + return _adc_init(hw, _adc_get_regs((uint32_t)hw)); +} + +/** + * \brief De-initialize ADC + */ +void _adc_sync_deinit(struct _adc_sync_device *const device) +{ + _adc_deinit(device->hw); +} + +/** + * \brief De-initialize ADC + */ +void _adc_async_deinit(struct _adc_async_device *const device) +{ + NVIC_DisableIRQ(_adc_get_irq_num(device)); + NVIC_ClearPendingIRQ(_adc_get_irq_num(device)); + + _adc_deinit(device->hw); +} + +/** + * \brief De-initialize ADC + */ +void _adc_dma_deinit(struct _adc_dma_device *const device) +{ + _adc_deinit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_dma_enable_channel(struct _adc_dma_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_set_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable ADC + */ +void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable ADC + */ +void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Disable ADC + */ +void _adc_dma_disable_channel(struct _adc_dma_device *const device, const uint8_t channel) +{ + (void)channel; + + hri_adc_clear_CTRLA_ENABLE_bit(device->hw); +} + +/** + * \brief Return address of ADC DMA source + */ +uint32_t _adc_get_source_for_dma(struct _adc_dma_device *const device) +{ + return (uint32_t) & (((Adc *)(device->hw))->RESULT.reg); +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device) +{ + return hri_adc_read_CTRLB_RESSEL_bf(device->hw) == ADC_CTRLB_RESSEL_8BIT_Val ? 1 : 2; +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device) +{ + return hri_adc_read_CTRLB_RESSEL_bf(device->hw) == ADC_CTRLB_RESSEL_8BIT_Val ? 1 : 2; +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_dma_get_data_size(const struct _adc_dma_device *const device) +{ + return hri_adc_read_CTRLB_RESSEL_bf(device->hw) == ADC_CTRLB_RESSEL_8BIT_Val ? 1 : 2; +} + +/** + * \brief Check if conversion is done + */ +bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_get_interrupt_RESRDY_bit(device->hw); +} + +/** + * \brief Check if conversion is done + */ +bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_get_interrupt_RESRDY_bit(device->hw); +} + +/** + * \brief Check if conversion is done + */ +bool _adc_dma_is_conversion_done(const struct _adc_dma_device *const device) +{ + return hri_adc_get_interrupt_RESRDY_bit(device->hw); +} + +/** + * \brief Make conversion + */ +void _adc_sync_convert(struct _adc_sync_device *const device) +{ + hri_adc_set_SWTRIG_START_bit(device->hw); +} + +/** + * \brief Make conversion + */ +void _adc_async_convert(struct _adc_async_device *const device) +{ + hri_adc_set_SWTRIG_START_bit(device->hw); +} + +/** + * \brief Make conversion + */ +void _adc_dma_convert(struct _adc_dma_device *const device) +{ + hri_adc_set_SWTRIG_START_bit(device->hw); +} + +/** + * \brief Retrieve the conversion result + */ +uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_read_RESULT_reg(device->hw); +} + +/** + * \brief Retrieve the conversion result + */ +uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel) +{ + (void)channel; + + return hri_adc_read_RESULT_reg(device->hw); +} + +/** + * \brief Set reference source + */ +void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference) +{ + _adc_set_reference_source(device->hw, reference); +} + +/** + * \brief Set reference source + */ +void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference) +{ + _adc_set_reference_source(device->hw, reference); +} + +/** + * \brief Set reference source + */ +void _adc_dma_set_reference_source(struct _adc_dma_device *const device, const adc_reference_t reference) +{ + _adc_set_reference_source(device->hw, reference); +} + +/** + * \brief Set resolution + */ +void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution) +{ + hri_adc_write_CTRLB_RESSEL_bf(device->hw, resolution); +} + +/** + * \brief Set resolution + */ +void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution) +{ + hri_adc_write_CTRLB_RESSEL_bf(device->hw, resolution); +} + +/** + * \brief Set resolution + */ +void _adc_dma_set_resolution(struct _adc_dma_device *const device, const adc_resolution_t resolution) +{ + hri_adc_write_CTRLB_RESSEL_bf(device->hw, resolution); +} + +/** + * \brief Set channels input sources + */ +void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)channel; + + hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input); + hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input); +} + +/** + * \brief Set channels input sources + */ +void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)channel; + + hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input); + hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input); +} + +/** + * \brief Set channels input source + */ +void _adc_dma_set_inputs(struct _adc_dma_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)channel; + + hri_adc_write_INPUTCTRL_MUXPOS_bf(device->hw, pos_input); + hri_adc_write_INPUTCTRL_MUXNEG_bf(device->hw, neg_input); +} + +/** + * \brief Set thresholds + */ +void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_adc_write_WINLT_reg(device->hw, low_threshold); + hri_adc_write_WINUT_reg(device->hw, up_threshold); +} + +/** + * \brief Set thresholds + */ +void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_adc_write_WINLT_reg(device->hw, low_threshold); + hri_adc_write_WINUT_reg(device->hw, up_threshold); +} + +/** + * \brief Set thresholds + */ +void _adc_dma_set_thresholds(struct _adc_dma_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_adc_write_WINLT_reg(device->hw, low_threshold); + hri_adc_write_WINUT_reg(device->hw, up_threshold); +} + +/** + * \brief Set gain + */ +void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + (void)device, (void)channel, (void)gain; +} + +/** + * \brief Set gain + */ +void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + (void)device, (void)channel, (void)gain; +} + +/** + * \brief Set gain + */ +void _adc_dma_set_channel_gain(struct _adc_dma_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + (void)device, (void)channel, (void)gain; +} + +/** + * \brief Set conversion mode + */ +void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_adc_set_CTRLB_FREERUN_bit(device->hw); + } else { + hri_adc_clear_CTRLB_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set conversion mode + */ +void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_adc_set_CTRLB_FREERUN_bit(device->hw); + } else { + hri_adc_clear_CTRLB_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set conversion mode + */ +void _adc_dma_set_conversion_mode(struct _adc_dma_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_adc_set_CTRLB_FREERUN_bit(device->hw); + } else { + hri_adc_clear_CTRLB_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + (void)channel; + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_adc_set_INPUTCTRL_DIFFMODE_bit(device->hw); + } else { + hri_adc_clear_INPUTCTRL_DIFFMODE_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + (void)channel; + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_adc_set_INPUTCTRL_DIFFMODE_bit(device->hw); + } else { + hri_adc_clear_INPUTCTRL_DIFFMODE_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_dma_set_channel_differential_mode(struct _adc_dma_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + (void)channel; + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_adc_set_INPUTCTRL_DIFFMODE_bit(device->hw); + } else { + hri_adc_clear_INPUTCTRL_DIFFMODE_bit(device->hw); + } +} + +/** + * \brief Set window mode + */ +void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode) +{ + hri_adc_write_CTRLB_WINMODE_bf(device->hw, mode); +} + +/** + * \brief Set window mode + */ +void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode) +{ + hri_adc_write_CTRLB_WINMODE_bf(device->hw, mode); +} + +/** + * \brief Set window mode + */ +void _adc_dma_set_window_mode(struct _adc_dma_device *const device, const adc_window_mode_t mode) +{ + hri_adc_write_CTRLB_WINMODE_bf(device->hw, mode); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_adc_get_interrupt_WINMON_bit(device->hw); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_adc_get_interrupt_WINMON_bit(device->hw); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_dma_get_threshold_state(const struct _adc_dma_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_adc_get_interrupt_WINMON_bit(device->hw); +} + +/** + * \brief Enable/disable ADC channel interrupt + */ +void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel, + const enum _adc_async_callback_type type, const bool state) +{ + (void)channel; + + void *const hw = device->hw; + + if (ADC_ASYNC_DEVICE_MONITOR_CB == type) { + hri_adc_write_INTEN_WINMON_bit(hw, state); + } else if (ADC_ASYNC_DEVICE_ERROR_CB == type) { + hri_adc_write_INTEN_OVERRUN_bit(hw, state); + } else if (ADC_ASYNC_DEVICE_CONVERT_CB == type) { + hri_adc_write_INTEN_RESRDY_bit(hw, state); + } +} + +/** + * \brief Retrieve ADC sync helper functions + */ +void *_adc_get_adc_sync(void) +{ + return (void *)NULL; +} + +/** + * \brief Retrieve ADC async helper functions + */ +void *_adc_get_adc_async(void) +{ + return (void *)NULL; +} + +/** + * \brief Set ADC reference source + * + * \param[in] hw The pointer to hardware instance + * \param[in] reference The reference to set + */ +static void _adc_set_reference_source(void *const hw, const adc_reference_t reference) +{ + bool enabled = hri_adc_get_CTRLA_ENABLE_bit(hw); + + hri_adc_clear_CTRLA_ENABLE_bit(hw); + hri_adc_write_REFCTRL_REFSEL_bf(hw, reference); + + if (enabled) { + hri_adc_set_CTRLA_ENABLE_bit(hw); + } +} diff --git a/bsp/microchip/same54/bsp/hpl/adc/hpl_adc_base.h b/bsp/microchip/same54/bsp/hpl/adc/hpl_adc_base.h new file mode 100644 index 0000000000..e9b95283aa --- /dev/null +++ b/bsp/microchip/same54/bsp/hpl/adc/hpl_adc_base.h @@ -0,0 +1,72 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_ADC_H_INCLUDED +#define _HPL_ADC_ADC_H_INCLUDED + +#include +#include + +/** + * \addtogroup HPL ADC + * + * \section hpl_adc_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name HPL functions + */ +//@{ + +/** + * \brief Retrieve ADC helper functions + * + * \return A pointer to set of ADC helper functions + */ +void *_adc_get_adc_sync(void); +void *_adc_get_adc_async(void); + +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_USART_UART_H_INCLUDED */ diff --git a/bsp/microchip/same54/bsp/hpl/gmac/hpl_gmac.c b/bsp/microchip/same54/bsp/hpl/gmac/hpl_gmac.c new file mode 100644 index 0000000000..6531c9c7f7 --- /dev/null +++ b/bsp/microchip/same54/bsp/hpl/gmac/hpl_gmac.c @@ -0,0 +1,538 @@ +/** + * \file + * + * \brief MAC functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +#include +#include + +/** + * @brief Transmit buffer descriptor + **/ +struct _mac_txbuf_descriptor { + uint32_t address; + union gmac_tx_status { + uint32_t val; + struct _gmac_tx_status_bm { + uint32_t len : 14, /**< Length of buffer */ + reserved : 1, last_buf : 1, /**< Last buffer (in the current frame) */ + no_crc : 1, /**< No CRC */ + reserved1 : 3, checksum_err : 3, /**< Transmit checksum generation offload error */ + reserved2 : 3, lco : 1, /**< Late collision, transmit error detected */ + exhausted : 1, /**< Buffer exhausted in mid frame */ + reserved3 : 1, error : 1, /**< Retry limit exceeded, error detected */ + wrap : 1, /**< Marks last descriptor in TD list */ + used : 1; /**< User clear, GMAC sets this to 1 once a frame + has been successfully transmitted */ + } bm; + } status; +}; + +/** + * @brief Receive buffer descriptor + **/ +struct _mac_rxbuf_descriptor { + union _gmac_rx_addr { + uint32_t val; + struct rx_addr_bm { + uint32_t ownership : 1, /**< clear before buffer can be used again */ + wrap : 1, /**< Marks last entry in array */ + addr : 30; /**< Address in number of DW */ + } bm; + } address; + union gmac_rx_status { + uint32_t val; + struct _gmac_rx_status_bm { + uint32_t len : 13, /**< Length of frame including FCS */ + fcs : 1, /**< Frame has bad FCS */ + sof : 1, /**< Start of frame */ + eof : 1, /**< End of frame */ + cfi : 1, /**< Concatenation Format Indicator */ + vlan_priority : 3, /**< VLAN priority (if VLAN detected) */ + priority_detected : 1, /**< Priority tag detected */ + vlan_detected : 1, /**< VLAN tag detected */ + type_id_match : 2, /**< Type ID match */ + checksumoffload : 1, /**< Checksum offload specific function */ + addrmatch : 2, /**< Address register match */ + ext_addr_match : 1, /**< External address match found */ + reserved : 1, uni_hash_match : 1, /**< Unicast hash match */ + multi_hash_match : 1, /**< Multicast hash match */ + boardcast_detect : 1; /**< Global broadcast address detected */ + } bm; + } status; +}; + +/* Transmit and Receive buffer descriptor array */ +COMPILER_ALIGNED(8) static struct _mac_txbuf_descriptor _txbuf_descrs[CONF_GMAC_TXDESCR_NUM]; +COMPILER_ALIGNED(8) static struct _mac_rxbuf_descriptor _rxbuf_descrs[CONF_GMAC_RXDESCR_NUM]; + +/* Transmit buffer data array */ +COMPILER_ALIGNED(32) +static uint8_t _txbuf[CONF_GMAC_TXDESCR_NUM][CONF_GMAC_TXBUF_SIZE]; +COMPILER_ALIGNED(32) +static uint8_t _rxbuf[CONF_GMAC_RXDESCR_NUM][CONF_GMAC_RXBUF_SIZE]; + +COMPILER_PACK_RESET() + +/*!< Pointer to hpl device */ +static struct _mac_async_device *_gmac_dev = NULL; + +/* Transmit and receive Buffer index */ +static volatile uint32_t _txbuf_index; +static volatile uint32_t _last_txbuf_index; +static volatile uint32_t _rxbuf_index; + +/** + * \internal Initialize the Transmit and receive buffer descriptor array + * + * \param[in] dev Pointer to the HPL MAC descriptor + */ +static void _mac_init_bufdescr(struct _mac_async_device *const dev) +{ + uint32_t i; + + /* TX buffer descriptor */ + for (i = 0; i < CONF_GMAC_TXDESCR_NUM; i++) { + _txbuf_descrs[i].address = (uint32_t)_txbuf[i]; + _txbuf_descrs[i].status.val = 0; + _txbuf_descrs[i].status.bm.used = 1; + } + + _txbuf_descrs[CONF_GMAC_TXDESCR_NUM - 1].status.bm.wrap = 1; + _txbuf_index = 0; + _last_txbuf_index = 0; + + /* RX buffer descriptor */ + for (i = 0; i < CONF_GMAC_RXDESCR_NUM; i++) { + _rxbuf_descrs[i].address.val = (uint32_t)_rxbuf[i]; + _rxbuf_descrs[i].status.val = 0; + } + + _rxbuf_descrs[CONF_GMAC_RXDESCR_NUM - 1].address.bm.wrap = 1; + _rxbuf_index = 0; + + hri_gmac_write_TBQB_reg(dev->hw, (uint32_t)_txbuf_descrs); + hri_gmac_write_RBQB_reg(dev->hw, (uint32_t)_rxbuf_descrs); +} + +/* + * \internal GMAC interrupt handler + */ +void GMAC_Handler(void) +{ + volatile uint32_t tsr; + volatile uint32_t rsr; + + tsr = hri_gmac_read_TSR_reg(_gmac_dev->hw); + rsr = hri_gmac_read_RSR_reg(_gmac_dev->hw); + /* Must be Clear ISR (Clear on read) */ + hri_gmac_read_ISR_reg(_gmac_dev->hw); + + /* Frame transmited */ + if (tsr & GMAC_TSR_TXCOMP) { + hri_gmac_write_TSR_reg(_gmac_dev->hw, tsr); + if ((_txbuf_descrs[_txbuf_index].status.bm.used) && (_gmac_dev->cb.transmited != NULL)) { + _gmac_dev->cb.transmited(_gmac_dev); + } + } + + /* Frame received */ + if (rsr & GMAC_RSR_REC) { + if (_gmac_dev->cb.received != NULL) { + _gmac_dev->cb.received(_gmac_dev); + } + } + hri_gmac_write_RSR_reg(_gmac_dev->hw, rsr); +} + +int32_t _mac_async_init(struct _mac_async_device *const dev, void *const hw) +{ + dev->hw = hw; + hri_gmac_write_NCR_reg(dev->hw, + (CONF_GMAC_NCR_LBL ? GMAC_NCR_LBL : 0) | (CONF_GMAC_NCR_MPE ? GMAC_NCR_MPE : 0) + | (CONF_GMAC_NCR_WESTAT ? GMAC_NCR_WESTAT : 0) | (CONF_GMAC_NCR_BP ? GMAC_NCR_BP : 0) + | (CONF_GMAC_NCR_ENPBPR ? GMAC_NCR_ENPBPR : 0) + | (CONF_GMAC_NCR_TXPBPF ? GMAC_NCR_TXPBPF : 0)); + hri_gmac_write_NCFGR_reg( + dev->hw, + (CONF_GMAC_NCFGR_SPD ? GMAC_NCFGR_SPD : 0) | (CONF_GMAC_NCFGR_FD ? GMAC_NCFGR_FD : 0) + | (CONF_GMAC_NCFGR_DNVLAN ? GMAC_NCFGR_DNVLAN : 0) | (CONF_GMAC_NCFGR_JFRAME ? GMAC_NCFGR_JFRAME : 0) + | (CONF_GMAC_NCFGR_CAF ? GMAC_NCFGR_CAF : 0) | (CONF_GMAC_NCFGR_NBC ? GMAC_NCFGR_NBC : 0) + | (CONF_GMAC_NCFGR_MTIHEN ? GMAC_NCFGR_MTIHEN : 0) | (CONF_GMAC_NCFGR_UNIHEN ? GMAC_NCFGR_UNIHEN : 0) + | (CONF_GMAC_NCFGR_MAXFS ? GMAC_NCFGR_MAXFS : 0) | (CONF_GMAC_NCFGR_RTY ? GMAC_NCFGR_RTY : 0) + | (CONF_GMAC_NCFGR_PEN ? GMAC_NCFGR_PEN : 0) | GMAC_NCFGR_RXBUFO(CONF_GMAC_NCFGR_RXBUFO) + | (CONF_GMAC_NCFGR_LFERD ? GMAC_NCFGR_LFERD : 0) | (CONF_GMAC_NCFGR_RFCS ? GMAC_NCFGR_RFCS : 0) + | GMAC_NCFGR_CLK(CONF_GMAC_NCFGR_CLK) | (CONF_GMAC_NCFGR_DCPF ? GMAC_NCFGR_DCPF : 0) + | (CONF_GMAC_NCFGR_RXCOEN ? GMAC_NCFGR_RXCOEN : 0) | (CONF_GMAC_NCFGR_EFRHD ? GMAC_NCFGR_EFRHD : 0) + | (CONF_GMAC_NCFGR_IRXFCS ? GMAC_NCFGR_IRXFCS : 0) | (CONF_GMAC_NCFGR_IPGSEN ? GMAC_NCFGR_IPGSEN : 0) + | (CONF_GMAC_NCFGR_RXBP ? GMAC_NCFGR_RXBP : 0) | (CONF_GMAC_NCFGR_IRXER ? GMAC_NCFGR_IRXER : 0)); + hri_gmac_write_UR_reg(dev->hw, (CONF_GMAC_UR_MII ? GMAC_UR_MII : 0)); + hri_gmac_write_DCFGR_reg( + dev->hw, + GMAC_DCFGR_FBLDO(CONF_GMAC_DCFGR_FBLDO) | (CONF_GMAC_DCFGR_ESMA ? GMAC_DCFGR_ESMA : 0) + | (CONF_GMAC_DCFGR_ESPA ? GMAC_DCFGR_ESPA : 0) | GMAC_DCFGR_RXBMS(CONF_GMAC_DCFGR_RXBMS) + | (CONF_GMAC_DCFGR_TXPBMS ? GMAC_DCFGR_TXPBMS : 0) | (CONF_GMAC_DCFGR_TXCOEN ? GMAC_DCFGR_TXCOEN : 0) + | GMAC_DCFGR_DRBS(CONF_GMAC_DCFGR_DRBS) | (CONF_GMAC_DCFGR_DDRP ? GMAC_DCFGR_DDRP : 0)); + hri_gmac_write_WOL_reg(dev->hw, 0); + hri_gmac_write_IPGS_reg(dev->hw, GMAC_IPGS_FL((CONF_GMAC_IPGS_FL_MUL << 8) | CONF_GMAC_IPGS_FL_DIV)); + _mac_init_bufdescr(dev); + + _gmac_dev = dev; + NVIC_DisableIRQ(GMAC_IRQn); + NVIC_ClearPendingIRQ(GMAC_IRQn); + NVIC_EnableIRQ(GMAC_IRQn); + + return ERR_NONE; +} + +int32_t _mac_async_deinit(struct _mac_async_device *const dev) +{ + /* Disable all GMAC Interrupt */ + hri_gmac_clear_IMR_reg(dev->hw, 0xFFFFFFFF); + /* Disable transmit/receive */ + hri_gmac_write_NCR_reg(dev->hw, 0x0); + dev->hw = NULL; + /* Disable Interrupt */ + NVIC_DisableIRQ(GMAC_IRQn); + + return ERR_NONE; +} + +int32_t _mac_async_enable(struct _mac_async_device *const dev) +{ + hri_gmac_set_NCR_reg(dev->hw, GMAC_NCR_RXEN | GMAC_NCR_TXEN); + return ERR_NONE; +} + +int32_t _mac_async_disable(struct _mac_async_device *const dev) +{ + hri_gmac_clear_NCR_reg(dev->hw, GMAC_NCR_RXEN | GMAC_NCR_TXEN); + return ERR_NONE; +} + +int32_t _mac_async_write(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len) +{ + uint32_t pos; + uint32_t blen; + uint32_t i; + + if (_txbuf_descrs[_last_txbuf_index].status.bm.used && !_txbuf_descrs[_last_txbuf_index].status.bm.last_buf) { + /* Set used flag from first descriptor to last descriptor, + * as DMA olny set the first used flag */ + for (i = 1; i < CONF_GMAC_TXDESCR_NUM; i++) { + pos = _last_txbuf_index + i; + if (pos >= CONF_GMAC_TXDESCR_NUM) { + pos -= CONF_GMAC_TXDESCR_NUM; + } + _txbuf_descrs[pos].status.bm.used = 1; + + if (_txbuf_descrs[pos].status.bm.last_buf) { + break; + } + } + } + + if (!_txbuf_descrs[_txbuf_index].status.bm.used) { + return ERR_NO_RESOURCE; + } + + /* Check if have enough buffers, the first buffer already checked */ + if (len > CONF_GMAC_TXBUF_SIZE) { + for (i = 1; i < CONF_GMAC_TXDESCR_NUM; i++) { + pos = _txbuf_index + i; + if (pos >= CONF_GMAC_TXDESCR_NUM) { + pos -= CONF_GMAC_TXDESCR_NUM; + } + + if (!_txbuf_descrs[pos].status.bm.used) { + return ERR_NO_RESOURCE; + } + + if ((len - (CONF_GMAC_TXBUF_SIZE * i)) < CONF_GMAC_TXBUF_SIZE) { + break; + } + } + } + _last_txbuf_index = _txbuf_index; + + /* Write data to transmit buffer */ + for (i = 0; i < CONF_GMAC_TXDESCR_NUM; i++) { + blen = min(len, CONF_GMAC_TXBUF_SIZE); + memcpy(_txbuf[_txbuf_index], buf + (i * CONF_GMAC_TXBUF_SIZE), blen); + len -= blen; + + if (len > 0) { + /* Here the Used flag be set to zero */ + _txbuf_descrs[_txbuf_index].status.val = blen; + } else { + _txbuf_descrs[_txbuf_index].status.val = blen; + _txbuf_descrs[_txbuf_index].status.bm.last_buf = 1; + } + _txbuf_index++; + if (_txbuf_index == CONF_GMAC_TXDESCR_NUM) { + _txbuf_index = 0; + _txbuf_descrs[CONF_GMAC_TXDESCR_NUM - 1].status.bm.wrap = 1; + } + if (len == 0) { + break; + } + } + + /* Data synchronization barrier */ + __DSB(); + + /* Active Transmit */ + hri_gmac_set_NCR_reg(dev->hw, GMAC_NCR_TSTART); + + return ERR_NONE; +} + +uint32_t _mac_async_read(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len) +{ + uint32_t i; + uint32_t j; + uint32_t pos; + uint32_t n; + uint32_t sof = 0xFFFFFFFF; /* Start of Frame index */ + uint32_t eof = 0xFFFFFFFF; /* End of Frame index */ + uint32_t total_len = 0; /* Total length of received package */ + + (void)dev; + for (i = 0; i < CONF_GMAC_RXDESCR_NUM; i++) { + pos = _rxbuf_index + i; + + if (pos >= CONF_GMAC_RXDESCR_NUM) { + pos -= CONF_GMAC_RXDESCR_NUM; + } + + /* No more data for Ethernet package */ + if (!_rxbuf_descrs[pos].address.bm.ownership) { + break; + } + + if (_rxbuf_descrs[pos].status.bm.sof) { + sof = i; + } + + if ((_rxbuf_descrs[pos].status.bm.eof) && (sof != 0xFFFFFFFF)) { + /* eof now indicate the number of bufs the frame used */ + eof = i; + n = _rxbuf_descrs[pos].status.bm.len; + len = min(n, len); + /* Break process since the last data has been found */ + break; + } + } + + if (eof != 0xFFFFFFFF) { + j = eof + 1; + } else if (sof != 0xFFFFFFFF) { + j = sof; + } else { + j = i; + } + + /* Copy data to user buffer */ + for (i = 0; i < j; i++) { + if (eof != 0xFFFFFFFF && i >= sof && i <= eof && len > 0) { + n = min(len, CONF_GMAC_RXBUF_SIZE); + memcpy(buf, _rxbuf[_rxbuf_index], n); + buf += n; + total_len += n; + len -= n; + } + + _rxbuf_descrs[_rxbuf_index].address.bm.ownership = 0; + _rxbuf_index++; + + if (_rxbuf_index == CONF_GMAC_RXDESCR_NUM) { + _rxbuf_index = 0; + } + } + + return total_len; +} + +uint32_t _mac_async_read_len(struct _mac_async_device *const dev) +{ + uint32_t i; + uint32_t pos; + bool sof = false; /* Start of Frame */ + uint32_t total_len = 0; /* Total length of received package */ + + (void)dev; + + for (i = 0; i < CONF_GMAC_RXDESCR_NUM; i++) { + pos = _rxbuf_index + i; + + if (pos >= CONF_GMAC_RXDESCR_NUM) { + pos -= CONF_GMAC_RXDESCR_NUM; + } + + /* No more data for Ethernet package */ + if (!(_rxbuf_descrs[pos].address.bm.ownership)) { + break; + } + + if (_rxbuf_descrs[pos].status.bm.sof) { + sof = true; + } + if (sof == true) { + total_len += _rxbuf_descrs[pos].status.bm.len; + } + + if (_rxbuf_descrs[pos].status.bm.eof) { + /* Break process since the last data has been found */ + break; + } + } + + return total_len; +} + +void _mac_async_enable_irq(struct _mac_async_device *const dev) +{ + (void)dev; + NVIC_EnableIRQ(GMAC_IRQn); +} + +void _mac_async_disable_irq(struct _mac_async_device *const dev) +{ + (void)dev; + NVIC_DisableIRQ(GMAC_IRQn); +} + +int32_t _mac_async_register_callback(struct _mac_async_device *const dev, const enum mac_async_cb_type type, + const FUNC_PTR func) +{ + switch (type) { + case MAC_ASYNC_TRANSMIT_CB: + dev->cb.transmited = (_mac_async_cb_t)func; + if (func) { + hri_gmac_set_IMR_TCOMP_bit(dev->hw); + } else { + hri_gmac_clear_IMR_TCOMP_bit(dev->hw); + } + break; + case MAC_ASYNC_RECEIVE_CB: + dev->cb.received = (_mac_async_cb_t)func; + if (func) { + hri_gmac_set_IMR_RCOMP_bit(dev->hw); + } else { + hri_gmac_set_IMR_RCOMP_bit(dev->hw); + } + break; + default: + return ERR_INVALID_ARG; + } + return ERR_NONE; +} + +int32_t _mac_async_set_filter(struct _mac_async_device *const dev, uint8_t index, struct mac_async_filter *filter) +{ + ASSERT(index < 4); + + hri_gmac_write_SAB_reg(dev->hw, index, *((uint32_t *)(filter->mac))); + hri_gmac_write_SAT_reg(dev->hw, index, *((uint16_t *)(filter->mac + 4))); + + hri_gmac_write_TIDM_reg(dev->hw, index, GMAC_TIDM_TID(*((uint16_t *)(filter->tid)) | filter->tid_enable << 31)); + return ERR_NONE; +} + +int32_t _mac_async_set_filter_ex(struct _mac_async_device *const dev, uint8_t mac[6]) +{ + uint8_t j; + uint8_t m; + uint8_t n; + uint8_t k = 0; + + /* Apply the hash function */ + for (j = 0; j < 48; j += 6) { + /* Calculate the shift count */ + n = j / 8; + m = j % 8; + + /* Update hash value */ + if (!m) { + k ^= mac[n]; + } else { + k ^= (mac[n] >> m) | (mac[n + 1] << (8 - m)); + } + } + + /* The hash value is reduced to a 6-bit index */ + k &= 0x3F; + + if (k < 32) { + hri_gmac_set_HRB_reg(dev->hw, 1 << k); + } else { + hri_gmac_set_HRT_reg(dev->hw, 1 << (k % 32)); + } + + return ERR_NONE; +} + +int32_t _mac_async_write_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t data) +{ + hri_gmac_set_NCR_reg(dev->hw, GMAC_NCR_MPE); + hri_gmac_write_MAN_reg(dev->hw, + GMAC_MAN_OP(1) | /* 0x01 write operation */ + CONF_GMAC_CLTTO << 30 | /* Clause 22/45 operation */ + GMAC_MAN_WTN(2) | /* Must be written to 0x2 */ + GMAC_MAN_PHYA(addr) | GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(data)); + /* Wait for the write operation complete */ + while (!hri_gmac_get_NSR_IDLE_bit(dev->hw)) { + } + + hri_gmac_clear_NCR_reg(dev->hw, GMAC_NCR_MPE); + return ERR_NONE; +} + +int32_t _mac_async_read_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t *data) +{ + hri_gmac_set_NCR_reg(dev->hw, GMAC_NCR_MPE); + hri_gmac_write_MAN_reg(dev->hw, + GMAC_MAN_OP(2) | /* 0x02 read operation */ + CONF_GMAC_CLTTO << 30 | /* Clause 22/45 operation */ + GMAC_MAN_WTN(0x2) | /* Must be written to 0x2 */ + GMAC_MAN_PHYA(addr) | GMAC_MAN_REGA(reg)); + + /* Wait for the read operation complete */ + while (!hri_gmac_get_NSR_IDLE_bit(dev->hw)) { + } + + *data = GMAC_MAN_DATA(hri_gmac_read_MAN_reg(dev->hw)); + hri_gmac_clear_NCR_reg(dev->hw, GMAC_NCR_MPE); + + return ERR_NONE; +} diff --git a/bsp/microchip/same54/bsp/hpl/sercom/hpl_sercom.c b/bsp/microchip/same54/bsp/hpl/sercom/hpl_sercom.c index 770278f523..e4a55d10cf 100644 --- a/bsp/microchip/same54/bsp/hpl/sercom/hpl_sercom.c +++ b/bsp/microchip/same54/bsp/hpl/sercom/hpl_sercom.c @@ -163,6 +163,8 @@ static struct usart_configuration _usarts[] = { }; #endif +static struct _usart_async_device *_sercom2_dev = NULL; + static uint8_t _get_sercom_index(const void *const hw); static uint8_t _sercom_get_irq_num(const void *const hw); static void _sercom_init_irq_param(const void *const hw, void *dev); @@ -562,6 +564,40 @@ void _usart_async_set_irq_state(struct _usart_async_device *const device, const } } +/** + * \internal Sercom interrupt handler + * + * \param[in] p The pointer to interrupt parameter + */ +static void _sercom_usart_interrupt_handler(struct _usart_async_device *device) +{ + void *hw = device->hw; + + if (hri_sercomusart_get_interrupt_DRE_bit(hw) && hri_sercomusart_get_INTEN_DRE_bit(hw)) { + hri_sercomusart_clear_INTEN_DRE_bit(hw); + device->usart_cb.tx_byte_sent(device); + } else if (hri_sercomusart_get_interrupt_TXC_bit(hw) && hri_sercomusart_get_INTEN_TXC_bit(hw)) { + hri_sercomusart_clear_INTEN_TXC_bit(hw); + device->usart_cb.tx_done_cb(device); + } else if (hri_sercomusart_get_interrupt_RXC_bit(hw)) { + if (hri_sercomusart_read_STATUS_reg(hw) + & (SERCOM_USART_STATUS_PERR | SERCOM_USART_STATUS_FERR | SERCOM_USART_STATUS_BUFOVF + | SERCOM_USART_STATUS_ISF | SERCOM_USART_STATUS_COLL)) { + hri_sercomusart_clear_STATUS_reg(hw, SERCOM_USART_STATUS_MASK); + return; + } + + device->usart_cb.rx_done_cb(device, hri_sercomusart_read_DATA_reg(hw)); + } else if (hri_sercomusart_get_interrupt_ERROR_bit(hw)) { + uint32_t status; + + hri_sercomusart_clear_interrupt_ERROR_bit(hw); + device->usart_cb.error_cb(device); + status = hri_sercomusart_read_STATUS_reg(hw); + hri_sercomusart_clear_STATUS_reg(hw, status); + } +} + /** * \internal Retrieve ordinal number of the given sercom hardware instance * @@ -589,6 +625,10 @@ static uint8_t _get_sercom_index(const void *const hw) */ static void _sercom_init_irq_param(const void *const hw, void *dev) { + + if (hw == SERCOM2) { + _sercom2_dev = (struct _usart_async_device *)dev; + } } /** @@ -2433,6 +2473,35 @@ static inline const struct sercomspi_regs_cfg *_spi_get_regs(const uint32_t hw_a return NULL; } +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_0_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_1_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_2_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} +/** + * \internal Sercom interrupt handler + */ +void SERCOM2_3_Handler(void) +{ + _sercom_usart_interrupt_handler(_sercom2_dev); +} + int32_t _spi_m_sync_init(struct _spi_m_sync_dev *dev, void *const hw) { const struct sercomspi_regs_cfg *regs = _spi_get_regs((uint32_t)hw); diff --git a/bsp/microchip/same54/bsp/iar-project-connection.ipcf b/bsp/microchip/same54/bsp/iar-project-connection.ipcf index dfb94898fd..e266da50e0 100644 --- a/bsp/microchip/same54/bsp/iar-project-connection.ipcf +++ b/bsp/microchip/same54/bsp/iar-project-connection.ipcf @@ -10,6 +10,7 @@ $PROJ_DIR$\examples $PROJ_DIR$\hal\include $PROJ_DIR$\hal\utils\include + $PROJ_DIR$\hpl\adc $PROJ_DIR$\hpl\aes $PROJ_DIR$\hpl\can $PROJ_DIR$\hpl\cmcc @@ -25,6 +26,9 @@ $PROJ_DIR$\hpl\sercom $PROJ_DIR$\hri $PROJ_DIR$\ + $PROJ_DIR$\config + $PROJ_DIR$\ethernet_phy + $PROJ_DIR$\ $PROJ_DIR$\CMSIS\Core\Include $PROJ_DIR$\include @@ -35,6 +39,7 @@ $PROJ_DIR$\examples $PROJ_DIR$\hal\include $PROJ_DIR$\hal\utils\include + $PROJ_DIR$\hpl\adc $PROJ_DIR$\hpl\aes $PROJ_DIR$\hpl\can $PROJ_DIR$\hpl\cmcc @@ -50,6 +55,9 @@ $PROJ_DIR$\hpl\sercom $PROJ_DIR$\hri $PROJ_DIR$\ + $PROJ_DIR$\config + $PROJ_DIR$\ethernet_phy + $PROJ_DIR$\ $PROJ_DIR$\CMSIS\Core\Include $PROJ_DIR$\include @@ -75,6 +83,8 @@ atmel_start_pins.h driver_init.c driver_init.h + ethernet_phy_main.c + ethernet_phy_main.h main.c @@ -103,35 +113,50 @@ + config/hpl_adc_config.h config/hpl_aes_config.h config/hpl_can_config.h config/hpl_cmcc_config.h config/hpl_dmac_config.h config/hpl_gclk_config.h + config/hpl_gmac_config.h config/hpl_mclk_config.h config/hpl_osc32kctrl_config.h config/hpl_oscctrl_config.h config/hpl_port_config.h config/hpl_sercom_config.h + config/ieee8023_mii_standard_config.h config/peripheral_clk_config.h + + ethernet_phy/ethernet_phy.c + ethernet_phy/ethernet_phy.h + ethernet_phy/ieee8023_mii_standard_register.h + + examples/driver_examples.c examples/driver_examples.h + hal/include/hal_adc_sync.h hal/include/hal_aes_sync.h hal/include/hal_atomic.h hal/include/hal_cache.h hal/include/hal_can_async.h hal/include/hal_delay.h hal/include/hal_gpio.h + hal/include/hal_i2c_m_sync.h hal/include/hal_init.h hal/include/hal_io.h + hal/include/hal_mac_async.h hal/include/hal_sleep.h - hal/include/hal_usart_sync.h + hal/include/hal_usart_async.h + hal/include/hpl_adc_async.h + hal/include/hpl_adc_dma.h + hal/include/hpl_adc_sync.h hal/include/hpl_aes.h hal/include/hpl_aes_sync.h hal/include/hpl_can.h @@ -147,6 +172,7 @@ hal/include/hpl_i2c_s_sync.h hal/include/hpl_init.h hal/include/hpl_irq.h + hal/include/hpl_mac_async.h hal/include/hpl_missing_features.h hal/include/hpl_ramecc.h hal/include/hpl_reset.h @@ -165,16 +191,19 @@ + hal/src/hal_adc_sync.c hal/src/hal_aes_sync.c hal/src/hal_atomic.c hal/src/hal_cache.c hal/src/hal_can_async.c hal/src/hal_delay.c hal/src/hal_gpio.c + hal/src/hal_i2c_m_sync.c hal/src/hal_init.c hal/src/hal_io.c + hal/src/hal_mac_async.c hal/src/hal_sleep.c - hal/src/hal_usart_sync.c + hal/src/hal_usart_async.c @@ -188,12 +217,19 @@ hal/utils/include/utils_increment_macro.h hal/utils/include/utils_list.h hal/utils/include/utils_repeat_macro.h + hal/utils/include/utils_ringbuffer.h hal/utils/src/utils_assert.c hal/utils/src/utils_event.c hal/utils/src/utils_list.c + hal/utils/src/utils_ringbuffer.c + + + + hpl/adc/hpl_adc.c + hpl/adc/hpl_adc_base.h @@ -224,6 +260,10 @@ hpl/gclk/hpl_gclk_base.h + + hpl/gmac/hpl_gmac.c + + hpl/mclk/hpl_mclk.c diff --git a/bsp/microchip/same54/rtconfig.h b/bsp/microchip/same54/rtconfig.h index a2fe607b75..9bde14d3a4 100644 --- a/bsp/microchip/same54/rtconfig.h +++ b/bsp/microchip/same54/rtconfig.h @@ -17,6 +17,9 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 256 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 /* kservice optimization */ @@ -55,15 +58,38 @@ #define RT_USING_USER_MAIN #define RT_MAIN_THREAD_STACK_SIZE 2048 #define RT_MAIN_THREAD_PRIORITY 10 +#define RT_USING_MSH +#define RT_USING_FINSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 +#define RT_USING_DFS +#define DFS_USING_POSIX +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 4 +#define DFS_FILESYSTEM_TYPES_MAX 4 +#define DFS_FD_MAX 16 +#define RT_USING_DFS_DEVFS /* Device Drivers */ #define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_PIN +#define RT_USING_I2C /* Using USB */ @@ -74,6 +100,17 @@ /* POSIX (Portable Operating System Interface) layer */ +#define RT_USING_POSIX_FS +#define RT_USING_POSIX_DEVIO +#define RT_USING_POSIX_POLL +#define RT_USING_POSIX_SELECT +#define RT_USING_POSIX_SOCKET +#define RT_USING_POSIX_AIO +#define RT_USING_POSIX_DELAY +#define RT_USING_POSIX_CLOCK +#define RT_USING_POSIX_TIMER +#define RT_USING_PTHREADS +#define PTHREAD_NUM_MAX 8 /* Interprocess Communication (IPC) */ @@ -83,6 +120,63 @@ /* Network */ +#define RT_USING_SAL +#define SAL_INTERNET_CHECK + +/* protocol stack implement */ + +#define SAL_USING_LWIP +#define SAL_USING_POSIX +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 +#define RT_USING_LWIP +#define RT_USING_LWIP_LOCAL_VERSION +#define RT_USING_LWIP212 +#define RT_USING_LWIP_VER_NUM 0x20102 +#define RT_LWIP_MEM_ALIGNMENT 4 +#define RT_LWIP_IGMP +#define RT_LWIP_ICMP +#define RT_LWIP_DNS +#define RT_LWIP_DHCP +#define IP_SOF_BROADCAST 1 +#define IP_SOF_BROADCAST_RECV 1 + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.1.30" +#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING /* Utilities */ @@ -172,11 +266,15 @@ #define SAME5X_CAN0 #define SAME5X_ADC0 +#define SAME5X_I2C0 +#define SAME5X_GMAC /* Application Demo Config */ #define SAM_CAN_EXAMPLE #define SAM_ADC_EXAMPLE +#define SAM_I2C_EXAMPLE +#define SAM_LWIP_EXAMPLE #define SOC_SAME54 #endif diff --git a/bsp/microchip/same70/.config b/bsp/microchip/same70/.config index feb084ecef..1e947dbb45 100644 --- a/bsp/microchip/same70/.config +++ b/bsp/microchip/same70/.config @@ -21,7 +21,9 @@ CONFIG_RT_HOOK_USING_FUNC_PTR=y CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=256 -# CONFIG_RT_USING_TIMER_SOFT is not set +CONFIG_RT_USING_TIMER_SOFT=y +CONFIG_RT_TIMER_THREAD_PRIO=4 +CONFIG_RT_TIMER_THREAD_STACK_SIZE=512 # # kservice optimization @@ -93,8 +95,33 @@ CONFIG_RT_USING_USER_MAIN=y CONFIG_RT_MAIN_THREAD_STACK_SIZE=2048 CONFIG_RT_MAIN_THREAD_PRIORITY=10 # CONFIG_RT_USING_LEGACY is not set -# CONFIG_RT_USING_MSH is not set -# CONFIG_RT_USING_DFS is not set +CONFIG_RT_USING_MSH=y +CONFIG_RT_USING_FINSH=y +CONFIG_FINSH_USING_MSH=y +CONFIG_FINSH_THREAD_NAME="tshell" +CONFIG_FINSH_THREAD_PRIORITY=20 +CONFIG_FINSH_THREAD_STACK_SIZE=4096 +CONFIG_FINSH_USING_HISTORY=y +CONFIG_FINSH_HISTORY_LINES=5 +CONFIG_FINSH_USING_SYMTAB=y +CONFIG_FINSH_CMD_SIZE=80 +CONFIG_MSH_USING_BUILT_IN_COMMANDS=y +CONFIG_FINSH_USING_DESCRIPTION=y +# CONFIG_FINSH_ECHO_DISABLE_DEFAULT is not set +# CONFIG_FINSH_USING_AUTH is not set +CONFIG_FINSH_ARG_MAX=10 +CONFIG_RT_USING_DFS=y +CONFIG_DFS_USING_POSIX=y +CONFIG_DFS_USING_WORKDIR=y +CONFIG_DFS_FILESYSTEMS_MAX=4 +CONFIG_DFS_FILESYSTEM_TYPES_MAX=4 +CONFIG_DFS_FD_MAX=16 +# CONFIG_RT_USING_DFS_MNTTABLE is not set +# CONFIG_RT_USING_DFS_ELMFAT is not set +CONFIG_RT_USING_DFS_DEVFS=y +# CONFIG_RT_USING_DFS_ROMFS is not set +# CONFIG_RT_USING_DFS_RAMFS is not set +# CONFIG_RT_USING_DFS_NFS is not set # CONFIG_RT_USING_FAL is not set # CONFIG_RT_USING_LWP is not set @@ -102,7 +129,9 @@ CONFIG_RT_MAIN_THREAD_PRIORITY=10 # Device Drivers # CONFIG_RT_USING_DEVICE_IPC=y -# CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set +CONFIG_RT_USING_SYSTEM_WORKQUEUE=y +CONFIG_RT_SYSTEM_WORKQUEUE_STACKSIZE=2048 +CONFIG_RT_SYSTEM_WORKQUEUE_PRIORITY=23 CONFIG_RT_USING_SERIAL=y CONFIG_RT_USING_SERIAL_V1=y # CONFIG_RT_USING_SERIAL_V2 is not set @@ -111,9 +140,11 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set -# CONFIG_RT_USING_I2C is not set +CONFIG_RT_USING_I2C=y +# CONFIG_RT_I2C_DEBUG is not set +# CONFIG_RT_USING_I2C_BITOPS is not set # CONFIG_RT_USING_PHY is not set -CONFIG_RT_USING_PIN=y +# CONFIG_RT_USING_PIN is not set # CONFIG_RT_USING_ADC is not set # CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set @@ -147,11 +178,20 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # POSIX (Portable Operating System Interface) layer # -# CONFIG_RT_USING_POSIX_FS is not set -# CONFIG_RT_USING_POSIX_DELAY is not set -# CONFIG_RT_USING_POSIX_CLOCK is not set -# CONFIG_RT_USING_POSIX_TIMER is not set -# CONFIG_RT_USING_PTHREADS is not set +CONFIG_RT_USING_POSIX_FS=y +CONFIG_RT_USING_POSIX_DEVIO=y +# CONFIG_RT_USING_POSIX_STDIO is not set +CONFIG_RT_USING_POSIX_POLL=y +CONFIG_RT_USING_POSIX_SELECT=y +CONFIG_RT_USING_POSIX_SOCKET=y +# CONFIG_RT_USING_POSIX_TERMIOS is not set +CONFIG_RT_USING_POSIX_AIO=y +# CONFIG_RT_USING_POSIX_MMAN is not set +CONFIG_RT_USING_POSIX_DELAY=y +CONFIG_RT_USING_POSIX_CLOCK=y +CONFIG_RT_USING_POSIX_TIMER=y +CONFIG_RT_USING_PTHREADS=y +CONFIG_PTHREAD_NUM_MAX=8 # CONFIG_RT_USING_MODULE is not set # @@ -169,9 +209,80 @@ CONFIG_RT_LIBC_DEFAULT_TIMEZONE=8 # # Network # -# CONFIG_RT_USING_SAL is not set -# CONFIG_RT_USING_NETDEV is not set -# CONFIG_RT_USING_LWIP is not set +CONFIG_RT_USING_SAL=y +CONFIG_SAL_INTERNET_CHECK=y + +# +# protocol stack implement +# +CONFIG_SAL_USING_LWIP=y +CONFIG_SAL_USING_POSIX=y +CONFIG_RT_USING_NETDEV=y +CONFIG_NETDEV_USING_IFCONFIG=y +CONFIG_NETDEV_USING_PING=y +CONFIG_NETDEV_USING_NETSTAT=y +CONFIG_NETDEV_USING_AUTO_DEFAULT=y +# CONFIG_NETDEV_USING_IPV6 is not set +CONFIG_NETDEV_IPV4=1 +CONFIG_NETDEV_IPV6=0 +# CONFIG_NETDEV_IPV6_SCOPES is not set +CONFIG_RT_USING_LWIP=y +CONFIG_RT_USING_LWIP_LOCAL_VERSION=y +# CONFIG_RT_USING_LWIP141 is not set +# CONFIG_RT_USING_LWIP203 is not set +CONFIG_RT_USING_LWIP212=y +CONFIG_RT_USING_LWIP_VER_NUM=0x20102 +# CONFIG_RT_USING_LWIP_IPV6 is not set +CONFIG_RT_LWIP_MEM_ALIGNMENT=4 +CONFIG_RT_LWIP_IGMP=y +CONFIG_RT_LWIP_ICMP=y +# CONFIG_RT_LWIP_SNMP is not set +CONFIG_RT_LWIP_DNS=y +CONFIG_RT_LWIP_DHCP=y +CONFIG_IP_SOF_BROADCAST=1 +CONFIG_IP_SOF_BROADCAST_RECV=1 + +# +# Static IPv4 Address +# +CONFIG_RT_LWIP_IPADDR="192.168.1.30" +CONFIG_RT_LWIP_GWADDR="192.168.1.1" +CONFIG_RT_LWIP_MSKADDR="255.255.255.0" +CONFIG_RT_LWIP_UDP=y +CONFIG_RT_LWIP_TCP=y +CONFIG_RT_LWIP_RAW=y +# CONFIG_RT_LWIP_PPP is not set +CONFIG_RT_MEMP_NUM_NETCONN=8 +CONFIG_RT_LWIP_PBUF_NUM=16 +CONFIG_RT_LWIP_RAW_PCB_NUM=4 +CONFIG_RT_LWIP_UDP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_PCB_NUM=4 +CONFIG_RT_LWIP_TCP_SEG_NUM=40 +CONFIG_RT_LWIP_TCP_SND_BUF=8196 +CONFIG_RT_LWIP_TCP_WND=8196 +CONFIG_RT_LWIP_TCPTHREAD_PRIORITY=10 +CONFIG_RT_LWIP_TCPTHREAD_MBOX_SIZE=8 +CONFIG_RT_LWIP_TCPTHREAD_STACKSIZE=1024 +# CONFIG_LWIP_NO_RX_THREAD is not set +# CONFIG_LWIP_NO_TX_THREAD is not set +CONFIG_RT_LWIP_ETHTHREAD_PRIORITY=12 +CONFIG_RT_LWIP_ETHTHREAD_STACKSIZE=1024 +CONFIG_RT_LWIP_ETHTHREAD_MBOX_SIZE=8 +# CONFIG_RT_LWIP_REASSEMBLY_FRAG is not set +CONFIG_LWIP_NETIF_STATUS_CALLBACK=1 +CONFIG_LWIP_NETIF_LINK_CALLBACK=1 +CONFIG_SO_REUSE=1 +CONFIG_LWIP_SO_RCVTIMEO=1 +CONFIG_LWIP_SO_SNDTIMEO=1 +CONFIG_LWIP_SO_RCVBUF=1 +CONFIG_LWIP_SO_LINGER=0 +# CONFIG_RT_LWIP_NETIF_LOOPBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=0 +# CONFIG_RT_LWIP_STATS is not set +# CONFIG_RT_LWIP_USING_HW_CHECKSUM is not set +CONFIG_RT_LWIP_USING_PING=y +# CONFIG_LWIP_USING_DHCPD is not set +# CONFIG_RT_LWIP_DEBUG is not set # CONFIG_RT_USING_AT is not set # @@ -640,9 +751,14 @@ CONFIG_SOC_SAME70Q21=y # CONFIG_SAME70_CAN0=y CONFIG_SAME70_ADC0=y +CONFIG_SAME70_I2C0=y +CONFIG_SAME70_GMAC=y # # Application Demo Config # CONFIG_SAM_CAN_EXAMPLE=y +CONFIG_SAM_ADC_EXAMPLE=y +CONFIG_SAM_I2C_EXAMPLE=y +CONFIG_SAM_LWIP_EXAMPLE=y CONFIG_SOC_SAME70=y diff --git a/bsp/microchip/same70/SConstruct b/bsp/microchip/same70/SConstruct index 4d91cd5ba5..9f8b13d9cf 100644 --- a/bsp/microchip/same70/SConstruct +++ b/bsp/microchip/same70/SConstruct @@ -34,8 +34,27 @@ if rtconfig.PLATFORM == 'iar': Export('RTT_ROOT') Export('rtconfig') +SDK_ROOT = os.path.abspath('./') + +if os.path.exists(SDK_ROOT + '/common'): + common_path_prefix = SDK_ROOT + '/common' +else: + common_path_prefix = os.path.dirname(SDK_ROOT) + '/common' + +SDK_LIB = common_path_prefix +Export('SDK_LIB') + # prepare building environment objs = PrepareBuilding(env, RTT_ROOT, has_libcpu=False) +sam_board = 'board' +rtconfig.BSP_LIBRARY_TYPE = sam_board + +# include libraries +objs.extend(SConscript(os.path.join(common_path_prefix, sam_board, 'SConscript'))) + +# include drivers +objs.extend(SConscript(os.path.join(common_path_prefix, 'applications', 'SConscript'))) + # make a building DoBuilding(TARGET, objs) diff --git a/bsp/microchip/same70/applications/can_demo.c b/bsp/microchip/same70/applications/can_demo.c deleted file mode 100644 index 1c82466220..0000000000 --- a/bsp/microchip/same70/applications/can_demo.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2006-2021, RT-Thread Development Team - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release - */ - -#include - -#ifdef RT_USING_FINSH -#include -#include -#endif - -#include "atmel_start.h" -#include "driver_init.h" -#include "utils.h" - -#include "can_demo.h" - -#ifdef SAM_CAN_EXAMPLE - -static volatile enum can_async_interrupt_type can_errors; -static rt_sem_t can_txdone; -static rt_sem_t can_rxdone; -static rt_uint8_t can_stack[ 512 ]; -static struct rt_thread can_thread; - -/** - * @brief Callback function and should be invoked after call can_async_write. - * - * @note - * - * @param descr is CAN device description. - * - * @return None. - */ - -static void can_tx_callback(struct can_async_descriptor *const descr) -{ - rt_err_t result; - - rt_interrupt_enter(); - result = rt_sem_release(can_txdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); -} - -/** - * @brief Callback function and should be invoked after remote device send. - * - * @note This callback function will be called in CAN interrupt function - * - * @param descr is CAN device description. - * - * @return None. - */ - -static void can_rx_callback(struct can_async_descriptor *const descr) -{ - rt_err_t result; - - rt_interrupt_enter(); - result = rt_sem_release(can_rxdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); -} - -/** - * @brief Callback function and should be invoked after CAN device IRQ handler detects errors happened. - * - * @note This callback function will be called in CAN interrupt function - * - * @param descr is CAN device description. - * - * @return None. - */ - -static void can_err_callback(struct can_async_descriptor *const descr, - enum can_async_interrupt_type type) -{ - rt_err_t result; - - if (type == CAN_IRQ_EW) - { - /* Error warning, Error counter has reached the error warning limit of 96, - * An error count value greater than about 96 indicates a heavily disturbed - * bus. It may be of advantage to provide means to test for this condition. - */ - } - else if (type == CAN_IRQ_EA) - { - /* Error Active State, The CAN node normally take part in bus communication - * and sends an ACTIVE ERROR FLAG when an error has been detected. - */ - } - else if (type == CAN_IRQ_EP) - { - /* Error Passive State, The Can node goes into error passive state if at least - * one of its error counters is greater than 127. It still takes part in bus - * activities, but it sends a passive error frame only, on errors. - */ - } - else if (type == CAN_IRQ_BO) - { - /* Bus Off State, The CAN node is 'bus off' when the TRANSMIT ERROR COUNT is - * greater than or equal to 256. - */ - - /* Suspend CAN task and re-initialize CAN module. */ - can_errors = type; - rt_interrupt_enter(); - result = rt_sem_release(can_rxdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); - } - else if (type == CAN_IRQ_DO) - { - /* Data Overrun in receive queue. A message was lost because the messages in - * the queue was not reading and releasing fast enough. There is not enough - * space for a new message in receive queue. - */ - - /* Suggest to delete CAN task and re-initialize it. */ - can_errors = type; - rt_interrupt_enter(); - result = rt_sem_release(can_rxdone); - if (RT_EOK != result) - { -#ifndef RT_USING_FINSH - rt_kprintf("rt_sem_release failed in %s %d\r\n",__FUNCTION__, __LINE__); -#endif - } - rt_interrupt_leave(); - } -}; - -/** - * @brief Initialize CAN module before task run. - * - * @note This function will set CAN Tx/Rx callback function and filters. - * - * @param None. - * - * @return None. - */ - -static inline void can_demo_init(void) -{ - struct can_filter filter; - - /** - * CAN_Node0_tx_callback callback should be invoked after call - * can_async_write, and remote device should receive message with ID=0x45A - */ - can_async_register_callback(&CAN_0, CAN_ASYNC_TX_CB, (FUNC_PTR)can_tx_callback); - - /** - * CAN_0_rx_callback callback should be invoked after call - * can_async_set_filter and remote device send CAN Message with the same - * content as the filter. - */ - can_async_register_callback(&CAN_0, CAN_ASYNC_RX_CB, (FUNC_PTR)can_rx_callback); - - - /* Should set at least one CAN standard & message filter before enable it. */ - - filter.id = 0x469; - filter.mask = 0; - can_async_set_filter(&CAN_0, 0, CAN_FMT_STDID, &filter); - - /* If set second standard message filter, should increase filter index - * and filter algorithm - * For example: index should set to 1, otherwise it will replace filter 0. - * can_async_set_filter(&CAN_0, 1, CAN_FMT_STDID, &filter); */ - - filter.id = 0x10000096; - filter.mask = 0; - can_async_set_filter(&CAN_0, 0, CAN_FMT_EXTID, &filter); - - can_async_enable(&CAN_0); -} - -/** - * @brief CAN task. - * - * @note This task will waiting for CAN RX semaphore and then process input. - * - * @param parameter - task input parameter. - * - * @return None. - */ - -static void can_thread_entry(void* parameter) -{ - int32_t ret; - rt_err_t result; - uint8_t data[64]; - uint32_t count=0; - struct can_message msg; - - while (1) - { -#ifndef RT_USING_FINSH - rt_kprintf("can task run count : %d\r\n",count); -#endif - count++; - - result = rt_sem_take(can_rxdone, RT_WAITING_FOREVER); - if (RT_EOK != result) - continue; - - do - { - /* Process the incoming packet. */ - ret = can_async_read(&CAN_0, &msg); - if (ret == ERR_NONE) - { -#ifndef RT_USING_FINSH - rt_kprintf("CAN RX Message is % frame\r\n", - msg.type == CAN_TYPE_DATA ? "data" : "remote"); - rt_kprintf("CAN RX Message is % frame\r\n", - msg.type == CAN_FMT_STDID ? "Standard" : "Extended"); - rt_kprintf("can RX Message ID: 0x%X length: %d\r\n", msg.id, msg.len); - rt_kprintf("CAN RX Message content: "); - for (uint8_t i = 0; i < msg.len; i++) - rt_kprintf("0x%02X ", data[i]); - rt_kprintf("\r\n"); -#endif - } - } while (ret == ERR_NONE); /* Get all data stored in CAN RX FIFO */ - - /* CAN task got CAN error message, handler CAN Error Status */ - if ((can_errors == CAN_IRQ_BO) || (can_errors == CAN_IRQ_DO)) - { - can_async_init(&CAN_0, MCAN1); - } - } -} - -/** - * @brief Call this function will to send a CAN message. - * - * @note - * - * @param msg - message to be sent, timeouts - wait timeouts for Tx completion. - * - * @return RT_OK or RT_ERROR. - */ - -rt_err_t can_send_message(struct can_message *msg, rt_uint32_t timeouts) -{ - rt_err_t result; - - if (RT_NULL == msg) - { - rt_kprintf("can_send_message input message error\r\n"); - return RT_ERROR; - } - - can_async_write(&CAN_0, msg); - result = rt_sem_take(can_rxdone, timeouts); - - return result; -} - -/** - * @brief Call this function will create a CAN task. - * - * @note Should create Tx/Rx semaphore before run task. - * - * @param None. - * - * @return RT_OK or -RT_ERROR. - */ - -rt_err_t can_demo_run(void) -{ - rt_err_t result; - - can_rxdone = rt_sem_create("can_rx", 0, RT_IPC_FLAG_FIFO); - if (RT_NULL == can_rxdone) - { - rt_kprintf("can_rx semaphore create failed\r\n"); - return (-RT_ERROR); - } - - can_txdone = rt_sem_create("can_tx", 0, RT_IPC_FLAG_FIFO); - if (RT_NULL == can_txdone) - { - rt_kprintf("can_tx semaphore create failed\r\n"); - return (-RT_ERROR); - } - - can_demo_init(); - - /* initialize CAN thread */ - result = rt_thread_init(&can_thread, - "can", - can_thread_entry, - RT_NULL, - (rt_uint8_t*)&can_stack[0], - sizeof(can_stack), - RT_THREAD_PRIORITY_MAX/3, - 5); - if (result == RT_EOK) - { - rt_thread_startup(&can_thread); - } - - return result; -} -#endif - -/*@}*/ diff --git a/bsp/microchip/same70/applications/can_demo.h b/bsp/microchip/same70/applications/can_demo.h deleted file mode 100644 index 499d0390f8..0000000000 --- a/bsp/microchip/same70/applications/can_demo.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release - */ - -#ifndef __APPLICATION_CAN_H_ -#define __APPLICATION_CAN_H_ - -#include - -/** - * @brief External function definitions - * - */ -rt_err_t can_demo_run(void); - -rt_err_t can_send_message(struct can_message *msg, rt_uint32_t timeouts); - -#endif // __APPLICATION_CAN_H_ diff --git a/bsp/microchip/same70/applications/main.c b/bsp/microchip/same70/applications/main.c index 8985159058..d08200f628 100644 --- a/bsp/microchip/same70/applications/main.c +++ b/bsp/microchip/same70/applications/main.c @@ -5,7 +5,7 @@ * * Change Logs: * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release + * 2022-04-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release */ #include @@ -22,6 +22,18 @@ #include "can_demo.h" #endif +#ifdef SAM_I2C_EXAMPLE +#include "i2c_demo.h" +#endif + +#ifdef SAM_ADC_EXAMPLE +#include "adc_demo.h" +#endif + +#ifdef SAM_LWIP_EXAMPLE +#include "lwip_demo.h" +#endif + static rt_uint8_t led_stack[ 512 ]; static struct rt_thread led_thread; @@ -63,6 +75,18 @@ int main(void) can_demo_run(); #endif +#ifdef SAM_I2C_EXAMPLE + i2c_demo_run(); +#endif + +#ifdef SAM_ADC_EXAMPLE + adc_demo_run(); +#endif + +#ifdef SAM_LWIP_EXAMPLE + lwip_demo_run(); +#endif + return 0; } diff --git a/bsp/microchip/same70/board/Kconfig b/bsp/microchip/same70/board/Kconfig index 19921f9eec..5de3724a4a 100644 --- a/bsp/microchip/same70/board/Kconfig +++ b/bsp/microchip/same70/board/Kconfig @@ -30,6 +30,14 @@ menu "Onboard Peripheral Drivers" config SAME70_ADC0 bool "Enable ADC0" default false + + config SAME70_I2C0 + bool "Enable I2C0" + default false + + config SAME70_GMAC + bool "Enable GMAC" + default false endmenu menu "Application Demo Config" @@ -47,4 +55,18 @@ menu "Application Demo Config" help Add ADC example task to project + config SAM_I2C_EXAMPLE + bool "Enable SAM I2C Example" + depends on SAME70_I2C0 + default true + help + Add I2C example task to project + + config SAM_LWIP_EXAMPLE + bool "Enable SAM LWIP Example" + depends on SAME70_GMAC + default false + help + Add GMAC LWIP example task to project + endmenu diff --git a/bsp/microchip/same70/board/board.c b/bsp/microchip/same70/board/board.c index bd98d8bf88..00f9874edb 100644 --- a/bsp/microchip/same70/board/board.c +++ b/bsp/microchip/same70/board/board.c @@ -25,13 +25,14 @@ static struct io_descriptor* g_stdio; void rt_hw_console_output(const char *str) { io_write(g_stdio, (uint8_t *)str, strlen(str)); + while (TARGET_IO.stat != 0); } RTM_EXPORT(rt_hw_console_output); static inline void hw_board_init_usart(void) { - usart_sync_get_io_descriptor(&TARGET_IO, &g_stdio); - usart_sync_enable(&TARGET_IO); + usart_async_get_io_descriptor(&TARGET_IO, &g_stdio); + usart_async_enable(&TARGET_IO); } /** diff --git a/bsp/microchip/same70/board/serial.c b/bsp/microchip/same70/board/serial.c deleted file mode 100644 index 28ba104dbe..0000000000 --- a/bsp/microchip/same70/board/serial.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (c) - * - * SPDX-License-Identifier: Apache-2.0 - * - * Change Logs: - * Date Author Email Notes - * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release - */ - -#include -#include - -#include - -/* SAM MCU serial device */ -static struct rt_serial_device sam_serial; - -/** - * @brief Configure serial port - * - * This function will configure UART baudrate, parity and so on. - * - * @return RT_EOK. - */ -static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg) -{ - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - RT_ASSERT(cfg != RT_NULL); - - usart_sync_disable(desc); - - /* Set baudrate */ - usart_sync_set_baud_rate(desc, (const uint32_t)cfg->baud_rate); - - /* Set stop bit */ - if (cfg->stop_bits == STOP_BITS_1) - usart_sync_set_stopbits(desc, USART_STOP_BITS_ONE); - else if (cfg->stop_bits == STOP_BITS_2) - usart_sync_set_stopbits(desc, USART_STOP_BITS_TWO); - - if (cfg->bit_order == BIT_ORDER_LSB) - usart_sync_set_data_order(desc, USART_DATA_ORDER_LSB); - else if (cfg->bit_order == BIT_ORDER_MSB) - usart_sync_set_data_order(desc, USART_DATA_ORDER_MSB); - - /* Set character size */ - switch (cfg->data_bits) - { - case DATA_BITS_5: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_5BITS); - break; - case DATA_BITS_6: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_6BITS); - break; - case DATA_BITS_7: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_7BITS); - break; - case DATA_BITS_8: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_8BITS); - break; - case DATA_BITS_9: - usart_sync_set_character_size(desc, USART_CHARACTER_SIZE_9BITS); - break; - default: - break; - } - - if (cfg->parity == PARITY_NONE) - usart_sync_set_parity(desc, USART_PARITY_NONE); - else if (cfg->parity == PARITY_ODD) - usart_sync_set_parity(desc, USART_PARITY_ODD); - else if (cfg->parity == PARITY_EVEN) - usart_sync_set_parity(desc, USART_PARITY_EVEN); - - usart_sync_enable(desc); - - return RT_EOK; -} - -/** - * @brief Control serial port - * - * This function provide UART enable/disable control. - * - * @return RT_EOK. - */ -static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg) -{ - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - - switch (cmd) - { - /* disable interrupt */ - case RT_DEVICE_CTRL_CLR_INT: - usart_sync_disable(desc); - break; - /* enable interrupt */ - case RT_DEVICE_CTRL_SET_INT: - usart_sync_enable(desc); - break; - /* UART config */ - case RT_DEVICE_CTRL_CONFIG : - break; - } - - return RT_EOK; -} - -/** - * @brief Serial sends a char - * - * This function will send a char to the UART - * - * @return 1. - */ -static int serial_putc(struct rt_serial_device *serial, char c) -{ - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - - io_write(&desc->io, (const uint8_t *)&c, 1); - - return 1; -} - -/** - * @brief Serial gets a char - * - * This function will get a char from the UART - * - * @return received char character or -1 if no char received. - */ -static int serial_getc(struct rt_serial_device *serial) -{ - char c; - int ch; - struct usart_sync_descriptor* desc; - - RT_ASSERT(serial != RT_NULL); - desc = (struct usart_sync_descriptor *)serial->parent.user_data; - - RT_ASSERT(desc != RT_NULL); - - ch = -1; - if (usart_sync_is_rx_not_empty(desc)) - { - io_read(&desc->io, (uint8_t *)&c, 1);; - ch = c & 0xff; - } - - return ch; -} - -static const struct rt_uart_ops sam_serial_ops = -{ - serial_configure, - serial_control, - serial_putc, - serial_getc, -}; - -/** - * @brief Initialize the UART - * - * This function initialize the UART - * - * @return None. - */ -int rt_hw_uart_init(void) -{ - struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; - - sam_serial.ops = &sam_serial_ops; - sam_serial.config = config; - sam_serial.serial_rx = RT_NULL; - sam_serial.serial_rx = RT_NULL; - rt_hw_serial_register(&sam_serial, "uart0", - RT_DEVICE_FLAG_RDWR, (void *)&TARGET_IO); - - return 0; -} - -/*@}*/ diff --git a/bsp/microchip/same70/bsp/AtmelStart.gpdsc b/bsp/microchip/same70/bsp/AtmelStart.gpdsc index ace1a9358b..f90c1b21ed 100644 --- a/bsp/microchip/same70/bsp/AtmelStart.gpdsc +++ b/bsp/microchip/same70/bsp/AtmelStart.gpdsc @@ -42,14 +42,19 @@ Atmel Start Framework #define ATMEL_START + - + + + + + @@ -58,17 +63,23 @@ + + + + + - + + @@ -85,6 +96,7 @@ + @@ -123,56 +135,75 @@ - - + + + + + - + + + + - + + + + - + + + + + - + + + + - + + + + diff --git a/bsp/microchip/same70/bsp/SConscript b/bsp/microchip/same70/bsp/SConscript index 246544ed8c..d536217949 100644 --- a/bsp/microchip/same70/bsp/SConscript +++ b/bsp/microchip/same70/bsp/SConscript @@ -14,14 +14,19 @@ CPPDEFINES += [rtconfig.DEVICE_TYPE] src = Glob('hal/src/*.c') src += Glob('hal/utils/src/*.c') +src += Glob('hpl/afec/*.c') src += Glob('hpl/core/*.c') +src += Glob('hpl/gmac/*.c') src += Glob('hpl/mcan/*.c') src += Glob('hpl/pmc/*.c') src += Glob('hpl/systick/*.c') +src += Glob('hpl/twihs/*.c') src += Glob('hpl/usart/*.c') src += Glob('hpl/xdmac/*.c') +src += Glob('ethernet_phy/*.c') src += [cwd + '/atmel_start.c'] src += [cwd + '/driver_init.c'] +src += [cwd + '/ethernet_phy_main.c'] #add for startup script if rtconfig.CROSS_TOOL == 'gcc': @@ -38,6 +43,7 @@ path = [ cwd, cwd + '/CMSIS/Core/Include', cwd + '/config', + cwd + '/ethernet_phy', cwd + '/hal/include', cwd + '/hal/utils/include', cwd + '/hpl/core', @@ -47,7 +53,9 @@ path = [ cwd + '/hpl/systick', cwd + '/hpl/usart', cwd + '/hri', - cwd + '/same70b/include',] + cwd + '/same70b/include', + cwd + '/../board', + cwd + '/../../common/applications'] group = DefineGroup('Libraries', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) diff --git a/bsp/microchip/same70/bsp/atmel_start.c b/bsp/microchip/same70/bsp/atmel_start.c index 79f252aed9..2faf66d653 100644 --- a/bsp/microchip/same70/bsp/atmel_start.c +++ b/bsp/microchip/same70/bsp/atmel_start.c @@ -6,4 +6,5 @@ void atmel_start_init(void) { system_init(); + ethernet_phys_init(); } diff --git a/bsp/microchip/same70/bsp/atmel_start.h b/bsp/microchip/same70/bsp/atmel_start.h index 0de62f528d..0793962b7a 100644 --- a/bsp/microchip/same70/bsp/atmel_start.h +++ b/bsp/microchip/same70/bsp/atmel_start.h @@ -6,6 +6,7 @@ extern "C" { #endif #include "driver_init.h" +#include "ethernet_phy_main.h" /** * Initializes MCU, drivers and middleware in the project diff --git a/bsp/microchip/same70/bsp/atmel_start_config.atstart b/bsp/microchip/same70/bsp/atmel_start_config.atstart index fdb95a78d9..0172faf227 100644 --- a/bsp/microchip/same70/bsp/atmel_start_config.atstart +++ b/bsp/microchip/same70/bsp/atmel_start_config.atstart @@ -17,21 +17,168 @@ board: identifier: SAME70Xplained device: ATSAME70Q21B-AN details: null -application: - definition: 'Atmel:Application_Examples:0.0.1::Application:LED_switcher:' - configuration: null -middlewares: {} +application: null +middlewares: + MACIF_PHY: + user_label: MACIF_PHY + configuration: + ieee8023_mii_control_autoneg_en: true + ieee8023_mii_control_duplex_mode: full duplex + ieee8023_mii_control_isolate_en: false + ieee8023_mii_control_loopback_en: false + ieee8023_mii_control_powerdown_en: false + ieee8023_mii_control_reg0_setting: true + ieee8023_mii_control_speed_lsb: 100 Mb/s + ieee8023_mii_phy_address: 0 + definition: Atmel:Ethernet_PHY:0.0.1::Generic_Ethernet_PHY_Driver + functionality: Ethernet_PHY + api: Ethernet:GenericPHY:Driver + dependencies: + Communication IO: MACIF drivers: + ADC_0: + user_label: ADC_0 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::AFEC0::driver_config_definition::ADC::HAL:Driver:ADC.Sync + functionality: ADC + api: HAL:Driver:ADC_Sync + configuration: + afec_advanced_settings: true + afec_channel0_enable: false + afec_channel10_enable: true + afec_channel11_enable: false + afec_channel1_enable: false + afec_channel2_enable: false + afec_channel3_enable: false + afec_channel4_enable: false + afec_channel5_enable: false + afec_channel6_enable: false + afec_channel7_enable: false + afec_channel8_enable: false + afec_channel9_enable: false + afec_channel_diff0: false + afec_channel_diff1: false + afec_channel_diff10: false + afec_channel_diff11: false + afec_channel_diff2: false + afec_channel_diff3: false + afec_channel_diff4: false + afec_channel_diff5: false + afec_channel_diff6: false + afec_channel_diff7: false + afec_channel_diff8: false + afec_channel_diff9: false + afec_channel_dual0: false + afec_channel_dual1: false + afec_channel_dual10: true + afec_channel_dual11: false + afec_channel_dual2: false + afec_channel_dual3: false + afec_channel_dual4: false + afec_channel_dual5: false + afec_channel_dual6: false + afec_channel_dual7: false + afec_channel_dual8: false + afec_channel_dual9: false + afec_channel_ecorr0: false + afec_channel_ecorr1: false + afec_channel_ecorr10: true + afec_channel_ecorr11: false + afec_channel_ecorr2: false + afec_channel_ecorr3: false + afec_channel_ecorr4: false + afec_channel_ecorr5: false + afec_channel_ecorr6: false + afec_channel_ecorr7: false + afec_channel_ecorr8: false + afec_channel_ecorr9: false + afec_channel_gain0: '1' + afec_channel_gain1: '1' + afec_channel_gain10: '1' + afec_channel_gain11: '1' + afec_channel_gain2: '1' + afec_channel_gain3: '1' + afec_channel_gain4: '1' + afec_channel_gain5: '1' + afec_channel_gain6: '1' + afec_channel_gain7: '1' + afec_channel_gain8: '1' + afec_channel_gain9: '1' + afec_channel_offset0: 512 + afec_channel_offset1: 512 + afec_channel_offset10: 512 + afec_channel_offset11: 512 + afec_channel_offset2: 512 + afec_channel_offset3: 512 + afec_channel_offset4: 512 + afec_channel_offset5: 512 + afec_channel_offset6: 512 + afec_channel_offset7: 512 + afec_channel_offset8: 512 + afec_channel_offset9: 512 + afec_cmpmode: The converted data is lower than the low threshold of the window. + afec_cmpsel: Channel 0 + afec_compare_all_channels: false + afec_comparison_settings: false + afec_cosr_csel: false + afec_fast_wakeup_mode: false + afec_freerunning_mode: false + afec_gaincorr: 0 + afec_highthres: 0 + afec_ibctl: 1 + afec_lowthres: 0 + afec_offsetcorr: 0 + afec_prescaler: 49 + afec_resolution: 16-bit + afec_sign_mode: 'Single-Ended channels: Unsigned. Differential channels: Signed.' + afec_sleep_mode: false + afec_startup_time: 64 periods of AFE clock + afec_stm: true + afec_tag: true + afec_tracktim: 15 + afec_transfer: 2 + afec_trigger_enable: false + afec_trigger_selection: AFE0_ADTRG for AFEC0 / AFE1_ADTRG for AFEC1 + afec_usch0: None + afec_usch1: None + afec_usch10: None + afec_usch11: None + afec_usch2: None + afec_usch3: None + afec_usch4: None + afec_usch5: None + afec_usch6: None + afec_usch7: None + afec_usch8: None + afec_usch9: None + afec_useq: false + optional_signals: + - identifier: ADC_0:AD/10 + pad: PB0 + mode: Enabled + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::AFEC0.AD.10 + name: AFEC0/AD/10 + label: AD/10 + variant: null + clocks: + domain_group: + nodes: + - name: AFEC + input: Master Clock (MCK) + external: false + external_frequency: 0 + configuration: + afec_clock_source: Master Clock (MCK) PMC: user_label: PMC definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::PMC::driver_config_definition::PMC::HAL:HPL:PMC functionality: System api: HAL:HPL:PMC configuration: - $input: 240000000 - $input_id: UDPLL with Divider (MCKR UPLLDIV2) - RESERVED_InputFreq: 240000000 - RESERVED_InputFreq_id: UDPLL with Divider (MCKR UPLLDIV2) + $input: 12000000 + $input_id: Main Clock (MAINCK) + RESERVED_InputFreq: 12000000 + RESERVED_InputFreq_id: Main Clock (MAINCK) _$freq_output_32kHz External Crystal Oscillator (XOSC32K): 0 _$freq_output_32kHz High Accuracy Internal Oscillator (OSC32K): 0 _$freq_output_Embedded 4/8/12MHz RC Oscillator (OSC12M): '12000000' @@ -165,27 +312,58 @@ drivers: external: false external_frequency: 0 configuration: {} - DELAY_0: - user_label: DELAY_0 - definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::SysTick::driver_config_definition::Delay::HAL:Driver:Delay - functionality: Delay - api: HAL:Driver:Delay + I2C_0: + user_label: I2C_0 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::TWIHS0::driver_config_definition::I2C.Master.Standard~2FFast-mode::HAL:Driver:I2C.Master.Sync + functionality: I2C + api: HAL:Driver:I2C_Master_Sync configuration: - systick_arch_tickint: false - optional_signals: [] + i2c_master_advanced: true + i2c_master_baud_rate: 100000 + i2c_master_digital_filter_enable: true + i2c_master_filter_threshold: '2' + i2c_master_packet_error_check: false + i2c_master_pad_filter_enable: true + i2c_master_smbus_clock_prescaler: Divide by 2 + i2c_master_smbus_enable: false + i2c_master_thigh_max: 0 + i2c_master_tlow_mext: 0 + i2c_master_tlow_sext: 0 + optional_signals: + - identifier: I2C_0:TWCK/0 + pad: PA4 + mode: Enabled + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::TWIHS0.TWCK.0 + name: TWIHS0/TWCK/0 + label: TWCK/0 + - identifier: I2C_0:TWD/0 + pad: PA3 + mode: Enabled + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::TWIHS0.TWD.0 + name: TWIHS0/TWD/0 + label: TWD/0 variant: null clocks: - domain_group: null + domain_group: + nodes: + - name: TWIHS + input: Master Clock (MCK) + external: false + external_frequency: 0 + configuration: + twihs_clock_source: Master Clock (MCK) TARGET_IO: user_label: TARGET_IO - definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::USART1::driver_config_definition::UART::HAL:Driver:USART.Sync + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::USART1::driver_config_definition::UART::HAL:Driver:USART.Async functionality: USART - api: HAL:Driver:USART_Sync + api: HAL:Driver:USART_Async configuration: usart_9bits_enable: false usart__inack: The NACK is not generated usart__oversampling_mode: 16 Oversampling - usart_advanced: false + usart_advanced: true usart_arch_fractional: 0 usart_arch_msbf: LSB is transmitted first usart_baud_rate: 115200 @@ -479,6 +657,145 @@ drivers: variant: null clocks: domain_group: null + MACIF: + user_label: MACIF + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::GMAC::driver_config_definition::GMAC::HAL:Driver:GMAC.Async + functionality: Ethernet_MAC + api: HAL:Driver:GMAC_Async + configuration: + gmac_arch_adv_cfg: true + gmac_arch_cltto: Clause 22 Operation + gmac_arch_dcfgr_ddrp: false + gmac_arch_dcfgr_drbs: 8 + gmac_arch_dcfgr_esma: false + gmac_arch_dcfgr_espa: false + gmac_arch_dcfgr_fbldo: Always use INCR4 AHB bursts + gmac_arch_dcfgr_rxbms: 4 Kbytes + gmac_arch_dcfgr_txcoen: true + gmac_arch_dcfgr_txpbms: 4 Kbytes + gmac_arch_dma_cfg: true + gmac_arch_ipgs_fl_div: 1 + gmac_arch_ipgs_fl_mul: 1 + gmac_arch_mii_cfg: true + gmac_arch_ncfgr_caf: false + gmac_arch_ncfgr_clk: '64' + gmac_arch_ncfgr_dcpf: false + gmac_arch_ncfgr_df: true + gmac_arch_ncfgr_dnvlan: false + gmac_arch_ncfgr_efrhd: false + gmac_arch_ncfgr_ipgsen: false + gmac_arch_ncfgr_irxer: false + gmac_arch_ncfgr_irxfcs: false + gmac_arch_ncfgr_jframe: false + gmac_arch_ncfgr_lferd: false + gmac_arch_ncfgr_maxfs: true + gmac_arch_ncfgr_mtihen: false + gmac_arch_ncfgr_nbc: false + gmac_arch_ncfgr_pen: false + gmac_arch_ncfgr_rfcs: false + gmac_arch_ncfgr_rty: false + gmac_arch_ncfgr_rxbp: false + gmac_arch_ncfgr_rxbufo: 0 + gmac_arch_ncfgr_rxcoen: false + gmac_arch_ncfgr_spd: true + gmac_arch_ncfgr_unihen: false + gmac_arch_ncr_bp: false + gmac_arch_ncr_enpbpr: false + gmac_arch_ncr_lbl: false + gmac_arch_ncr_mpe: true + gmac_arch_ncr_txpbpf: false + gmac_arch_ncr_westat: false + gmac_arch_rpsf_en: false + gmac_arch_rpsf_wm: 100 + gmac_arch_rxdescr_num: 16 + gmac_arch_svlan_enable: true + gmac_arch_svlan_type: 33024 + gmac_arch_tpsf_en: false + gmac_arch_tpsf_wm: 100 + gmac_arch_txbuf_size: 1500 + gmac_arch_txdescr_num: 8 + gmac_arch_ur_rmii: RMII + optional_signals: + - identifier: MACIF:GMDC + pad: PD8 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GMDC + name: GMAC/GMDC + label: GMDC + - identifier: MACIF:GMDIO + pad: PD9 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GMDIO + name: GMAC/GMDIO + label: GMDIO + - identifier: MACIF:GRX/0 + pad: PD5 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GRX.0 + name: GMAC/GRX/0 + label: GRX/0 + - identifier: MACIF:GRX/1 + pad: PD6 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GRX.1 + name: GMAC/GRX/1 + label: GRX/1 + - identifier: MACIF:GRXDV + pad: PD4 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GRXDV + name: GMAC/GRXDV + label: GRXDV + - identifier: MACIF:GRXER + pad: PD7 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GRXER + name: GMAC/GRXER + label: GRXER + - identifier: MACIF:GTX/0 + pad: PD2 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GTX.0 + name: GMAC/GTX/0 + label: GTX/0 + - identifier: MACIF:GTX/1 + pad: PD3 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GTX.1 + name: GMAC/GTX/1 + label: GTX/1 + - identifier: MACIF:GTXCK + pad: PD0 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GTXCK + name: GMAC/GTXCK + label: GTXCK + - identifier: MACIF:GTXEN + pad: PD1 + mode: Enable + configuration: null + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::optional_signal_definition::GMAC.GTXEN + name: GMAC/GTXEN + label: GTXEN + variant: null + clocks: + domain_group: + nodes: + - name: GMAC + input: Master Clock (MCK) + external: false + external_frequency: 0 + configuration: + gmac_clock_source: Master Clock (MCK) CAN_0: user_label: CAN_0 definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::MCAN1::driver_config_definition::CAN::HAL:Driver:CAN.Async @@ -543,12 +860,24 @@ drivers: configuration: mcan_clock_source: Programmable Clock Controller 5 (PMC_PCK5) pads: + PD0: + name: PD0 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD0 + mode: Peripheral IO + user_label: PD0 + configuration: null PC12: name: PC12 definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PC12 mode: Peripheral IO user_label: PC12 configuration: null + PB0: + name: PB0 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PB0 + mode: Analog + user_label: PB0 + configuration: null PA21: name: PA21 definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PA21 @@ -562,6 +891,12 @@ pads: user_label: SW0 configuration: pad_pull_config: Pull-up + PA4: + name: PA4 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PA4 + mode: Peripheral IO + user_label: PA4 + configuration: null LED0: name: PC8 definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PC8 @@ -569,6 +904,12 @@ pads: user_label: LED0 configuration: pad_initial_level: High + PA3: + name: PA3 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PA3 + mode: Peripheral IO + user_label: PA3 + configuration: null PC14: name: PC14 definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PC14 @@ -581,5 +922,59 @@ pads: mode: Peripheral IO user_label: PB4 configuration: null + PD9: + name: PD9 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD9 + mode: Peripheral IO + user_label: PD9 + configuration: null + PD8: + name: PD8 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD8 + mode: Peripheral IO + user_label: PD8 + configuration: null + PD7: + name: PD7 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD7 + mode: Peripheral IO + user_label: PD7 + configuration: null + PD6: + name: PD6 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD6 + mode: Peripheral IO + user_label: PD6 + configuration: null + PD5: + name: PD5 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD5 + mode: Peripheral IO + user_label: PD5 + configuration: null + PD4: + name: PD4 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD4 + mode: Peripheral IO + user_label: PD4 + configuration: null + PD3: + name: PD3 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD3 + mode: Peripheral IO + user_label: PD3 + configuration: null + PD2: + name: PD2 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD2 + mode: Peripheral IO + user_label: PD2 + configuration: null + PD1: + name: PD1 + definition: Atmel:SAME70B_Drivers:0.0.1::ATSAME70Q21B-AN::pad::PD1 + mode: Peripheral IO + user_label: PD1 + configuration: null toolchain_options: [] static_files: [] diff --git a/bsp/microchip/same70/bsp/atmel_start_pins.h b/bsp/microchip/same70/bsp/atmel_start_pins.h index 5a93767aeb..80cb035402 100644 --- a/bsp/microchip/same70/bsp/atmel_start_pins.h +++ b/bsp/microchip/same70/bsp/atmel_start_pins.h @@ -17,11 +17,24 @@ #define GPIO_PIN_FUNCTION_C 2 #define GPIO_PIN_FUNCTION_D 3 +#define PA3 GPIO(GPIO_PORTA, 3) +#define PA4 GPIO(GPIO_PORTA, 4) #define SW0 GPIO(GPIO_PORTA, 11) #define PA21 GPIO(GPIO_PORTA, 21) +#define PB0 GPIO(GPIO_PORTB, 0) #define PB4 GPIO(GPIO_PORTB, 4) #define LED0 GPIO(GPIO_PORTC, 8) #define PC12 GPIO(GPIO_PORTC, 12) #define PC14 GPIO(GPIO_PORTC, 14) +#define PD0 GPIO(GPIO_PORTD, 0) +#define PD1 GPIO(GPIO_PORTD, 1) +#define PD2 GPIO(GPIO_PORTD, 2) +#define PD3 GPIO(GPIO_PORTD, 3) +#define PD4 GPIO(GPIO_PORTD, 4) +#define PD5 GPIO(GPIO_PORTD, 5) +#define PD6 GPIO(GPIO_PORTD, 6) +#define PD7 GPIO(GPIO_PORTD, 7) +#define PD8 GPIO(GPIO_PORTD, 8) +#define PD9 GPIO(GPIO_PORTD, 9) #endif // ATMEL_START_PINS_H_INCLUDED diff --git a/bsp/microchip/same70/bsp/config/hpl_afec_config.h b/bsp/microchip/same70/bsp/config/hpl_afec_config.h new file mode 100644 index 0000000000..b9892e8096 --- /dev/null +++ b/bsp/microchip/same70/bsp/config/hpl_afec_config.h @@ -0,0 +1,1042 @@ +/* Auto-generated config file hpl_afec_config.h */ +#ifndef HPL_AFEC_CONFIG_H +#define HPL_AFEC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#ifndef CONF_AFEC_0_ENABLE +#define CONF_AFEC_0_ENABLE 1 +#endif + +// Basic Configuration + +// Conversion Result Resolution +// <0x0=>12-bit +// <0x2=>13-bit +// <0x3=>14-bit +// <0x4=>15-bit +// <0x5=>16-bit +// Defines the bit resolution for the AFEC sample values (RES) +// afec_resolution +#ifndef CONF_AFEC_0_RES +#define CONF_AFEC_0_RES 0x5 +#endif + +// Prescaler Rate Selection <1-255> +// PRESCAL = fperipheral clock/ fAFE_clock - 1 +// afec_prescaler +#ifndef CONF_AFEC_0_PRESCAL +#define CONF_AFEC_0_PRESCAL 0x31 +#endif + +// Free Running Mode +// When enabled, the ADC is in free running mode and a new conversion will be initiated when a previous conversion completes. (FREERUN) +// afec_freerunning_mode +#ifndef CONF_AFEC_0_FREERUN +#define CONF_AFEC_0_FREERUN 0 +#endif + +// TAG of the AFEC_LDCR +// When enabled, appends the channel number to the conversion result. +// afec_tag +#ifndef CONF_AFEC_0_TAG +#define CONF_AFEC_0_TAG 1 +#endif + +// Single Trigger Mode +// When enabled, only a single trigger is required to get an averaged value +// afec_stm +#ifndef CONF_AFEC_0_STM +#define CONF_AFEC_0_STM 1 +#endif + +// Sign Mode Selection +// <0x0=>Single-Ended channels: Unsigned. Differential channels: Signed. +// <0x1=>Single-Ended channels: Signed. Differential channels: Unsigned. +// <0x2=>All channels: Unsigned. +// <0x3=>All channels: Signed. +// Defines the bit resolution for the AFEC sample values (RES) +// afec_sign_mode +#ifndef CONF_AFEC_0_SIGNMODE +#define CONF_AFEC_0_SIGNMODE 0x0 +#endif + +// Trigger Enable +// Hardware triggers are disabled. Starting a conversion is only possible by software. +// afec_trigger_enable +#ifndef CONF_AFEC_0_TRGEN +#define CONF_AFEC_0_TRGEN 0 +#endif + +// Trigger Selection +// <0x0=>AFE0_ADTRG for AFEC0 / AFE1_ADTRG for AFEC1 +// <0x1=>TIOA Output of the TC Channel 0 for AFEC0/TIOA Output of the TC Channel 3 for AFEC1 +// <0x2=>TIOA Output of the TC Channel 1 for AFEC0/TIOA Output of the TC Channel 4 for AFEC1 +// <0x3=>TIOA Output of the TC Channel 2 for AFEC0/TIOA Output of the TC Channel 5 for AFEC1 +// <0x4=>PWM0 event line 0 for AFEC0 / PWM1 event line 0 for AFEC1 +// <0x5=>PWM0 event line 1 for AFEC0 / PWM1 event line 1 for AFEC1 +// <0x6=>Analog Comparator +// These bits define the trigger selection. +// afec_trigger_selection +#ifndef CONF_AFEC_0_TRGSEL +#define CONF_AFEC_0_TRGSEL 0x0 +#endif +// + +// + +// Channel Configuration + +// User Sequence Mode +// When enabled, the sequence respects what is defined +// afec_useq +#ifndef CONF_AFEC_0_USEQ +#define CONF_AFEC_0_USEQ 0x0 +#endif + +// User Sequence Number 0 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch0 +#ifndef CONF_AFEC_0_USCH0 +#define CONF_AFEC_0_USCH0 0xf +#endif + +// User Sequence Number 1 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch1 +#ifndef CONF_AFEC_0_USCH1 +#define CONF_AFEC_0_USCH1 0xf +#endif + +// User Sequence Number 2 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch2 +#ifndef CONF_AFEC_0_USCH2 +#define CONF_AFEC_0_USCH2 0xf +#endif + +// User Sequence Number 3 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch3 +#ifndef CONF_AFEC_0_USCH3 +#define CONF_AFEC_0_USCH3 0xf +#endif + +// User Sequence Number 4 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch4 +#ifndef CONF_AFEC_0_USCH4 +#define CONF_AFEC_0_USCH4 0xf +#endif + +// User Sequence Number 5 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch5 +#ifndef CONF_AFEC_0_USCH5 +#define CONF_AFEC_0_USCH5 0xf +#endif + +// User Sequence Number 6 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch6 +#ifndef CONF_AFEC_0_USCH6 +#define CONF_AFEC_0_USCH6 0xf +#endif + +// User Sequence Number 7 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch7 +#ifndef CONF_AFEC_0_USCH7 +#define CONF_AFEC_0_USCH7 0xf +#endif + +// User Sequence Number 8 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch8 +#ifndef CONF_AFEC_0_USCH8 +#define CONF_AFEC_0_USCH8 0xf +#endif + +// User Sequence Number 9 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch9 +#ifndef CONF_AFEC_0_USCH9 +#define CONF_AFEC_0_USCH9 0xf +#endif + +// User Sequence Number 10 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch10 +#ifndef CONF_AFEC_0_USCH10 +#define CONF_AFEC_0_USCH10 0xf +#endif + +// User Sequence Number 11 +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// <0xF=>None +// Defines the bit user sequence. +// afec_usch11 +#ifndef CONF_AFEC_0_USCH11 +#define CONF_AFEC_0_USCH11 0xf +#endif + +// + +// Channel 0 Enable +// afec_channel0_enable +#ifndef CONF_AFEC_0_CHANNEL0_ENABLE +#define CONF_AFEC_0_CHANNEL0_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain0 +#ifndef CONF_AFEC_0_GAIN0 +#define CONF_AFEC_0_GAIN0 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset0 +#ifndef CONF_AFEC_0_AOFF0 +#define CONF_AFEC_0_AOFF0 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff0 +#ifndef CONF_AFEC_0_DIFF0 +#define CONF_AFEC_0_DIFF0 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual0 +#ifndef CONF_AFEC_0_DUAL0 +#define CONF_AFEC_0_DUAL0 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr0 +#ifndef CONF_AFEC_0_ECORR0 +#define CONF_AFEC_0_ECORR0 0 +#endif +// + +// Channel 1 Enable +// afec_channel1_enable +#ifndef CONF_AFEC_0_CHANNEL1_ENABLE +#define CONF_AFEC_0_CHANNEL1_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain1 +#ifndef CONF_AFEC_0_GAIN1 +#define CONF_AFEC_0_GAIN1 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset1 +#ifndef CONF_AFEC_0_AOFF1 +#define CONF_AFEC_0_AOFF1 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff1 +#ifndef CONF_AFEC_0_DIFF1 +#define CONF_AFEC_0_DIFF1 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual1 +#ifndef CONF_AFEC_0_DUAL1 +#define CONF_AFEC_0_DUAL1 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr1 +#ifndef CONF_AFEC_0_ECORR1 +#define CONF_AFEC_0_ECORR1 0 +#endif +// + +// Channel 2 Enable +// afec_channel2_enable +#ifndef CONF_AFEC_0_CHANNEL2_ENABLE +#define CONF_AFEC_0_CHANNEL2_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain2 +#ifndef CONF_AFEC_0_GAIN2 +#define CONF_AFEC_0_GAIN2 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset2 +#ifndef CONF_AFEC_0_AOFF2 +#define CONF_AFEC_0_AOFF2 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff2 +#ifndef CONF_AFEC_0_DIFF2 +#define CONF_AFEC_0_DIFF2 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual2 +#ifndef CONF_AFEC_0_DUAL2 +#define CONF_AFEC_0_DUAL2 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr2 +#ifndef CONF_AFEC_0_ECORR2 +#define CONF_AFEC_0_ECORR2 0 +#endif +// + +// Channel 3 Enable +// afec_channel3_enable +#ifndef CONF_AFEC_0_CHANNEL3_ENABLE +#define CONF_AFEC_0_CHANNEL3_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain3 +#ifndef CONF_AFEC_0_GAIN3 +#define CONF_AFEC_0_GAIN3 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset3 +#ifndef CONF_AFEC_0_AOFF3 +#define CONF_AFEC_0_AOFF3 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff3 +#ifndef CONF_AFEC_0_DIFF3 +#define CONF_AFEC_0_DIFF3 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual3 +#ifndef CONF_AFEC_0_DUAL3 +#define CONF_AFEC_0_DUAL3 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr3 +#ifndef CONF_AFEC_0_ECORR3 +#define CONF_AFEC_0_ECORR3 0 +#endif +// + +// Channel 4 Enable +// afec_channel4_enable +#ifndef CONF_AFEC_0_CHANNEL4_ENABLE +#define CONF_AFEC_0_CHANNEL4_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain4 +#ifndef CONF_AFEC_0_GAIN4 +#define CONF_AFEC_0_GAIN4 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset4 +#ifndef CONF_AFEC_0_AOFF4 +#define CONF_AFEC_0_AOFF4 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff4 +#ifndef CONF_AFEC_0_DIFF4 +#define CONF_AFEC_0_DIFF4 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual4 +#ifndef CONF_AFEC_0_DUAL4 +#define CONF_AFEC_0_DUAL4 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr4 +#ifndef CONF_AFEC_0_ECORR4 +#define CONF_AFEC_0_ECORR4 0 +#endif +// + +// Channel 5 Enable +// afec_channel5_enable +#ifndef CONF_AFEC_0_CHANNEL5_ENABLE +#define CONF_AFEC_0_CHANNEL5_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain5 +#ifndef CONF_AFEC_0_GAIN5 +#define CONF_AFEC_0_GAIN5 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset5 +#ifndef CONF_AFEC_0_AOFF5 +#define CONF_AFEC_0_AOFF5 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff5 +#ifndef CONF_AFEC_0_DIFF5 +#define CONF_AFEC_0_DIFF5 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual5 +#ifndef CONF_AFEC_0_DUAL5 +#define CONF_AFEC_0_DUAL5 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr5 +#ifndef CONF_AFEC_0_ECORR5 +#define CONF_AFEC_0_ECORR5 0 +#endif +// + +// Channel 6 Enable +// afec_channel6_enable +#ifndef CONF_AFEC_0_CHANNEL6_ENABLE +#define CONF_AFEC_0_CHANNEL6_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain6 +#ifndef CONF_AFEC_0_GAIN6 +#define CONF_AFEC_0_GAIN6 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset6 +#ifndef CONF_AFEC_0_AOFF6 +#define CONF_AFEC_0_AOFF6 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff6 +#ifndef CONF_AFEC_0_DIFF6 +#define CONF_AFEC_0_DIFF6 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual6 +#ifndef CONF_AFEC_0_DUAL6 +#define CONF_AFEC_0_DUAL6 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr6 +#ifndef CONF_AFEC_0_ECORR6 +#define CONF_AFEC_0_ECORR6 0 +#endif +// + +// Channel 7 Enable +// afec_channel7_enable +#ifndef CONF_AFEC_0_CHANNEL7_ENABLE +#define CONF_AFEC_0_CHANNEL7_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain7 +#ifndef CONF_AFEC_0_GAIN7 +#define CONF_AFEC_0_GAIN7 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset7 +#ifndef CONF_AFEC_0_AOFF7 +#define CONF_AFEC_0_AOFF7 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff7 +#ifndef CONF_AFEC_0_DIFF7 +#define CONF_AFEC_0_DIFF7 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual7 +#ifndef CONF_AFEC_0_DUAL7 +#define CONF_AFEC_0_DUAL7 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr7 +#ifndef CONF_AFEC_0_ECORR7 +#define CONF_AFEC_0_ECORR7 0 +#endif +// + +// Channel 8 Enable +// afec_channel8_enable +#ifndef CONF_AFEC_0_CHANNEL8_ENABLE +#define CONF_AFEC_0_CHANNEL8_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain8 +#ifndef CONF_AFEC_0_GAIN8 +#define CONF_AFEC_0_GAIN8 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset8 +#ifndef CONF_AFEC_0_AOFF8 +#define CONF_AFEC_0_AOFF8 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff8 +#ifndef CONF_AFEC_0_DIFF8 +#define CONF_AFEC_0_DIFF8 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual8 +#ifndef CONF_AFEC_0_DUAL8 +#define CONF_AFEC_0_DUAL8 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr8 +#ifndef CONF_AFEC_0_ECORR8 +#define CONF_AFEC_0_ECORR8 0 +#endif +// + +// Channel 9 Enable +// afec_channel9_enable +#ifndef CONF_AFEC_0_CHANNEL9_ENABLE +#define CONF_AFEC_0_CHANNEL9_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain9 +#ifndef CONF_AFEC_0_GAIN9 +#define CONF_AFEC_0_GAIN9 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset9 +#ifndef CONF_AFEC_0_AOFF9 +#define CONF_AFEC_0_AOFF9 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff9 +#ifndef CONF_AFEC_0_DIFF9 +#define CONF_AFEC_0_DIFF9 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual9 +#ifndef CONF_AFEC_0_DUAL9 +#define CONF_AFEC_0_DUAL9 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr9 +#ifndef CONF_AFEC_0_ECORR9 +#define CONF_AFEC_0_ECORR9 0 +#endif +// + +// Channel 10 Enable +// afec_channel10_enable +#ifndef CONF_AFEC_0_CHANNEL10_ENABLE +#define CONF_AFEC_0_CHANNEL10_ENABLE 1 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain10 +#ifndef CONF_AFEC_0_GAIN10 +#define CONF_AFEC_0_GAIN10 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset10 +#ifndef CONF_AFEC_0_AOFF10 +#define CONF_AFEC_0_AOFF10 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff10 +#ifndef CONF_AFEC_0_DIFF10 +#define CONF_AFEC_0_DIFF10 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual10 +#ifndef CONF_AFEC_0_DUAL10 +#define CONF_AFEC_0_DUAL10 1 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr10 +#ifndef CONF_AFEC_0_ECORR10 +#define CONF_AFEC_0_ECORR10 1 +#endif +// + +// Channel 11 Enable +// afec_channel11_enable +#ifndef CONF_AFEC_0_CHANNEL11_ENABLE +#define CONF_AFEC_0_CHANNEL11_ENABLE 0 +#endif + +// Gain +// <0x0=>1 +// <0x1=>2 +// <0x2=>4 +// Defines the bit gain for channel. +// afec_channel_gain11 +#ifndef CONF_AFEC_0_GAIN11 +#define CONF_AFEC_0_GAIN11 0x0 +#endif + +// Offset Compensation <0-1023> +// Defines the analog offset. This value is used as an input value for the DAC included in the AFE. +// afec_channel_offset11 +#ifndef CONF_AFEC_0_AOFF11 +#define CONF_AFEC_0_AOFF11 0x200 +#endif + +// Differential Inputs Mode Enable +// When enabled, appends the channel number to the conversion result. +// afec_channel_diff11 +#ifndef CONF_AFEC_0_DIFF11 +#define CONF_AFEC_0_DIFF11 0 +#endif + +// Dual Sample & Hold Enable +// If enabled, dual Sample-and-Hold mode. Else, single Sample-and-Hold mode. +// afec_channel_dual11 +#ifndef CONF_AFEC_0_DUAL11 +#define CONF_AFEC_0_DUAL11 0 +#endif + +// Error Correction Enable +// If enabled, automatic error correction. +// afec_channel_ecorr11 +#ifndef CONF_AFEC_0_ECORR11 +#define CONF_AFEC_0_ECORR11 0 +#endif +// + +// + +// Advanced Configuration +// afec_advanced_settings +#ifndef CONF_AFEC_0_ADVANCED +#define CONF_AFEC_0_ADVANCED 1 +#endif + +// Sleep Mode +// When enabled, the AFE and reference voltage circuitry are OFF between conversions. +// afec_sleep_mode +#ifndef CONF_AFEC_0_SLEEP +#define CONF_AFEC_0_SLEEP 0 +#endif + +// Fast Wake-up Mode +// When enabled, the voltage reference is ON between conversions and AFE is OFF. +// afec_fast_wakeup_mode +#ifndef CONF_AFEC_0_FWUP +#define CONF_AFEC_0_FWUP 0 +#endif + +// Start-up Time +// <0x0=>0 periods of AFE clock +// <0x1=>8 periods of AFE clock +// <0x2=>16 periods of AFE clock +// <0x3=>24 periods of AFE clock +// <0x4=>64 periods of AFE clock +// <0x5=>80 periods of AFE clock +// <0x6=>96 periods of AFE clock +// <0x7=>112 periods of AFE clock +// <0x8=>512 periods of AFE clock +// <0x9=>576 periods of AFE clock +// <0xA=>640 periods of AFE clock +// <0xB=>704 periods of AFE clock +// <0xC=>768 periods of AFE clock +// <0xD=>832 periods of AFE clock +// <0xE=>896 periods of AFE clock +// <0xF=>960 periods of AFE clock +// Defines the bit start-up time. +// afec_startup_time +#ifndef CONF_AFEC_0_STARTUP +#define CONF_AFEC_0_STARTUP 0x4 +#endif + +// +// Tracking Time <0-16> +// Inherent tracking time is always 15 AFE clock cycles. Do not modify this field. +// afec_tracktim +#ifndef CONF_AFEC_0_TRACKTIM +#define CONF_AFEC_0_TRACKTIM 15 +#endif +// Transfer Period <0-3> +// Set to 2 to optimize transfer time. Do not modify this field. +// afec_transfer +#ifndef CONF_AFEC_0_TRANSFER +#define CONF_AFEC_0_TRANSFER 2 +#endif +// + +// AFE Bias Current Control <0-3> +// Adapts performance versus power consumption. +// afec_ibctl +#ifndef CONF_AFEC_0_IBCTL +#define CONF_AFEC_0_IBCTL 0x1 +#endif + +// Sample & Hold unit Correction Enable +// If enabled, selects the Sample & Hold unit will be displayed +// afec_cosr_csel +#ifndef CONF_AFEC_0_COSR_CSEL +#define CONF_AFEC_0_COSR_CSEL 0 +#endif + +// Offset Correction <0-4095> +// These bits define Offset correction. The offset is signed (2's complement), only bits 0 to 11 are relevant. +// afec_offsetcorr +#ifndef CONF_AFEC_0_OFFSETCORR +#define CONF_AFEC_0_OFFSETCORR 0 +#endif + +// Gain Correction <0-4095> +// These bits define gain correction. Only bits 0 to 11 are relevant. +// afec_gaincorr +#ifndef CONF_AFEC_0_GAINCORR +#define CONF_AFEC_0_GAINCORR 0 +#endif + +// + +// Comparison Mode Configuration +// Comparison mode configuration +// afec_comparison_settings +#ifndef CONF_AFEC_0_COMPARISON +#define CONF_AFEC_0_COMPARISON 0 +#endif + +// Comparison Mode +// <0x0=>The converted data is lower than the low threshold of the window. +// <0x1=>the converted data is higher than the high threshold of the window. +// <0x2=>the converted data is in the comparison window. +// <0x3=>the converted data is out of the comparison window. +// Defines the bit comparison mode. +// afec_cmpmode +#ifndef CONF_AFEC_0_CMPMODE +#define CONF_AFEC_0_CMPMODE 0x0 +#endif + +// Compare Window Lower Threshold <0-65535> +// These bits define the lower threshold value. +// afec_lowthres +#ifndef CONF_AFEC_0_LOWTHRES +#define CONF_AFEC_0_LOWTHRES 0 +#endif + +// Compare Window Upper Threshold <0-65535> +// These bits define the lower threshold value. +// afec_highthres +#ifndef CONF_AFEC_0_HIGHTHRES +#define CONF_AFEC_0_HIGHTHRES 0 +#endif + +// Compare All Channels +// If enabled, all channels are compared. Else, only the channel indicated in CMPSEL field is compared. +// afec_compare_all_channels +#ifndef CONF_AFEC_0_CMPALL +#define CONF_AFEC_0_CMPALL 0 +#endif + +// Comparison Selected Channel +// <0x0=>Channel 0 +// <0x1=>Channel 1 +// <0x2=>Channel 2 +// <0x3=>Channel 3 +// <0x4=>Channel 4 +// <0x5=>Channel 5 +// <0x6=>Channel 6 +// <0x7=>Channel 7 +// <0x8=>Channel 8 +// <0x9=>Channel 9 +// <0xA=>Channel 10 +// <0xB=>Channel 11 +// Defines the bit indicates which channel has to be compared. +// afec_cmpsel +#ifndef CONF_AFEC_0_CMPSEL +#define CONF_AFEC_0_CMPSEL 0x0 +#endif +// + +// + +// + +#if ((0 || CONF_AFEC_0_CHANNEL0_ENABLE || CONF_AFEC_0_CHANNEL1_ENABLE || CONF_AFEC_0_CHANNEL2_ENABLE \ + || CONF_AFEC_0_CHANNEL3_ENABLE || CONF_AFEC_0_CHANNEL4_ENABLE || CONF_AFEC_0_CHANNEL5_ENABLE \ + || CONF_AFEC_0_CHANNEL6_ENABLE || CONF_AFEC_0_CHANNEL7_ENABLE || CONF_AFEC_0_CHANNEL8_ENABLE \ + || CONF_AFEC_0_CHANNEL9_ENABLE || CONF_AFEC_0_CHANNEL10_ENABLE || CONF_AFEC_0_CHANNEL11_ENABLE) \ + == 0) +#warning Select one channel at least, check your configuration! +#endif + +// <<< end of configuration section >>> + +#endif // HPL_AFEC_CONFIG_H diff --git a/bsp/microchip/same70/bsp/config/hpl_gmac_config.h b/bsp/microchip/same70/bsp/config/hpl_gmac_config.h new file mode 100644 index 0000000000..9d63c18023 --- /dev/null +++ b/bsp/microchip/same70/bsp/config/hpl_gmac_config.h @@ -0,0 +1,492 @@ +/* Auto-generated config file hpl_gmac_config.h */ +#ifndef HPL_GMAC_CONFIG_H +#define HPL_GMAC_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include + +// Network Control configuration + +// Enable LoopBack Local +// Connects GTX to GRX, GTXEN to GRXDV and forces full duplex mode. +// gmac_arch_ncr_lbl +#ifndef CONF_GMAC_NCR_LBL +#define CONF_GMAC_NCR_LBL 0 +#endif + +// Management Port Enable +// Enable the Management port +// gmac_arch_ncr_mpe +#ifndef CONF_GMAC_NCR_MPE +#define CONF_GMAC_NCR_MPE 1 +#endif + +// Enable write for Static Register +// Make the statistics registers writable for functional test proposes. +// gmac_arch_ncr_westat +#ifndef CONF_GMAC_NCR_WESTAT +#define CONF_GMAC_NCR_WESTAT 0 +#endif + +// Enable Back pressure +// If set in 10M or 100M half duplex mode, forces collisions on all received frames. +// gmac_arch_ncr_bp +#ifndef CONF_GMAC_NCR_BP +#define CONF_GMAC_NCR_BP 0 +#endif + +// Enable PFC Priority-based Pause Reception +// Enables PFC negotiation and recognition of priority-based pause frames. +// gmac_arch_ncr_enpbpr +#ifndef CONF_GMAC_NCR_ENPBPR +#define CONF_GMAC_NCR_ENPBPR 0 +#endif + +// Enable PFC Priority-based Pause Frame +// Takes the values stored in the Transmit PFC Pause Register. +// gmac_arch_ncr_txpbpf +#ifndef CONF_GMAC_NCR_TXPBPF +#define CONF_GMAC_NCR_TXPBPF 0 +#endif + +// + +// Network Configuration + +// 100Mbps Speed +// Set to one to indicate 100 Mbps operation, zero for 10 Mbps. +// gmac_arch_ncfgr_spd +#ifndef CONF_GMAC_NCFGR_SPD +#define CONF_GMAC_NCFGR_SPD 1 +#endif + +// Enable Full Duplex +// Enable Full duplex +// gmac_arch_ncfgr_df +#ifndef CONF_GMAC_NCFGR_FD +#define CONF_GMAC_NCFGR_FD 1 +#endif + +// Discard Non-VLAN Frames +// Discard Non-VLAN Frames +// gmac_arch_ncfgr_dnvlan +#ifndef CONF_GMAC_NCFGR_DNVLAN +#define CONF_GMAC_NCFGR_DNVLAN 0 +#endif + +// Enable Jumbo Frame +// Enable jumbo frames up to 10240 bytes to be accepted. +// gmac_arch_ncfgr_jframe +#ifndef CONF_GMAC_NCFGR_JFRAME +#define CONF_GMAC_NCFGR_JFRAME 0 +#endif + +// Copy All Frames +// All valid frames will be accepted +// gmac_arch_ncfgr_caf +#ifndef CONF_GMAC_NCFGR_CAF +#define CONF_GMAC_NCFGR_CAF 0 +#endif + +// No broadcast +// Frames addressed to the broadcast address of all ones will not be accepted. +// gmac_arch_ncfgr_nbc +#ifndef CONF_GMAC_NCFGR_NBC +#define CONF_GMAC_NCFGR_NBC 0 +#endif + +// Multicast Hash Enable +// Multicast frames will be accepted when the 6-bit hash function of the destination address points to a bit that is set in the Hash Register. +// gmac_arch_ncfgr_mtihen +#ifndef CONF_GMAC_NCFGR_MTIHEN +#define CONF_GMAC_NCFGR_MTIHEN 0 +#endif + +// Unicast Hash Enable +// Unicast frames will be accepted when the 6-bit hash function of the destination address points to a bit that is set in the Hash Register. +// gmac_arch_ncfgr_unihen +#ifndef CONF_GMAC_NCFGR_UNIHEN +#define CONF_GMAC_NCFGR_UNIHEN 0 +#endif + +// 1536 Maximum Frame Size +// Accept frames up to 1536 bytes in length. +// gmac_arch_ncfgr_maxfs +#ifndef CONF_GMAC_NCFGR_MAXFS +#define CONF_GMAC_NCFGR_MAXFS 1 +#endif + +// Retry Test +// Must be set to zero for normal operation. If set to one the backoff +// between collisions will always be one slot time. Setting this bit to +// one helps test the too many retries condition. Also used in the pause +// frame tests to reduce the pause counter's decrement time from 512 bit +// times, to every GRXCK cycle. +// gmac_arch_ncfgr_rty +#ifndef CONF_GMAC_NCFGR_RTY +#define CONF_GMAC_NCFGR_RTY 0 +#endif + +// Pause Enable +// When set, transmission will pause if a non-zero 802.3 classic pause +// frame is received and PFC has not been negotiated +// gmac_arch_ncfgr_pen +#ifndef CONF_GMAC_NCFGR_PEN +#define CONF_GMAC_NCFGR_PEN 0 +#endif + +// Receive Buffer Offset <0-3> +// Indicates the number of bytes by which the received data is offset from +// the start of the receive buffer. +// gmac_arch_ncfgr_rxbufo +#ifndef CONF_GMAC_NCFGR_RXBUFO +#define CONF_GMAC_NCFGR_RXBUFO 0 +#endif + +// Length Field Error Frame Discard +// Setting this bit causes frames with a measured length shorter than the +// extracted length field (as indicated by bytes 13 and 14 in a non-VLAN +// tagged frame) to be discarded. This only applies to frames with a length +// field less than 0x0600. +// gmac_arch_ncfgr_lferd +#ifndef CONF_GMAC_NCFGR_LFERD +#define CONF_GMAC_NCFGR_LFERD 0 +#endif + +// Remove FCS +// Setting this bit will cause received frames to be written to memory +// without their frame check sequence (last 4 bytes). The frame length +// indicated will be reduced by four bytes in this mode. +// gmac_arch_ncfgr_rfcs +#ifndef CONF_GMAC_NCFGR_RFCS +#define CONF_GMAC_NCFGR_RFCS 0 +#endif + +// MDC Clock Division +// Set according to MCK speed. These three bits determine the number MCK +// will be divided by to generate Management Data Clock (MDC). For +// conformance with the 802.3 specification, MDC must not exceed 2.5 MHz +// (MDC is only active during MDIO read and write operations). +// <0=> 8 +// <1=> 16 +// <2=> 32 +// <3=> 48 +// <4=> 64 +// <5=> 96 +// gmac_arch_ncfgr_clk +#ifndef CONF_GMAC_NCFGR_CLK +#define CONF_GMAC_NCFGR_CLK 4 +#endif + +/** + * For conformance with the 802.3 specification, MDC must not exceed 2.5 MHz + **/ +#ifndef CONF_GMAC_MCK_FREQUENCY +#if CONF_GMAC_NCFGR_CLK == 0 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 8) +#elif CONF_GMAC_NCFGR_CLK == 1 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 16) +#elif CONF_GMAC_NCFGR_CLK == 2 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 32) +#elif CONF_GMAC_NCFGR_CLK == 3 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 48) +#elif CONF_GMAC_NCFGR_CLK == 4 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 64) +#elif CONF_GMAC_NCFGR_CLK == 5 +#define CONF_GMAC_MCK_FREQUENCY (CONF_GMAC_FREQUENCY / 96) +#endif +#endif + +#if CONF_GMAC_MCK_FREQUENCY > 2500000 +#warning For conformance with the 802.3 specification, MDC must not exceed 2.5 MHz +#endif +// Disable Copy of Pause Frames +// Set to one to prevent valid pause frames being copied to memory. When +// set, pause frames are not copied to memory regardless of the state of +// the Copy All Frames bit, whether a hash match is found or whether a +// type ID match is identified. If a destination address match is found, +// the pause frame will be copied to memory. Note that valid pause frames +// received will still increment pause statistics and pause the +// transmission of frames as required. +// gmac_arch_ncfgr_dcpf +#ifndef CONF_GMAC_NCFGR_DCPF +#define CONF_GMAC_NCFGR_DCPF 0 +#endif + +// Receive Checksum Offload Enable +// When set, the receive checksum engine is enabled. Frames with bad IP, +// TCP or UDP checksums are discarded. +// gmac_arch_ncfgr_rxcoen +#ifndef CONF_GMAC_NCFGR_RXCOEN +#define CONF_GMAC_NCFGR_RXCOEN 0 +#endif + +// Enable Frames Received in Half Duplex +// Enable frames to be received in half-duplex mode while transmittinga. +// gmac_arch_ncfgr_efrhd +#ifndef CONF_GMAC_NCFGR_EFRHD +#define CONF_GMAC_NCFGR_EFRHD 0 +#endif + +// Ignore RX FCS +// When set, frames with FCS/CRC errors will not be rejected. FCS error +// statistics will still be collected for frames with bad FCS and FCS +// status will be recorded in frame's DMA descriptor. For normal operation +// this bit must be set to zero. +// gmac_arch_ncfgr_irxfcs +#ifndef CONF_GMAC_NCFGR_IRXFCS +#define CONF_GMAC_NCFGR_IRXFCS 0 +#endif + +// IP Stretch Enable +// When set, the transmit IPG can be increased above 96 bit times depending +// on the previous frame length using the IPG Stretch Register. +// gmac_arch_ncfgr_ipgsen +#ifndef CONF_GMAC_NCFGR_IPGSEN +#define CONF_GMAC_NCFGR_IPGSEN 0 +#endif + +// Receive Bad Preamble +// When set, frames with non-standard preamble are not rejected. +// gmac_arch_ncfgr_rxbp +#ifndef CONF_GMAC_NCFGR_RXBP +#define CONF_GMAC_NCFGR_RXBP 0 +#endif + +// Ignore IPG GRXER +// When set, GRXER has no effect on the GMAC's operation when GRXDV is low. +// gmac_arch_ncfgr_irxer +#ifndef CONF_GMAC_NCFGR_IRXER +#define CONF_GMAC_NCFGR_IRXER 0 +#endif + +// + +// MII Configuration +// gmac_arch_mii_cfg +#ifndef CONF_GMAC_MII_CFG +#define CONF_GMAC_MII_CFG 1 +#endif + +// MII Mode +// Select MII or RMII mode +// <0=> RMII +// <1=> MII +// gmac_arch_ur_rmii +#ifndef CONF_GMAC_UR_RMII +#define CONF_GMAC_UR_RMII 0 +#endif + +// PHY Clause Operation +// Chose which Clause operation will be used +// <0=>Clause 45 Operation +// <1=>Clause 22 Operation +// gmac_arch_cltto +#ifndef CONF_GMAC_CLTTO +#define CONF_GMAC_CLTTO 1 +#endif + +// + +// Stacked VLAN Processing +// When enabled, the first VLAN tag in a received frame will only be +// accepted if the VLAN type field is equal to the User defined VLAN Type, +// OR equal to the standard VLAN type (0x8100). Note that the second VLAN +// tag of a Stacked VLAN packet will only be matched correctly if its +// VLAN_TYPE field equals 0x8100. +// gmac_arch_svlan_enable +#ifndef CONF_GMAC_SVLAN_ENABLE +#define CONF_GMAC_SVLAN_ENABLE 1 +#endif + +// User Defined VLAN Type <0x0-0xFFFF> +// User defined VLAN TYPE +// gmac_arch_svlan_type +#ifndef CONF_GMAC_SVLAN_TYPE +#define CONF_GMAC_SVLAN_TYPE 0x8100 +#endif +// + +// DMA Configuration +// The GMAC DMA controller is connected to the MAC FIFO interface and +// provides a scatter-gather type capability for packet data storage. +// The DMA implements packet buffering where dual-port memories are used +// to buffer multiple frames. +// gmac_arch_dma_cfg +#ifndef CONF_GMAC_DMA_CFG +#define CONF_GMAC_DMA_CFG 1 +#endif + +// Fixed Burst Length for DMA Data Operations +// Selects the burst length to attempt to use on the AHB when transferring +// frame data. Not used for DMA management operations and only used where +// space and data size allow. Otherwise SINGLE type AHB transfers are used. +// <1=> Always use SINGLE AHB bursts +// <4=> Always use INCR4 AHB bursts +// <8=> Always use INCR8 AHB bursts +// <16=> Always use INCR16 AHB bursts +// gmac_arch_dcfgr_fbldo +#ifndef CONF_GMAC_DCFGR_FBLDO +#define CONF_GMAC_DCFGR_FBLDO 4 +#endif + +// Endian Swap Mode Enable for Management Descriptor Accesses +// When set, selects swapped endianism for AHB transfers. When clear, +// selects little endian mode. +// gmac_arch_dcfgr_esma +#ifndef CONF_GMAC_DCFGR_ESMA +#define CONF_GMAC_DCFGR_ESMA 0 +#endif + +// Endian Swap Mode Enable for Packet Data Accesses +// When set, selects swapped endianism for AHB transfers. When clear, +// selects little endian mode. +// gmac_arch_dcfgr_espa +#ifndef CONF_GMAC_DCFGR_ESPA +#define CONF_GMAC_DCFGR_ESPA 0 +#endif + +// Receiver Packet Buffer Memory Size Select +// Select the receive packet buffer size +// <0=> 0.5 Kbytes +// <1=> 1 Kbytes +// <2=> 2 Kbytes +// <3=> 4 Kbytes +// gmac_arch_dcfgr_rxbms +#ifndef CONF_GMAC_DCFGR_RXBMS +#define CONF_GMAC_DCFGR_RXBMS 3 +#endif + +// Transmitter Packet Buffer Memory Size Select +// Select the Transmitter packet buffer size +// <0=> 2 Kbytes +// <1=> 4 Kbytes +// gmac_arch_dcfgr_txpbms +#ifndef CONF_GMAC_DCFGR_TXPBMS +#define CONF_GMAC_DCFGR_TXPBMS 1 +#endif + +// Transmitter Checksum Generation Offload Enable +// Transmitter IP, TCP and UDP checksum generation offload enable. When +// set, the transmitter checksum generation engine is enabled to calculate +// and substitute checksums for transmit frames. When clear, frame data is +// unaffected +// gmac_arch_dcfgr_txcoen +#ifndef CONF_GMAC_DCFGR_TXCOEN +#define CONF_GMAC_DCFGR_TXCOEN 1 +#endif + +// DMA Receive Buffer Size <1-255> +// DMA receive buffer size in AHB system memory. The value defined by these +// bits determines the size of buffer to use in main AHB system memory when +// writing received data. The value is defined in multiples of 64 bytes, +// thus a value of 0x01 corresponds to buffers of 64 bytes, 0x02 +// corresponds to 128 bytes etc. +// gmac_arch_dcfgr_drbs +#ifndef CONF_GMAC_DCFGR_DRBS +#define CONF_GMAC_DCFGR_DRBS 8 +#endif + +// DMA Discard Received Packets +// When set, the GMAC DMA will automatically discard receive packets from +// the receiver packet buffer memory when no AHB resource is available. +// When low, the received packets will remain to be stored in the SRAM +// based packet buffer until AHB buffer resource next becomes available. +// Note: packet buffer full store and forward mode should be enabled. +// gmac_arch_dcfgr_ddrp +#ifndef CONF_GMAC_DCFGR_DDRP +#define CONF_GMAC_DCFGR_DDRP 0 +#endif +// + +// Advanced configuration +// gmac_arch_adv_cfg +#ifndef CONF_GMAC_ADV_CFG +#define CONF_GMAC_ADV_CFG 1 +#endif + +// Number of Transmit Buffer Descriptor <1-255> +// Number of Transmit Buffer Descriptor +// gmac_arch_txdescr_num +#ifndef CONF_GMAC_TXDESCR_NUM +#define CONF_GMAC_TXDESCR_NUM 8 +#endif + +// Number of Receive Buffer Descriptor <1-255> +// Number of Receive Buffer Descriptor +// gmac_arch_rxdescr_num +#ifndef CONF_GMAC_RXDESCR_NUM +#define CONF_GMAC_RXDESCR_NUM 16 +#endif + +// Byte size of Transmit Buffer <64-10240> +// Byte size of buffer for each transmit buffer descriptor. +// gmac_arch_txbuf_size +#ifndef CONF_GMAC_TXBUF_SIZE +#define CONF_GMAC_TXBUF_SIZE 1500 +#endif + +/* + * Receive buffer size is defined by DMA Configuration Register GMAC_DCFGR, + * DRBS: DMA Receive Buffer Size.The value is defined in multiples of 64 bytes, + * thus CONF_GMAC_DCFGR_DRBS = 0x01 corresponds to buffers of 64 bytes, + * 0x02 corresponds to 128 bytes etc. + */ +#ifndef CONF_GMAC_RXBUF_SIZE +#define CONF_GMAC_RXBUF_SIZE (CONF_GMAC_DCFGR_DRBS * 64) +#endif + +// Enable Transmit Partial Store and Forward +// This allows for a reduced latency but there are performance implications. +// gmac_arch_tpsf_en +#ifndef CONF_GMAC_TPSF_EN +#define CONF_GMAC_TPSF_EN 0 +#endif + +// Watermark <20-4095> +// Byte size of buffer for each transmit buffer descriptor. +// gmac_arch_tpsf_wm +#ifndef CONF_GMAC_TPSF_WM +#define CONF_GMAC_TPSF_WM 100 +#endif +// + +// Enable Receive Partial Store and Forward +// This allows for a reduced latency but there are performance implications. +// gmac_arch_rpsf_en +#ifndef CONF_GMAC_RPSF_EN +#define CONF_GMAC_RPSF_EN 0 +#endif + +// Watermark <20-4095> +// Byte size of buffer for each transmite buffer descriptor. +// gmac_arch_rpsf_wm +#ifndef CONF_GMAC_RPSF_WM +#define CONF_GMAC_RPSF_WM 100 +#endif + +// IPG Stretch Multiple <0-15> +// This value will multiplied with the previously transmitted frame length +// (including preamble) +// gmac_arch_ipgs_fl_mul +#ifndef CONF_GMAC_IPGS_FL_MUL +#define CONF_GMAC_IPGS_FL_MUL 1 +#endif + +// IPG Stretch Divide <1-16> +// Divide the frame length. If the resulting number is greater than 96 and +// IP Stretch Enabled then the resulting number is used for the transmit +// inter-packet-gap +// gmac_arch_ipgs_fl_div +#ifndef CONF_GMAC_IPGS_FL_DIV +#define CONF_GMAC_IPGS_FL_DIV 1 +#endif + +// + +// + +// <<< end of configuration section >>> + +#endif // HPL_GMAC_CONFIG_H diff --git a/bsp/microchip/same70/bsp/config/hpl_systick_ARMv7_config.h b/bsp/microchip/same70/bsp/config/hpl_systick_ARMv7_config.h deleted file mode 100644 index 48108a7fe9..0000000000 --- a/bsp/microchip/same70/bsp/config/hpl_systick_ARMv7_config.h +++ /dev/null @@ -1,18 +0,0 @@ -/* Auto-generated config file hpl_systick_ARMv7_config.h */ -#ifndef HPL_SYSTICK_ARMV7_CONFIG_H -#define HPL_SYSTICK_ARMV7_CONFIG_H - -// <<< Use Configuration Wizard in Context Menu >>> - -// Advanced settings -// SysTick exception request -// Indicates whether the generation of SysTick exception is enabled or not -// systick_arch_tickint -#ifndef CONF_SYSTICK_TICKINT -#define CONF_SYSTICK_TICKINT 0 -#endif -// - -// <<< end of configuration section >>> - -#endif // HPL_SYSTICK_ARMV7_CONFIG_H diff --git a/bsp/microchip/same70/bsp/config/hpl_twihs_config.h b/bsp/microchip/same70/bsp/config/hpl_twihs_config.h new file mode 100644 index 0000000000..694cdf9eb2 --- /dev/null +++ b/bsp/microchip/same70/bsp/config/hpl_twihs_config.h @@ -0,0 +1,213 @@ +/* Auto-generated config file hpl_twihs_config.h */ +#ifndef HPL_TWIHS_CONFIG_H +#define HPL_TWIHS_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +#include + +/* TWI0 peripheral clock frequency */ +#ifndef CONF_TWIHS0_FREQUENCY +#define CONF_TWIHS0_FREQUENCY (CONF_TWIHS0_FREQUENCY) +#endif + +// Standard configuration + +// I2C Bus clock speed (Hz) <1-400000> +// I2C Bus clock (SCL) speed measured in Hz +// i2c_master_baud_rate +#ifndef CONF_TWIHS0_BAUD +#define CONF_TWIHS0_BAUD 100000 +#endif + +// + +// Advanced configuration +// i2c_master_advanced +#ifndef CONF_TWIHS0_ADVANCED_CONFIG +#define CONF_TWIHS0_ADVANCED_CONFIG 1 +#endif + +// SMBus Mode Enabled +// Determine if the SMBus mode enabled +// i2c_master_smbus_enable +#ifndef CONF_TWIHS0_SMBEN +#define CONF_TWIHS0_SMBEN 0 +#endif + +// Packet Error Checking +// SMBus PEC (CRC) generation and check enabled +// i2c_master_packet_error_check +#ifndef CONF_TWIHS0_PECEN +#define CONF_TWIHS0_PECEN 0 +#endif + +// SMBus Clock Prescaler +// <0=> Divide by 2 +// <1=> Divide by 4 +// <2=> Divide by 8 +// <3=> Divide by 16 +// <4=> Divide by 32 +// <5=> Divide by 64 +// <6=> Divide by 128 +// <7=> Divide by 256 +// <8=> Divide by 512 +// <9=> Divide by 1024 +// <10=> Divide by 2048 +// <11=> Divide by 4096 +// <12=> Divide by 8192 +// <13=> Divide by 16384 +// <14=> Divide by 32768 +// <15=> Divide by 65536 +// Used to specify how to prescale the TLOWS, TLOWM and THMAX counters in SMBTR +// i2c_master_smbus_clock_prescaler +#ifndef CONF_TWIHS0_SMBTR_PRESC +#define CONF_TWIHS0_SMBTR_PRESC 0 +#endif + +// Master Clock Stretch Maximum Cycles <0-255> +// Clock cycles in master maximum clock stretch count. Prescaled by PRESC. +// Used to time TLOW:MEXT. If 0, timeout check disabled. +// i2c_master_tlow_mext +#ifndef CONF_TWIHS0_SMBTR_TLOWM +#define CONF_TWIHS0_SMBTR_TLOWM 0 +#endif + +// Slave Clock Stretch Maximum Cycles <0-255> +// Clock cycles in slave maximum clock stretch count. Prescaled by PRESC. +// Used to time TLOW:SEXT. If 0, timeout check disabled. +// i2c_master_tlow_sext +#ifndef CONF_TWIHS0_SMBTR_TLOWS +#define CONF_TWIHS0_SMBTR_TLOWS 0 +#endif + +// Clock High Maximum Cycles <0-255> +// Clock cycles in clock high maximum count. Prescaled by PRESC. Used for +// bus free detection. Used to time THIGH:MAX. +// i2c_master_thigh_max +#ifndef CONF_TWIHS0_SMBTR_THMAX +#define CONF_TWIHS0_SMBTR_THMAX 0 +#endif + +// RX Digital Filter Enable +// TWIHS input filtering is active (only in Standard and Fast modes) +// i2c_master_digital_filter_enable +#ifndef CONF_TWIHS0_FILTR_FILT +#define CONF_TWIHS0_FILTR_FILT 1 +#endif + +// PAD Filter Enable +// PAD analog filter is enabled (The analog filter must be enabled if High-speed mode is enabled) +// i2c_master_pad_filter_enable +#ifndef CONF_TWIHS0_FILTR_PADFEN +#define CONF_TWIHS0_FILTR_PADFEN 1 +#endif + +// Digital Filter Threshold +// <0=> Disabled +// <1=> 1 +// <2=> 2 +// <3=> 3 +// <4=> 4 +// <5=> 5 +// <6=> 6 +// <6=> 7 +// Maximum pulse width of spikes to be suppressed by the input filter, defined in peripheral clock cycles. +// i2c_master_filter_threshold +#ifndef CONF_TWIHS0_FILTR_THRES +#define CONF_TWIHS0_FILTR_THRES 2 +#endif + +// + +/* Configuration for CR (Control Register) */ +#ifndef CONF_TWIHS0_CR_REG +#define CONF_TWIHS0_CR_REG \ + (TWIHS_CR_SVDIS | (CONF_TWIHS0_SMBEN << TWIHS_CR_SMBEN_Pos) | (CONF_TWIHS0_PECEN << TWIHS_CR_PECEN_Pos)) +#endif + +/* Configuration for SMBTR(TWI SMBus Timing Register Register) */ +#ifndef CONF_TWIHS0_SMBTR_REG +#define CONF_TWIHS0_SMBTR_REG \ + ((CONF_TWIHS0_SMBTR_PRESC << TWIHS_SMBTR_PRESC_Pos) | (CONF_TWIHS0_SMBTR_TLOWM << TWIHS_SMBTR_TLOWM_Pos) \ + | (CONF_TWIHS0_SMBTR_TLOWS << TWIHS_SMBTR_TLOWS_Pos) | (CONF_TWIHS0_SMBTR_THMAX << TWIHS_SMBTR_THMAX_Pos)) +#endif + +/* Configuration for FILTR(TWI Filter Register Register) */ +#ifndef CONF_TWIHS0_FILTR_REG +#define CONF_TWIHS0_FILTR_REG \ + ((CONF_TWIHS0_FILTR_FILT << TWIHS_FILTR_FILT_Pos) | (CONF_TWIHS0_FILTR_PADFEN << TWIHS_FILTR_PADFEN_Pos) \ + | (CONF_TWIHS0_FILTR_THRES << TWIHS_FILTR_THRES_Pos)) +#endif + +/* The peripheral clock is the source clock for the bit rate generation when + * CONF_TWIHS0_CWGR_BRSRCCLK == 0 + * 1 (CLDIV * CKDIV_val + 3) + * Tlow = --------------- = ------------------------------ + * baudrate * 2 PeripheralFrequency(HZ) + */ +#define CONF_TWIHS0_CWGR_CLDIV_CALC(freq, baud, ckdiv) (((freq / (baud * 2)) - 3) / ckdiv) + +/* Find a valid CWGR_CKDIV value and Check if the CONF_TWIHS0_CKDIV will overflow */ +#ifndef CONF_TWIHS0_CWGR_CKDIV +#if CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 1) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 0 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 2) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 1 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 4) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 2 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 8) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 3 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 16) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 4 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 32) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 5 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 64) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 6 +#elif CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, 128) <= 255 +#define CONF_TWIHS0_CWGR_CKDIV 7 +#else +#error Failed to generate TWI0 I2C baudrate, please check settings. +#endif +#endif /* end ifndef CONF_TWIHS0_CWGR_CKDIV */ + +/* TWIHS_CWGR_CKDIV Result value for calc CWGR_CLDIV and CWGR_CHDIV */ +#if CONF_TWIHS0_CWGR_CKDIV == 0 +#define CONF_TWIHS0_CWGR_CKDIV_val 1 +#elif CONF_TWIHS0_CWGR_CKDIV == 1 +#define CONF_TWIHS0_CWGR_CKDIV_val 2 +#elif CONF_TWIHS0_CWGR_CKDIV == 2 +#define CONF_TWIHS0_CWGR_CKDIV_val 4 +#elif CONF_TWIHS0_CWGR_CKDIV == 3 +#define CONF_TWIHS0_CWGR_CKDIV_val 8 +#elif CONF_TWIHS0_CWGR_CKDIV == 4 +#define CONF_TWIHS0_CWGR_CKDIV_val 16 +#elif CONF_TWIHS0_CWGR_CKDIV == 5 +#define CONF_TWIHS0_CWGR_CKDIV_val 32 +#elif CONF_TWIHS0_CWGR_CKDIV == 6 +#define CONF_TWIHS0_CWGR_CKDIV_val 64 +#elif CONF_TWIHS0_CWGR_CKDIV == 7 +#define CONF_TWIHS0_CWGR_CKDIV_val 128 +#endif + +/* Clock Waveform Generator Register Clock Divider */ +#ifndef CONF_TWIHS0_CWGR_CLDIV +#define CONF_TWIHS0_CWGR_CLDIV \ + (CONF_TWIHS0_CWGR_CLDIV_CALC(CONF_TWIHS0_FREQUENCY, CONF_TWIHS0_BAUD, CONF_TWIHS0_CWGR_CKDIV_val)) +#endif + +/* CHDIV same as CLDIV for generator a 50 duty cycle clock */ +#ifndef CONF_TWIHS0_CWGR_CHDIV +#define CONF_TWIHS0_CWGR_CHDIV CONF_TWIHS0_CWGR_CLDIV +#endif /* endif CONF_TWIHS0_CWGR_BRSRCCLK == 1 */ + +/* Configuration for CWGR(TWI Clock Waveform Generator Register) */ +#ifndef CONF_TWIHS0_CWGR_REG +#define CONF_TWIHS0_CWGR_REG \ + (TWIHS_CWGR_CKDIV(CONF_TWIHS0_CWGR_CKDIV) | TWIHS_CWGR_CHDIV(CONF_TWIHS0_CWGR_CHDIV) \ + | TWIHS_CWGR_CLDIV(CONF_TWIHS0_CWGR_CLDIV)) +#endif + +// <<< end of configuration section >>> + +#endif // HPL_TWIHS_CONFIG_H diff --git a/bsp/microchip/same70/bsp/config/ieee8023_mii_standard_config.h b/bsp/microchip/same70/bsp/config/ieee8023_mii_standard_config.h new file mode 100644 index 0000000000..e60cd8a250 --- /dev/null +++ b/bsp/microchip/same70/bsp/config/ieee8023_mii_standard_config.h @@ -0,0 +1,106 @@ +/* Auto-generated config file ieee8023_mii_standard_config.h */ +#ifndef IEEE8023_MII_STANDARD_CONFIG_H +#define IEEE8023_MII_STANDARD_CONFIG_H + +// <<< Use Configuration Wizard in Context Menu >>> + +// Basic configuration + +// PHY Address <0-31> +// The PHY Address is five bits, allowing 32 unique PHY addresses. A PHY +// that is connected to the station management entity via the mechanical +// interface defined in IEEE 802.3 22.6 shall always respond to +// transactions addressed to PHY Address zero b00000. A station management +// entity that is attached to multiple PHYs must have prior knowledge of +// the appropriate PHY Address for each PHY. +// ieee8023_mii_phy_address +#ifndef CONF_MACIF_PHY_IEEE8023_MII_PHY_ADDRESS +#define CONF_MACIF_PHY_IEEE8023_MII_PHY_ADDRESS 0 +#endif + +// + +// Control Register (Register 0) Settings +// The MII Management Interface Control Register (Register 0) Setting. +// Full details about the can be found in Clause 22.2.4 of the IEEE 802.3 +// Specification. +// ieee8023_mii_control_reg0_setting +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING 1 +#endif + +// Loopback Enable +// Set PHY be placed in a loopback mode of operation. +// ieee8023_mii_control_loopback_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_LOOPBACK_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_LOOPBACK_EN 0 +#endif + +// Speed Selection +// These bits select the PHY speed. +// <0x0=> 10 Mb/s +// <0x1=> 100 Mb/s +// <0x2=> 1000 Mb/s +// ieee8023_mii_control_speed_lsb +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED 1 +#endif + +// Auto-Negotiation Enable +// Indicates whether the Auto-Negotiation enable or not +// ieee8023_mii_control_autoneg_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_AUTONEG_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_AUTONEG_EN 1 +#endif + +// Power Down Enable +// Set PHY in a low-power consumption state, The specific behavior of a +// PHY in the power-down state is implementation specific. While in the +// power-down state, the PHY shall respond to management transactions. +// During the transition to the power-down state and while in the +// power-down state, the PHY shall not generate spurious signals on the +// MII or GMII. +// ieee8023_mii_control_powerdown_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_POWER_DOWN_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_POWER_DOWN_EN 0 +#endif + +// Isolate Enable +// Set PHY forced to electrically isolate its data paths from the MII or +// GMII. When the PHY is isolated from the MII or GMII it shall not +// respond to the TXD data bundle, TX_EN, TX_ER and GTX_CLK inputs, and it +// shall present a high impedance on its TX_CLK, RX_CLK, RX_DV, RX_ER, RXD +// data bundle, COL, and CRS outputs. When the PHY is isolated from the +// MII or GMII it shall respond to management transactions. +// ieee8023_mii_control_isolate_en +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_ISOLATE_EN +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_ISOLATE_EN 0 +#endif + +// Duplex Mode Selection +// The duplex mode can be selected via either the Auto-Negotiation enable, +// or manual duplex selection. Manual duplex selection is allowed when +// Auto-Negotiation is disabled. When Auto-Negotiation is enabled, this +// setting has no effect on the link configuration. +// <0x0=> half duplex +// <0x1=> full duplex +// ieee8023_mii_control_duplex_mode +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_DUPLEX_MODE +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_DUPLEX_MODE 1 +#endif + +#ifndef CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0 +#define CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0 \ + (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_LOOPBACK_EN ? MDIO_REG0_BIT_RESET : 0) \ + | ((CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED & 0x1) ? MDIO_REG0_BIT_SPEED_SELECT_LSB : 0) \ + | ((CONF_MACIF_PHY_IEEE8023_MII_CONTROL_SPEED & 0x2) ? MDIO_REG0_BIT_SPEED_SELECT_MSB : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_AUTONEG_EN ? MDIO_REG0_BIT_AUTONEG : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_POWER_DOWN_EN ? MDIO_REG0_BIT_POWER_DOWN : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_ISOLATE_EN ? MDIO_REG0_BIT_ISOLATE : 0) \ + | (CONF_MACIF_PHY_IEEE8023_MII_CONTROL_DUPLEX_MODE ? MDIO_REG0_BIT_DUPLEX_MODE : 0) +#endif +// + +// <<< end of configuration section >>> + +#endif // IEEE8023_MII_STANDARD_CONFIG_H diff --git a/bsp/microchip/same70/bsp/config/peripheral_clk_config.h b/bsp/microchip/same70/bsp/config/peripheral_clk_config.h index ee87cce4a9..e7632940bd 100644 --- a/bsp/microchip/same70/bsp/config/peripheral_clk_config.h +++ b/bsp/microchip/same70/bsp/config/peripheral_clk_config.h @@ -4,6 +4,24 @@ // <<< Use Configuration Wizard in Context Menu >>> +// AFEC Clock Settings +// AFEC Clock source +// Master Clock (MCK) +// This defines the clock source for the AFEC +// afec_clock_source +#ifndef CONF_AFEC0_SRC +#define CONF_AFEC0_SRC CONF_SRC_MCK +#endif +// + +/** + * \def AFEC FREQUENCY + * \brief AFEC's Clock frequency + */ +#ifndef CONF_AFEC0_FREQUENCY +#define CONF_AFEC0_FREQUENCY 150000000 +#endif + /** * \def CONF_HCLK_FREQUENCY * \brief HCLK's Clock frequency @@ -46,6 +64,24 @@ */ #define CONF_PCK6_FREQUENCY 1714285 +// TWIHS Clock Settings +// TWIHS Clock source +// Master Clock (MCK) +// This defines the clock source for the TWIHS +// twihs_clock_source +#ifndef CONF_TWIHS0_SRC +#define CONF_TWIHS0_SRC CONF_SRC_MCK +#endif +// + +/** + * \def TWIHS FREQUENCY + * \brief TWIHS's Clock frequency + */ +#ifndef CONF_TWIHS0_FREQUENCY +#define CONF_TWIHS0_FREQUENCY 150000000 +#endif + // USART Clock Settings // USART Clock source @@ -76,6 +112,24 @@ #define CONF_USART1_FREQUENCY 150000000 #endif +// GMAC Clock Settings +// GMAC Clock source +// Master Clock (MCK) +// Select the clock source for GMAC +// gmac_clock_source +#ifndef CONF_GMAC_SRC +#define CONF_GMAC_SRC CONF_SRC_MCK +#endif +// + +/** + * \def GMAC FREQUENCY + * \brief GMAC Clock frequency + */ +#ifndef CONF_GMAC_FREQUENCY +#define CONF_GMAC_FREQUENCY 150000000 +#endif + // MCAN Clock Settings // MCAN Clock source // Programmable Clock Controller 5 (PMC_PCK5) diff --git a/bsp/microchip/same70/bsp/documentation/ethernet_phy.rst b/bsp/microchip/same70/bsp/documentation/ethernet_phy.rst new file mode 100644 index 0000000000..b8bfcf20fa --- /dev/null +++ b/bsp/microchip/same70/bsp/documentation/ethernet_phy.rst @@ -0,0 +1,56 @@ +====================================== +Generic IEEE 802.3 Ethernet PHY Driver +====================================== + +This software component supply a generic IEEE802.3 Ethernet PHY driver. +The PHY chip should be compliant IEEE 802.3 Ethernet Standard that +supports MDC/MDIO management interface for PHY register configuration. + +The management interface specified here provides a simple, two-wire, serial +interface to connect a management entity and a managed PHY for the purposes of +controlling the PHY and gathering status from the PHY. This interface is +referred to as the MII Management Interface. + +The management interface consists of a pair of signals that physically +transport the management information across the MII or GMII, a frame format +and a protocol specification for exchanging management frames, and a register +set that can be read and written using these frames. The register definition +specifies a basic register set with an extension mechanism. The MII uses two +basic registers. The GMII also uses the same two basic registers and adds a +third basic register. + +The MII basic register set consists of two registers referred to as the Control +register (Register 0) and the Status register (Register 1). All PHYs that +provide an MII shall incorporate the basic register set. All PHYs that provide +a GMII shall incorporate an extended basic register set consisting of the +Control register (Register 0), Status register (Register 1), and Extended +Status register (Register 15). The status and control functions defined here +are considered basic and fundamental to 100 Mb/s and 1000 Mb/s PHYs. +Registers 2 through 14 are part of the extended register set. The format of +Registers 4 through 10 are defined for the specific Auto-Negotiation protocol +used (Clause 28 or Clause 37). The format of these registers is selected by +the bit settings of Registers 1 and 15. +More information please refer to IEEE Std 802.3 Chapter 22.2.4 + +Features +-------- + +* Initialization the Ethernet PHY driver with Ethernet MAC communication +* Setting PHY address +* Reading/Writing register from PHY device +* Setting/Clearing register bit from PHY device +* Enabling/Disabling Power Down +* Restart Auto Negotiation +* Enabling/Disabling Loop Back +* Getting Link Status +* Reset PHY device + +Dependencies +------------ + +* An instance of the Ethernet MAC driver is used by this driver. + +Limitations +----------- + +N/A diff --git a/bsp/microchip/same70/bsp/driver_init.c b/bsp/microchip/same70/bsp/driver_init.c index 98cb54d45f..7ca57da71e 100644 --- a/bsp/microchip/same70/bsp/driver_init.c +++ b/bsp/microchip/same70/bsp/driver_init.c @@ -13,33 +13,130 @@ #include #include -struct can_async_descriptor CAN_0; +/*! The buffer size for USART */ +#define TARGET_IO_BUFFER_SIZE 16 -struct usart_sync_descriptor TARGET_IO; +struct usart_async_descriptor TARGET_IO; +struct can_async_descriptor CAN_0; -void delay_driver_init(void) +static uint8_t TARGET_IO_buffer[TARGET_IO_BUFFER_SIZE]; + +struct adc_sync_descriptor ADC_0; + +struct i2c_m_sync_desc I2C_0; + +struct mac_async_descriptor MACIF; + +void ADC_0_PORT_init(void) { - delay_init(SysTick); + + gpio_set_pin_function(PB0, GPIO_PIN_FUNCTION_OFF); } -void TARGET_IO_PORT_init(void) +void ADC_0_CLOCK_init(void) { - gpio_set_pin_function(PA21, MUX_PA21A_USART1_RXD1); + _pmc_enable_periph_clock(ID_AFEC0); +} - gpio_set_pin_function(PB4, MUX_PB4D_USART1_TXD1); +void ADC_0_init(void) +{ + ADC_0_CLOCK_init(); + ADC_0_PORT_init(); + adc_sync_init(&ADC_0, AFEC0, (void *)NULL); } -void TARGET_IO_CLOCK_init(void) +void I2C_0_PORT_init(void) +{ + + gpio_set_pin_function(PA4, MUX_PA4A_TWIHS0_TWCK0); + + gpio_set_pin_function(PA3, MUX_PA3A_TWIHS0_TWD0); +} + +void I2C_0_CLOCK_init(void) +{ + _pmc_enable_periph_clock(ID_TWIHS0); +} + +void I2C_0_init(void) +{ + I2C_0_CLOCK_init(); + + i2c_m_sync_init(&I2C_0, TWIHS0); + + I2C_0_PORT_init(); +} + +/** + * \brief USART Clock initialization function + * + * Enables register interface and peripheral clock + */ +void TARGET_IO_CLOCK_init() { _pmc_enable_periph_clock(ID_USART1); } +/** + * \brief USART pinmux initialization function + * + * Set each required pin to USART functionality + */ +void TARGET_IO_PORT_init() +{ + + gpio_set_pin_function(PA21, MUX_PA21A_USART1_RXD1); + + gpio_set_pin_function(PB4, MUX_PB4D_USART1_TXD1); +} + +/** + * \brief USART initialization function + * + * Enables USART peripheral, clocks and initializes USART driver + */ void TARGET_IO_init(void) { TARGET_IO_CLOCK_init(); TARGET_IO_PORT_init(); - usart_sync_init(&TARGET_IO, USART1, _usart_get_usart_sync()); + usart_async_init(&TARGET_IO, USART1, TARGET_IO_buffer, TARGET_IO_BUFFER_SIZE, _usart_get_usart_async()); +} + +void MACIF_PORT_init(void) +{ + + gpio_set_pin_function(PD8, MUX_PD8A_GMAC_GMDC); + + gpio_set_pin_function(PD9, MUX_PD9A_GMAC_GMDIO); + + gpio_set_pin_function(PD5, MUX_PD5A_GMAC_GRX0); + + gpio_set_pin_function(PD6, MUX_PD6A_GMAC_GRX1); + + gpio_set_pin_function(PD4, MUX_PD4A_GMAC_GRXDV); + + gpio_set_pin_function(PD7, MUX_PD7A_GMAC_GRXER); + + gpio_set_pin_function(PD2, MUX_PD2A_GMAC_GTX0); + + gpio_set_pin_function(PD3, MUX_PD3A_GMAC_GTX1); + + gpio_set_pin_function(PD0, MUX_PD0A_GMAC_GTXCK); + + gpio_set_pin_function(PD1, MUX_PD1A_GMAC_GTXEN); +} + +void MACIF_CLOCK_init(void) +{ + _pmc_enable_periph_clock(ID_GMAC); +} + +void MACIF_init(void) +{ + MACIF_CLOCK_init(); + mac_async_init(&MACIF, GMAC); + MACIF_PORT_init(); } /** @@ -116,9 +213,11 @@ void system_init(void) gpio_set_pin_function(LED0, GPIO_PIN_FUNCTION_OFF); - delay_driver_init(); + ADC_0_init(); + I2C_0_init(); TARGET_IO_init(); + MACIF_init(); CAN_0_init(); } diff --git a/bsp/microchip/same70/bsp/driver_init.h b/bsp/microchip/same70/bsp/driver_init.h index 06cb71eca9..470c7b4fff 100644 --- a/bsp/microchip/same70/bsp/driver_init.h +++ b/bsp/microchip/same70/bsp/driver_init.h @@ -21,21 +21,40 @@ extern "C" { #include #include -#include +#include -#include +#include +#include +#include #include -extern struct usart_sync_descriptor TARGET_IO; -extern struct can_async_descriptor CAN_0; +extern struct adc_sync_descriptor ADC_0; + +#define CONF_ADC_0_CHANNEL_10 10 + +extern struct i2c_m_sync_desc I2C_0; +extern struct usart_async_descriptor TARGET_IO; -void delay_driver_init(void); +extern struct mac_async_descriptor MACIF; +extern struct can_async_descriptor CAN_0; + +void ADC_0_PORT_init(void); +void ADC_0_CLOCK_init(void); +void ADC_0_init(void); + +void I2C_0_CLOCK_init(void); +void I2C_0_init(void); +void I2C_0_PORT_init(void); void TARGET_IO_PORT_init(void); void TARGET_IO_CLOCK_init(void); void TARGET_IO_init(void); +void MACIF_CLOCK_init(void); +void MACIF_init(void); +void MACIF_PORT_init(void); + void CAN_0_PORT_init(void); void CAN_0_CLOCK_init(void); void CAN_0_init(void); diff --git a/bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.c b/bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.c new file mode 100644 index 0000000000..a4f5caecc6 --- /dev/null +++ b/bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.c @@ -0,0 +1,184 @@ +/** + * \file + * + * \brief Ethernet PHY functionality implementation. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +/** + * \brief Perform a HW initialization to the PHY + */ +int32_t ethernet_phy_init(struct ethernet_phy_descriptor *const descr, struct mac_async_descriptor *const mac, + uint16_t addr) +{ + ASSERT(descr && mac && (addr <= 0x1F)); + + descr->mac = mac; + descr->addr = addr; + return ERR_NONE; +} + +/** + * \brief Set PHY address + */ +int32_t ethernet_phy_set_address(struct ethernet_phy_descriptor *const descr, uint16_t addr) +{ + ASSERT(descr && (addr <= 0x1F)); + + descr->addr = addr; + return ERR_NONE; +} + +/** + * \brief Read PHY Register value. + */ +int32_t ethernet_phy_read_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t *val) +{ + ASSERT(descr && descr->mac && (reg <= 0x1F) && val); + + return mac_async_read_phy_reg(descr->mac, descr->addr, reg, val); +} + +/** + * \brief Write PHY Register value. + */ +int32_t ethernet_phy_write_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t val) +{ + ASSERT(descr && descr->mac && (reg <= 0x1F)); + return mac_async_write_phy_reg(descr->mac, descr->addr, reg, val); +} + +/** + * \brief Setting bit for a PHY Register + */ +int32_t ethernet_phy_set_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst) +{ + int32_t rst; + uint16_t val; + + ASSERT(descr && descr->mac && (reg <= 0x1F)); + + rst = mac_async_read_phy_reg(descr->mac, descr->addr, reg, &val); + if (rst == ERR_NONE) { + val |= ofst; + rst = mac_async_write_phy_reg(descr->mac, descr->addr, reg, val); + } + return rst; +} +/** + * \brief Clear bit for a PHY Register + */ +int32_t ethernet_phy_clear_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst) +{ + int32_t rst; + uint16_t val; + + ASSERT(descr && (reg <= 0x1F)); + + rst = mac_async_read_phy_reg(descr->mac, descr->addr, reg, &val); + if (rst == ERR_NONE) { + val &= ~ofst; + rst = mac_async_write_phy_reg(descr->mac, descr->addr, reg, val); + } + return rst; +} +/** + * \brief Set PHY low-power consumption state. + */ +int32_t ethernet_phy_set_powerdown(struct ethernet_phy_descriptor *const descr, bool state) +{ + ASSERT(descr); + if (state) { + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_POWER_DOWN); + } else { + return ethernet_phy_clear_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_POWER_DOWN); + } +} + +/** + * \brief Set PHY electrically isolate state. + */ +int32_t ethernet_phy_set_isolate(struct ethernet_phy_descriptor *const descr, bool state) +{ + ASSERT(descr); + if (state) { + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_ISOLATE); + } else { + return ethernet_phy_clear_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_ISOLATE); + } +} + +/** + * \brief Restart an auto negotiation of the PHY. + */ +int32_t ethernet_phy_restart_autoneg(struct ethernet_phy_descriptor *const descr) +{ + ASSERT(descr); + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_RESTART_AUTONEG); +} + +/** + * \brief Set PHY placed in a loopback mode of operation. + */ +int32_t ethernet_phy_set_loopback(struct ethernet_phy_descriptor *const descr, bool state) +{ + ASSERT(descr); + if (state) { + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_LOOPBACK); + } else { + return ethernet_phy_clear_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_LOOPBACK); + } +} + +/** + * \brief Get PHY link status + */ +int32_t ethernet_phy_get_link_status(struct ethernet_phy_descriptor *const descr, bool *status) +{ + int32_t rst; + uint16_t val; + + ASSERT(descr && descr->mac && status); + rst = mac_async_read_phy_reg(descr->mac, descr->addr, MDIO_REG1_BMSR, &val); + if (rst == ERR_NONE) { + *status = (val & MDIO_REG1_BIT_LINK_STATUS) ? true : false; + } + return rst; +} + +/** + * \brief Reset PHY. + */ +int32_t ethernet_phy_reset(struct ethernet_phy_descriptor *const descr) +{ + ASSERT(descr); + return ethernet_phy_set_reg_bit(descr, MDIO_REG0_BMCR, MDIO_REG0_BIT_RESET); +} diff --git a/bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.h b/bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.h new file mode 100644 index 0000000000..65ad5afecc --- /dev/null +++ b/bsp/microchip/same70/bsp/ethernet_phy/ethernet_phy.h @@ -0,0 +1,230 @@ +/** + * \file + * + * \brief Ethernet PHY functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef ETHERNET_PHY_H_INCLUDED +#define ETHERNET_PHY_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "compiler.h" +#include "hal_mac_async.h" +#include "ieee8023_mii_standard_register.h" + +struct ethernet_phy_descriptor { + struct mac_async_descriptor *mac; /* MAC descriptor handler */ + uint16_t addr; /* PHY address, defined by IEEE802.3 + section 22.2.4.5.5 */ +}; + +/** + * \brief Perform a HW initialization to the PHY + * + * This should be called only once to initialize the PHY pre-settings. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] mac MAC descriptor, the descriptor should be initialized. + * \param[in] addr Ethernet PHY 5 bits address. + * + * \return Operation result + * \retval ERR_NONE initializing successful. + */ +int32_t ethernet_phy_init(struct ethernet_phy_descriptor *const descr, struct mac_async_descriptor *const mac, + uint16_t addr); + +/** + * \brief Set PHY address + * + * Set PHY management PHY address which defined by IEEE802.3 section 22.2.4.5.5 + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] addr PHY address + * + * \return Operation result + * \retval ERR_NONE Set address successful. + */ +int32_t ethernet_phy_set_address(struct ethernet_phy_descriptor *const descr, uint16_t addr); + +/** + * \brief Read PHY Register value. + * + * Read PHY Register value from PHY. + * + * \note For conformance with the 802.3 specification, MDC must not exceed + * 2.5 MHz (MDC is only active during MDIO read and write operations). + * The function execution time depend on MDC frequency. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address + * \param[out] val Register value + * + * \return Operation result. + * \retval ERR_NONE Read register successful. + */ +int32_t ethernet_phy_read_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t *val); + +/** + * \brief Write PHY Register value. + * + * Read PHY Register value from PHY. + * + * \note For conformance with the 802.3 specification, MDC must not exceed + * 2.5 MHz (MDC is only active during MDIO read and write operations). + * The function execution time depend on MDC frequency. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address + * \param[out] val Register value + * + * \return Operation result. + * \retval ERR_NONE Write register successful. + */ +int32_t ethernet_phy_write_reg(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t val); + +/** + * \brief Setting bit for a PHY Register + * + * Bit setting for a PHY Register. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address. + * \param[in] ofst Register bit mask. + * + * \return Operation result. + * \retval ERR_NONE Set register bit successful. + */ +int32_t ethernet_phy_set_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst); + +/** + * \brief Clear bit for a PHY Register + * + * Clear bit for a PHY Register. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] reg Register address. + * \param[in] ofst Register bit mask. + * + * \return Operation result. + * \retval ERR_NONE Clear register bit successful. + */ +int32_t ethernet_phy_clear_reg_bit(struct ethernet_phy_descriptor *const descr, uint16_t reg, uint16_t ofst); + +/** + * \brief Set PHY low-power consumption state. + * + * The specific behavior of a PHY in the power-down state is implementation + * specific. While in the power-down state, the PHY shall respond to management + * transactions. During the transition to the power-down state and while in the + * power-down state, the PHY shall not generate spurious signals on the MII or + * GMII. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] state The state of the power-down mode. + * + * \return Operation result. + * \retval ERR_NONE Power-Down has been config successful. + */ +int32_t ethernet_phy_set_powerdown(struct ethernet_phy_descriptor *const descr, bool state); + +/** + * \brief Set PHY electrically isolate state. + * + * When the PHY is isolated from the MII or RMII it shall not respond to the + * data bundle. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] state The state of the isolate mode. + * + * \return Operation result. + * \retval ERR_NONE Isolate has been config successful. + */ +int32_t ethernet_phy_set_isolate(struct ethernet_phy_descriptor *const descr, bool state); + +/** + * \brief Restart an auto negotiation of the PHY. + * + * Restart Auto_Negotantion process + * + * \param[in] descr Ethernet PHY descriptor. + * + * \return Operation result + * \retval ERR_NONE Auto-Negotiation has been initiated. + */ +int32_t ethernet_phy_restart_autoneg(struct ethernet_phy_descriptor *const descr); + +/** + * \brief Set PHY placed in a loopback mode of operation. + * + * When in loopback mode, the PHY shall accept data from the MII/RMII transmit + * data path and return it to the MII/RMII receive data path. + * + * \param[in] descr Ethernet PHY descriptor. + * \param[in] state State of the loopback mode. + * + * \return Operation result + * \retval ERR_NONE Loopback has been set successful. + */ +int32_t ethernet_phy_set_loopback(struct ethernet_phy_descriptor *const descr, bool state); + +/** + * \brief Get PHY link status + * + * Get PHY link status + * + * \param[in] descr Ethernet PHY descriptor. + * \param[out] status Pointer to the Link Status. + * + * \return ERR_NONE if successfully + */ +int32_t ethernet_phy_get_link_status(struct ethernet_phy_descriptor *const descr, bool *status); + +/** + * \brief Reset PHY. + * + * Resetting PHY, this action set all the status and control register to their + * default states. As a consequence this action may change the internal state + * of the PHY and the state of the physical link associated with the PHY. The + * reset process shall be completed within 0.5 second. + * + * \param[in] descr Ethernet PHY descriptor. + * + * \return ERR_NONE if successfully + */ +int32_t ethernet_phy_reset(struct ethernet_phy_descriptor *const descr); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef ETHERNET_PHY_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/ethernet_phy/ieee8023_mii_standard_register.h b/bsp/microchip/same70/bsp/ethernet_phy/ieee8023_mii_standard_register.h new file mode 100644 index 0000000000..e36caddf24 --- /dev/null +++ b/bsp/microchip/same70/bsp/ethernet_phy/ieee8023_mii_standard_register.h @@ -0,0 +1,137 @@ +/** + * \file + * + * \brief IEEE802.3 MII Management Standard Register Set + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef ETHERNET_MII_REGISTER_H_INCLUDED +#define ETHERNET_MII_REGISTER_H_INCLUDED + +/* IEEE 802.3 Clause22.2.4 defined Standard Registers. + * The MII basic register set consists of two registers referred to as the + * Control register (Register 0) and the Status register (Register 1). All + * PHYs that provide an MII shall incorporate the basic register set. All PHYs + * that provide a GMII shall incorporate an extended basic register set + * consisting of the Control register (Register 0), Status register + * (Register 1), and Extended Status register (Register 15). The status and + * control functions defined here are considered basic and fundamental to + * 100 Mb/s and 1000 Mb/s PHYs. Registers 2 through 14 are part of the + * extended register set. The format of Registers 4 through 10 are defined for + * the specific Auto-Negotiation protocol used (Clause 28 or Clause 37). The + * format of these registers is selected by the bit settings of Registers 1 + * and 15. + **/ +#define MDIO_REG0_BMCR 0x00 /* Basic Control */ +#define MDIO_REG1_BMSR 0x01 /* Basic Status */ +#define MDIO_REG2_PHYID1 0x02 /* PHY Idendifier 1 */ +#define MDIO_REG3_PHYID2 0x03 /* PHY Idendifier 2 */ +#define MDIO_REG4_ANA 0x04 /* Auto_Negotiation Advertisement */ +#define MDIO_REG5_ANLPA 0x05 /* Auto_negotiation Link Partner Base Page Ability */ +#define MDIO_REG6_ANE 0x06 /* Auto-negotiation Expansion */ +#define MDIO_REG7_ANNPT 0x07 /* Auto-negotiation Next Page Transmit */ +#define MDIO_REG8_ANLPRNP 0x08 /* Auto-Negotiation Link Partner Received Next Page */ +#define MDIO_REG9_MSC 0x09 /* MASTER-SLAVE Control Register */ +#define MDIO_REG10_MSS 0x0A /* MASTER-SLAVE Status Register */ +#define MDIO_REG11_PSEC 0x0B /* PSE Control Register */ +#define MDIO_REG12_PSES 0x0C /* PSE Status Register */ +#define MDIO_REG13_MMDAC 0x0D /* MMD Access Control Register */ +#define MDIO_REG14_MMDAAD 0x0E /* MMD Access Address Data Register */ +#define MDIO_REG15_EXTS 0x0F /* Extended Status */ +/* Register 16 to 31 are Reserved for Vendor Specific */ + +/* Bit definitions: MDIO_REG0_BMCR 0x00 Basic Control */ +#define MDIO_REG0_BIT_RESET (1 << 15) /* 1 = Software Reset; 0 = Normal Operation */ +#define MDIO_REG0_BIT_LOOPBACK (1 << 14) /* 1 = loopback Enabled; 0 = Normal Operation */ +#define MDIO_REG0_BIT_SPEED_SELECT_LSB (1 << 13) /* 1 = 100Mbps; 0=10Mbps */ +#define MDIO_REG0_BIT_AUTONEG (1 << 12) /* 1 = Auto-negotiation Enable */ +#define MDIO_REG0_BIT_POWER_DOWN (1 << 11) /* 1 = Power down 0=Normal operation */ +#define MDIO_REG0_BIT_ISOLATE (1 << 10) /* 1 = Isolates 0 = Normal operation */ +#define MDIO_REG0_BIT_RESTART_AUTONEG (1 << 9) /* 1 = Restart auto-negotiation 0 = Normal operation */ +#define MDIO_REG0_BIT_DUPLEX_MODE (1 << 8) /* 1 = Full duplex operation 0 = Normal operation */ +#define MDIO_REG0_BIT_COLLISION_TEST (1 << 7) /* 1 = Enable COL test; 0 = Disable COL test */ +#define MDIO_REG0_BIT_SPEED_SELECT_MSB (1 << 6) /* 1 with LSB0 = 1000Mbps */ +#define MDIO_REG0_BIT_UNIDIR_ENABLE (1 << 5) /* Unidirectional Enable */ +/* Reserved 4 to 0 Read as 0, ignore on write */ + +/* Bit definitions: MDIO_BMSR 0x01 Basic Status */ +#define MDIO_REG1_BIT_100BASE_T4 (1 << 15) /* 100BASE-T4 Capable */ +#define MDIO_REG1_BIT_100BASE_TX_FD (1 << 14) /* 100BASE-TX Full Duplex Capable */ +#define MDIO_REG1_BIT_100BASE_TX_HD (1 << 13) /* 100BASE-TX Half Duplex Capable */ +#define MDIO_REG1_BIT_10BASE_T_FD (1 << 12) /* 10BASE-T Full Duplex Capable */ +#define MDIO_REG1_BIT_10BASE_T_HD (1 << 11) /* 10BASE-T Half Duplex Capable */ +#define MDIO_REG1_BIT_100BASE_T2_FD (1 << 10) /* 1000BASE-T2 Full Duplex Capable */ +#define MDIO_REG1_BIT_100BASE_T2_HD (1 << 9) /* 1000BASE-T2 Half Duplex Capable */ +#define MDIO_REG1_BIT_EXTEND_STATUS (1 << 8) /* 1 = Extend Status Information In Reg 15 */ +#define MDIO_REG1_BIT_UNIDIR_ABILITY (1 << 7) /* Unidirectional ability */ +#define MDIO_REG1_BIT_MF_PREAMB_SUPPR (1 << 6) /* MII Frame Preamble Suppression */ +#define MDIO_REG1_BIT_AUTONEG_COMP (1 << 5) /* Auto-negotiation Complete */ +#define MDIO_REG1_BIT_REMOTE_FAULT (1 << 4) /* Remote Fault */ +#define MDIO_REG1_BIT_AUTONEG_ABILITY (1 << 3) /* Auto Configuration Ability */ +#define MDIO_REG1_BIT_LINK_STATUS (1 << 2) /* Link Status */ +#define MDIO_REG1_BIT_JABBER_DETECT (1 << 1) /* Jabber Detect */ +#define MDIO_REG1_BIT_EXTEND_CAPAB (1 << 0) /* Extended Capability */ + +/* Bit definitions: MDIO_PHYID1 0x02 PHY Idendifier 1 */ +/* Bit definitions: MDIO_PHYID2 0x03 PHY Idendifier 2 */ +#define MDIO_LSB_MASK 0x3F +#define MDIO_OUI_MSB 0x0022 +#define MDIO_OUI_LSB 0x1572 + +/* Bit definitions: MDIO_REG4_ANA 0x04 Auto-Negotiation advertisement */ +#define MDIO_REG4_BIT_NEXTPAGE (15 << 0) /* Next Page */ +#define MDIO_REG4_BIT_REMOTE_FAULT (13 << 0) /* Remote Fault */ +#define MDIO_REG4_BIT_EXT_NEXTPAGE (12 << 0) /* Extended Next Page */ + +/* Bit definitions: MDIO_ANAR 0x04 Auto_Negotiation Advertisement */ +/* Bit definitions: MDIO_ANLPAR 0x05 Auto_negotiation Link Partner Ability */ +#define MDIO_NP (1 << 15) /* Next page Indication */ +#define MDIO_RF (1 << 13) /* Remote Fault */ +#define MDIO_PAUSE_MASK (3 << 10) /* 0,0 = No Pause 1,0 = Asymmetric Pause(link partner) */ + /* 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device) */ +#define MDIO_100T4 (1 << 9) /* 100BASE-T4 Support */ +#define MDIO_100TX_FDX (1 << 8) /* 100BASE-TX Full Duplex Support */ +#define MDIO_100TX_HDX (1 << 7) /* 100BASE-TX Half Duplex Support */ +#define MDIO_10_FDX (1 << 6) /* 10BASE-T Full Duplex Support */ +#define MDIO_10_HDX (1 << 5) /* 10BASE-T Half Duplex Support */ +#define MDIO_AN_IEEE_802_3 0x0001 /* [00001] = IEEE 802.3 */ + +/* Bit definitions: MDIO_ANER 0x06 Auto-negotiation Expansion */ +#define MDIO_PDF (1 << 4) /* Local Device Parallel Detection Fault */ +#define MDIO_LP_NP_ABLE (1 << 3) /* Link Partner Next Page Able */ +#define MDIO_NP_ABLE (1 << 2) /* Local Device Next Page Able */ +#define MDIO_PAGE_RX (1 << 1) /* New Page Received */ +#define MDIO_LP_AN_ABLE (1 << 0) /* Link Partner Auto-negotiation Able */ + +/* Bit definitions: MDIO_PCR1 0x1E PHY Control 1 */ +#define MDIO_OMI_10BASE_T_HD 0x0001 +#define MDIO_OMI_100BASE_TX_HD 0x0002 +#define MDIO_OMI_10BASE_T_FD 0x0005 + +#endif /* #ifndef ETHERNET_MII_REGISTER_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/ethernet_phy_main.c b/bsp/microchip/same70/bsp/ethernet_phy_main.c new file mode 100644 index 0000000000..7ece274706 --- /dev/null +++ b/bsp/microchip/same70/bsp/ethernet_phy_main.c @@ -0,0 +1,43 @@ +/* + * Code generated from Atmel Start. + * + * This file will be overwritten when reconfiguring your Atmel Start project. + * Please copy examples or other code you want to keep to a separate file or main.c + * to avoid loosing it when reconfiguring. + */ + +#include +#include +#include + +struct ethernet_phy_descriptor MACIF_PHY_desc; + +void MACIF_PHY_init(void) +{ + mac_async_enable(&MACIF); + ethernet_phy_init(&MACIF_PHY_desc, &MACIF, CONF_MACIF_PHY_IEEE8023_MII_PHY_ADDRESS); +#if CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING == 1 + ethernet_phy_write_reg(&MACIF_PHY_desc, MDIO_REG0_BMCR, CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0); +#endif /* CONF_MACIF_PHY_IEEE8023_MII_CONTROL_REG0_SETTING */ +} + +void MACIF_PHY_example(void) +{ + bool link_state; + int32_t rst; + /* Restart an auto-negotiation */ + rst = ethernet_phy_restart_autoneg(&MACIF_PHY_desc); + while (rst != ERR_NONE) { + } + + /* Wait for PHY link up */ + do { + rst = ethernet_phy_get_link_status(&MACIF_PHY_desc, &link_state); + } while (rst == ERR_NONE && link_state == true); +} + +void ethernet_phys_init(void) +{ + + MACIF_PHY_init(); +} diff --git a/bsp/microchip/same70/bsp/ethernet_phy_main.h b/bsp/microchip/same70/bsp/ethernet_phy_main.h new file mode 100644 index 0000000000..e55c9706e4 --- /dev/null +++ b/bsp/microchip/same70/bsp/ethernet_phy_main.h @@ -0,0 +1,30 @@ +/* + * Code generated from Atmel Start. + * + * This file will be overwritten when reconfiguring your Atmel Start project. + * Please copy examples or other code you want to keep to a separate file or main.c + * to avoid loosing it when reconfiguring. + */ +#ifndef ETHERNET_PHY_MAIN_H +#define ETHERNET_PHY_MAIN_H + +#ifdef __cplusplus +extern "C" { +#endif +#include + +extern struct ethernet_phy_descriptor MACIF_PHY_desc; + +void ethernet_phys_init(void); +void MACIF_PHY_example(void); + +/** + * \brief Ethernet PHY devices + */ +void ethernet_phys_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ETHERNET_PHY_MAIN_H */ diff --git a/bsp/microchip/same70/bsp/examples/driver_examples.c b/bsp/microchip/same70/bsp/examples/driver_examples.c index 116cc2adb8..84a1ad4159 100644 --- a/bsp/microchip/same70/bsp/examples/driver_examples.c +++ b/bsp/microchip/same70/bsp/examples/driver_examples.c @@ -10,21 +10,63 @@ #include "driver_init.h" #include "utils.h" -void delay_example(void) +/** + * Example of using ADC_0 to generate waveform. + */ +void ADC_0_example(void) +{ + uint8_t buffer_ch10[2]; + + adc_sync_enable_channel(&ADC_0, CONF_ADC_0_CHANNEL_10); + + while (1) { + adc_sync_read_channel(&ADC_0, CONF_ADC_0_CHANNEL_10, buffer_ch10, 2); + } +} + +void I2C_0_example(void) { - delay_ms(5000); + struct io_descriptor *I2C_0_io; + + i2c_m_sync_get_io_descriptor(&I2C_0, &I2C_0_io); + i2c_m_sync_enable(&I2C_0); + i2c_m_sync_set_slaveaddr(&I2C_0, 0x12, I2C_M_SEVEN); + io_write(I2C_0_io, (uint8_t *)"Hello World!", 12); } /** * Example of using TARGET_IO to write "Hello World" using the IO abstraction. + * + * Since the driver is asynchronous we need to use statically allocated memory for string + * because driver initiates transfer and then returns before the transmission is completed. + * + * Once transfer has been completed the tx_cb function will be called. */ + +static uint8_t example_TARGET_IO[12] = "Hello World!"; + +static void tx_cb_TARGET_IO(const struct usart_async_descriptor *const io_descr) +{ + /* Transfer completed */ +} + void TARGET_IO_example(void) { struct io_descriptor *io; - usart_sync_get_io_descriptor(&TARGET_IO, &io); - usart_sync_enable(&TARGET_IO); - io_write(io, (uint8_t *)"Hello World!", 12); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, tx_cb_TARGET_IO); + /*usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, rx_cb); + usart_async_register_callback(&TARGET_IO, USART_ASYNC_ERROR_CB, err_cb);*/ + usart_async_get_io_descriptor(&TARGET_IO, &io); + usart_async_enable(&TARGET_IO); + + io_write(io, example_TARGET_IO, 12); +} + +void MACIF_example(void) +{ + mac_async_enable(&MACIF); + mac_async_write(&MACIF, (uint8_t *)"Hello World!", 12); } void CAN_0_tx_callback(struct can_async_descriptor *const descr) diff --git a/bsp/microchip/same70/bsp/examples/driver_examples.h b/bsp/microchip/same70/bsp/examples/driver_examples.h index 5aa87ac195..8fafd42f46 100644 --- a/bsp/microchip/same70/bsp/examples/driver_examples.h +++ b/bsp/microchip/same70/bsp/examples/driver_examples.h @@ -16,10 +16,14 @@ extern "C" { #endif -void delay_example(void); +void ADC_0_example(void); + +void I2C_0_example(void); void TARGET_IO_example(void); +void MACIF_example(void); + void CAN_0_example(void); #ifdef __cplusplus diff --git a/bsp/microchip/same70/bsp/hal/documentation/adc_sync.rst b/bsp/microchip/same70/bsp/hal/documentation/adc_sync.rst new file mode 100644 index 0000000000..d189565ad8 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/documentation/adc_sync.rst @@ -0,0 +1,74 @@ +====================== +ADC Synchronous driver +====================== + +An ADC (Analog-to-Digital Converter) converts analog signals to digital values. +A reference signal with a known voltage level is quantified into equally +sized chunks, each representing a digital value from 0 to the highest number +possible with the bit resolution supported by the ADC. The input voltage +measured by the ADC is compared against these chunks and the chunk with the +closest voltage level defines the digital value that can be used to represent +the analog input voltage level. + +Usually an ADC can operate in either differential or single-ended mode. +In differential mode two signals (V+ and V-) are compared against each other +and the resulting digital value represents the relative voltage level between +V+ and V-. This means that if the input voltage level on V+ is lower than on +V- the digital value is negative, which also means that in differential +mode one bit is lost to the sign. In single-ended mode only V+ is compared +against the reference voltage, and the resulting digital value can only be +positive, but the full bit-range of the ADC can be used. + +Usually multiple resolutions are supported by the ADC, lower resolution can +reduce the conversion time, but lose accuracy. + +Some ADCs has a gain stage on the input lines which can be used to increase the +dynamic range. The default gain value is usually x1, which means that the +conversion range is from 0V to the reference voltage. +Applications can change the gain stage, to increase or reduce the conversion +range. + +The window mode allows the conversion result to be compared to a set of +predefined threshold values. Applications can use callback function to monitor +if the conversion result exceeds predefined threshold value. + +Usually multiple reference voltages are supported by the ADC, both internal and +external with difference voltage levels. The reference voltage have an impact +on the accuracy, and should be selected to cover the full range of the analog +input signal and never less than the expected maximum input voltage. + +There are two conversion modes supported by ADC, single shot and free running. +In single shot mode the ADC only make one conversion when triggered by the +application, in free running mode it continues to make conversion from it +is triggered until it is stopped by the application. When window monitoring, +the ADC should be set to free running mode. + +Features +-------- +* Initialization and de-initialization +* Support multiple Conversion Mode, Single or Free run +* Start ADC Conversion +* Read Conversion Result + +Applications +------------ +* Measurement of internal sensor. E.g., MCU internal temperature sensor value. +* Measurement of external sensor. E.g., Temperature, humidity sensor value. +* Sampling and measurement of a signal. E.g., sinusoidal wave, square wave. + +Dependencies +------------ +* ADC hardware + +Concurrency +----------- +N/A + +Limitations +----------- +N/A + +Knows issues and workarounds +---------------------------- +N/A + diff --git a/bsp/microchip/same70/bsp/hal/documentation/i2c_master_sync.rst b/bsp/microchip/same70/bsp/hal/documentation/i2c_master_sync.rst new file mode 100644 index 0000000000..77b4f6e9c4 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/documentation/i2c_master_sync.rst @@ -0,0 +1,87 @@ +============================= +I2C Master synchronous driver +============================= + +I2C (Inter-Integrated Circuit) is a two wire serial interface usually used +for on-board low-speed bi-directional communication between controllers and +peripherals. The master device is responsible for initiating and controlling +all transfers on the I2C bus. Only one master device can be active on the I2C +bus at the time, but the master role can be transferred between devices on the +same I2C bus. I2C uses only two bidirectional open-drain lines, usually +designated SDA (Serial Data Line) and SCL (Serial Clock Line), with pull up +resistors. + +The stop condition is automatically controlled by the driver if the I/O write and +read functions are used, but can be manually controlled by using the +i2c_m_sync_transfer function. + +Often a master accesses different information in the slave by accessing +different registers in the slave. This is done by first sending a message to +the target slave containing the register address, followed by a repeated start +condition (no stop condition between) ending with transferring register data. +This scheme is supported by the i2c_m_sync_cmd_write and i2c_m_sync_cmd_read +function, but limited to 8-bit register addresses. + +I2C Modes (standard mode/fastmode+/highspeed mode) can only be selected in +Atmel Start. If the SCL frequency (baudrate) has changed run-time, make sure to +stick within the SCL clock frequency range supported by the selected mode. +The requested SCL clock frequency is not validated by the +i2c_m_sync_set_baudrate function against the selected I2C mode. + +Features +-------- + + * I2C Master support + * Initialization and de-initialization + * Enabling and disabling + * Run-time bus speed configuration + * Write and read I2C messages + * Slave register access functions (limited to 8-bit address) + * Manual or automatic stop condition generation + * 10- and 7- bit addressing + * I2C Modes supported + +----------------------+-------------------+ + |* Standard/Fast mode | (SCL: 1 - 400kHz) | + +----------------------+-------------------+ + |* Fastmode+ | (SCL: 1 - 1000kHz)| + +----------------------+-------------------+ + |* Highspeed mode | (SCL: 1 - 3400kHz)| + +----------------------+-------------------+ + +Applications +------------ + +* Transfer data to and from one or multiple I2C slaves like I2C connected sensors, data storage or other I2C capable peripherals +* Data communication between micro controllers +* Controlling displays + +Dependencies +------------ + +* I2C Master capable hardware + +Concurrency +----------- + +N/A + +Limitations +----------- + +General +^^^^^^^ + + * System Managmenet Bus (SMBus) not supported. + * Power Management Bus (PMBus) not supported. + +Clock considerations +^^^^^^^^^^^^^^^^^^^^ + +The register value for the requested I2C speed is calculated and placed in the correct register, but not validated if it works correctly with the clock/prescaler settings used for the module. To validate the I2C speed setting use the formula found in the configuration file for the module. Selectable speed is automatically limited within the speed range defined by the I2C mode selected. + +Known issues and workarounds +---------------------------- + +N/A + + diff --git a/bsp/microchip/same70/bsp/hal/documentation/mac_async.rst b/bsp/microchip/same70/bsp/hal/documentation/mac_async.rst new file mode 100644 index 0000000000..688dc3797a --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/documentation/mac_async.rst @@ -0,0 +1,43 @@ +================================ +Ethernet MAC Asynchronous Driver +================================ + +The Ethernet MAC driver implements a 10/100 Mbps Ethernet MAC compatible with +the IEEE 802.3 standard. + +Features +-------- + +* Initialization/de-initialization +* Enabling/disabling +* Data transfer: transmission, reception +* Enabling/disabling Interrupt +* Notifications about transfer completion and frame received via callbacks +* Address Filter for Specific 48-bit Addresses and Type ID +* Address Filter for Unicast and Multicase Addresses +* Reading/writing PHY registers + +Applications +------------ + +Co-works with thirdpart TCP/IP stacks. E.g., Lwip, Cyclone IP stack. + +Dependencies +------------ + +MAC capable hardware compatible with the IEEE 802.3 standard. + +Concurrency +----------- + +N/A + +Limitations +----------- + +N/A + +Known issues and workarounds +---------------------------- + +N/A diff --git a/bsp/microchip/same54/bsp/hal/documentation/usart_sync.rst b/bsp/microchip/same70/bsp/hal/documentation/usart_async.rst similarity index 62% rename from bsp/microchip/same54/bsp/hal/documentation/usart_sync.rst rename to bsp/microchip/same70/bsp/hal/documentation/usart_async.rst index 15e4b13885..6bf4a23e92 100644 --- a/bsp/microchip/same54/bsp/hal/documentation/usart_sync.rst +++ b/bsp/microchip/same70/bsp/hal/documentation/usart_async.rst @@ -1,9 +1,20 @@ -The USART Synchronous Driver -============================ +The USART Asynchronous Driver +============================= The universal synchronous and asynchronous receiver and transmitter (USART) is usually used to transfer data from one device to the other. +The USART driver use a ring buffer to store received data. When the USART +raise the data received interrupt, this data will be stored in the ring buffer +at the next free location. When the ring buffer is full, the next reception +will overwrite the oldest data stored in the ring buffer. There is one +USART_BUFFER_SIZE macro per used hardware instance, e.g. for SERCOM0 the macro +is called SERCOM0_USART_BUFFER_SIZE. + +On the other hand, when sending data over USART, the data is not copied to an +internal buffer, but the data buffer supplied by the user is used. The callback +will only be generated at the end of the buffer and not for each byte. + User can set action for flow control pins by function usart_set_flow_control, if the flow control is enabled. All the available states are defined in union usart_flow_control_state. @@ -24,6 +35,8 @@ Features * Data order * Flow control * Data transfer: transmission, reception +* Notifications about transfer done or error case via callbacks +* Status information with busy state and transfer count Applications ------------ @@ -34,7 +47,8 @@ between devices. Dependencies ------------ -USART capable hardware. +USART capable hardware, with interrupt on each character is sent or +received. Concurrency ----------- diff --git a/bsp/microchip/same70/bsp/hal/include/hal_adc_sync.h b/bsp/microchip/same70/bsp/hal/include/hal_adc_sync.h new file mode 100644 index 0000000000..1b66e3df7c --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hal_adc_sync.h @@ -0,0 +1,277 @@ +/** + * \file + * + * \brief ADC functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_ADC_SYNC_H_INCLUDED +#define _HAL_ADC_SYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_adc_sync + * + * @{ + */ + +/** + * \brief ADC descriptor + * + * The ADC descriptor forward declaration. + */ +struct adc_sync_descriptor; + +/** + * \brief ADC descriptor + */ +struct adc_sync_descriptor { + /** ADC device */ + struct _adc_sync_device device; +}; + +/** + * \brief Initialize ADC + * + * This function initializes the given ADC descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[out] descr An ADC descriptor to initialize + * \param[in] hw The pointer to hardware instance + * \param[in] func The pointer to a set of functions pointers + * + * \return Initialization status. + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func); + +/** + * \brief Deinitialize ADC + * + * This function deinitializes the given ADC descriptor. + * It checks if the given hardware is initialized and if the given hardware is + * permitted to be deinitialized. + * + * \param[in] descr An ADC descriptor to deinitialize + * + * \return De-initialization status. + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr); + +/** + * \brief Enable ADC + * + * Use this function to set the ADC peripheral to enabled state. + * + * \param[in] descr Pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return Operation status + * + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Disable ADC + * + * Use this function to set the ADC peripheral to disabled state. + * + * \param[in] descr Pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return Operation status + * + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Read data from ADC + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] buf A buffer to read data to + * \param[in] length The size of a buffer + * + * \return The number of bytes read. + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length); + +/** + * \brief Set ADC reference source + * + * This function sets ADC reference source. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] reference A reference source to set + * + * \return Status of the ADC reference source setting. + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference); + +/** + * \brief Set ADC resolution + * + * This function sets ADC resolution. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] resolution A resolution to set + * + * \return Status of the ADC resolution setting. + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * This function sets ADC positive and negative input sources. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + * + * \return Status of the ADC channels setting. + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set ADC conversion mode + * + * This function sets ADC conversion mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] mode A conversion mode to set + * + * \return Status of the ADC conversion mode setting. + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode); + +/** + * \brief Set ADC differential mode + * + * This function sets ADC differential mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + * + * \return Status of the ADC differential mode setting. + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set ADC channel gain + * + * This function sets ADC channel gain. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * \param[in] gain A gain to set + * + * \return Status of the ADC gain setting. + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, + const adc_gain_t gain); + +/** + * \brief Set ADC window mode + * + * This function sets ADC window mode. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] mode A window mode to set + * + * \return Status of the ADC window mode setting. + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode); + +/** + * \brief Set ADC thresholds + * + * This function sets ADC positive and negative thresholds. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] low_threshold A lower thresholds to set + * \param[in] up_threshold An upper thresholds to set + * + * \return Status of the ADC thresholds setting. + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * This function retrieves ADC threshold state. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[out] state The threshold state + * + * \return The state of ADC thresholds state retrieving. + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, + adc_threshold_status_t *const state); + +/** + * \brief Check if conversion is complete + * + * This function checks if the ADC has finished the conversion. + * + * \param[in] descr The pointer to the ADC descriptor + * \param[in] channel Channel number + * + * \return The status of ADC conversion completion checking. + * \retval 1 The conversion is complete + * \retval 0 The conversion is not complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t adc_sync_get_version(void); +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#include + +#endif /* _HAL_ADC_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hal_i2c_m_sync.h b/bsp/microchip/same70/bsp/hal/include/hal_i2c_m_sync.h new file mode 100644 index 0000000000..24afd63933 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hal_i2c_m_sync.h @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief Sync I2C Hardware Abstraction Layer(HAL) declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_I2C_M_SYNC_H_INCLUDED +#define _HAL_I2C_M_SYNC_H_INCLUDED + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_i2c_master_sync + * + * @{ + */ + +#define I2C_M_MAX_RETRY 1 + +/** + * \brief I2C descriptor structure, embed i2c_device & i2c_interface + */ +struct i2c_m_sync_desc { + struct _i2c_m_sync_device device; + struct io_descriptor io; + uint16_t slave_addr; +}; + +/** + * \brief Initialize synchronous I2C interface + * + * This function initializes the given I/O descriptor to be used as a + * synchronous I2C interface descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] hw The pointer to hardware instance + * + * \return Initialization status. + * \retval -1 The passed parameters were invalid or the interface is already initialized + * \retval 0 The initialization is completed successfully + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw); + +/** + * \brief Deinitialize I2C interface + * + * This function deinitializes the given I/O descriptor. + * It checks if the given hardware is initialized and if the given hardware is permitted to be deinitialized. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Uninitialization status. + * \retval -1 The passed parameters were invalid or the interface is already deinitialized + * \retval 0 The de-initialization is completed successfully + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c); + +/** + * \brief Set the slave device address + * + * This function sets the next transfer target slave I2C device address. + * It takes no effect to any already started access. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] addr The slave address to access + * \param[in] addr_len The slave address length, can be I2C_M_TEN or I2C_M_SEVEN + * + * \return Masked slave address. The mask is a maximum 10-bit address, and 10th + * bit is set if a 10-bit address is used + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len); + +/** + * \brief Set baudrate + * + * This function sets the I2C device to the specified baudrate. + * It only takes effect when the hardware is disabled. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] clkrate Unused parameter. Should always be 0 + * \param[in] baudrate The baudrate value set to master + * + * \return Whether successfully set the baudrate + * \retval -1 The passed parameters were invalid or the device is already enabled + * \retval 0 The baudrate set is completed successfully + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate); + +/** + * \brief Sync version of enable hardware + * + * This function enables the I2C device, and then waits for this enabling operation to be done + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Whether successfully enable the device + * \retval -1 The passed parameters were invalid or the device enable failed + * \retval 0 The hardware enabling is completed successfully + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c); + +/** + * \brief Sync version of disable hardware + * + * This function disables the I2C device and then waits for this disabling operation to be done + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return Whether successfully disable the device + * \retval -1 The passed parameters were invalid or the device disable failed + * \retval 0 The hardware disabling is completed successfully + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c); + +/** + * \brief Sync version of write command to I2C slave + * + * This function will write the value to a specified register in the I2C slave device and + * then wait for this operation to be done. + * + * The sequence of this routine is + * sta->address(write)->ack->reg address->ack->resta->address(write)->ack->reg value->nack->stt + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] reg The internal address/register of the I2C slave device + * \param[in] buffer The buffer holding data to write to the I2C slave device + * \param[in] length The length (in bytes) to write to the I2C slave device + * + * \return Whether successfully write to the device + * \retval <0 The passed parameters were invalid or write fail + * \retval 0 Writing to register is completed successfully + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length); + +/** + * \brief Sync version of read register value from I2C slave + * + * This function will read a byte value from a specified register in the I2C slave device and + * then wait for this operation to be done. + * + * The sequence of this routine is + * sta->address(write)->ack->reg address->ack->resta->address(read)->ack->reg value->nack->stt + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] reg The internal address/register of the I2C slave device + * \param[in] buffer The buffer to hold the read data from the I2C slave device + * \param[in] length The length (in bytes) to read from the I2C slave device + * + * \return Whether successfully read from the device + * \retval <0 The passed parameters were invalid or read fail + * \retval 0 Reading from register is completed successfully + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length); + +/** + * \brief Sync version of transfer message to/from the I2C slave + * + * This function will transfer a message between the I2C slave and the master. This function will wait for the operation + * to be done. + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * \param[in] msg An i2c_m_msg struct + * + * \return The status of the operation + * \retval 0 Operation completed successfully + * \retval <0 Operation failed + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg); + +/** + * \brief Sync version of send stop condition on the i2c bus + * + * This function will create a stop condition on the i2c bus to release the bus + * + * \param[in] i2c An I2C descriptor, which is used to communicate through I2C + * + * \return The status of the operation + * \retval 0 Operation completed successfully + * \retval <0 Operation failed + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c); + +/** + * \brief Return I/O descriptor for this I2C instance + * + * This function will return a I/O instance for this I2C driver instance + * + * \param[in] i2c_m_sync_desc An I2C descriptor, which is used to communicate through I2C + * \param[in] io_descriptor A pointer to an I/O descriptor pointer type + * + * \return Error code + * \retval 0 No error detected + * \retval <0 Error code + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t i2c_m_sync_get_version(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/microchip/same70/bsp/hal/include/hal_mac_async.h b/bsp/microchip/same70/bsp/hal/include/hal_mac_async.h new file mode 100644 index 0000000000..8d54d7ec32 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hal_mac_async.h @@ -0,0 +1,260 @@ +/** + * \file + * + * \brief MAC functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef HAL_MAC_ASYNC_H_INCLUDED +#define HAL_MAC_ASYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup doc_driver_hal_mac_async + * + *@{ + */ + +/** + * \brief MAC descriptor + * + * The MAC descriptor forward declaration. + */ +struct mac_async_descriptor; + +/** + * \brief MAC callback type + * + * \param[in] descr A MAC descriptor + */ +typedef void (*mac_async_cb_t)(struct mac_async_descriptor *const descr); + +/** + * \brief MAC callbacks + */ +struct mac_async_callbacks { + mac_async_cb_t receive; + mac_async_cb_t transmit; +}; + +/** + * \brief MAC descriptor + */ +struct mac_async_descriptor { + struct _mac_async_device dev; /*!< MAC HPL device descriptor */ + struct mac_async_callbacks cb; /*!< MAC Callback handlers */ +}; + +/** + * Callback for MAC interrupt + */ +typedef void (*mac_cb)(struct mac_async_descriptor *const descr); + +/** + * \brief Initialize the MAC driver + * + * \param[in] descr A MAC descriptor to init. + * \param[in] hw Hardware instance pointer. + * + * \return Operation status. + * \retval ERR_NONE Success. + + */ +int32_t mac_async_init(struct mac_async_descriptor *const descr, void *const dev); + +/** + * \brief Deinitialize the MAC driver + * + * \param[in] descr A MAC descriptor to deinitialize. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_deinit(struct mac_async_descriptor *const descr); + +/** \brief Enable the MAC + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_enable(struct mac_async_descriptor *const descr); + +/** + * \brief Disable the MAC + * + * \param[in] descr Pointer to the HAL MAC descriptor + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_disable(struct mac_async_descriptor *const descr); + +/** + * \brief Write raw data to MAC + * + * Write the raw data to the MAC that will be transmitted + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] buf Pointer to the data buffer. + * \param[in] len Length of the data buffer. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_write(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len); + +/** + * \brief Read raw data from MAC + * + * Read received raw data from MAC + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] buffer Pointer to the data buffer. If the pointer is NULL, then the + * frame will be discarded. + * \param[in] length The max. length of the data buffer to be read. If the length is zero, + * then the frame will be discard + * + * \return Number of bytes that received + */ +uint32_t mac_async_read(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len); + +/** + * \brief Get next valid package length + * + * Get next valid package length from the MAC. The application can use this function + * to fetch the length of the next package, malloc a buffer with this + * length, and then invoke mac_async_read to read out the package data. + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * + * \return The number of bytes in the next package that can be read. + */ +uint32_t mac_async_read_len(struct mac_async_descriptor *const descr); + +/** + * \brief Enable the MAC IRQ + * + * \param[in] descr Pointer to the HAL MAC descriptor + */ +void mac_async_enable_irq(struct mac_async_descriptor *const descr); + +/** + * \brief Disable the MAC IRQ + * + * \param[in] descr Pointer to the HAL MAC descriptor + */ +void mac_async_disable_irq(struct mac_async_descriptor *const descr); + +/** + * \brief Register the MAC callback function + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] type Callback function type. + * \param[in] func A callback function. Passing NULL will de-register any + * registered callback. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_register_callback(struct mac_async_descriptor *const descr, const enum mac_async_cb_type type, + const FUNC_PTR func); + +/** + * \brief Set MAC filter + * + * Set MAC filter. Ethernet frames matching the filter, will be received. + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] index MAC filter index. Start from 0. The maximum value depends on + * the hardware specifications. + * \param[in] filter Pointer to the filter descriptor. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_set_filter(struct mac_async_descriptor *const descr, uint8_t index, struct mac_async_filter *filter); + +/** + * \brief Set MAC filter (expanded). + * + * Set MAC filter. The Ethernet frames matching the filter, will be received. + * + * \param[in] descr Pointer to the HAL MAC descriptor + * \param[in] mac MAC address + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_set_filter_ex(struct mac_async_descriptor *const descr, uint8_t mac[6]); + +/** + * \brief Write PHY register + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] val Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_write_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t val); + +/** + * \brief Read PHY register + * + * \param[in] descr Pointer to the HAL MAC descriptor. + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] val Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t mac_async_read_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t *val); + +/** + * \brief Get the MAC driver version + */ +uint32_t mac_async_get_version(void); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_MAC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hal_usart_async.h b/bsp/microchip/same70/bsp/hal/include/hal_usart_async.h new file mode 100644 index 0000000000..661c72bc77 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hal_usart_async.h @@ -0,0 +1,339 @@ +/** + * \file + * + * \brief USART related functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HAL_USART_ASYNC_H_INCLUDED +#define _HAL_USART_ASYNC_H_INCLUDED + +#include "hal_io.h" +#include +#include + +/** + * \addtogroup doc_driver_hal_usart_async + * + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief USART descriptor + * + * The USART descriptor forward declaration. + */ +struct usart_async_descriptor; + +/** + * \brief USART callback type + */ +typedef void (*usart_cb_t)(const struct usart_async_descriptor *const descr); + +/** + * \brief USART callback types + */ +enum usart_async_callback_type { USART_ASYNC_RXC_CB, USART_ASYNC_TXC_CB, USART_ASYNC_ERROR_CB }; + +/** + * \brief USART callbacks + */ +struct usart_async_callbacks { + usart_cb_t tx_done; + usart_cb_t rx_done; + usart_cb_t error; +}; + +/** \brief USART status + * Status descriptor holds the current status of transfer. + */ +struct usart_async_status { + /** Status flags */ + uint32_t flags; + /** Number of characters transmitted */ + uint16_t txcnt; + /** Number of characters receviced */ + uint16_t rxcnt; +}; + +/** + * \brief Asynchronous USART descriptor structure + */ +struct usart_async_descriptor { + struct io_descriptor io; + struct _usart_async_device device; + struct usart_async_callbacks usart_cb; + volatile uint32_t stat; + + struct ringbuffer rx; + uint16_t tx_por; + uint8_t * tx_buffer; + uint16_t tx_buffer_length; +}; + +/** USART write busy */ +#define USART_ASYNC_STATUS_BUSY 0x0001 + +/** + * \brief Initialize USART interface + * + * This function initializes the given I/O descriptor to be used as USART + * interface descriptor. + * It checks if the given hardware is not initialized and if the given hardware + * is permitted to be initialized. + * + * \param[out] descr A USART descriptor which is used to communicate via the USART + * \param[in] hw The pointer to the hardware instance + * \param[in] rx_buffer An RX buffer + * \param[in] rx_buffer_length The length of the buffer above + * \param[in] func The pointer to a set of function pointers + * + * \return Initialization status. + * \retval -1 Passed parameters were invalid or the interface is already + * initialized + * \retval 0 The initialization is completed successfully + */ +int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *const rx_buffer, + const uint16_t rx_buffer_length, void *const func); + +/** + * \brief Deinitialize USART interface + * + * This function deinitializes the given I/O descriptor. + * It checks if the given hardware is initialized and if the given hardware + * is permitted to be deinitialized. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return De-initialization status. + */ +int32_t usart_async_deinit(struct usart_async_descriptor *const descr); + +/** + * \brief Enable USART interface + * + * Enables the USART interface + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return Enabling status. + */ +int32_t usart_async_enable(struct usart_async_descriptor *const descr); + +/** + * \brief Disable USART interface + * + * Disables the USART interface + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return Disabling status. + */ +int32_t usart_async_disable(struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve I/O descriptor + * + * This function retrieves the I/O descriptor of the given USART descriptor. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] io An I/O descriptor to retrieve + * + * \return The status of I/O descriptor retrieving. + */ +int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io); + +/** + * \brief Register USART callback + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] type Callback type + * \param[in] cb A callback function + * + * \return The status of callback assignment. + * \retval -1 Passed parameters were invalid or the interface is not initialized + * \retval 0 A callback is registered successfully + */ +int32_t usart_async_register_callback(struct usart_async_descriptor *const descr, + const enum usart_async_callback_type type, usart_cb_t cb); + +/** + * \brief Specify action for flow control pins + * + * This function sets action (or state) for flow control pins if + * the flow control is enabled. + * It sets state of flow control pins only if automatic support of + * the flow control is not supported by the hardware. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] state A state to set the flow control pins + * + * \return The status of flow control action setup. + */ +int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr, + const union usart_flow_control_state state); + +/** + * \brief Set USART baud rate + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] baud_rate A baud rate to set + * + * \return The status of baud rate setting. + */ +int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate); + +/** + * \brief Set USART data order + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] data_order A data order to set + * + * \return The status of data order setting. + */ +int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order); + +/** + * \brief Set USART mode + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] mode A mode to set + * + * \return The status of mode setting. + */ +int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode); + +/** + * \brief Set USART parity + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] parity A parity to set + * + * \return The status of parity setting. + */ +int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity); + +/** + * \brief Set USART stop bits + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] stop_bits Stop bits to set + * + * \return The status of stop bits setting. + */ +int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits); + +/** + * \brief Set USART character size + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[in] size A character size to set + * + * \return The status of character size setting. + */ +int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, + const enum usart_character_size size); + +/** + * \brief Retrieve the state of flow control pins + * + * This function retrieves the flow control pins + * if the flow control is enabled. + * + * The function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case + * if the flow control is done by the hardware + * and the pins state cannot be read out. + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] state The state of flow control pins + * + * \return The status of flow control state reading. + */ +int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr, + union usart_flow_control_state *const state); + +/** + * \brief Check if the USART transmitter is empty + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return The status of USART TX empty checking. + * \retval 0 The USART transmitter is not empty + * \retval 1 The USART transmitter is empty + */ +int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr); + +/** + * \brief Check if the USART receiver is not empty + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * + * \return The status of the USART RX empty checking. + * \retval 1 The USART receiver is not empty + * \retval 0 The USART receiver is empty + */ +int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve the current interface status + * + * \param[in] descr A USART descriptor which is used to communicate via USART + * \param[out] status The state of USART + * + * \return The status of USART status retrieving. + */ +int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status); + +/** + * \brief flush USART ringbuf + * + * This function flush USART RX ringbuf. + * + * \param[in] descr The pointer to USART descriptor + * + * \return ERR_NONE + */ +int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr); + +/** + * \brief Retrieve the current driver version + * + * \return Current driver version. + */ +uint32_t usart_async_get_version(void); + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HAL_USART_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hal_usart_sync.h b/bsp/microchip/same70/bsp/hal/include/hal_usart_sync.h deleted file mode 100644 index 1ef22fc63f..0000000000 --- a/bsp/microchip/same70/bsp/hal/include/hal_usart_sync.h +++ /dev/null @@ -1,247 +0,0 @@ -/** - * \file - * - * \brief USART related functionality declaration. - * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#ifndef _HAL_SYNC_USART_H_INCLUDED -#define _HAL_SYNC_USART_H_INCLUDED - -#include "hal_io.h" -#include - -/** - * \addtogroup doc_driver_hal_usart_sync - * - * @{ - */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Synchronous USART descriptor - */ -struct usart_sync_descriptor { - struct io_descriptor io; - struct _usart_sync_device device; -}; - -/** - * \brief Initialize USART interface - * - * This function initializes the given I/O descriptor to be used - * as USART interface descriptor. - * It checks if the given hardware is not initialized and - * if the given hardware is permitted to be initialized. - * - * \param[out] descr A USART descriptor which is used to communicate via USART - * \param[in] hw The pointer to hardware instance - * \param[in] func The pointer to as set of functions pointers - * - * \return Initialization status. - */ -int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func); - -/** - * \brief Deinitialize USART interface - * - * This function deinitializes the given I/O descriptor. - * It checks if the given hardware is initialized and - * if the given hardware is permitted to be deinitialized. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return De-initialization status. - */ -int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr); - -/** - * \brief Enable USART interface - * - * Enables the USART interface - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return Enabling status. - */ -int32_t usart_sync_enable(struct usart_sync_descriptor *const descr); - -/** - * \brief Disable USART interface - * - * Disables the USART interface - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return Disabling status. - */ -int32_t usart_sync_disable(struct usart_sync_descriptor *const descr); - -/** - * \brief Retrieve I/O descriptor - * - * This function retrieves the I/O descriptor of the given USART descriptor. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[out] io An I/O descriptor to retrieve - * - * \return The status of the I/O descriptor retrieving. - */ -int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io); - -/** - * \brief Specify action for flow control pins - * - * This function sets the action (or state) for the flow control pins - * if the flow control is enabled. - * It sets the state of flow control pins only if the automatic support of - * the flow control is not supported by the hardware. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] state A state to set the flow control pins - * - * \return The status of flow control action setup. - */ -int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr, - const union usart_flow_control_state state); - -/** - * \brief Set USART baud rate - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] baud_rate A baud rate to set - * - * \return The status of baud rate setting. - */ -int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate); - -/** - * \brief Set USART data order - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] data_order A data order to set - * - * \return The status of data order setting. - */ -int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order); - -/** - * \brief Set USART mode - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] mode A mode to set - * - * \return The status of mode setting. - */ -int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode); - -/** - * \brief Set USART parity - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] parity A parity to set - * - * \return The status of parity setting. - */ -int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity); - -/** - * \brief Set USART stop bits - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] stop_bits Stop bits to set - * - * \return The status of stop bits setting. - */ -int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits); - -/** - * \brief Set USART character size - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[in] size A character size to set - * - * \return The status of character size setting. - */ -int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size); - -/** - * \brief Retrieve the state of flow control pins - * - * This function retrieves the of flow control pins - * if the flow control is enabled. - * Function can return USART_FLOW_CONTROL_STATE_UNAVAILABLE in case - * if the flow control is done by the hardware - * and the pins state cannot be read out. - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * \param[out] state The state of flow control pins - * - * \return The status of flow control state reading. - */ -int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr, - union usart_flow_control_state *const state); - -/** - * \brief Check if the USART transmitter is empty - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return The status of USART TX empty checking. - * \retval 0 The USART transmitter is not empty - * \retval 1 The USART transmitter is empty - */ -int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr); - -/** - * \brief Check if the USART receiver is not empty - * - * \param[in] descr A USART descriptor which is used to communicate via USART - * - * \return The status of USART RX empty checking. - * \retval 1 The USART receiver is not empty - * \retval 0 The USART receiver is empty - */ -int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr); - -/** - * \brief Retrieve the current driver version - * - * \return Current driver version. - */ -uint32_t usart_sync_get_version(void); - -#ifdef __cplusplus -} -#endif -/**@}*/ -#endif /* _HAL_SYNC_USART_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_adc_async.h b/bsp/microchip/same70/bsp/hal/include/hpl_adc_async.h new file mode 100644 index 0000000000..1aa4162409 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_adc_async.h @@ -0,0 +1,264 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_ASYNC_H_INCLUDED +#define _HPL_ADC_ASYNC_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_async_adc_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include "hpl_adc_sync.h" +#include "hpl_irq.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC device structure + * + * The ADC device structure forward declaration. + */ +struct _adc_async_device; + +/** + * \brief ADC callback types + */ +enum _adc_async_callback_type { ADC_ASYNC_DEVICE_CONVERT_CB, ADC_ASYNC_DEVICE_MONITOR_CB, ADC_ASYNC_DEVICE_ERROR_CB }; + +/** + * \brief ADC interrupt callbacks + */ +struct _adc_async_callbacks { + void (*window_cb)(struct _adc_async_device *device, const uint8_t channel); + void (*error_cb)(struct _adc_async_device *device, const uint8_t channel); +}; + +/** + * \brief ADC channel interrupt callbacks + */ +struct _adc_async_ch_callbacks { + void (*convert_done)(struct _adc_async_device *device, const uint8_t channel, const uint16_t data); +}; + +/** + * \brief ADC descriptor device structure + */ +struct _adc_async_device { + struct _adc_async_callbacks adc_async_cb; + struct _adc_async_ch_callbacks adc_async_ch_cb; + struct _irq_descriptor irq; + void * hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_async_deinit(struct _adc_async_device *const device); + +/** + * \brief Enable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC peripheral + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_async_convert(struct _adc_async_device *const device); + +/** + * \brief Retrieve the conversion result + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * The result value + */ +uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set lower threshold + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower threshold to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state); + +/** + * \brief Enable/disable ADC channel interrupt + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] type The type of interrupt to disable/enable if applicable + * \param[in] state Enable or disable + */ +void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel, + const enum _adc_async_callback_type type, const bool state); + +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_adc_sync.h b/bsp/microchip/same70/bsp/hal/include/hpl_adc_sync.h new file mode 100644 index 0000000000..3bfbc61d9c --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_adc_sync.h @@ -0,0 +1,271 @@ +/** + * \file + * + * \brief ADC related functionality declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef _HPL_ADC_SYNC_H_INCLUDED +#define _HPL_ADC_SYNC_H_INCLUDED + +/** + * \addtogroup HPL ADC + * + * \section hpl_adc_sync_rev Revision History + * - v1.0.0 Initial Release + * + *@{ + */ + +#include "compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief ADC reference source + */ +typedef uint8_t adc_reference_t; + +/** + * \brief ADC resolution + */ +typedef uint8_t adc_resolution_t; + +/** + * \brief ADC positive input for channel + */ +typedef uint8_t adc_pos_input_t; + +/** + * \brief ADC negative input for channel + */ +typedef uint8_t adc_neg_input_t; + +/** + * \brief ADC threshold + */ +typedef uint16_t adc_threshold_t; + +/** + * \brief ADC gain + */ +typedef uint8_t adc_gain_t; + +/** + * \brief ADC conversion mode + */ +enum adc_conversion_mode { ADC_CONVERSION_MODE_SINGLE_CONVERSION = 0, ADC_CONVERSION_MODE_FREERUN }; + +/** + * \brief ADC differential mode + */ +enum adc_differential_mode { ADC_DIFFERENTIAL_MODE_SINGLE_ENDED = 0, ADC_DIFFERENTIAL_MODE_DIFFERENTIAL }; + +/** + * \brief ADC window mode + */ +typedef uint8_t adc_window_mode_t; + +/** + * \brief ADC threshold status + */ +typedef bool adc_threshold_status_t; + +/** + * \brief ADC sync descriptor device structure + */ +struct _adc_sync_device { + void *hw; +}; + +/** + * \name HPL functions + */ +//@{ +/** + * \brief Initialize synchronous ADC + * + * This function does low level ADC configuration. + * + * param[in] device The pointer to ADC device instance + * param[in] hw The pointer to hardware instance + * + * \return Initialization status + */ +int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw); + +/** + * \brief Deinitialize ADC + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_sync_deinit(struct _adc_sync_device *const device); + +/** + * \brief Enable ADC + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Disable ADC + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + */ +void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Retrieve ADC conversion data size + * + * \param[in] device The pointer to ADC device instance + * + * \return The data size in bytes + */ +uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device); + +/** + * \brief Check if conversion is done + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The status of conversion + * \retval true The conversion is done + * \retval false The conversion is not done + */ +bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Make conversion + * + * \param[in] device The pointer to ADC device instance + */ +void _adc_sync_convert(struct _adc_sync_device *const device); + +/** + * \brief Retrieve the conversion result + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * + * \return The result value of channel + */ +uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel); + +/** + * \brief Set reference source + * + * \param[in] device The pointer to ADC device instance + * \param[in] reference A reference source to set + */ +void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference); + +/** + * \brief Set resolution + * + * \param[in] device The pointer to ADC device instance + * \param[in] resolution A resolution to set + */ +void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution); + +/** + * \brief Set ADC input source of a channel + * + * \param[in] device The pointer to ADC device instance + * \param[in] pos_input A positive input source to set + * \param[in] neg_input A negative input source to set + * \param[in] channel Channel number + */ +void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel); + +/** + * \brief Set conversion mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A conversion mode to set + */ +void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode); + +/** + * \brief Set differential mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] mode A differential mode to set + */ +void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel, + const enum adc_differential_mode mode); + +/** + * \brief Set gain + * + * \param[in] device The pointer to ADC device instance + * \param[in] channel Channel number + * \param[in] gain A gain to set + */ +void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain); + +/** + * \brief Set window mode + * + * \param[in] device The pointer to ADC device instance + * \param[in] mode A mode to set + */ +void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode); + +/** + * \brief Set threshold + * + * \param[in] device The pointer to ADC device instance + * \param[in] low_threshold A lower threshold to set + * \param[in] up_threshold An upper thresholds to set + */ +void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold); + +/** + * \brief Retrieve threshold state + * + * \param[in] device The pointer to ADC device instance + * \param[out] state The threshold state + */ +void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state); +//@} + +#ifdef __cplusplus +} +#endif +/**@}*/ +#endif /* _HPL_ADC_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_async.h b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_async.h new file mode 100644 index 0000000000..8a9491debb --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_async.h @@ -0,0 +1,205 @@ +/** + * \file + * + * \brief I2C Master Hardware Proxy Layer(HPL) declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#ifndef _HPL_I2C_M_ASYNC_H_INCLUDED +#define _HPL_I2C_M_ASYNC_H_INCLUDED + +#include "hpl_i2c_m_sync.h" +#include "hpl_irq.h" +#include "utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief i2c master callback names + */ +enum _i2c_m_async_callback_type { + I2C_M_ASYNC_DEVICE_ERROR, + I2C_M_ASYNC_DEVICE_TX_COMPLETE, + I2C_M_ASYNC_DEVICE_RX_COMPLETE +}; + +struct _i2c_m_async_device; + +typedef void (*_i2c_complete_cb_t)(struct _i2c_m_async_device *i2c_dev); +typedef void (*_i2c_error_cb_t)(struct _i2c_m_async_device *i2c_dev, int32_t errcode); + +/** + * \brief i2c callback pointers structure + */ +struct _i2c_m_async_callback { + _i2c_error_cb_t error; + _i2c_complete_cb_t tx_complete; + _i2c_complete_cb_t rx_complete; +}; + +/** + * \brief i2c device structure + */ +struct _i2c_m_async_device { + struct _i2c_m_service service; + void * hw; + struct _i2c_m_async_callback cb; + struct _irq_descriptor irq; +}; + +/** + * \name HPL functions + */ + +/** + * \brief Initialize I2C in interrupt mode + * + * This function does low level I2C configuration. + * + * \param[in] i2c_dev The pointer to i2c interrupt device structure + * \param[in] hw The pointer to hardware instance + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_init(struct _i2c_m_async_device *const i2c_dev, void *const hw); + +/** + * \brief Deinitialize I2C in interrupt mode + * + * \param[in] i2c_dev The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_deinit(struct _i2c_m_async_device *const i2c_dev); + +/** + * \brief Enable I2C module + * + * This function does low level I2C enable. + * + * \param[in] i2c_dev The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_enable(struct _i2c_m_async_device *const i2c_dev); + +/** + * \brief Disable I2C module + * + * This function does low level I2C disable. + * + * \param[in] i2c_dev The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_disable(struct _i2c_m_async_device *const i2c_dev); + +/** + * \brief Transfer data by I2C + * + * This function does low level I2C data transfer. + * + * \param[in] i2c_dev The pointer to i2c device structure + * \param[in] msg The pointer to i2c msg structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_transfer(struct _i2c_m_async_device *const i2c_dev, struct _i2c_m_msg *msg); + +/** + * \brief Set baud rate of I2C + * + * This function does low level I2C set baud rate. + * + * \param[in] i2c_dev The pointer to i2c device structure + * \param[in] clkrate The clock rate(KHz) input to i2c module + * \param[in] baudrate The demand baud rate(KHz) of i2c module + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_set_baudrate(struct _i2c_m_async_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate); + +/** + * \brief Register callback to I2C + * + * This function does low level I2C callback register. + * + * \param[in] i2c_dev The pointer to i2c device structure + * \param[in] cb_type The callback type request + * \param[in] func The callback function pointer + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_async_register_callback(struct _i2c_m_async_device *i2c_dev, enum _i2c_m_async_callback_type cb_type, + FUNC_PTR func); + +/** + * \brief Generate stop condition on the I2C bus + * + * This function will generate a stop condition on the I2C bus + * + * \param[in] i2c_m_async_descriptor An i2c descriptor which is used to communicate through I2C + * + * \return Operation status + * \retval 0 Operation executed successfully + * \retval <0 Operation failed + */ +int32_t _i2c_m_async_send_stop(struct _i2c_m_async_device *const i2c_dev); + +/** + * \brief Returns the number of bytes left or not used in the I2C message buffer + * + * This function will return the number of bytes left (not written to the bus) or still free + * (not received from the bus) in the message buffer, depending on direction of transmission. + * + * \param[in] i2c_m_async_descriptor An i2c descriptor which is used to communicate through I2C + * + * \return Number of bytes or error code + * \retval >0 Positive number indicating bytes left + * \retval 0 Buffer is full/empty depending on direction + * \retval <0 Error code + */ +int32_t _i2c_m_async_get_bytes_left(struct _i2c_m_async_device *const i2c_dev); + +/** + * \brief Enable/disable I2C master interrupt + * + * param[in] device The pointer to I2C master device instance + * param[in] type The type of interrupt to disable/enable if applicable + * param[in] state Enable or disable + */ +void _i2c_m_async_set_irq_state(struct _i2c_m_async_device *const device, const enum _i2c_m_async_callback_type type, + const bool state); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_sync.h b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_sync.h new file mode 100644 index 0000000000..ce173ae29a --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_m_sync.h @@ -0,0 +1,185 @@ +/** + * \file + * + * \brief I2C Master Hardware Proxy Layer(HPL) declaration. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#ifndef _HPL_I2C_M_SYNC_H_INCLUDED +#define _HPL_I2C_M_SYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief i2c flags + */ +#define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_BUSY 0x0100 +#define I2C_M_TEN 0x0400 /* this is a ten bit chip address */ +#define I2C_M_SEVEN 0x0800 /* this is a seven bit chip address */ +#define I2C_M_FAIL 0x1000 +#define I2C_M_STOP 0x8000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + +/** + * \brief i2c Return codes + */ +#define I2C_OK 0 /* Operation successful */ +#define I2C_ACK -1 /* Received ACK from device on I2C bus */ +#define I2C_NACK -2 /* Received NACK from device on I2C bus */ +#define I2C_ERR_ARBLOST -3 /* Arbitration lost */ +#define I2C_ERR_BAD_ADDRESS -4 /* Bad address */ +#define I2C_ERR_BUS -5 /* Bus error */ +#define I2C_ERR_BUSY -6 /* Device busy */ +#define I2c_ERR_PACKAGE_COLLISION -7 /* Package collision */ + +/** + * \brief i2c I2C Modes + */ +#define I2C_STANDARD_MODE 0x00 +#define I2C_FASTMODE 0x01 +#define I2C_HIGHSPEED_MODE 0x02 + +/** + * \brief i2c master message structure + */ +struct _i2c_m_msg { + uint16_t addr; + volatile uint16_t flags; + int32_t len; + uint8_t * buffer; +}; + +/** + * \brief i2c master service + */ +struct _i2c_m_service { + struct _i2c_m_msg msg; + uint16_t mode; + uint16_t trise; +}; + +/** + * \brief i2c sync master device structure + */ +struct _i2c_m_sync_device { + struct _i2c_m_service service; + void * hw; +}; + +/** + * \name HPL functions + */ + +/** + * \brief Initialize I2C + * + * This function does low level I2C configuration. + * + * \param[in] i2c_dev The pointer to i2c device structure + * \param[in] hw The pointer to hardware instance + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const i2c_dev, void *const hw); + +/** + * \brief Deinitialize I2C + * + * \param[in] i2c_dev The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const i2c_dev); + +/** + * \brief Enable I2C module + * + * This function does low level I2C enable. + * + * \param[in] i2c_dev The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const i2c_dev); + +/** + * \brief Disable I2C module + * + * This function does low level I2C disable. + * + * \param[in] i2c_dev The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const i2c_dev); + +/** + * \brief Transfer data by I2C + * + * This function does low level I2C data transfer. + * + * \param[in] i2c_dev The pointer to i2c device structure + * \param[in] msg The pointer to i2c msg structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const i2c_dev, struct _i2c_m_msg *msg); + +/** + * \brief Set baud rate of I2C + * + * This function does low level I2C set baud rate. + * + * \param[in] i2c_dev The pointer to i2c device structure + * \param[in] clkrate The clock rate(KHz) input to i2c module + * \param[in] baudrate The demand baud rate(KHz) of i2c module + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const i2c_dev, uint32_t clkrate, uint32_t baudrate); + +/** + * \brief Send send condition on the I2C bus + * + * This function will generate a stop condition on the I2C bus + * + * \param[in] i2c_dev The pointer to i2c device struct + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const i2c_dev); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_async.h b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_async.h new file mode 100644 index 0000000000..92a5765d16 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_async.h @@ -0,0 +1,184 @@ +/** + * \file + * + * \brief I2C Slave Hardware Proxy Layer(HPL) declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#ifndef _HPL_I2C_S_ASYNC_H_INCLUDED +#define _HPL_I2C_S_ASYNC_H_INCLUDED + +#include "hpl_i2c_s_sync.h" +#include "hpl_irq.h" +#include "utils.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief i2c callback types + */ +enum _i2c_s_async_callback_type { I2C_S_DEVICE_ERROR, I2C_S_DEVICE_TX, I2C_S_DEVICE_RX_COMPLETE }; + +/** + * \brief Forward declaration of I2C Slave device + */ +struct _i2c_s_async_device; + +/** + * \brief i2c slave callback function type + */ +typedef void (*_i2c_s_async_cb_t)(struct _i2c_s_async_device *device); + +/** + * \brief i2c slave callback pointers structure + */ +struct _i2c_s_async_callback { + void (*error)(struct _i2c_s_async_device *const device); + void (*tx)(struct _i2c_s_async_device *const device); + void (*rx_done)(struct _i2c_s_async_device *const device, const uint8_t data); +}; + +/** + * \brief i2c slave device structure + */ +struct _i2c_s_async_device { + void * hw; + struct _i2c_s_async_callback cb; + struct _irq_descriptor irq; +}; + +/** + * \name HPL functions + */ + +/** + * \brief Initialize asynchronous I2C slave + * + * This function does low level I2C configuration. + * + * \param[in] device The pointer to i2c interrupt device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_async_init(struct _i2c_s_async_device *const device, void *const hw); + +/** + * \brief Deinitialize asynchronous I2C in interrupt mode + * + * \param[in] device The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_async_deinit(struct _i2c_s_async_device *const device); + +/** + * \brief Enable I2C module + * + * This function does low level I2C enable. + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_async_enable(struct _i2c_s_async_device *const device); + +/** + * \brief Disable I2C module + * + * This function does low level I2C disable. + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_async_disable(struct _i2c_s_async_device *const device); + +/** + * \brief Check if 10-bit addressing mode is on + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Cheking status + * \retval 1 10-bit addressing mode is on + * \retval 0 10-bit addressing mode is off + */ +int32_t _i2c_s_async_is_10bit_addressing_on(const struct _i2c_s_async_device *const device); + +/** + * \brief Set I2C slave address + * + * \param[in] device The pointer to i2c slave device structure + * \param[in] address Address to set + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_async_set_address(struct _i2c_s_async_device *const device, const uint16_t address); + +/** + * \brief Write a byte to the given I2C instance + * + * \param[in] device The pointer to i2c slave device structure + * \param[in] data Data to write + */ +void _i2c_s_async_write_byte(struct _i2c_s_async_device *const device, const uint8_t data); + +/** + * \brief Retrieve I2C slave status + * + * \param[in] device The pointer to i2c slave device structure + * + *\return I2C slave status + */ +i2c_s_status_t _i2c_s_async_get_status(const struct _i2c_s_async_device *const device); + +/** + * \brief Abort data transmission + * + * \param[in] device The pointer to i2c device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_async_abort_transmission(const struct _i2c_s_async_device *const device); + +/** + * \brief Enable/disable I2C slave interrupt + * + * param[in] device The pointer to I2C slave device instance + * param[in] type The type of interrupt to disable/enable if applicable + * param[in] disable Enable or disable + */ +int32_t _i2c_s_async_set_irq_state(struct _i2c_s_async_device *const device, const enum _i2c_s_async_callback_type type, + const bool disable); + +#ifdef __cplusplus +} +#endif + +#endif /* _HPL_I2C_S_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_sync.h b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_sync.h new file mode 100644 index 0000000000..93b593456c --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_i2c_s_sync.h @@ -0,0 +1,184 @@ +/** + * \file + * + * \brief I2C Slave Hardware Proxy Layer(HPL) declaration. + * + * Copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#ifndef _HPL_I2C_S_SYNC_H_INCLUDED +#define _HPL_I2C_S_SYNC_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief I2C Slave status type + */ +typedef uint32_t i2c_s_status_t; + +/** + * \brief i2c slave device structure + */ +struct _i2c_s_sync_device { + void *hw; +}; + +#include + +/** + * \name HPL functions + */ + +/** + * \brief Initialize synchronous I2C slave + * + * This function does low level I2C configuration. + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_sync_init(struct _i2c_s_sync_device *const device, void *const hw); + +/** + * \brief Deinitialize synchronous I2C slave + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_sync_deinit(struct _i2c_s_sync_device *const device); + +/** + * \brief Enable I2C module + * + * This function does low level I2C enable. + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_sync_enable(struct _i2c_s_sync_device *const device); + +/** + * \brief Disable I2C module + * + * This function does low level I2C disable. + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_sync_disable(struct _i2c_s_sync_device *const device); + +/** + * \brief Check if 10-bit addressing mode is on + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Cheking status + * \retval 1 10-bit addressing mode is on + * \retval 0 10-bit addressing mode is off + */ +int32_t _i2c_s_sync_is_10bit_addressing_on(const struct _i2c_s_sync_device *const device); + +/** + * \brief Set I2C slave address + * + * \param[in] device The pointer to i2c slave device structure + * \param[in] address Address to set + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_sync_set_address(struct _i2c_s_sync_device *const device, const uint16_t address); + +/** + * \brief Write a byte to the given I2C instance + * + * \param[in] device The pointer to i2c slave device structure + * \param[in] data Data to write + */ +void _i2c_s_sync_write_byte(struct _i2c_s_sync_device *const device, const uint8_t data); + +/** + * \brief Retrieve I2C slave status + * + * \param[in] device The pointer to i2c slave device structure + * + *\return I2C slave status + */ +i2c_s_status_t _i2c_s_sync_get_status(const struct _i2c_s_sync_device *const device); + +/** + * \brief Clear the Data Ready interrupt flag + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Return 0 for success and negative value for error + */ +int32_t _i2c_s_sync_clear_data_ready_flag(const struct _i2c_s_sync_device *const device); + +/** + * \brief Read a byte from the given I2C instance + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Data received via I2C interface. + */ +uint8_t _i2c_s_sync_read_byte(const struct _i2c_s_sync_device *const device); + +/** + * \brief Check if I2C is ready to send next byte + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Status of the ready check. + * \retval true if the I2C is ready to send next byte + * \retval false if the I2C is not ready to send next byte + */ +bool _i2c_s_sync_is_byte_sent(const struct _i2c_s_sync_device *const device); + +/** + * \brief Check if there is data received by I2C + * + * \param[in] device The pointer to i2c slave device structure + * + * \return Status of the data received check. + * \retval true if the I2C has received a byte + * \retval false if the I2C has not received a byte + */ +bool _i2c_s_sync_is_byte_received(const struct _i2c_s_sync_device *const device); + +#ifdef __cplusplus +} +#endif + +#endif /* _HPL_I2C_S_SYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/include/hpl_mac_async.h b/bsp/microchip/same70/bsp/hal/include/hpl_mac_async.h new file mode 100644 index 0000000000..20802ef9d6 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/include/hpl_mac_async.h @@ -0,0 +1,280 @@ +/** + * \file + * + * \brief MAC functionality declaration. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#ifndef HPL_MAC_ASYNC_H_INCLUDED +#define HPL_MAC_ASYNC_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +/** + * \addtogroup hpl__mac__async__group MAC HPL APIs + * + *@{ + */ + +/** + * \brief MAC device descriptor Forward declaration + */ +struct _mac_async_device; + +/** + * \brief MAC callback type + * + * \param[in] dev An MAC device descriptor + */ +typedef void (*_mac_async_cb_t)(struct _mac_async_device *const dev); + +/** + * \brief MAC callbacks + */ +struct _mac_async_callbacks { + _mac_async_cb_t transmited; /*!< Frame received */ + _mac_async_cb_t received; /*!< Frame transmited */ +}; + +/** + * \brief MAC device descriptor + */ +struct _mac_async_device { + void * hw; /*!< Hardware module instance handler */ + struct _mac_async_callbacks cb; /*!< Callback handler */ + struct _irq_descriptor irq; /*!< IRQ handler */ +}; + +/** + * \brief MAC callback types + */ +enum mac_async_cb_type { + MAC_ASYNC_RECEIVE_CB, /*!< One or more frame been received */ + MAC_ASYNC_TRANSMIT_CB /*!< One or more frame been transmited */ +}; + +struct mac_async_filter { + uint8_t mac[6]; /*!< Destination address */ + uint8_t tid[2]; /*!< Type ID, 0x0600 IP package */ + bool tid_enable; /*!< Enable TID matching */ +}; +/** + * \brief Initialize the MAC driver + * + * Initialize the MAC driver + * + * \param[in] dev A MAC device descriptor to deinit + * \param[in] hw Hardware module instance + * + * \return Operation status. + * \retval ERR_NONE Success. + + */ +int32_t _mac_async_init(struct _mac_async_device *const dev, void *const hw); + +/** + * \brief Deinitialize the MAC driver + * + * Deinitialize the MAC driver + * + * \param[in] descr A MAC device descriptor to deinit + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_deinit(struct _mac_async_device *const dev); + +/** \brief Enable the MAC + * + * Enable the MAC + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_enable(struct _mac_async_device *const dev); + +/** + * \brief Disable the MAC + * + * Disable the MAC + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_disable(struct _mac_async_device *const dev); + +/** + * \brief Write raw data to MAC + * + * Write raw data to MAC that will be transmitted. + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] buffer Pointer to the data buffer + * \param[in] length Length of the data buffer + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_write(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len); + +/** + * \brief Read received raw data from MAC + * + * Read received raw data from MAC + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] buffer Pointer to the data buffer. if pointer is null, then the + * frame will be discard. + * \param[in] length Max Length of the data buffer to be read. if len is zero, + * then the frame will be discard + * + * \return Number of bytes that have been received + */ +uint32_t _mac_async_read(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len); + +/** + * \brief Get next valid package length + * + * Get next valid package length from MAC. Application can use this function + * to fetch the length of the next package, malloc the a buffer whit this + * length, and then invoke mac_async_read to read out the package data. + * + * \param[in] dev Pointer to the HPL MAC device descriptor. + * + * \return Number of bytes that next package can be read. + */ +uint32_t _mac_async_read_len(struct _mac_async_device *const dev); + +/** + * \brief Enable the MAC IRQ + * + * Enable the MAC IRQ + * + * \param[in] dev Pointer to the HPL MAC device descriptor + */ +void _mac_async_enable_irq(struct _mac_async_device *const dev); + +/** + * \brief Disable the MAC IRQ + * + * Disable the MAC IRQ + * + * \param[in] dev Pointer to the HPL MAC device descriptor + */ +void _mac_async_disable_irq(struct _mac_async_device *const dev); + +/** + * \brief Register the MAC callback + * + * Register the MAC callback + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] type Callback function type. + * \param[in] func A callback function, passing NULL will de-register + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_register_callback(struct _mac_async_device *const dev, const enum mac_async_cb_type type, + const FUNC_PTR func); + +/** + * \brief Set MAC filter + * + * Set MAC filter, ethernet frames which match the filter will be received. + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] index Mac filter index, start from 0, max value depends on + * hardware specificaions. + * \param[in] filter Pointer to the filter descriptor. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_set_filter(struct _mac_async_device *const dev, uint8_t index, struct mac_async_filter *filter); + +/** + * \brief Set MAC filter (expaneded) + * + * Set MAC filter, ethernet frames which match the filter will be received. + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] mac Mac address + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_set_filter_ex(struct _mac_async_device *const dev, uint8_t mac[6]); + +/** + * \brief Write PHY register + * + * Write PHY register + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] data Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_write_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t data); + +/** + * \brief Read PHY register + * + * Read PHY register + * + * \param[in] dev Pointer to the HPL MAC device descriptor + * \param[in] addr PHY address. + * \param[in] reg Register address. + * \param[in] data Register value. + * + * \return Operation status. + * \retval ERR_NONE Success. + */ +int32_t _mac_async_read_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t *val); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* HPL_MAC_ASYNC_H_INCLUDED */ diff --git a/bsp/microchip/same70/bsp/hal/src/hal_adc_sync.c b/bsp/microchip/same70/bsp/hal/src/hal_adc_sync.c new file mode 100644 index 0000000000..33e0d92976 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/src/hal_adc_sync.c @@ -0,0 +1,244 @@ +/** + * \file + * + * \brief ADC functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +/** + * \brief Indicates HAL being compiled. Must be defined before including. + */ +#define _COMPILING_HAL + +#include "hal_adc_sync.h" +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Maximum amount of ADC interface instances + */ +#define MAX_ADC_AMOUNT ADC_INST_NUM + +/** + * \brief Initialize ADC + */ +int32_t adc_sync_init(struct adc_sync_descriptor *const descr, void *const hw, void *const func) +{ + ASSERT(descr && hw); + + return _adc_sync_init(&descr->device, hw); +} + +/** + * \brief Deinitialize ADC + */ +int32_t adc_sync_deinit(struct adc_sync_descriptor *const descr) +{ + ASSERT(descr); + _adc_sync_deinit(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Enable ADC + */ +int32_t adc_sync_enable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_enable_channel(&descr->device, channel); + + return ERR_NONE; +} + +/** + * \brief Disable ADC + */ +int32_t adc_sync_disable_channel(struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_disable_channel(&descr->device, channel); + return ERR_NONE; +} + +/* + * \brief Read data from ADC + */ +int32_t adc_sync_read_channel(struct adc_sync_descriptor *const descr, const uint8_t channel, uint8_t *const buffer, + const uint16_t length) +{ + uint8_t data_size; + uint16_t offset = 0; + + ASSERT(descr && buffer && length); + data_size = _adc_sync_get_data_size(&descr->device); + ASSERT(!(length % data_size)); + + do { + uint16_t result; + _adc_sync_convert(&descr->device); + + while (!_adc_sync_is_channel_conversion_done(&descr->device, channel)) + ; + + result = _adc_sync_read_channel_data(&descr->device, channel); + buffer[offset] = result; + if (1 < data_size) { + buffer[offset + 1] = result >> 8; + } + offset += data_size; + } while (offset < length); + + return offset; +} + +/** + * \brief Set ADC reference source + */ +int32_t adc_sync_set_reference(struct adc_sync_descriptor *const descr, const adc_reference_t reference) +{ + ASSERT(descr); + _adc_sync_set_reference_source(&descr->device, reference); + + return ERR_NONE; +} + +/** + * \brief Set ADC resolution + */ +int32_t adc_sync_set_resolution(struct adc_sync_descriptor *const descr, const adc_resolution_t resolution) +{ + ASSERT(descr); + _adc_sync_set_resolution(&descr->device, resolution); + + return ERR_NONE; +} + +/** + * \brief Set ADC input source of a channel + */ +int32_t adc_sync_set_inputs(struct adc_sync_descriptor *const descr, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + ASSERT(descr); + _adc_sync_set_inputs(&descr->device, pos_input, neg_input, channel); + + return ERR_NONE; +} + +/** + * \brief Set ADC thresholds + */ +int32_t adc_sync_set_thresholds(struct adc_sync_descriptor *const descr, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + ASSERT(descr); + _adc_sync_set_thresholds(&descr->device, low_threshold, up_threshold); + + return ERR_NONE; +} + +/** + * \brief Set ADC gain + */ +int32_t adc_sync_set_channel_gain(struct adc_sync_descriptor *const descr, const uint8_t channel, const adc_gain_t gain) +{ + ASSERT(descr); + _adc_sync_set_channel_gain(&descr->device, channel, gain); + + return ERR_NONE; +} + +/** + * \brief Set ADC conversion mode + */ +int32_t adc_sync_set_conversion_mode(struct adc_sync_descriptor *const descr, const enum adc_conversion_mode mode) +{ + ASSERT(descr); + _adc_sync_set_conversion_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC differential mode + */ +int32_t adc_sync_set_channel_differential_mode(struct adc_sync_descriptor *const descr, const uint8_t channel, + const enum adc_differential_mode mode) +{ + ASSERT(descr); + _adc_sync_set_channel_differential_mode(&descr->device, channel, mode); + + return ERR_NONE; +} + +/** + * \brief Set ADC window mode + */ +int32_t adc_sync_set_window_mode(struct adc_sync_descriptor *const descr, const adc_window_mode_t mode) +{ + ASSERT(descr); + _adc_sync_set_window_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Retrieve threshold state + */ +int32_t adc_sync_get_threshold_state(const struct adc_sync_descriptor *const descr, adc_threshold_status_t *const state) +{ + ASSERT(descr && state); + _adc_sync_get_threshold_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Check if conversion is complete + */ +int32_t adc_sync_is_channel_conversion_complete(const struct adc_sync_descriptor *const descr, const uint8_t channel) +{ + ASSERT(descr); + return _adc_sync_is_channel_conversion_done(&descr->device, channel); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t adc_sync_get_version(void) +{ + return DRIVER_VERSION; +} + +//@} diff --git a/bsp/microchip/same70/bsp/hal/src/hal_i2c_m_sync.c b/bsp/microchip/same70/bsp/hal/src/hal_i2c_m_sync.c new file mode 100644 index 0000000000..30821a27c3 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/src/hal_i2c_m_sync.c @@ -0,0 +1,258 @@ +/** + * \file + * + * \brief I/O I2C related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include +#include +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/** + * \brief Sync version of I2C I/O read + */ +static int32_t i2c_m_sync_read(struct io_descriptor *io, uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of I2C I/O write + */ +static int32_t i2c_m_sync_write(struct io_descriptor *io, const uint8_t *buf, const uint16_t n) +{ + struct i2c_m_sync_desc *i2c = CONTAINER_OF(io, struct i2c_m_sync_desc, io); + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = n; + msg.flags = I2C_M_STOP; + msg.buffer = (uint8_t *)buf; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret) { + return ret; + } + + return n; +} + +/** + * \brief Sync version of i2c initialize + */ +int32_t i2c_m_sync_init(struct i2c_m_sync_desc *i2c, void *hw) +{ + int32_t init_status; + ASSERT(i2c); + + init_status = _i2c_m_sync_init(&i2c->device, hw); + if (init_status) { + return init_status; + } + + /* Init I/O */ + i2c->io.read = i2c_m_sync_read; + i2c->io.write = i2c_m_sync_write; + + return ERR_NONE; +} + +/** + * \brief deinitialize + */ +int32_t i2c_m_sync_deinit(struct i2c_m_sync_desc *i2c) +{ + int32_t status; + ASSERT(i2c); + + status = _i2c_m_sync_deinit(&i2c->device); + if (status) { + return status; + } + + i2c->io.read = NULL; + i2c->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c enable + */ +int32_t i2c_m_sync_enable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_enable(&i2c->device); +} + +/** + * \brief Sync version of i2c disable + */ +int32_t i2c_m_sync_disable(struct i2c_m_sync_desc *i2c) +{ + return _i2c_m_sync_disable(&i2c->device); +} + +/** + * \brief Sync version of i2c set slave address + */ +int32_t i2c_m_sync_set_slaveaddr(struct i2c_m_sync_desc *i2c, int16_t addr, int32_t addr_len) +{ + return i2c->slave_addr = (addr & 0x3ff) | (addr_len & I2C_M_TEN); +} + +/** + * \brief Sync version of i2c set baudrate + */ +int32_t i2c_m_sync_set_baudrate(struct i2c_m_sync_desc *i2c, uint32_t clkrate, uint32_t baudrate) +{ + return _i2c_m_sync_set_baudrate(&i2c->device, clkrate, baudrate); +} + +/** + * \brief Sync version of i2c write command + */ +int32_t i2c_m_sync_cmd_write(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c read command + */ +int32_t i2c_m_sync_cmd_read(struct i2c_m_sync_desc *i2c, uint8_t reg, uint8_t *buffer, uint8_t length) +{ + struct _i2c_m_msg msg; + int32_t ret; + + msg.addr = i2c->slave_addr; + msg.len = 1; + msg.flags = 0; + msg.buffer = ® + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + msg.flags = I2C_M_STOP | I2C_M_RD; + msg.buffer = buffer; + msg.len = length; + + ret = _i2c_m_sync_transfer(&i2c->device, &msg); + + if (ret != 0) { + /* error occurred */ + return ret; + } + + return ERR_NONE; +} + +/** + * \brief Sync version of i2c transfer command + */ +int32_t i2c_m_sync_transfer(struct i2c_m_sync_desc *const i2c, struct _i2c_m_msg *msg) +{ + return _i2c_m_sync_transfer(&i2c->device, msg); +} + +/** + * \brief Sync version of i2c send stop condition command + */ +int32_t i2c_m_sync_send_stop(struct i2c_m_sync_desc *const i2c) +{ + return _i2c_m_sync_send_stop(&i2c->device); +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t i2c_m_sync_get_io_descriptor(struct i2c_m_sync_desc *const i2c, struct io_descriptor **io) +{ + *io = &i2c->io; + return ERR_NONE; +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t i2c_m_sync_get_version(void) +{ + return DRIVER_VERSION; +} diff --git a/bsp/microchip/same70/bsp/hal/src/hal_mac_async.c b/bsp/microchip/same70/bsp/hal/src/hal_mac_async.c new file mode 100644 index 0000000000..a7512c8bee --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/src/hal_mac_async.c @@ -0,0 +1,222 @@ +/** + * \file + * + * \brief MAC functionality implementation. + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ +#include +#include +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +/* Private function */ +static void mac_read_cb(struct _mac_async_device *dev); +static void mac_write_cb(struct _mac_async_device *dev); + +/** + * \brief Initialize the MAC driver + */ +int32_t mac_async_init(struct mac_async_descriptor *const descr, void *const hw) +{ + ASSERT(descr && hw); + + return _mac_async_init(&descr->dev, hw); +} + +/** + * \brief Deinitialize the MAC driver + */ +int32_t mac_async_deinit(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_deinit(&descr->dev); +} + +/** + * \brief Enable the MAC + */ +int32_t mac_async_enable(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_enable(&descr->dev); +} +/** + * \brief Disable the MAC + */ +int32_t mac_async_disable(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_disable(&descr->dev); +} +/** + * \brief Write raw data to MAC + */ +int32_t mac_async_write(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len) +{ + ASSERT(descr && buf && len); + + return _mac_async_write(&descr->dev, buf, len); +} + +/** + * \brief Read raw data from MAC + */ +uint32_t mac_async_read(struct mac_async_descriptor *const descr, uint8_t *buf, uint32_t len) +{ + ASSERT(descr); + + return _mac_async_read(&descr->dev, buf, len); +} + +/** + * \brief Get next valid package length + */ +uint32_t mac_async_read_len(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + return _mac_async_read_len(&descr->dev); +} +/** + * \brief Enable the MAC IRQ + */ +void mac_async_enable_irq(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + _mac_async_enable_irq(&descr->dev); +} + +/** + * \brief Disable the MAC IRQ + */ +void mac_async_disable_irq(struct mac_async_descriptor *const descr) +{ + ASSERT(descr); + + _mac_async_disable_irq(&descr->dev); +} + +/** + * \brief Register the MAC callback function + */ +int32_t mac_async_register_callback(struct mac_async_descriptor *const descr, const enum mac_async_cb_type type, + const FUNC_PTR func) +{ + ASSERT(descr); + + switch (type) { + case MAC_ASYNC_RECEIVE_CB: + descr->cb.receive = (mac_async_cb_t)func; + return _mac_async_register_callback(&descr->dev, type, (func == NULL) ? NULL : (FUNC_PTR)mac_read_cb); + case MAC_ASYNC_TRANSMIT_CB: + descr->cb.transmit = (mac_async_cb_t)func; + return _mac_async_register_callback(&descr->dev, type, (func == NULL) ? NULL : (FUNC_PTR)mac_write_cb); + default: + return ERR_INVALID_ARG; + } +} +/** + * \brief Set MAC filter + */ +int32_t mac_async_set_filter(struct mac_async_descriptor *const descr, uint8_t index, struct mac_async_filter *filter) +{ + ASSERT(descr && filter); + + return _mac_async_set_filter(&descr->dev, index, filter); +} + +/** + * \brief Set MAC filter (expaneded) + */ +int32_t mac_async_set_filter_ex(struct mac_async_descriptor *const descr, uint8_t mac[6]) +{ + ASSERT(descr && mac); + + return _mac_async_set_filter_ex(&descr->dev, mac); +} + +/** + * \brief Write PHY register + */ +int32_t mac_async_write_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t val) +{ + ASSERT(descr); + + return _mac_async_write_phy_reg(&descr->dev, addr, reg, val); +} +/** + * \brief Read PHY register + */ +int32_t mac_async_read_phy_reg(struct mac_async_descriptor *const descr, uint16_t addr, uint16_t reg, uint16_t *val) +{ + ASSERT(descr && val); + + return _mac_async_read_phy_reg(&descr->dev, addr, reg, val); +} +/** + * \brief Get MAC driver version + */ +uint32_t mac_async_get_version(void) +{ + return DRIVER_VERSION; +} + +/** + * \internal data receivced handler + * + * \param[in] dev The pointer to MAC device structure + */ +static void mac_read_cb(struct _mac_async_device *dev) +{ + struct mac_async_descriptor *const descr = CONTAINER_OF(dev, struct mac_async_descriptor, dev); + + if (descr->cb.receive) { + descr->cb.receive(descr); + } +} + +/** + * \internal data transmit handler + * + * \param[in] dev The pointer to MAC device structure + */ +static void mac_write_cb(struct _mac_async_device *dev) +{ + struct mac_async_descriptor *const descr = CONTAINER_OF(dev, struct mac_async_descriptor, dev); + + if (descr->cb.transmit) { + descr->cb.transmit(descr); + } +} diff --git a/bsp/microchip/same70/bsp/hal/src/hal_sleep.c b/bsp/microchip/same70/bsp/hal/src/hal_sleep.c index 89472f156a..5decfb6c9c 100644 --- a/bsp/microchip/same70/bsp/hal/src/hal_sleep.c +++ b/bsp/microchip/same70/bsp/hal/src/hal_sleep.c @@ -38,7 +38,7 @@ * \brief Driver version */ #define DRIVER_VERSION 0x00000001u - +#if 0 /** * \brief Set the sleep mode of the device and put the MCU to sleep * @@ -61,7 +61,7 @@ int sleep(const uint8_t mode) return ERR_NONE; } - +#endif /** * \brief Retrieve the current driver version * diff --git a/bsp/microchip/same70/bsp/hal/src/hal_usart_async.c b/bsp/microchip/same70/bsp/hal/src/hal_usart_async.c new file mode 100644 index 0000000000..f07b266124 --- /dev/null +++ b/bsp/microchip/same70/bsp/hal/src/hal_usart_async.c @@ -0,0 +1,420 @@ +/** + * \file + * + * \brief I/O USART related functionality implementation. + * + * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include "hal_usart_async.h" +#include +#include +#include + +/** + * \brief Driver version + */ +#define DRIVER_VERSION 0x00000001u + +static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length); +static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length); +static void usart_process_byte_sent(struct _usart_async_device *device); +static void usart_transmission_complete(struct _usart_async_device *device); +static void usart_error(struct _usart_async_device *device); +static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data); + +/** + * \brief Initialize usart interface + */ +int32_t usart_async_init(struct usart_async_descriptor *const descr, void *const hw, uint8_t *rx_buffer, + uint16_t rx_buffer_length, void *const func) +{ + int32_t init_status; + ASSERT(descr && hw && rx_buffer && rx_buffer_length); + + if (ERR_NONE != ringbuffer_init(&descr->rx, rx_buffer, rx_buffer_length)) { + return ERR_INVALID_ARG; + } + init_status = _usart_async_init(&descr->device, hw); + if (init_status) { + return init_status; + } + + descr->io.read = usart_async_read; + descr->io.write = usart_async_write; + + descr->device.usart_cb.tx_byte_sent = usart_process_byte_sent; + descr->device.usart_cb.rx_done_cb = usart_fill_rx_buffer; + descr->device.usart_cb.tx_done_cb = usart_transmission_complete; + descr->device.usart_cb.error_cb = usart_error; + + return ERR_NONE; +} + +/** + * \brief Deinitialize usart interface + */ +int32_t usart_async_deinit(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_deinit(&descr->device); + descr->io.read = NULL; + descr->io.write = NULL; + + return ERR_NONE; +} + +/** + * \brief Enable usart interface + */ +int32_t usart_async_enable(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_enable(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Disable usart interface + */ +int32_t usart_async_disable(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + _usart_async_disable(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Retrieve I/O descriptor + */ +int32_t usart_async_get_io_descriptor(struct usart_async_descriptor *const descr, struct io_descriptor **io) +{ + ASSERT(descr && io); + + *io = &descr->io; + return ERR_NONE; +} + +/** + * \brief Register usart callback + */ +int32_t usart_async_register_callback(struct usart_async_descriptor *const descr, + const enum usart_async_callback_type type, usart_cb_t cb) +{ + ASSERT(descr); + + switch (type) { + case USART_ASYNC_RXC_CB: + descr->usart_cb.rx_done = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_RX_DONE, NULL != cb); + break; + case USART_ASYNC_TXC_CB: + descr->usart_cb.tx_done = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_TX_DONE, NULL != cb); + break; + case USART_ASYNC_ERROR_CB: + descr->usart_cb.error = cb; + _usart_async_set_irq_state(&descr->device, USART_ASYNC_ERROR, NULL != cb); + break; + default: + return ERR_INVALID_ARG; + } + + return ERR_NONE; +} + +/** + * \brief Specify action for flow control pins + */ +int32_t usart_async_set_flow_control(struct usart_async_descriptor *const descr, + const union usart_flow_control_state state) +{ + ASSERT(descr); + _usart_async_set_flow_control_state(&descr->device, state); + + return ERR_NONE; +} + +/** + * \brief Set usart baud rate + */ +int32_t usart_async_set_baud_rate(struct usart_async_descriptor *const descr, const uint32_t baud_rate) +{ + ASSERT(descr); + _usart_async_set_baud_rate(&descr->device, baud_rate); + + return ERR_NONE; +} + +/** + * \brief Set usart data order + */ +int32_t usart_async_set_data_order(struct usart_async_descriptor *const descr, const enum usart_data_order data_order) +{ + ASSERT(descr); + _usart_async_set_data_order(&descr->device, data_order); + + return ERR_NONE; +} + +/** + * \brief Set usart mode + */ +int32_t usart_async_set_mode(struct usart_async_descriptor *const descr, const enum usart_mode mode) +{ + ASSERT(descr); + _usart_async_set_mode(&descr->device, mode); + + return ERR_NONE; +} + +/** + * \brief Set usart parity + */ +int32_t usart_async_set_parity(struct usart_async_descriptor *const descr, const enum usart_parity parity) +{ + ASSERT(descr); + _usart_async_set_parity(&descr->device, parity); + + return ERR_NONE; +} + +/** + * \brief Set usart stop bits + */ +int32_t usart_async_set_stopbits(struct usart_async_descriptor *const descr, const enum usart_stop_bits stop_bits) +{ + ASSERT(descr); + _usart_async_set_stop_bits(&descr->device, stop_bits); + + return ERR_NONE; +} + +/** + * \brief Set usart character size + */ +int32_t usart_async_set_character_size(struct usart_async_descriptor *const descr, const enum usart_character_size size) +{ + ASSERT(descr); + _usart_async_set_character_size(&descr->device, size); + + return ERR_NONE; +} + +/** + * \brief Retrieve the state of flow control pins + */ +int32_t usart_async_flow_control_status(const struct usart_async_descriptor *const descr, + union usart_flow_control_state *const state) +{ + ASSERT(descr && state); + *state = _usart_async_get_flow_control_state(&descr->device); + + return ERR_NONE; +} + +/** + * \brief Check if the usart transmitter is empty + */ +int32_t usart_async_is_tx_empty(const struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + return _usart_async_is_byte_sent(&descr->device); +} + +/** + * \brief Check if the usart receiver is not empty + */ +int32_t usart_async_is_rx_not_empty(const struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + + return ringbuffer_num(&descr->rx) > 0; +} + +/** + * \brief Retrieve the current interface status + */ +int32_t usart_async_get_status(struct usart_async_descriptor *const descr, struct usart_async_status *const status) +{ + ASSERT(descr); + + volatile uint32_t *tmp_stat = &(descr->stat); + volatile uint16_t *tmp_txcnt = &(descr->tx_por); + + if (status) { + status->flags = *tmp_stat; + status->txcnt = *tmp_txcnt; + status->rxcnt = ringbuffer_num(&descr->rx); + } + if (*tmp_stat & USART_ASYNC_STATUS_BUSY) { + return ERR_BUSY; + } + + return ERR_NONE; +} + +/** + * \brief flush usart rx ringbuf + */ +int32_t usart_async_flush_rx_buffer(struct usart_async_descriptor *const descr) +{ + ASSERT(descr); + + return ringbuffer_flush(&descr->rx); +} + +/** + * \brief Retrieve the current driver version + */ +uint32_t usart_async_get_version(void) +{ + return DRIVER_VERSION; +} + +/* + * \internal Write the given data to usart interface + * + * \param[in] descr The pointer to an io descriptor + * \param[in] buf Data to write to usart + * \param[in] length The number of bytes to write + * + * \return The number of bytes written. + */ +static int32_t usart_async_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io); + + ASSERT(descr && buf && length); + + if (descr->tx_por != descr->tx_buffer_length) { + return ERR_NO_RESOURCE; + } + descr->tx_buffer = (uint8_t *)buf; + descr->tx_buffer_length = length; + descr->tx_por = 0; + descr->stat = USART_ASYNC_STATUS_BUSY; + _usart_async_enable_byte_sent_irq(&descr->device); + + return (int32_t)length; +} + +/* + * \internal Read data from usart interface + * + * \param[in] descr The pointer to an io descriptor + * \param[in] buf A buffer to read data to + * \param[in] length The size of a buffer + * + * \return The number of bytes read. + */ +static int32_t usart_async_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) +{ + uint16_t was_read = 0; + uint32_t num; + struct usart_async_descriptor *descr = CONTAINER_OF(io_descr, struct usart_async_descriptor, io); + + ASSERT(descr && buf && length); + + CRITICAL_SECTION_ENTER() + num = ringbuffer_num(&descr->rx); + CRITICAL_SECTION_LEAVE() + + while ((was_read < num) && (was_read < length)) { + ringbuffer_get(&descr->rx, &buf[was_read++]); + } + + return (int32_t)was_read; +} + +/** + * \brief Process "byte is sent" interrupt + * + * \param[in] device The pointer to device structure + */ +static void usart_process_byte_sent(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + if (descr->tx_por != descr->tx_buffer_length) { + _usart_async_write_byte(&descr->device, descr->tx_buffer[descr->tx_por++]); + _usart_async_enable_byte_sent_irq(&descr->device); + } else { + _usart_async_enable_tx_done_irq(&descr->device); + } +} + +/** + * \brief Process completion of data sending + * + * \param[in] device The pointer to device structure + */ +static void usart_transmission_complete(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + descr->stat = 0; + if (descr->usart_cb.tx_done) { + descr->usart_cb.tx_done(descr); + } +} + +/** + * \brief Process byte reception + * + * \param[in] device The pointer to device structure + * \param[in] data Data read + */ +static void usart_fill_rx_buffer(struct _usart_async_device *device, uint8_t data) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + ringbuffer_put(&descr->rx, data); + + if (descr->usart_cb.rx_done) { + descr->usart_cb.rx_done(descr); + } +} + +/** + * \brief Process error interrupt + * + * \param[in] device The pointer to device structure + */ +static void usart_error(struct _usart_async_device *device) +{ + struct usart_async_descriptor *descr = CONTAINER_OF(device, struct usart_async_descriptor, device); + + descr->stat = 0; + if (descr->usart_cb.error) { + descr->usart_cb.error(descr); + } +} + +//@} diff --git a/bsp/microchip/same70/bsp/hal/src/hal_usart_sync.c b/bsp/microchip/same70/bsp/hal/src/hal_usart_sync.c deleted file mode 100644 index ab99c1d166..0000000000 --- a/bsp/microchip/same70/bsp/hal/src/hal_usart_sync.c +++ /dev/null @@ -1,276 +0,0 @@ -/** - * \file - * - * \brief I/O USART related functionality implementation. - * - * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#include "hal_usart_sync.h" -#include -#include - -/** - * \brief Driver version - */ -#define DRIVER_VERSION 0x00000001u - -static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length); -static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length); - -/** - * \brief Initialize usart interface - */ -int32_t usart_sync_init(struct usart_sync_descriptor *const descr, void *const hw, void *const func) -{ - int32_t init_status; - ASSERT(descr && hw); - init_status = _usart_sync_init(&descr->device, hw); - if (init_status) { - return init_status; - } - - descr->io.read = usart_sync_read; - descr->io.write = usart_sync_write; - - return ERR_NONE; -} - -/** - * \brief Uninitialize usart interface - */ -int32_t usart_sync_deinit(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_deinit(&descr->device); - - descr->io.read = NULL; - descr->io.write = NULL; - - return ERR_NONE; -} - -/** - * \brief Enable usart interface - */ -int32_t usart_sync_enable(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_enable(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Disable usart interface - */ -int32_t usart_sync_disable(struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - _usart_sync_disable(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Retrieve I/O descriptor - */ -int32_t usart_sync_get_io_descriptor(struct usart_sync_descriptor *const descr, struct io_descriptor **io) -{ - ASSERT(descr && io); - - *io = &descr->io; - return ERR_NONE; -} - -/** - * \brief Specify action for flow control pins - */ -int32_t usart_sync_set_flow_control(struct usart_sync_descriptor *const descr, - const union usart_flow_control_state state) -{ - ASSERT(descr); - _usart_sync_set_flow_control_state(&descr->device, state); - - return ERR_NONE; -} - -/** - * \brief Set usart baud rate - */ -int32_t usart_sync_set_baud_rate(struct usart_sync_descriptor *const descr, const uint32_t baud_rate) -{ - ASSERT(descr); - _usart_sync_set_baud_rate(&descr->device, baud_rate); - - return ERR_NONE; -} - -/** - * \brief Set usart data order - */ -int32_t usart_sync_set_data_order(struct usart_sync_descriptor *const descr, const enum usart_data_order data_order) -{ - ASSERT(descr); - _usart_sync_set_data_order(&descr->device, data_order); - - return ERR_NONE; -} - -/** - * \brief Set usart mode - */ -int32_t usart_sync_set_mode(struct usart_sync_descriptor *const descr, const enum usart_mode mode) -{ - ASSERT(descr); - _usart_sync_set_mode(&descr->device, mode); - - return ERR_NONE; -} - -/** - * \brief Set usart parity - */ -int32_t usart_sync_set_parity(struct usart_sync_descriptor *const descr, const enum usart_parity parity) -{ - ASSERT(descr); - _usart_sync_set_parity(&descr->device, parity); - - return ERR_NONE; -} - -/** - * \brief Set usart stop bits - */ -int32_t usart_sync_set_stopbits(struct usart_sync_descriptor *const descr, const enum usart_stop_bits stop_bits) -{ - ASSERT(descr); - _usart_sync_set_stop_bits(&descr->device, stop_bits); - - return ERR_NONE; -} - -/** - * \brief Set usart character size - */ -int32_t usart_sync_set_character_size(struct usart_sync_descriptor *const descr, const enum usart_character_size size) -{ - ASSERT(descr); - _usart_sync_set_character_size(&descr->device, size); - - return ERR_NONE; -} - -/** - * \brief Retrieve the state of flow control pins - */ -int32_t usart_sync_flow_control_status(const struct usart_sync_descriptor *const descr, - union usart_flow_control_state *const state) -{ - ASSERT(descr && state); - *state = _usart_sync_get_flow_control_state(&descr->device); - - return ERR_NONE; -} - -/** - * \brief Check if the usart transmitter is empty - */ -int32_t usart_sync_is_tx_empty(const struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - return _usart_sync_is_ready_to_send(&descr->device); -} - -/** - * \brief Check if the usart receiver is not empty - */ -int32_t usart_sync_is_rx_not_empty(const struct usart_sync_descriptor *const descr) -{ - ASSERT(descr); - return _usart_sync_is_byte_received(&descr->device); -} - -/** - * \brief Retrieve the current driver version - */ -uint32_t usart_sync_get_version(void) -{ - return DRIVER_VERSION; -} - -/* - * \internal Write the given data to usart interface - * - * \param[in] descr The pointer to an io descriptor - * \param[in] buf Data to write to usart - * \param[in] length The number of bytes to write - * - * \return The number of bytes written. - */ -static int32_t usart_sync_write(struct io_descriptor *const io_descr, const uint8_t *const buf, const uint16_t length) -{ - uint32_t offset = 0; - struct usart_sync_descriptor *descr = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io); - - ASSERT(io_descr && buf && length); - while (!_usart_sync_is_ready_to_send(&descr->device)) - ; - do { - _usart_sync_write_byte(&descr->device, buf[offset]); - while (!_usart_sync_is_ready_to_send(&descr->device)) - ; - } while (++offset < length); - while (!_usart_sync_is_transmit_done(&descr->device)) - ; - return (int32_t)offset; -} - -/* - * \internal Read data from usart interface - * - * \param[in] descr The pointer to an io descriptor - * \param[in] buf A buffer to read data to - * \param[in] length The size of a buffer - * - * \return The number of bytes read. - */ -static int32_t usart_sync_read(struct io_descriptor *const io_descr, uint8_t *const buf, const uint16_t length) -{ - uint32_t offset = 0; - struct usart_sync_descriptor *descr = CONTAINER_OF(io_descr, struct usart_sync_descriptor, io); - - ASSERT(io_descr && buf && length); - do { - while (!_usart_sync_is_byte_received(&descr->device)) - ; - buf[offset] = _usart_sync_read_byte(&descr->device); - } while (++offset < length); - - return (int32_t)offset; -} diff --git a/bsp/microchip/same70/bsp/hpl/afec/hpl_afec.c b/bsp/microchip/same70/bsp/hpl/afec/hpl_afec.c new file mode 100644 index 0000000000..c165d80876 --- /dev/null +++ b/bsp/microchip/same70/bsp/hpl/afec/hpl_afec.c @@ -0,0 +1,638 @@ +/** + * \file + * + * \brief SAM Analog Front-End Controller (AFEC) + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +#include +#include +#include + +#include "hpl_afec_config.h" + +#ifndef CONF_AFEC_0_ENABLE +#define CONF_AFEC_0_ENABLE 0 +#endif +#ifndef CONF_AFEC_1_ENABLE +#define CONF_AFEC_1_ENABLE 0 +#endif + +#define AFEC_CHANNEL_AMOUNT 12 + +/** Build configuration from header macros. */ +#define AFEC_CONFIGURATION(n) \ + { \ + (n), \ + (uint32_t)(((uint32_t)(CONF_AFEC_##n##_USEQ) << 31) | (AFEC_MR_TRANSFER(CONF_AFEC_##n##_TRANSFER)) \ + | (AFEC_MR_TRACKTIM(CONF_AFEC_##n##_TRACKTIM)) | (AFEC_MR_ONE) \ + | (AFEC_MR_STARTUP(CONF_AFEC_##n##_STARTUP)) | (AFEC_MR_PRESCAL(CONF_AFEC_##n##_PRESCAL)) \ + | (CONF_AFEC_##n##_FREERUN << 7) | (CONF_AFEC_##n##_FWUP << 6) | (CONF_AFEC_##n##_SLEEP << 5) \ + | (AFEC_MR_TRGSEL(CONF_AFEC_##n##_TRGSEL)) | (CONF_AFEC_##n##_TRGEN << 0)), \ + (uint32_t)((AFEC_EMR_SIGNMODE(CONF_AFEC_##n##_SIGNMODE)) | (CONF_AFEC_##n##_STM << 25) \ + | (CONF_AFEC_##n##_TAG << 24) | (AFEC_EMR_RES(CONF_AFEC_##n##_RES)) \ + | (CONF_AFEC_##n##_CMPALL << 9) | (AFEC_EMR_CMPSEL(CONF_AFEC_##n##_CMPSEL)) \ + | (AFEC_EMR_CMPMODE(CONF_AFEC_##n##_CMPMODE))), \ + (uint32_t)(0 | (AFEC_SEQ1R_USCH0(CONF_AFEC_##n##_USCH0)) | (AFEC_SEQ1R_USCH1(CONF_AFEC_##n##_USCH1)) \ + | (AFEC_SEQ1R_USCH2(CONF_AFEC_##n##_USCH2)) | (AFEC_SEQ1R_USCH3(CONF_AFEC_##n##_USCH3)) \ + | (AFEC_SEQ1R_USCH4(CONF_AFEC_##n##_USCH4)) | (AFEC_SEQ1R_USCH5(CONF_AFEC_##n##_USCH5)) \ + | (AFEC_SEQ1R_USCH6(CONF_AFEC_##n##_USCH6)) | (AFEC_SEQ1R_USCH7(CONF_AFEC_##n##_USCH7))), \ + (uint32_t)(0 | (AFEC_SEQ2R_USCH8(CONF_AFEC_##n##_USCH8)) | (AFEC_SEQ2R_USCH9(CONF_AFEC_##n##_USCH9)) \ + | (AFEC_SEQ2R_USCH10(CONF_AFEC_##n##_USCH10)) | (AFEC_SEQ2R_USCH11(CONF_AFEC_##n##_USCH11))), \ + (uint32_t)((AFEC_CWR_HIGHTHRES(CONF_AFEC_##n##_HIGHTHRES)) \ + | (AFEC_CWR_LOWTHRES(CONF_AFEC_##n##_LOWTHRES))), \ + (uint32_t)(0 | (AFEC_CGR_GAIN0(CONF_AFEC_##n##_GAIN0)) | (AFEC_CGR_GAIN1(CONF_AFEC_##n##_GAIN1)) \ + | (AFEC_CGR_GAIN2(CONF_AFEC_##n##_GAIN2)) | (AFEC_CGR_GAIN3(CONF_AFEC_##n##_GAIN3)) \ + | (AFEC_CGR_GAIN4(CONF_AFEC_##n##_GAIN4)) | (AFEC_CGR_GAIN5(CONF_AFEC_##n##_GAIN5)) \ + | (AFEC_CGR_GAIN6(CONF_AFEC_##n##_GAIN6)) | (AFEC_CGR_GAIN7(CONF_AFEC_##n##_GAIN7)) \ + | (AFEC_CGR_GAIN8(CONF_AFEC_##n##_GAIN8)) | (AFEC_CGR_GAIN9(CONF_AFEC_##n##_GAIN9)) \ + | (AFEC_CGR_GAIN10(CONF_AFEC_##n##_GAIN10)) | (AFEC_CGR_GAIN11(CONF_AFEC_##n##_GAIN11))), \ + (uint32_t)(0 | (CONF_AFEC_##n##_DIFF0 << 0) | (CONF_AFEC_##n##_DIFF1 << 1) | (CONF_AFEC_##n##_DIFF2 << 2) \ + | (CONF_AFEC_##n##_DIFF3 << 3) | (CONF_AFEC_##n##_DIFF4 << 4) | (CONF_AFEC_##n##_DIFF5 << 5) \ + | (CONF_AFEC_##n##_DIFF6 << 6) | (CONF_AFEC_##n##_DIFF7 << 7) | (CONF_AFEC_##n##_DIFF8 << 8) \ + | (CONF_AFEC_##n##_DIFF9 << 9) | (CONF_AFEC_##n##_DIFF10 << 10) \ + | (CONF_AFEC_##n##_DIFF11 << 11)), \ + (uint32_t)(AFEC_ACR_IBCTL(CONF_AFEC_##n##_IBCTL) | (AFEC_ACR_PGA0EN | AFEC_ACR_PGA1EN)), \ + (uint32_t)(0 | (CONF_AFEC_##n##_DUAL0 << 0) | (CONF_AFEC_##n##_DUAL1 << 1) | (CONF_AFEC_##n##_DUAL2 << 2) \ + | (CONF_AFEC_##n##_DUAL3 << 3) | (CONF_AFEC_##n##_DUAL4 << 4) | (CONF_AFEC_##n##_DUAL5 << 5) \ + | (CONF_AFEC_##n##_DUAL6 << 6) | (CONF_AFEC_##n##_DUAL7 << 7) | (CONF_AFEC_##n##_DUAL8 << 8) \ + | (CONF_AFEC_##n##_DUAL9 << 9) | (CONF_AFEC_##n##_DUAL10 << 10) \ + | (CONF_AFEC_##n##_DUAL11 << 11)), \ + (uint32_t)(CONF_AFEC_##n##_COSR_CSEL), \ + (uint32_t)(AFEC_CVR_GAINCORR(CONF_AFEC_##n##_OFFSETCORR) \ + | (AFEC_CVR_OFFSETCORR(CONF_AFEC_##n##_GAINCORR))), \ + (uint32_t)(0 | (CONF_AFEC_##n##_ECORR0 << 0) | (CONF_AFEC_##n##_ECORR1 << 1) \ + | (CONF_AFEC_##n##_ECORR2 << 2) | (CONF_AFEC_##n##_ECORR3 << 3) | (CONF_AFEC_##n##_ECORR4 << 4) \ + | (CONF_AFEC_##n##_ECORR5 << 5) | (CONF_AFEC_##n##_ECORR6 << 6) | (CONF_AFEC_##n##_ECORR7 << 7) \ + | (CONF_AFEC_##n##_ECORR8 << 8) | (CONF_AFEC_##n##_ECORR9 << 9) \ + | (CONF_AFEC_##n##_ECORR10 << 10) | (CONF_AFEC_##n##_ECORR11 << 11)), \ + { \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF0), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF1), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF2), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF3), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF4), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF5), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF6), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF7), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF8), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF9), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF10), \ + (uint32_t)AFEC_COCR_AOFF(CONF_AFEC_##n##_AOFF11), \ + }, \ + } + +/** + * \brief AFEC configuration + */ +struct afec_configuration { + uint8_t number; + uint32_t mr; + uint32_t emr; + uint32_t seq1r; + uint32_t seq2r; + uint32_t cwr; + uint32_t cgr; + uint32_t diffr; + uint32_t acr; + uint32_t shmr; + uint32_t cosr; + uint32_t cvr; + uint32_t cecr; + uint32_t cocr[AFEC_CHANNEL_AMOUNT]; +}; + +#define AFEC_AMOUNT (CONF_AFEC_0_ENABLE + CONF_AFEC_1_ENABLE) + +#if AFEC_AMOUNT < 1 +/** Dummy array for compiling. */ +static const struct afec_configuration _afecs[1] = {{0}}; +#else +/** + * \brief Array of AFEC configurations + */ +static const struct afec_configuration _afecs[] = { +#if CONF_AFEC_0_ENABLE == 1 + AFEC_CONFIGURATION(0), +#endif +#if CONF_AFEC_1_ENABLE == 1 + AFEC_CONFIGURATION(1), +#endif +}; +#endif + +/** + * \brief Retrieve ordinal number of the given afec hardware instance + */ +static uint8_t _afec_get_hardware_index(const void *const hw) +{ + if (hw == AFEC0) { + return 0; + } else if (hw == AFEC1) { + return 1; + } + + ASSERT(false); + return 0; +} + +/** \brief Return the pointer to register settings of specific afec + * \param[in] hw_addr The hardware register base address. + * \return Pointer to register settings of specific afec. + */ +static uint8_t _afec_get_regs(const uint32_t hw_addr) +{ + uint8_t n = _afec_get_hardware_index((const void *)hw_addr); + uint8_t i; + + for (i = 0; i < sizeof(_afecs) / sizeof(struct afec_configuration); i++) { + if (_afecs[i].number == n) { + return i; + } + } + + return 0; +} + +/** + * \brief Retrieve IRQ number for the given hardware instance + */ +static IRQn_Type _afec_get_irq_num(const struct _adc_async_device *const device) +{ + if (device->hw == AFEC0) { + return AFEC0_IRQn; + } else if (device->hw == AFEC1) { + return AFEC1_IRQn; + } + + return (IRQn_Type)-1; +} + +/** + * \brief Init irq param with the given afec hardware instance + */ +static void _afec_init_irq_param(const void *const hw, struct _adc_async_device *dev) +{ +} + +/** + * \brief Initialize ADC + * + * \param[in] hw The pointer to hardware instance + * \param[in] i The number of hardware instance + */ +static int32_t _afec_init(void *const hw, const uint8_t i) +{ + uint8_t cnt; + + hri_afec_write_MR_reg(hw, _afecs[i].mr); + hri_afec_write_EMR_reg(hw, _afecs[i].emr); + hri_afec_write_SEQ1R_reg(hw, _afecs[i].seq1r); + hri_afec_write_SEQ2R_reg(hw, _afecs[i].seq2r); + hri_afec_write_CWR_reg(hw, _afecs[i].cwr); + hri_afec_write_CGR_reg(hw, _afecs[i].cgr); + hri_afec_write_DIFFR_reg(hw, _afecs[i].diffr); + hri_afec_write_ACR_reg(hw, _afecs[i].acr); + hri_afec_write_SHMR_reg(hw, _afecs[i].shmr); + hri_afec_write_COSR_reg(hw, _afecs[i].cosr); + hri_afec_write_CVR_reg(hw, _afecs[i].cvr); + hri_afec_write_CECR_reg(hw, _afecs[i].cecr); + + for (cnt = 0; cnt < AFEC_CHANNEL_AMOUNT; cnt++) { + hri_afec_write_CSELR_reg(hw, cnt); + hri_afec_write_COCR_reg(hw, _afecs[i].cocr[cnt]); + } + + return ERR_NONE; +} + +/** + * \brief De-initialize ADC + * + * \param[in] hw The pointer to hardware instance + */ +static inline void _afec_deinit(void *hw) +{ + hri_afec_clear_CHSR_reg(hw, AFEC_CHDR_MASK); + hri_afec_write_CR_reg(hw, AFEC_CR_SWRST); +} + +/** + * \internal ADC interrupt handler + * + * \param[in] p The pointer to interrupt parameter + */ +static void _afec_interrupt_handler(struct _adc_async_device *device) +{ + void *const hw = device->hw; + volatile uint32_t status; + uint8_t cnt = 0; + + status = hri_afec_read_ISR_reg(hw) & hri_afec_read_IMR_reg(hw); + if (status & AFEC_IMR_COMPE) { + device->adc_async_cb.window_cb(device, cnt); + } + if (status & AFEC_IMR_GOVRE) { + device->adc_async_cb.error_cb(device, cnt); + } + status &= 0xFFFu; + cnt = 32 - clz(status); + while (cnt) { + cnt--; + hri_afec_write_CSELR_reg(device->hw, cnt); + device->adc_async_ch_cb.convert_done(device, cnt, hri_afec_read_CDR_reg(device->hw)); + status &= ~(1 << cnt); + cnt = 32 - clz(status); + } +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_sync_init(struct _adc_sync_device *const device, void *const hw) +{ + ASSERT(device); + + device->hw = hw; + + return _afec_init(hw, _afec_get_regs((uint32_t)hw)); +} + +/** + * \brief Initialize ADC + */ +int32_t _adc_async_init(struct _adc_async_device *const device, void *const hw) +{ + int32_t init_status; + + ASSERT(device); + + init_status = _afec_init(hw, _afec_get_regs((uint32_t)hw)); + if (init_status) { + return init_status; + } + + device->hw = hw; + _afec_init_irq_param(hw, device); + NVIC_DisableIRQ(_afec_get_irq_num(device)); + NVIC_ClearPendingIRQ(_afec_get_irq_num(device)); + NVIC_EnableIRQ(_afec_get_irq_num(device)); + + return ERR_NONE; +} + +/** + * \brief De-initialize ADC + */ +void _adc_sync_deinit(struct _adc_sync_device *const device) +{ + _afec_deinit(device->hw); +} + +/** + * \brief De-initialize ADC + */ +void _adc_async_deinit(struct _adc_async_device *const device) +{ + NVIC_DisableIRQ(_afec_get_irq_num(device)); + NVIC_ClearPendingIRQ(_afec_get_irq_num(device)); + + _afec_deinit(device->hw); +} + +/** + * \brief Enable ADC + */ +void _adc_sync_enable_channel(struct _adc_sync_device *const device, const uint8_t channel) +{ + hri_afec_set_CHSR_reg(device->hw, (1 << channel)); +} + +/** + * \brief Enable ADC + */ +void _adc_async_enable_channel(struct _adc_async_device *const device, const uint8_t channel) +{ + hri_afec_set_CHSR_reg(device->hw, (1 << channel)); +} + +/** + * \brief Disable ADC + */ +void _adc_sync_disable_channel(struct _adc_sync_device *const device, const uint8_t channel) +{ + hri_afec_clear_CHSR_reg(device->hw, (1 << channel)); +} + +/** + * \brief Disable ADC + */ +void _adc_async_disable_channel(struct _adc_async_device *const device, const uint8_t channel) +{ + hri_afec_clear_CHSR_reg(device->hw, (1 << channel)); +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_sync_get_data_size(const struct _adc_sync_device *const device) +{ + (void)device; + + return 2; +} + +/** + * \brief Retrieve ADC conversion data size + */ +uint8_t _adc_async_get_data_size(const struct _adc_async_device *const device) +{ + (void)device; + + return 2; +} + +/** + * \brief Check if conversion is done + */ +bool _adc_sync_is_channel_conversion_done(const struct _adc_sync_device *const device, const uint8_t channel) +{ + return hri_afec_get_ISR_reg(device->hw, (1 << channel)); +} + +/** + * \brief Check if conversion is done + */ +bool _adc_async_is_channel_conversion_done(const struct _adc_async_device *const device, const uint8_t channel) +{ + return hri_afec_get_ISR_reg(device->hw, (1 << channel)); +} + +/** + * \brief Make conversion + */ +void _adc_sync_convert(struct _adc_sync_device *const device) +{ + hri_afec_write_CR_reg(device->hw, AFEC_CR_START); +} + +/** + * \brief Make conversion + */ +void _adc_async_convert(struct _adc_async_device *const device) +{ + hri_afec_write_CR_reg(device->hw, AFEC_CR_START); +} + +/** + * \brief Retrieve the conversion result + */ +uint16_t _adc_sync_read_channel_data(const struct _adc_sync_device *const device, const uint8_t channel) +{ + hri_afec_write_CSELR_reg(device->hw, channel); + + return hri_afec_read_CDR_reg(device->hw); +} + +/** + * \brief Retrieve the conversion result + */ +uint16_t _adc_async_read_channel_data(const struct _adc_async_device *const device, const uint8_t channel) +{ + hri_afec_write_CSELR_reg(device->hw, channel); + + return hri_afec_read_CDR_reg(device->hw); +} + +/** + * \brief Set reference source + */ +void _adc_sync_set_reference_source(struct _adc_sync_device *const device, const adc_reference_t reference) +{ + (void)device; + (void)reference; +} + +/** + * \brief Set reference source + */ +void _adc_async_set_reference_source(struct _adc_async_device *const device, const adc_reference_t reference) +{ + (void)device; + (void)reference; +} + +/** + * \brief Set resolution + */ +void _adc_sync_set_resolution(struct _adc_sync_device *const device, const adc_resolution_t resolution) +{ + hri_afec_write_EMR_RES_bf(device->hw, resolution); +} + +/** + * \brief Set resolution + */ +void _adc_async_set_resolution(struct _adc_async_device *const device, const adc_resolution_t resolution) +{ + hri_afec_write_EMR_RES_bf(device->hw, resolution); +} + +/** + * \brief Set channels input sources + */ +void _adc_sync_set_inputs(struct _adc_sync_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)device; + (void)pos_input; + (void)neg_input; + (void)channel; +} + +/** + * \brief Set channels input sources + */ +void _adc_async_set_inputs(struct _adc_async_device *const device, const adc_pos_input_t pos_input, + const adc_neg_input_t neg_input, const uint8_t channel) +{ + (void)device; + (void)pos_input; + (void)neg_input; + (void)channel; +} + +/** + * \brief Set thresholds + */ +void _adc_sync_set_thresholds(struct _adc_sync_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_afec_write_CWR_LOWTHRES_bf(device->hw, low_threshold); + hri_afec_write_CWR_HIGHTHRES_bf(device->hw, up_threshold); +} + +/** + * \brief Set thresholds + */ +void _adc_async_set_thresholds(struct _adc_async_device *const device, const adc_threshold_t low_threshold, + const adc_threshold_t up_threshold) +{ + hri_afec_write_CWR_LOWTHRES_bf(device->hw, low_threshold); + hri_afec_write_CWR_HIGHTHRES_bf(device->hw, up_threshold); +} + +/** + * \brief Set gain + */ +void _adc_sync_set_channel_gain(struct _adc_sync_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + hri_afec_clear_CGR_reg(device->hw, (0x3u << (channel * 2))); + hri_afec_set_CGR_reg(device->hw, (gain << (channel * 2))); +} + +/** + * \brief Set gain + */ +void _adc_async_set_channel_gain(struct _adc_async_device *const device, const uint8_t channel, const adc_gain_t gain) +{ + hri_afec_clear_CGR_reg(device->hw, (0x3u << (channel * 2))); + hri_afec_set_CGR_reg(device->hw, (gain << (channel * 2))); +} + +/** + * \brief Set conversion mode + */ +void _adc_sync_set_conversion_mode(struct _adc_sync_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_afec_set_MR_FREERUN_bit(device->hw); + } else { + hri_afec_clear_MR_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set conversion mode + */ +void _adc_async_set_conversion_mode(struct _adc_async_device *const device, const enum adc_conversion_mode mode) +{ + if (ADC_CONVERSION_MODE_FREERUN == mode) { + hri_afec_set_MR_FREERUN_bit(device->hw); + } else { + hri_afec_clear_MR_FREERUN_bit(device->hw); + } +} + +/** + * \brief Set differential mode + */ +void _adc_sync_set_channel_differential_mode(struct _adc_sync_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_afec_set_DIFFR_reg(device->hw, (0x1u << channel)); + } else { + hri_afec_clear_DIFFR_reg(device->hw, (0x1u << channel)); + } +} + +/** + * \brief Set differential mode + */ +void _adc_async_set_channel_differential_mode(struct _adc_async_device *const device, const uint8_t channel, + const enum adc_differential_mode mode) +{ + ASSERT(!(channel % 2)); + + if (ADC_DIFFERENTIAL_MODE_DIFFERENTIAL == mode) { + hri_afec_set_DIFFR_reg(device->hw, (0x3u << channel)); + } else { + hri_afec_clear_DIFFR_reg(device->hw, (0x3u << channel)); + } +} + +/** + * \brief Set window mode + */ +void _adc_sync_set_window_mode(struct _adc_sync_device *const device, const adc_window_mode_t mode) +{ + hri_afec_write_EMR_CMPMODE_bf(device->hw, mode); +} + +/** + * \brief Set window mode + */ +void _adc_async_set_window_mode(struct _adc_async_device *const device, const adc_window_mode_t mode) +{ + hri_afec_write_EMR_CMPMODE_bf(device->hw, mode); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_sync_get_threshold_state(const struct _adc_sync_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_afec_get_ISR_COMPE_bit(device->hw); +} + +/** + * \brief Retrieve threshold state + */ +void _adc_async_get_threshold_state(const struct _adc_async_device *const device, adc_threshold_status_t *const state) +{ + *state = hri_afec_get_ISR_COMPE_bit(device->hw); +} + +/** + * \brief Enable/disable ADC interrupt + * + * param[in] device The pointer to ADC device instance + * param[in] type The type of interrupt to disable/enable if applicable + * param[in] state Enable or disable + */ +void _adc_async_set_irq_state(struct _adc_async_device *const device, const uint8_t channel, + const enum _adc_async_callback_type type, const bool state) +{ + void *const hw = device->hw; + + if (ADC_ASYNC_DEVICE_MONITOR_CB == type) { + hri_afec_write_IMR_COMPE_bit(hw, state); + } else if (ADC_ASYNC_DEVICE_ERROR_CB == type) { + hri_afec_write_IMR_GOVRE_bit(hw, state); + } else if (ADC_ASYNC_DEVICE_CONVERT_CB == type) { + if (state) { + hri_afec_set_IMR_reg(hw, (0x1u << channel)); + } else { + hri_afec_clear_IMR_reg(hw, (0x1u << channel)); + } + } +} diff --git a/bsp/microchip/same70/bsp/hpl/core/hpl_core_m7_base.c b/bsp/microchip/same70/bsp/hpl/core/hpl_core_m7_base.c index 315c6f4efa..3e5e61fa92 100644 --- a/bsp/microchip/same70/bsp/hpl/core/hpl_core_m7_base.c +++ b/bsp/microchip/same70/bsp/hpl/core/hpl_core_m7_base.c @@ -149,17 +149,17 @@ static inline uint32_t _get_cycles_for_us_internal(const uint16_t us, const uint { switch (power) { case 9: - return (us * (freq / 1000000) - 1) + 1; + return (us * (freq / 1000000)); case 8: - return (us * (freq / 100000) - 1) / 10 + 1; + return (us * (freq / 100000) + 9) / 10; case 7: - return (us * (freq / 10000) - 1) / 100 + 1; + return (us * (freq / 10000) + 99) / 100; case 6: - return (us * (freq / 1000) - 1) / 1000 + 1; + return (us * (freq / 1000) + 999) / 1000; case 5: - return (us * (freq / 100) - 1) / 10000 + 1; + return (us * (freq / 100) + 9999) / 10000; default: - return (us * freq - 1) / 1000000 + 1; + return (us * freq + 999999) / 1000000; } } @@ -178,17 +178,17 @@ static inline uint32_t _get_cycles_for_ms_internal(const uint16_t ms, const uint { switch (power) { case 9: - return (ms * (freq / 1000000)) * 1000; + return (ms * (freq / 1000000) * 1000); case 8: - return (ms * (freq / 100000)) * 100; + return (ms * (freq / 100000) * 100); case 7: - return (ms * (freq / 10000)) * 10; + return (ms * (freq / 10000) * 10); case 6: return (ms * (freq / 1000)); case 5: - return (ms * (freq / 100) - 1) / 10 + 1; + return (ms * (freq / 100) + 9) / 10; default: - return (ms * freq - 1) / 1000 + 1; + return (ms * (freq / 1) + 999) / 1000; } } @@ -199,3 +199,38 @@ uint32_t _get_cycles_for_ms(const uint16_t ms) { return _get_cycles_for_ms_internal(ms, CONF_HCLK_FREQUENCY, HCLK_FREQ_POWER); } +/** + * \brief Initialize delay functionality + */ +void _delay_init(void *const hw) +{ + (void)hw; +} + +/** + * \brief Delay loop to delay n number of cycles + * + * \note In theory, a single loop runs take 2 cycles or more. But we find it + * really only needs 1 cycle through debugging. + * + */ +void _delay_cycles(void *const hw, uint32_t cycles) +{ +#ifndef _UNIT_TEST_ + (void)hw; + (void)cycles; +#if defined __GNUC__ + __asm("__delay:\n" + "subs r1, r1, #1\n" + "bhi __delay\n"); +#elif defined __CC_ARM + __asm("__delay:\n" + "subs cycles, cycles, #1\n" + "bhi __delay\n"); +#elif defined __ICCARM__ + __asm("__delay:\n" + "subs r1, r1, #1\n" + "bhi __delay\n"); +#endif +#endif +} diff --git a/bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac.c b/bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac.c new file mode 100644 index 0000000000..aa6e05412e --- /dev/null +++ b/bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac.c @@ -0,0 +1,567 @@ +/** + * \file + * + * \brief MAC functionality declaration. + * + * Copyright (c) 2016-2019 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +#include +#include +#include "hpl_gmac_base.h" + +#define DUMMY_SIZE 1 +#define DUMMY_BUFSIZE 4 + +/* Transmit and Receive buffer descriptor array */ +COMPILER_ALIGNED(8) static struct _mac_txbuf_descriptor _txbuf_descrs[CONF_GMAC_TXDESCR_NUM]; +COMPILER_ALIGNED(8) static struct _mac_rxbuf_descriptor _rxbuf_descrs[CONF_GMAC_RXDESCR_NUM]; + +/* Transmit buffer data array */ +COMPILER_ALIGNED(32) +static uint8_t _txbuf[CONF_GMAC_TXDESCR_NUM][CONF_GMAC_TXBUF_SIZE]; +COMPILER_ALIGNED(32) +static uint8_t _rxbuf[CONF_GMAC_RXDESCR_NUM][CONF_GMAC_RXBUF_SIZE]; + +/* Dummy transmit and Receive buffer descriptor array */ +COMPILER_ALIGNED(8) static struct _mac_txbuf_descriptor _txdummy_descrs[DUMMY_SIZE]; +COMPILER_ALIGNED(8) static struct _mac_rxbuf_descriptor _rxdummy_descrs[DUMMY_SIZE]; + +/* Dummy transmit and Receive buffer data array */ +COMPILER_ALIGNED(32) +static uint8_t _dummy_txbuf[DUMMY_SIZE][DUMMY_BUFSIZE]; +COMPILER_ALIGNED(32) +static uint8_t _dummy_rxbuf[DUMMY_SIZE][DUMMY_BUFSIZE]; + +COMPILER_PACK_RESET() + +/* Transmit and receive Buffer index */ +static volatile uint32_t _txbuf_index; +static volatile uint32_t _rxbuf_index; + +/** Pointer to hpl device */ +static struct _mac_async_device *_gmac_dev = NULL; + +/** + * \brief Initialize the Transmit and receive buffer descriptor array + * + * \param[in] dev Pointer to the HPL MAC descriptor + */ +static void _mac_init_bufdescr(struct _mac_async_device *const dev); + +/** + * \brief Initialize the MAC driver + */ +int32_t _mac_async_init(struct _mac_async_device *const dev, void *const hw) +{ + dev->hw = hw; + hri_gmac_write_NCR_reg(dev->hw, + (CONF_GMAC_NCR_LBL ? GMAC_NCR_LBL : 0) | (CONF_GMAC_NCR_MPE ? GMAC_NCR_MPE : 0) + | (CONF_GMAC_NCR_WESTAT ? GMAC_NCR_WESTAT : 0) | (CONF_GMAC_NCR_BP ? GMAC_NCR_BP : 0) + | (CONF_GMAC_NCR_ENPBPR ? GMAC_NCR_ENPBPR : 0) + | (CONF_GMAC_NCR_TXPBPF ? GMAC_NCR_TXPBPF : 0)); + hri_gmac_write_NCFGR_reg( + dev->hw, + (CONF_GMAC_NCFGR_SPD ? GMAC_NCFGR_SPD : 0) | (CONF_GMAC_NCFGR_FD ? GMAC_NCFGR_FD : 0) + | (CONF_GMAC_NCFGR_DNVLAN ? GMAC_NCFGR_DNVLAN : 0) | (CONF_GMAC_NCFGR_JFRAME ? GMAC_NCFGR_JFRAME : 0) + | (CONF_GMAC_NCFGR_CAF ? GMAC_NCFGR_CAF : 0) | (CONF_GMAC_NCFGR_NBC ? GMAC_NCFGR_NBC : 0) + | (CONF_GMAC_NCFGR_MTIHEN ? GMAC_NCFGR_MTIHEN : 0) | (CONF_GMAC_NCFGR_UNIHEN ? GMAC_NCFGR_UNIHEN : 0) + | (CONF_GMAC_NCFGR_MAXFS ? GMAC_NCFGR_MAXFS : 0) | (CONF_GMAC_NCFGR_RTY ? GMAC_NCFGR_RTY : 0) + | (CONF_GMAC_NCFGR_PEN ? GMAC_NCFGR_PEN : 0) | GMAC_NCFGR_RXBUFO(CONF_GMAC_NCFGR_RXBUFO) + | (CONF_GMAC_NCFGR_LFERD ? GMAC_NCFGR_LFERD : 0) | (CONF_GMAC_NCFGR_RFCS ? GMAC_NCFGR_RFCS : 0) + | GMAC_NCFGR_CLK(CONF_GMAC_NCFGR_CLK) | (CONF_GMAC_NCFGR_DCPF ? GMAC_NCFGR_DCPF : 0) + | (CONF_GMAC_NCFGR_RXCOEN ? GMAC_NCFGR_RXCOEN : 0) | (CONF_GMAC_NCFGR_EFRHD ? GMAC_NCFGR_EFRHD : 0) + | (CONF_GMAC_NCFGR_IRXFCS ? GMAC_NCFGR_IRXFCS : 0) | (CONF_GMAC_NCFGR_IPGSEN ? GMAC_NCFGR_IPGSEN : 0) + | (CONF_GMAC_NCFGR_RXBP ? GMAC_NCFGR_RXBP : 0) | (CONF_GMAC_NCFGR_IRXER ? GMAC_NCFGR_IRXER : 0)); + hri_gmac_write_UR_reg(dev->hw, (CONF_GMAC_UR_RMII)); + hri_gmac_write_DCFGR_reg( + dev->hw, + GMAC_DCFGR_FBLDO(CONF_GMAC_DCFGR_FBLDO) | (CONF_GMAC_DCFGR_ESMA ? GMAC_DCFGR_ESMA : 0) + | (CONF_GMAC_DCFGR_ESPA ? GMAC_DCFGR_ESPA : 0) | GMAC_DCFGR_RXBMS(CONF_GMAC_DCFGR_RXBMS) + | (CONF_GMAC_DCFGR_TXPBMS ? GMAC_DCFGR_TXPBMS : 0) | (CONF_GMAC_DCFGR_TXCOEN ? GMAC_DCFGR_TXCOEN : 0) + | GMAC_DCFGR_DRBS(CONF_GMAC_DCFGR_DRBS) | (CONF_GMAC_DCFGR_DDRP ? GMAC_DCFGR_DDRP : 0)); + hri_gmac_write_WOL_reg(dev->hw, 0); + hri_gmac_write_IPGS_reg(dev->hw, GMAC_IPGS_FL((CONF_GMAC_IPGS_FL_MUL << 8) | CONF_GMAC_IPGS_FL_DIV)); + _mac_init_bufdescr(dev); + + _gmac_dev = dev; + NVIC_DisableIRQ(GMAC_IRQn); + NVIC_ClearPendingIRQ(GMAC_IRQn); + NVIC_EnableIRQ(GMAC_IRQn); + + return ERR_NONE; +} + +/** + * \brief Deinitialize the MAC driver + */ +int32_t _mac_async_deinit(struct _mac_async_device *const dev) +{ + /* Disable all GMAC Interrupt */ + hri_gmac_clear_IMR_reg(dev->hw, 0xFFFFFFFF); + /* Disable transmit/receive */ + hri_gmac_write_NCR_reg(dev->hw, 0x0); + /* Disable Interrupt */ + NVIC_DisableIRQ(GMAC_IRQn); + dev->hw = NULL; + + return ERR_NONE; +} + +/* + * \brief Enable the MAC + */ +int32_t _mac_async_enable(struct _mac_async_device *const dev) +{ + hri_gmac_set_NCR_reg(dev->hw, GMAC_NCR_RXEN | GMAC_NCR_TXEN); + return ERR_NONE; +} + +/** + * \brief Disable the MAC + */ +int32_t _mac_async_disable(struct _mac_async_device *const dev) +{ + hri_gmac_clear_NCR_reg(dev->hw, GMAC_NCR_RXEN | GMAC_NCR_TXEN); + return ERR_NONE; +} + +/** + * \brief Transmit raw data to MAC + */ +int32_t _mac_async_write(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len) +{ + uint32_t pos; + uint32_t blen; /* Data Buffer length */ + uint32_t i; + + /* Set used flag from first descriptor to last descriptor, + * as DMA olny set the first used flag */ + for (i = 0; i < CONF_GMAC_TXDESCR_NUM; i++) { + pos = (_txbuf_index + i) % CONF_GMAC_TXDESCR_NUM; + if (_txbuf_descrs[pos].status.bm.used && !_txbuf_descrs[pos].status.bm.last_buf) { + for (i = i + 1; i < CONF_GMAC_TXDESCR_NUM; i++) { + pos = (_txbuf_index + i) % CONF_GMAC_TXDESCR_NUM; + _txbuf_descrs[pos].status.bm.used = 1; + if (_txbuf_descrs[pos].status.bm.last_buf) { + break; + } + } + } + } + + if (!_txbuf_descrs[_txbuf_index].status.bm.used) { + return ERR_NO_RESOURCE; + } + + /* Check if have enough buffers, the first buffer already checked */ + if (len > CONF_GMAC_TXBUF_SIZE) { + for (i = 1; i < CONF_GMAC_TXDESCR_NUM; i++) { + + pos = _txbuf_index + i; + + if (pos >= CONF_GMAC_TXDESCR_NUM) { + pos -= CONF_GMAC_TXDESCR_NUM; + } + + if (!_txbuf_descrs[pos].status.bm.used) { + return ERR_NO_RESOURCE; + } + if ((len - (CONF_GMAC_TXBUF_SIZE * i)) <= CONF_GMAC_TXBUF_SIZE) { + break; + } + } + } + + /* Write data to transmit buffer */ + for (i = 0; i < CONF_GMAC_TXDESCR_NUM; i++) { + blen = min(len, CONF_GMAC_TXBUF_SIZE); + memcpy(_txbuf[_txbuf_index], buf + (i * CONF_GMAC_TXBUF_SIZE), blen); + len -= blen; + + if (len > 0) { + /* Here the Used flag be set to zero */ + _txbuf_descrs[_txbuf_index].status.val = blen; + } else { + _txbuf_descrs[_txbuf_index].status.val = blen; + _txbuf_descrs[_txbuf_index].status.bm.last_buf = 1; + } + _txbuf_index++; + if (_txbuf_index == CONF_GMAC_TXDESCR_NUM) { + _txbuf_index = 0; + _txbuf_descrs[CONF_GMAC_TXDESCR_NUM - 1].status.bm.wrap = 1; + } + if (len == 0) { + break; + } + } + + /* Data synchronization barrier */ + __DSB(); + + /* Active Transmit */ + hri_gmac_set_NCR_TSTART_bit(dev->hw); + + return ERR_NONE; +} + +/** + * \brief Read received raw data from MAC + */ +uint32_t _mac_async_read(struct _mac_async_device *const dev, uint8_t *buf, uint32_t len) +{ + uint32_t i; + uint32_t j; + uint32_t pos; + uint32_t n; + uint32_t sof = 0xFFFFFFFF; /* Start of Frame index */ + uint32_t eof = 0xFFFFFFFF; /* End of Frame index */ + uint32_t total_len = 0; /* Total length of received package */ + + (void)dev; + for (i = 0; i < CONF_GMAC_RXDESCR_NUM; i++) { + pos = _rxbuf_index + i; + + if (pos >= CONF_GMAC_RXDESCR_NUM) { + pos -= CONF_GMAC_RXDESCR_NUM; + } + + /* No more data for Ethernet package */ + if (!(_rxbuf_descrs[pos].address.bm.ownership)) { + break; + } + + if (_rxbuf_descrs[pos].status.bm.sof) { + sof = i; + } + + if ((_rxbuf_descrs[pos].status.bm.eof) && (sof != 0xFFFFFFFF)) { + /* eof now indicate the number of bufs the frame used */ + eof = i; + n = _rxbuf_descrs[pos].status.bm.len; + len = min(n, len); + /* Break process since the last data has been found */ + break; + } + } + + if (eof != 0xFFFFFFFF) { + j = eof + 1; + } else if (sof != 0xFFFFFFFF) { + j = sof; + } else { + j = i; + } + + /* Copy data to user buffer */ + for (i = 0; i < j; i++) { + if (eof != 0xFFFFFFFF && i >= sof && i <= eof && buf && len > 0) { + n = min(len, CONF_GMAC_RXBUF_SIZE); + memcpy(buf, _rxbuf[_rxbuf_index], n); + buf += n; + total_len += n; + len -= n; + } + + _rxbuf_descrs[_rxbuf_index].address.bm.ownership = 0; + _rxbuf_index++; + + if (_rxbuf_index == CONF_GMAC_RXDESCR_NUM) { + _rxbuf_index = 0; + } + } + + return total_len; +} + +/** + * \brief Get next valid package length + */ +uint32_t _mac_async_read_len(struct _mac_async_device *const dev) +{ + uint32_t i; + uint32_t pos; + bool sof = false; /* Start of Frame */ + uint32_t total_len = 0; /* Total length of received package */ + + (void)dev; + for (i = 0; i < CONF_GMAC_RXDESCR_NUM; i++) { + pos = _rxbuf_index + i; + + if (pos >= CONF_GMAC_RXDESCR_NUM) { + pos -= CONF_GMAC_RXDESCR_NUM; + } + + /* No more data for Ethernet package */ + if (!(_rxbuf_descrs[pos].address.bm.ownership)) { + break; + } + + if (_rxbuf_descrs[pos].status.bm.sof) { + sof = true; + } + if (sof == true) { + total_len += _rxbuf_descrs[pos].status.bm.len; + } + + if (_rxbuf_descrs[pos].status.bm.eof) { + /* Break process since the last data has been found */ + break; + } + } + + return total_len; +} + +/** + * \brief Enable the MAC IRQ + */ +void _mac_async_enable_irq(struct _mac_async_device *const dev) +{ + (void)dev; + NVIC_EnableIRQ(GMAC_IRQn); +} + +/** + * \brief Disable the MAC IRQ + */ +void _mac_async_disable_irq(struct _mac_async_device *const dev) +{ + (void)dev; + NVIC_DisableIRQ(GMAC_IRQn); +} + +/** + * \brief Register the MAC callback + */ +int32_t _mac_async_register_callback(struct _mac_async_device *const dev, const enum mac_async_cb_type type, + const FUNC_PTR func) +{ + switch (type) { + case MAC_ASYNC_TRANSMIT_CB: + dev->cb.transmited = (_mac_async_cb_t)func; + if (func) { + hri_gmac_set_IMR_TCOMP_bit(dev->hw); + } else { + hri_gmac_clear_IMR_TCOMP_bit(dev->hw); + } + break; + case MAC_ASYNC_RECEIVE_CB: + dev->cb.received = (_mac_async_cb_t)func; + if (func) { + hri_gmac_set_IMR_RCOMP_bit(dev->hw); + } else { + hri_gmac_clear_IMR_RCOMP_bit(dev->hw); + } + break; + default: + return ERR_INVALID_ARG; + } + return ERR_NONE; +} + +/** + * \brief Set MAC filter + */ +int32_t _mac_async_set_filter(struct _mac_async_device *const dev, uint8_t index, struct mac_async_filter *filter) +{ + ASSERT(index < GMACSA_NUMBER); + + hri_gmac_set_SAB_ADDR_bf(dev->hw, index, *((uint32_t *)(filter->mac))); + hri_gmac_set_SAT_ADDR_bf(dev->hw, index, *((uint16_t *)(filter->mac + 4))); + + (*(__IO uint32_t *)(REG_GMAC_TIDM1 + (index * 4))) + = *((uint16_t *)(filter->tid)) | ((filter->tid_enable) ? GMAC_TIDM1_ENID1 : 0); + return ERR_NONE; +} + +/** + * \brief Set MAC filter (expaneded) + */ +int32_t _mac_async_set_filter_ex(struct _mac_async_device *const dev, uint8_t mac[6]) +{ + uint8_t j; + uint8_t m; + uint8_t n; + uint8_t k = 0; + + /* Apply the hash function */ + for (j = 0; j < 48; j += 6) { + /* Calculate the shift count */ + n = j / 8; + m = j % 8; + + /* Update hash value */ + if (!m) { + k ^= mac[n]; + } else { + k ^= (mac[n] >> m) | (mac[n + 1] << (8 - m)); + } + } + + /* The hash value is reduced to a 6-bit index */ + k &= 0x3F; + + if (k < 32) { + hri_gmac_set_HRB_reg(dev->hw, 1 << k); + } else { + hri_gmac_set_HRT_reg(dev->hw, 1 << (k % 32)); + } + + return ERR_NONE; +} + +/** + * \brief Write PHY register + */ +int32_t _mac_async_write_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t data) +{ + hri_gmac_set_NCR_MPE_bit(dev->hw); + hri_gmac_write_MAN_reg(dev->hw, + GMAC_MAN_OP(1) | /* 0x01 write operation */ + CONF_GMAC_CLTTO << 30 | /* Clause 22/45 operation */ + GMAC_MAN_WTN(2) | /* Must be written to 0x2 */ + GMAC_MAN_PHYA(addr) | GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(data)); + /* Wait for the write operation complete */ + while (!hri_gmac_get_NSR_IDLE_bit(dev->hw)) { + } + hri_gmac_clear_NCR_MPE_bit(dev->hw); + return ERR_NONE; +} + +/** + * \brief Read PHY register + */ +int32_t _mac_async_read_phy_reg(struct _mac_async_device *const dev, uint16_t addr, uint16_t reg, uint16_t *data) +{ + hri_gmac_set_NCR_MPE_bit(dev->hw); + hri_gmac_write_MAN_reg(dev->hw, + GMAC_MAN_OP(2) | /* 0x02 read operation */ + CONF_GMAC_CLTTO << 30 | /* Clause 22/45 operation */ + GMAC_MAN_WTN(0x2) | /* Must be written to 0x2 */ + GMAC_MAN_PHYA(addr) | GMAC_MAN_REGA(reg)); + + /* Wait for the read operation complete */ + while (!hri_gmac_get_NSR_IDLE_bit(dev->hw)) { + ; + } + + *data = hri_gmac_read_MAN_DATA_bf(dev->hw); + hri_gmac_clear_NCR_MPE_bit(dev->hw); + return ERR_NONE; +} + +/** + * \brief Initialize buffer descriptors + * + * \param[in] dev MAC device descriptor + **/ + +static void _mac_init_bufdescr(struct _mac_async_device *const dev) +{ + uint32_t i; + + /* TX buffer descriptor */ + for (i = 0; i < CONF_GMAC_TXDESCR_NUM; i++) { + _txbuf_descrs[i].address = (uint32_t)_txbuf[i]; + _txbuf_descrs[i].status.val = 0; + _txbuf_descrs[i].status.bm.used = 1; + } + + _txbuf_descrs[CONF_GMAC_TXDESCR_NUM - 1].status.bm.wrap = 1; + _txbuf_index = 0; + + /* RX buffer descriptor */ + for (i = 0; i < CONF_GMAC_RXDESCR_NUM; i++) { + _rxbuf_descrs[i].address.val = (uint32_t)_rxbuf[i]; + _rxbuf_descrs[i].status.val = 0; + } + + _rxbuf_descrs[CONF_GMAC_RXDESCR_NUM - 1].address.bm.wrap = 1; + _rxbuf_index = 0; + + hri_gmac_write_TBQB_reg(dev->hw, (uint32_t)_txbuf_descrs); + hri_gmac_write_RBQB_reg(dev->hw, (uint32_t)_rxbuf_descrs); + + /* Dummy TX buffer descriptor */ + for (i = 0; i < DUMMY_SIZE; i++) { + _txdummy_descrs[i].address = (uint32_t)_dummy_txbuf[i]; + _txdummy_descrs[i].status.val = 0; + _txdummy_descrs[i].status.bm.used = 1; + } + + _txdummy_descrs[DUMMY_SIZE - 1].status.bm.wrap = 1; + + /* Dummy RX buffer descriptor */ + for (i = 0; i < DUMMY_SIZE; i++) { + _rxdummy_descrs[i].address.val = (uint32_t)_dummy_rxbuf[i]; + _rxdummy_descrs[i].status.val = 0; + } + + _rxdummy_descrs[DUMMY_SIZE - 1].address.bm.wrap = 1; + /** + * Init Priority Queueing in DMA, even though the driver currently not + * support. it still need to init with the validate buffer descriptor. + */ + for (i = 0; i < 5; i++) { + hri_gmac_write_TBQBAPQ_reg(dev->hw, i, (uint32_t)_txdummy_descrs); + hri_gmac_write_RBQBAPQ_reg(dev->hw, i, (uint32_t)_rxdummy_descrs); + } +} + +/* + * \brief GMAC interrupt handler + */ +void GMAC_Handler(void) +{ + volatile uint32_t tsr; + volatile uint32_t rsr; + + tsr = hri_gmac_read_TSR_reg(_gmac_dev->hw); + rsr = hri_gmac_read_RSR_reg(_gmac_dev->hw); + /* Must be Clear ISR (Clear on read) */ + hri_gmac_read_ISR_reg(_gmac_dev->hw); + + /* Frame transmited */ + if (tsr & GMAC_TSR_TXCOMP) { + hri_gmac_write_TSR_reg(_gmac_dev->hw, tsr); + if ((_txbuf_descrs[_txbuf_index].status.bm.used) && (_gmac_dev->cb.transmited != NULL)) { + _gmac_dev->cb.transmited(_gmac_dev); + } + } + + /* Frame received */ + if (rsr & GMAC_RSR_REC) { + if (_gmac_dev->cb.received != NULL) { + _gmac_dev->cb.received(_gmac_dev); + } + } + hri_gmac_write_RSR_reg(_gmac_dev->hw, rsr); +} diff --git a/bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac_base.h b/bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac_base.h new file mode 100644 index 0000000000..b861cc4342 --- /dev/null +++ b/bsp/microchip/same70/bsp/hpl/gmac/hpl_gmac_base.h @@ -0,0 +1,102 @@ +/** + * \file + * + * \brief functionality declaration. + * + * Copyright (c) 2017-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + */ + +#ifndef HPL_GMAC_BASE_H_ +#define HPL_GMAC_BASE_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Transmit buffer descriptor + **/ +typedef struct _mac_txbuf_descriptor { + uint32_t address; + union gmac_tx_status { + uint32_t val; + struct _gmac_tx_status_bm { + uint32_t len : 14, /**< Length of buffer */ + reserved : 1, last_buf : 1, /**< Last buffer (in the current frame) */ + no_crc : 1, /**< No CRC */ + reserved1 : 3, checksum_err : 3, /**< Transmit checksum generation offload error */ + reserved2 : 3, lco : 1, /**< Late collision, transmit error detected */ + exhausted : 1, /**< Buffer exhausted in mid frame */ + reserved3 : 1, error : 1, /**< Retry limit exceeded, error detected */ + wrap : 1, /**< Marks last descriptor in TD list */ + used : 1; /**< User clear, GMAC sets this to 1 once a frame + has been successfully transmitted */ + } bm; + } status; +} _mac_txbuf_descr; + +/** + * @brief Receive buffer descriptor + **/ +typedef struct _mac_rxbuf_descriptor { + union _gmac_rx_addr { + uint32_t val; + struct rx_addr_bm { + uint32_t ownership : 1, /**< clear before buffer can be used again */ + wrap : 1, /**< Marks last entry in array */ + addr : 30; /**< Address in number of DW */ + } bm; + } address; + union gmac_rx_status { + uint32_t val; + struct _gmac_rx_status_bm { + uint32_t len : 13, /**< Length of frame including FCS */ + fcs : 1, /**< Frame has bad FCS */ + sof : 1, /**< Start of frame */ + eof : 1, /**< End of frame */ + cfi : 1, /**< Concatenation Format Indicator */ + vlan_priority : 3, /**< VLAN priority (if VLAN detected) */ + priority_detected : 1, /**< Priority tag detected */ + vlan_detected : 1, /**< VLAN tag detected */ + type_id_match : 2, /**< Type ID match */ + checksumoffload : 1, /**< Checksum offload specific function */ + addrmatch : 2, /**< Address register match */ + ext_addr_match : 1, /**< External address match found */ + reserved : 1, uni_hash_match : 1, /**< Unicast hash match */ + multi_hash_match : 1, /**< Multicast hash match */ + boardcast_detect : 1; /**< Global broadcast address detected */ + } bm; + } status; +} _mac_rxbuf_descr; + +#ifdef __cplusplus +} +#endif + +#endif /* HPL_GMAC_BASE_H_ */ diff --git a/bsp/microchip/same70/bsp/hpl/systick/hpl_systick_ARMv7_base.c b/bsp/microchip/same70/bsp/hpl/systick/hpl_systick_ARMv7_base.c deleted file mode 100644 index bec816109b..0000000000 --- a/bsp/microchip/same70/bsp/hpl/systick/hpl_systick_ARMv7_base.c +++ /dev/null @@ -1,106 +0,0 @@ -/** - * \file - * - * \brief SysTick related functionality implementation. - * - * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. - * - * \asf_license_start - * - * \page License - * - * Subject to your compliance with these terms, you may use Microchip - * software and any derivatives exclusively with Microchip products. - * It is your responsibility to comply with third party license terms applicable - * to your use of third party software (including open source software) that - * may accompany Microchip software. - * - * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, - * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, - * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, - * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE - * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL - * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE - * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE - * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT - * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY - * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, - * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. - * - * \asf_license_stop - * - */ - -#include -#include -#include -#ifdef _UNIT_TEST_ -#include -#endif - -/** - * \brief Initialize system time module - */ -void _system_time_init(void *const hw) -{ - (void)hw; - SysTick->LOAD = (0xFFFFFF << SysTick_LOAD_RELOAD_Pos); - SysTick->CTRL = (1 << SysTick_CTRL_ENABLE_Pos) | (CONF_SYSTICK_TICKINT << SysTick_CTRL_TICKINT_Pos) - | (1 << SysTick_CTRL_CLKSOURCE_Pos); -} -/** - * \brief Initialize delay functionality - */ -void _delay_init(void *const hw) -{ - _system_time_init(hw); -} - -/** - * \brief De-initialize system time module - */ -void _system_time_deinit(void *const hw) -{ - (void)hw; - SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; -} - -/** - * \brief Get system time - */ -system_time_t _system_time_get(const void *const hw) -{ - (void)hw; - return (system_time_t)SysTick->VAL; -} - -/** - * \brief Get maximum possible system time - */ -system_time_t _system_time_get_max_time_value(const void *const hw) -{ - (void)hw; - return 0xFFFFFF; -} -/** - * \brief Delay loop to delay n number of cycles - */ -void _delay_cycles(void *const hw, uint32_t cycles) -{ - (void)hw; - uint8_t n = cycles >> 24; - uint32_t buf = cycles; - - while (n--) { - SysTick->LOAD = 0xFFFFFF; - SysTick->VAL = 0xFFFFFF; - while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) - ; - buf -= 0xFFFFFF; - } - - SysTick->LOAD = buf; - SysTick->VAL = buf; - while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) - ; -} diff --git a/bsp/microchip/same70/bsp/hpl/twihs/hpl_twihs.c b/bsp/microchip/same70/bsp/hpl/twihs/hpl_twihs.c new file mode 100644 index 0000000000..4643527f68 --- /dev/null +++ b/bsp/microchip/same70/bsp/hpl/twihs/hpl_twihs.c @@ -0,0 +1,307 @@ +/** + * \file + * + * \brief SAM Two-Wire Interface + * + * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries. + * + * \asf_license_start + * + * \page License + * + * Subject to your compliance with these terms, you may use Microchip + * software and any derivatives exclusively with Microchip products. + * It is your responsibility to comply with third party license terms applicable + * to your use of third party software (including open source software) that + * may accompany Microchip software. + * + * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, + * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, + * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, + * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE + * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL + * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE + * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE + * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT + * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY + * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, + * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. + * + * \asf_license_stop + * + */ + +#include +#include +#include +#include + +/** + * \internal Set baudrate for TWIHS + * + * \param[in] hw TWIHS Base Address + * \param[in] clk TWIHS peripheral clock rate in HZ + * \param[in] baudrate TWIHS I2C baudrate in HZ + */ +static int32_t _twihs_set_baudrate(void *const hw, uint32_t clk, uint32_t baudrate); + +/** + * \internal Retrieve I2C Master Sync configuration instance + * + * \param[in] hw The pointer of TWIHS hardware instance + * + * \return The I2C Master Sync configuration instance + */ +static const struct _i2cm_sync_cfg *_get_i2cm_sync_cfg(void *hw); + +/** + * \internal I2C Master Sync read operation + * + * \param[in] dev The pointer of I2C Master instance + * \param[in] msg The pointer of I2C message struct + * + * \return The status of the operation + * \retval ERR_NONE Operation sucessfully + */ +static inline int32_t _i2c_m_sync_read(struct _i2c_m_sync_device *const dev, struct _i2c_m_msg *msg); + +/** + * \internal I2C Master Sync write operation + * + * \param[in] dev The pointer of I2C Master instance + * \param[in] msg The pointer of I2C message struct + * + * \return The status of the operation + * \retval ERR_NONE Operation sucessfully + */ +static inline int32_t _i2c_m_sync_write(struct _i2c_m_sync_device *const dev, struct _i2c_m_msg *msg); + +/** + * \brief TWIHS I2C Master Sync configuration Type + */ +struct _i2cm_sync_cfg { + void * hw; /*!< instance of TWIHS */ + hri_twihs_cr_reg_t ctrl; + hri_twihs_smbtr_reg_t smbtr; + hri_twihs_filtr_reg_t filtr; + hri_twihs_cwgr_reg_t cwgr; + uint32_t clkrate; +}; + +/** + * \brief Array of I2C Master Sync configurations + */ +static const struct _i2cm_sync_cfg _i2cm_sync_cfgs[1] = { + {(void *)TWIHS0, + CONF_TWIHS0_CR_REG, + CONF_TWIHS0_SMBTR_REG, + CONF_TWIHS0_FILTR_REG, + CONF_TWIHS0_CWGR_REG, + CONF_TWIHS0_FREQUENCY / 1000}, +}; + +/** + * \berif Retrieve I2C Master Sync configuration instance + */ +static const struct _i2cm_sync_cfg *_get_i2cm_sync_cfg(void *hw) +{ + uint8_t i; + + for (i = 0; i < ARRAY_SIZE(_i2cm_sync_cfgs); i++) { + if (_i2cm_sync_cfgs[i].hw == hw) { + return &(_i2cm_sync_cfgs[i]); + } + } + return NULL; +} + +int32_t _i2c_m_sync_init(struct _i2c_m_sync_device *const dev, void *const hw) +{ + ASSERT(dev && hw); + + const struct _i2cm_sync_cfg *cfg; + + dev->hw = hw; + cfg = _get_i2cm_sync_cfg(dev->hw); + + // hri_twihs_write_CR_reg(hw, TWIHS_CR_SWRST); + // hri_twihs_read_RHR_reg(hw); + hri_twihs_write_CR_reg(dev->hw, cfg->ctrl); + hri_twihs_write_SMBTR_reg(dev->hw, cfg->smbtr); + hri_twihs_write_FILTR_reg(dev->hw, cfg->filtr); + hri_twihs_write_CWGR_reg(dev->hw, cfg->cwgr); + + return ERR_NONE; +} + +int32_t _i2c_m_sync_deinit(struct _i2c_m_sync_device *const dev) +{ + ASSERT(dev); + + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_SWRST); + dev->hw = NULL; + + return ERR_NONE; +} + +int32_t _i2c_m_sync_enable(struct _i2c_m_sync_device *const dev) +{ + ASSERT(dev); + + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_MSEN); + + return ERR_NONE; +} + +int32_t _i2c_m_sync_disable(struct _i2c_m_sync_device *const dev) +{ + ASSERT(dev); + + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_MSDIS); + + return ERR_NONE; +} + +int32_t _i2c_m_sync_set_baudrate(struct _i2c_m_sync_device *const dev, uint32_t clkrate, uint32_t baudrate) +{ + ASSERT(dev && baudrate); + (void)clkrate; + + const struct _i2cm_sync_cfg *cfg = _get_i2cm_sync_cfg(dev->hw); + + return _twihs_set_baudrate(dev->hw, cfg->clkrate, baudrate); +} + +int32_t _i2c_m_sync_send_stop(struct _i2c_m_sync_device *const dev) +{ + ASSERT(dev && dev->hw); + + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_STOP); + + return ERR_NONE; +} + +int32_t _i2c_m_sync_transfer(struct _i2c_m_sync_device *const dev, struct _i2c_m_msg *msg) +{ + ASSERT(dev && msg); + + if (dev->service.msg.flags & I2C_M_BUSY) { + return I2C_ERR_BUSY; + } + + if (msg->flags & I2C_M_RD) { + return _i2c_m_sync_read(dev, msg); + } else { + return _i2c_m_sync_write(dev, msg); + } +} + +static inline int32_t _i2c_m_sync_write(struct _i2c_m_sync_device *const dev, struct _i2c_m_msg *msg) +{ + uint32_t i; + uint32_t sr; + int ret = ERR_NONE; + + msg->flags |= I2C_M_BUSY; + + if (msg->addr & I2C_M_TEN) { + hri_twihs_write_MMR_reg(dev->hw, TWIHS_MMR_DADR(0x78 | (msg->addr >> 8)) | TWIHS_MMR_IADRSZ(1)); + hri_twihs_write_IADR_reg(dev->hw, msg->addr & 0xff); + } else { + hri_twihs_write_MMR_reg(dev->hw, TWIHS_MMR_DADR(msg->addr)); + } + + for (i = 0; i < msg->len; i++) { + /* Wait for data is transferred from TWIHS_THR or if NACK is detected */ + do { + sr = hri_twihs_read_SR_reg(dev->hw); + if (sr & TWIHS_SR_NACK) { + ret = I2C_NACK; + break; + } + } while (!(sr & TWIHS_SR_TXRDY)); + + if (ret != ERR_NONE) + break; + hri_twihs_write_THR_reg(dev->hw, msg->buffer[i]); + } + + if (msg->flags & I2C_M_STOP) { + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_STOP); + while (!hri_twihs_get_SR_TXCOMP_bit(dev->hw)) { + }; + } + + dev->service.msg.flags &= ~I2C_M_BUSY; + + return ret; +} + +static inline int32_t _i2c_m_sync_read(struct _i2c_m_sync_device *const dev, struct _i2c_m_msg *msg) +{ + uint32_t i; + + msg->flags |= I2C_M_BUSY; + + if (msg->addr & I2C_M_TEN) { + hri_twihs_write_MMR_reg(dev->hw, + TWIHS_MMR_DADR(0x78 | (msg->addr >> 8)) | TWIHS_MMR_IADRSZ(1) | TWIHS_MMR_MREAD); + hri_twihs_write_IADR_reg(dev->hw, msg->addr & 0xff); + } else { + hri_twihs_write_MMR_reg(dev->hw, TWIHS_MMR_DADR(msg->addr) | TWIHS_MMR_MREAD); + } + /* In single data byte master read, the START and STOP must both be set */ + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_START | ((msg->len == 1) ? TWIHS_CR_STOP : 0)); + + for (i = 0; i < msg->len; i++) { + /* Wait for a byte has been received in TWIHS_RHR since last read */ + while (!hri_twihs_get_SR_RXRDY_bit(dev->hw)) { + /* Check whether slave acknowledge received after the address byte */ + if (hri_twihs_get_SR_NACK_bit(dev->hw)) + return I2C_NACK; + }; + + msg->buffer[i] = hri_twihs_read_RHR_reg(dev->hw); + /* In multiple data bytes master read, the STOP must be set after the + * last data received but one */ + if (i == (msg->len - 2)) { + hri_twihs_write_CR_reg(dev->hw, TWIHS_CR_STOP); + } + } + + while (!hri_twihs_get_SR_TXCOMP_bit(dev->hw)) { + }; + dev->service.msg.flags &= ~I2C_M_BUSY; + + return ERR_NONE; +} + +static int32_t _twihs_set_baudrate(void *const hw, uint32_t clk, uint32_t baudrate) +{ + uint8_t ckdiv = 0; /* CWGR_CKDIV */ + uint32_t cldiv; /* CWGR_CLDIV */ + + cldiv = clk / (baudrate * 2); + + /* cldiv(CWGR_CLDIV) must fit in 8 bits and + * ckdiv(CWGR_CKDIV) must fit in 3 bits + * + * cldiv may overflow 255 by ckdiv = 0 in previous step, + * So here will check cldiv, if cldiv > 255 then will loop ckdiv from 1 to + * 7 for find a valid cldiv value + */ + while ((cldiv > 255) && (ckdiv < 7)) { + /* Increase clock divider */ + ckdiv++; + /* Divide cldiv value */ + cldiv = cldiv >> 1; + } + + if (cldiv > 255) { + return ERR_INVALID_DATA; + } + /* set CWGR(Clock Waveform Generator Register) */ + hri_twihs_write_CWGR_reg(hw, TWIHS_CWGR_CKDIV(ckdiv) | TWIHS_CWGR_CLDIV(cldiv) | TWIHS_CWGR_CHDIV(cldiv)); + + return ERR_NONE; +} diff --git a/bsp/microchip/same70/bsp/hpl/usart/hpl_usart.c b/bsp/microchip/same70/bsp/hpl/usart/hpl_usart.c index e2c0d099a2..dbfd844540 100644 --- a/bsp/microchip/same70/bsp/hpl/usart/hpl_usart.c +++ b/bsp/microchip/same70/bsp/hpl/usart/hpl_usart.c @@ -147,6 +147,8 @@ static struct usart_configuration _usarts[] = { }; #endif +static struct _usart_async_device *_usart1_dev = NULL; + static uint8_t _usart_get_irq_num(const void *const hw); static uint8_t _get_usart_index(const void *const hw); static uint8_t _usart_get_hardware_index(const void *const hw); @@ -179,12 +181,15 @@ static uint8_t _usart_get_irq_num(const void *const hw) */ static void _usart_init_irq_param(const void *const hw, struct _usart_async_device *dev) { + if (hw == USART1) { + _usart1_dev = dev; + } } /** * \brief Initialize synchronous USART */ -int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw) +int32_t _usart_usart_sync_init(struct _usart_sync_device *const device, void *const hw) { ASSERT(device); ASSERT(hw); @@ -197,7 +202,7 @@ int32_t _usart_sync_init(struct _usart_sync_device *const device, void *const hw /** * \brief Initialize asynchronous USART */ -int32_t _usart_usart_async_init(struct _usart_async_device *const device, void *const hw) +int32_t _usart_async_init(struct _usart_async_device *const device, void *const hw) { int32_t init_status; @@ -220,7 +225,7 @@ int32_t _usart_usart_async_init(struct _usart_async_device *const device, void * /** * \brief De-initialize USART */ -void _usart_sync_deinit(struct _usart_sync_device *const device) +void _usart_usart_sync_deinit(struct _usart_sync_device *const device) { ASSERT(device); _usart_deinit(device->hw); @@ -229,7 +234,7 @@ void _usart_sync_deinit(struct _usart_sync_device *const device) /** * \brief De-initialize USART */ -void _usart_usart_async_deinit(struct _usart_async_device *const device) +void _usart_async_deinit(struct _usart_async_device *const device) { ASSERT(device); NVIC_DisableIRQ((IRQn_Type)_usart_get_irq_num(device->hw)); @@ -239,8 +244,8 @@ void _usart_usart_async_deinit(struct _usart_async_device *const device) /** * \brief Calculate baud rate register value */ -uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, - const enum usart_baud_rate_mode mode, const uint8_t fraction) +uint16_t _usart_usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, + const enum usart_baud_rate_mode mode, const uint8_t fraction) { return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction); } @@ -248,15 +253,15 @@ uint16_t _usart_sync_calculate_baud_rate(const uint32_t baud, const uint32_t clo /** * \brief Calculate baud rate register value */ -uint16_t _usart_usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, - const enum usart_baud_rate_mode mode, const uint8_t fraction) +uint16_t _usart_async_calculate_baud_rate(const uint32_t baud, const uint32_t clock_rate, const uint8_t samples, + const enum usart_baud_rate_mode mode, const uint8_t fraction) { return _usart_calculate_baud_rate(baud, clock_rate, samples, mode, fraction); } /** * \brief Enable USART sync module */ -void _usart_sync_enable(struct _usart_sync_device *const device) +void _usart_usart_sync_enable(struct _usart_sync_device *const device) { ASSERT(device); _usart_enable(device->hw); @@ -265,7 +270,7 @@ void _usart_sync_enable(struct _usart_sync_device *const device) /** * \brief Enable USART async module */ -void _usart_usart_async_enable(struct _usart_async_device *const device) +void _usart_async_enable(struct _usart_async_device *const device) { ASSERT(device); _usart_enable(device->hw); @@ -274,7 +279,7 @@ void _usart_usart_async_enable(struct _usart_async_device *const device) /** * \brief Disable USART sync module */ -void _usart_sync_disable(struct _usart_sync_device *const device) +void _usart_usart_sync_disable(struct _usart_sync_device *const device) { ASSERT(device); _usart_disable(device->hw); @@ -283,7 +288,7 @@ void _usart_sync_disable(struct _usart_sync_device *const device) /** * \brief Disable USART async module */ -void _usart_usart_async_disable(struct _usart_async_device *const device) +void _usart_async_disable(struct _usart_async_device *const device) { ASSERT(device); _usart_disable(device->hw); @@ -292,7 +297,7 @@ void _usart_usart_async_disable(struct _usart_async_device *const device) /** * \brief Set baud rate */ -void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate) +void _usart_usart_sync_set_baud_rate(struct _usart_sync_device *const device, const uint32_t baud_rate) { ASSERT(device); _usart_set_baud_rate(device->hw, baud_rate); @@ -301,7 +306,7 @@ void _usart_sync_set_baud_rate(struct _usart_sync_device *const device, const ui /** * \brief Set baud rate */ -void _usart_usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate) +void _usart_async_set_baud_rate(struct _usart_async_device *const device, const uint32_t baud_rate) { ASSERT(device); _usart_set_baud_rate(device->hw, baud_rate); @@ -310,7 +315,7 @@ void _usart_usart_async_set_baud_rate(struct _usart_async_device *const device, /** * \brief Set data order */ -void _usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order) +void _usart_usart_sync_set_data_order(struct _usart_sync_device *const device, const enum usart_data_order order) { ASSERT(device); _usart_set_data_order(device->hw, order); @@ -319,7 +324,7 @@ void _usart_sync_set_data_order(struct _usart_sync_device *const device, const e /** * \brief Set data order */ -void _usart_usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order) +void _usart_async_set_data_order(struct _usart_async_device *const device, const enum usart_data_order order) { ASSERT(device); _usart_set_data_order(device->hw, order); @@ -328,7 +333,7 @@ void _usart_usart_async_set_data_order(struct _usart_async_device *const device, /** * \brief Set mode */ -void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode) +void _usart_usart_sync_set_mode(struct _usart_sync_device *const device, const enum usart_mode mode) { ASSERT(device); _usart_set_mode(device->hw, mode); @@ -337,7 +342,7 @@ void _usart_sync_set_mode(struct _usart_sync_device *const device, const enum us /** * \brief Set mode */ -void _usart_usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode) +void _usart_async_set_mode(struct _usart_async_device *const device, const enum usart_mode mode) { ASSERT(device); _usart_set_mode(device->hw, mode); @@ -346,7 +351,7 @@ void _usart_usart_async_set_mode(struct _usart_async_device *const device, const /** * \brief Set parity */ -void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity) +void _usart_usart_sync_set_parity(struct _usart_sync_device *const device, const enum usart_parity parity) { ASSERT(device); _usart_set_parity(device->hw, parity); @@ -355,7 +360,7 @@ void _usart_sync_set_parity(struct _usart_sync_device *const device, const enum /** * \brief Set parity */ -void _usart_usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity) +void _usart_async_set_parity(struct _usart_async_device *const device, const enum usart_parity parity) { ASSERT(device); _usart_set_parity(device->hw, parity); @@ -364,7 +369,7 @@ void _usart_usart_async_set_parity(struct _usart_async_device *const device, con /** * \brief Set stop bits mode */ -void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits) +void _usart_usart_sync_set_stop_bits(struct _usart_sync_device *const device, const enum usart_stop_bits stop_bits) { ASSERT(device); _usart_set_stop_bits(device->hw, stop_bits); @@ -373,7 +378,7 @@ void _usart_sync_set_stop_bits(struct _usart_sync_device *const device, const en /** * \brief Set stop bits mode */ -void _usart_usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits) +void _usart_async_set_stop_bits(struct _usart_async_device *const device, const enum usart_stop_bits stop_bits) { ASSERT(device); _usart_set_stop_bits(device->hw, stop_bits); @@ -382,7 +387,7 @@ void _usart_usart_async_set_stop_bits(struct _usart_async_device *const device, /** * \brief Set character size */ -void _usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size) +void _usart_usart_sync_set_character_size(struct _usart_sync_device *const device, const enum usart_character_size size) { ASSERT(device); _usart_set_character_size(device->hw, size); @@ -391,8 +396,7 @@ void _usart_sync_set_character_size(struct _usart_sync_device *const device, con /** * \brief Set character size */ -void _usart_usart_async_set_character_size(struct _usart_async_device *const device, - const enum usart_character_size size) +void _usart_async_set_character_size(struct _usart_async_device *const device, const enum usart_character_size size) { ASSERT(device); _usart_set_character_size(device->hw, size); @@ -401,7 +405,7 @@ void _usart_usart_async_set_character_size(struct _usart_async_device *const dev /** * \brief Retrieve usart status */ -uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device) +uint32_t _usart_usart_sync_get_status(const struct _usart_sync_device *const device) { ASSERT(device); return (uint32_t)hri_usart_read_US_CSR_reg(device->hw); @@ -410,7 +414,7 @@ uint32_t _usart_sync_get_status(const struct _usart_sync_device *const device) /** * \brief Retrieve usart status */ -uint32_t _usart_usart_async_get_status(const struct _usart_async_device *const device) +uint32_t _usart_async_get_status(const struct _usart_async_device *const device) { ASSERT(device); return (uint32_t)hri_usart_read_US_CSR_reg(device->hw); @@ -419,7 +423,7 @@ uint32_t _usart_usart_async_get_status(const struct _usart_async_device *const d /** * \brief Write a byte to the given USART instance */ -void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data) +void _usart_usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t data) { ASSERT(device); hri_usart_write_US_THR_reg(device->hw, (hri_usart_us_thr_reg_t)data); @@ -428,7 +432,7 @@ void _usart_sync_write_byte(struct _usart_sync_device *const device, uint8_t dat /** * \brief Write a byte to the given USART instance */ -void _usart_usart_async_write_byte(struct _usart_async_device *const device, uint8_t data) +void _usart_async_write_byte(struct _usart_async_device *const device, uint8_t data) { ASSERT(device); hri_usart_write_US_THR_reg(device->hw, (hri_usart_us_thr_reg_t)data); @@ -437,7 +441,7 @@ void _usart_usart_async_write_byte(struct _usart_async_device *const device, uin /** * \brief Read a byte from the given USART instance */ -uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device) +uint8_t _usart_usart_sync_read_byte(const struct _usart_sync_device *const device) { ASSERT(device); return (uint8_t)(hri_usart_read_US_RHR_reg(device->hw) & 0xff); @@ -446,7 +450,7 @@ uint8_t _usart_sync_read_byte(const struct _usart_sync_device *const device) /** * \brief Check if USART is ready to send next byte */ -bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device) +bool _usart_usart_sync_is_ready_to_send(const struct _usart_sync_device *const device) { ASSERT(device); return hri_usart_get_US_CSR_TXRDY_bit(device->hw); @@ -455,7 +459,7 @@ bool _usart_sync_is_ready_to_send(const struct _usart_sync_device *const device) /** * \brief Check if USART transmission complete */ -bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device) +bool _usart_usart_sync_is_transmit_done(const struct _usart_sync_device *const device) { ASSERT(device); return hri_usart_get_US_CSR_TXEMPTY_bit(device->hw); @@ -464,7 +468,7 @@ bool _usart_sync_is_transmit_done(const struct _usart_sync_device *const device) /** * \brief Check if USART is ready to send next byte */ -bool _usart_usart_async_is_byte_sent(const struct _usart_async_device *const device) +bool _usart_async_is_byte_sent(const struct _usart_async_device *const device) { ASSERT(device); return hri_usart_get_US_CSR_TXRDY_bit(device->hw); @@ -473,7 +477,7 @@ bool _usart_usart_async_is_byte_sent(const struct _usart_async_device *const dev /** * \brief Check if there is data received by USART */ -bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device) +bool _usart_usart_sync_is_byte_received(const struct _usart_sync_device *const device) { ASSERT(device); return hri_usart_get_US_CSR_RXRDY_bit(device->hw); @@ -482,8 +486,8 @@ bool _usart_sync_is_byte_received(const struct _usart_sync_device *const device) /** * \brief Set the state of flow control pins */ -void _usart_sync_set_flow_control_state(struct _usart_sync_device *const device, - const union usart_flow_control_state state) +void _usart_usart_sync_set_flow_control_state(struct _usart_sync_device *const device, + const union usart_flow_control_state state) { ASSERT(device); (void)device; @@ -493,8 +497,8 @@ void _usart_sync_set_flow_control_state(struct _usart_sync_device *const dev /** * \brief Set the state of flow control pins */ -void _usart_usart_async_set_flow_control_state(struct _usart_async_device *const device, - const union usart_flow_control_state state) +void _usart_async_set_flow_control_state(struct _usart_async_device *const device, + const union usart_flow_control_state state) { ASSERT(device); (void)device; @@ -504,7 +508,7 @@ void _usart_usart_async_set_flow_control_state(struct _usart_async_device *const /** * \brief Retrieve the state of flow control pins */ -union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _usart_sync_device *const device) +union usart_flow_control_state _usart_usart_sync_get_flow_control_state(const struct _usart_sync_device *const device) { ASSERT(device); (void)device; @@ -518,7 +522,7 @@ union usart_flow_control_state _usart_sync_get_flow_control_state(const struct _ /** * \brief Retrieve the state of flow control pins */ -union usart_flow_control_state _usart_usart_async_get_flow_control_state(const struct _usart_async_device *const device) +union usart_flow_control_state _usart_async_get_flow_control_state(const struct _usart_async_device *const device) { ASSERT(device); (void)device; @@ -532,7 +536,7 @@ union usart_flow_control_state _usart_usart_async_get_flow_control_state(const s /** * \brief Enable data register empty interrupt */ -void _usart_usart_async_enable_byte_sent_irq(struct _usart_async_device *const device) +void _usart_async_enable_byte_sent_irq(struct _usart_async_device *const device) { ASSERT(device); hri_usart_set_US_IMR_TXRDY_bit(device->hw); @@ -541,7 +545,7 @@ void _usart_usart_async_enable_byte_sent_irq(struct _usart_async_device *const d /** * \brief Enable transmission complete interrupt */ -void _usart_usart_async_enable_tx_done_irq(struct _usart_async_device *const device) +void _usart_async_enable_tx_done_irq(struct _usart_async_device *const device) { ASSERT(device); hri_usart_set_US_IMR_TXEMPTY_bit(device->hw); @@ -564,7 +568,7 @@ static uint8_t _usart_get_hardware_index(const void *const hw) /** * \brief Retrieve ordinal number of the given USART hardware instance */ -uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const device) +uint8_t _usart_usart_sync_get_hardware_index(const struct _usart_sync_device *const device) { ASSERT(device); return _usart_get_hardware_index(device->hw); @@ -573,7 +577,7 @@ uint8_t _usart_sync_get_hardware_index(const struct _usart_sync_device *const de /** * \brief Retrieve ordinal number of the given USART hardware instance */ -uint8_t _usart_usart_async_get_hardware_index(const struct _usart_async_device *const device) +uint8_t _usart_async_get_hardware_index(const struct _usart_async_device *const device) { ASSERT(device); return _usart_get_hardware_index(device->hw); @@ -582,8 +586,8 @@ uint8_t _usart_usart_async_get_hardware_index(const struct _usart_async_device * /** * \brief Enable/disable USART interrupt */ -void _usart_usart_async_set_irq_state(struct _usart_async_device *const device, - const enum _usart_async_callback_type type, const bool state) +void _usart_async_set_irq_state(struct _usart_async_device *const device, const enum _usart_async_callback_type type, + const bool state) { ASSERT(device); if (state) { @@ -635,6 +639,47 @@ void *_usart_get_usart_dma(void) return (void *)NULL; } +/** + * \internal Usart interrupt handler + * + * \param[in] p The pointer to interrupt parameter + */ +static void _usart_interrupt_handler(struct _usart_async_device *device) +{ + ASSERT(device); + void *hw = device->hw; + + if (hri_usart_get_US_CSR_TXRDY_bit(hw) && hri_usart_get_US_IMR_TXRDY_bit(hw)) { + hri_usart_clear_US_IMR_TXRDY_bit(hw); + device->usart_cb.tx_byte_sent(device); + } else if (hri_usart_get_US_CSR_TXEMPTY_bit(hw) && hri_usart_get_US_IMR_TXEMPTY_bit(hw)) { + hri_usart_clear_US_IMR_TXEMPTY_bit(hw); + device->usart_cb.tx_done_cb(device); + } else if (hri_usart_get_US_CSR_RXRDY_bit(hw) && hri_usart_get_US_IMR_RXRDY_bit(hw)) { + if (hri_usart_read_US_CSR_reg(hw) & + + (US_CSR_OVRE | US_CSR_USART_LIN_FRAME | US_CSR_USART_LIN_PARE | US_CSR_USART_MANERR)) { + hri_usart_read_US_RHR_reg(hw); + hri_usart_write_US_CR_reg(hw, US_CR_RSTSTA); + return; + } + device->usart_cb.rx_done_cb(device, (uint8_t)hri_usart_read_US_RHR_reg(hw)); + } else if (hri_usart_read_US_CSR_reg(hw) & + + (US_CSR_OVRE | US_CSR_USART_LIN_FRAME | US_CSR_USART_LIN_PARE | US_CSR_USART_MANERR)) { + hri_usart_write_US_CR_reg(hw, US_CR_RSTSTA); + device->usart_cb.error_cb(device); + } +} + +/** + * \internal USART interrupt handler + */ +void USART1_Handler(void) +{ + _usart_interrupt_handler(_usart1_dev); +} + /** * \internal Retrieve ordinal number of the given usart hardware instance * diff --git a/bsp/microchip/same70/bsp/iar-project-connection.ipcf b/bsp/microchip/same70/bsp/iar-project-connection.ipcf index 05099d8482..b9277f0f8c 100644 --- a/bsp/microchip/same70/bsp/iar-project-connection.ipcf +++ b/bsp/microchip/same70/bsp/iar-project-connection.ipcf @@ -10,15 +10,20 @@ $PROJ_DIR$\examples $PROJ_DIR$\hal\include $PROJ_DIR$\hal\utils\include + $PROJ_DIR$\hpl\afec $PROJ_DIR$\hpl\core + $PROJ_DIR$\hpl\gmac $PROJ_DIR$\hpl\mcan $PROJ_DIR$\hpl\pio $PROJ_DIR$\hpl\pmc - $PROJ_DIR$\hpl\systick + $PROJ_DIR$\hpl\twihs $PROJ_DIR$\hpl\usart $PROJ_DIR$\hpl\xdmac $PROJ_DIR$\hri $PROJ_DIR$\ + $PROJ_DIR$\config + $PROJ_DIR$\ethernet_phy + $PROJ_DIR$\ $PROJ_DIR$\CMSIS\Core\Include $PROJ_DIR$\same70b\include @@ -29,15 +34,20 @@ $PROJ_DIR$\examples $PROJ_DIR$\hal\include $PROJ_DIR$\hal\utils\include + $PROJ_DIR$\hpl\afec $PROJ_DIR$\hpl\core + $PROJ_DIR$\hpl\gmac $PROJ_DIR$\hpl\mcan $PROJ_DIR$\hpl\pio $PROJ_DIR$\hpl\pmc - $PROJ_DIR$\hpl\systick + $PROJ_DIR$\hpl\twihs $PROJ_DIR$\hpl\usart $PROJ_DIR$\hpl\xdmac $PROJ_DIR$\hri $PROJ_DIR$\ + $PROJ_DIR$\config + $PROJ_DIR$\ethernet_phy + $PROJ_DIR$\ $PROJ_DIR$\CMSIS\Core\Include $PROJ_DIR$\same70b\include @@ -63,7 +73,9 @@ atmel_start_pins.h driver_init.c driver_init.h - led_switcher_main.c + ethernet_phy_main.c + ethernet_phy_main.h + main.c @@ -91,28 +103,42 @@ + config/hpl_afec_config.h + config/hpl_gmac_config.h config/hpl_mcan_config.h config/hpl_pmc_config.h - config/hpl_systick_ARMv7_config.h + config/hpl_twihs_config.h config/hpl_usart_config.h config/hpl_xdmac_config.h + config/ieee8023_mii_standard_config.h config/peripheral_clk_config.h + + ethernet_phy/ethernet_phy.c + ethernet_phy/ethernet_phy.h + ethernet_phy/ieee8023_mii_standard_register.h + + examples/driver_examples.c examples/driver_examples.h + hal/include/hal_adc_sync.h hal/include/hal_atomic.h hal/include/hal_can_async.h hal/include/hal_delay.h hal/include/hal_gpio.h + hal/include/hal_i2c_m_sync.h hal/include/hal_init.h hal/include/hal_io.h + hal/include/hal_mac_async.h hal/include/hal_sleep.h - hal/include/hal_usart_sync.h + hal/include/hal_usart_async.h + hal/include/hpl_adc_async.h + hal/include/hpl_adc_sync.h hal/include/hpl_can.h hal/include/hpl_can_async.h hal/include/hpl_core.h @@ -120,12 +146,16 @@ hal/include/hpl_dma.h hal/include/hpl_ext_irq.h hal/include/hpl_gpio.h + hal/include/hpl_i2c_m_async.h + hal/include/hpl_i2c_m_sync.h + hal/include/hpl_i2c_s_async.h + hal/include/hpl_i2c_s_sync.h hal/include/hpl_init.h hal/include/hpl_irq.h + hal/include/hpl_mac_async.h hal/include/hpl_missing_features.h hal/include/hpl_reset.h hal/include/hpl_sleep.h - hal/include/hpl_time_measure.h hal/include/hpl_usart.h hal/include/hpl_usart_async.h hal/include/hpl_usart_dma.h @@ -133,14 +163,17 @@ + hal/src/hal_adc_sync.c hal/src/hal_atomic.c hal/src/hal_can_async.c hal/src/hal_delay.c hal/src/hal_gpio.c + hal/src/hal_i2c_m_sync.c hal/src/hal_init.c hal/src/hal_io.c + hal/src/hal_mac_async.c hal/src/hal_sleep.c - hal/src/hal_usart_sync.c + hal/src/hal_usart_async.c @@ -164,12 +197,21 @@ hal/utils/src/utils_ringbuffer.c + + hpl/afec/hpl_afec.c + + hpl/core/hpl_core_m7_base.c hpl/core/hpl_core_port.h hpl/core/hpl_init.c + + hpl/gmac/hpl_gmac.c + hpl/gmac/hpl_gmac_base.h + + hpl/mcan/hpl_mcan.c hpl/mcan/hpl_mcan.h @@ -185,8 +227,8 @@ hpl/pmc/hpl_sleep.c - - hpl/systick/hpl_systick_ARMv7_base.c + + hpl/twihs/hpl_twihs.c diff --git a/bsp/microchip/same70/bsp/same70b/gcc/gcc/same70q21b_flash.ld b/bsp/microchip/same70/bsp/same70b/gcc/gcc/same70q21b_flash.ld index f09a9ebda1..ad00686c06 100644 --- a/bsp/microchip/same70/bsp/same70b/gcc/gcc/same70q21b_flash.ld +++ b/bsp/microchip/same70/bsp/same70b/gcc/gcc/same70q21b_flash.ld @@ -61,6 +61,31 @@ SECTIONS *(.rodata .rodata* .gnu.linkonce.r.*) *(.ARM.extab* .gnu.linkonce.armextab.*) + /* section information for finsh shell */ + . = ALIGN(4); + __fsymtab_start = .; + KEEP(*(FSymTab)) + __fsymtab_end = .; + . = ALIGN(4); + __vsymtab_start = .; + KEEP(*(VSymTab)) + __vsymtab_end = .; + . = ALIGN(4); + + /* section information for initial. */ + . = ALIGN(4); + __rt_init_start = .; + KEEP(*(SORT(.rti_fn*))) + __rt_init_end = .; + . = ALIGN(4); + + /* section information for utest */ + . = ALIGN(4); + __rt_utest_tc_tab_start = .; + KEEP(*(UtestTcTab)) + __rt_utest_tc_tab_end = .; + + /* Support C constructors, and C destructors in both user code and the C library. This also provides support for C++ code. */ . = ALIGN(4); diff --git a/bsp/microchip/same70/rtconfig.h b/bsp/microchip/same70/rtconfig.h index f16d65036b..264c41b513 100644 --- a/bsp/microchip/same70/rtconfig.h +++ b/bsp/microchip/same70/rtconfig.h @@ -17,6 +17,9 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 256 +#define RT_USING_TIMER_SOFT +#define RT_TIMER_THREAD_PRIO 4 +#define RT_TIMER_THREAD_STACK_SIZE 512 /* kservice optimization */ @@ -55,15 +58,38 @@ #define RT_USING_USER_MAIN #define RT_MAIN_THREAD_STACK_SIZE 2048 #define RT_MAIN_THREAD_PRIORITY 10 +#define RT_USING_MSH +#define RT_USING_FINSH +#define FINSH_USING_MSH +#define FINSH_THREAD_NAME "tshell" +#define FINSH_THREAD_PRIORITY 20 +#define FINSH_THREAD_STACK_SIZE 4096 +#define FINSH_USING_HISTORY +#define FINSH_HISTORY_LINES 5 +#define FINSH_USING_SYMTAB +#define FINSH_CMD_SIZE 80 +#define MSH_USING_BUILT_IN_COMMANDS +#define FINSH_USING_DESCRIPTION +#define FINSH_ARG_MAX 10 +#define RT_USING_DFS +#define DFS_USING_POSIX +#define DFS_USING_WORKDIR +#define DFS_FILESYSTEMS_MAX 4 +#define DFS_FILESYSTEM_TYPES_MAX 4 +#define DFS_FD_MAX 16 +#define RT_USING_DFS_DEVFS /* Device Drivers */ #define RT_USING_DEVICE_IPC +#define RT_USING_SYSTEM_WORKQUEUE +#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048 +#define RT_SYSTEM_WORKQUEUE_PRIORITY 23 #define RT_USING_SERIAL #define RT_USING_SERIAL_V1 #define RT_SERIAL_USING_DMA #define RT_SERIAL_RB_BUFSZ 64 -#define RT_USING_PIN +#define RT_USING_I2C /* Using USB */ @@ -74,6 +100,17 @@ /* POSIX (Portable Operating System Interface) layer */ +#define RT_USING_POSIX_FS +#define RT_USING_POSIX_DEVIO +#define RT_USING_POSIX_POLL +#define RT_USING_POSIX_SELECT +#define RT_USING_POSIX_SOCKET +#define RT_USING_POSIX_AIO +#define RT_USING_POSIX_DELAY +#define RT_USING_POSIX_CLOCK +#define RT_USING_POSIX_TIMER +#define RT_USING_PTHREADS +#define PTHREAD_NUM_MAX 8 /* Interprocess Communication (IPC) */ @@ -83,6 +120,63 @@ /* Network */ +#define RT_USING_SAL +#define SAL_INTERNET_CHECK + +/* protocol stack implement */ + +#define SAL_USING_LWIP +#define SAL_USING_POSIX +#define RT_USING_NETDEV +#define NETDEV_USING_IFCONFIG +#define NETDEV_USING_PING +#define NETDEV_USING_NETSTAT +#define NETDEV_USING_AUTO_DEFAULT +#define NETDEV_IPV4 1 +#define NETDEV_IPV6 0 +#define RT_USING_LWIP +#define RT_USING_LWIP_LOCAL_VERSION +#define RT_USING_LWIP212 +#define RT_USING_LWIP_VER_NUM 0x20102 +#define RT_LWIP_MEM_ALIGNMENT 4 +#define RT_LWIP_IGMP +#define RT_LWIP_ICMP +#define RT_LWIP_DNS +#define RT_LWIP_DHCP +#define IP_SOF_BROADCAST 1 +#define IP_SOF_BROADCAST_RECV 1 + +/* Static IPv4 Address */ + +#define RT_LWIP_IPADDR "192.168.1.30" +#define RT_LWIP_GWADDR "192.168.1.1" +#define RT_LWIP_MSKADDR "255.255.255.0" +#define RT_LWIP_UDP +#define RT_LWIP_TCP +#define RT_LWIP_RAW +#define RT_MEMP_NUM_NETCONN 8 +#define RT_LWIP_PBUF_NUM 16 +#define RT_LWIP_RAW_PCB_NUM 4 +#define RT_LWIP_UDP_PCB_NUM 4 +#define RT_LWIP_TCP_PCB_NUM 4 +#define RT_LWIP_TCP_SEG_NUM 40 +#define RT_LWIP_TCP_SND_BUF 8196 +#define RT_LWIP_TCP_WND 8196 +#define RT_LWIP_TCPTHREAD_PRIORITY 10 +#define RT_LWIP_TCPTHREAD_MBOX_SIZE 8 +#define RT_LWIP_TCPTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_PRIORITY 12 +#define RT_LWIP_ETHTHREAD_STACKSIZE 1024 +#define RT_LWIP_ETHTHREAD_MBOX_SIZE 8 +#define LWIP_NETIF_STATUS_CALLBACK 1 +#define LWIP_NETIF_LINK_CALLBACK 1 +#define SO_REUSE 1 +#define LWIP_SO_RCVTIMEO 1 +#define LWIP_SO_SNDTIMEO 1 +#define LWIP_SO_RCVBUF 1 +#define LWIP_SO_LINGER 0 +#define LWIP_NETIF_LOOPBACK 0 +#define RT_LWIP_USING_PING /* Utilities */ @@ -172,5 +266,15 @@ #define SAME70_CAN0 #define SAME70_ADC0 +#define SAME70_I2C0 +#define SAME70_GMAC + +/* Application Demo Config */ + +#define SAM_CAN_EXAMPLE +#define SAM_ADC_EXAMPLE +#define SAM_I2C_EXAMPLE +#define SAM_LWIP_EXAMPLE +#define SOC_SAME70 #endif -- GitLab