mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-27 12:49:01 +08:00
Add driver for CMSIS-Driver
This commit is contained in:
parent
b357485523
commit
b792304cf8
1
.github/workflows/test.yml
vendored
1
.github/workflows/test.yml
vendored
@ -359,6 +359,7 @@ jobs:
|
||||
- path: stm32/nucleo-f746zg-make-freertos-builtin
|
||||
- path: stm32/nucleo-f746zg-make-freertos-tcp
|
||||
- path: stm32/nucleo-f746zg-make-baremetal-builtin-rndis
|
||||
- path: stm32/nucleo-f746zg-make-baremetal-builtin-cmsis_driver
|
||||
- path: stm32/nucleo-g031-make-baremetal-builtin
|
||||
- path: stm32/nucleo-h563zi-make-baremetal-builtin
|
||||
- path: stm32/nucleo-h563zi-make-freertos-builtin
|
||||
|
@ -0,0 +1,212 @@
|
||||
/******************************************************************************
|
||||
* File Name : MX_Device.h
|
||||
* Date : 14/03/2023 13:27:52
|
||||
* Description : STM32Cube MX parameter definitions
|
||||
* Note : This file is generated by STM32CubeMX (DO NOT EDIT!)
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef __MX_DEVICE_H
|
||||
#define __MX_DEVICE_H
|
||||
|
||||
/*---------------------------- Clock Configuration ---------------------------*/
|
||||
|
||||
#define MX_LSI_VALUE 32000
|
||||
#define MX_LSE_VALUE 32768
|
||||
#define MX_HSI_VALUE 16000000
|
||||
#define MX_HSE_VALUE 25000000
|
||||
#define MX_EXTERNAL_CLOCK_VALUE 12288000
|
||||
#define MX_SYSCLKFreq_VALUE 216000000
|
||||
#define MX_HCLKFreq_Value 216000000
|
||||
#define MX_FCLKCortexFreq_Value 216000000
|
||||
#define MX_CortexFreq_Value 216000000
|
||||
#define MX_AHBFreq_Value 216000000
|
||||
#define MX_APB1Freq_Value 54000000
|
||||
#define MX_APB2Freq_Value 108000000
|
||||
#define MX_APB1TimFreq_Value 108000000
|
||||
#define MX_APB2TimFreq_Value 216000000
|
||||
#define MX_EthernetFreq_Value 216000000
|
||||
#define MX_CECFreq_Value 32786
|
||||
#define MX_LCDTFToutputFreq_Value 96000000
|
||||
#define MX_I2C1Freq_Value 54000000
|
||||
#define MX_I2C2Freq_Value 54000000
|
||||
#define MX_I2C3Freq_Value 54000000
|
||||
#define MX_I2C4Freq_Value 54000000
|
||||
#define MX_I2SFreq_Value 192000000
|
||||
#define MX_SAI1Freq_Value 192000000
|
||||
#define MX_SAI2Freq_Value 192000000
|
||||
#define MX_SDMMCFreq_Value 216000000
|
||||
#define MX_RTCFreq_Value 32000
|
||||
#define MX_USART1Freq_Value 108000000
|
||||
#define MX_USART2Freq_Value 54000000
|
||||
#define MX_USART3Freq_Value 54000000
|
||||
#define MX_UART4Freq_Value 54000000
|
||||
#define MX_UART5Freq_Value 54000000
|
||||
#define MX_UART8Freq_Value 54000000
|
||||
#define MX_UART7Freq_Value 54000000
|
||||
#define MX_USART6Freq_Value 108000000
|
||||
#define MX_USBFreq_Value 48000000
|
||||
#define MX_WatchDogFreq_Value 32000
|
||||
#define MX_LPTIM1Freq_Value 54000000
|
||||
#define MX_SPDIFRXFreq_Value 192000000
|
||||
#define MX_MCO1PinFreq_Value 16000000
|
||||
#define MX_MCO2PinFreq_Value 216000000
|
||||
|
||||
/*-------------------------------- CORTEX_M7 --------------------------------*/
|
||||
|
||||
#define MX_CORTEX_M7 1
|
||||
|
||||
/* GPIO Configuration */
|
||||
|
||||
/*-------------------------------- ETH --------------------------------*/
|
||||
|
||||
#define MX_ETH 1
|
||||
|
||||
/* GPIO Configuration */
|
||||
|
||||
/* Pin PA1 */
|
||||
#define MX_ETH_REF_CLK_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_REF_CLK_Pin PA1
|
||||
#define MX_ETH_REF_CLK_GPIOx GPIOA
|
||||
#define MX_ETH_REF_CLK_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_REF_CLK_GPIO_Pin GPIO_PIN_1
|
||||
#define MX_ETH_REF_CLK_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_REF_CLK_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PA7 */
|
||||
#define MX_ETH_CRS_DV_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_CRS_DV_Pin PA7
|
||||
#define MX_ETH_CRS_DV_GPIOx GPIOA
|
||||
#define MX_ETH_CRS_DV_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_CRS_DV_GPIO_Pin GPIO_PIN_7
|
||||
#define MX_ETH_CRS_DV_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_CRS_DV_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PC4 */
|
||||
#define MX_ETH_RXD0_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_RXD0_Pin PC4
|
||||
#define MX_ETH_RXD0_GPIOx GPIOC
|
||||
#define MX_ETH_RXD0_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_RXD0_GPIO_Pin GPIO_PIN_4
|
||||
#define MX_ETH_RXD0_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_RXD0_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PC5 */
|
||||
#define MX_ETH_RXD1_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_RXD1_Pin PC5
|
||||
#define MX_ETH_RXD1_GPIOx GPIOC
|
||||
#define MX_ETH_RXD1_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_RXD1_GPIO_Pin GPIO_PIN_5
|
||||
#define MX_ETH_RXD1_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_RXD1_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PG11 */
|
||||
#define MX_ETH_TX_EN_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_TX_EN_Pin PG11
|
||||
#define MX_ETH_TX_EN_GPIOx GPIOG
|
||||
#define MX_ETH_TX_EN_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_TX_EN_GPIO_Pin GPIO_PIN_11
|
||||
#define MX_ETH_TX_EN_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_TX_EN_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PA2 */
|
||||
#define MX_ETH_MDIO_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_MDIO_Pin PA2
|
||||
#define MX_ETH_MDIO_GPIOx GPIOA
|
||||
#define MX_ETH_MDIO_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_MDIO_GPIO_Pin GPIO_PIN_2
|
||||
#define MX_ETH_MDIO_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_MDIO_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PB13 */
|
||||
#define MX_ETH_TXD1_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_TXD1_Pin PB13
|
||||
#define MX_ETH_TXD1_GPIOx GPIOB
|
||||
#define MX_ETH_TXD1_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_TXD1_GPIO_Pin GPIO_PIN_13
|
||||
#define MX_ETH_TXD1_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_TXD1_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PG13 */
|
||||
#define MX_ETH_TXD0_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_TXD0_Pin PG13
|
||||
#define MX_ETH_TXD0_GPIOx GPIOG
|
||||
#define MX_ETH_TXD0_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_TXD0_GPIO_Pin GPIO_PIN_13
|
||||
#define MX_ETH_TXD0_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_TXD0_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* Pin PC1 */
|
||||
#define MX_ETH_MDC_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_ETH_MDC_Pin PC1
|
||||
#define MX_ETH_MDC_GPIOx GPIOC
|
||||
#define MX_ETH_MDC_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_ETH_MDC_GPIO_Pin GPIO_PIN_1
|
||||
#define MX_ETH_MDC_GPIO_AF GPIO_AF11_ETH
|
||||
#define MX_ETH_MDC_GPIO_Mode GPIO_MODE_AF_PP
|
||||
|
||||
/* NVIC Configuration */
|
||||
|
||||
/* NVIC ETH_IRQn */
|
||||
#define MX_ETH_IRQn_interruptPremptionPriority 0
|
||||
#define MX_ETH_IRQn_PriorityGroup NVIC_PRIORITYGROUP_4
|
||||
#define MX_ETH_IRQn_Subriority 0
|
||||
|
||||
/*-------------------------------- RNG --------------------------------*/
|
||||
|
||||
#define MX_RNG 1
|
||||
|
||||
/* GPIO Configuration */
|
||||
|
||||
/*-------------------------------- SYS --------------------------------*/
|
||||
|
||||
#define MX_SYS 1
|
||||
|
||||
/* GPIO Configuration */
|
||||
|
||||
/*-------------------------------- USART3 --------------------------------*/
|
||||
|
||||
#define MX_USART3 1
|
||||
|
||||
#define MX_USART3_VM VM_ASYNC
|
||||
|
||||
/* GPIO Configuration */
|
||||
|
||||
/* Pin PD8 */
|
||||
#define MX_USART3_TX_GPIO_ModeDefaultPP GPIO_MODE_AF_PP
|
||||
#define MX_USART3_TX_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_USART3_TX_Pin PD8
|
||||
#define MX_USART3_TX_GPIOx GPIOD
|
||||
#define MX_USART3_TX_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_USART3_TX_GPIO_Pin GPIO_PIN_8
|
||||
#define MX_USART3_TX_GPIO_AF GPIO_AF7_USART3
|
||||
|
||||
/* Pin PD9 */
|
||||
#define MX_USART3_RX_GPIO_ModeDefaultPP GPIO_MODE_AF_PP
|
||||
#define MX_USART3_RX_GPIO_Speed GPIO_SPEED_FREQ_VERY_HIGH
|
||||
#define MX_USART3_RX_Pin PD9
|
||||
#define MX_USART3_RX_GPIOx GPIOD
|
||||
#define MX_USART3_RX_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_USART3_RX_GPIO_Pin GPIO_PIN_9
|
||||
#define MX_USART3_RX_GPIO_AF GPIO_AF7_USART3
|
||||
|
||||
/*-------------------------------- NVIC --------------------------------*/
|
||||
|
||||
#define MX_NVIC 1
|
||||
|
||||
/*-------------------------------- GPIO --------------------------------*/
|
||||
|
||||
#define MX_GPIO 1
|
||||
|
||||
/* GPIO Configuration */
|
||||
|
||||
/* Pin PB7 */
|
||||
#define MX_PB7_GPIO_Speed GPIO_SPEED_FREQ_LOW
|
||||
#define MX_PB7_Pin PB7
|
||||
#define MX_PB7_GPIOx GPIOB
|
||||
#define MX_PB7_PinState GPIO_PIN_RESET
|
||||
#define MX_PB7_GPIO_PuPd GPIO_NOPULL
|
||||
#define MX_PB7_GPIO_Pin GPIO_PIN_7
|
||||
#define MX_PB7_GPIO_ModeDefaultOutputPP GPIO_MODE_OUTPUT_PP
|
||||
|
||||
#endif /* __MX_DEVICE_H */
|
||||
|
@ -0,0 +1,82 @@
|
||||
CFLAGS = -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion
|
||||
CFLAGS += -Wformat-truncation -fno-common -Wconversion -Wno-sign-conversion
|
||||
CFLAGS += -g3 -Os -ffunction-sections -fdata-sections
|
||||
CFLAGS += -I.
|
||||
# CMSIS Driver specifics, and its dependencies
|
||||
CFLAGS += -Icmsis_core/CMSIS/Core/Include # CMSIS core headers
|
||||
CFLAGS += -Icmsis_core/CMSIS/Driver/Include -Icmsis_driver/ETH # CMSIS Driver core and ETH headers
|
||||
CFLAGS += -Icmsis_mcu/CMSIS/Driver # CMSIS Driver device driver headers
|
||||
CFLAGS += -D__MEMORY_AT\(x\)= # disable using specific memory address for Eth buffers
|
||||
CFLAGS += -Icmsis_mcu/Drivers/CMSIS/Device/ST/STM32F7xx/Include -DSTM32F746xx # CMSIS device headers
|
||||
CFLAGS += -Icmsis_mcu/Drivers/STM32F7xx_HAL_Driver/Inc/ # HAL headers, required by CMSIS Driver device driver (HAL-based)
|
||||
CFLAGS += -Icmsis_mcu/MDK/Templates/Inc/ # pull stm32f7xx_hal_conf.h (HAL configuration)
|
||||
CFLAGS += -DRTE_DEVICE_HAL_ETH -DRTE_DEVICE_HAL_GPIO -DRTE_DEVICE_HAL_RCC # configure it
|
||||
CFLAGS += -DRTE_DEVICE_HAL_COMMON -DRTE_DEVICE_FRAMEWORK_CUBE_MX
|
||||
|
||||
CFLAGS += -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16
|
||||
LDFLAGS ?= -Tlink.ld -nostdlib -nostartfiles --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
|
||||
|
||||
SOURCES = main.c syscalls.c sysinit.c
|
||||
# CMSIS Driver specifics, and its dependencies
|
||||
SOURCES += cmsis_driver/ETH/PHY_LAN8742A.c # CMSIS Driver for the PHY present in this board
|
||||
CFLAGS += -Wno-conversion # avoid warnings when building it
|
||||
SOURCES += cmsis_mcu/CMSIS/Driver/EMAC_STM32F7xx.c # CMSIS Driver for EMAC peripheral
|
||||
SOURCES += cmsis_mcu/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_eth.c # HAL sources required by the driver
|
||||
SOURCES += cmsis_mcu/Drivers/STM32F7xx_HAL_Driver/Src/stm32f7xx_hal_rcc.c
|
||||
SOURCES += cmsis_mcu/Drivers/CMSIS/Device/ST/STM32F7xx/Source/Templates/gcc/startup_stm32f746xx.s # ST startup file. Compiler-dependent!
|
||||
|
||||
# Mongoose-specific. See https://mongoose.ws/documentation/#build-options
|
||||
SOURCES += mongoose.c net.c packed_fs.c
|
||||
CFLAGS += -DMG_ENABLE_TCPIP=1 -DMG_ARCH=MG_ARCH_NEWLIB -DMG_ENABLE_CUSTOM_MILLIS=1
|
||||
CFLAGS += -DMG_ENABLE_CUSTOM_RANDOM=1 -DMG_ENABLE_PACKED_FS=1
|
||||
CFLAGS += -DMG_ENABLE_DRIVER_CMSIS=1 $(CFLAGS_EXTRA)
|
||||
|
||||
# Example specific build options. See README.md
|
||||
CFLAGS += -DHTTP_URL=\"http://0.0.0.0/\" -DHTTPS_URL=\"https://0.0.0.0/\"
|
||||
|
||||
ifeq ($(OS),Windows_NT)
|
||||
RM = cmd /C del /Q /F /S
|
||||
else
|
||||
RM = rm -rf
|
||||
endif
|
||||
|
||||
all build example: firmware.bin
|
||||
|
||||
firmware.bin: firmware.elf
|
||||
arm-none-eabi-objcopy -O binary $< $@
|
||||
|
||||
firmware.elf: cmsis_core cmsis_driver cmsis_mcu $(SOURCES) hal.h link.ld Makefile
|
||||
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
|
||||
|
||||
flash: firmware.bin
|
||||
st-flash --reset write $< 0x8000000
|
||||
|
||||
cmsis_core: # ARM CMSIS core headers
|
||||
git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
|
||||
cmsis_driver: # ARM CMSIS Driver code and headers
|
||||
git clone --depth 1 -b 2.7.2 https://github.com/ARM-software/CMSIS-Driver $@
|
||||
cmsis_mcu: # Keil CMSIS headers and drivers for STM32F7 series (CMSIS-pack)
|
||||
curl -sL https://www.keil.com/pack/Keil.STM32F7xx_DFP.2.15.2.pack -o $@.zip
|
||||
mkdir $@ && cd $@ && unzip -q ../$@.zip
|
||||
mbedtls: # mbedTLS library
|
||||
git clone --depth 1 -b v2.28.2 https://github.com/mbed-tls/mbedtls $@
|
||||
|
||||
ifeq ($(TLS), mbedtls)
|
||||
CFLAGS += -DMG_TLS=MG_TLS_MBED -Wno-conversion -Imbedtls/include
|
||||
CFLAGS += -DMBEDTLS_CONFIG_FILE=\"mbedtls_config.h\" mbedtls/library/*.c
|
||||
firmware.elf: mbedtls
|
||||
endif
|
||||
|
||||
# Automated remote test. Requires env variable VCON_API_KEY set. See https://vcon.io/automated-firmware-tests/
|
||||
DEVICE_URL ?= https://dash.vcon.io/api/v3/devices/5
|
||||
update: firmware.bin
|
||||
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/ota --data-binary @$<
|
||||
|
||||
test update: CFLAGS += -DUART_DEBUG=USART1
|
||||
test: update
|
||||
curl --fail-with-body -su :$(VCON_API_KEY) $(DEVICE_URL)/tx?t=5 | tee /tmp/output.txt
|
||||
grep 'READY, IP:' /tmp/output.txt # Check for network init
|
||||
# grep 'MQTT connected' /tmp/output.txt # Check for MQTT connection success
|
||||
|
||||
clean:
|
||||
$(RM) firmware.* *.su cmsis_core cmsis_driver cmsis_mcu* mbedtls
|
@ -0,0 +1,17 @@
|
||||
# CMSIS-Driver example
|
||||
|
||||
Mongoose includes a driver for CMSIS-Driver, that is, Mongoose built-in TCP/IP stack can run over any (ARM) chip that has a CMSIS Driver for its Ethernet controller, and uses a PHY that also has a CMSIS Driver. You can follow this example to use Mongoose there, the Makefile in this example performs the following list of actions.
|
||||
|
||||
Actions:
|
||||
|
||||
- Pull CMSIS core, this also includes the basic support for CMSIS Driver
|
||||
- Pull CMSIS Driver, this repository has driver code for several widely used PHYs and some Ethernet chips (stand-alone controllers, not MCUs)
|
||||
- Pull the device family CMSIS Pack, this includes CMSIS headers and also includes CMSIS Drivers for those peripherals that have Middleware (Ethernet, CAN, UART...) available
|
||||
- The rest of the job is to find and solve the driver dependencies. In this example, the CMSIS Driver for the STM32F746 uses the STM32 HAL, so we have copied some files from an STM32CubeMX generated project in order to have some defines available, then picked the correct sources to compile, and provided a HAL_GetTick() function to satisfy those parts of the HAL that use it, without having to include more pieces of the HAL, as we already have a time base in place.
|
||||
- Finally,
|
||||
- enable the driver by defining `MG_ENABLE_DRIVER_CMSIS=1`
|
||||
- select it in your `main.c`
|
||||
|
||||
```c
|
||||
struct mg_tcpip_if mif = {.driver = &mg_tcpip_driver_cmsis}
|
||||
```
|
@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2022 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
// https://www.st.com/resource/en/reference_manual/dm00124865-stm32f75xxx-and-stm32f74xxx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
|
||||
// https://www.st.com/resource/en/datasheet/stm32f746zg.pdf
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stm32f746xx.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define BIT(x) (1UL << (x))
|
||||
#define SETBITS(R, CLEARMASK, SETMASK) (R) = ((R) & ~(CLEARMASK)) | (SETMASK)
|
||||
#define PIN(bank, num) ((((bank) - 'A') << 8) | (num))
|
||||
#define PINNO(pin) (pin & 255)
|
||||
#define PINBANK(pin) (pin >> 8)
|
||||
|
||||
#define LED1 PIN('B', 0) // On-board LED pin (green)
|
||||
#define LED2 PIN('B', 7) // On-board LED pin (blue)
|
||||
#define LED3 PIN('B', 14) // On-board LED pin (red)
|
||||
|
||||
#define LED LED2 // Use blue LED for blinking
|
||||
|
||||
/* System clock
|
||||
5.3.3: APB1 clock <= 54MHz; APB2 clock <= 108MHz
|
||||
3.3.2, Table 5: configure flash latency (WS) in accordance to clock freq
|
||||
38.4: The AHB clock frequency must be at least 25 MHz when the Ethernet
|
||||
controller is used */
|
||||
enum { APB1_PRE = 5 /* AHB clock / 4 */, APB2_PRE = 4 /* AHB clock / 2 */ };
|
||||
enum { PLL_HSI = 16, PLL_M = 8, PLL_N = 216, PLL_P = 2 }; // Run at 216 Mhz
|
||||
#define FLASH_LATENCY 7
|
||||
#define SYS_FREQUENCY ((PLL_HSI * PLL_N / PLL_M / PLL_P) * 1000000)
|
||||
#define APB2_FREQUENCY (SYS_FREQUENCY / (BIT(APB2_PRE - 3)))
|
||||
#define APB1_FREQUENCY (SYS_FREQUENCY / (BIT(APB1_PRE - 3)))
|
||||
|
||||
static inline void spin(volatile uint32_t count) {
|
||||
while (count--) (void) 0;
|
||||
}
|
||||
|
||||
enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG };
|
||||
enum { GPIO_OTYPE_PUSH_PULL, GPIO_OTYPE_OPEN_DRAIN };
|
||||
enum { GPIO_SPEED_LOW, GPIO_SPEED_MEDIUM, GPIO_SPEED_HIGH, GPIO_SPEED_INSANE };
|
||||
enum { GPIO_PULL_NONE, GPIO_PULL_UP, GPIO_PULL_DOWN };
|
||||
#define GPIO(N) ((GPIO_TypeDef *) (0x40020000 + 0x400 * (N)))
|
||||
|
||||
static GPIO_TypeDef *gpio_bank(uint16_t pin) { return GPIO(PINBANK(pin)); }
|
||||
static inline void gpio_toggle(uint16_t pin) {
|
||||
GPIO_TypeDef *gpio = gpio_bank(pin);
|
||||
uint32_t mask = BIT(PINNO(pin));
|
||||
gpio->BSRR = mask << (gpio->ODR & mask ? 16 : 0);
|
||||
}
|
||||
static inline int gpio_read(uint16_t pin) {
|
||||
return gpio_bank(pin)->IDR & BIT(PINNO(pin)) ? 1 : 0;
|
||||
}
|
||||
static inline void gpio_write(uint16_t pin, bool val) {
|
||||
GPIO_TypeDef *gpio = gpio_bank(pin);
|
||||
gpio->BSRR = BIT(PINNO(pin)) << (val ? 0 : 16);
|
||||
}
|
||||
static inline void gpio_init(uint16_t pin, uint8_t mode, uint8_t type,
|
||||
uint8_t speed, uint8_t pull, uint8_t af) {
|
||||
GPIO_TypeDef *gpio = gpio_bank(pin);
|
||||
uint8_t n = (uint8_t) (PINNO(pin));
|
||||
RCC->AHB1ENR |= BIT(PINBANK(pin)); // Enable GPIO clock
|
||||
SETBITS(gpio->OTYPER, 1UL << n, ((uint32_t) type) << n);
|
||||
SETBITS(gpio->OSPEEDR, 3UL << (n * 2), ((uint32_t) speed) << (n * 2));
|
||||
SETBITS(gpio->PUPDR, 3UL << (n * 2), ((uint32_t) pull) << (n * 2));
|
||||
SETBITS(gpio->AFR[n >> 3], 15UL << ((n & 7) * 4),
|
||||
((uint32_t) af) << ((n & 7) * 4));
|
||||
SETBITS(gpio->MODER, 3UL << (n * 2), ((uint32_t) mode) << (n * 2));
|
||||
}
|
||||
static inline void gpio_input(uint16_t pin) {
|
||||
gpio_init(pin, GPIO_MODE_INPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH,
|
||||
GPIO_PULL_NONE, 0);
|
||||
}
|
||||
static inline void gpio_output(uint16_t pin) {
|
||||
gpio_init(pin, GPIO_MODE_OUTPUT, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH,
|
||||
GPIO_PULL_NONE, 0);
|
||||
}
|
||||
|
||||
static inline void irq_exti_attach(uint16_t pin) {
|
||||
uint8_t bank = (uint8_t) (PINBANK(pin)), n = (uint8_t) (PINNO(pin));
|
||||
SYSCFG->EXTICR[n / 4] &= ~(15UL << ((n % 4) * 4));
|
||||
SYSCFG->EXTICR[n / 4] |= (uint32_t) (bank << ((n % 4) * 4));
|
||||
EXTI->IMR |= BIT(n);
|
||||
EXTI->RTSR |= BIT(n);
|
||||
EXTI->FTSR |= BIT(n);
|
||||
int irqvec = n < 5 ? 6 + n : n < 10 ? 23 : 40; // IRQ vector index, 10.1.2
|
||||
NVIC_SetPriority(irqvec, 3);
|
||||
NVIC_EnableIRQ(irqvec);
|
||||
}
|
||||
|
||||
#ifndef UART_DEBUG
|
||||
#define UART_DEBUG USART3
|
||||
#endif
|
||||
|
||||
static inline void uart_init(USART_TypeDef *uart, unsigned long baud) {
|
||||
uint8_t af = 7; // Alternate function
|
||||
uint16_t rx = 0, tx = 0; // pins
|
||||
uint32_t freq = 0; // Bus frequency. UART1 is on APB2, rest on APB1
|
||||
|
||||
if (uart == USART1) freq = APB2_FREQUENCY, RCC->APB2ENR |= BIT(4);
|
||||
if (uart == USART2) freq = APB1_FREQUENCY, RCC->APB1ENR |= BIT(17);
|
||||
if (uart == USART3) freq = APB1_FREQUENCY, RCC->APB1ENR |= BIT(18);
|
||||
|
||||
if (uart == USART1) tx = PIN('A', 9), rx = PIN('A', 10);
|
||||
if (uart == USART2) tx = PIN('A', 2), rx = PIN('A', 3);
|
||||
if (uart == USART3) tx = PIN('D', 8), rx = PIN('D', 9);
|
||||
|
||||
gpio_init(tx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af);
|
||||
gpio_init(rx, GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_HIGH, 0, af);
|
||||
uart->CR1 = 0; // Disable this UART
|
||||
uart->BRR = freq / baud; // Set baud rate
|
||||
uart->CR1 |= BIT(0) | BIT(2) | BIT(3); // Set UE, RE, TE
|
||||
}
|
||||
static inline void uart_write_byte(USART_TypeDef *uart, uint8_t byte) {
|
||||
uart->TDR = byte;
|
||||
while ((uart->ISR & BIT(7)) == 0) spin(1);
|
||||
}
|
||||
static inline void uart_write_buf(USART_TypeDef *uart, char *buf, size_t len) {
|
||||
while (len-- > 0) uart_write_byte(uart, *(uint8_t *) buf++);
|
||||
}
|
||||
static inline int uart_read_ready(USART_TypeDef *uart) {
|
||||
return uart->ISR & BIT(5); // If RXNE bit is set, data is ready
|
||||
}
|
||||
static inline uint8_t uart_read_byte(USART_TypeDef *uart) {
|
||||
return (uint8_t) (uart->RDR & 255);
|
||||
}
|
||||
|
||||
static inline void rng_init(void) {
|
||||
RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN;
|
||||
RNG->CR |= RNG_CR_RNGEN;
|
||||
}
|
||||
static inline uint32_t rng_read(void) {
|
||||
while ((RNG->SR & RNG_SR_DRDY) == 0) (void) 0;
|
||||
return RNG->DR;
|
||||
}
|
||||
|
||||
static inline void ethernet_init(void) {
|
||||
// Initialise Ethernet. Enable MAC GPIO pins, see
|
||||
// https://www.farnell.com/datasheets/2014265.pdf section 6.10
|
||||
uint16_t pins[] = {PIN('A', 1), PIN('A', 2), PIN('A', 7),
|
||||
PIN('B', 13), PIN('C', 1), PIN('C', 4),
|
||||
PIN('C', 5), PIN('G', 11), PIN('G', 13)};
|
||||
for (size_t i = 0; i < sizeof(pins) / sizeof(pins[0]); i++) {
|
||||
gpio_init(pins[i], GPIO_MODE_AF, GPIO_OTYPE_PUSH_PULL, GPIO_SPEED_INSANE,
|
||||
GPIO_PULL_NONE, 11); // 11 is the Ethernet function
|
||||
}
|
||||
NVIC_EnableIRQ(ETH_IRQn); // Setup Ethernet IRQ handler
|
||||
SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; // Use RMII. Goes first!
|
||||
RCC->AHB1ENR |=
|
||||
RCC_AHB1ENR_ETHMACEN | RCC_AHB1ENR_ETHMACTXEN | RCC_AHB1ENR_ETHMACRXEN;
|
||||
}
|
||||
|
||||
#define UUID ((uint8_t *) UID_BASE) // Unique 96-bit chip ID. TRM 41.1
|
||||
|
||||
// Helper macro for MAC generation
|
||||
#define GENERATE_LOCALLY_ADMINISTERED_MAC() \
|
||||
{ \
|
||||
2, UUID[0] ^ UUID[1], UUID[2] ^ UUID[3], UUID[4] ^ UUID[5], \
|
||||
UUID[6] ^ UUID[7] ^ UUID[8], UUID[9] ^ UUID[10] ^ UUID[11] \
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
ENTRY(Reset_Handler);
|
||||
MEMORY {
|
||||
flash(rx) : ORIGIN = 0x08000000, LENGTH = 1024k
|
||||
sram(rwx) : ORIGIN = 0x20000000, LENGTH = 320k
|
||||
}
|
||||
_estack = ORIGIN(sram) + LENGTH(sram); /* stack points to end of SRAM */
|
||||
|
||||
SECTIONS {
|
||||
.vectors : { KEEP(*(.isr_vector)) } > flash
|
||||
.text : { *(.text* .text.*) } > flash
|
||||
.rodata : { *(.rodata*) } > flash
|
||||
|
||||
.data : {
|
||||
_sdata = .; /* for init_ram() */
|
||||
*(.first_data)
|
||||
*(.data SORT(.data.*))
|
||||
_edata = .; /* for init_ram() */
|
||||
} > sram AT > flash
|
||||
_sidata = LOADADDR(.data);
|
||||
|
||||
.bss : {
|
||||
_sbss = .; /* for init_ram() */
|
||||
*(.bss SORT(.bss.*) COMMON)
|
||||
_ebss = .; /* for init_ram() */
|
||||
} > sram
|
||||
|
||||
. = ALIGN(8);
|
||||
_end = .; /* for cmsis_gcc.h and init_ram() */
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2023 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
|
||||
#include "hal.h"
|
||||
#include "mongoose.h"
|
||||
#include "net.h"
|
||||
|
||||
#define BLINK_PERIOD_MS 1000 // LED blinking period in millis
|
||||
|
||||
static volatile uint64_t s_ticks; // Milliseconds since boot
|
||||
void SysTick_Handler(void) { // SyStick IRQ handler, triggered every 1ms
|
||||
s_ticks++;
|
||||
}
|
||||
|
||||
uint64_t mg_millis(void) { // Let Mongoose use our uptime function
|
||||
return s_ticks; // Return number of milliseconds since boot
|
||||
}
|
||||
|
||||
void mg_random(void *buf, size_t len) { // Use on-board RNG
|
||||
for (size_t n = 0; n < len; n += sizeof(uint32_t)) {
|
||||
uint32_t r = rng_read();
|
||||
memcpy((char *) buf + n, &r, n + sizeof(r) > len ? len - n : sizeof(r));
|
||||
}
|
||||
}
|
||||
|
||||
static void timer_fn(void *arg) {
|
||||
gpio_toggle(LED); // Blink LED
|
||||
struct mg_tcpip_if *ifp = arg; // And show
|
||||
const char *names[] = {"down", "up", "req", "ready"}; // network stats
|
||||
MG_INFO(("Ethernet: %s, IP: %M, rx:%u, tx:%u, dr:%u, er:%u",
|
||||
names[ifp->state], mg_print_ip4, &ifp->ip, ifp->nrecv, ifp->nsent,
|
||||
ifp->ndrop, ifp->nerr));
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
gpio_output(LED); // Setup blue LED
|
||||
uart_init(UART_DEBUG, 115200); // Initialise debug printf
|
||||
ethernet_init(); // Initialise ethernet pins
|
||||
MG_INFO(("Starting, CPU freq %g MHz", (double) SystemCoreClock / 1000000));
|
||||
|
||||
struct mg_mgr mgr; // Initialise
|
||||
mg_mgr_init(&mgr); // Mongoose event manager
|
||||
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||
|
||||
// Initialise Mongoose network stack
|
||||
struct mg_tcpip_if mif = {.mac = GENERATE_LOCALLY_ADMINISTERED_MAC(),
|
||||
// Uncomment below for static configuration:
|
||||
// .ip = mg_htonl(MG_U32(192, 168, 0, 223)),
|
||||
// .mask = mg_htonl(MG_U32(255, 255, 255, 0)),
|
||||
// .gw = mg_htonl(MG_U32(192, 168, 0, 1)),
|
||||
.driver = &mg_tcpip_driver_cmsis};
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
mg_timer_add(&mgr, BLINK_PERIOD_MS, MG_TIMER_REPEAT, timer_fn, &mif);
|
||||
|
||||
MG_INFO(("MAC: %M. Waiting for IP...", mg_print_mac, mif.mac));
|
||||
while (mif.state != MG_TCPIP_STATE_READY) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
}
|
||||
|
||||
MG_INFO(("Initialising application..."));
|
||||
web_init(&mgr);
|
||||
|
||||
MG_INFO(("Starting event loop"));
|
||||
for (;;) {
|
||||
mg_mgr_poll(&mgr, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "stm32f7xx_hal.h"
|
||||
ETH_HandleTypeDef heth;
|
||||
|
||||
uint32_t HAL_GetTick(void) { // we already have a time base function
|
||||
return (uint32_t) s_ticks;
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/* Workaround for some mbedtls source files using INT_MAX without including limits.h */
|
||||
#include <limits.h>
|
||||
|
||||
#define MBEDTLS_NO_PLATFORM_ENTROPY
|
||||
#define MBEDTLS_ENTROPY_HARDWARE_ALT
|
||||
#define MBEDTLS_SSL_OUT_CONTENT_LEN 2048
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#define MBEDTLS_HAVE_TIME
|
||||
#define MBEDTLS_SSL_SESSION_TICKETS
|
||||
|
||||
#define MBEDTLS_CIPHER_MODE_CBC
|
||||
#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
#define MBEDTLS_PKCS1_V15
|
||||
#define MBEDTLS_SHA256_SMALLER
|
||||
#define MBEDTLS_SSL_SERVER_NAME_INDICATION
|
||||
#define MBEDTLS_AES_C
|
||||
#define MBEDTLS_ASN1_PARSE_C
|
||||
#define MBEDTLS_BIGNUM_C
|
||||
#define MBEDTLS_CIPHER_C
|
||||
#define MBEDTLS_CTR_DRBG_C
|
||||
#define MBEDTLS_ENTROPY_C
|
||||
#define MBEDTLS_ERROR_C
|
||||
#define MBEDTLS_MD_C
|
||||
#define MBEDTLS_MD5_C
|
||||
#define MBEDTLS_OID_C
|
||||
#define MBEDTLS_PKCS5_C
|
||||
#define MBEDTLS_PK_C
|
||||
#define MBEDTLS_PK_PARSE_C
|
||||
#define MBEDTLS_PLATFORM_C
|
||||
#define MBEDTLS_RSA_C
|
||||
#define MBEDTLS_SHA1_C
|
||||
#define MBEDTLS_SHA224_C
|
||||
#define MBEDTLS_SHA256_C
|
||||
#define MBEDTLS_SHA512_C
|
||||
#define MBEDTLS_SSL_CLI_C
|
||||
#define MBEDTLS_SSL_SRV_C
|
||||
#define MBEDTLS_SSL_TLS_C
|
||||
#define MBEDTLS_X509_CRT_PARSE_C
|
||||
#define MBEDTLS_X509_USE_C
|
||||
#define MBEDTLS_AES_FEWER_TABLES
|
||||
#define MBEDTLS_PEM_PARSE_C
|
||||
#define MBEDTLS_BASE64_C
|
||||
#define MBEDTLS_SSL_TICKET_C
|
||||
|
||||
#define MBEDTLS_SSL_PROTO_TLS1_2
|
||||
#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
#define MBEDTLS_GCM_C
|
||||
#define MBEDTLS_ECDH_C
|
||||
#define MBEDTLS_ECP_C
|
||||
#define MBEDTLS_ECDSA_C
|
||||
#define MBEDTLS_ASN1_WRITE_C
|
||||
|
@ -0,0 +1 @@
|
||||
../../../mongoose.c
|
@ -0,0 +1 @@
|
||||
../../../mongoose.h
|
@ -0,0 +1 @@
|
||||
../../device-dashboard/net.c
|
@ -0,0 +1 @@
|
||||
../../device-dashboard/net.h
|
@ -0,0 +1 @@
|
||||
../../device-dashboard/packed_fs.c
|
@ -0,0 +1,98 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
int _fstat(int fd, struct stat *st) {
|
||||
if (fd < 0) return -1;
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *_sbrk(int incr) {
|
||||
extern char _end;
|
||||
static unsigned char *heap = NULL;
|
||||
unsigned char *prev_heap;
|
||||
unsigned char x = 0, *heap_end = (unsigned char *)((size_t) &x - 512);
|
||||
(void) x;
|
||||
if (heap == NULL) heap = (unsigned char *) &_end;
|
||||
prev_heap = heap;
|
||||
if (heap + incr > heap_end) return (void *) -1;
|
||||
heap += incr;
|
||||
return prev_heap;
|
||||
}
|
||||
|
||||
int _open(const char *path) {
|
||||
(void) path;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _close(int fd) {
|
||||
(void) fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _isatty(int fd) {
|
||||
(void) fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int fd, int ptr, int dir) {
|
||||
(void) fd, (void) ptr, (void) dir;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void _exit(int status) {
|
||||
(void) status;
|
||||
for (;;) asm volatile("BKPT #0");
|
||||
}
|
||||
|
||||
void _kill(int pid, int sig) {
|
||||
(void) pid, (void) sig;
|
||||
}
|
||||
|
||||
int _getpid(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _write(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
if (fd == 1) uart_write_buf(UART_DEBUG, ptr, (size_t) len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _read(int fd, char *ptr, int len) {
|
||||
(void) fd, (void) ptr, (void) len;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _link(const char *a, const char *b) {
|
||||
(void) a, (void) b;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink(const char *a) {
|
||||
(void) a;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat(const char *path, struct stat *st) {
|
||||
(void) path, (void) st;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mkdir(const char *path, mode_t mode) {
|
||||
(void) path, (void) mode;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _init(void) {}
|
||||
|
||||
extern uint64_t mg_now(void);
|
||||
|
||||
int _gettimeofday(struct timeval *tv, void *tz) {
|
||||
uint64_t now = mg_now();
|
||||
(void) tz;
|
||||
tv->tv_sec = (time_t) (now / 1000);
|
||||
tv->tv_usec = (unsigned long) ((now % 1000) * 1000);
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// Copyright (c) 2023 Cesanta Software Limited
|
||||
// All rights reserved
|
||||
//
|
||||
// This file contains essentials required by the CMSIS:
|
||||
// uint32_t SystemCoreClock - holds the system core clock value
|
||||
// SystemInit() - initialises the system, e.g. sets up clocks
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
uint32_t SystemCoreClock = SYS_FREQUENCY;
|
||||
|
||||
void SystemInit(void) { // Called automatically by startup code
|
||||
SCB->CPACR |= ((3UL << 10 * 2) | (3UL << 11 * 2)); // Enable FPU
|
||||
asm("DSB");
|
||||
asm("ISB");
|
||||
FLASH->ACR |= FLASH_LATENCY | BIT(8) | BIT(9); // Flash latency, prefetch
|
||||
RCC->PLLCFGR &= ~((BIT(17) - 1)); // Clear PLL multipliers
|
||||
RCC->PLLCFGR |= (((PLL_P - 2) / 2) & 3) << 16; // Set PLL_P
|
||||
RCC->PLLCFGR |= PLL_M | (PLL_N << 6); // Set PLL_M and PLL_N
|
||||
RCC->CR |= BIT(24); // Enable PLL
|
||||
while ((RCC->CR & BIT(25)) == 0) spin(1); // Wait until done
|
||||
RCC->CFGR = (APB1_PRE << 10) | (APB2_PRE << 13); // Set prescalers
|
||||
RCC->CFGR |= 2; // Set clock source to PLL
|
||||
while ((RCC->CFGR & 12) == 0) spin(1); // Wait until done
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; // Enable SYSCFG
|
||||
rng_init(); // Initialise random number generator
|
||||
SysTick_Config(SystemCoreClock / 1000); // Sys tick every 1ms
|
||||
}
|
118
mongoose.c
118
mongoose.c
@ -8433,6 +8433,124 @@ size_t mg_ws_wrap(struct mg_connection *c, size_t len, int op) {
|
||||
return c->send.len;
|
||||
}
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/drivers/cmsis.c"
|
||||
#endif
|
||||
// https://arm-software.github.io/CMSIS_5/Driver/html/index.html
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0;
|
||||
extern ARM_DRIVER_ETH_PHY Driver_ETH_PHY0;
|
||||
|
||||
static struct mg_tcpip_if *s_ifp;
|
||||
|
||||
static void mac_cb(uint32_t);
|
||||
static bool cmsis_init(struct mg_tcpip_if *);
|
||||
static bool cmsis_up(struct mg_tcpip_if *);
|
||||
static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
|
||||
static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
|
||||
cmsis_up};
|
||||
|
||||
static bool cmsis_init(struct mg_tcpip_if *ifp) {
|
||||
ARM_ETH_MAC_ADDR addr;
|
||||
s_ifp = ifp;
|
||||
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
||||
ARM_ETH_MAC_CAPABILITIES cap = mac->GetCapabilities();
|
||||
if (mac->Initialize(mac_cb) != ARM_DRIVER_OK) return false;
|
||||
if (phy->Initialize(mac->PHY_Read, mac->PHY_Write) != ARM_DRIVER_OK)
|
||||
return false;
|
||||
if (cap.event_rx_frame == 0) // polled mode driver
|
||||
mg_tcpip_driver_cmsis.rx = cmsis_rx;
|
||||
mac->PowerControl(ARM_POWER_FULL);
|
||||
if (cap.mac_address) { // driver provides MAC address
|
||||
mac->GetMacAddress(&addr);
|
||||
memcpy(ifp->mac, &addr, sizeof(ifp->mac));
|
||||
} else { // we provide MAC address
|
||||
memcpy(&addr, ifp->mac, sizeof(addr));
|
||||
mac->SetMacAddress(&addr);
|
||||
}
|
||||
phy->PowerControl(ARM_POWER_FULL);
|
||||
phy->SetInterface(cap.media_interface);
|
||||
phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t cmsis_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
if (mac->SendFrame(buf, (uint32_t) len, 0) != ARM_DRIVER_OK) {
|
||||
ifp->nerr++;
|
||||
return 0;
|
||||
}
|
||||
ifp->nsent++;
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool cmsis_up(struct mg_tcpip_if *ifp) {
|
||||
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // just went up
|
||||
ARM_ETH_LINK_INFO st = phy->GetLinkInfo();
|
||||
mac->Control(ARM_ETH_MAC_CONFIGURE,
|
||||
(st.speed << ARM_ETH_MAC_SPEED_Pos) |
|
||||
(st.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
|
||||
ARM_ETH_MAC_ADDRESS_BROADCAST);
|
||||
MG_DEBUG(("Link is %uM %s-duplex",
|
||||
(st.speed == 2) ? 1000
|
||||
: st.speed ? 100
|
||||
: 10,
|
||||
st.duplex ? "full" : "half"));
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_TX, 1);
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_RX, 1);
|
||||
} else if ((ifp->state != MG_TCPIP_STATE_DOWN) && !up) { // just went down
|
||||
mac->Control(ARM_ETH_MAC_FLUSH,
|
||||
ARM_ETH_MAC_FLUSH_TX | ARM_ETH_MAC_FLUSH_RX);
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_TX, 0);
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_RX, 0);
|
||||
}
|
||||
return up;
|
||||
}
|
||||
|
||||
static void mac_cb(uint32_t ev) {
|
||||
if ((ev & ARM_ETH_MAC_EVENT_RX_FRAME) == 0) return;
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
|
||||
if (len >= 60 && len <= 1518) { // proper frame
|
||||
char *p;
|
||||
if (mg_queue_book(&s_ifp->recv_queue, &p, len) >= len) { // have room
|
||||
if ((len = mac->ReadFrame((uint8_t *) p, len)) > 0) { // copy succeeds
|
||||
mg_queue_add(&s_ifp->recv_queue, len);
|
||||
s_ifp->nrecv++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
s_ifp->ndrop++;
|
||||
}
|
||||
mac->ReadFrame(NULL, 0); // otherwise, discard
|
||||
}
|
||||
|
||||
static size_t cmsis_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
|
||||
if (len >= 60 && len <= 1518 &&
|
||||
((len = mac->ReadFrame(buf, (uint32_t) buflen)) > 0))
|
||||
return len;
|
||||
if (len > 0) mac->ReadFrame(NULL, 0); // discard bad frames
|
||||
(void) ifp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/drivers/rt1020.c"
|
||||
#endif
|
||||
|
@ -1791,6 +1791,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_rt1020;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_same54;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_cmsis;
|
||||
|
||||
// Drivers that require SPI, can use this SPI abstraction
|
||||
struct mg_tcpip_spi {
|
||||
@ -1802,6 +1803,14 @@ struct mg_tcpip_spi {
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
|
||||
|
||||
#include "Driver_ETH_MAC.h" // keep this include
|
||||
#include "Driver_ETH_PHY.h" // keep this include
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
struct mg_tcpip_driver_rt1020_data {
|
||||
// MDC clock divider. MDC clock is derived from IPS Bus clock (ipg_clk),
|
||||
// must not exceed 2.5MHz. Configuration for clock range 2.36~2.50 MHz
|
||||
|
114
src/drivers/cmsis.c
Normal file
114
src/drivers/cmsis.c
Normal file
@ -0,0 +1,114 @@
|
||||
// https://arm-software.github.io/CMSIS_5/Driver/html/index.html
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "net_builtin.h"
|
||||
#include "queue.h"
|
||||
|
||||
extern ARM_DRIVER_ETH_MAC Driver_ETH_MAC0;
|
||||
extern ARM_DRIVER_ETH_PHY Driver_ETH_PHY0;
|
||||
|
||||
static struct mg_tcpip_if *s_ifp;
|
||||
|
||||
static void mac_cb(uint32_t);
|
||||
static bool cmsis_init(struct mg_tcpip_if *);
|
||||
static bool cmsis_up(struct mg_tcpip_if *);
|
||||
static size_t cmsis_tx(const void *, size_t, struct mg_tcpip_if *);
|
||||
static size_t cmsis_rx(void *, size_t, struct mg_tcpip_if *);
|
||||
|
||||
struct mg_tcpip_driver mg_tcpip_driver_cmsis = {cmsis_init, cmsis_tx, NULL,
|
||||
cmsis_up};
|
||||
|
||||
static bool cmsis_init(struct mg_tcpip_if *ifp) {
|
||||
ARM_ETH_MAC_ADDR addr;
|
||||
s_ifp = ifp;
|
||||
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
||||
ARM_ETH_MAC_CAPABILITIES cap = mac->GetCapabilities();
|
||||
if (mac->Initialize(mac_cb) != ARM_DRIVER_OK) return false;
|
||||
if (phy->Initialize(mac->PHY_Read, mac->PHY_Write) != ARM_DRIVER_OK)
|
||||
return false;
|
||||
if (cap.event_rx_frame == 0) // polled mode driver
|
||||
mg_tcpip_driver_cmsis.rx = cmsis_rx;
|
||||
mac->PowerControl(ARM_POWER_FULL);
|
||||
if (cap.mac_address) { // driver provides MAC address
|
||||
mac->GetMacAddress(&addr);
|
||||
memcpy(ifp->mac, &addr, sizeof(ifp->mac));
|
||||
} else { // we provide MAC address
|
||||
memcpy(&addr, ifp->mac, sizeof(addr));
|
||||
mac->SetMacAddress(&addr);
|
||||
}
|
||||
phy->PowerControl(ARM_POWER_FULL);
|
||||
phy->SetInterface(cap.media_interface);
|
||||
phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE);
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t cmsis_tx(const void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
if (mac->SendFrame(buf, (uint32_t) len, 0) != ARM_DRIVER_OK) {
|
||||
ifp->nerr++;
|
||||
return 0;
|
||||
}
|
||||
ifp->nsent++;
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool cmsis_up(struct mg_tcpip_if *ifp) {
|
||||
ARM_DRIVER_ETH_PHY *phy = &Driver_ETH_PHY0;
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
bool up = (phy->GetLinkState() == ARM_ETH_LINK_UP) ? 1 : 0; // link state
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) { // just went up
|
||||
ARM_ETH_LINK_INFO st = phy->GetLinkInfo();
|
||||
mac->Control(ARM_ETH_MAC_CONFIGURE,
|
||||
(st.speed << ARM_ETH_MAC_SPEED_Pos) |
|
||||
(st.duplex << ARM_ETH_MAC_DUPLEX_Pos) |
|
||||
ARM_ETH_MAC_ADDRESS_BROADCAST);
|
||||
MG_DEBUG(("Link is %uM %s-duplex",
|
||||
(st.speed == 2) ? 1000
|
||||
: st.speed ? 100
|
||||
: 10,
|
||||
st.duplex ? "full" : "half"));
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_TX, 1);
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_RX, 1);
|
||||
} else if ((ifp->state != MG_TCPIP_STATE_DOWN) && !up) { // just went down
|
||||
mac->Control(ARM_ETH_MAC_FLUSH,
|
||||
ARM_ETH_MAC_FLUSH_TX | ARM_ETH_MAC_FLUSH_RX);
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_TX, 0);
|
||||
mac->Control(ARM_ETH_MAC_CONTROL_RX, 0);
|
||||
}
|
||||
return up;
|
||||
}
|
||||
|
||||
static void mac_cb(uint32_t ev) {
|
||||
if ((ev & ARM_ETH_MAC_EVENT_RX_FRAME) == 0) return;
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
|
||||
if (len >= 60 && len <= 1518) { // proper frame
|
||||
char *p;
|
||||
if (mg_queue_book(&s_ifp->recv_queue, &p, len) >= len) { // have room
|
||||
if ((len = mac->ReadFrame((uint8_t *) p, len)) > 0) { // copy succeeds
|
||||
mg_queue_add(&s_ifp->recv_queue, len);
|
||||
s_ifp->nrecv++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
s_ifp->ndrop++;
|
||||
}
|
||||
mac->ReadFrame(NULL, 0); // otherwise, discard
|
||||
}
|
||||
|
||||
static size_t cmsis_rx(void *buf, size_t buflen, struct mg_tcpip_if *ifp) {
|
||||
ARM_DRIVER_ETH_MAC *mac = &Driver_ETH_MAC0;
|
||||
uint32_t len = mac->GetRxFrameSize(); // CRC already stripped
|
||||
if (len >= 60 && len <= 1518 &&
|
||||
((len = mac->ReadFrame(buf, (uint32_t) buflen)) > 0))
|
||||
return len;
|
||||
if (len > 0) mac->ReadFrame(NULL, 0); // discard bad frames
|
||||
(void) ifp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
8
src/drivers/cmsis.h
Normal file
8
src/drivers/cmsis.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_CMSIS) && MG_ENABLE_DRIVER_CMSIS
|
||||
|
||||
#include "Driver_ETH_MAC.h" // keep this include
|
||||
#include "Driver_ETH_PHY.h" // keep this include
|
||||
|
||||
#endif
|
@ -57,6 +57,7 @@ extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_rt1020;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_same54;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_cmsis;
|
||||
|
||||
// Drivers that require SPI, can use this SPI abstraction
|
||||
struct mg_tcpip_spi {
|
||||
|
Loading…
Reference in New Issue
Block a user