diff --git a/CHANGELOG.md b/CHANGELOG.md index 805b92393..13fe597a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,279 @@ # Change Log +## [1.5.0] - 2024-03-29: + +Main changes since 1.4.0 + +Tested Segger Embedded Studio Version: 7.32a +Tested IAR Embedded Workbench for RISC-V Version: 3.20.1 + +### Known Issue: + - some IAR projects does not work properly when optimization level is increased + +### Changed: + - soc: iomux: update macro prefix in pmic_iomux and batt_iomux. + - soc: feature: change usb endpoint max number from 8 to 16 + - soc: correct svd files and add subpart module list + - drivers: usb: change usb_phy_get_line_state() to external function + - drivers: qeiv2: update filter length setting + - drivers: adc12/adc16: add sanity check for sample cycle + - drivers: femc: add delay_cell_disable config option + - drivers: i2s: change fifo threshold parameter. + - drivers: i2c: replace and use the macro definition of hpm_soc_ip_feature. + - drivers: uart: supplementary description of uart_check_status API. + - components: enet_phy: lan8720/rtl8201/rtl8211: unify the default config with type bool + - components: enet_phy: remove unused included header file + - components: enet_phy: rtl8201/rtl8211: update register description + - components: dma_mgr: change isr handler from static to public + - middleware: tinyusb: host: use echi drivers + - middleware: tinyusb: rename CFG_TUSB_HOST_DEVICE_MAX to CFG_TUH_DEVICE_MAX + - middleware: tinyusb: update to v0.16 + - middleware: rtthread-nano: use soc reset_handler and define MAIN_ENTRY as entry + - middleware: fatfs: tinyusb: adapter to tinyusb update + - middleware: threadx: use TX_TIMER_TICKS_PER_SECOND to config work ticks + - middleware: threadx: use samples tx_user.h + - middleware: uC/OS-III: enable sw interrupt in OSCtxSw/OSIntCtxSw + - middleware: ucos: ports: Added IAR portable layer for ucos. + - middleware: cherryusb/azure_rtos: add defined __ICCRISCV__ for iar + - middleware: hpm_math: simplify libdsp path. + - middleware: cherryusb: update to v1.1.0 + - middleware: rtthread-nano:halt cpu when exception occur. + - middleware: hpm_math: simplify libnn path. + - middleware: threadx: move frequently called function to ram. + - middleware: tinyusb: change endpoint number from 8 to 16 + - middleware: usbx: change endpoint number from 8 to 16 + - middleware: cherryusb: msc device: update to support multi lun and deinit + - middleware: eclipse_threadx: update license + - middleware: fatfs: tinyusb: add osal_task_delay() when use rtos wait + - middleware: tinyusb: update CMakeLists.txt and delete custom osal_task_delay() + - middleware: tinyusb: add debounce in port change isr + - samples: erpc: add middleware src use middleware CMakeLists.txt + - samples: multicore: core1: use board_init_core1() API + - samples: multicore: coremark: delete custom reset_handler and use app_main as MAIN_ENTRY + - samples: tinyusb: update samples to adapter tinyusb v0.16 + - samples: usbx: host: delete unused hpm_usb_host.h + - samples: usb: delete CONFIG_USB_HOST set + - samples: lvgl_coremark: disable freqswitch_btn when coremark running + - samples: mono: move to driver directory. + - samples: freertos: change configMAX_PRIORITIES from 7 to 32 + - samples: rtthread: delete unused macro RT_THREAD_PRIORITY_32 + - samples: cherryusb: usbnet: decrease rtos stack config size + - samples: lwip: all: unify logs about IP information + - samples: lwip: lwip_https_server: remove an unused file + - samples: lwip: all: update DHCP progress logic + - samples: lwip: common: remove s_pxNetIf + - samples: lwip: adjust the directories of netconf.c/netcof.h + - samples: lwip: common: optimize speed for getting IP from DHCP server + - samples: lwip: rename common_lwip.c to common.c + - samples: lwip: common: adjust the call logic of netif_set_up/netif_set_down + - samples: lwip: common: change the time of invoking netif_user_notification + - samples: lwip: common: rename user_notification to netif_user_notification + - samples: lwip: adjust directory structures to be compatible with single and multiple network ports + - samples: use generate_ide_projects for new samples + - samples: cherryusb: device: cdc acm: reorganize directory structure + - samplse: gptmr: t_shape_accel_decel: modify the source address mode of DMA. + - samples: cherryusb: device: change readbuf size from 2048 to CDC_MAX_MPS + - samples: drivers: femc: update sdram dqs config + - samples: update app.yaml to use ip_feature + - samples: drivers: uart: change to app uart + - samples: audio_codec: update wm8960 I2S protocol. + - samples: drivers: cam: change cam sample to cam_dvp sample. + - samples: usbx: device: msc: decrease ram disk size to 16KB + - samples: cherryusb: msc device: update to support multi lun + - samples: driver: uart_lin: support LIN transceiver on board. + - samples: adc: temp: rename temp to adc16_temperature + - samples: bldc block: Compatible with both hall and qeiv2 peripherals. + - samples: motor_ctrl: Modify the value of pwm reload. + - samples: lwip: common: single/multiple: update the size passed into sys_mbox_new() + - samples: lwip: common: single/multiple: replace enet_get_link_status with netif_is_link_up + - samples: lwip: lwip_https_server: remove unused header file + - samples: lwip: rename macro TCP_XXX_PORT + - samples: lwip: add cmake flag for netconn/socket api + - samples: decode_wav: sd_fafts: update sd_choose_music. + - samples: power_mode_switch: maintain xpi0 clock on switching preset + - samples: dhrystone Change the optmization level to O3. + - samples: tinyusb: hid_generic_inout: delete redundant image + - samples: power_mode_switch: hpm67/hpm63: preserve femc clock at wait/stop mode + - samples: erpc: core1: use optimization -os + - samples: update uart_tamagawa to use software trig if TRGM not exist. + - samples: eeprom_emulation: reduce management area + - samples: sdxc: use block_size instead of 512 + - samples: erpc: add -fno-exceptions compile option + - samples: tinyusb: disable debug log print + - boards: hpm5300evk and hpm6800evk: add delay after USB_PWR Pin init for power stable + - boards: hpm6750evkmini: modify gptmr pins. + - boards: hpm6200evk: modify gptmr pins. + - boards: hpm6200evk: modify the i2c pins. + - boards: hpm6750xxx: update sdram dqs config + - boards: hpm6800evk:pinmux Increase drive strength for sdxc pins + - boards: iomux: update macro prefix for pmic_iomux and batt_iomux. + - boards: rename board feature + - boards: update BOARD_APP_UART definition + - boards: rename console definitions + - boards: hpm5301evklite: update uart clock in board.c. + - boards: hpm6750evkmini: change BOARD_GPTMR_PWM_DMA_SRC definition. + - docs: samples: use glob in high level readme. + - docs: update top level readme. + - docs: netxduo: update sntp readme. + - docs: threadx: update threadx hello readme. + - docs: lwip: align pictures to the left + - docs: pip: add cmake doc dependency + - docs: add changelog to sphnix-doc. + - scripts: ses: generate asm after build by default. + - scripts: update linked project path logic. + - scripts: check_board_cap.py: check ip feature's availability + - cmake: remove CMP0116 setting. + - cmake&scripts: clarify the error caused by core1 compiling failure. + - scripts: ses/iar: use relpath in project file + +### Added: + - soc: hpm6360/hpm6750/hpm6800: add MAC-related definitions in OTP section + - soc: reset: add MAIN_ENTRY macro to custom define main entry + - soc: add hpm6850 and hpm6830 part. + - soc: soc_modules.list: add tamper drivers + - soc: Add IAR toolchain support. + - soc: add ip feature to soc_modules.list + - soc: add hpm_soc_ip_feature.h + - soc: driver: ppor: add reset hold operation APIs + - soc: clock_driver add the clock_get_divider API. + - soc: sysctl: add apis to control clock preservation + - soc: toolchains: gcc: ram linker: add ILM last address overflow check + - drivers: mcan Add timeout counter support. + - drivers: tamper: add tamper driver + - drivers: cam: add cam_update_buffer2 API + - drivers: opamp: Add user configuration code. + - drivers: lcdc: add stride for layer config. + - drivers: pdma: add pdma_blit_ex. + - drivers:pllctl add out-of-bound check in pllctl driver. + - components:uart_lin: add hpm_uart_lin_send_wakeup() API + - components: enet_phy: add LAN8720 driver + - components: enet_phy: add definition of enet_phy_link_status_t + - middleware: cherryusb: host: add dual port support + - middleware: cmsis_os2: adapter to rtthread wrapper + - middleware: cmsis_os2: update freertos files + - middleware: cmsis_os2: adapter to threadx wrapper + - middleware: cmsis_os2: adapter to ucOS-III wrapper + - middleware: hpm_sdmmc Add eMMC config partition API. + - middleware: cherryusb Add IAR toolchain support + - middleware: erpc Fix IAR RISC-V support issue + - middleware: tflm: add IAR riscv support in flatbuffer + - middleware: FreeRTOS: portable:Added IAR portable layer. + - middleware: segger_rtt Added EWRISCV support + - middleware: hpm_math Add nds_dsp library for IAR. + - middleware: lwip: cc: add PACK_STRUCT_XXX definitions for IAR platform + - middleware: uC/OS-III: enable plicsw in IAR asm code + - middleware: add tinyengine + - middleware: threadx: add support for gptmr. + - middleware: threadx: add profile support. + - middleware: add agile_modbus. + - middleware: add cherryrb. + - middleware: cherryusb Add missing swap32/swap16 implementation. + - middleware: hpm_mclv2: add block type drive motors + - middleware: cherryusb: fix usbh_core ep0 buffer index + - boards: hpm6200xxx and hpm6750xxx: add board_init_core1() API + - boards: add tamper feature and pins init + - boards: hpm5300evk: add board_init_console() declaration in board.h + - boards: hpm6750evk/hpm6750evk2: add board_dual_usb feature + - boards: openocd: add windows guide to *_all_in_one.cfg + - boards: openocd: soc: add reset_soc proc + - board:add pgpio configuration on hpm5301evklite + - samples: drivers: add mono sample. + - samples: drivers:mcan Add timeout counter sample. + - samples: drivers: tamper: add tamper sample + - samples: cmsis_os2: blinky: add rtthread samples + - samples: cmsis_os2: add msg_queue sample + - samples: cmsis_os2: add mem_pool samples + - samples: cmsis_os2: msg_queue: add ucOS-III support + - samples: cmsis_os2: blinky: add ucOS-III support + - samples: lwip: common: add a task netif_update_link_status + - samples: lwip: add MAC address load from OPT MAC area + - samples: cherryusb: device: cdc acm: add cdc_acm_uart_com sample + - samples: cherryusb: device: add msc sdcard sample + - samples: tinyengine: add person detection. + - samples: rtos: add threadx gptmr sample. + - samples: modbus: tcp: add tcp samples. + - samples: modbus: rtu: add rtu sample. + - samples: add cherryrb sample. + - samples: cherryusb: host: add dual port sample + - samples: cherryusb: device: add dual port sample + - samples: cherryusb: device: add dual lun msc sample + - samples: lwip: ports: rtthread-nano: multiple: add arch-related files + - samples: lwip: ports: freertos: multiple: add arch-related files + - samples: lwip: common: multiple: osal: add osTaskFunction definition + - samples: lwip: add a lwip_tcpecho_multi_ports_rtthread-nano sample + - samples: lwip: add a lwip_tcpecho_multi_ports_freertos + - samples: lwip: lwip_tcpecho_xxx: add definitions for task priorities + - samples: lwip: lwip_tcpecho_freertos_socket: newly add + - samples: lwip: lwip_tcpclient: newly add + - samples: lwip: add lwip_tcpclient_freertos_socket + - samples: vglite: add sample of rotate tiger. + - samples: lwip: lwip_tcpclient_freertos_socket: fix failure to run + - samples: lwip: lwip_tcpclient: fix failure to run with some release-related type + - samples: jpeg: jpeg_encode: add debounce for button. + - docs: add cmake doc + - docs: hpm5300evk: add qeiv2 sin/cos pins + - scripts: support sdk project localization. + - cmake: add nds-gcc options to sdk_lib for nds-gcc. + - cmake/scripts: add IAR project generation support + - cmake: add symbols to specify linker for tools. + - cmake: add sdk_*_src_glob. + - cmake: add custom targets for localization. + +### Fixed: + - soc: hpm6750: fix segger linker vectors order + - soc: hpm_interrupt.h Fix compiling warning for DSP related macros + - soc: hpm6750: otp Fix OTP program and read logic + - soc: hpm6880: clock Fix wrong enum value for TSNS clock. + - soc: clock driver: correct the clock name value for pll clocks. + - soc: HPM6280: fix adc/dac clock setting + - soc: ppor: fix ppor clear reset flag and set reset type API error + - soc: HPM6880: fix i2s clock config driver + - drivers: adc12: fix calibration setting error + - drivers: cam: DMASA_FB2 need to be assigned whether FB2 buffer is enable or not. + - drivers:can correct the logic of disabling re-transmission for ptb & stb. + - drivers: qeo: fix driver error + - drivers: i2s: ensure valid BCLK before call software reset. + - drivers: pdma: fixed OUT_PS[] config. + - components: wm8960: invert LRCLK to align with soc I2S. + - middleware: uC/OS-III: fix register t0 unsafe. + - middleware: ptpd: fix netShutdown error in ptpd initialization + - middleware: cmsis_os2: task should call exit interface before exit + - middleware: threadx: fix threadx profile RA register save and restore bug. + - middleware: hpm_mcl: fix divide-by-zero error. refs: hpm_sdk-#1091 + - middleware: cherryusb/tinyusb/usbx: device: fix transfer_len not reset + - middleware: cherryusb/usbx: fix dtd return problem + - middleware: cherryusb/tinyusb/usbx: fix usb device interrupt should be check active status + - middleware: tinyusb: fix ehci cap_reg address error + - middleware: tinyusb: fix hid report id + - middleware: cherryusb: fix usbd_ep_close not reset ep_enable flag + - middleware: cherryusb: fix rndis message length check + - middleware: freertos: fix implementation error in xPortIsInsideInterrupt. + - boards: hpm6200evk: fix tamper pin config + - board: openocd: all_in_one: hpm6800 config file is missed. + - boards: openocd: all_in_one: hpm5300: correct soc config name. + - samples: threadx hello: fix printing errors. + - samples: drivers: ad12/adc16: fix initialization sequence for trigger source, trigger mux and trigger target config + - samples: lwip: lwip_ptp: fix netSend error before link-up + - samples: dma: fix dma uart init position + - samples: drivers:spi:master_trans_large_amound_of_data Fix logic error if SPI support 4GB transfer size + - samples: sdxc: add boundary protection for last 1024 blocks test + - samples: lwip: common: multiple: fix typo of enet_update_dhcp_state() + - samples: lwip: common: single/multiple: fix timeout passed into sys_arch_mbox_fetch() + - samples: e2prom: bugfix: base read fail if run perf firstly .refs:hpm_sdk-#1499 + - samples: modbus: tcp: use volatile to prevent the compiler from optimizing out key variables + - samples: modbus: rtu: fixed failed to run after turning on optimization issue. + - samples: power_mode_switch: hpm68xx: fix ddr access issue for wait/stop mode + - samples: cherryrb: fixed stack overflow issue + - samples: lwip: lwip_tcpecho_multi_ports_ports_rtthread-nano: fix failure to run + - sample: jpeg: jpeg_encode: fix that udisk can't be mounted when first capture. + - cmake: correct board search path symbol for core1. + - cmake: gcc: fix system include path. + - cmake: fix sdk_link_libraries failed to link std lib. + - cmake: EXTAR_LD_FLAGS to be added as ld options. + - docs: lwip_ptp: v1: salve: fix format error + - docs: samples: ppor: change title from sysctl to ppor + - docs: hpm6750evk2: fix table display error + ## [1.4.0] - 2023-12-29: Main changes since 1.3.0 @@ -805,7 +1079,7 @@ Main changes since 0.10.0-hpm6360-er - boards: LED status is not the same between hpm6750mini rev-A and rev-B - boards: update board_led_write. -## Added: +### Added: - driver: add spi_setup_dma_transfer() API - middleware: hpm_math: add software fft function - middleware: hpm_math: add ffa to hpm_math @@ -989,3 +1263,4 @@ All changes since 0.6.2 - samples: drivers: gpiom: Add example to demonstrate gpiom's function - drivers: common: add macro to put data into noncacheable sections - middleware: integrate lwip + diff --git a/CMakeLists.txt b/CMakeLists.txt index 97e0a4e4c..fabf927dc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,6 @@ # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.13) -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.20) - cmake_policy(SET CMP0116 OLD) -endif() cmake_policy(SET CMP0079 NEW) project(hpm_sdk) @@ -15,6 +12,11 @@ target_link_libraries(${HPM_SDK_LIB} PUBLIC ${HPM_SDK_LIB_ITF}) add_library(${HPM_SDK_GCC_LIB} STATIC "") target_link_libraries(${HPM_SDK_GCC_LIB} PUBLIC ${HPM_SDK_GCC_LIB_ITF} ${HPM_SDK_LIB_ITF}) +target_link_libraries(${HPM_SDK_LIB} PUBLIC ${HPM_SDK_GCC_LIB_ITF}) +if("${TOOLCHAIN_VARIANT}" STREQUAL "nds-gcc") +target_link_libraries(${HPM_SDK_LIB} PUBLIC ${HPM_SDK_NDSGCC_LIB_ITF}) +endif() + if(flash_size) sdk_linker_global_symbols("_flash_size=${flash_size}") endif() @@ -120,6 +122,11 @@ if(DEFINED CUSTOM_SES_STARTUP_FILE) sdk_ses_src(${CUSTOM_SES_STARTUP_FILE}) endif() +if(DEFINED CUSTOM_IAR_STARTUP_FILE) + set(USE_CUSTOM_STARTUP 1) + sdk_iar_src(${CUSTOM_IAR_STARTUP_FILE}) +endif() + sdk_sys_inc(${SYSROOT_DIR}/include) # parse module list file provided in soc folder, it will decide which modules to be enabled under drivers folder @@ -194,6 +201,7 @@ if(${HPM_SDK_LD_NO_WHOLE_SDK}) endif() if("${TOOLCHAIN_VARIANT}" STREQUAL "nds-gcc") + target_link_libraries(${HPM_SDK_LIB} PUBLIC ${HPM_SDK_NDSGCC_LIB_ITF}) target_link_libraries(${APP_ELF_NAME} "-Wl,-Map=${EXECUTABLE_OUTPUT_PATH}/${APP_MAP_NAME}" ${HPM_SDK_WHOLE_ARCHIVE_OPT} diff --git a/README.md b/README.md index c182ae1b6..389c0384e 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ gantt title HPM SDK Release Plan dateFormat YYYY-MM-DD section Mainline Release - v1.1.0 :a1, 2023-01-01, 2023-03-31 - v1.2.0 :a2, 2023-04-01, 2023-06-30 - v1.3.0 :a3, 2023-07-01, 2023-09-30 - v1.4.0 :a4, 2023-10-01, 2023-12-31 + v1.5.0 :a1, 2024-01-01, 2024-03-31 + v1.6.0 :a2, 2024-04-01, 2024-06-30 + v1.7.0 :a3, 2024-07-01, 2024-09-30 + v1.8.0 :a4, 2024-10-01, 2024-12-31 ``` [中文](README_zh.md) @@ -35,7 +35,7 @@ The HPM SDK Project is a software development kit based on HPMicro's MCUs, which SDK documentation can be built locally, once it's done, it can be accessed with the following entries: - >/docs/index.html - >/docs/index_zh.html - > Please refer to /docs/README.md for more details about documentation building. + > Please refer to for [hpm_sdk Getting Started](docs/en/get_started.md) more details about documentation building. - Online: - http://hpm-sdk.readthedocs.io/ - http://hpm-sdk-zh.readthedocs.io/ diff --git a/README_zh.md b/README_zh.md index 411ecbfe9..22b86f655 100644 --- a/README_zh.md +++ b/README_zh.md @@ -3,10 +3,10 @@ gantt title HPM SDK Release Plan dateFormat YYYY-MM-DD section Mainline Release - v1.1.0 :a1, 2023-01-01, 2023-03-31 - v1.2.0 :a2, 2023-04-01, 2023-06-30 - v1.3.0 :a3, 2023-07-01, 2023-09-30 - v1.4.0 :a4, 2023-10-01, 2023-12-31 + v1.5.0 :a1, 2024-01-01, 2024-03-31 + v1.6.0 :a2, 2024-04-01, 2024-06-30 + v1.7.0 :a3, 2024-07-01, 2024-09-30 + v1.8.0 :a4, 2024-10-01, 2024-12-31 ``` [English](README.md) @@ -35,7 +35,7 @@ HPM SDK项目是基于HPMicro 公司的MCU编写的软件开发包,支持多 SDK文档可以进行本地编译,成功编译之后可以通过以下入口访问本地文档: - >/docs/index.html - >/docs/index_zh.html - > 文档编译方式请参考/docs/README.md + > 文档编译方式请参考[hpm_sdk Getting Started](docs/zh/get_started.md) - 在线文档: - http://hpm-sdk.readthedocs.io/ - http://hpm-sdk-zh.readthedocs.io/ diff --git a/VERSION b/VERSION index cd4fba666..e110767a6 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ VERSION_MAJOR = 1 -VERSION_MINOR = 4 +VERSION_MINOR = 5 PATCHLEVEL = 0 VERSION_TWEAK = 0 EXTRAVERSION = 0 diff --git a/boards/hpm5300evk/README_en.md b/boards/hpm5300evk/README_en.md index 23e4df6fb..f39acde5b 100644 --- a/boards/hpm5300evk/README_en.md +++ b/boards/hpm5300evk/README_en.md @@ -30,7 +30,9 @@ The HPM5300EVK provides a series of interfaces for the characteristic peripheral (lab_hpm5300_evk_board)= -- UART Pin: +- UART Pin: modbus_rtu sample + +- The UART2 is used for some functional testing using UART, such as MICROROS_UART, USB_CDC_ACM_UART, etc. | Function | Position | | --------- | -------- | @@ -38,11 +40,11 @@ The HPM5300EVK provides a series of interfaces for the characteristic peripheral | UART2.RXD | P1[10] | | UART2.DE | P1[38] | -- LIN Pin: +- LIN Pin (UART_LIN case): | Function | Position | | -------- | -------- | -| LIN3 | J9[5] | +| LIN | J9[5] | - SPI Pin: @@ -77,14 +79,9 @@ The HPM5300EVK provides a series of interfaces for the characteristic peripheral - ADC16 Pin: -| Function | Position | -| ---------- | -------- | -| ADC0.INA4 | J7[15] | -| ADC0.INA11 | J7[20] | -| ADC1.INA1 | J7[2] | -| ADC1.INA2 | J7[6] | -| ADC1.INA3 | J7[4] | -| ADC1.INA5 | J7[13] | +| Function | Position | Remark | +| ---------- | -------- | -------- | +| ADC0.INA13 | P1[32] | ADC16 | - DAC Pin: @@ -163,6 +160,13 @@ The HPM5300EVK provides a series of interfaces for the characteristic peripheral | --------- | ------ |------| | SEI1.CLK Section | J5 | Master side, CLKO active. Slave side,CLKI active | +- QEIV2 Sin/Cos Pin: + +| Function | Position | Remark | +| ---------- | -------- | -------- | +| ADC0.INA4 | J7[15] | ADC_IW (Cos) | +| ADC1.INA5 | J7[13] | ADC_IU (Sin) | + - Motor Pin: Refer to section [DRV-LV50A-MP1907 Motor Driver Board ](lab_drv_lv50a_mp1907) for configuration diff --git a/boards/hpm5300evk/README_zh.md b/boards/hpm5300evk/README_zh.md index 2496ff2ad..b78d12dd8 100644 --- a/boards/hpm5300evk/README_zh.md +++ b/boards/hpm5300evk/README_zh.md @@ -30,13 +30,15 @@ HPM5300EVK提供了一系列HPM5300系列微控制器特色外设的接口,包 (lab_hpm5300_evk_board)= -- LIN引脚 +- LIN引脚 (UART_LIN示例) | 功能 | 位置 | | ---- | ----- | -| LIN3 | J9[5] | +| LIN | J9[5] | -- UART引脚 +- UART引脚 可用于modbus rtu工程 + + UART2用于一些使用UART的功能测试,例如MICROROS_UART,USB_CDC_ACM_UART等。 | 功能 | 位置 | | --------- | ------ | @@ -77,14 +79,9 @@ HPM5300EVK提供了一系列HPM5300系列微控制器特色外设的接口,包 - ADC16引脚 -| 功能 | 位置 | -| ---------- | ------ | -| ADC0.INA4 | J7[15] | -| ADC0.INA11 | J7[20] | -| ADC1.INA1 | J7[2] | -| ADC1.INA2 | J7[6] | -| ADC1.INA3 | J7[4] | -| ADC1.INA5 | J7[13] | +| 功能 | 位置 | 备注 | +| ---------- | ------ | ------ +| ADC0.INA13 | P1[32] | ADC16 | - DAC引脚 @@ -163,6 +160,13 @@ HPM5300EVK提供了一系列HPM5300系列微控制器特色外设的接口,包 | --------- | ------ |------| | SEI1.CLK选择 | J5 | Master侧,选择CLKO;Slave侧,选择CLKI | +- QEIV2 Sin/Cos引脚 + +| 功能 | 位置 | 备注 | +| ---------- | ------ | ------ | +| ADC0.INA4 | J7[15] | ADC_IW (Cos) | +| ADC1.INA5 | J7[13] | ADC_IU (Sin) | + - 电机引脚 参考 [DRV-LV50A-MP1907 电机驱动板章节](lab_drv_lv50a_mp1907) 进行连接 diff --git a/boards/hpm5300evk/board.c b/boards/hpm5300evk/board.c index 14879ed51..9eafc5506 100644 --- a/boards/hpm5300evk/board.c +++ b/boards/hpm5300evk/board.c @@ -88,16 +88,16 @@ void board_init_console(void) * uart rx pin when configuring pin function will cause a wrong data to be received. * And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t)BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t)BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -211,10 +211,6 @@ void board_init_clock(void) clock_add_to_group(clock_can2, 0); clock_add_to_group(clock_can3, 0); clock_add_to_group(clock_ptpc, 0); - clock_add_to_group(clock_lin0, 0); - clock_add_to_group(clock_lin1, 0); - clock_add_to_group(clock_lin2, 0); - clock_add_to_group(clock_lin3, 0); clock_add_to_group(clock_gptmr0, 0); clock_add_to_group(clock_gptmr1, 0); clock_add_to_group(clock_gptmr2, 0); @@ -332,6 +328,8 @@ void board_init_usb_pins(void) { init_usb_pins(); usb_hcd_set_power_ctrl_polarity(BOARD_USB, true); + /* Wait USB_PWR pin control vbus power stable. Time depend on decoupling capacitor, you can decrease or increase this time */ + board_delay_ms(100); /* As QFN32, QFN48 and LQFP64 has no vbus pin, so should be call usb_phy_using_internal_vbus() API to use internal vbus. */ /* usb_phy_using_internal_vbus(BOARD_USB); */ @@ -386,26 +384,6 @@ void board_init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) GPIO_GET_PIN_INDEX(BOARD_SPI_CS_PIN), !BOARD_SPI_CS_ACTIVE_LEVEL); } -void board_init_lin_pins(LINV2_Type *ptr) -{ - init_lin_pins(ptr); - gpio_set_pin_output_with_initial(BOARD_12V_EN_GPIO_CTRL, BOARD_12V_EN_GPIO_INDEX, BOARD_12V_EN_GPIO_PIN, 1); /* enable 12v output */ -} - -uint32_t board_init_lin_clock(LINV2_Type *ptr) -{ - if (ptr == HPM_LIN2) { - clock_add_to_group(clock_lin2, 0); - clock_set_source_divider(clock_lin2, clk_src_pll1_clk0, 40U); /* 20MHz */ - return clock_get_frequency(clock_lin2); - } else if (ptr == HPM_LIN3) { - clock_add_to_group(clock_lin3, 0); - clock_set_source_divider(clock_lin3, clk_src_pll1_clk0, 40U); /* 20MHz */ - return clock_get_frequency(clock_lin3); - } - return 0; -} - void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level) { (void) usb_index; @@ -559,6 +537,10 @@ uint32_t board_init_uart_clock(UART_Type *ptr) clock_set_source_divider(clock_uart2, clk_src_pll0_clk2, 8); clock_add_to_group(clock_uart2, 0); freq = clock_get_frequency(clock_uart2); + } else if (ptr == HPM_UART3) { + clock_set_source_divider(clock_uart3, clk_src_pll0_clk2, 8); + clock_add_to_group(clock_uart3, 0); + freq = clock_get_frequency(clock_uart3); } return freq; @@ -620,4 +602,16 @@ void board_init_i2c(I2C_Type *ptr) void board_init_adc_qeiv2_pins(void) { init_adc_qeiv2_pins(); -} \ No newline at end of file +} + +void board_lin_transceiver_control(bool enable) +{ + init_lin_transceiver_ctrl_pin(); + if (enable) { + gpio_set_pin_output_with_initial(BOARD_12V_EN_GPIO_CTRL, BOARD_12V_EN_GPIO_INDEX, BOARD_12V_EN_GPIO_PIN, 1); /* enable 12v output */ + gpio_set_pin_output_with_initial(BOARD_LIN_TRANSCEIVER_GPIO_CTRL, BOARD_LIN_TRANSCEIVER_GPIO_INDEX, BOARD_LIN_TRANSCEIVER_GPIO_PIN, 1); /* disable transceiver sleep */ + } else { + gpio_set_pin_output_with_initial(BOARD_12V_EN_GPIO_CTRL, BOARD_12V_EN_GPIO_INDEX, BOARD_12V_EN_GPIO_PIN, 0); /* disable 12v output */ + gpio_set_pin_output_with_initial(BOARD_LIN_TRANSCEIVER_GPIO_CTRL, BOARD_LIN_TRANSCEIVER_GPIO_INDEX, BOARD_LIN_TRANSCEIVER_GPIO_PIN, 0); /* enable transceiver sleep */ + } +} diff --git a/boards/hpm5300evk/board.h b/boards/hpm5300evk/board.h index b75f0702d..ee3e9e442 100644 --- a/boards/hpm5300evk/board.h +++ b/boards/hpm5300evk/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 HPMicro + * Copyright (c) 2023-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -18,40 +18,44 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm5300evk" +#define BOARD_NAME "hpm5300evk" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_4 /* align with used pin */ /* dma section */ -#define BOARD_APP_HDMA HPM_HDMA -#define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_HDMA_IRQ IRQn_HDMA +#define BOARD_APP_DMAMUX HPM_DMAMUX #define TEST_DMA_CONTROLLER HPM_HDMA -#define TEST_DMA_IRQ IRQn_HDMA +#define TEST_DMA_IRQ IRQn_HDMA -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART2 +#define BOARD_APP_UART_IRQ IRQn_UART2 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart2 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART2_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART2_TX #endif -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* uart lin sample section */ +#define BOARD_UART_LIN HPM_UART3 +#define BOARD_UART_LIN_IRQ IRQn_UART3 +#define BOARD_UART_LIN_CLK_NAME clock_uart3 +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOA +#define BOARD_UART_LIN_TX_PIN (15U) /* PA15 should align with used pin in pinmux configuration */ + #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -59,29 +63,43 @@ #endif #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#ifndef BOARD_CONSOLE_UART_BASE +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif -#define BOARD_FREEMASTER_UART_BASE HPM_UART2 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART2 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart2 +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ /* nor flash section */ #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) /* Check */ -#define BOARD_FLASH_SIZE (SIZE_1MB) +#define BOARD_FLASH_SIZE (SIZE_1MB) /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 +#define BOARD_APP_I2C_BASE HPM_I2C0 +#define BOARD_APP_I2C_IRQ IRQn_I2C0 #define BOARD_APP_I2C_CLK_NAME clock_i2c0 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 /* gptmr section */ #define BOARD_GPTMR HPM_GPTMR0 @@ -99,17 +117,22 @@ #define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr0 /* User LED */ -#define BOARD_LED_GPIO_CTRL HPM_GPIO0 +#define BOARD_LED_GPIO_CTRL HPM_GPIO0 #define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_LED_GPIO_PIN 23 +#define BOARD_LED_GPIO_PIN 23 #define BOARD_LED_OFF_LEVEL 1 -#define BOARD_LED_ON_LEVEL 0 +#define BOARD_LED_ON_LEVEL 0 -/* 12V Power Enable*/ -#define BOARD_12V_EN_GPIO_CTRL HPM_GPIO0 +/* 12V Power Enable for lin transceiver */ +#define BOARD_SUPPORT_LIN_TRANSCEIVER_CONTROL 1 +#define BOARD_12V_EN_GPIO_CTRL HPM_GPIO0 #define BOARD_12V_EN_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_12V_EN_GPIO_PIN 24 +#define BOARD_12V_EN_GPIO_PIN 24 +#define BOARD_LIN_TRANSCEIVER_GPIO_CTRL HPM_GPIO0 +#define BOARD_LIN_TRANSCEIVER_GPIO_INDEX GPIO_DI_GPIOA +#define BOARD_LIN_TRANSCEIVER_GPIO_PIN 13 + /* gpiom section */ #define BOARD_APP_GPIOM_BASE HPM_GPIOM @@ -117,30 +140,30 @@ #define BOARD_APP_GPIOM_USING_CTRL_NAME gpiom_core0_fast /* User button */ -#define BOARD_APP_GPIO_CTRL HPM_GPIO0 +#define BOARD_APP_GPIO_CTRL HPM_GPIO0 #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_APP_GPIO_PIN 9 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_A +#define BOARD_APP_GPIO_PIN 9 +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_A /* spi section */ -#define BOARD_APP_SPI_BASE HPM_SPI1 +#define BOARD_APP_SPI_BASE HPM_SPI1 #define BOARD_APP_SPI_CLK_NAME clock_spi1 #define BOARD_APP_SPI_IRQ IRQn_SPI1 #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI1_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI1_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PA26 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI1_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI1_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PA26 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* ADC section */ -#define BOARD_APP_ADC16_NAME "ADC0" -#define BOARD_APP_ADC16_BASE HPM_ADC0 -#define BOARD_APP_ADC16_IRQn IRQn_ADC0 -#define BOARD_APP_ADC16_CH_1 (11U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) +#define BOARD_APP_ADC16_NAME "ADC0" +#define BOARD_APP_ADC16_BASE HPM_ADC0 +#define BOARD_APP_ADC16_IRQn IRQn_ADC0 +#define BOARD_APP_ADC16_CH_1 (13U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) #define BOARD_APP_ADC16_HW_TRIG_SRC HPM_PWM0 #define BOARD_APP_ADC16_HW_TRGM HPM_TRGM0 @@ -148,142 +171,136 @@ #define BOARD_APP_ADC16_HW_TRGM_OUT_SEQ TRGM_TRGOCFG_ADC0_STRGI #define BOARD_APP_ADC16_HW_TRGM_OUT_PMT TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* DAC section */ -#define BOARD_DAC_BASE HPM_DAC0 -#define BOARD_DAC_IRQn IRQn_DAC0 -#define BOARD_APP_DAC_CLOCK_NAME clock_dac0 +#define BOARD_DAC_BASE HPM_DAC0 +#define BOARD_DAC_IRQn IRQn_DAC0 +#define BOARD_APP_DAC_CLOCK_NAME clock_dac0 /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90002U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000006U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90002U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000006U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* SDXC section */ -#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC0) -#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) +#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC0) +#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) /* MCAN section */ -#define BOARD_APP_CAN_BASE HPM_MCAN3 -#define BOARD_APP_CAN_IRQn IRQn_CAN3 +#define BOARD_APP_CAN_BASE HPM_MCAN3 +#define BOARD_APP_CAN_IRQn IRQn_MCAN3 /* CALLBACK TIMER section */ -#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr3) /* APP PWM */ -#define BOARD_APP_PWM HPM_PWM0 -#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 -#define BOARD_APP_PWM_OUT1 2 -#define BOARD_APP_PWM_OUT2 3 -#define BOARD_APP_TRGM HPM_TRGM0 -#define BOARD_APP_PWM_IRQ IRQn_PWM0 +#define BOARD_APP_PWM HPM_PWM0 +#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 +#define BOARD_APP_PWM_OUT1 2 +#define BOARD_APP_PWM_OUT2 3 +#define BOARD_APP_TRGM HPM_TRGM0 +#define BOARD_APP_PWM_IRQ IRQn_PWM0 #define BOARD_APP_TRGM_PWM_OUTPUT TRGM_TRGOCFG_PWM0_SYNCI /*BLDC pwm*/ /*PWM define*/ -#define BOARD_BLDCPWM HPM_PWM0 -#define BOARD_BLDC_UH_PWM_OUTPIN (6U) -#define BOARD_BLDC_UL_PWM_OUTPIN (7U) -#define BOARD_BLDC_VH_PWM_OUTPIN (4U) -#define BOARD_BLDC_VL_PWM_OUTPIN (5U) -#define BOARD_BLDC_WH_PWM_OUTPIN (2U) -#define BOARD_BLDC_WL_PWM_OUTPIN (3U) -#define BOARD_BLDCPWM_TRGM HPM_TRGM0 -#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM0 -#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) -#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) -#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) -#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) -#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) -#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) -#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) -#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) -#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) +#define BOARD_BLDCPWM HPM_PWM0 +#define BOARD_BLDC_UH_PWM_OUTPIN (6U) +#define BOARD_BLDC_UL_PWM_OUTPIN (7U) +#define BOARD_BLDC_VH_PWM_OUTPIN (4U) +#define BOARD_BLDC_VL_PWM_OUTPIN (5U) +#define BOARD_BLDC_WH_PWM_OUTPIN (2U) +#define BOARD_BLDC_WL_PWM_OUTPIN (3U) +#define BOARD_BLDCPWM_TRGM HPM_TRGM0 +#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM0 +#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) +#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) +#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) +#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) +#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) +#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) +#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) +#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) +#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) /*HALL define*/ /*RDC*/ -#define BOARD_RDC_TRGM HPM_TRGM0 -#define BOARD_RDC_TRGIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_RDC_TRGO_0 -#define BOARD_RDC_TRG_NUM TRGM_TRGOCFG_MOT_GPIO0 -#define BOARD_RDC_TRG_ADC_NUM TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_RDC_ADC_I_BASE HPM_ADC0 -#define BOARD_RDC_ADC_Q_BASE HPM_ADC1 -#define BOARD_RDC_ADC_I_CHN (5U) -#define BOARD_RDC_ADC_Q_CHN (6U) -#define BOARD_RDC_ADC_IRQn IRQn_ADC0 -#define BOARD_RDC_ADC_TRIG_FLAG adc16_event_trig_complete -#define BOARD_RDC_ADC_TRG ADC16_CONFIG_TRG0A +#define BOARD_RDC_TRGM HPM_TRGM0 +#define BOARD_RDC_TRGIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_RDC_TRGO_0 +#define BOARD_RDC_TRG_NUM TRGM_TRGOCFG_MOT_GPIO0 +#define BOARD_RDC_TRG_ADC_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_RDC_ADC_I_BASE HPM_ADC0 +#define BOARD_RDC_ADC_Q_BASE HPM_ADC1 +#define BOARD_RDC_ADC_I_CHN (5U) +#define BOARD_RDC_ADC_Q_CHN (6U) +#define BOARD_RDC_ADC_IRQn IRQn_ADC0 +#define BOARD_RDC_ADC_TRIG_FLAG adc16_event_trig_complete +#define BOARD_RDC_ADC_TRG ADC16_CONFIG_TRG0A /*QEI*/ -#define BOARD_BLDC_QEI_TRGM HPM_TRGM0 -#define BOARD_BLDC_QEIV2_BASE HPM_QEI1 -#define BOARD_BLDC_QEIV2_IRQ IRQn_QEI1 -#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) -#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0 -#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) -#define BOARD_BLDC_QEI_ADC_MATRIX_ADC0 trgm_adc_matrix_output_to_qei1_adc0 -#define BOARD_BLDC_QEI_ADC_MATRIX_ADC1 trgm_adc_matrix_output_to_qei1_adc1 +#define BOARD_BLDC_QEI_TRGM HPM_TRGM0 +#define BOARD_BLDC_QEIV2_BASE HPM_QEI1 +#define BOARD_BLDC_QEIV2_IRQ IRQn_QEI1 +#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) +#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0 +#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) +#define BOARD_BLDC_QEI_ADC_MATRIX_ADC0 trgm_adc_matrix_output_to_qei1_adc0 +#define BOARD_BLDC_QEI_ADC_MATRIX_ADC1 trgm_adc_matrix_output_to_qei1_adc1 /*Timer define*/ -#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 -#define BOARD_BLDC_TMR_CH 0 -#define BOARD_BLDC_TMR_CMP 0 -#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 -#define BOARD_BLDC_TMR_RELOAD (100000U) +#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 +#define BOARD_BLDC_TMR_CH 0 +#define BOARD_BLDC_TMR_CMP 0 +#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 +#define BOARD_BLDC_TMR_RELOAD (100000U) /*adc*/ -#define BOARD_BLDC_ADC_MODULE (ADCX_MODULE_ADC16) -#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (5U) -#define BOARD_BLDC_ADC_CH_V (6U) -#define BOARD_BLDC_ADC_CH_W (4U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE (ADCX_MODULE_ADC16) +#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (5U) +#define BOARD_BLDC_ADC_CH_V (6U) +#define BOARD_BLDC_ADC_CH_W (4U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC16_CONFIG_TRG0A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A - -#define BOARD_PLB_COUNTER HPM_PLB -#define BOARD_PLB_PWM_BASE HPM_PWM0 -#define BOARD_PLB_PWM_CLOCK_NAME clock_mot0 -#define BOARD_PLB_TRGM HPM_TRGM0 -#define BOARD_PLB_PWM_TRG (HPM_TRGM0_INPUT_SRC_PWM0_CH8REF) -#define BOARD_PLB_IN_PWM_TRG_NUM (TRGM_TRGOCFG_PLB_IN_00) -#define BOARD_PLB_IN_PWM_PULSE_TRG_NUM (TRGM_TRGOCFG_PLB_IN_02) -#define BOARD_PLB_OUT_TRG (HPM_TRGM0_INPUT_SRC_PLB_OUT00) -#define BOARD_PLB_IO_TRG_NUM (TRGM_TRGOCFG_MOT_GPIO2) -#define BOARD_PLB_IO_TRG_SHIFT (2) -#define BOARD_PLB_PWM_CMP (8U) -#define BOARD_PLB_PWM_CHN (8U) -#define BOARD_PLB_CHN plb_chn0 - -/* lin section */ -#define BOARD_LIN HPM_LIN3 -#define BOARD_LIN_CLK_NAME clock_lin3 -#define BOARD_LIN_IRQ IRQn_LIN3 -#define BOARD_LIN_BAUDRATE (19200U) +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A + +#define BOARD_PLB_COUNTER HPM_PLB +#define BOARD_PLB_PWM_BASE HPM_PWM0 +#define BOARD_PLB_PWM_CLOCK_NAME clock_mot0 +#define BOARD_PLB_TRGM HPM_TRGM0 +#define BOARD_PLB_PWM_TRG (HPM_TRGM0_INPUT_SRC_PWM0_CH8REF) +#define BOARD_PLB_IN_PWM_TRG_NUM (TRGM_TRGOCFG_PLB_IN_00) +#define BOARD_PLB_IN_PWM_PULSE_TRG_NUM (TRGM_TRGOCFG_PLB_IN_02) +#define BOARD_PLB_OUT_TRG (HPM_TRGM0_INPUT_SRC_PLB_OUT00) +#define BOARD_PLB_IO_TRG_NUM (TRGM_TRGOCFG_MOT_GPIO2) +#define BOARD_PLB_IO_TRG_SHIFT (2) +#define BOARD_PLB_PWM_CMP (8U) +#define BOARD_PLB_PWM_CHN (8U) +#define BOARD_PLB_CHN plb_chn0 /* QEO */ -#define BOARD_QEO HPM_QEO0 +#define BOARD_QEO HPM_QEO0 #define BOARD_QEO_TRGM_POS trgm_pos_matrix_output_to_qeo0 /* moto */ #define BOARD_MOTOR_CLK_NAME clock_mot0 /* SEI */ -#define BOARD_SEI HPM_SEI +#define BOARD_SEI HPM_SEI #define BOARD_SEI_CTRL SEI_CTRL_1 #define BOARD_SEI_IRQn IRQn_SEI1 @@ -301,17 +318,24 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR2 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR2 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr2 - +#define BOARD_FREERTOS_TIMER HPM_GPTMR2 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR2 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr2 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR2 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR2 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr2 #if defined(__cplusplus) extern "C" { #endif /* __cplusplus */ typedef void (*board_timer_cb)(void); +void board_init(void); +void board_init_console(void); void board_init_gpio_pins(void); void board_init_led_pins(void); void board_init_usb_pins(void); @@ -332,10 +356,7 @@ void board_enable_output_rgb_led(uint8_t color); void board_init_dac_pins(DAC_Type *ptr); void board_write_spi_cs(uint32_t pin, uint8_t state); void board_init_spi_pins_with_gpio_as_cs(SPI_Type *ptr); -void board_init_lin_pins(LINV2_Type *ptr); -uint32_t board_init_lin_clock(LINV2_Type *ptr); -void board_init(void); void board_init_usb_dp_dm_pins(void); void board_init_clock(void); void board_delay_us(uint32_t us); @@ -354,6 +375,8 @@ void board_init_sei_pins(SEI_Type *ptr, uint8_t sei_ctrl_idx); void board_init_i2c(I2C_Type *ptr); void board_init_adc_qeiv2_pins(void); + +void board_lin_transceiver_control(bool enable); #if defined(__cplusplus) } #endif /* __cplusplus */ diff --git a/boards/hpm5300evk/hpm5300evk.yaml b/boards/hpm5300evk/hpm5300evk.yaml index 7a7e38f3a..652e227f8 100644 --- a/boards/hpm5300evk/hpm5300evk.yaml +++ b/boards/hpm5300evk/hpm5300evk.yaml @@ -11,37 +11,7 @@ board: type: qspi-nor-flash size: 1M feature: - - sei - - sdp - - rng - - rdc - - qeiv2 - - linv2 - - dmav2 - - qeo - - pwm - - mmc - - uart_hardware_rx_idle - - uart_tamagawa - - uart_9bit - - uart - - plb - - dac - - adc16 - - pdgo - - mcan - - ewdg - - gpiom - - tsns - - crc - - spi - - i2c - - usb-otg - - ptp - - motor-control - - bldc_hfi - - bldc_smc - - opamp - - gpt_pin - - acmp - - ptpc + - board_gpt_pin + - board_motor_control + excluded_samples: + - samples/motor_ctrl/bldc_block diff --git a/boards/hpm5300evk/pinmux.c b/boards/hpm5300evk/pinmux.c index 2577bbfa8..2bc568f78 100644 --- a/boards/hpm5300evk/pinmux.c +++ b/boards/hpm5300evk/pinmux.c @@ -27,12 +27,12 @@ void init_xtal_pins(void) void init_py_pins_as_pgpio(void) { /* Set PY00-PY05 default function to PGPIO */ - HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = IOC_PY00_FUNC_CTL_PGPIO_Y_00; - HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = IOC_PY01_FUNC_CTL_PGPIO_Y_01; - HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = IOC_PY02_FUNC_CTL_PGPIO_Y_02; - HPM_PIOC->PAD[IOC_PAD_PY03].FUNC_CTL = IOC_PY03_FUNC_CTL_PGPIO_Y_03; - HPM_PIOC->PAD[IOC_PAD_PY04].FUNC_CTL = IOC_PY04_FUNC_CTL_PGPIO_Y_04; - HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_PGPIO_Y_05; + HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = PIOC_PY00_FUNC_CTL_PGPIO_Y_00; + HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = PIOC_PY01_FUNC_CTL_PGPIO_Y_01; + HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = PIOC_PY02_FUNC_CTL_PGPIO_Y_02; + HPM_PIOC->PAD[IOC_PAD_PY03].FUNC_CTL = PIOC_PY03_FUNC_CTL_PGPIO_Y_03; + HPM_PIOC->PAD[IOC_PAD_PY04].FUNC_CTL = PIOC_PY04_FUNC_CTL_PGPIO_Y_04; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_PGPIO_Y_05; } void init_uart_pins(UART_Type *ptr) @@ -44,11 +44,37 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PB08].FUNC_CTL = IOC_PB08_FUNC_CTL_UART2_TXD; HPM_IOC->PAD[IOC_PAD_PB09].FUNC_CTL = IOC_PB09_FUNC_CTL_UART2_RXD; HPM_IOC->PAD[IOC_PAD_PB10].FUNC_CTL = IOC_PB10_FUNC_CTL_UART2_DE; + } else if (ptr == HPM_UART3) { + /* using for uart_lin function */ + HPM_IOC->PAD[IOC_PAD_PA14].FUNC_CTL = IOC_PA14_FUNC_CTL_UART3_RXD; + HPM_IOC->PAD[IOC_PAD_PA15].FUNC_CTL = IOC_PA15_FUNC_CTL_UART3_TXD; } else { ; } } +void init_lin_transceiver_ctrl_pin(void) +{ + /* PA24 is used to control the 12V power supply of the LIN transceiver */ + HPM_IOC->PAD[IOC_PAD_PA24].FUNC_CTL = IOC_PA24_FUNC_CTL_GPIO_A_24; + /* PA13 is used to control the LIN transceiver not to enter sleep mode */ + HPM_IOC->PAD[IOC_PAD_PA13].FUNC_CTL = IOC_PA13_FUNC_CTL_GPIO_A_13; +} + +/* for uart_lin case, need to configure pin as gpio to sent break signal */ +void init_uart_pin_as_gpio(UART_Type *ptr) +{ + /* pull-up */ + uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); + + if (ptr == HPM_UART3) { + HPM_IOC->PAD[IOC_PAD_PA14].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PA15].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PA14].FUNC_CTL = IOC_PA14_FUNC_CTL_GPIO_A_14; + HPM_IOC->PAD[IOC_PAD_PA15].FUNC_CTL = IOC_PA15_FUNC_CTL_GPIO_A_15; + } +} + void init_i2c_pins(I2C_Type *ptr) { if (ptr == HPM_I2C0) { @@ -152,16 +178,7 @@ void init_pwm_pins(PWM_Type *ptr) void init_adc_pins(void) { - HPM_IOC->PAD[IOC_PAD_PB00].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC Test: ADC0.15/ADC1.15 */ - HPM_IOC->PAD[IOC_PAD_PB01].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_BUS: ADC0.14/ADC1.14 */ - HPM_IOC->PAD[IOC_PAD_PB08].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_A: ADC0.11/ADC1.11 */ - HPM_IOC->PAD[IOC_PAD_PB09].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_B: ADC0.1 /ADC1.1 */ - HPM_IOC->PAD[IOC_PAD_PB10].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_C: ADC0.2 /ADC1.2 */ - HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_D: ADC0.3 /ADC1.3 */ - HPM_IOC->PAD[IOC_PAD_PB12].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_IW: ADC0.4 /ADC1.4 */ - HPM_IOC->PAD[IOC_PAD_PB13].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_IU: ADC0.5 /ADC1.5 */ - HPM_IOC->PAD[IOC_PAD_PB14].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_IV: ADC0.6 /ADC1.6 */ - HPM_IOC->PAD[IOC_PAD_PB15].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* Board ID: ADC0.7 /ADC1.7 */ + HPM_IOC->PAD[IOC_PAD_PB05].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC0.13 */ } void init_adc_bldc_pins(void) @@ -198,19 +215,19 @@ void init_usb_pins(void) HPM_IOC->PAD[IOC_PAD_PY02].FUNC_CTL = IOC_PY02_FUNC_CTL_USB0_PWR; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = IOC_PY00_FUNC_CTL_SOC_GPIO_Y_00; - HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = IOC_PY01_FUNC_CTL_SOC_GPIO_Y_01; - HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = IOC_PY02_FUNC_CTL_SOC_GPIO_Y_02; + HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = PIOC_PY00_FUNC_CTL_SOC_GPIO_Y_00; + HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = PIOC_PY01_FUNC_CTL_SOC_GPIO_Y_01; + HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = PIOC_PY02_FUNC_CTL_SOC_GPIO_Y_02; } void init_can_pins(MCAN_Type *ptr) { if (ptr == HPM_MCAN3) { - HPM_IOC->PAD[IOC_PAD_PY04].FUNC_CTL = IOC_PY04_FUNC_CTL_CAN3_RXD; - HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_CAN3_TXD; + HPM_IOC->PAD[IOC_PAD_PY04].FUNC_CTL = IOC_PY04_FUNC_CTL_MCAN3_RXD; + HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_MCAN3_TXD; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY04].FUNC_CTL = IOC_PY04_FUNC_CTL_SOC_GPIO_Y_04; - HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_SOC_GPIO_Y_05; + HPM_PIOC->PAD[IOC_PAD_PY04].FUNC_CTL = PIOC_PY04_FUNC_CTL_SOC_GPIO_Y_04; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_SOC_GPIO_Y_05; } } @@ -233,22 +250,6 @@ void init_dac_pins(DAC_Type *ptr) } } -void init_lin_pins(LINV2_Type *ptr) -{ - /** enable open drain and pull up */ - uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_OD_SET(1); - if (ptr == HPM_LIN3) { - HPM_IOC->PAD[IOC_PAD_PA13].FUNC_CTL = IOC_PA13_FUNC_CTL_LIN3_TREN; - HPM_IOC->PAD[IOC_PAD_PA13].PAD_CTL = pad_ctl; - HPM_IOC->PAD[IOC_PAD_PA14].FUNC_CTL = IOC_PA14_FUNC_CTL_LIN3_RXD; - HPM_IOC->PAD[IOC_PAD_PA14].PAD_CTL = pad_ctl; - HPM_IOC->PAD[IOC_PAD_PA15].FUNC_CTL = IOC_PA15_FUNC_CTL_LIN3_TXD; - HPM_IOC->PAD[IOC_PAD_PA15].PAD_CTL = pad_ctl; - } - /* Enable 12V */ - HPM_IOC->PAD[IOC_PAD_PA24].FUNC_CTL = IOC_PA24_FUNC_CTL_GPIO_A_24; -} - void init_plb_pins(void) { HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_TRGM0_P_02; diff --git a/boards/hpm5300evk/pinmux.h b/boards/hpm5300evk/pinmux.h index bd77953e7..1ff177986 100644 --- a/boards/hpm5300evk/pinmux.h +++ b/boards/hpm5300evk/pinmux.h @@ -14,6 +14,7 @@ extern "C" { void init_xtal_pins(void); void init_py_pins_as_pgpio(void); void init_uart_pins(UART_Type *ptr); +void init_uart_pin_as_gpio(UART_Type *ptr); void init_i2c_pins(I2C_Type *ptr); void init_gpio_pins(void); void init_spi_pins(SPI_Type *ptr); @@ -33,7 +34,6 @@ void init_dac_pins(DAC_Type *ptr); void init_led_pins_as_gpio(void); void init_led_pins_as_pwm(void); void init_plb_pins(void); -void init_lin_pins(LINV2_Type *ptr); void init_qeo_pins(QEO_Type *ptr); void init_sei_pins(SEI_Type *ptr, uint8_t sei_ctrl_idx); void init_rdc_pin(void); @@ -41,6 +41,7 @@ void init_qeiv2_uvw_pins(QEIV2_Type *ptr); void init_qeiv2_ab_pins(QEIV2_Type *ptr); void init_qeiv2_abz_pins(QEIV2_Type *ptr); void init_opamp_pins(void); +void init_lin_transceiver_ctrl_pin(void); #ifdef __cplusplus } #endif diff --git a/boards/hpm5301evklite/README_en.md b/boards/hpm5301evklite/README_en.md index 0f0c8d4d0..495763574 100644 --- a/boards/hpm5301evklite/README_en.md +++ b/boards/hpm5301evklite/README_en.md @@ -40,7 +40,9 @@ By default, UART0 is used for console printing. Connect UART0.TXD (J3.36) and UA (lab_hpm5301_evklite_board)= -- UART Pin: +- UART Pin: modbus_rtu sample + - The UART0 used for debugger console or some functional testing using UART + - The UART3 is used for some functional testing using UART, such as MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. | Function | Position | | --------- | -------- | diff --git a/boards/hpm5301evklite/README_zh.md b/boards/hpm5301evklite/README_zh.md index 7fd2c8b76..81c3d7056 100644 --- a/boards/hpm5301evklite/README_zh.md +++ b/boards/hpm5301evklite/README_zh.md @@ -41,6 +41,8 @@ HPM5301EVKLite是基于先楫的入门级高性能MCU HPM5301的开发板。HPM5 (lab_hpm5301_evklite_board)= - UART引脚 + - UART0用于调试控制台串口或一些使用UART的功能测试 + - UART3用于一些使用UART的功能测试,例如MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 | 功能 | 位置 | | --------- | ------ | diff --git a/boards/hpm5301evklite/board.c b/boards/hpm5301evklite/board.c index caf7074c0..e613bdfbe 100644 --- a/boards/hpm5301evklite/board.c +++ b/boards/hpm5301evklite/board.c @@ -88,16 +88,16 @@ void board_init_console(void) * uart rx pin when configuring pin function will cause a wrong data to be received. * And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t)BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t)BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -301,6 +301,8 @@ void board_init_usb_pins(void) { init_usb_pins(); usb_hcd_set_power_ctrl_polarity(BOARD_USB, true); + /* Wait USB_PWR pin control vbus power stable. Time depend on decoupling capacitor, you can decrease or increase this time */ + board_delay_ms(100); /* As QFN32, QFN48 and LQFP64 has no vbus pin, so should be call usb_phy_using_internal_vbus() API to use internal vbus. */ usb_phy_using_internal_vbus(BOARD_USB); @@ -413,7 +415,7 @@ uint32_t board_init_uart_clock(UART_Type *ptr) clock_add_to_group(clock_uart0, 0); freq = clock_get_frequency(clock_uart0); } else if (ptr == HPM_UART3) { - clock_set_source_divider(clock_uart3, clk_src_osc24m, 1); + clock_set_source_divider(clock_uart3, clk_src_pll0_clk2, 6); /* 50MHz */ clock_add_to_group(clock_uart3, 0); freq = clock_get_frequency(clock_uart3); } diff --git a/boards/hpm5301evklite/board.h b/boards/hpm5301evklite/board.h index 6af238b4b..a851e978c 100644 --- a/boards/hpm5301evklite/board.h +++ b/boards/hpm5301evklite/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 HPMicro + * Copyright (c) 2023-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -18,40 +18,43 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm5301evklite" +#define BOARD_NAME "hpm5301evklite" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_4 /* align with used pin */ /* dma section */ -#define BOARD_APP_HDMA HPM_HDMA -#define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_HDMA_IRQ IRQn_HDMA +#define BOARD_APP_DMAMUX HPM_DMAMUX #define TEST_DMA_CONTROLLER HPM_HDMA -#define TEST_DMA_IRQ IRQn_HDMA +#define TEST_DMA_IRQ IRQn_HDMA -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART3 +#define BOARD_APP_UART_IRQ IRQn_UART3 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart3 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART3_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART3_TX #endif -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* uart lin sample section */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOB +#define BOARD_UART_LIN_TX_PIN (15U) /* PB15 should align with used pin in pinmux configuration */ + #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -59,25 +62,43 @@ #endif #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#ifndef BOARD_CONSOLE_UART_BASE +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ + /* nor flash section */ #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) /* Check */ -#define BOARD_FLASH_SIZE (SIZE_1MB) +#define BOARD_FLASH_SIZE (SIZE_1MB) /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C2 -#define BOARD_APP_I2C_IRQ IRQn_I2C2 +#define BOARD_APP_I2C_BASE HPM_I2C2 +#define BOARD_APP_I2C_IRQ IRQn_I2C2 #define BOARD_APP_I2C_CLK_NAME clock_i2c2 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C2 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C2 /* gptmr section */ #define BOARD_GPTMR HPM_GPTMR0 @@ -95,17 +116,17 @@ #define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr0 /* User LED */ -#define BOARD_LED_GPIO_CTRL HPM_GPIO0 +#define BOARD_LED_GPIO_CTRL HPM_GPIO0 #define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_LED_GPIO_PIN 10 +#define BOARD_LED_GPIO_PIN 10 #define BOARD_LED_OFF_LEVEL 1 -#define BOARD_LED_ON_LEVEL 0 +#define BOARD_LED_ON_LEVEL 0 /* 12V Power Enable*/ -#define BOARD_12V_EN_GPIO_CTRL HPM_GPIO0 +#define BOARD_12V_EN_GPIO_CTRL HPM_GPIO0 #define BOARD_12V_EN_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_12V_EN_GPIO_PIN 24 +#define BOARD_12V_EN_GPIO_PIN 24 /* gpiom section */ #define BOARD_APP_GPIOM_BASE HPM_GPIOM @@ -119,69 +140,69 @@ #define BOARD_BUTTON_TINYUF2_PIN 9 /* User button */ -#define BOARD_APP_GPIO_CTRL HPM_GPIO0 +#define BOARD_APP_GPIO_CTRL HPM_GPIO0 #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_APP_GPIO_PIN 3 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_A +#define BOARD_APP_GPIO_PIN 3 +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_A /* spi section */ -#define BOARD_APP_SPI_BASE HPM_SPI1 +#define BOARD_APP_SPI_BASE HPM_SPI1 #define BOARD_APP_SPI_CLK_NAME clock_spi1 #define BOARD_APP_SPI_IRQ IRQn_SPI1 #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI1_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI1_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PA26 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI1_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI1_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PA26 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* ADC section */ -#define BOARD_APP_ADC16_NAME "ADC0" -#define BOARD_APP_ADC16_BASE HPM_ADC0 -#define BOARD_APP_ADC16_IRQn IRQn_ADC0 -#define BOARD_APP_ADC16_CH_1 (11U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) +#define BOARD_APP_ADC16_NAME "ADC0" +#define BOARD_APP_ADC16_BASE HPM_ADC0 +#define BOARD_APP_ADC16_IRQn IRQn_ADC0 +#define BOARD_APP_ADC16_CH_1 (11U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90002U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000006U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90002U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000006U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* CALLBACK TIMER section */ -#define BOARD_CALLBACK_TIMER (HPM_GPTMR1) -#define BOARD_CALLBACK_TIMER_CH 0 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR1 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR1) +#define BOARD_CALLBACK_TIMER_CH 0 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR1 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr1) /*Timer define*/ -#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 -#define BOARD_BLDC_TMR_CH 0 -#define BOARD_BLDC_TMR_CMP 0 -#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 -#define BOARD_BLDC_TMR_RELOAD (100000U) +#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 +#define BOARD_BLDC_TMR_CH 0 +#define BOARD_BLDC_TMR_CMP 0 +#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 +#define BOARD_BLDC_TMR_RELOAD (100000U) /*adc*/ -#define BOARD_BLDC_ADC_MODULE (ADCX_MODULE_ADC16) -#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (5U) -#define BOARD_BLDC_ADC_CH_V (6U) -#define BOARD_BLDC_ADC_CH_W (4U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE (ADCX_MODULE_ADC16) +#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (5U) +#define BOARD_BLDC_ADC_CH_V (6U) +#define BOARD_BLDC_ADC_CH_W (4U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC16_CONFIG_TRG0A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A /* USB */ #define BOARD_USB HPM_USB0 @@ -194,11 +215,16 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR0 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR0 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr0 - +#define BOARD_FREERTOS_TIMER HPM_GPTMR0 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR0 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr0 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR0 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR0 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr0 #if defined(__cplusplus) extern "C" { #endif /* __cplusplus */ diff --git a/boards/hpm5301evklite/hpm5301evklite.yaml b/boards/hpm5301evklite/hpm5301evklite.yaml index 8e8926174..31086eb63 100644 --- a/boards/hpm5301evklite/hpm5301evklite.yaml +++ b/boards/hpm5301evklite/hpm5301evklite.yaml @@ -10,16 +10,3 @@ board: on-board-flash: type: qspi-nor-flash size: 1M - feature: - - uart_hardware_rx_idle - - uart - - adc16 - - pdgo - - ewdg - - gpiom - - tsns - - crc - - spi - - i2c - - usb-otg - - acmp diff --git a/boards/hpm5301evklite/pinmux.c b/boards/hpm5301evklite/pinmux.c index 78ce27f88..fd9b3b12d 100644 --- a/boards/hpm5301evklite/pinmux.c +++ b/boards/hpm5301evklite/pinmux.c @@ -26,6 +26,13 @@ void init_xtal_pins(void) void init_py_pins_as_pgpio(void) { + /* Set PY00-PY05 default function to PGPIO */ + HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = PIOC_PY00_FUNC_CTL_PGPIO_Y_00; + HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = PIOC_PY01_FUNC_CTL_PGPIO_Y_01; + HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = PIOC_PY02_FUNC_CTL_PGPIO_Y_02; + HPM_PIOC->PAD[IOC_PAD_PY03].FUNC_CTL = PIOC_PY03_FUNC_CTL_PGPIO_Y_03; + HPM_PIOC->PAD[IOC_PAD_PY04].FUNC_CTL = PIOC_PY04_FUNC_CTL_PGPIO_Y_04; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_PGPIO_Y_05; } void init_uart_pins(UART_Type *ptr) @@ -41,6 +48,20 @@ void init_uart_pins(UART_Type *ptr) } } +/* for uart_lin case, need to configure pin as gpio to sent break signal */ +void init_uart_pin_as_gpio(UART_Type *ptr) +{ + /* pull-up */ + uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); + + if (ptr == HPM_UART3) { + HPM_IOC->PAD[IOC_PAD_PB15].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PB14].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PB15].FUNC_CTL = IOC_PB15_FUNC_CTL_GPIO_B_15; + HPM_IOC->PAD[IOC_PAD_PB14].FUNC_CTL = IOC_PB14_FUNC_CTL_GPIO_B_14; + } +} + void init_i2c_pins(I2C_Type *ptr) { if (ptr == HPM_I2C2) { @@ -140,9 +161,9 @@ void init_usb_pins(void) HPM_IOC->PAD[IOC_PAD_PY02].FUNC_CTL = IOC_PY02_FUNC_CTL_USB0_PWR; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = IOC_PY00_FUNC_CTL_SOC_GPIO_Y_00; - HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = IOC_PY01_FUNC_CTL_SOC_GPIO_Y_01; - HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = IOC_PY02_FUNC_CTL_SOC_GPIO_Y_02; + HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = PIOC_PY00_FUNC_CTL_SOC_GPIO_Y_00; + HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = PIOC_PY01_FUNC_CTL_SOC_GPIO_Y_01; + HPM_PIOC->PAD[IOC_PAD_PY02].FUNC_CTL = PIOC_PY02_FUNC_CTL_SOC_GPIO_Y_02; } void init_led_pins_as_gpio(void) diff --git a/boards/hpm5301evklite/pinmux.h b/boards/hpm5301evklite/pinmux.h index 4e5f2e530..a34414b58 100644 --- a/boards/hpm5301evklite/pinmux.h +++ b/boards/hpm5301evklite/pinmux.h @@ -14,6 +14,7 @@ extern "C" { void init_xtal_pins(void); void init_py_pins_as_pgpio(void); void init_uart_pins(UART_Type *ptr); +void init_uart_pin_as_gpio(UART_Type *ptr); void init_i2c_pins(I2C_Type *ptr); void init_gpio_pins(void); void init_spi_pins(SPI_Type *ptr); diff --git a/boards/hpm6200evk/README_en.md b/boards/hpm6200evk/README_en.md index f0763d4c2..f6dbd1073 100644 --- a/boards/hpm6200evk/README_en.md +++ b/boards/hpm6200evk/README_en.md @@ -28,7 +28,9 @@ The HPM6200EVK provides a series of interfaces for the characteristic peripheral (lab_hpm6200_evk_board)= -- UART for core1 debug console +- UART pin + + The UART2 is used for core1 debug console or some functional testing using UART, such as MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. | Function | Position | | ---------- | -------- | @@ -62,8 +64,8 @@ The HPM6200EVK provides a series of interfaces for the characteristic peripheral | Function | Position | | -------- | ------ | -| I2C0.SCL | P1[5] | -| I2C0.SDA | P1[3] | +| I2C0.SCL | P2[7] | +| I2C0.SDA | P2[10] | - ACMP Pin: @@ -76,18 +78,15 @@ The HPM6200EVK provides a series of interfaces for the characteristic peripheral | Function | Position | | ------------- | ------ | -| GPTMR2.CAPT_0 | J4[15] | -| GPTMR2.COMP_0 | J4[17] | -| GPTMR2.COMP_1 | J4[1] | +| GPTMR1.CAPT_0 | P2[3] | +| GPTMR1.COMP_0 | P2[23] | +| GPTMR1.COMP_1 | P2[24] | - ADC16 Pin: -| Function | Position | -| ------------------------------ | -------- | -| ADC0.INA1 | J4[5] | -| ADC0.INA12/ADC1.INA8/ADC2.INA4 | J4[6] | -| ADC0.INA13/ADC1.INA9/ADC2.INA5 | J4[7] | -| ADC0.INA11/ADC1.INA7.ADC2.INA3 | J4[8] | +| Function | Position | +| --------- | -------- | +| ADC0.INA8 | P2[11] | - DAC Pin: @@ -130,3 +129,11 @@ The HPM6200EVK provides a series of interfaces for the characteristic peripheral | HALL.V | J4[18] | J12[4] | | HALL.W | J4[16] | J12[5] | | GND | J4[4] | J12[1] | + +- Tamper Pin + +| Function | Pin | Position | Mode | +|----------|--------|--------|----------| +| TAMP.04 | PZ04 | P1[33] | Active Mode | +| TAMP.05 | PZ05 | P1[36] | Active Mode | +| TAMP.06 | PZ06 | P1[38] | Passive Mode | diff --git a/boards/hpm6200evk/README_zh.md b/boards/hpm6200evk/README_zh.md index 87a6823eb..fe103006a 100644 --- a/boards/hpm6200evk/README_zh.md +++ b/boards/hpm6200evk/README_zh.md @@ -29,7 +29,9 @@ HPM6200EVK提供了一系列HPM6200系列微控制器特色外设的接口,包 (lab_hpm6200_evk_board)= -- CORE1调试串口引脚: +- UART引脚 + + UART2用于CORE1调试串口或一些使用UART的功能测试,例如MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 | 功能 | 位置 | | ---------- | ------ | @@ -63,8 +65,8 @@ HPM6200EVK提供了一系列HPM6200系列微控制器特色外设的接口,包 | 功能 | 位置 | | -------- | ------ | -| I2C0.SCL | P1[5] | -| I2C0.SDA | P1[3] | +| I2C0.SCL | P2[7] | +| I2C0.SDA | P2[10] | - ACMP引脚 @@ -77,18 +79,15 @@ HPM6200EVK提供了一系列HPM6200系列微控制器特色外设的接口,包 | 功能 | 位置 | | ------------- | ------ | -| GPTMR2.CAPT_0 | J4[15] | -| GPTMR2.COMP_0 | J4[17] | -| GPTMR2.COMP_1 | J4[1] | +| GPTMR1.CAPT_0 | P2[3] | +| GPTMR1.COMP_0 | P2[23] | +| GPTMR1.COMP_1 | P2[24] | - ADC16引脚 -| 功能 | 位置 | -| ------------------------------ | ----- | -| ADC0.INA1 | J4[5] | -| ADC0.INA12/ADC1.INA8/ADC2.INA4 | J4[6] | -| ADC0.INA13/ADC1.INA9/ADC2.INA5 | J4[7] | -| ADC0.INA11/ADC1.INA7.ADC2.INA3 | J4[8] | +| 功能 | 位置 | +| --------- | ------ | +| ADC0.INA8 | P2[11] | - DAC引脚 @@ -130,3 +129,11 @@ HPM6200EVK提供了一系列HPM6200系列微控制器特色外设的接口,包 | HALL.V | J4[18] | J12[4] | | HALL.W | J4[16] | J12[5] | | GND | J4[4] | J12[1] | + +- Tamper 接口 + +| 功能 | 引脚 | 位置 | 模式 | +|----------|--------|--------|---------| +| TAMP.04 | PZ04 | P1[33] | 主动模式 | +| TAMP.05 | PZ05 | P1[36] | 主动模式 | +| TAMP.06 | PZ06 | P1[38] | 被动模式 | diff --git a/boards/hpm6200evk/board.c b/boards/hpm6200evk/board.c index d0d394882..35b0faf0c 100644 --- a/boards/hpm6200evk/board.c +++ b/boards/hpm6200evk/board.c @@ -92,16 +92,16 @@ void board_init_console(void) /* uart needs to configure pin function before enabling clock, otherwise the level change of uart rx pin when configuring pin function will cause a wrong data to be received. And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t)BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t)BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -185,6 +185,12 @@ void board_init(void) #endif } +void board_init_core1(void) +{ + board_init_console(); + board_init_pmp(); +} + void board_delay_us(uint32_t us) { clock_cpu_delay_us(us); diff --git a/boards/hpm6200evk/board.h b/boards/hpm6200evk/board.h index e4c3df628..1d1402e6f 100644 --- a/boards/hpm6200evk/board.h +++ b/boards/hpm6200evk/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 HPMicro + * Copyright (c) 2023-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -17,35 +17,39 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm6200evk" +#define BOARD_NAME "hpm6200evk" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) #define SEC_CORE_IMG_START CORE1_ILM_LOCAL_BASE /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART2 +#define BOARD_APP_UART_IRQ IRQn_UART2 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart2 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART2_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART2_TX #endif -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* uart lin sample section */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOC +#define BOARD_UART_LIN_TX_PIN (26U) /* PC26 should align with used pin in pinmux configuration */ + #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -53,99 +57,116 @@ #endif #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE +#ifndef BOARD_CONSOLE_UART_BASE #if BOARD_RUNNING_CORE == HPM_CORE0 -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #else -#define BOARD_CONSOLE_BASE HPM_UART2 -#define BOARD_CONSOLE_CLK_NAME clock_uart2 +#define BOARD_CONSOLE_UART_BASE HPM_UART2 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart2 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART2 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART2_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART2_RX #endif #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif -#define BOARD_FREEMASTER_UART_BASE HPM_UART0 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART0 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart0 - /* uart microros sample section */ -#define BOARD_MICROROS_UART_BASE HPM_UART2 -#define BOARD_MICROROS_UART_IRQ IRQn_UART2 -#define BOARD_MICROROS_UART_CLK_NAME clock_uart2 +#define BOARD_MICROROS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MICROROS_UART_IRQ BOARD_APP_UART_IRQ +#define BOARD_MICROROS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME + +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ /* sdm section */ -#define BOARD_SDM HPM_SDM -#define BOARD_SDM_IRQ IRQn_SDFM -#define BOARD_SDM_CHANNEL 3 -#define BOARD_SDM_TRGM HPM_TRGM3 -#define BOARD_SDM_TRGM_GPTMR HPM_GPTMR3 -#define BOARD_SDM_TRGM_GPTMR_CH 2 -#define BOARD_SDM_TRGM_INPUT_SRC HPM_TRGM3_INPUT_SRC_GPTMR3_OUT2 -#define BOARD_SDM_TRGM_OUTPUT_DST HPM_TRGM3_OUTPUT_SRC_SDFM_TRG15 +#define BOARD_SDM HPM_SDM +#define BOARD_SDM_IRQ IRQn_SDFM +#define BOARD_SDM_CHANNEL 3 +#define BOARD_SDM_TRGM HPM_TRGM3 +#define BOARD_SDM_TRGM_GPTMR HPM_GPTMR3 +#define BOARD_SDM_TRGM_GPTMR_CH 2 +#define BOARD_SDM_TRGM_INPUT_SRC HPM_TRGM3_INPUT_SRC_GPTMR3_OUT2 +#define BOARD_SDM_TRGM_OUTPUT_DST HPM_TRGM3_OUTPUT_SRC_SDFM_TRG15 /* lin section */ -#define BOARD_LIN HPM_LIN0 -#define BOARD_LIN_CLK_NAME clock_lin0 -#define BOARD_LIN_IRQ IRQn_LIN0 -#define BOARD_LIN_BAUDRATE (19200U) +#define BOARD_LIN HPM_LIN0 +#define BOARD_LIN_CLK_NAME clock_lin0 +#define BOARD_LIN_IRQ IRQn_LIN0 +#define BOARD_LIN_BAUDRATE (19200U) /* nor flash section */ #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) -#define BOARD_FLASH_SIZE (16 * SIZE_1MB) +#define BOARD_FLASH_SIZE (16 * SIZE_1MB) /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 -#define BOARD_APP_I2C_CLK_NAME clock_i2c0 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 -#define BOARD_APP_I2C_DMAMUX_CH DMAMUX_MUXCFG_HDMA_MUX0 -#define BOARD_I2C_GPIO_CTRL HPM_GPIO0 -#define BOARD_I2C_SCL_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_I2C_SCL_GPIO_PIN 22 -#define BOARD_I2C_SDA_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_I2C_SDA_GPIO_PIN 23 +#define BOARD_APP_I2C_BASE HPM_I2C3 +#define BOARD_APP_I2C_IRQ IRQn_I2C3 +#define BOARD_APP_I2C_CLK_NAME clock_i2c3 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C3 +#define BOARD_APP_I2C_DMAMUX_CH DMAMUX_MUXCFG_HDMA_MUX0 +#define BOARD_I2C_GPIO_CTRL HPM_GPIO0 +#define BOARD_I2C_SCL_GPIO_INDEX GPIO_DO_GPIOB +#define BOARD_I2C_SCL_GPIO_PIN 20 +#define BOARD_I2C_SDA_GPIO_INDEX GPIO_DO_GPIOB +#define BOARD_I2C_SDA_GPIO_PIN 21 /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_5 /* align with used pin */ /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX /* gptmr section */ -#define BOARD_GPTMR HPM_GPTMR2 -#define BOARD_GPTMR_IRQ IRQn_GPTMR2 +#define BOARD_GPTMR HPM_GPTMR1 +#define BOARD_GPTMR_IRQ IRQn_GPTMR1 #define BOARD_GPTMR_CHANNEL 0 -#define BOARD_GPTMR_DMA_SRC HPM_DMA_SRC_GPTMR2_0 -#define BOARD_GPTMR_CLK_NAME clock_gptmr2 -#define BOARD_GPTMR_PWM HPM_GPTMR2 +#define BOARD_GPTMR_DMA_SRC HPM_DMA_SRC_GPTMR1_0 +#define BOARD_GPTMR_CLK_NAME clock_gptmr1 +#define BOARD_GPTMR_PWM HPM_GPTMR1 #define BOARD_GPTMR_PWM_CHANNEL 0 -#define BOARD_GPTMR_PWM_DMA_SRC HPM_DMA_SRC_GPTMR2_0 -#define BOARD_GPTMR_PWM_CLK_NAME clock_gptmr2 -#define BOARD_GPTMR_PWM_IRQ IRQn_GPTMR2 -#define BOARD_GPTMR_PWM_SYNC HPM_GPTMR2 +#define BOARD_GPTMR_PWM_DMA_SRC HPM_DMA_SRC_GPTMR1_0 +#define BOARD_GPTMR_PWM_CLK_NAME clock_gptmr1 +#define BOARD_GPTMR_PWM_IRQ IRQn_GPTMR1 +#define BOARD_GPTMR_PWM_SYNC HPM_GPTMR1 #define BOARD_GPTMR_PWM_SYNC_CHANNEL 1 -#define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr2 +#define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr1 /* pinmux section */ #define USING_GPIO0_FOR_GPIOZ #ifndef USING_GPIO0_FOR_GPIOZ #define BOARD_APP_GPIO_CTRL HPM_BGPIO -#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO #else #define BOARD_APP_GPIO_CTRL HPM_GPIO0 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z #endif /* gpiom section */ @@ -160,27 +181,24 @@ #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI1_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI1_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PB02 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) - -/* mtimer section */ -#define BOARD_MCHTMR_FREQ_IN_HZ (1000000UL) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI1_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI1_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PB02 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* ADC section */ -#define BOARD_APP_ADC16_NAME "ADC0" -#define BOARD_APP_ADC16_BASE HPM_ADC0 -#define BOARD_APP_ADC16_IRQn IRQn_ADC0 -#define BOARD_APP_ADC16_CH_1 (1U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) +#define BOARD_APP_ADC16_NAME "ADC0" +#define BOARD_APP_ADC16_BASE HPM_ADC0 +#define BOARD_APP_ADC16_IRQn IRQn_ADC0 +#define BOARD_APP_ADC16_CH_1 (8U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) #define BOARD_APP_ADC16_HW_TRIG_SRC HPM_PWM0 #define BOARD_APP_ADC16_HW_TRGM HPM_TRGM0 @@ -188,27 +206,27 @@ #define BOARD_APP_ADC16_HW_TRGM_OUT_SEQ TRGM_TRGOCFG_ADC0_STRGI #define BOARD_APP_ADC16_HW_TRGM_OUT_PMT TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* DAC section */ -#define BOARD_DAC_BASE HPM_DAC0 -#define BOARD_DAC_IRQn IRQn_DAC0 -#define BOARD_APP_DAC_CLOCK_NAME clock_dac0 +#define BOARD_DAC_BASE HPM_DAC0 +#define BOARD_DAC_IRQn IRQn_DAC0 +#define BOARD_APP_DAC_CLOCK_NAME clock_dac0 /* CAN section */ -#define BOARD_APP_CAN_BASE HPM_MCAN0 -#define BOARD_APP_CAN_IRQn IRQn_CAN0 +#define BOARD_APP_CAN_BASE HPM_MCAN0 +#define BOARD_APP_CAN_IRQn IRQn_MCAN0 /* * timer for board delay */ -#define BOARD_DELAY_TIMER (HPM_GPTMR3) -#define BOARD_DELAY_TIMER_CH 0 +#define BOARD_DELAY_TIMER (HPM_GPTMR3) +#define BOARD_DELAY_TIMER_CH 0 #define BOARD_DELAY_TIMER_CLK_NAME (clock_gptmr3) -#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr3) /* USB section */ @@ -219,255 +237,253 @@ /*BLDC pwm*/ /*PWM define*/ -#define BOARD_BLDCPWM HPM_PWM0 -#define BOARD_BLDC_UH_PWM_OUTPIN (0U) -#define BOARD_BLDC_UL_PWM_OUTPIN (1U) -#define BOARD_BLDC_VH_PWM_OUTPIN (2U) -#define BOARD_BLDC_VL_PWM_OUTPIN (3U) -#define BOARD_BLDC_WH_PWM_OUTPIN (4U) -#define BOARD_BLDC_WL_PWM_OUTPIN (5U) -#define BOARD_BLDCPWM_TRGM HPM_TRGM0 -#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM0 -#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) -#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) -#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) -#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) -#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) -#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) -#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) -#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) -#define BOARD_BLDCPWM_CMP_TRIG_CMP (15U) +#define BOARD_BLDCPWM HPM_PWM0 +#define BOARD_BLDC_UH_PWM_OUTPIN (0U) +#define BOARD_BLDC_UL_PWM_OUTPIN (1U) +#define BOARD_BLDC_VH_PWM_OUTPIN (2U) +#define BOARD_BLDC_VL_PWM_OUTPIN (3U) +#define BOARD_BLDC_WH_PWM_OUTPIN (4U) +#define BOARD_BLDC_WL_PWM_OUTPIN (5U) +#define BOARD_BLDCPWM_TRGM HPM_TRGM0 +#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM0 +#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) +#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) +#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) +#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) +#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) +#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) +#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) +#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) +#define BOARD_BLDCPWM_CMP_TRIG_CMP (15U) /*HALL define*/ -#define BOARD_BLDC_HALL_BASE HPM_HALL0 -#define BOARD_BLDC_HALL_TRGM HPM_TRGM0 -#define BOARD_BLDC_HALL_IRQ IRQn_HALL0 -#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P8 -#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P7 -#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P6 -#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) - - +#define BOARD_BLDC_HALL_BASE HPM_HALL0 +#define BOARD_BLDC_HALL_TRGM HPM_TRGM0 +#define BOARD_BLDC_HALL_IRQ IRQn_HALL0 +#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P8 +#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P7 +#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P6 +#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) /*QEI*/ -#define BOARD_BLDC_QEI_BASE HPM_QEI0 -#define BOARD_BLDC_QEI_IRQ IRQn_QEI0 -#define BOARD_BLDC_QEI_TRGM HPM_TRGM0 -#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P6 -#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P7 -#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) -#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0 -#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) +#define BOARD_BLDC_QEI_BASE HPM_QEI0 +#define BOARD_BLDC_QEI_IRQ IRQn_QEI0 +#define BOARD_BLDC_QEI_TRGM HPM_TRGM0 +#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P6 +#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P7 +#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) +#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0 +#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) /*Timer define*/ -#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 -#define BOARD_BLDC_TMR_CH 0 -#define BOARD_BLDC_TMR_CMP 0 -#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 -#define BOARD_BLDC_TMR_RELOAD (100000U) +#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 +#define BOARD_BLDC_TMR_CH 0 +#define BOARD_BLDC_TMR_CMP 0 +#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 +#define BOARD_BLDC_TMR_RELOAD (100000U) /*adc*/ -#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC16 -#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 -#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (11U) -#define BOARD_BLDC_ADC_CH_V (9U) -#define BOARD_BLDC_ADC_CH_W (4U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC16 +#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 +#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (11U) +#define BOARD_BLDC_ADC_CH_V (9U) +#define BOARD_BLDC_ADC_CH_W (4U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC16_CONFIG_TRG0A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A /*PLA*/ -#define BOARD_PLA_COUNTER HPM_PLA0 -#define BOARD_PLA_PWM_BASE HPM_PWM0 +#define BOARD_PLA_COUNTER HPM_PLA0 +#define BOARD_PLA_PWM_BASE HPM_PWM0 #define BOARD_PLA_PWM_CLOCK_NAME clock_mot0 -#define BOARD_PLA_TRGM HPM_TRGM0 -#define BOARD_PLA_PWM_TRG (HPM_TRGM0_INPUT_SRC_PWM0_CH8REF) -#define BOARD_PLA_IN_TRG_NUM (TRGM_TRGOCFG_PLA_IN0) -#define BOARD_PLA_OUT_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT0) -#define BOARD_PLA_IO_TRG_NUM (TRGM_TRGOCFG_TRGM_OUT5) -#define BOARD_PLA_PWM_CMP (8U) -#define BOARD_PLA_PWM_CHN (8U) +#define BOARD_PLA_TRGM HPM_TRGM0 +#define BOARD_PLA_PWM_TRG (HPM_TRGM0_INPUT_SRC_PWM0_CH8REF) +#define BOARD_PLA_IN_TRG_NUM (TRGM_TRGOCFG_PLA_IN0) +#define BOARD_PLA_OUT_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT0) +#define BOARD_PLA_IO_TRG_NUM (TRGM_TRGOCFG_TRGM_OUT5) +#define BOARD_PLA_PWM_CMP (8U) +#define BOARD_PLA_PWM_CHN (8U) /* APP PWM */ -#define BOARD_APP_PWM HPM_PWM0 -#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 -#define BOARD_APP_PWM_OUT1 0 -#define BOARD_APP_PWM_OUT2 1 -#define BOARD_APP_TRGM HPM_TRGM0 -#define BOARD_APP_PWM_IRQ IRQn_PWM0 +#define BOARD_APP_PWM HPM_PWM0 +#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 +#define BOARD_APP_PWM_OUT1 0 +#define BOARD_APP_PWM_OUT2 1 +#define BOARD_APP_TRGM HPM_TRGM0 +#define BOARD_APP_PWM_IRQ IRQn_PWM0 #define BOARD_APP_TRGM_PWM_OUTPUT TRGM_TRGOCFG_PWM_SYNCI /* APP HRPWM */ -#define BOARD_APP_HRPWM HPM_PWM1 +#define BOARD_APP_HRPWM HPM_PWM1 #define BOARD_APP_HRPWM_CLOCK_NAME clock_mot1 -#define BOARD_APP_HRPWM_OUT1 0 -#define BOARD_APP_HRPWM_OUT2 2 -#define BOARD_APP_HRPWM_TRGM HPM_TRGM1 +#define BOARD_APP_HRPWM_OUT1 0 +#define BOARD_APP_HRPWM_OUT2 2 +#define BOARD_APP_HRPWM_TRGM HPM_TRGM1 #define BOARD_CPU_FREQ (480000000UL) /* LED */ -#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_CTRL HPM_GPIO0 #define BOARD_R_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_R_GPIO_PIN 27 -#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_PIN 27 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 #define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_G_GPIO_PIN 1 -#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_PIN 1 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 #define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_B_GPIO_PIN 19 +#define BOARD_B_GPIO_PIN 19 -#define BOARD_LED_GPIO_CTRL BOARD_G_GPIO_CTRL +#define BOARD_LED_GPIO_CTRL BOARD_G_GPIO_CTRL #define BOARD_LED_GPIO_INDEX BOARD_G_GPIO_INDEX -#define BOARD_LED_GPIO_PIN BOARD_G_GPIO_PIN +#define BOARD_LED_GPIO_PIN BOARD_G_GPIO_PIN -#define BOARD_LED_OFF_LEVEL 0 -#define BOARD_LED_ON_LEVEL !BOARD_LED_OFF_LEVEL +#define BOARD_LED_OFF_LEVEL 0 +#define BOARD_LED_ON_LEVEL !BOARD_LED_OFF_LEVEL #define BOARD_LED_TOGGLE_RGB 1 /* Key Section */ #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ -#define BOARD_APP_GPIO_PIN 2 +#define BOARD_APP_GPIO_PIN 2 /* RGB LED Section */ -#define BOARD_RED_PWM_IRQ IRQn_PWM3 -#define BOARD_RED_PWM HPM_PWM3 -#define BOARD_RED_PWM_OUT 7 -#define BOARD_RED_PWM_CMP 8 +#define BOARD_RED_PWM_IRQ IRQn_PWM3 +#define BOARD_RED_PWM HPM_PWM3 +#define BOARD_RED_PWM_OUT 7 +#define BOARD_RED_PWM_CMP 8 #define BOARD_RED_PWM_CMP_INITIAL_ZERO true -#define BOARD_RED_PWM_CLOCK_NAME clock_mot3 +#define BOARD_RED_PWM_CLOCK_NAME clock_mot3 -#define BOARD_GREEN_PWM_IRQ IRQn_PWM1 -#define BOARD_GREEN_PWM HPM_PWM1 -#define BOARD_GREEN_PWM_OUT 1 -#define BOARD_GREEN_PWM_CMP 8 +#define BOARD_GREEN_PWM_IRQ IRQn_PWM1 +#define BOARD_GREEN_PWM HPM_PWM1 +#define BOARD_GREEN_PWM_OUT 1 +#define BOARD_GREEN_PWM_CMP 8 #define BOARD_GREEN_PWM_CMP_INITIAL_ZERO true -#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot1 +#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot1 -#define BOARD_BLUE_PWM_IRQ IRQn_PWM0 -#define BOARD_BLUE_PWM HPM_PWM0 -#define BOARD_BLUE_PWM_OUT 7 -#define BOARD_BLUE_PWM_CMP 8 +#define BOARD_BLUE_PWM_IRQ IRQn_PWM0 +#define BOARD_BLUE_PWM HPM_PWM0 +#define BOARD_BLUE_PWM_OUT 7 +#define BOARD_BLUE_PWM_CMP 8 #define BOARD_BLUE_PWM_CMP_INITIAL_ZERO true -#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot0 +#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot0 -#define BOARD_RGB_RED 0 +#define BOARD_RGB_RED 0 #define BOARD_RGB_GREEN (BOARD_RGB_RED + 1) #define BOARD_RGB_BLUE (BOARD_RGB_RED + 2) /* PLA TAMAGAWA*/ -#define PLA_TMGW_SPI HPM_SPI2 -#define PLA_TMGW_SPI_DMA BOARD_APP_HDMA -#define PLA_TMGW_SPI_DMAMUX BOARD_APP_DMAMUX -#define PLA_TMGW_SPI_RX_DMA_REQ HPM_DMA_SRC_SPI2_RX -#define PLA_TMGW_SPI_TX_DMA_REQ HPM_DMA_SRC_SPI2_TX -#define PLA_TMGW_SPI_RX_DMA_CH 0 -#define PLA_TMGW_SPI_TX_DMA_CH 1 -#define PLA_TMGW_SPI_RX_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_SPI_DMA, PLA_TMGW_SPI_RX_DMA_CH) -#define PLA_TMGW_SPI_TX_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_SPI_DMA, PLA_TMGW_SPI_TX_DMA_CH) - -#define PLA_TMGW_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define PLA_TMGW_SPI_CS_GPIO_INDEX GPIO_DI_GPIOB +#define PLA_TMGW_SPI HPM_SPI2 +#define PLA_TMGW_SPI_DMA BOARD_APP_HDMA +#define PLA_TMGW_SPI_DMAMUX BOARD_APP_DMAMUX +#define PLA_TMGW_SPI_RX_DMA_REQ HPM_DMA_SRC_SPI2_RX +#define PLA_TMGW_SPI_TX_DMA_REQ HPM_DMA_SRC_SPI2_TX +#define PLA_TMGW_SPI_RX_DMA_CH 0 +#define PLA_TMGW_SPI_TX_DMA_CH 1 +#define PLA_TMGW_SPI_RX_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_SPI_DMA, PLA_TMGW_SPI_RX_DMA_CH) +#define PLA_TMGW_SPI_TX_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_SPI_DMA, PLA_TMGW_SPI_TX_DMA_CH) + +#define PLA_TMGW_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define PLA_TMGW_SPI_CS_GPIO_INDEX GPIO_DI_GPIOB #define PLA_TMGW_SPI_CS_GPIO_PIN 30 -#define PLA_TMGW_DATA_DIR_GPIO_CTRL HPM_GPIO0 -#define PLA_TMGW_DATA_DIR_GPIO_INDEX GPIO_DI_GPIOB +#define PLA_TMGW_DATA_DIR_GPIO_CTRL HPM_GPIO0 +#define PLA_TMGW_DATA_DIR_GPIO_INDEX GPIO_DI_GPIOB #define PLA_TMGW_DATA_DIR_GPIO_PIN 21 -#define PLA_TMGW_POWER_GPIO_CTRL HPM_GPIO0 -#define PLA_TMGW_POWER_GPIO_INDEX GPIO_DI_GPIOB +#define PLA_TMGW_POWER_GPIO_CTRL HPM_GPIO0 +#define PLA_TMGW_POWER_GPIO_INDEX GPIO_DI_GPIOB #define PLA_TMGW_POWER_GPIO_PIN 31 -#define PLA_TMGW_SPI_485_DIR_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT1) -#define PLA_TMGW_SPI_485_DIR_TRGNUM (TRGM_TRGOCFG_TRGM_OUT1) -#define PLA_TMGW_SPI_MOSI_DATA_TRG (HPM_TRGM0_INPUT_SRC_TRGM0_P3) -#define PLA_TMGW_SPI_MOSI_DATA_TRGNUM (TRGM_TRGOCFG_PLA_IN3) - -#define PLA_TMGW_SPI_CS_TRG (TEST_MOTOR_PWM_TRG_PLA_TRG) -#define PLA_TMGW_SPI_CS_TRGNUM (TRGM_TRGOCFG_TRGM_OUT0) - -#define PLA_TMGW_COUNTER HPM_PLA0 -#define PLA_TMGW_PWM_BASE HPM_PWM3 -#define PLA_TMGW_PWM_CLOCK_NAME clock_mot3 -#define PLA_TMGW_TRGM_CLK_IN_TRG (HPM_TRGM0_INPUT_SRC_TRGM3_OUTX0) -#define PLA_TMGW_TRGM_CLK_To_PLA_TRGNUM (TRGM_TRGOCFG_PLA_IN0) -#define PLA_TMGW_TRGM (HPM_TRGM0) -#define PLA_TMGW_CLK_TRGM (HPM_TRGM3) -#define PLA_TMGW_CLK_PWM_TRG (HPM_TRGM3_INPUT_SRC_PWM3_CH15REF) -#define PLA_TMGW_CLK_TRG_NUM (TRGM_TRGOCFG_TRGM_OUTX0) -#define PLA_TMGW_OUT_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT0) -#define PLA_TMGW_IO_TRG_NUM (TRGM_TRGOCFG_TRGM_OUT5) -#define PLA_TMGW_PWM_CMP (15U) -#define PLA_TMGW_PWM_CHN (15U) -#define PLA_TMGW_PWM_SYNCI_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT2) -#define PLA_TMGW_PWM_SYNCI_TRGNUM (TRGM_TRGOCFG_TRGM_OUTX0) -#define PLA_TMGW_PWM_SYNCI_IN_TRG (HPM_TRGM3_INPUT_SRC_TRGM0_OUTX0) -#define PLA_TMGW_PWM_SYNCI_IN_TRGNUM (TRGM_TRGOCFG_PWM_SYNCI) - -#define PLA_TMGW_HALL_TIME_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT2) - -#define PLA_TMGW_IN_MOTOR_TRG_NUM (TRGM_TRGOCFG_PLA_IN2) - -#define PLA_TMGW_QEI_BASE HPM_QEI0 -#define PLA_TMGW_QEI_TRGM HPM_TRGM0 -#define PLA_TMGW_QEI_TRGM_QEI_A_SRC HPM_TRGM0_INPUT_SRC_PLA0_OUT0 -#define PLA_TMGW_QEI_IRQ IRQn_QEI0 -#define PLA_TMGW_QEI_MOTOR_PHASE_COUNT_MAX (0xffffff) - -#define PLA_TMGW_QEI_TRGM_QEI_TRG0 HPM_TRGM0_INPUT_SRC_QEI0_TRGO -#define PLA_TMGW_QEI_TRGM_QEI_PLA_IN TRGM_TRGOCFG_PLA_IN1 - -#define PLA_TMGW_QEI_DMA BOARD_APP_HDMA -#define PLA_TMGW_QEI_DMAMUX BOARD_APP_DMAMUX -#define PLA_TMGW_QEI_DMAREQ HPM_DMA_SRC_MOT0_0 -#define PLA_TMGW_QEI_DMACH (2UL) -#define PLA_TMGW_QEI_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_QEI_DMA, PLA_TMGW_QEI_DMACH) - -#define PLA_TMGW_HALL_BASE HPM_HALL0 -#define PLA_TMGW_HALL_TRGM HPM_TRGM0 -#define PLA_TMGW_HALL_DMA BOARD_APP_HDMA -#define PLA_TMGW_HALL_DMAMUX BOARD_APP_DMAMUX -#define PLA_TMGW_HALL_DMA_CH (3U) -#define PLA_TMGW_HALL_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_HALL_DMA, PLA_TMGW_HALL_DMA_CH) -#define PLA_TMGW_HALL_TRAN_SIZE (4U) /* four world */ -#define PLA_TMGW_HALL_DMA_REQ HPM_DMA_SRC_MOT0_1 - -#define PLA_TMGW_DMA_LINK_NUM (25U) -#define PLA_TMGW_DMA_LINK_TRGM HPM_TRGM0 -#define PLA_TMGW_DMA_LINK_DMA BOARD_APP_HDMA -#define PLA_TMGW_DMA_LINK_DMAMUX BOARD_APP_DMAMUX -#define PLA_TMGW_DMA_LINK_DMA_CH (4U) -#define PLA_TMGW_DMA_LINK_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_DMA_LINK_DMA, PLA_TMGW_DMA_LINK_DMA_CH) -#define PLA_TMGW_DMA_LINK_TRAN_SIZE (4U) -#define PLA_TMGW_DMA_LINK_DMA_REQ HPM_DMA_SRC_MOT0_2 -#define PLA_TMGW_DMA_LINK_TRGM_INPUT HPM_TRGM0_INPUT_SRC_PLA0_OUT6 +#define PLA_TMGW_SPI_485_DIR_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT1) +#define PLA_TMGW_SPI_485_DIR_TRGNUM (TRGM_TRGOCFG_TRGM_OUT1) +#define PLA_TMGW_SPI_MOSI_DATA_TRG (HPM_TRGM0_INPUT_SRC_TRGM0_P3) +#define PLA_TMGW_SPI_MOSI_DATA_TRGNUM (TRGM_TRGOCFG_PLA_IN3) + +#define PLA_TMGW_SPI_CS_TRG (TEST_MOTOR_PWM_TRG_PLA_TRG) +#define PLA_TMGW_SPI_CS_TRGNUM (TRGM_TRGOCFG_TRGM_OUT0) + +#define PLA_TMGW_COUNTER HPM_PLA0 +#define PLA_TMGW_PWM_BASE HPM_PWM3 +#define PLA_TMGW_PWM_CLOCK_NAME clock_mot3 +#define PLA_TMGW_TRGM_CLK_IN_TRG (HPM_TRGM0_INPUT_SRC_TRGM3_OUTX0) +#define PLA_TMGW_TRGM_CLK_To_PLA_TRGNUM (TRGM_TRGOCFG_PLA_IN0) +#define PLA_TMGW_TRGM (HPM_TRGM0) +#define PLA_TMGW_CLK_TRGM (HPM_TRGM3) +#define PLA_TMGW_CLK_PWM_TRG (HPM_TRGM3_INPUT_SRC_PWM3_CH15REF) +#define PLA_TMGW_CLK_TRG_NUM (TRGM_TRGOCFG_TRGM_OUTX0) +#define PLA_TMGW_OUT_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT0) +#define PLA_TMGW_IO_TRG_NUM (TRGM_TRGOCFG_TRGM_OUT5) +#define PLA_TMGW_PWM_CMP (15U) +#define PLA_TMGW_PWM_CHN (15U) +#define PLA_TMGW_PWM_SYNCI_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT2) +#define PLA_TMGW_PWM_SYNCI_TRGNUM (TRGM_TRGOCFG_TRGM_OUTX0) +#define PLA_TMGW_PWM_SYNCI_IN_TRG (HPM_TRGM3_INPUT_SRC_TRGM0_OUTX0) +#define PLA_TMGW_PWM_SYNCI_IN_TRGNUM (TRGM_TRGOCFG_PWM_SYNCI) + +#define PLA_TMGW_HALL_TIME_TRG (HPM_TRGM0_INPUT_SRC_PLA0_OUT2) + +#define PLA_TMGW_IN_MOTOR_TRG_NUM (TRGM_TRGOCFG_PLA_IN2) + +#define PLA_TMGW_QEI_BASE HPM_QEI0 +#define PLA_TMGW_QEI_TRGM HPM_TRGM0 +#define PLA_TMGW_QEI_TRGM_QEI_A_SRC HPM_TRGM0_INPUT_SRC_PLA0_OUT0 +#define PLA_TMGW_QEI_IRQ IRQn_QEI0 +#define PLA_TMGW_QEI_MOTOR_PHASE_COUNT_MAX (0xffffff) + +#define PLA_TMGW_QEI_TRGM_QEI_TRG0 HPM_TRGM0_INPUT_SRC_QEI0_TRGO +#define PLA_TMGW_QEI_TRGM_QEI_PLA_IN TRGM_TRGOCFG_PLA_IN1 + +#define PLA_TMGW_QEI_DMA BOARD_APP_HDMA +#define PLA_TMGW_QEI_DMAMUX BOARD_APP_DMAMUX +#define PLA_TMGW_QEI_DMAREQ HPM_DMA_SRC_MOT0_0 +#define PLA_TMGW_QEI_DMACH (2UL) +#define PLA_TMGW_QEI_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_QEI_DMA, PLA_TMGW_QEI_DMACH) + +#define PLA_TMGW_HALL_BASE HPM_HALL0 +#define PLA_TMGW_HALL_TRGM HPM_TRGM0 +#define PLA_TMGW_HALL_DMA BOARD_APP_HDMA +#define PLA_TMGW_HALL_DMAMUX BOARD_APP_DMAMUX +#define PLA_TMGW_HALL_DMA_CH (3U) +#define PLA_TMGW_HALL_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_HALL_DMA, PLA_TMGW_HALL_DMA_CH) +#define PLA_TMGW_HALL_TRAN_SIZE (4U) /* four world */ +#define PLA_TMGW_HALL_DMA_REQ HPM_DMA_SRC_MOT0_1 + +#define PLA_TMGW_DMA_LINK_NUM (25U) +#define PLA_TMGW_DMA_LINK_TRGM HPM_TRGM0 +#define PLA_TMGW_DMA_LINK_DMA BOARD_APP_HDMA +#define PLA_TMGW_DMA_LINK_DMAMUX BOARD_APP_DMAMUX +#define PLA_TMGW_DMA_LINK_DMA_CH (4U) +#define PLA_TMGW_DMA_LINK_DMAMUX_CH DMA_SOC_CHN_TO_DMAMUX_CHN(PLA_TMGW_DMA_LINK_DMA, PLA_TMGW_DMA_LINK_DMA_CH) +#define PLA_TMGW_DMA_LINK_TRAN_SIZE (4U) +#define PLA_TMGW_DMA_LINK_DMA_REQ HPM_DMA_SRC_MOT0_2 +#define PLA_TMGW_DMA_LINK_TRGM_INPUT HPM_TRGM0_INPUT_SRC_PLA0_OUT6 /** * @brief Get adc phase current * */ -#define BOARD_BLDC_ADC_PHASE_CH_U (3U) -#define BOARD_BLDC_ADC_PHASE_CH_V (4U) -#define BOARD_BLDC_ADC_PHASE_CH_W (2U) -#define BOARD_BLDC_ADC_PHASE_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_PHASE_V_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_PHASE_W_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_PHASE_TRG ADC16_CONFIG_TRG0A -#define BOARD_BLDC_ADC_PHASE_PREEMPT_TRIG_LEN (3) -#define BOARD_BLDC_ADC_PHASE_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PHASE_TRIG_FLAG adc16_event_trig_complete +#define BOARD_BLDC_ADC_PHASE_CH_U (3U) +#define BOARD_BLDC_ADC_PHASE_CH_V (4U) +#define BOARD_BLDC_ADC_PHASE_CH_W (2U) +#define BOARD_BLDC_ADC_PHASE_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_PHASE_V_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_PHASE_W_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_PHASE_TRG ADC16_CONFIG_TRG0A +#define BOARD_BLDC_ADC_PHASE_PREEMPT_TRIG_LEN (3) +#define BOARD_BLDC_ADC_PHASE_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PHASE_TRIG_FLAG adc16_event_trig_complete #ifndef BOARD_SHOW_CLOCK #define BOARD_SHOW_CLOCK 1 @@ -477,10 +493,19 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR1 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR1 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr1 +#define BOARD_FREERTOS_TIMER HPM_GPTMR1 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR1 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr1 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR1 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR1 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr1 +/* Tamper Section */ +#define BOARD_TAMP_ACTIVE_CH 4 +#define BOARD_TAMP_LOW_LEVEL_CH 6 #if defined(__cplusplus) extern "C" { @@ -491,6 +516,8 @@ typedef void (*board_timer_cb)(void); void board_init(void); void board_init_console(void); +void board_init_core1(void); + void board_init_uart(UART_Type *ptr); void board_init_i2c(I2C_Type *ptr); @@ -532,7 +559,6 @@ void board_init_usb_pins(void); void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level); uint8_t board_get_usb_id_status(void); - /* * @brief Initialize PMP and PMA for but not limited to the following purposes: * -- non-cacheable memory initialization diff --git a/boards/hpm6200evk/hpm6200evk.yaml b/boards/hpm6200evk/hpm6200evk.yaml index 2503bea0b..8d445acf1 100644 --- a/boards/hpm6200evk/hpm6200evk.yaml +++ b/boards/hpm6200evk/hpm6200evk.yaml @@ -11,41 +11,8 @@ board: type: qspi-nor-flash size: 16M feature: - - butn - - sdp - - rng - - rtc - - wdg - - lin - - sdm - - adc16 - - usb-otg - - spi - - uart - - mcan - - i2c - - dual-i2c - - gpio - - gpio-led - - gpio-key - - gpiom - - pwm - - hall - - qei - - motor-control - - multicore - - tsns - - dac - - ptp - - uart_hardware_rx_idle - - hrpwm - - pla - - pwm-rgb-led - - crc - - motor-phase-voltage - - bldc_smc - - bldc_hfi - - puart - - gpt_pin - - acmp - - ptpc + - board_pwm_rgb_led + - board_gpt_pin + - board_motor_control + - board_motor_control_phase_voltage_sampling + - board_puart_pin diff --git a/boards/hpm6200evk/pinmux.c b/boards/hpm6200evk/pinmux.c index 5de605b1f..7947e3bc4 100644 --- a/boards/hpm6200evk/pinmux.c +++ b/boards/hpm6200evk/pinmux.c @@ -20,8 +20,8 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_SOC_GPIO_Y_07; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_SOC_GPIO_Y_06; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_GPIO_Y_07; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_GPIO_Y_06; } else if (ptr == HPM_UART1) { HPM_IOC->PAD[IOC_PAD_PC24].FUNC_CTL = IOC_PC24_FUNC_CTL_UART1_TXD; HPM_IOC->PAD[IOC_PAD_PC25].FUNC_CTL = IOC_PC25_FUNC_CTL_UART1_RXD; @@ -29,8 +29,22 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PC26].FUNC_CTL = IOC_PC26_FUNC_CTL_UART2_TXD; HPM_IOC->PAD[IOC_PAD_PC27].FUNC_CTL = IOC_PC27_FUNC_CTL_UART2_RXD; } else if (ptr == HPM_PUART) { - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART_RXD; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART_TXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_UART_RXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_UART_TXD; + } +} + +/* for uart_lin case, need to configure pin as gpio to sent break signal */ +void init_uart_pin_as_gpio(UART_Type *ptr) +{ + /* pull-up */ + uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); + + if (ptr == HPM_UART2) { + HPM_IOC->PAD[IOC_PAD_PC26].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PC27].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PC26].FUNC_CTL = IOC_PC26_FUNC_CTL_GPIO_C_26; + HPM_IOC->PAD[IOC_PAD_PC27].FUNC_CTL = IOC_PC27_FUNC_CTL_GPIO_C_27; } } @@ -40,6 +54,10 @@ void init_i2c_pins_as_gpio(I2C_Type *ptr) /* I2C0 */ HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_GPIO_B_22; HPM_IOC->PAD[IOC_PAD_PB23].FUNC_CTL = IOC_PB23_FUNC_CTL_GPIO_B_23; + } else if (ptr == HPM_I2C3) { + /* I2C3 */ + HPM_IOC->PAD[IOC_PAD_PB20].FUNC_CTL = IOC_PB20_FUNC_CTL_GPIO_B_20; + HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_GPIO_B_21; } else { while (1) { } @@ -56,12 +74,12 @@ void init_i2c_pins(I2C_Type *ptr) HPM_IOC->PAD[IOC_PAD_PB22].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); HPM_IOC->PAD[IOC_PAD_PB23].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); } else if (ptr == HPM_I2C3) { - HPM_IOC->PAD[IOC_PAD_PC11].FUNC_CTL = IOC_PC11_FUNC_CTL_I2C3_SCL + HPM_IOC->PAD[IOC_PAD_PB20].FUNC_CTL = IOC_PB20_FUNC_CTL_I2C3_SCL | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; - HPM_IOC->PAD[IOC_PAD_PC12].FUNC_CTL = IOC_PC12_FUNC_CTL_I2C3_SDA + HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_I2C3_SDA | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; - HPM_IOC->PAD[IOC_PAD_PC11].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); - HPM_IOC->PAD[IOC_PAD_PC12].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); + HPM_IOC->PAD[IOC_PAD_PB20].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); + HPM_IOC->PAD[IOC_PAD_PB21].PAD_CTL = IOC_PAD_PAD_CTL_OD_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); } else { while (1) { } @@ -86,7 +104,7 @@ void init_gpio_pins(void) HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = pad_ctl; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_SOC_GPIO_Z_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_GPIO_Z_02; #endif } @@ -112,17 +130,17 @@ void init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) void init_pins(void) { -#ifdef BOARD_CONSOLE_BASE - init_uart_pins(BOARD_CONSOLE_BASE); +#ifdef BOARD_CONSOLE_UART_BASE + init_uart_pins(BOARD_CONSOLE_UART_BASE); #endif } void init_gptmr_pins(GPTMR_Type *ptr) { - if (ptr == HPM_GPTMR2) { - HPM_IOC->PAD[IOC_PAD_PC06].FUNC_CTL = IOC_PC06_FUNC_CTL_GPTMR2_CAPT_0; - HPM_IOC->PAD[IOC_PAD_PC08].FUNC_CTL = IOC_PC08_FUNC_CTL_GPTMR2_COMP_0; - HPM_IOC->PAD[IOC_PAD_PC09].FUNC_CTL = IOC_PC09_FUNC_CTL_GPTMR2_COMP_1; + if (ptr == HPM_GPTMR1) { + HPM_IOC->PAD[IOC_PAD_PA23].FUNC_CTL = IOC_PA23_FUNC_CTL_GPTMR1_CAPT_0; + HPM_IOC->PAD[IOC_PAD_PA25].FUNC_CTL = IOC_PA25_FUNC_CTL_GPTMR1_COMP_0; + HPM_IOC->PAD[IOC_PAD_PA26].FUNC_CTL = IOC_PA26_FUNC_CTL_GPTMR1_COMP_1; } } @@ -175,10 +193,8 @@ void init_hrpwm_pins(PWM_Type *ptr) void init_adc_pins(void) { - HPM_IOC->PAD[IOC_PAD_PC05].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_BUS:ADC0.INA1 */ - HPM_IOC->PAD[IOC_PAD_PC16].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_IW: ADC0.INA12/ADC1.INA8/ADC2.INA4 */ - HPM_IOC->PAD[IOC_PAD_PC17].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_IV: ADC0.INA13/ADC1.INA9/ADC2.INA5 */ - HPM_IOC->PAD[IOC_PAD_PC15].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; /* ADC_IU: ADC0.INA11/ADC1.INA7.ADC2.INA3 */ + /* ADC0.INA8 */ + HPM_IOC->PAD[IOC_PAD_PC12].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; } void init_adc_bldc_pins(void) @@ -197,9 +213,9 @@ void init_usb_pins(void) void init_can_pins(MCAN_Type *ptr) { if (ptr == HPM_MCAN0) { - HPM_IOC->PAD[IOC_PAD_PB19].FUNC_CTL = IOC_PB19_FUNC_CTL_CAN0_STBY | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; - HPM_IOC->PAD[IOC_PAD_PB20].FUNC_CTL = IOC_PB20_FUNC_CTL_CAN0_TXD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; - HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_CAN0_RXD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PB19].FUNC_CTL = IOC_PB19_FUNC_CTL_MCAN0_STBY | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PB20].FUNC_CTL = IOC_PB20_FUNC_CTL_MCAN0_TXD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_MCAN0_RXD | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; HPM_IOC->PAD[IOC_PAD_PB19].PAD_CTL = IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1); HPM_IOC->PAD[IOC_PAD_PB20].PAD_CTL = IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1); @@ -288,3 +304,13 @@ void init_led_pins_as_pwm(void) /* Red */ HPM_IOC->PAD[IOC_PAD_PA27].FUNC_CTL = IOC_PA27_FUNC_CTL_PWM3_P_07; } + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_BATT_TAMPER_04 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_BATT_TAMPER_05; + HPM_BIOC->PAD[IOC_PAD_PZ06].FUNC_CTL = BIOC_PZ06_FUNC_CTL_BATT_TAMPER_06; + + HPM_BIOC->PAD[IOC_PAD_PZ04].PAD_CTL &= ~IOC_PAD_PAD_CTL_OD_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ05].PAD_CTL &= ~IOC_PAD_PAD_CTL_OD_MASK; +} diff --git a/boards/hpm6200evk/pinmux.h b/boards/hpm6200evk/pinmux.h index 129dcec9c..bc6a5613a 100644 --- a/boards/hpm6200evk/pinmux.h +++ b/boards/hpm6200evk/pinmux.h @@ -12,6 +12,7 @@ extern "C" { #endif void init_uart_pins(UART_Type *ptr); +void init_uart_pin_as_gpio(UART_Type *ptr); void init_i2c_pins(I2C_Type *ptr); void init_gpio_pins(void); void init_spi_pins(SPI_Type *ptr); @@ -39,6 +40,8 @@ void init_lin_pins(LIN_Type *ptr); void init_sdm_pins(void); void init_pla_tamagawa_pins(void); void init_motor_over_zero_sensorless_adc_pins(void); +void init_tamper_pins(void); + #ifdef __cplusplus } #endif diff --git a/boards/hpm6300evk/README_en.md b/boards/hpm6300evk/README_en.md index 0bb2d8a18..750888a06 100644 --- a/boards/hpm6300evk/README_en.md +++ b/boards/hpm6300evk/README_en.md @@ -95,17 +95,17 @@ Plug-in - ADC16 Pin -| Function | Position | -| ------------------------------ | -------- | -| ADC16 Reference Voltage | J108[2] | -| ADC0.INA13/ADC1.INA9/ADC2.INA5 | J26[6] | - -- DAC Pin - | Function | Position | | ----------------------- | -------- | | ADC16 Reference Voltage | J108[2] | -| DAC0.OUT | J26[11] | +| ADC0.INA6 | J28[38] | + +- DAC Pin + +| Function | Position | +| --------------------- | -------- | +| DAC Reference Voltage | J108[2] | +| DAC0.OUT | J26[11] | - PWM Pin @@ -121,7 +121,9 @@ Plug-in | ENET0.EVTO0 | J28[19] | | ENET0.EVTO1 | J28[23] | -- UART pin for uart_software_rx_idle sample or uart_rx_timeout sample +- UART pin + + The UART2 is used for some functional testing using UART, such as uart_software_rx_idle, uart_rx_timeout, uart_software_lin, MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. | Function | Position | | --------- | -------- | @@ -137,3 +139,10 @@ Plug-in - Motor Pin: Refer to section [DRV-LV50A-MP1907 Motor Driver Board ](lab_drv_lv50a_mp1907) for configuration + +- Tamper Pin + +| Function | Pin | Position | Mode | +|----------|--------|--------|----------| +| TAMP.06 | PZ06 | J28[8] | Active Mode | +| TAMP.07 | PZ07 | J28[10]| Active Mode | diff --git a/boards/hpm6300evk/README_zh.md b/boards/hpm6300evk/README_zh.md index 3869563aa..b871ff7b1 100644 --- a/boards/hpm6300evk/README_zh.md +++ b/boards/hpm6300evk/README_zh.md @@ -95,10 +95,10 @@ HPM6300EVK提供了HPM6300微控制器大部分外设的接口,包括1个SD卡 - ADC16引脚 -| 功能 | 位置 | -| ------------------------------ | ------- | -| ADC16参考电压 | J108[2] | -| ADC0.INA13/ADC1.INA9/ADC2.INA5 | J26[6] | +| 功能 | 位置 | +| ------------- | ------- | +| ADC16参考电压 | J108[2] | +| ADC0.INA6 | J28[38] | - DAC引脚 @@ -120,7 +120,9 @@ HPM6300EVK提供了HPM6300微控制器大部分外设的接口,包括1个SD卡 | ENET0.EVTO0 | J28[19] | | ENET0.EVTO1 | J28[23] | -- UART引脚用于uart_software_rx_idle或uart_rx_timeout或uart_lin工程 +- UART引脚 + + UART2用于一些使用UART的功能测试,例如uart_software_rx_idle,uart_rx_timeout,uart_software_lin,MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 | 功能 | 位置 | | --------- | ------- | @@ -136,3 +138,10 @@ HPM6300EVK提供了HPM6300微控制器大部分外设的接口,包括1个SD卡 - 电机引脚 参考 [DRV-LV50A-MP1907 电机驱动板章节](lab_drv_lv50a_mp1907) 进行连接 + +- Tamper 接口 + +| 功能 | 引脚 | 位置 | 模式 | +|----------|--------|--------|---------| +| TAMP.06 | PZ06 | J28[8] | 主动模式 | +| TAMP.07 | PZ07 | J28[10]| 主动模式 | diff --git a/boards/hpm6300evk/board.c b/boards/hpm6300evk/board.c index ae2b66f64..650281697 100644 --- a/boards/hpm6300evk/board.c +++ b/boards/hpm6300evk/board.c @@ -95,16 +95,16 @@ void board_init_console(void) /* uart needs to configure pin function before enabling clock, otherwise the level change of uart rx pin when configuring pin function will cause a wrong data to be received. And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t) BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t) BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -635,6 +635,7 @@ void _init_ext_ram(void) sdram_config.refresh_count = BOARD_SDRAM_REFRESH_COUNT; sdram_config.refresh_in_ms = BOARD_SDRAM_REFRESH_IN_MS; sdram_config.data_width_in_byte = BOARD_SDRAM_DATA_WIDTH_IN_BYTE; + sdram_config.delay_cell_disable = false; sdram_config.delay_cell_value = 29; femc_config_sdram(HPM_FEMC, femc_clk_in_hz, &sdram_config); diff --git a/boards/hpm6300evk/board.h b/boards/hpm6300evk/board.h index 5a879fad9..e8badd366 100644 --- a/boards/hpm6300evk/board.h +++ b/boards/hpm6300evk/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 HPMicro + * Copyright (c) 2022-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -17,33 +17,29 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm6300evk" +#define BOARD_NAME "hpm6300evk" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart +#define BOARD_APP_UART_BASE HPM_UART2 +#define BOARD_APP_UART_IRQ IRQn_UART2 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart2 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART2_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART2_TX #endif -#endif - -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -51,94 +47,110 @@ #endif #if CONSOLE_TYPE_UART == BOARD_CONSOLE_TYPE -#ifndef BOARD_CONSOLE_BASE +#ifndef BOARD_CONSOLE_UART_BASE #if BOARD_RUNNING_CORE == HPM_CORE0 -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #else -#define BOARD_CONSOLE_BASE HPM_UART13 -#define BOARD_CONSOLE_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_BASE HPM_UART13 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART13 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX #endif #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif -#define BOARD_FREEMASTER_UART_BASE HPM_UART0 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART0 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart0 - /* uart rx idle demo section */ -#define BOARD_UART_IDLE HPM_UART2 -#define BOARD_UART_IDLE_IRQ IRQn_UART2 -#define BOARD_UART_IDLE_CLK_NAME clock_uart2 -#define BOARD_UART_IDLE_TX_DMA_SRC HPM_DMA_SRC_UART2_TX -#define BOARD_UART_IDLE_DMA_SRC HPM_DMA_SRC_UART2_RX - -#define BOARD_UART_IDLE_TRGM HPM_TRGM1 -#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PA24 -#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM1_INPUT_SRC_TRGM1_P4 -#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM1_OUTPUT_SRC_GPTMR2_IN2 +#define BOARD_UART_IDLE BOARD_APP_UART_BASE +#define BOARD_UART_IDLE_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_IDLE_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_IDLE_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_UART_IDLE_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +#define BOARD_UART_IDLE_TRGM HPM_TRGM1 +#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PA24 +#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM1_INPUT_SRC_TRGM1_P4 +#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM1_OUTPUT_SRC_GPTMR2_IN2 #define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_SYNCI HPM_TRGM1_OUTPUT_SRC_GPTMR2_SYNCI -#define BOARD_UART_IDLE_GPTMR HPM_GPTMR2 +#define BOARD_UART_IDLE_GPTMR HPM_GPTMR2 #define BOARD_UART_IDLE_GPTMR_CLK_NAME clock_gptmr2 -#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR2 -#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 -#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 +#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR2 +#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 +#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 /* uart lin sample section */ -#define BOARD_UART_LIN HPM_UART2 -#define BOARD_UART_LIN_IRQ IRQn_UART2 -#define BOARD_UART_LIN_CLK_NAME clock_uart2 -#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOC -#define BOARD_UART_LIN_TX_PIN (26U) /* PC26 should align with used pin in pinmux configuration */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOC +#define BOARD_UART_LIN_TX_PIN (26U) /* PC26 should align with used pin in pinmux configuration */ /* uart microros sample section */ -#define BOARD_MICROROS_UART_BASE HPM_UART2 -#define BOARD_MICROROS_UART_IRQ IRQn_UART2 -#define BOARD_MICROROS_UART_CLK_NAME clock_uart2 +#define BOARD_MICROROS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MICROROS_UART_IRQ BOARD_APP_UART_IRQ +#define BOARD_MICROROS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME + +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ /* sdram section */ -#define BOARD_SDRAM_ADDRESS (0x40000000UL) -#define BOARD_SDRAM_SIZE (32*SIZE_1MB) -#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 -#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_16_BITS -#define BOARD_SDRAM_REFRESH_COUNT (8192UL) -#define BOARD_SDRAM_REFRESH_IN_MS (64UL) +#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_SIZE (32 * SIZE_1MB) +#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 +#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_16_BITS +#define BOARD_SDRAM_REFRESH_COUNT (8192UL) +#define BOARD_SDRAM_REFRESH_IN_MS (64UL) #define BOARD_SDRAM_DATA_WIDTH_IN_BYTE (4UL) - /* nor flash section */ #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) -#define BOARD_FLASH_SIZE (16 * SIZE_1MB) +#define BOARD_FLASH_SIZE (16 * SIZE_1MB) /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 -#define BOARD_APP_I2C_CLK_NAME clock_i2c0 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 -#define BOARD_I2C_GPIO_CTRL HPM_GPIO0 -#define BOARD_I2C_SCL_GPIO_INDEX GPIO_DO_GPIOC -#define BOARD_I2C_SCL_GPIO_PIN 13 -#define BOARD_I2C_SDA_GPIO_INDEX GPIO_DO_GPIOC -#define BOARD_I2C_SDA_GPIO_PIN 14 +#define BOARD_APP_I2C_BASE HPM_I2C0 +#define BOARD_APP_I2C_IRQ IRQn_I2C0 +#define BOARD_APP_I2C_CLK_NAME clock_i2c0 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 +#define BOARD_I2C_GPIO_CTRL HPM_GPIO0 +#define BOARD_I2C_SCL_GPIO_INDEX GPIO_DO_GPIOC +#define BOARD_I2C_SCL_GPIO_PIN 13 +#define BOARD_I2C_SDA_GPIO_INDEX GPIO_DO_GPIOC +#define BOARD_I2C_SDA_GPIO_PIN 14 /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_5 /* align with used pin */ /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX /* gptmr section */ #define BOARD_GPTMR HPM_GPTMR2 @@ -157,16 +169,16 @@ /* gpio section */ #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ -#define BOARD_APP_GPIO_PIN 2 +#define BOARD_APP_GPIO_PIN 2 /* pinmux section */ #define USING_GPIO0_FOR_GPIOZ #ifndef USING_GPIO0_FOR_GPIOZ #define BOARD_APP_GPIO_CTRL HPM_BGPIO -#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO #else #define BOARD_APP_GPIO_CTRL HPM_GPIO0 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z #endif /* gpiom section */ @@ -175,51 +187,51 @@ #define BOARD_APP_GPIOM_USING_CTRL_NAME gpiom_core0_fast /* spi section */ -#define BOARD_APP_SPI_BASE HPM_SPI3 +#define BOARD_APP_SPI_BASE HPM_SPI3 #define BOARD_APP_SPI_CLK_NAME clock_spi3 #define BOARD_APP_SPI_IRQ IRQn_SPI3 #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI3_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI3_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PC18 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI3_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI3_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PC18 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* i2s section */ -#define BOARD_APP_I2S_BASE HPM_I2S0 +#define BOARD_APP_I2S_BASE HPM_I2S0 #define BOARD_APP_I2S_DATA_LINE (2U) -#define BOARD_APP_I2S_CLK_NAME clock_i2s0 -#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll2_clk0 +#define BOARD_APP_I2S_CLK_NAME clock_i2s0 +#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll2_clk0 #define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll2clk0 /* enet section */ -#define BOARD_ENET_PPS HPM_ENET0 -#define BOARD_ENET_PPS_IDX enet_pps_0 -#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 +#define BOARD_ENET_PPS HPM_ENET0 +#define BOARD_ENET_PPS_IDX enet_pps_0 +#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 -#define BOARD_ENET_RMII HPM_ENET0 +#define BOARD_ENET_RMII HPM_ENET0 #define BOARD_ENET_RMII_RST_GPIO #define BOARD_ENET_RMII_RST_GPIO_INDEX #define BOARD_ENET_RMII_RST_GPIO_PIN -#define BOARD_ENET_RMII HPM_ENET0 -#define BOARD_ENET_RMII_INT_REF_CLK (1U) -#define BOARD_ENET_RMII_PTP_CLOCK (clock_ptp0) -#define BOARD_ENET_RMII_PPS0_PINOUT (1) +#define BOARD_ENET_RMII HPM_ENET0 +#define BOARD_ENET_RMII_INT_REF_CLK (1U) +#define BOARD_ENET_RMII_PTP_CLOCK (clock_ptp0) +#define BOARD_ENET_RMII_PPS0_PINOUT (1) /* ADC section */ -#define BOARD_APP_ADC16_NAME "ADC0" -#define BOARD_APP_ADC16_BASE HPM_ADC0 -#define BOARD_APP_ADC16_IRQn IRQn_ADC0 -#define BOARD_APP_ADC16_CH_1 (13U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) +#define BOARD_APP_ADC16_NAME "ADC0" +#define BOARD_APP_ADC16_BASE HPM_ADC0 +#define BOARD_APP_ADC16_IRQn IRQn_ADC0 +#define BOARD_APP_ADC16_CH_1 (6U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc0) #define BOARD_APP_ADC16_HW_TRIG_SRC HPM_PWM0 #define BOARD_APP_ADC16_HW_TRGM HPM_TRGM0 @@ -227,40 +239,40 @@ #define BOARD_APP_ADC16_HW_TRGM_OUT_SEQ TRGM_TRGOCFG_ADC0_STRGI #define BOARD_APP_ADC16_HW_TRGM_OUT_PMT TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* DAC section */ -#define BOARD_DAC_BASE HPM_DAC -#define BOARD_DAC_IRQn IRQn_DAC -#define BOARD_APP_DAC_CLOCK_NAME clock_dac0 +#define BOARD_DAC_BASE HPM_DAC +#define BOARD_DAC_IRQn IRQn_DAC +#define BOARD_APP_DAC_CLOCK_NAME clock_dac0 /* CAN section */ -#define BOARD_APP_CAN_BASE HPM_CAN1 -#define BOARD_APP_CAN_IRQn IRQn_CAN1 +#define BOARD_APP_CAN_BASE HPM_CAN1 +#define BOARD_APP_CAN_IRQn IRQn_CAN1 /* * timer for board delay */ -#define BOARD_DELAY_TIMER (HPM_GPTMR3) -#define BOARD_DELAY_TIMER_CH 0 +#define BOARD_DELAY_TIMER (HPM_GPTMR3) +#define BOARD_DELAY_TIMER_CH 0 #define BOARD_DELAY_TIMER_CLK_NAME (clock_gptmr3) -#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr3) /* SDXC section */ -#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC0) -#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) -#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) -#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC0) -#define BOARD_APP_EMMC_SUPPORT_3V3 (1) -#define BOARD_APP_EMMC_SUPPORT_1V8 (0) -#define BOARD_APP_EMMC_SUPPORT_4BIT (1) -#define BOARD_APP_EMMC_HOST_USING_IRQ (0) +#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC0) +#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) +#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) +#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC0) +#define BOARD_APP_EMMC_SUPPORT_3V3 (1) +#define BOARD_APP_EMMC_SUPPORT_1V8 (0) +#define BOARD_APP_EMMC_SUPPORT_4BIT (1) +#define BOARD_APP_EMMC_HOST_USING_IRQ (0) /* USB section */ #define BOARD_USB0_ID_PORT (HPM_GPIO0) @@ -270,91 +282,89 @@ /*BLDC pwm*/ /*PWM define*/ -#define BOARD_BLDCPWM HPM_PWM0 -#define BOARD_BLDC_UH_PWM_OUTPIN (0U) -#define BOARD_BLDC_UL_PWM_OUTPIN (1U) -#define BOARD_BLDC_VH_PWM_OUTPIN (2U) -#define BOARD_BLDC_VL_PWM_OUTPIN (3U) -#define BOARD_BLDC_WH_PWM_OUTPIN (4U) -#define BOARD_BLDC_WL_PWM_OUTPIN (5U) -#define BOARD_BLDCPWM_TRGM HPM_TRGM0 -#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM0 -#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) -#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) -#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) -#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) -#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) -#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) -#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) -#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) -#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) +#define BOARD_BLDCPWM HPM_PWM0 +#define BOARD_BLDC_UH_PWM_OUTPIN (0U) +#define BOARD_BLDC_UL_PWM_OUTPIN (1U) +#define BOARD_BLDC_VH_PWM_OUTPIN (2U) +#define BOARD_BLDC_VL_PWM_OUTPIN (3U) +#define BOARD_BLDC_WH_PWM_OUTPIN (4U) +#define BOARD_BLDC_WL_PWM_OUTPIN (5U) +#define BOARD_BLDCPWM_TRGM HPM_TRGM0 +#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM0 +#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) +#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) +#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) +#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) +#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) +#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) +#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) +#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) +#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) /*HALL define*/ -#define BOARD_BLDC_HALL_BASE HPM_HALL0 -#define BOARD_BLDC_HALL_TRGM HPM_TRGM0 -#define BOARD_BLDC_HALL_IRQ IRQn_HALL0 -#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P8 -#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P7 -#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P6 -#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) - - +#define BOARD_BLDC_HALL_BASE HPM_HALL0 +#define BOARD_BLDC_HALL_TRGM HPM_TRGM0 +#define BOARD_BLDC_HALL_IRQ IRQn_HALL0 +#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P8 +#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P7 +#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P6 +#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) /*QEI*/ -#define BOARD_BLDC_QEI_BASE HPM_QEI0 -#define BOARD_BLDC_QEI_IRQ IRQn_QEI0 -#define BOARD_BLDC_QEI_TRGM HPM_TRGM0 -#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P9 -#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P10 -#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) -#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0 -#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) +#define BOARD_BLDC_QEI_BASE HPM_QEI0 +#define BOARD_BLDC_QEI_IRQ IRQn_QEI0 +#define BOARD_BLDC_QEI_TRGM HPM_TRGM0 +#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P9 +#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM0_INPUT_SRC_TRGM0_P10 +#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) +#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot0 +#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) /*Timer define*/ -#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 -#define BOARD_BLDC_TMR_CH 0 -#define BOARD_BLDC_TMR_CMP 0 -#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 -#define BOARD_BLDC_TMR_RELOAD (100000U) +#define BOARD_BLDC_TMR_1MS HPM_GPTMR2 +#define BOARD_BLDC_TMR_CH 0 +#define BOARD_BLDC_TMR_CMP 0 +#define BOARD_BLDC_TMR_IRQ IRQn_GPTMR2 +#define BOARD_BLDC_TMR_RELOAD (100000U) /*adc*/ -#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC16 -#define BOARD_BLDC_ADC_U_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 -#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (7U) -#define BOARD_BLDC_ADC_CH_V (12U) -#define BOARD_BLDC_ADC_CH_W (5U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC1 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC16 +#define BOARD_BLDC_ADC_U_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 +#define BOARD_BLDC_ADC_TRIG_FLAG adc16_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (7U) +#define BOARD_BLDC_ADC_CH_V (12U) +#define BOARD_BLDC_ADC_CH_W (5U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC1 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC16_CONFIG_TRG0A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM0_INPUT_SRC_PWM0_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A /* APP PWM */ -#define BOARD_APP_PWM HPM_PWM0 -#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 -#define BOARD_APP_PWM_OUT1 0 -#define BOARD_APP_PWM_OUT2 1 -#define BOARD_APP_TRGM HPM_TRGM0 -#define BOARD_APP_PWM_IRQ IRQn_PWM0 +#define BOARD_APP_PWM HPM_PWM0 +#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 +#define BOARD_APP_PWM_OUT1 0 +#define BOARD_APP_PWM_OUT2 1 +#define BOARD_APP_TRGM HPM_TRGM0 +#define BOARD_APP_PWM_IRQ IRQn_PWM0 #define BOARD_APP_TRGM_PWM_OUTPUT TRGM_TRGOCFG_PWM_SYNCI #define BOARD_CPU_FREQ (480000000UL) /* LED */ -#define BOARD_LED_GPIO_CTRL HPM_GPIO0 +#define BOARD_LED_GPIO_CTRL HPM_GPIO0 #define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_LED_GPIO_PIN 7 -#define BOARD_LED_OFF_LEVEL 1 -#define BOARD_LED_ON_LEVEL 0 +#define BOARD_LED_GPIO_PIN 7 +#define BOARD_LED_OFF_LEVEL 1 +#define BOARD_LED_ON_LEVEL 0 #ifndef BOARD_SHOW_CLOCK #define BOARD_SHOW_CLOCK 1 @@ -364,10 +374,19 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR1 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR1 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr1 +#define BOARD_FREERTOS_TIMER HPM_GPTMR1 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR1 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr1 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR1 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR1 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr1 +/* Tamper Section */ +#define BOARD_TAMP_NO_LEVEL_PINS +#define BOARD_TAMP_ACTIVE_CH 6 #if defined(__cplusplus) extern "C" { @@ -423,8 +442,8 @@ void board_init_usb_pins(void); void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level); uint8_t board_get_usb_id_status(void); -void board_init_enet_pps_pins(ENET_Type *ptr); -uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); +void board_init_enet_pps_pins(ENET_Type *ptr); +uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); hpm_stat_t board_reset_enet_phy(ENET_Type *ptr); hpm_stat_t board_init_enet_pins(ENET_Type *ptr); hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal); diff --git a/boards/hpm6300evk/hpm6300evk.yaml b/boards/hpm6300evk/hpm6300evk.yaml index 538e478e2..d58e3cca0 100644 --- a/boards/hpm6300evk/hpm6300evk.yaml +++ b/boards/hpm6300evk/hpm6300evk.yaml @@ -1,4 +1,3 @@ -# Copyright (c) 2022 HPMicro # SPDX-License-Identifier: BSD-3-Clause board: @@ -15,44 +14,10 @@ board: type: qspi-nor-flash size: 16M feature: - - butn - - sdp - - rng - - rtc - - wdg - - adc16 - - sdcard - - usb-otg - - spi - - uart - - can - - i2c - - dual-i2c - - femc - - gpio - - gpio-led - - gpio-key - - gpiom - - pwm - - hall - - qei - - ffa - - motor-control - - bldc_hfi - - tsns - - dac - - ptp - - uart_software_rx_idle - - uart_rx_timeout - - uart_software_lin - - sdxc - - drv_pllctlv2 - - enet - - enet_pps_pinout - - enet_phy_on_board - - sw_gm_api - - hall-qei - - puart - - gpt_pin - - acmp - - ptpc + - board_uart_software_rx_idle_pin + - board_gpt_pin + - board_motor_control + - board_puart_pin + - board_enet_pps_pin + - board_enet_phy + - board_sdram diff --git a/boards/hpm6300evk/pinmux.c b/boards/hpm6300evk/pinmux.c index dd5fb57ea..54589a5f6 100644 --- a/boards/hpm6300evk/pinmux.c +++ b/boards/hpm6300evk/pinmux.c @@ -20,8 +20,8 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_SOC_PY_07; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_SOC_PY_06; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; } else if (ptr == HPM_UART1) { HPM_IOC->PAD[IOC_PAD_PC24].FUNC_CTL = IOC_PC24_FUNC_CTL_UART1_TXD; HPM_IOC->PAD[IOC_PAD_PC25].FUNC_CTL = IOC_PC25_FUNC_CTL_UART1_RXD; @@ -29,8 +29,8 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PC26].FUNC_CTL = IOC_PC26_FUNC_CTL_UART2_TXD; HPM_IOC->PAD[IOC_PAD_PC27].FUNC_CTL = IOC_PC27_FUNC_CTL_UART2_RXD; } else if (ptr == HPM_PUART) { - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_PUART_RXD; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_PUART_TXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_PUART_RXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_PUART_TXD; } } @@ -173,7 +173,7 @@ void init_gpio_pins(void) HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = pad_ctl; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_SOC_PZ_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_PZ_02; #endif } @@ -199,8 +199,8 @@ void init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) void init_pins(void) { -#ifdef BOARD_CONSOLE_BASE - init_uart_pins(BOARD_CONSOLE_BASE); +#ifdef BOARD_CONSOLE_UART_BASE + init_uart_pins(BOARD_CONSOLE_UART_BASE); #endif init_sdram_pins(); } @@ -229,8 +229,8 @@ void init_qei_trgm_pins(void) void init_butn_pins(void) { - /* HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_PBUTN; */ - /* HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = IOC_PZ03_FUNC_CTL_WBUTN; */ + /* HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_PBUTN; */ + /* HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = BIOC_PZ03_FUNC_CTL_WBUTN; */ } void init_acmp_pins(void) @@ -273,10 +273,8 @@ void init_pwm_pins(PWM_Type *ptr) void init_adc_pins(void) { - HPM_IOC->PAD[IOC_PAD_PC15].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PC16].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PC17].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PC22].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + /* ADC0.INA6 */ + HPM_IOC->PAD[IOC_PAD_PC10].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; } void init_adc_bldc_pins(void) @@ -298,8 +296,8 @@ void init_can_pins(CAN_Type *ptr) HPM_IOC->PAD[IOC_PAD_PZ04].FUNC_CTL = IOC_PZ04_FUNC_CTL_CAN1_TXD; HPM_IOC->PAD[IOC_PAD_PZ05].FUNC_CTL = IOC_PZ05_FUNC_CTL_CAN1_RXD; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = IOC_PZ04_FUNC_CTL_SOC_PZ_04; - HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = IOC_PZ05_FUNC_CTL_SOC_PZ_05; + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_SOC_PZ_04; + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_SOC_PZ_05; } } @@ -387,3 +385,9 @@ void init_enet_pps_pins(void) HPM_IOC->PAD[IOC_PAD_PC21].FUNC_CTL = IOC_PC21_FUNC_CTL_ETH0_EVTO_0; HPM_IOC->PAD[IOC_PAD_PC20].FUNC_CTL = IOC_PC20_FUNC_CTL_ETH0_EVTO_1; } + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ06].FUNC_CTL = BIOC_PZ06_FUNC_CTL_TAMP_06 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ07].FUNC_CTL = BIOC_PZ07_FUNC_CTL_TAMP_07; +} diff --git a/boards/hpm6300evk/pinmux.h b/boards/hpm6300evk/pinmux.h index c6a5b7184..39906ec0c 100644 --- a/boards/hpm6300evk/pinmux.h +++ b/boards/hpm6300evk/pinmux.h @@ -40,6 +40,8 @@ void init_i2c_pins_as_gpio(I2C_Type *ptr); void init_led_pins(void); void init_trgmux_pins(uint32_t pin); void init_enet_pps_pins(void); +void init_tamper_pins(void); + #ifdef __cplusplus } #endif diff --git a/boards/hpm6750evk/README_en.md b/boards/hpm6750evk/README_en.md index 40c3c01bf..5ef8d141b 100644 --- a/boards/hpm6750evk/README_en.md +++ b/boards/hpm6750evk/README_en.md @@ -116,9 +116,7 @@ The HPM6750 is a dual-core flashless MCU running 816Mhz. It has a 2MB continuous | Function | Position | | ------------------------------- | -------- | | ADC12 Reference Voltage Setting | N/A | -| ADC0/1/2.VINP11 | J12[6] | -| ADC0/1/2.VINP10 | J12[7] | -| ADC0/1/2.VINP7 | J12[8] | +| ADC0.VINP11 | J12[6] | - ADC16 Pin @@ -151,7 +149,8 @@ The HPM6750 is a dual-core flashless MCU running 816Mhz. It has a 2MB continuous | ----------- | -------- | | ENET0.EVTO0 | U29[2] | -- UART pin for uart_software_rx_idle sample or uart_rx_timeout sample +- UART13 pin + The UART13 is used for core1 debug console or some functional testing using UART, such as uart_software_rx_idle, uart_rx_timeout, uart_software_lin, MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. | Function | Position | | ---------- | -------- | @@ -167,3 +166,11 @@ The HPM6750 is a dual-core flashless MCU running 816Mhz. It has a 2MB continuous - Motor Pin: Refer to section [DRV-LV50A-MP1907 Motor Driver Board ](lab_drv_lv50a_mp1907) for configuration + +- Tamper Pin + +| Function | Pin | Position | Mode | +|----------|--------|--------|----------| +| TAMP.08 | PZ08 | J20[6] | Active Mode | +| TAMP.09 | PZ09 | J20[5] | Active Mode | +| TAMP.10 | PZ10 | J20[4] | Passive Mode | diff --git a/boards/hpm6750evk/README_zh.md b/boards/hpm6750evk/README_zh.md index b87f9caf3..704226358 100644 --- a/boards/hpm6750evk/README_zh.md +++ b/boards/hpm6750evk/README_zh.md @@ -73,6 +73,7 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | PWM2.P1 | J12[13] | ![image-1](doc/hpm6750evk_pwm_output_pin.png "image-1") + - SPI引脚: | 功能 | 位置 | @@ -89,13 +90,6 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | I2C0.SCL | J20[3] | | I2C0.SDA | J20[4] | -- CORE1调试串口引脚: - -| 功能 | 位置 | -| ---------- | ------ | -| UART13.TXD | J20[5] | -| UART13.RXD | J20[6] | - - ACMP引脚 | 功能 | 位置 | @@ -116,9 +110,7 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | 功能 | 位置 | | ----------------- | ------ | | ADC12参考电压设置 | 无 | -| ADC0/1/2.VINP11 | J12[6] | -| ADC0/1/2.VINP10 | J12[7] | -| ADC0/1/2.VINP7 | J12[8] | +| ADC0.VINP11 | J12[6] | - ADC16引脚 @@ -151,7 +143,8 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | ----------- | ------ | | ENET0.EVTO0 | U29[2] | -- UART引脚用于uart_software_rx_idle或uart_rx_timeout或uart_lin工程 +- UART13引脚 + UART13用于Core1调试串口或一些使用UART的功能测试,例如uart_software_rx_idle,uart_rx_timeout,uart_software_lin,MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 | 功能 | 位置 | | ---------- | ------ | @@ -167,3 +160,11 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M - 电机引脚 参考 [DRV-LV50A-MP1907 电机驱动板章节](lab_drv_lv50a_mp1907) 进行连接 + +- Tamper 接口 + +| 功能 | 引脚 | 位置 | 模式 | +|----------|--------|--------|---------| +| TAMP.08 | PZ08 | J20[6] | 主动模式 | +| TAMP.09 | PZ09 | J20[5] | 主动模式 | +| TAMP.10 | PZ10 | J20[4] | 被动模式 | diff --git a/boards/hpm6750evk/board.c b/boards/hpm6750evk/board.c index 373bea3d3..951791163 100644 --- a/boards/hpm6750evk/board.c +++ b/boards/hpm6750evk/board.c @@ -97,16 +97,16 @@ void board_init_console(void) /* uart needs to configure pin function before enabling clock, otherwise the level change of uart rx pin when configuring pin function will cause a wrong data to be received. And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t) BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t) BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -222,6 +222,12 @@ void board_init(void) #endif } +void board_init_core1(void) +{ + board_init_console(); + board_init_pmp(); +} + void board_init_sdram_pins(void) { init_sdram_pins(); @@ -954,7 +960,6 @@ void _init_ext_ram(void) femc_sdram_config_t sdram_config = {0}; femc_default_config(HPM_FEMC, &config); - config.dqs = FEMC_DQS_INTERNAL; femc_init(HPM_FEMC, &config); sdram_config.bank_num = FEMC_SDRAM_BANK_NUM_4; @@ -984,7 +989,8 @@ void _init_ext_ram(void) sdram_config.refresh_count = BOARD_SDRAM_REFRESH_COUNT; sdram_config.refresh_in_ms = BOARD_SDRAM_REFRESH_IN_MS; sdram_config.data_width_in_byte = BOARD_SDRAM_DATA_WIDTH_IN_BYTE; - sdram_config.delay_cell_value = 29; + sdram_config.delay_cell_disable = true; + sdram_config.delay_cell_value = 0; femc_config_sdram(HPM_FEMC, femc_clk_in_hz, &sdram_config); } @@ -1290,7 +1296,7 @@ hpm_stat_t board_init_enet_phy(ENET_Type *ptr) if (ptr == HPM_ENET0) { dp83867_reset(HPM_ENET0); - #if __DISABLE_AUTO_NEGO + #if defined(__DISABLE_AUTO_NEGO) && __DISABLE_AUTO_NEGO dp83867_set_mdi_crossover_mode(HPM_ENET0, enet_phy_mdi_crossover_manual_mdix); #endif dp83867_basic_mode_default_config(HPM_ENET0, &phy_config0); diff --git a/boards/hpm6750evk/board.h b/boards/hpm6750evk/board.h index feb0226b5..c91dcf5c7 100644 --- a/boards/hpm6750evk/board.h +++ b/boards/hpm6750evk/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -22,59 +22,70 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm6750evk" +#define BOARD_NAME "hpm6750evk" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) #define SEC_CORE_IMG_START ILM_LOCAL_BASE -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART13 +#define BOARD_APP_UART_IRQ IRQn_UART13 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart13 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX #endif /* uart rx idle demo section */ -#define BOARD_UART_IDLE HPM_UART13 -#define BOARD_UART_IDLE_IRQ IRQn_UART13 -#define BOARD_UART_IDLE_CLK_NAME clock_uart13 -#define BOARD_UART_IDLE_TX_DMA_SRC HPM_DMA_SRC_UART13_TX -#define BOARD_UART_IDLE_DMA_SRC HPM_DMA_SRC_UART13_RX - -#define BOARD_UART_IDLE_TRGM HPM_TRGM2 -#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PD19 -#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 -#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM2_OUTPUT_SRC_GPTMR4_IN2 +#define BOARD_UART_IDLE BOARD_APP_UART_BASE +#define BOARD_UART_IDLE_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_IDLE_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_IDLE_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_UART_IDLE_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +#define BOARD_UART_IDLE_TRGM HPM_TRGM2 +#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PD19 +#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 +#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM2_OUTPUT_SRC_GPTMR4_IN2 #define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_SYNCI HPM_TRGM2_OUTPUT_SRC_GPTMR4_SYNCI -#define BOARD_UART_IDLE_GPTMR HPM_GPTMR4 +#define BOARD_UART_IDLE_GPTMR HPM_GPTMR4 #define BOARD_UART_IDLE_GPTMR_CLK_NAME clock_gptmr4 -#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR4 -#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 -#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 +#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR4 +#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 +#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 /* uart microros sample section */ -#define BOARD_MICROROS_UART_BASE HPM_UART13 -#define BOARD_MICROROS_UART_IRQ IRQn_UART13 -#define BOARD_MICROROS_UART_CLK_NAME clock_uart13 +#define BOARD_MICROROS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MICROROS_UART_IRQ BOARD_APP_UART_IRQ +#define BOARD_MICROROS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME -/* uart lin sample section */ -#define BOARD_UART_LIN HPM_UART13 -#define BOARD_UART_LIN_IRQ IRQn_UART13 -#define BOARD_UART_LIN_CLK_NAME clock_uart13 -#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOZ -#define BOARD_UART_LIN_TX_PIN (9U) /* PZ09 should align with used pin in pinmux configuration */ +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* uart lin sample section */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOZ +#define BOARD_UART_LIN_TX_PIN (9U) /* PZ09 should align with used pin in pinmux configuration */ #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -82,89 +93,92 @@ #endif #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE +#ifndef BOARD_CONSOLE_UART_BASE #if BOARD_RUNNING_CORE == HPM_CORE0 -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #else -#define BOARD_CONSOLE_BASE HPM_UART13 -#define BOARD_CONSOLE_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_BASE HPM_UART13 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART13 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX #endif #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif - -#define BOARD_FREEMASTER_UART_BASE HPM_UART0 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART0 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart0 - /* sdram section */ -#define BOARD_SDRAM_ADDRESS (0x40000000UL) -#define BOARD_SDRAM_SIZE (32*SIZE_1MB) -#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 -#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_32_BITS -#define BOARD_SDRAM_REFRESH_COUNT (8192UL) -#define BOARD_SDRAM_REFRESH_IN_MS (64UL) +#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_SIZE (32 * SIZE_1MB) +#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 +#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_32_BITS +#define BOARD_SDRAM_REFRESH_COUNT (8192UL) +#define BOARD_SDRAM_REFRESH_IN_MS (64UL) #define BOARD_SDRAM_DATA_WIDTH_IN_BYTE (4UL) #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) -#define BOARD_FLASH_SIZE (16 << 20) +#define BOARD_FLASH_SIZE (16 << 20) + +#define BOARD_FEMC_DQS_FLOATING 1 /* lcd section */ -#define BOARD_LCD_BASE HPM_LCDC -#define BOARD_LCD_IRQ IRQn_LCDC_D0 -#define BOARD_LCD_POWER_GPIO_BASE HPM_GPIO0 -#define BOARD_LCD_POWER_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_LCD_POWER_GPIO_PIN 16 -#define BOARD_LCD_BACKLIGHT_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_BASE HPM_LCDC +#define BOARD_LCD_IRQ IRQn_LCDC_D0 +#define BOARD_LCD_POWER_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_POWER_GPIO_INDEX GPIO_DO_GPIOB +#define BOARD_LCD_POWER_GPIO_PIN 16 +#define BOARD_LCD_BACKLIGHT_GPIO_BASE HPM_GPIO0 #define BOARD_LCD_BACKLIGHT_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_LCD_BACKLIGHT_GPIO_PIN 10 +#define BOARD_LCD_BACKLIGHT_GPIO_PIN 10 /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 +#define BOARD_APP_I2C_BASE HPM_I2C0 +#define BOARD_APP_I2C_IRQ IRQn_I2C0 #define BOARD_APP_I2C_CLK_NAME clock_i2c0 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 -#define BOARD_CAM_I2C_BASE HPM_I2C0 +#define BOARD_CAM_I2C_BASE HPM_I2C0 #define BOARD_CAM_I2C_CLK_NAME clock_i2c0 #define BOARD_SUPPORT_CAM_RESET -#define BOARD_CAM_RST_GPIO_CTRL HPM_GPIO0 +#define BOARD_CAM_RST_GPIO_CTRL HPM_GPIO0 #define BOARD_CAM_RST_GPIO_INDEX GPIO_DI_GPIOY -#define BOARD_CAM_RST_GPIO_PIN 5 - -#define BOARD_CAP_I2C_BASE (HPM_I2C0) -#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 -#define BOARD_CAP_RST_GPIO (HPM_GPIO0) -#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_RST_GPIO_PIN (9) -#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_B) -#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) -#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_INTR_GPIO_PIN (8) -#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_B) +#define BOARD_CAM_RST_GPIO_PIN 5 + +#define BOARD_CAP_I2C_BASE (HPM_I2C0) +#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 +#define BOARD_CAP_RST_GPIO (HPM_GPIO0) +#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOB) +#define BOARD_CAP_RST_GPIO_PIN (9) +#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_B) +#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) +#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOB) +#define BOARD_CAP_INTR_GPIO_PIN (8) +#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_B) #define BOARD_CAP_I2C_SDA_GPIO_INDEX (GPIO_DI_GPIOZ) -#define BOARD_CAP_I2C_SDA_GPIO_PIN (10) +#define BOARD_CAP_I2C_SDA_GPIO_PIN (10) #define BOARD_CAP_I2C_CLK_GPIO_INDEX (GPIO_DI_GPIOZ) -#define BOARD_CAP_I2C_CLK_GPIO_PIN (11) +#define BOARD_CAP_I2C_CLK_GPIO_PIN (11) /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_6 /* align with used pin */ /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX /* gptmr section */ #define BOARD_GPTMR HPM_GPTMR4 @@ -182,36 +196,36 @@ #define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr5 /* gpio section */ -#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_CTRL HPM_GPIO0 #define BOARD_R_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_R_GPIO_PIN 11 -#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_PIN 11 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 #define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_G_GPIO_PIN 12 -#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_PIN 12 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 #define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_B_GPIO_PIN 13 +#define BOARD_B_GPIO_PIN 13 #define BOARD_LED_GPIO_CTRL HPM_GPIO0 #define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_LED_GPIO_PIN 12 -#define BOARD_LED_OFF_LEVEL 1 -#define BOARD_LED_ON_LEVEL 0 +#define BOARD_LED_GPIO_PIN 12 +#define BOARD_LED_OFF_LEVEL 1 +#define BOARD_LED_ON_LEVEL 0 #define BOARD_LED_TOGGLE_RGB 1 #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ -#define BOARD_APP_GPIO_PIN 2 +#define BOARD_APP_GPIO_PIN 2 /* pinmux section */ #define USING_GPIO0_FOR_GPIOZ #ifndef USING_GPIO0_FOR_GPIOZ #define BOARD_APP_GPIO_CTRL HPM_BGPIO -#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO #else #define BOARD_APP_GPIO_CTRL HPM_GPIO0 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z #endif /* gpiom section */ @@ -220,23 +234,23 @@ #define BOARD_APP_GPIOM_USING_CTRL_NAME gpiom_core0_fast /* spi section */ -#define BOARD_APP_SPI_BASE HPM_SPI2 +#define BOARD_APP_SPI_BASE HPM_SPI2 #define BOARD_APP_SPI_CLK_NAME clock_spi2 #define BOARD_APP_SPI_IRQ IRQn_SPI2 #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI2_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI2_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PE31 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI2_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI2_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PE31 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* lcd section */ @@ -251,21 +265,21 @@ #define BOARD_PDMA_BASE HPM_PDMA /* i2s section */ -#define BOARD_APP_I2S_BASE HPM_I2S0 -#define BOARD_APP_I2S_DATA_LINE (2U) -#define BOARD_APP_I2S_CLK_NAME clock_i2s0 -#define BOARD_APP_I2S_TX_DMA_REQ HPM_DMA_SRC_I2S0_TX -#define BOARD_APP_I2S_IRQ IRQn_I2S0 -#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 -#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 +#define BOARD_APP_I2S_BASE HPM_I2S0 +#define BOARD_APP_I2S_DATA_LINE (2U) +#define BOARD_APP_I2S_CLK_NAME clock_i2s0 +#define BOARD_APP_I2S_TX_DMA_REQ HPM_DMA_SRC_I2S0_TX +#define BOARD_APP_I2S_IRQ IRQn_I2S0 +#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 +#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 #define BOARD_PDM_SINGLE_CHANNEL_MASK (1U) #define BOARD_PDM_DUAL_CHANNEL_MASK (0x11U) /* enet section */ -#define BOARD_ENET_COUNT (2U) -#define BOARD_ENET_PPS HPM_ENET0 -#define BOARD_ENET_PPS_IDX enet_pps_0 -#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 +#define BOARD_ENET_COUNT (2U) +#define BOARD_ENET_PPS HPM_ENET0 +#define BOARD_ENET_PPS_IDX enet_pps_0 +#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 #define BOARD_ENET_RGMII_PHY_ITF enet_inf_rgmii #define BOARD_ENET_RGMII_RST_GPIO HPM_GPIO0 @@ -277,29 +291,27 @@ #define BOARD_ENET_RGMII_PTP_CLOCK clock_ptp0 #define BOARD_ENET_RGMII_PPS0_PINOUT (1) -#define BOARD_ENET_RMII_PHY_ITF enet_inf_rmii -#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0 -#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOE -#define BOARD_ENET_RMII_RST_GPIO_PIN (26U) -#define BOARD_ENET_RMII HPM_ENET1 -#define BOARD_ENET_RMII_INT_REF_CLK (1U) -#define BOARD_ENET_RMII_PTP_CLOCK clock_ptp1 -#define BOARD_ENET_RMII_PPS0_PINOUT (0) +#define BOARD_ENET_RMII_PHY_ITF enet_inf_rmii +#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0 +#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOE +#define BOARD_ENET_RMII_RST_GPIO_PIN (26U) +#define BOARD_ENET_RMII HPM_ENET1 +#define BOARD_ENET_RMII_INT_REF_CLK (1U) +#define BOARD_ENET_RMII_PTP_CLOCK clock_ptp1 +#define BOARD_ENET_RMII_PPS0_PINOUT (0) /* ADC section */ -#define BOARD_APP_ADC12_NAME "ADC0" -#define BOARD_APP_ADC12_BASE HPM_ADC0 -#define BOARD_APP_ADC12_IRQn IRQn_ADC0 -#define BOARD_APP_ADC12_CH_1 (11U) -#define BOARD_APP_ADC12_CH_2 (10U) -#define BOARD_APP_ADC12_CH_3 (7U) -#define BOARD_APP_ADC12_CLK_NAME (clock_adc0) - -#define BOARD_APP_ADC16_NAME "ADC3" -#define BOARD_APP_ADC16_BASE HPM_ADC3 -#define BOARD_APP_ADC16_IRQn IRQn_ADC3 -#define BOARD_APP_ADC16_CH_1 (2U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc3) +#define BOARD_APP_ADC12_NAME "ADC0" +#define BOARD_APP_ADC12_BASE HPM_ADC0 +#define BOARD_APP_ADC12_IRQn IRQn_ADC0 +#define BOARD_APP_ADC12_CH_1 (11U) +#define BOARD_APP_ADC12_CLK_NAME (clock_adc0) + +#define BOARD_APP_ADC16_NAME "ADC3" +#define BOARD_APP_ADC16_BASE HPM_ADC3 +#define BOARD_APP_ADC16_IRQn IRQn_ADC3 +#define BOARD_APP_ADC16_CH_1 (2U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc3) #define BOARD_APP_ADC12_HW_TRIG_SRC HPM_PWM0 #define BOARD_APP_ADC12_HW_TRGM HPM_TRGM0 @@ -313,46 +325,45 @@ #define BOARD_APP_ADC16_HW_TRGM_OUT_SEQ TRGM_TRGOCFG_ADC3_STRGI #define BOARD_APP_ADC16_HW_TRGM_OUT_PMT TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_APP_ADC12_PMT_TRIG_CH ADC12_CONFIG_TRG0A -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC12_PMT_TRIG_CH ADC12_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* CAN section */ -#define BOARD_APP_CAN_BASE HPM_CAN0 -#define BOARD_APP_CAN_IRQn IRQn_CAN0 - +#define BOARD_APP_CAN_BASE HPM_CAN0 +#define BOARD_APP_CAN_IRQn IRQn_CAN0 /* * timer for board delay */ -#define BOARD_DELAY_TIMER (HPM_GPTMR7) -#define BOARD_DELAY_TIMER_CH 0 +#define BOARD_DELAY_TIMER (HPM_GPTMR7) +#define BOARD_DELAY_TIMER_CH 0 #define BOARD_DELAY_TIMER_CLK_NAME (clock_gptmr7) -#define BOARD_CALLBACK_TIMER (HPM_GPTMR7) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR7 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR7) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR7 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr7) /* SDXC section */ -#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) -#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) -#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (0) -#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (0) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (1) +#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) +#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) +#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (0) +#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (0) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (1) #if defined(BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO) && (BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO == 1) -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN IOC_PAD_PD15 -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_POL 1 /* PIN value 0 means card is inserted */ +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN IOC_PAD_PD15 +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_POL 1 /* PIN value 0 means card is inserted */ #endif -#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_EMMC_SUPPORT_3V3 (1) -#define BOARD_APP_EMMC_SUPPORT_1V8 (0) -#define BOARD_APP_EMMC_SUPPORT_4BIT (1) -#define BOARD_APP_EMMC_HOST_USING_IRQ (0) +#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_EMMC_SUPPORT_3V3 (1) +#define BOARD_APP_EMMC_SUPPORT_1V8 (0) +#define BOARD_APP_EMMC_SUPPORT_4BIT (1) +#define BOARD_APP_EMMC_HOST_USING_IRQ (0) /* USB section */ #define BOARD_USB0_ID_PORT (HPM_GPIO0) @@ -374,113 +385,111 @@ /*BLDC pwm*/ /*PWM define*/ -#define BOARD_BLDCPWM HPM_PWM2 -#define BOARD_BLDC_UH_PWM_OUTPIN (0U) -#define BOARD_BLDC_UL_PWM_OUTPIN (1U) -#define BOARD_BLDC_VH_PWM_OUTPIN (2U) -#define BOARD_BLDC_VL_PWM_OUTPIN (3U) -#define BOARD_BLDC_WH_PWM_OUTPIN (4U) -#define BOARD_BLDC_WL_PWM_OUTPIN (5U) -#define BOARD_BLDCPWM_TRGM HPM_TRGM2 -#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM2 -#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) -#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) -#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) -#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) -#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) -#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) -#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) -#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) -#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) +#define BOARD_BLDCPWM HPM_PWM2 +#define BOARD_BLDC_UH_PWM_OUTPIN (0U) +#define BOARD_BLDC_UL_PWM_OUTPIN (1U) +#define BOARD_BLDC_VH_PWM_OUTPIN (2U) +#define BOARD_BLDC_VL_PWM_OUTPIN (3U) +#define BOARD_BLDC_WH_PWM_OUTPIN (4U) +#define BOARD_BLDC_WL_PWM_OUTPIN (5U) +#define BOARD_BLDCPWM_TRGM HPM_TRGM2 +#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM2 +#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) +#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) +#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) +#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) +#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) +#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) +#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) +#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) +#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) /*HALL define*/ -#define BOARD_BLDC_HALL_BASE HPM_HALL2 -#define BOARD_BLDC_HALL_TRGM HPM_TRGM2 -#define BOARD_BLDC_HALL_IRQ IRQn_HALL2 -#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P6 -#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P7 -#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P8 -#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) - - +#define BOARD_BLDC_HALL_BASE HPM_HALL2 +#define BOARD_BLDC_HALL_TRGM HPM_TRGM2 +#define BOARD_BLDC_HALL_IRQ IRQn_HALL2 +#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P6 +#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P7 +#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P8 +#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) /*QEI*/ -#define BOARD_BLDC_QEI_BASE HPM_QEI2 -#define BOARD_BLDC_QEI_IRQ IRQn_QEI2 -#define BOARD_BLDC_QEI_TRGM HPM_TRGM2 -#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 -#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P10 -#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) -#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot2 -#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) +#define BOARD_BLDC_QEI_BASE HPM_QEI2 +#define BOARD_BLDC_QEI_IRQ IRQn_QEI2 +#define BOARD_BLDC_QEI_TRGM HPM_TRGM2 +#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 +#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P10 +#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) +#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot2 +#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) /*Timer define*/ -#define BOARD_TMR_1MS HPM_GPTMR2 -#define BOARD_TMR_1MS_CH 0 -#define BOARD_TMR_1MS_CMP 0 -#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 -#define BOARD_TMR_1MS_RELOAD (100000U) +#define BOARD_TMR_1MS HPM_GPTMR2 +#define BOARD_TMR_1MS_CH 0 +#define BOARD_TMR_1MS_CMP 0 +#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 +#define BOARD_TMR_1MS_RELOAD (100000U) -#define BOARD_BLDC_TMR_1MS BOARD_TMR_1MS -#define BOARD_BLDC_TMR_CH BOARD_TMR_1MS_CH -#define BOARD_BLDC_TMR_CMP BOARD_TMR_1MS_CMP -#define BOARD_BLDC_TMR_IRQ BOARD_TMR_1MS_IRQ -#define BOARD_BLDC_TMR_RELOAD BOARD_TMR_1MS_RELOAD +#define BOARD_BLDC_TMR_1MS BOARD_TMR_1MS +#define BOARD_BLDC_TMR_CH BOARD_TMR_1MS_CH +#define BOARD_BLDC_TMR_CMP BOARD_TMR_1MS_CMP +#define BOARD_BLDC_TMR_IRQ BOARD_TMR_1MS_IRQ +#define BOARD_BLDC_TMR_RELOAD BOARD_TMR_1MS_RELOAD /*adc*/ -#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC12 -#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 -#define BOARD_BLDC_ADC_TRIG_FLAG adc12_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (7U) -#define BOARD_BLDC_ADC_CH_V (10U) -#define BOARD_BLDC_ADC_CH_W (11U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC12 +#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 +#define BOARD_BLDC_ADC_TRIG_FLAG adc12_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (7U) +#define BOARD_BLDC_ADC_CH_V (10U) +#define BOARD_BLDC_ADC_CH_W (11U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC12_CONFIG_TRG2A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM2_INPUT_SRC_PWM2_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM2_INPUT_SRC_PWM2_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 /* APP PWM */ -#define BOARD_APP_PWM HPM_PWM2 -#define BOARD_APP_PWM_CLOCK_NAME clock_mot2 -#define BOARD_APP_PWM_OUT1 0 -#define BOARD_APP_PWM_OUT2 1 -#define BOARD_APP_TRGM HPM_TRGM2 -#define BOARD_APP_PWM_IRQ IRQn_PWM2 +#define BOARD_APP_PWM HPM_PWM2 +#define BOARD_APP_PWM_CLOCK_NAME clock_mot2 +#define BOARD_APP_PWM_OUT1 0 +#define BOARD_APP_PWM_OUT2 1 +#define BOARD_APP_TRGM HPM_TRGM2 +#define BOARD_APP_PWM_IRQ IRQn_PWM2 #define BOARD_APP_TRGM_PWM_OUTPUT TRGM_TRGOCFG_PWM_SYNCI /* RGB LED Section */ -#define BOARD_RED_PWM_IRQ IRQn_PWM1 -#define BOARD_RED_PWM HPM_PWM1 -#define BOARD_RED_PWM_OUT 8 -#define BOARD_RED_PWM_CMP 8 +#define BOARD_RED_PWM_IRQ IRQn_PWM1 +#define BOARD_RED_PWM HPM_PWM1 +#define BOARD_RED_PWM_OUT 8 +#define BOARD_RED_PWM_CMP 8 #define BOARD_RED_PWM_CMP_INITIAL_ZERO true -#define BOARD_RED_PWM_CLOCK_NAME clock_mot1 +#define BOARD_RED_PWM_CLOCK_NAME clock_mot1 -#define BOARD_GREEN_PWM_IRQ IRQn_PWM0 -#define BOARD_GREEN_PWM HPM_PWM0 -#define BOARD_GREEN_PWM_OUT 8 -#define BOARD_GREEN_PWM_CMP 8 +#define BOARD_GREEN_PWM_IRQ IRQn_PWM0 +#define BOARD_GREEN_PWM HPM_PWM0 +#define BOARD_GREEN_PWM_OUT 8 +#define BOARD_GREEN_PWM_CMP 8 #define BOARD_GREEN_PWM_CMP_INITIAL_ZERO true -#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot0 +#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot0 -#define BOARD_BLUE_PWM_IRQ IRQn_PWM1 -#define BOARD_BLUE_PWM HPM_PWM1 -#define BOARD_BLUE_PWM_OUT 9 -#define BOARD_BLUE_PWM_CMP 9 +#define BOARD_BLUE_PWM_IRQ IRQn_PWM1 +#define BOARD_BLUE_PWM HPM_PWM1 +#define BOARD_BLUE_PWM_OUT 9 +#define BOARD_BLUE_PWM_CMP 9 #define BOARD_BLUE_PWM_CMP_INITIAL_ZERO true -#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot1 +#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot1 -#define BOARD_RGB_RED 0 +#define BOARD_RGB_RED 0 #define BOARD_RGB_GREEN (BOARD_RGB_RED + 1) #define BOARD_RGB_BLUE (BOARD_RGB_RED + 2) @@ -496,10 +505,19 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR4 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR4 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr4 +#define BOARD_FREERTOS_TIMER HPM_GPTMR4 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR4 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr4 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR4 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR4 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr4 +/* Tamper Section */ +#define BOARD_TAMP_ACTIVE_CH 8 +#define BOARD_TAMP_LOW_LEVEL_CH 10 #if defined(__cplusplus) extern "C" { @@ -510,6 +528,8 @@ typedef void (*board_timer_cb)(void); void board_init(void); void board_init_console(void); +void board_init_core1(void); + void board_init_uart(UART_Type *ptr); void board_init_i2c(I2C_Type *ptr); void board_init_lcd(void); @@ -574,8 +594,8 @@ void board_init_adc16_pins(void); void board_init_usb_pins(void); void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level); -void board_init_enet_pps_pins(ENET_Type *ptr); -uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); +void board_init_enet_pps_pins(ENET_Type *ptr); +uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); hpm_stat_t board_reset_enet_phy(ENET_Type *ptr); hpm_stat_t board_init_enet_pins(ENET_Type *ptr); hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal); @@ -590,8 +610,8 @@ hpm_stat_t board_init_multiple_enet_clock(void); hpm_stat_t board_reset_multiple_enet_phy(void); hpm_stat_t board_init_enet_phy(ENET_Type *ptr); ENET_Type *board_get_enet_base(uint8_t idx); -uint8_t board_get_enet_phy_itf(uint8_t idx); -void board_get_enet_phy_status(uint8_t idx, void *status); +uint8_t board_get_enet_phy_itf(uint8_t idx); +void board_get_enet_phy_status(uint8_t idx, void *status); #endif /* diff --git a/boards/hpm6750evk/hpm6750evk.yaml b/boards/hpm6750evk/hpm6750evk.yaml index 67b27b018..5d31a1478 100644 --- a/boards/hpm6750evk/hpm6750evk.yaml +++ b/boards/hpm6750evk/hpm6750evk.yaml @@ -15,59 +15,18 @@ board: type: qspi-nor-flash size: 16M feature: - - butn - - sdp - - rng - - rtc - - wdg - - adc - - sdcard - - usb-otg - - dao - - pdm - - vad - - cam - - lcd - - spi - - uart - - can - - i2c - - femc - - gpio - - gpio-led - - gpio-key - - pwm - - pwm-beep - - pwm-rgb-led - - hall - - qei - - motor-control - - audio-codec - - sgtl5000 - - tflm - - multicore - - drv_pllctl - - drv_sysctl - - sdxc - - i2s - - uart_software_rx_idle - - uart_rx_timeout - - uart_software_lin - - ptp - - gpiom - - adc12 - - adc16 - - adc_tempsns - - enet - - enet_pps_pinout - - enet_phy_on_board - - enet_multi_port - - sw_gm_api - - hall-qei - - bldc_smc - - bldc_hfi - - puart - - gpt_pin - - sdram - - acmp - - ptpc + - board_audio_in + - board_audio_out + - board_audio_in_vad + - board_audio_codec + - board_uart_software_rx_idle_pin + - board_gpt_pin + - board_motor_control + - board_pwm_rgb_led + - board_puart_pin + - board_enet_pps_pin + - board_sdcard + - board_sdram + - board_enet_phy + - board_enet_dual_phy + - board_dual_usb diff --git a/boards/hpm6750evk/pinmux.c b/boards/hpm6750evk/pinmux.c index c0e8d1a24..e098ca899 100644 --- a/boards/hpm6750evk/pinmux.c +++ b/boards/hpm6750evk/pinmux.c @@ -21,8 +21,8 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_SOC_PY_07; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_SOC_PY_06; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; } else if (ptr == HPM_UART2) { HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_UART2_TXD; HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PE21_FUNC_CTL_UART2_RXD; @@ -30,11 +30,11 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_UART13_RXD; HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_UART13_TXD; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_SOC_PZ_08; - HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_SOC_PZ_09; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; } else if (ptr == HPM_PUART) { - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_PUART_RXD; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_PUART_TXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_PUART_RXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_PUART_TXD; } } @@ -47,11 +47,11 @@ void init_uart_pin_as_gpio(UART_Type *ptr) /* PZ port IO needs to configure BIOC as well */ HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_GPIO_Z_08; - HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; /* PZ port IO needs to configure BIOC as well */ HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_GPIO_Z_09; - HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_SOC_PZ_09; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; } } @@ -268,7 +268,7 @@ void init_gpio_pins(uint8_t led_pull_select) HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_SOC_PZ_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_PZ_02; #endif } @@ -294,8 +294,8 @@ void init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) void init_pins(void) { -#ifdef BOARD_CONSOLE_BASE - init_uart_pins(BOARD_CONSOLE_BASE); +#ifdef BOARD_CONSOLE_UART_BASE + init_uart_pins(BOARD_CONSOLE_UART_BASE); #endif init_sdram_pins(); } @@ -362,8 +362,8 @@ void init_dao_pins(void) HPM_IOC->PAD[IOC_PAD_PY08].FUNC_CTL = IOC_PY08_FUNC_CTL_DAOR_P; HPM_IOC->PAD[IOC_PAD_PY09].FUNC_CTL = IOC_PY09_FUNC_CTL_DAOR_N; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY08].FUNC_CTL = IOC_PY08_FUNC_CTL_SOC_PY_08; - HPM_PIOC->PAD[IOC_PAD_PY09].FUNC_CTL = IOC_PY09_FUNC_CTL_SOC_PY_09; + HPM_PIOC->PAD[IOC_PAD_PY08].FUNC_CTL = PIOC_PY08_FUNC_CTL_SOC_PY_08; + HPM_PIOC->PAD[IOC_PAD_PY09].FUNC_CTL = PIOC_PY09_FUNC_CTL_SOC_PY_09; } void init_pdm_pins(void) @@ -371,14 +371,14 @@ void init_pdm_pins(void) HPM_IOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_PDM0_CLK; HPM_IOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_PDM0_D_0; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_SOC_PY_10; - HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_SOC_PY_11; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_SOC_PY_10; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_SOC_PY_11; } void init_vad_pins(void) { - HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_VAD_CLK; - HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_VAD_DAT; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_VAD_CLK; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_VAD_DAT; } void init_cam_pins(void) @@ -386,7 +386,7 @@ void init_cam_pins(void) /* configure rst pin function */ HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_GPIO_Y_05; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_SOC_PY_05; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_SOC_PY_05; HPM_IOC->PAD[IOC_PAD_PA10].FUNC_CTL = IOC_PA10_FUNC_CTL_CAM0_XCLK; HPM_IOC->PAD[IOC_PAD_PA11].FUNC_CTL = IOC_PA11_FUNC_CTL_CAM0_PIXCLK; @@ -404,10 +404,10 @@ void init_cam_pins(void) void init_butn_pins(void) { - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_PBUTN; - HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = IOC_PZ03_FUNC_CTL_WBUTN; - HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = IOC_PZ04_FUNC_CTL_PLED; - HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = IOC_PZ05_FUNC_CTL_WLED; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_PBUTN; + HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = BIOC_PZ03_FUNC_CTL_WBUTN; + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_PLED; + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_WLED; } void init_acmp_pins(void) @@ -476,11 +476,7 @@ void init_pwm_pins(PWM_Type *ptr) void init_adc12_pins(void) { - /* ADC0/1/2.VIN7 */ - HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2.VIN10 */ - HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2.VIN11 */ + /* ADC0.VIN11 */ HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; } @@ -607,3 +603,10 @@ void init_enet_pps_pins(void) { HPM_IOC->PAD[IOC_PAD_PF05].FUNC_CTL = IOC_PF05_FUNC_CTL_ETH0_EVTO_0; } + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_TAMP_08 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_TAMP_09; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_TAMP_10; +} diff --git a/boards/hpm6750evk/pinmux.h b/boards/hpm6750evk/pinmux.h index 183586f09..ffad1dc14 100644 --- a/boards/hpm6750evk/pinmux.h +++ b/boards/hpm6750evk/pinmux.h @@ -48,6 +48,7 @@ void init_i2c_pins_as_gpio(I2C_Type *ptr); void init_led_pins_as_gpio(void); void init_trgmux_pins(uint32_t pin); void init_enet_pps_pins(void); +void init_tamper_pins(void); #ifdef __cplusplus } diff --git a/boards/hpm6750evk2/README_en.md b/boards/hpm6750evk2/README_en.md index 748403f4a..869c0d46a 100644 --- a/boards/hpm6750evk2/README_en.md +++ b/boards/hpm6750evk2/README_en.md @@ -82,6 +82,21 @@ The UART0 pin leads to three positions: > **_Note_:**To avoid abnormal functions caused by multiple connections, please ensure that there is only one connection. For example, if the JTAG interface is connected to UART0, USB2UART0 interface send data to UART0 will be abnormal. +- UART13 Pin: + + The UART13 is used for core1 debug console or some functional testing using UART, such as uart_software_rx_idle, uart_rx_timeout, uart_software_lin, MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. + +| Function | Pin | Position | +| ---------- | ---- | -------- | +| UART13.TXD | PZ09 | J11[5] | +| UART13.RXD | PZ08 | J11[6] | + +- TRGMUX pin for uart_software_rx_idle sample + +| Function | Position | +| -------------- | -------- | +| TRGM2_P9(PD19) | J10[20] | + - SPI Pin: | Function | Pin | Position | @@ -98,13 +113,6 @@ The UART0 pin leads to three positions: | I2C0.SCL | PZ11 | J11[3] | | I2C0.SDA | PZ10 | J11[4] | -- UART for core1 debug console: - -| Function | Pin | Position | -| ---------- | ---- | -------- | -| UART13.TXD | PZ09 | J11[5] | -| UART13.RXD | PZ08 | J11[6] | - - PWM Pin: | Function | Pin | Position | @@ -132,9 +140,7 @@ The UART0 pin leads to three positions: | Function | Pin | Position | | ----------------- | ----- | -------- | | Reference Voltage | VREFH | J108[2] | -| ADC0/1/2.VINP11 | PE25 | J10[6] | -| ADC0/1/2.VINP10 | PE24 | J10[7] | -| ADC0/1/2.VINP7 | PE21 | J10[8] | +| ADC0.VINP11 | PE25 | J10[6] | - ADC16 Pin @@ -167,19 +173,6 @@ The UART0 pin leads to three positions: | ----------- | -------- | | ENET0.EVTO0 | U11[3] | -- UART pin for uart_software_rx_idle sample or uart_rx_timeout sample - -| Function | Position | -| ---------- | -------- | -| UART13.TXD | J11[5] | -| UART13.RXD | J11[6] | - -- TRGMUX pin for uart_software_rx_idle sample - -| Function | Position | -| -------------- | -------- | -| TRGM2_P9(PD19) | J10[20] | - - Motor Pin: Need to remove all the resistors selected by `GigEPOP` silkscreen and make sure all the resistors selected by `MOTOR POP` silkscreen are soldered, the development board list is as follows. @@ -187,3 +180,11 @@ The UART0 pin leads to three positions: Using the high-frequency injection demo, need to remove PWM ground resistors R436-R441. Refer to section [DRV-LV50A-MP1907 Motor Driver Board ](lab_drv_lv50a_mp1907) for configuration + +- Tamper Pin + +| Function | Pin | Position | Mode | +|----------|--------|--------|----------| +| TAMP.08 | PZ08 | J11[6] | Active Mode | +| TAMP.09 | PZ09 | J11[5] | Active Mode | +| TAMP.10 | PZ10 | J11[4] | Passive Mode | diff --git a/boards/hpm6750evk2/README_zh.md b/boards/hpm6750evk2/README_zh.md index 20f8c8776..dbf99325f 100644 --- a/boards/hpm6750evk2/README_zh.md +++ b/boards/hpm6750evk2/README_zh.md @@ -64,7 +64,9 @@ HPM6750是一款主频达816MHz的双核微控制器。该芯片拥有最大2M ## 功能选择电阻 -- GigE POP `R177-R182`| 状态 | 描述 | +- GigE POP `R177-R182` + +- | 状态 | 描述 | | ---- | ---- | | 焊接 | 网络 | | 断开 | 电机 | @@ -82,6 +84,21 @@ HPM6750是一款主频达816MHz的双核微控制器。该芯片拥有最大2M 注意:使用UART0时,请确保只有一处连接,避免多处连接造成功能不正常。例如,JTAG口连接了UART0,从USB2UART0接口发送数据给UART0就会异常。 +- UART13串口引脚: + + UART13用于CORE1调试串口或一些使用UART的功能测试,例如uart_software_rx_idle,uart_rx_timeout,uart_software_lin,MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 + +| 功能 | 引脚 | 位置 | +| ---------- | ---- | ------ | +| UART13.TXD | PZ09 | J11[5] | +| UART13.RXD | PZ08 | J11[6] | + +- TRGMUX引脚用于uart_software_rx_idle工程 + +| 功能 | 位置 | +| ---------- | -------- | +| TRGM2_P9(PD19) | J10[20] | + - SPI引脚: | 功能 | 引脚 | 位置 | @@ -98,12 +115,6 @@ HPM6750是一款主频达816MHz的双核微控制器。该芯片拥有最大2M | I2C0.SCL | PZ11 | J11[3] | | I2C0.SDA | PZ10 | J11[4] | -- CORE1调试串口引脚: - -| 功能 | 引脚 | 位置 | -| ---------- | ---- | ------ | -| UART13.TXD | PZ09 | J11[5] | -| UART13.RXD | PZ08 | J11[6] | - PWM引脚: @@ -132,9 +143,7 @@ HPM6750是一款主频达816MHz的双核微控制器。该芯片拥有最大2M | 功能 | 引脚 | 位置 | | --------------- | ----- | ------- | | ADC12参考电压 | VREFH | J108[2] | -| ADC0/1/2.VINP11 | PE25 | J10[6] | -| ADC0/1/2.VINP10 | PE24 | J10[7] | -| ADC0/1/2.VINP7 | PE21 | J10[8] | +| ADC0.VINP11 | PE25 | J10[6] | - ADC16引脚 @@ -167,19 +176,6 @@ HPM6750是一款主频达816MHz的双核微控制器。该芯片拥有最大2M | ----------- | ------ | | ENET0.EVTO0 | U11[3] | -- UART引脚用于uart_software_rx_idle或uart_rx_timeout或uart_lin工程 - -| 功能 | 位置 | -| ---------- | ------ | -| UART13.TXD | J11[5] | -| UART13.RXD | J11[6] | - -- TRGMUX引脚用于uart_software_rx_idle工程 - -| 功能 | 位置 | -| ---------- | -------- | -| TRGM2_P9(PD19) | J10[20] | - - 电机引脚 需要根据功能选择电阻章节,选择GigE POP为电机 @@ -187,3 +183,11 @@ HPM6750是一款主频达816MHz的双核微控制器。该芯片拥有最大2M 如果使用高频注入的demo,需要去掉PWM接地电阻R436-R441 参考 [DRV-LV50A-MP1907 电机驱动板章节](lab_drv_lv50a_mp1907) 进行连接 + +- Tamper 接口 + +| 功能 | 引脚 | 位置 | 模式 | +|----------|--------|--------|---------| +| TAMP.08 | PZ08 | J11[6] | 主动模式 | +| TAMP.09 | PZ09 | J11[5] | 主动模式 | +| TAMP.10 | PZ10 | J11[4] | 被动模式 | diff --git a/boards/hpm6750evk2/board.c b/boards/hpm6750evk2/board.c index 0ff1f1d79..e766d7785 100644 --- a/boards/hpm6750evk2/board.c +++ b/boards/hpm6750evk2/board.c @@ -96,16 +96,16 @@ void board_init_console(void) /* uart needs to configure pin function before enabling clock, otherwise the level change of uart rx pin when configuring pin function will cause a wrong data to be received. And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t) BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t) BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -201,6 +201,12 @@ void board_init(void) #endif } +void board_init_core1(void) +{ + board_init_console(); + board_init_pmp(); +} + void board_init_sdram_pins(void) { init_sdram_pins(); @@ -925,7 +931,6 @@ void _init_ext_ram(void) femc_sdram_config_t sdram_config = {0}; femc_default_config(HPM_FEMC, &config); - config.dqs = FEMC_DQS_INTERNAL; femc_init(HPM_FEMC, &config); sdram_config.bank_num = FEMC_SDRAM_BANK_NUM_4; @@ -955,7 +960,8 @@ void _init_ext_ram(void) sdram_config.refresh_count = BOARD_SDRAM_REFRESH_COUNT; sdram_config.refresh_in_ms = BOARD_SDRAM_REFRESH_IN_MS; sdram_config.data_width_in_byte = BOARD_SDRAM_DATA_WIDTH_IN_BYTE; - sdram_config.delay_cell_value = 29; + sdram_config.delay_cell_disable = true; + sdram_config.delay_cell_value = 0; femc_config_sdram(HPM_FEMC, femc_clk_in_hz, &sdram_config); } diff --git a/boards/hpm6750evk2/board.h b/boards/hpm6750evk2/board.h index a763be02c..2dac3a88a 100644 --- a/boards/hpm6750evk2/board.h +++ b/boards/hpm6750evk2/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -22,59 +22,70 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm6750evk2" +#define BOARD_NAME "hpm6750evk2" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) #define SEC_CORE_IMG_START ILM_LOCAL_BASE -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART13 +#define BOARD_APP_UART_IRQ IRQn_UART13 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart13 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX #endif /* uart rx idle demo section */ -#define BOARD_UART_IDLE HPM_UART13 -#define BOARD_UART_IDLE_IRQ IRQn_UART13 -#define BOARD_UART_IDLE_CLK_NAME clock_uart13 -#define BOARD_UART_IDLE_TX_DMA_SRC HPM_DMA_SRC_UART13_TX -#define BOARD_UART_IDLE_DMA_SRC HPM_DMA_SRC_UART13_RX - -#define BOARD_UART_IDLE_TRGM HPM_TRGM2 -#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PD19 -#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 -#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM2_OUTPUT_SRC_GPTMR4_IN2 +#define BOARD_UART_IDLE BOARD_APP_UART_BASE +#define BOARD_UART_IDLE_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_IDLE_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_IDLE_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_UART_IDLE_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +#define BOARD_UART_IDLE_TRGM HPM_TRGM2 +#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PD19 +#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 +#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM2_OUTPUT_SRC_GPTMR4_IN2 #define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_SYNCI HPM_TRGM2_OUTPUT_SRC_GPTMR4_SYNCI -#define BOARD_UART_IDLE_GPTMR HPM_GPTMR4 +#define BOARD_UART_IDLE_GPTMR HPM_GPTMR4 #define BOARD_UART_IDLE_GPTMR_CLK_NAME clock_gptmr4 -#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR4 -#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 -#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 +#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR4 +#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 +#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 /* uart microros sample section */ -#define BOARD_MICROROS_UART_BASE HPM_UART13 -#define BOARD_MICROROS_UART_IRQ IRQn_UART13 -#define BOARD_MICROROS_UART_CLK_NAME clock_uart13 +#define BOARD_MICROROS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MICROROS_UART_IRQ BOARD_APP_UART_IRQ +#define BOARD_MICROROS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME -/* uart lin sample section */ -#define BOARD_UART_LIN HPM_UART13 -#define BOARD_UART_LIN_IRQ IRQn_UART13 -#define BOARD_UART_LIN_CLK_NAME clock_uart13 -#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOZ -#define BOARD_UART_LIN_TX_PIN (9U) /* PZ09 should align with used pin in pinmux configuration */ +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ + +/* uart lin sample section */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOZ +#define BOARD_UART_LIN_TX_PIN (9U) /* PZ09 should align with used pin in pinmux configuration */ #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -82,92 +93,95 @@ #endif #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE +#ifndef BOARD_CONSOLE_UART_BASE #if BOARD_RUNNING_CORE == HPM_CORE0 -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #else -#define BOARD_CONSOLE_BASE HPM_UART13 -#define BOARD_CONSOLE_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_BASE HPM_UART13 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART13 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX #endif #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif - -#define BOARD_FREEMASTER_UART_BASE HPM_UART0 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART0 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart0 - /* sdram section */ -#define BOARD_SDRAM_ADDRESS (0x40000000UL) -#define BOARD_SDRAM_SIZE (32*SIZE_1MB) -#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 -#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_32_BITS -#define BOARD_SDRAM_REFRESH_COUNT (8192UL) -#define BOARD_SDRAM_REFRESH_IN_MS (64UL) +#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_SIZE (32 * SIZE_1MB) +#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 +#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_32_BITS +#define BOARD_SDRAM_REFRESH_COUNT (8192UL) +#define BOARD_SDRAM_REFRESH_IN_MS (64UL) #define BOARD_SDRAM_DATA_WIDTH_IN_BYTE (4UL) #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) -#define BOARD_FLASH_SIZE (16 << 20) +#define BOARD_FLASH_SIZE (16 << 20) + +#define BOARD_FEMC_DQS_FLOATING 1 /* lcd section */ -#define BOARD_LCD_BASE HPM_LCDC -#define BOARD_LCD_IRQ IRQn_LCDC_D0 -#define BOARD_LCD_RESET_GPIO_BASE HPM_GPIO0 -#define BOARD_LCD_RESET_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_LCD_RESET_GPIO_PIN 16 -#define BOARD_LCD_BACKLIGHT_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_BASE HPM_LCDC +#define BOARD_LCD_IRQ IRQn_LCDC_D0 +#define BOARD_LCD_RESET_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_RESET_GPIO_INDEX GPIO_DO_GPIOB +#define BOARD_LCD_RESET_GPIO_PIN 16 +#define BOARD_LCD_BACKLIGHT_GPIO_BASE HPM_GPIO0 #define BOARD_LCD_BACKLIGHT_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_LCD_BACKLIGHT_GPIO_PIN 10 -#define BOARD_LCD_POWER_EN_GPIO_BASE HPM_GPIO0 -#define BOARD_LCD_POWER_EN_GPIO_INDEX GPIO_DO_GPIOZ -#define BOARD_LCD_POWER_EN_GPIO_PIN 00 +#define BOARD_LCD_BACKLIGHT_GPIO_PIN 10 +#define BOARD_LCD_POWER_EN_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_POWER_EN_GPIO_INDEX GPIO_DO_GPIOZ +#define BOARD_LCD_POWER_EN_GPIO_PIN 00 /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 +#define BOARD_APP_I2C_BASE HPM_I2C0 +#define BOARD_APP_I2C_IRQ IRQn_I2C0 #define BOARD_APP_I2C_CLK_NAME clock_i2c0 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 -#define BOARD_CAM_I2C_BASE HPM_I2C0 +#define BOARD_CAM_I2C_BASE HPM_I2C0 #define BOARD_CAM_I2C_CLK_NAME clock_i2c0 #define BOARD_SUPPORT_CAM_RESET -#define BOARD_CAM_RST_GPIO_CTRL HPM_GPIO0 +#define BOARD_CAM_RST_GPIO_CTRL HPM_GPIO0 #define BOARD_CAM_RST_GPIO_INDEX GPIO_DI_GPIOY -#define BOARD_CAM_RST_GPIO_PIN 5 - -#define BOARD_CAP_I2C_BASE (HPM_I2C0) -#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 -#define BOARD_CAP_RST_GPIO (HPM_GPIO0) -#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_RST_GPIO_PIN (9) -#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_B) -#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) -#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_INTR_GPIO_PIN (8) -#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_B) +#define BOARD_CAM_RST_GPIO_PIN 5 + +#define BOARD_CAP_I2C_BASE (HPM_I2C0) +#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 +#define BOARD_CAP_RST_GPIO (HPM_GPIO0) +#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOB) +#define BOARD_CAP_RST_GPIO_PIN (9) +#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_B) +#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) +#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOB) +#define BOARD_CAP_INTR_GPIO_PIN (8) +#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_B) #define BOARD_CAP_I2C_SDA_GPIO_INDEX (GPIO_DI_GPIOZ) -#define BOARD_CAP_I2C_SDA_GPIO_PIN (10) +#define BOARD_CAP_I2C_SDA_GPIO_PIN (10) #define BOARD_CAP_I2C_CLK_GPIO_INDEX (GPIO_DI_GPIOZ) -#define BOARD_CAP_I2C_CLK_GPIO_PIN (11) +#define BOARD_CAP_I2C_CLK_GPIO_PIN (11) /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_6 /* align with used pin */ /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX /* gptmr section */ #define BOARD_GPTMR HPM_GPTMR4 @@ -185,36 +199,36 @@ #define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr5 /* gpio section */ -#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_CTRL HPM_GPIO0 #define BOARD_R_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_R_GPIO_PIN 11 -#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_PIN 11 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 #define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_G_GPIO_PIN 12 -#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_PIN 12 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 #define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_B_GPIO_PIN 13 +#define BOARD_B_GPIO_PIN 13 #define BOARD_LED_GPIO_CTRL HPM_GPIO0 #define BOARD_LED_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_LED_GPIO_PIN 12 -#define BOARD_LED_OFF_LEVEL 0 -#define BOARD_LED_ON_LEVEL 1 +#define BOARD_LED_GPIO_PIN 12 +#define BOARD_LED_OFF_LEVEL 0 +#define BOARD_LED_ON_LEVEL 1 #define BOARD_LED_TOGGLE_RGB 1 #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ -#define BOARD_APP_GPIO_PIN 2 +#define BOARD_APP_GPIO_PIN 2 /* pinmux section */ #define USING_GPIO0_FOR_GPIOZ #ifndef USING_GPIO0_FOR_GPIOZ #define BOARD_APP_GPIO_CTRL HPM_BGPIO -#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO #else #define BOARD_APP_GPIO_CTRL HPM_GPIO0 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z #endif /* gpiom section */ @@ -223,23 +237,23 @@ #define BOARD_APP_GPIOM_USING_CTRL_NAME gpiom_core0_fast /* spi section */ -#define BOARD_APP_SPI_BASE HPM_SPI2 +#define BOARD_APP_SPI_BASE HPM_SPI2 #define BOARD_APP_SPI_CLK_NAME clock_spi2 #define BOARD_APP_SPI_IRQ IRQn_SPI2 #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI2_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI2_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PE31 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI2_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI2_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PE31 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* lcd section */ @@ -254,21 +268,21 @@ #define BOARD_PDMA_BASE HPM_PDMA /* i2s section */ -#define BOARD_APP_I2S_BASE HPM_I2S0 -#define BOARD_APP_I2S_DATA_LINE (2U) -#define BOARD_APP_I2S_CLK_NAME clock_i2s0 -#define BOARD_APP_I2S_TX_DMA_REQ HPM_DMA_SRC_I2S0_TX -#define BOARD_APP_I2S_IRQ IRQn_I2S0 -#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 -#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 +#define BOARD_APP_I2S_BASE HPM_I2S0 +#define BOARD_APP_I2S_DATA_LINE (2U) +#define BOARD_APP_I2S_CLK_NAME clock_i2s0 +#define BOARD_APP_I2S_TX_DMA_REQ HPM_DMA_SRC_I2S0_TX +#define BOARD_APP_I2S_IRQ IRQn_I2S0 +#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 +#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 #define BOARD_PDM_SINGLE_CHANNEL_MASK (1U) #define BOARD_PDM_DUAL_CHANNEL_MASK (0x11U) /* enet section */ -#define BOARD_ENET_COUNT (2U) -#define BOARD_ENET_PPS HPM_ENET0 -#define BOARD_ENET_PPS_IDX enet_pps_0 -#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 +#define BOARD_ENET_COUNT (2U) +#define BOARD_ENET_PPS HPM_ENET0 +#define BOARD_ENET_PPS_IDX enet_pps_0 +#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 #define BOARD_ENET_RGMII_PHY_ITF enet_inf_rgmii #define BOARD_ENET_RGMII_RST_GPIO HPM_GPIO0 @@ -280,29 +294,27 @@ #define BOARD_ENET_RGMII_PTP_CLOCK (clock_ptp0) #define BOARD_ENET_RGMII_PPS0_PINOUT (1) -#define BOARD_ENET_RMII_PHY_ITF enet_inf_rmii -#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0 -#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOE -#define BOARD_ENET_RMII_RST_GPIO_PIN (26U) -#define BOARD_ENET_RMII HPM_ENET1 -#define BOARD_ENET_RMII_INT_REF_CLK (1U) -#define BOARD_ENET_RMII_PTP_CLOCK (clock_ptp1) -#define BOARD_ENET_RMII_PPS0_PINOUT (0) +#define BOARD_ENET_RMII_PHY_ITF enet_inf_rmii +#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0 +#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOE +#define BOARD_ENET_RMII_RST_GPIO_PIN (26U) +#define BOARD_ENET_RMII HPM_ENET1 +#define BOARD_ENET_RMII_INT_REF_CLK (1U) +#define BOARD_ENET_RMII_PTP_CLOCK (clock_ptp1) +#define BOARD_ENET_RMII_PPS0_PINOUT (0) /* ADC section */ -#define BOARD_APP_ADC12_NAME "ADC0" -#define BOARD_APP_ADC12_BASE HPM_ADC0 -#define BOARD_APP_ADC12_IRQn IRQn_ADC0 -#define BOARD_APP_ADC12_CH_1 (11U) -#define BOARD_APP_ADC12_CH_2 (10U) -#define BOARD_APP_ADC12_CH_3 (7U) -#define BOARD_APP_ADC12_CLK_NAME (clock_adc0) - -#define BOARD_APP_ADC16_NAME "ADC3" -#define BOARD_APP_ADC16_BASE HPM_ADC3 -#define BOARD_APP_ADC16_IRQn IRQn_ADC3 -#define BOARD_APP_ADC16_CH_1 (2U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc3) +#define BOARD_APP_ADC12_NAME "ADC0" +#define BOARD_APP_ADC12_BASE HPM_ADC0 +#define BOARD_APP_ADC12_IRQn IRQn_ADC0 +#define BOARD_APP_ADC12_CH_1 (11U) +#define BOARD_APP_ADC12_CLK_NAME (clock_adc0) + +#define BOARD_APP_ADC16_NAME "ADC3" +#define BOARD_APP_ADC16_BASE HPM_ADC3 +#define BOARD_APP_ADC16_IRQn IRQn_ADC3 +#define BOARD_APP_ADC16_CH_1 (2U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc3) #define BOARD_APP_ADC12_HW_TRIG_SRC HPM_PWM0 #define BOARD_APP_ADC12_HW_TRGM HPM_TRGM0 @@ -316,57 +328,55 @@ #define BOARD_APP_ADC16_HW_TRGM_OUT_SEQ TRGM_TRGOCFG_ADC3_STRGI #define BOARD_APP_ADC16_HW_TRGM_OUT_PMT TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_APP_ADC12_PMT_TRIG_CH ADC12_CONFIG_TRG0A -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC12_PMT_TRIG_CH ADC12_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* CAN section */ -#define BOARD_APP_CAN_BASE HPM_CAN0 -#define BOARD_APP_CAN_IRQn IRQn_CAN0 - +#define BOARD_APP_CAN_BASE HPM_CAN0 +#define BOARD_APP_CAN_IRQn IRQn_CAN0 /* * timer for board delay */ -#define BOARD_DELAY_TIMER (HPM_GPTMR7) -#define BOARD_DELAY_TIMER_CH 0 +#define BOARD_DELAY_TIMER (HPM_GPTMR7) +#define BOARD_DELAY_TIMER_CH 0 #define BOARD_DELAY_TIMER_CLK_NAME (clock_gptmr7) -#define BOARD_CALLBACK_TIMER (HPM_GPTMR7) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR7 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR7) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR7 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr7) /* SDXC section */ -#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) -#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) -#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (1) -#define BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO (1) -#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (0) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (1) +#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) +#define BOARD_APP_SDCARD_SUPPORT_1V8 (0) +#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (1) +#define BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO (1) +#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (0) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (1) #if defined(BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO) && (BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO == 1) -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN IOC_PAD_PD15 -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_POL 1 /* PIN value 0 means card is inserted */ +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN IOC_PAD_PD15 +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_POL 1 /* PIN value 0 means card is inserted */ #endif #if defined(BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO) && (BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO == 1) -#define BOARD_APP_SDCARD_POWER_SWITCH_PIN IOC_PAD_PC20 -#define BOARD_APP_SDCARD_POWER_SWITCH_PIN_POL 0 /* PIN value 1 means power is supplied */ +#define BOARD_APP_SDCARD_POWER_SWITCH_PIN IOC_PAD_PC20 +#define BOARD_APP_SDCARD_POWER_SWITCH_PIN_POL 0 /* PIN value 1 means power is supplied */ #endif - -#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_EMMC_SUPPORT_3V3 (1) -#define BOARD_APP_EMMC_SUPPORT_1V8 (0) -#define BOARD_APP_EMMC_SUPPORT_4BIT (1) -#define BOARD_APP_EMMC_SUPPORT_POWER_SWITCH (1) -#define BOARD_APP_EMMC_POWER_SWITCH_USING_GPIO (1) -#define BOARD_APP_EMMC_HOST_USING_IRQ (0) +#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_EMMC_SUPPORT_3V3 (1) +#define BOARD_APP_EMMC_SUPPORT_1V8 (0) +#define BOARD_APP_EMMC_SUPPORT_4BIT (1) +#define BOARD_APP_EMMC_SUPPORT_POWER_SWITCH (1) +#define BOARD_APP_EMMC_POWER_SWITCH_USING_GPIO (1) +#define BOARD_APP_EMMC_HOST_USING_IRQ (0) #if defined(BOARD_APP_EMMC_POWER_SWITCH_USING_GPIO) && (BOARD_APP_EMMC_POWER_SWITCH_USING_GPIO == 1) -#define BOARD_APP_EMMC_POWER_SWITCH_PIN IOC_PAD_PC20 -#define BOARD_APP_EMMC_POWER_SWITCH_PIN_POL 0 /* PIN value 1 means power is supplied */ +#define BOARD_APP_EMMC_POWER_SWITCH_PIN IOC_PAD_PC20 +#define BOARD_APP_EMMC_POWER_SWITCH_PIN_POL 0 /* PIN value 1 means power is supplied */ #endif /* USB section */ @@ -389,117 +399,115 @@ /*BLDC pwm*/ /*PWM define*/ -#define BOARD_BLDCPWM HPM_PWM2 -#define BOARD_BLDC_UH_PWM_OUTPIN (0U) -#define BOARD_BLDC_UL_PWM_OUTPIN (1U) -#define BOARD_BLDC_VH_PWM_OUTPIN (2U) -#define BOARD_BLDC_VL_PWM_OUTPIN (3U) -#define BOARD_BLDC_WH_PWM_OUTPIN (4U) -#define BOARD_BLDC_WL_PWM_OUTPIN (5U) -#define BOARD_BLDCPWM_TRGM HPM_TRGM2 -#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM2 -#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) -#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) -#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) -#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) -#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) -#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) -#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) -#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) -#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) +#define BOARD_BLDCPWM HPM_PWM2 +#define BOARD_BLDC_UH_PWM_OUTPIN (0U) +#define BOARD_BLDC_UL_PWM_OUTPIN (1U) +#define BOARD_BLDC_VH_PWM_OUTPIN (2U) +#define BOARD_BLDC_VL_PWM_OUTPIN (3U) +#define BOARD_BLDC_WH_PWM_OUTPIN (4U) +#define BOARD_BLDC_WL_PWM_OUTPIN (5U) +#define BOARD_BLDCPWM_TRGM HPM_TRGM2 +#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM2 +#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) +#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) +#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) +#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) +#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) +#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) +#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) +#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) +#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) /*HALL define*/ -#define BOARD_BLDC_HALL_BASE HPM_HALL2 -#define BOARD_BLDC_HALL_TRGM HPM_TRGM2 -#define BOARD_BLDC_HALL_IRQ IRQn_HALL2 -#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P6 -#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P7 -#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P8 -#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) - - +#define BOARD_BLDC_HALL_BASE HPM_HALL2 +#define BOARD_BLDC_HALL_TRGM HPM_TRGM2 +#define BOARD_BLDC_HALL_IRQ IRQn_HALL2 +#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P6 +#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P7 +#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P8 +#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) /*QEI*/ -#define BOARD_BLDC_QEI_BASE HPM_QEI2 -#define BOARD_BLDC_QEI_IRQ IRQn_QEI2 -#define BOARD_BLDC_QEI_TRGM HPM_TRGM2 -#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 -#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P10 -#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) -#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot2 -#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) +#define BOARD_BLDC_QEI_BASE HPM_QEI2 +#define BOARD_BLDC_QEI_IRQ IRQn_QEI2 +#define BOARD_BLDC_QEI_TRGM HPM_TRGM2 +#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 +#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P10 +#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) +#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot2 +#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) /*HFI define*/ #define MOTOR0_HFI_SPD (0.5) -#define MOTOR0_HFI_KP (40) +#define MOTOR0_HFI_KP (40) /*Timer define*/ -#define BOARD_TMR_1MS HPM_GPTMR2 -#define BOARD_TMR_1MS_CH 0 -#define BOARD_TMR_1MS_CMP 0 -#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 -#define BOARD_TMR_1MS_RELOAD (100000U) +#define BOARD_TMR_1MS HPM_GPTMR2 +#define BOARD_TMR_1MS_CH 0 +#define BOARD_TMR_1MS_CMP 0 +#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 +#define BOARD_TMR_1MS_RELOAD (100000U) -#define BOARD_BLDC_TMR_1MS BOARD_TMR_1MS -#define BOARD_BLDC_TMR_CH BOARD_TMR_1MS_CH -#define BOARD_BLDC_TMR_CMP BOARD_TMR_1MS_CMP -#define BOARD_BLDC_TMR_IRQ BOARD_TMR_1MS_IRQ -#define BOARD_BLDC_TMR_RELOAD BOARD_TMR_1MS_RELOAD +#define BOARD_BLDC_TMR_1MS BOARD_TMR_1MS +#define BOARD_BLDC_TMR_CH BOARD_TMR_1MS_CH +#define BOARD_BLDC_TMR_CMP BOARD_TMR_1MS_CMP +#define BOARD_BLDC_TMR_IRQ BOARD_TMR_1MS_IRQ +#define BOARD_BLDC_TMR_RELOAD BOARD_TMR_1MS_RELOAD /*adc*/ -#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC12 -#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 -#define BOARD_BLDC_ADC_TRIG_FLAG adc12_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (7U) -#define BOARD_BLDC_ADC_CH_V (10U) -#define BOARD_BLDC_ADC_CH_W (11U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC12 +#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 +#define BOARD_BLDC_ADC_TRIG_FLAG adc12_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (7U) +#define BOARD_BLDC_ADC_CH_V (10U) +#define BOARD_BLDC_ADC_CH_W (11U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC12_CONFIG_TRG2A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM2_INPUT_SRC_PWM2_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM2_INPUT_SRC_PWM2_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 /* APP PWM */ -#define BOARD_APP_PWM HPM_PWM2 -#define BOARD_APP_PWM_CLOCK_NAME clock_mot2 -#define BOARD_APP_PWM_OUT1 0 -#define BOARD_APP_PWM_OUT2 1 -#define BOARD_APP_TRGM HPM_TRGM2 -#define BOARD_APP_PWM_IRQ IRQn_PWM2 +#define BOARD_APP_PWM HPM_PWM2 +#define BOARD_APP_PWM_CLOCK_NAME clock_mot2 +#define BOARD_APP_PWM_OUT1 0 +#define BOARD_APP_PWM_OUT2 1 +#define BOARD_APP_TRGM HPM_TRGM2 +#define BOARD_APP_PWM_IRQ IRQn_PWM2 #define BOARD_APP_TRGM_PWM_OUTPUT TRGM_TRGOCFG_PWM_SYNCI /* RGB LED Section */ -#define BOARD_RED_PWM_IRQ IRQn_PWM1 -#define BOARD_RED_PWM HPM_PWM1 -#define BOARD_RED_PWM_OUT 8 -#define BOARD_RED_PWM_CMP 8 +#define BOARD_RED_PWM_IRQ IRQn_PWM1 +#define BOARD_RED_PWM HPM_PWM1 +#define BOARD_RED_PWM_OUT 8 +#define BOARD_RED_PWM_CMP 8 #define BOARD_RED_PWM_CMP_INITIAL_ZERO true -#define BOARD_RED_PWM_CLOCK_NAME clock_mot1 +#define BOARD_RED_PWM_CLOCK_NAME clock_mot1 -#define BOARD_GREEN_PWM_IRQ IRQn_PWM0 -#define BOARD_GREEN_PWM HPM_PWM0 -#define BOARD_GREEN_PWM_OUT 8 -#define BOARD_GREEN_PWM_CMP 8 +#define BOARD_GREEN_PWM_IRQ IRQn_PWM0 +#define BOARD_GREEN_PWM HPM_PWM0 +#define BOARD_GREEN_PWM_OUT 8 +#define BOARD_GREEN_PWM_CMP 8 #define BOARD_GREEN_PWM_CMP_INITIAL_ZERO true -#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot0 +#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot0 -#define BOARD_BLUE_PWM_IRQ IRQn_PWM1 -#define BOARD_BLUE_PWM HPM_PWM1 -#define BOARD_BLUE_PWM_OUT 9 -#define BOARD_BLUE_PWM_CMP 9 +#define BOARD_BLUE_PWM_IRQ IRQn_PWM1 +#define BOARD_BLUE_PWM HPM_PWM1 +#define BOARD_BLUE_PWM_OUT 9 +#define BOARD_BLUE_PWM_CMP 9 #define BOARD_BLUE_PWM_CMP_INITIAL_ZERO true -#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot1 +#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot1 -#define BOARD_RGB_RED 0 +#define BOARD_RGB_RED 0 #define BOARD_RGB_GREEN (BOARD_RGB_RED + 1) #define BOARD_RGB_BLUE (BOARD_RGB_RED + 2) @@ -515,10 +523,20 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR6 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR6 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr6 +#define BOARD_FREERTOS_TIMER HPM_GPTMR6 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR6 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr6 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR6 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR6 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr6 + +/* Tamper Section */ +#define BOARD_TAMP_ACTIVE_CH 8 +#define BOARD_TAMP_LOW_LEVEL_CH 10 #if defined(__cplusplus) extern "C" { @@ -529,6 +547,8 @@ typedef void (*board_timer_cb)(void); void board_init(void); void board_init_console(void); +void board_init_core1(void); + void board_init_uart(UART_Type *ptr); void board_init_i2c(I2C_Type *ptr); void board_init_lcd(void); @@ -593,8 +613,8 @@ void board_init_adc16_pins(void); void board_init_usb_pins(void); void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level); -void board_init_enet_pps_pins(ENET_Type *ptr); -uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); +void board_init_enet_pps_pins(ENET_Type *ptr); +uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); hpm_stat_t board_reset_enet_phy(ENET_Type *ptr); hpm_stat_t board_init_enet_pins(ENET_Type *ptr); hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal); @@ -609,8 +629,8 @@ hpm_stat_t board_init_multiple_enet_clock(void); hpm_stat_t board_reset_multiple_enet_phy(void); hpm_stat_t board_init_enet_phy(ENET_Type *ptr); ENET_Type *board_get_enet_base(uint8_t idx); -uint8_t board_get_enet_phy_itf(uint8_t idx); -void board_get_enet_phy_status(uint8_t idx, void *status); +uint8_t board_get_enet_phy_itf(uint8_t idx); +void board_get_enet_phy_status(uint8_t idx, void *status); #endif /* diff --git a/boards/hpm6750evk2/hpm6750evk2.yaml b/boards/hpm6750evk2/hpm6750evk2.yaml index 14393428d..db4c2ae9e 100644 --- a/boards/hpm6750evk2/hpm6750evk2.yaml +++ b/boards/hpm6750evk2/hpm6750evk2.yaml @@ -15,58 +15,18 @@ board: type: qspi-nor-flash size: 16M feature: - - butn - - sdp - - rng - - rtc - - wdg - - adc - - sdcard - - usb-otg - - dao - - pdm - - vad - - cam - - lcd - - spi - - uart - - can - - i2c - - femc - - gpio - - gpio-led - - gpio-key - - pwm - - pwm-beep - - pwm-rgb-led - - hall - - qei - - motor-control - - audio-codec - - tflm - - multicore - - drv_pllctl - - drv_sysctl - - sdxc - - i2s - - uart_software_rx_idle - - uart_rx_timeout - - uart_software_lin - - ptp - - gpiom - - adc12 - - adc16 - - adc_tempsns - - sw_gm_api - - enet - - enet_pps_pinout - - enet_phy_on_board - - enet_multi_port - - hall-qei - - bldc_smc - - puart - - bldc_hfi - - gpt_pin - - sdram - - acmp - - ptpc + - board_audio_in + - board_audio_out + - board_audio_in_vad + - board_audio_codec + - board_uart_software_rx_idle_pin + - board_gpt_pin + - board_motor_control + - board_pwm_rgb_led + - board_puart_pin + - board_enet_pps_pin + - board_sdcard + - board_sdram + - board_enet_phy + - board_enet_dual_phy + - board_dual_usb diff --git a/boards/hpm6750evk2/pinmux.c b/boards/hpm6750evk2/pinmux.c index 10e6bb467..b12052819 100644 --- a/boards/hpm6750evk2/pinmux.c +++ b/boards/hpm6750evk2/pinmux.c @@ -21,8 +21,8 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_SOC_PY_07; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_SOC_PY_06; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; } else if (ptr == HPM_UART2) { HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_UART2_TXD; HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PE21_FUNC_CTL_UART2_RXD; @@ -30,11 +30,11 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_UART13_RXD; HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_UART13_TXD; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_SOC_PZ_08; - HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_SOC_PZ_09; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; } else if (ptr == HPM_PUART) { - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_PUART_RXD; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_PUART_TXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_PUART_RXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_PUART_TXD; } } @@ -47,11 +47,11 @@ void init_uart_pin_as_gpio(UART_Type *ptr) /* PZ port IO needs to configure BIOC as well */ HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_GPIO_Z_08; - HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; /* PZ port IO needs to configure BIOC as well */ HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_GPIO_Z_09; - HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_SOC_PZ_09; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; } } @@ -95,7 +95,7 @@ void init_lcd_pins(LCDC_Type *ptr) HPM_IOC->PAD[IOC_PAD_PZ00].FUNC_CTL = IOC_PZ00_FUNC_CTL_GPIO_Z_00; HPM_IOC->PAD[IOC_PAD_PZ00].PAD_CTL = IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_PE_SET(1); - HPM_BIOC->PAD[IOC_PAD_PZ00].FUNC_CTL = IOC_PZ00_FUNC_CTL_SOC_PZ_00; + HPM_BIOC->PAD[IOC_PAD_PZ00].FUNC_CTL = BIOC_PZ00_FUNC_CTL_SOC_PZ_00; } void init_cap_pins(void) @@ -273,7 +273,7 @@ void init_gpio_pins(void) HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_SOC_PZ_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_PZ_02; #endif } @@ -299,8 +299,8 @@ void init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) void init_pins(void) { -#ifdef BOARD_CONSOLE_BASE - init_uart_pins(BOARD_CONSOLE_BASE); +#ifdef BOARD_CONSOLE_UART_BASE + init_uart_pins(BOARD_CONSOLE_UART_BASE); #endif init_sdram_pins(); } @@ -367,8 +367,8 @@ void init_dao_pins(void) HPM_IOC->PAD[IOC_PAD_PY08].FUNC_CTL = IOC_PY08_FUNC_CTL_DAOR_P; HPM_IOC->PAD[IOC_PAD_PY09].FUNC_CTL = IOC_PY09_FUNC_CTL_DAOR_N; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY08].FUNC_CTL = IOC_PY08_FUNC_CTL_SOC_PY_08; - HPM_PIOC->PAD[IOC_PAD_PY09].FUNC_CTL = IOC_PY09_FUNC_CTL_SOC_PY_09; + HPM_PIOC->PAD[IOC_PAD_PY08].FUNC_CTL = PIOC_PY08_FUNC_CTL_SOC_PY_08; + HPM_PIOC->PAD[IOC_PAD_PY09].FUNC_CTL = PIOC_PY09_FUNC_CTL_SOC_PY_09; } void init_pdm_pins(void) @@ -376,14 +376,14 @@ void init_pdm_pins(void) HPM_IOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_PDM0_CLK; HPM_IOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_PDM0_D_0; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_SOC_PY_10; - HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_SOC_PY_11; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_SOC_PY_10; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_SOC_PY_11; } void init_vad_pins(void) { - HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_VAD_CLK; - HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_VAD_DAT; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_VAD_CLK; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_VAD_DAT; } void init_cam_pins(void) @@ -391,7 +391,7 @@ void init_cam_pins(void) /* configure rst pin function */ HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_GPIO_Y_05; /* PY port IO needs to configure PIOC */ - HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_SOC_PY_05; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_SOC_PY_05; HPM_IOC->PAD[IOC_PAD_PA10].FUNC_CTL = IOC_PA10_FUNC_CTL_CAM0_XCLK; HPM_IOC->PAD[IOC_PAD_PA11].FUNC_CTL = IOC_PA11_FUNC_CTL_CAM0_PIXCLK; @@ -409,10 +409,10 @@ void init_cam_pins(void) void init_butn_pins(void) { - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_PBUTN; - HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = IOC_PZ03_FUNC_CTL_WBUTN; - HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = IOC_PZ04_FUNC_CTL_PLED; - HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = IOC_PZ05_FUNC_CTL_WLED; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_PBUTN; + HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = BIOC_PZ03_FUNC_CTL_WBUTN; + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_PLED; + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_WLED; } void init_acmp_pins(void) @@ -481,11 +481,7 @@ void init_pwm_pins(PWM_Type *ptr) void init_adc12_pins(void) { - /* ADC0/1/2.VIN7 */ - HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2.VIN10 */ - HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2.VIN11 */ + /* ADC0.VIN11 */ HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; } @@ -625,3 +621,10 @@ void init_enet_pps_pins(void) { HPM_IOC->PAD[IOC_PAD_PF05].FUNC_CTL = IOC_PF05_FUNC_CTL_ETH0_EVTO_0; } + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_TAMP_08 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_TAMP_09; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_TAMP_10; +} diff --git a/boards/hpm6750evk2/pinmux.h b/boards/hpm6750evk2/pinmux.h index f2c5e23ba..5073f3a17 100644 --- a/boards/hpm6750evk2/pinmux.h +++ b/boards/hpm6750evk2/pinmux.h @@ -48,6 +48,7 @@ void init_i2c_pins_as_gpio(I2C_Type *ptr); void init_led_pins_as_gpio(void); void init_trgmux_pins(uint32_t pin); void init_enet_pps_pins(void); +void init_tamper_pins(void); #ifdef __cplusplus } diff --git a/boards/hpm6750evkmini/README_en.md b/boards/hpm6750evkmini/README_en.md index 8cba0e73b..546578ee3 100644 --- a/boards/hpm6750evkmini/README_en.md +++ b/boards/hpm6750evkmini/README_en.md @@ -88,19 +88,16 @@ The HPM6750 is a dual-core flashless MCU running 816Mhz. It has a 2MB continuous | Function | Position | | ------------- | -------- | -| GPTMR2.CAPT_2 | P2[15] | -| GPTMR2.COMP_0 | P2[19] | -| GPTMR2.COMP_1 | P2[22] | +| GPTMR5.CAPT_1 | P1[12] | +| GPTMR5.COMP_0 | P1[31] | +| GPTMR5.COMP_1 | P1[35] | - ADC12 Pin | Function | Position | | -------------------------------- | -------- | | ADC12 Reference Voltage Setting | N/A | -| ADC0/1/2.VINP7 | P2[11] | -| ADC0/1/2.VINP8 | P2[13] | -| ADC0/1/2.VINP9 | P2[15] | -| ADC0/1/2.VINP10 | P2[16] | +| ADC0.VINP14 | P1[33] | - ADC16 Pin @@ -140,7 +137,9 @@ The HPM6750 is a dual-core flashless MCU running 816Mhz. It has a 2MB continuous | ENET0.EVTO1 | P1[12] | | ENET0.EVTO2 | P1[35] | -- UART pin for uart_software_rx_idle sample or uart_rx_timeout sample +- UART13 pin + + The UART13 is used for core1 debug console or some functional testing using UART, such as uart_software_rx_idle, uart_rx_timeout, uart_software_lin, MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. | Function | Position | | ---------- | ------ | @@ -157,6 +156,14 @@ The HPM6750 is a dual-core flashless MCU running 816Mhz. It has a 2MB continuous Refer to section [HPM6750EVKMINI-TO-MOTOR Extension Board ](lab_board_hpm6750evkmini-to-motor-220530RevA) for configuration +- Tamper Pin + +| Function | Pin | Position | Mode | +|----------|--------|--------|----------| +| TAMP.08 | PZ08 | P1[10] | Active Mode | +| TAMP.09 | PZ09 | P1[8] | Active Mode | +| TAMP.10 | PZ10 | P1[22] | Passive Mode | + ## Known Issues - Some samples may enter the trap handler during runtime, with a MCAUSE == 2 (instruction error). This is due to a flaw in ILM, as detailed in the Errata Manual E00001. diff --git a/boards/hpm6750evkmini/README_zh.md b/boards/hpm6750evkmini/README_zh.md index e3af7a59b..4f8b302d6 100644 --- a/boards/hpm6750evkmini/README_zh.md +++ b/boards/hpm6750evkmini/README_zh.md @@ -70,13 +70,6 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | I2C0.SCL | P1[13] | | I2C0.SDA | P1[15] | -- CORE1调试串口引脚: - -| 功能 | 位置 | -| ---------- | ------ | -| UART13.TXD | P1[8] | -| UART13.RXD | P1[10] | - - ACMP引脚 | 功能 | 位置 | @@ -88,19 +81,16 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | 功能 | 位置 | | ------------- | ------ | -| GPTMR2.CAPT_2 | P2[15] | -| GPTMR2.COMP_0 | P2[19] | -| GPTMR2.COMP_1 | P2[22] | +| GPTMR5.CAPT_1 | P1[12] | +| GPTMR5.COMP_0 | P1[31] | +| GPTMR5.COMP_1 | P1[35] | - ADC12引脚 | 功能 | 位置 | | ----------------- | ------ | | ADC12参考电压设置 | 无 | -| ADC0/1/2.VINP7 | P2[11] | -| ADC0/1/2.VINP8 | P2[13] | -| ADC0/1/2.VINP9 | P2[15] | -| ADC0/1/2.VINP10 | P2[16] | +| ADC0.VINP14 | P1[33] | - ADC16引脚 @@ -140,7 +130,9 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M | ENET0.EVTO1 | P1[12] | | ENET0.EVTO2 | P1[35] | -- UART引脚用于uart_software_rx_idle或uart_rx_timeout或uart_lin工程 +- UART13引脚 + + UART13用于CORE1调试串口或一些使用UART的功能测试,例如uart_software_rx_idle,uart_rx_timeout,uart_software_lin,MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 | 功能 | 位置 | | ---------- | ------ | @@ -157,6 +149,14 @@ HPM6750是一款主频达816Mhz的双核微控制器。该芯片拥有最大2M 参考 [HPM6750EVKMINI-TO-MOTOR扩展板章节](lab_board_hpm6750evkmini-to-motor-220530RevA) 进行连接 +- Tamper 接口 + +| 功能 | 引脚 | 位置 | 模式 | +|----------|--------|--------|--------| +| TAMP.08 | PZ08 | P1[10] | 主动模式 | +| TAMP.09 | PZ09 | P1[8] | 主动模式 | +| TAMP.10 | PZ10 | P1[22] | 被动模式 | + ## 已知问题: - 一些例程在运行过程中有可能会进入trap handler,同时mcause为2(指令错误),这是由于ILM的缺陷导致的,详见《勘误手册E00001》。 - 处理办法:将链接脚本中的ILM接口地址改为ILM_SLV地址。 diff --git a/boards/hpm6750evkmini/board.c b/boards/hpm6750evkmini/board.c index 3e81b0368..845e8dd45 100644 --- a/boards/hpm6750evkmini/board.c +++ b/boards/hpm6750evkmini/board.c @@ -96,16 +96,16 @@ void board_init_console(void) /* uart needs to configure pin function before enabling clock, otherwise the level change of uart rx pin when configuring pin function will cause a wrong data to be received. And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t) BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t) BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -239,6 +239,12 @@ void board_init(void) #endif } +void board_init_core1(void) +{ + board_init_console(); + board_init_pmp(); +} + void board_init_sdram_pins(void) { init_sdram_pins(); @@ -944,7 +950,6 @@ void _init_ext_ram(void) femc_sdram_config_t sdram_config = {0}; femc_default_config(HPM_FEMC, &config); - config.dqs = FEMC_DQS_INTERNAL; femc_init(HPM_FEMC, &config); sdram_config.bank_num = FEMC_SDRAM_BANK_NUM_4; @@ -974,7 +979,8 @@ void _init_ext_ram(void) sdram_config.refresh_count = BOARD_SDRAM_REFRESH_COUNT; sdram_config.refresh_in_ms = BOARD_SDRAM_REFRESH_IN_MS; sdram_config.data_width_in_byte = BOARD_SDRAM_DATA_WIDTH_IN_BYTE; - sdram_config.delay_cell_value = 29; + sdram_config.delay_cell_disable = true; + sdram_config.delay_cell_value = 0; femc_config_sdram(HPM_FEMC, femc_clk_in_hz, &sdram_config); } diff --git a/boards/hpm6750evkmini/board.h b/boards/hpm6750evkmini/board.h index 7c3005b35..21903e72f 100644 --- a/boards/hpm6750evkmini/board.h +++ b/boards/hpm6750evkmini/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -21,59 +21,70 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm6750evkmini" +#define BOARD_NAME "hpm6750evkmini" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) #define SEC_CORE_IMG_START ILM_LOCAL_BASE -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART13 +#define BOARD_APP_UART_IRQ IRQn_UART13 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart13 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX #endif /* uart rx idle demo section */ -#define BOARD_UART_IDLE HPM_UART13 -#define BOARD_UART_IDLE_IRQ IRQn_UART13 -#define BOARD_UART_IDLE_CLK_NAME clock_uart13 -#define BOARD_UART_IDLE_TX_DMA_SRC HPM_DMA_SRC_UART13_TX -#define BOARD_UART_IDLE_DMA_SRC HPM_DMA_SRC_UART13_RX - -#define BOARD_UART_IDLE_TRGM HPM_TRGM2 -#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PD19 -#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 -#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM2_OUTPUT_SRC_GPTMR4_IN2 +#define BOARD_UART_IDLE BOARD_APP_UART_BASE +#define BOARD_UART_IDLE_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_IDLE_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_IDLE_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_UART_IDLE_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +#define BOARD_UART_IDLE_TRGM HPM_TRGM2 +#define BOARD_UART_IDLE_TRGM_PIN IOC_PAD_PD19 +#define BOARD_UART_IDLE_TRGM_INPUT_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 +#define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_IN HPM_TRGM2_OUTPUT_SRC_GPTMR4_IN2 #define BOARD_UART_IDLE_TRGM_OUTPUT_GPTMR_SYNCI HPM_TRGM2_OUTPUT_SRC_GPTMR4_SYNCI -#define BOARD_UART_IDLE_GPTMR HPM_GPTMR4 +#define BOARD_UART_IDLE_GPTMR HPM_GPTMR4 #define BOARD_UART_IDLE_GPTMR_CLK_NAME clock_gptmr4 -#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR4 -#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 -#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 +#define BOARD_UART_IDLE_GPTMR_IRQ IRQn_GPTMR4 +#define BOARD_UART_IDLE_GPTMR_CMP_CH 0 +#define BOARD_UART_IDLE_GPTMR_CAP_CH 2 /* uart microros sample section */ -#define BOARD_MICROROS_UART_BASE HPM_UART13 -#define BOARD_MICROROS_UART_IRQ IRQn_UART13 -#define BOARD_MICROROS_UART_CLK_NAME clock_uart13 +#define BOARD_MICROROS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MICROROS_UART_IRQ BOARD_APP_UART_IRQ +#define BOARD_MICROROS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME -/* uart lin sample section */ -#define BOARD_UART_LIN HPM_UART13 -#define BOARD_UART_LIN_IRQ IRQn_UART13 -#define BOARD_UART_LIN_CLK_NAME clock_uart13 -#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOZ -#define BOARD_UART_LIN_TX_PIN (9U) /* PC03 should align with used pin in pinmux configuration */ +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ + +/* uart lin sample section */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOZ +#define BOARD_UART_LIN_TX_PIN (9U) /* PC03 should align with used pin in pinmux configuration */ #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE @@ -81,131 +92,135 @@ #endif #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE +#ifndef BOARD_CONSOLE_UART_BASE #if BOARD_RUNNING_CORE == HPM_CORE0 -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #else -#define BOARD_CONSOLE_BASE HPM_UART13 -#define BOARD_CONSOLE_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_BASE HPM_UART13 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart13 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART13 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART13_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART13_RX #endif #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif -#define BOARD_FREEMASTER_UART_BASE HPM_UART0 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART0 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart0 - /* sdram section */ -#define BOARD_SDRAM_ADDRESS (0x40000000UL) -#define BOARD_SDRAM_SIZE (16*SIZE_1MB) -#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 -#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_16_BITS -#define BOARD_SDRAM_REFRESH_COUNT (4096UL) -#define BOARD_SDRAM_REFRESH_IN_MS (64UL) +#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_SIZE (16 * SIZE_1MB) +#define BOARD_SDRAM_CS FEMC_SDRAM_CS0 +#define BOARD_SDRAM_PORT_SIZE FEMC_SDRAM_PORT_SIZE_16_BITS +#define BOARD_SDRAM_REFRESH_COUNT (4096UL) +#define BOARD_SDRAM_REFRESH_IN_MS (64UL) #define BOARD_SDRAM_DATA_WIDTH_IN_BYTE (2UL) +#define BOARD_FEMC_DQS_FLOATING 1 + /* lcd section */ -#define BOARD_LCD_BASE HPM_LCDC -#define BOARD_LCD_IRQ IRQn_LCDC_D0 -#define BOARD_LCD_POWER_GPIO_BASE HPM_GPIO0 -#define BOARD_LCD_POWER_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_LCD_POWER_GPIO_PIN 12 -#define BOARD_LCD_BACKLIGHT_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_BASE HPM_LCDC +#define BOARD_LCD_IRQ IRQn_LCDC_D0 +#define BOARD_LCD_POWER_GPIO_BASE HPM_GPIO0 +#define BOARD_LCD_POWER_GPIO_INDEX GPIO_DO_GPIOB +#define BOARD_LCD_POWER_GPIO_PIN 12 +#define BOARD_LCD_BACKLIGHT_GPIO_BASE HPM_GPIO0 #define BOARD_LCD_BACKLIGHT_GPIO_INDEX GPIO_DO_GPIOB -#define BOARD_LCD_BACKLIGHT_GPIO_PIN 23 +#define BOARD_LCD_BACKLIGHT_GPIO_PIN 23 /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 -#define BOARD_APP_I2C_IRQ IRQn_I2C0 +#define BOARD_APP_I2C_BASE HPM_I2C0 +#define BOARD_APP_I2C_IRQ IRQn_I2C0 +#define BOARD_APP_I2C_IRQ IRQn_I2C0 #define BOARD_APP_I2C_CLK_NAME clock_i2c0 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C0 -#define BOARD_CAM_I2C_BASE HPM_I2C0 +#define BOARD_CAM_I2C_BASE HPM_I2C0 #define BOARD_CAM_I2C_CLK_NAME clock_i2c0 -#define BOARD_CAP_I2C_BASE (HPM_I2C0) -#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 -#define BOARD_CAP_RST_GPIO (HPM_GPIO0) -#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_RST_GPIO_PIN (9) -#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_B) -#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) -#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_INTR_GPIO_PIN (8) -#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_B) +#define BOARD_CAP_I2C_BASE (HPM_I2C0) +#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 +#define BOARD_CAP_RST_GPIO (HPM_GPIO0) +#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOB) +#define BOARD_CAP_RST_GPIO_PIN (9) +#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_B) +#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) +#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOB) +#define BOARD_CAP_INTR_GPIO_PIN (8) +#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_B) #define BOARD_CAP_I2C_SDA_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_I2C_SDA_GPIO_PIN (10) +#define BOARD_CAP_I2C_SDA_GPIO_PIN (10) #define BOARD_CAP_I2C_CLK_GPIO_INDEX (GPIO_DI_GPIOB) -#define BOARD_CAP_I2C_CLK_GPIO_PIN (11) +#define BOARD_CAP_I2C_CLK_GPIO_PIN (11) /* ACMP desction */ -#define BOARD_ACMP HPM_ACMP -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ IRQn_ACMP_1 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP HPM_ACMP +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ IRQn_ACMP_1 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_6 /* align with used pin */ /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX /* gptmr section */ -#define BOARD_GPTMR HPM_GPTMR2 -#define BOARD_GPTMR_IRQ IRQn_GPTMR2 -#define BOARD_GPTMR_CHANNEL 0 -#define BOARD_GPTMR_DMA_SRC HPM_DMA_SRC_GPTMR2_0 -#define BOARD_GPTMR_CLK_NAME clock_gptmr2 -#define BOARD_GPTMR_PWM HPM_GPTMR2 -#define BOARD_GPTMR_PWM_DMA_SRC HPM_DMA_SRC_GPTMR2_0 -#define BOARD_GPTMR_PWM_CHANNEL 0 -#define BOARD_GPTMR_PWM_CLK_NAME clock_gptmr2 -#define BOARD_GPTMR_PWM_IRQ IRQn_GPTMR2 -#define BOARD_GPTMR_PWM_SYNC HPM_GPTMR2 -#define BOARD_GPTMR_PWM_SYNC_CHANNEL 1 -#define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr2 +#define BOARD_GPTMR HPM_GPTMR5 +#define BOARD_GPTMR_IRQ IRQn_GPTMR5 +#define BOARD_GPTMR_CHANNEL 1 +#define BOARD_GPTMR_DMA_SRC HPM_DMA_SRC_GPTMR5_1 +#define BOARD_GPTMR_CLK_NAME clock_gptmr5 +#define BOARD_GPTMR_PWM HPM_GPTMR5 +#define BOARD_GPTMR_PWM_DMA_SRC HPM_DMA_SRC_GPTMR5_1 +#define BOARD_GPTMR_PWM_CHANNEL 1 +#define BOARD_GPTMR_PWM_CLK_NAME clock_gptmr5 +#define BOARD_GPTMR_PWM_IRQ IRQn_GPTMR5 +#define BOARD_GPTMR_PWM_SYNC HPM_GPTMR5 +#define BOARD_GPTMR_PWM_SYNC_CHANNEL 0 +#define BOARD_GPTMR_PWM_SYNC_CLK_NAME clock_gptmr5 /* gpio section */ -#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_CTRL HPM_GPIO0 #define BOARD_R_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_R_GPIO_PIN 19 -#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_PIN 19 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 #define BOARD_G_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_G_GPIO_PIN 18 -#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_PIN 18 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 #define BOARD_B_GPIO_INDEX GPIO_DI_GPIOB -#define BOARD_B_GPIO_PIN 20 +#define BOARD_B_GPIO_PIN 20 -#define BOARD_LED_GPIO_CTRL BOARD_G_GPIO_CTRL +#define BOARD_LED_GPIO_CTRL BOARD_G_GPIO_CTRL #define BOARD_LED_GPIO_INDEX BOARD_G_GPIO_INDEX -#define BOARD_LED_GPIO_PIN BOARD_G_GPIO_PIN +#define BOARD_LED_GPIO_PIN BOARD_G_GPIO_PIN /* *led Internal pull-up and pull-down resistance direction *The configurations of Rev-A / B boards are different */ #define BOARD_LED_OFF_LEVEL 1 -#define BOARD_LED_ON_LEVEL 0 +#define BOARD_LED_ON_LEVEL 0 #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOZ -#define BOARD_APP_GPIO_PIN 2 +#define BOARD_APP_GPIO_PIN 2 /* pinmux section */ #define USING_GPIO0_FOR_GPIOZ #ifndef USING_GPIO0_FOR_GPIOZ #define BOARD_APP_GPIO_CTRL HPM_BGPIO -#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO #else #define BOARD_APP_GPIO_CTRL HPM_GPIO0 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_Z #endif /* gpiom section */ @@ -214,26 +229,26 @@ #define BOARD_APP_GPIOM_USING_CTRL_NAME gpiom_core0_fast /* spi section */ -#define BOARD_APP_SPI_BASE HPM_SPI2 +#define BOARD_APP_SPI_BASE HPM_SPI2 #define BOARD_APP_SPI_CLK_NAME clock_spi2 #define BOARD_APP_SPI_IRQ IRQn_SPI2 #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI2_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI2_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PB24 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI2_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI2_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PB24 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000007U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00000000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000007U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00000000U) #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) -#define BOARD_FLASH_SIZE (8 << 20) +#define BOARD_FLASH_SIZE (8 << 20) /* lcd section */ @@ -248,36 +263,36 @@ #define BOARD_PDMA_BASE HPM_PDMA /* i2s section */ -#define BOARD_APP_I2S_CLK_NAME clock_i2s1 -#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 -#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 +#define BOARD_APP_I2S_CLK_NAME clock_i2s1 +#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 +#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 #define BOARD_PDM_SINGLE_CHANNEL_MASK (1U) #define BOARD_PDM_DUAL_CHANNEL_MASK (0x11U) /* enet section */ -#define BOARD_ENET_PPS HPM_ENET0 -#define BOARD_ENET_PPS_IDX enet_pps_0 -#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 +#define BOARD_ENET_PPS HPM_ENET0 +#define BOARD_ENET_PPS_IDX enet_pps_0 +#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 -#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0 -#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOD -#define BOARD_ENET_RMII_RST_GPIO_PIN (15U) -#define BOARD_ENET_RMII HPM_ENET1 -#define BOARD_ENET_RMII_INT_REF_CLK (0U) -#define BOARD_ENET_RMII_PTP_CLOCK clock_ptp1 +#define BOARD_ENET_RMII_RST_GPIO HPM_GPIO0 +#define BOARD_ENET_RMII_RST_GPIO_INDEX GPIO_DO_GPIOD +#define BOARD_ENET_RMII_RST_GPIO_PIN (15U) +#define BOARD_ENET_RMII HPM_ENET1 +#define BOARD_ENET_RMII_INT_REF_CLK (0U) +#define BOARD_ENET_RMII_PTP_CLOCK clock_ptp1 /* ADC section */ -#define BOARD_APP_ADC12_NAME "ADC0" -#define BOARD_APP_ADC12_BASE HPM_ADC0 -#define BOARD_APP_ADC12_IRQn IRQn_ADC0 -#define BOARD_APP_ADC12_CH_1 (7U) -#define BOARD_APP_ADC12_CLK_NAME (clock_adc0) - -#define BOARD_APP_ADC16_NAME "ADC3" -#define BOARD_APP_ADC16_IRQn IRQn_ADC3 -#define BOARD_APP_ADC16_BASE HPM_ADC3 -#define BOARD_APP_ADC16_CH_1 (2U) -#define BOARD_APP_ADC16_CLK_NAME (clock_adc3) +#define BOARD_APP_ADC12_NAME "ADC0" +#define BOARD_APP_ADC12_BASE HPM_ADC0 +#define BOARD_APP_ADC12_IRQn IRQn_ADC0 +#define BOARD_APP_ADC12_CH_1 (14U) +#define BOARD_APP_ADC12_CLK_NAME (clock_adc0) + +#define BOARD_APP_ADC16_NAME "ADC3" +#define BOARD_APP_ADC16_IRQn IRQn_ADC3 +#define BOARD_APP_ADC16_BASE HPM_ADC3 +#define BOARD_APP_ADC16_CH_1 (2U) +#define BOARD_APP_ADC16_CLK_NAME (clock_adc3) #define BOARD_APP_ADC12_HW_TRIG_SRC HPM_PWM0 #define BOARD_APP_ADC12_HW_TRGM HPM_TRGM0 @@ -291,58 +306,58 @@ #define BOARD_APP_ADC16_HW_TRGM_OUT_SEQ TRGM_TRGOCFG_ADC3_STRGI #define BOARD_APP_ADC16_HW_TRGM_OUT_PMT TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_APP_ADC12_PMT_TRIG_CH ADC12_CONFIG_TRG0A -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC12_PMT_TRIG_CH ADC12_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* CAN section */ -#define BOARD_APP_CAN_BASE HPM_CAN1 -#define BOARD_APP_CAN_IRQn IRQn_CAN1 +#define BOARD_APP_CAN_BASE HPM_CAN1 +#define BOARD_APP_CAN_IRQn IRQn_CAN1 /* * timer for board delay */ -#define BOARD_DELAY_TIMER (HPM_GPTMR7) -#define BOARD_DELAY_TIMER_CH 0 +#define BOARD_DELAY_TIMER (HPM_GPTMR7) +#define BOARD_DELAY_TIMER_CH 0 #define BOARD_DELAY_TIMER_CLK_NAME (clock_gptmr7) -#define BOARD_CALLBACK_TIMER (HPM_GPTMR7) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR7 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR7) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR7 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr7) /* timer for 1ms*/ -#define BOARD_TMR_1MS HPM_GPTMR2 -#define BOARD_TMR_1MS_CH 0 -#define BOARD_TMR_1MS_CMP 0 -#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 -#define BOARD_TMR_1MS_RELOAD (100000U) +#define BOARD_TMR_1MS HPM_GPTMR2 +#define BOARD_TMR_1MS_CH 0 +#define BOARD_TMR_1MS_CMP 0 +#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 +#define BOARD_TMR_1MS_RELOAD (100000U) /* SDXC section */ -#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) -#define BOARD_APP_SDCARD_SUPPORT_1V8 (1) -#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (0) -#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (1) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (0) +#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) +#define BOARD_APP_SDCARD_SUPPORT_1V8 (1) +#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (0) +#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (1) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (0) #if defined(BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO) && (BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO == 1) -#define BOARD_APP_SDCARD_CARD_DETECTION_GPIO NULL -#define BOARD_APP_SDCARD_CARD_DETECTION_GPIO_INDEX 0 -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_INDEX 0 +#define BOARD_APP_SDCARD_CARD_DETECTION_GPIO NULL +#define BOARD_APP_SDCARD_CARD_DETECTION_GPIO_INDEX 0 +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_INDEX 0 #endif -#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_EMMC_SUPPORT_3V3 (1) -#define BOARD_APP_EMMC_SUPPORT_1V8 (0) -#define BOARD_APP_EMMC_SUPPORT_4BIT (1) -#define BOARD_APP_EMMC_SUPPORT_8BIT (0) -#define BOARD_APP_EMMC_SUPPORT_VOLTAGE_SWITCH (0) +#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_EMMC_SUPPORT_3V3 (1) +#define BOARD_APP_EMMC_SUPPORT_1V8 (0) +#define BOARD_APP_EMMC_SUPPORT_4BIT (1) +#define BOARD_APP_EMMC_SUPPORT_8BIT (0) +#define BOARD_APP_EMMC_SUPPORT_VOLTAGE_SWITCH (0) /* For eMMC device, it is recommended to use GPIO to switch voltage directly */ #define BOARD_APP_EMMC_VOLTAGE_SWITCH_USING_GPIO (1) #if defined(BOARD_APP_EMMC_VOLTAGE_SWITCH_USING_GPIO) && (BOARD_APP_EMMC_VOLTAGE_SWITCH_USING_GPIO == 1) -#define BOARD_APP_EMMC_VSEL_PIN IOC_PAD_PD29 +#define BOARD_APP_EMMC_VSEL_PIN IOC_PAD_PD29 #endif /* USB section */ @@ -355,123 +370,120 @@ #define BOARD_USB0_OC_GPIO_PIN (8) /* APP PWM */ -#define BOARD_APP_PWM HPM_PWM0 -#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 -#define BOARD_APP_PWM_OUT1 4 -#define BOARD_APP_PWM_OUT2 5 -#define BOARD_APP_TRGM HPM_TRGM0 -#define BOARD_APP_PWM_IRQ IRQn_PWM0 +#define BOARD_APP_PWM HPM_PWM0 +#define BOARD_APP_PWM_CLOCK_NAME clock_mot0 +#define BOARD_APP_PWM_OUT1 4 +#define BOARD_APP_PWM_OUT2 5 +#define BOARD_APP_TRGM HPM_TRGM0 +#define BOARD_APP_PWM_IRQ IRQn_PWM0 #define BOARD_APP_TRGM_PWM_OUTPUT TRGM_TRGOCFG_PWM_SYNCI /* RGB LED Section */ -#define BOARD_RED_PWM_IRQ IRQn_PWM1 -#define BOARD_RED_PWM HPM_PWM1 -#define BOARD_RED_PWM_OUT 0 -#define BOARD_RED_PWM_CMP 0 +#define BOARD_RED_PWM_IRQ IRQn_PWM1 +#define BOARD_RED_PWM HPM_PWM1 +#define BOARD_RED_PWM_OUT 0 +#define BOARD_RED_PWM_CMP 0 #define BOARD_RED_PWM_CMP_INITIAL_ZERO true -#define BOARD_RED_PWM_CLOCK_NAME clock_mot1 +#define BOARD_RED_PWM_CLOCK_NAME clock_mot1 -#define BOARD_GREEN_PWM_IRQ IRQn_PWM1 -#define BOARD_GREEN_PWM HPM_PWM1 -#define BOARD_GREEN_PWM_OUT 1 -#define BOARD_GREEN_PWM_CMP 1 +#define BOARD_GREEN_PWM_IRQ IRQn_PWM1 +#define BOARD_GREEN_PWM HPM_PWM1 +#define BOARD_GREEN_PWM_OUT 1 +#define BOARD_GREEN_PWM_CMP 1 #define BOARD_GREEN_PWM_CMP_INITIAL_ZERO true -#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot1 +#define BOARD_GREEN_PWM_CLOCK_NAME clock_mot1 -#define BOARD_BLUE_PWM_IRQ IRQn_PWM0 -#define BOARD_BLUE_PWM HPM_PWM0 -#define BOARD_BLUE_PWM_OUT 7 -#define BOARD_BLUE_PWM_CMP 7 +#define BOARD_BLUE_PWM_IRQ IRQn_PWM0 +#define BOARD_BLUE_PWM HPM_PWM0 +#define BOARD_BLUE_PWM_OUT 7 +#define BOARD_BLUE_PWM_CMP 7 #define BOARD_BLUE_PWM_CMP_INITIAL_ZERO true -#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot0 +#define BOARD_BLUE_PWM_CLOCK_NAME clock_mot0 -#define BOARD_RGB_RED 0 +#define BOARD_RGB_RED 0 #define BOARD_RGB_GREEN (BOARD_RGB_RED + 1) #define BOARD_RGB_BLUE (BOARD_RGB_RED + 2) /* Beep Section */ -#define BOARD_BEEP_PWM HPM_PWM3 -#define BOARD_BEEP_PWM_OUT 4 +#define BOARD_BEEP_PWM HPM_PWM3 +#define BOARD_BEEP_PWM_OUT 4 #define BOARD_BEEP_PWM_CLOCK_NAME clock_mot3 /*BLDC pwm*/ /*PWM define*/ -#define BOARD_BLDCPWM HPM_PWM1 -#define BOARD_BLDC_UH_PWM_OUTPIN (2U) -#define BOARD_BLDC_UL_PWM_OUTPIN (3U) -#define BOARD_BLDC_VH_PWM_OUTPIN (4U) -#define BOARD_BLDC_VL_PWM_OUTPIN (5U) -#define BOARD_BLDC_WH_PWM_OUTPIN (6U) -#define BOARD_BLDC_WL_PWM_OUTPIN (7U) -#define BOARD_BLDCPWM_TRGM HPM_TRGM1 -#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM1 -#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) -#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) -#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) -#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) -#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) -#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) -#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) -#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) -#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) +#define BOARD_BLDCPWM HPM_PWM1 +#define BOARD_BLDC_UH_PWM_OUTPIN (2U) +#define BOARD_BLDC_UL_PWM_OUTPIN (3U) +#define BOARD_BLDC_VH_PWM_OUTPIN (4U) +#define BOARD_BLDC_VL_PWM_OUTPIN (5U) +#define BOARD_BLDC_WH_PWM_OUTPIN (6U) +#define BOARD_BLDC_WL_PWM_OUTPIN (7U) +#define BOARD_BLDCPWM_TRGM HPM_TRGM1 +#define BOARD_BLDCAPP_PWM_IRQ IRQn_PWM1 +#define BOARD_BLDCPWM_CMP_INDEX_0 (0U) +#define BOARD_BLDCPWM_CMP_INDEX_1 (1U) +#define BOARD_BLDCPWM_CMP_INDEX_2 (2U) +#define BOARD_BLDCPWM_CMP_INDEX_3 (3U) +#define BOARD_BLDCPWM_CMP_INDEX_4 (4U) +#define BOARD_BLDCPWM_CMP_INDEX_5 (5U) +#define BOARD_BLDCPWM_CMP_INDEX_6 (6U) +#define BOARD_BLDCPWM_CMP_INDEX_7 (7U) +#define BOARD_BLDCPWM_CMP_TRIG_CMP (20U) /*HALL define*/ -#define BOARD_BLDC_HALL_BASE HPM_HALL2 -#define BOARD_BLDC_HALL_TRGM HPM_TRGM2 -#define BOARD_BLDC_HALL_IRQ IRQn_HALL2 -#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 -#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P10 -#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P11 -#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) - - +#define BOARD_BLDC_HALL_BASE HPM_HALL2 +#define BOARD_BLDC_HALL_TRGM HPM_TRGM2 +#define BOARD_BLDC_HALL_IRQ IRQn_HALL2 +#define BOARD_BLDC_HALL_TRGM_HALL_U_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P9 +#define BOARD_BLDC_HALL_TRGM_HALL_V_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P10 +#define BOARD_BLDC_HALL_TRGM_HALL_W_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P11 +#define BOARD_BLDC_HALL_MOTOR_PHASE_COUNT_PER_REV (1000U) /*QEI*/ -#define BOARD_BLDC_QEI_BASE HPM_QEI2 -#define BOARD_BLDC_QEI_IRQ IRQn_QEI2 -#define BOARD_BLDC_QEI_TRGM HPM_TRGM2 -#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P6 -#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P7 -#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) -#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot2 -#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) +#define BOARD_BLDC_QEI_BASE HPM_QEI2 +#define BOARD_BLDC_QEI_IRQ IRQn_QEI2 +#define BOARD_BLDC_QEI_TRGM HPM_TRGM2 +#define BOARD_BLDC_QEI_TRGM_QEI_A_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P6 +#define BOARD_BLDC_QEI_TRGM_QEI_B_SRC HPM_TRGM2_INPUT_SRC_TRGM2_P7 +#define BOARD_BLDC_QEI_MOTOR_PHASE_COUNT_PER_REV (16U) +#define BOARD_BLDC_QEI_CLOCK_SOURCE clock_mot2 +#define BOARD_BLDC_QEI_FOC_PHASE_COUNT_PER_REV (4000U) /*Timer define*/ -#define BOARD_TMR_1MS HPM_GPTMR2 -#define BOARD_TMR_1MS_CH 0 -#define BOARD_TMR_1MS_CMP 0 -#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 -#define BOARD_TMR_1MS_RELOAD (100000U) +#define BOARD_TMR_1MS HPM_GPTMR2 +#define BOARD_TMR_1MS_CH 0 +#define BOARD_TMR_1MS_CMP 0 +#define BOARD_TMR_1MS_IRQ IRQn_GPTMR2 +#define BOARD_TMR_1MS_RELOAD (100000U) -#define BOARD_BLDC_TMR_1MS BOARD_TMR_1MS -#define BOARD_BLDC_TMR_CH BOARD_TMR_1MS_CH -#define BOARD_BLDC_TMR_CMP BOARD_TMR_1MS_CMP -#define BOARD_BLDC_TMR_IRQ BOARD_TMR_1MS_IRQ -#define BOARD_BLDC_TMR_RELOAD BOARD_TMR_1MS_RELOAD +#define BOARD_BLDC_TMR_1MS BOARD_TMR_1MS +#define BOARD_BLDC_TMR_CH BOARD_TMR_1MS_CH +#define BOARD_BLDC_TMR_CMP BOARD_TMR_1MS_CMP +#define BOARD_BLDC_TMR_IRQ BOARD_TMR_1MS_IRQ +#define BOARD_BLDC_TMR_RELOAD BOARD_TMR_1MS_RELOAD /*adc*/ -#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC12 -#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 -#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 -#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 -#define BOARD_BLDC_ADC_TRIG_FLAG adc12_event_trig_complete - -#define BOARD_BLDC_ADC_CH_U (1U) -#define BOARD_BLDC_ADC_CH_V (2U) -#define BOARD_BLDC_ADC_CH_W (3U) -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 -#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) +#define BOARD_BLDC_ADC_MODULE ADCX_MODULE_ADC12 +#define BOARD_BLDC_ADC_U_BASE HPM_ADC0 +#define BOARD_BLDC_ADC_V_BASE HPM_ADC1 +#define BOARD_BLDC_ADC_W_BASE HPM_ADC2 +#define BOARD_BLDC_ADC_TRIG_FLAG adc12_event_trig_complete + +#define BOARD_BLDC_ADC_CH_U (1U) +#define BOARD_BLDC_ADC_CH_V (2U) +#define BOARD_BLDC_ADC_CH_W (3U) +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 +#define BOARD_BLDC_ADC_PMT_DMA_SIZE_IN_4BYTES (ADC_SOC_PMT_MAX_DMA_BUFF_LEN_IN_4BYTES) #define BOARD_BLDC_ADC_TRG ADC12_CONFIG_TRG1A -#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) -#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) -#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM1_INPUT_SRC_PWM1_CH8REF -#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A -#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 - +#define BOARD_BLDC_ADC_PREEMPT_TRIG_LEN (1U) +#define BOARD_BLDC_PWM_TRIG_CMP_INDEX (8U) +#define BOARD_BLDC_TRIGMUX_IN_NUM HPM_TRGM1_INPUT_SRC_PWM1_CH8REF +#define BOARD_BLDC_TRG_NUM TRGM_TRGOCFG_ADCX_PTRGI0A +#define BOARD_BLDC_ADC_IRQn IRQn_ADC0 #define BOARD_CPU_FREQ (648000000UL) @@ -485,15 +497,24 @@ #endif /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR4 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR4 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr4 - +#define BOARD_FREERTOS_TIMER HPM_GPTMR4 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR4 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr4 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR4 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR4 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr4 #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE 0 #endif +/* Tamper Section */ +#define BOARD_TAMP_ACTIVE_CH 8 +#define BOARD_TAMP_LOW_LEVEL_CH 10 + #if defined(__cplusplus) extern "C" { #endif /* __cplusplus */ @@ -503,6 +524,8 @@ typedef void (*board_timer_cb)(void); void board_init(void); void board_init_console(void); +void board_init_core1(void); + void board_init_uart(UART_Type *ptr); void board_init_i2c(I2C_Type *ptr); void board_init_lcd(void); @@ -569,8 +592,8 @@ void board_init_adc16_pins(void); void board_init_usb_pins(void); void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level); -void board_init_enet_pps_pins(ENET_Type *ptr); -uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); +void board_init_enet_pps_pins(ENET_Type *ptr); +uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); hpm_stat_t board_reset_enet_phy(ENET_Type *ptr); hpm_stat_t board_init_enet_pins(ENET_Type *ptr); hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal); diff --git a/boards/hpm6750evkmini/hpm6750evkmini.yaml b/boards/hpm6750evkmini/hpm6750evkmini.yaml index e9402e002..9b24418d1 100644 --- a/boards/hpm6750evkmini/hpm6750evkmini.yaml +++ b/boards/hpm6750evkmini/hpm6750evkmini.yaml @@ -15,56 +15,19 @@ board: type: qspi-nor-flash size: 8M feature: - - butn - - sdp - - rng - - rtc - - wdg - - adc - - sdcard - - usb-otg - - dao - - pdm - - vad - - cam - - lcd - - spi - - uart - - can - - i2c - - femc - - pwm - - pwm-rgb-led - - pwm-beep - - gpio - - gpio-led - - gpio-key - - wifi-rt007-spi - - tflm - - multicore - - drv_pllctl - - drv_sysctl - - dual-i2c - - sdxc - - i2s - - uart_software_rx_idle - - uart_rx_timeout - - uart_software_lin - - ptp - - gpiom - - adc12 - - adc16 - - adc_tempsns - - motor-control - - enet - - enet_pps_pinout - - sw_gm_api - - i2s_pinout - - hall-qei - - qei - - bldc_smc - - puart - - gpt_pin - - sdram - - acmp - - ptpc + - board_audio_in + - board_audio_out + - board_audio_in_vad + - board_uart_software_rx_idle_pin + - board_gpt_pin + - board_motor_control + - board_gpio_led + - board_gpio_key + - board_pwm_rgb_led + - board_puart_pin + - board_enet_pps_pin + - board_sdcard + - board_sdram + - board_i2s_pin + excluded_samples: + - samples/motor_ctrl/bldc_hfi diff --git a/boards/hpm6750evkmini/pinmux.c b/boards/hpm6750evkmini/pinmux.c index 7ad1dfbe5..eca3ef072 100644 --- a/boards/hpm6750evkmini/pinmux.c +++ b/boards/hpm6750evkmini/pinmux.c @@ -21,8 +21,8 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_UART0_RXD; HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_UART0_TXD; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_SOC_PY_07; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_SOC_PY_06; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; } else if (ptr == HPM_UART6) { HPM_IOC->PAD[IOC_PAD_PE27].FUNC_CTL = IOC_PE27_FUNC_CTL_UART6_RXD; HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PE28_FUNC_CTL_UART6_TXD; @@ -33,17 +33,17 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_UART13_RXD; HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_UART13_TXD; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_SOC_PZ_08; - HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_SOC_PZ_09; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; } else if (ptr == HPM_UART14) { HPM_IOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_UART14_RXD; HPM_IOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_UART14_TXD; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = IOC_PZ10_FUNC_CTL_SOC_PZ_10; - HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = IOC_PZ11_FUNC_CTL_SOC_PZ_11; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_SOC_PZ_10; + HPM_BIOC->PAD[IOC_PAD_PZ11].FUNC_CTL = BIOC_PZ11_FUNC_CTL_SOC_PZ_11; } else if (ptr == HPM_PUART) { - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_PUART_RXD; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_PUART_TXD; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_PUART_RXD; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_PUART_TXD; } } @@ -63,11 +63,11 @@ void init_uart_pin_as_gpio(UART_Type *ptr) /* PZ port IO needs to configure BIOC as well */ HPM_IOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_GPIO_Z_08; - HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = IOC_PZ08_FUNC_CTL_SOC_PZ_08; + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_SOC_PZ_08; /* PZ port IO needs to configure BIOC as well */ HPM_IOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_GPIO_Z_09; - HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = IOC_PZ09_FUNC_CTL_SOC_PZ_09; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_SOC_PZ_09; } } @@ -266,7 +266,7 @@ void init_gpio_pins(void) HPM_IOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_GPIO_Z_02; HPM_IOC->PAD[IOC_PAD_PZ02].PAD_CTL = pad_ctl; /* PZ port IO needs to configure BIOC as well */ - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_SOC_PZ_02; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_SOC_PZ_02; #endif } @@ -312,21 +312,21 @@ void init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) void init_pins(void) { -#ifdef BOARD_CONSOLE_BASE - init_uart_pins(BOARD_CONSOLE_BASE); +#ifdef BOARD_CONSOLE_UART_BASE + init_uart_pins(BOARD_CONSOLE_UART_BASE); #endif init_sdram_pins(); } void init_gptmr_pins(GPTMR_Type *ptr) { - if (ptr == HPM_GPTMR2) { - /* TMR2 capture 0 */ - HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PE23_FUNC_CTL_GPTMR2_CAPT_0; - /* TMR2 compare 0 */ - HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PE18_FUNC_CTL_GPTMR2_COMP_0; - /* TMR2 compare 1*/ - HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PE16_FUNC_CTL_GPTMR2_COMP_1; + if (ptr == HPM_GPTMR5) { + /* TMR5 capture 0 */ + HPM_IOC->PAD[IOC_PAD_PF06].FUNC_CTL = IOC_PF06_FUNC_CTL_GPTMR5_CAPT_1; + /* TMR5 compare 0 */ + HPM_IOC->PAD[IOC_PAD_PF04].FUNC_CTL = IOC_PF04_FUNC_CTL_GPTMR5_COMP_0; + /* TMR5 compare 1*/ + HPM_IOC->PAD[IOC_PAD_PF09].FUNC_CTL = IOC_PF09_FUNC_CTL_GPTMR5_COMP_1; } } @@ -365,14 +365,14 @@ void init_pdm_pins(void) HPM_IOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_PDM0_CLK; HPM_IOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_PDM0_D_0; /* PY port IO needs to configure PIOC as well */ - HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_SOC_PY_10; - HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_SOC_PY_11; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_SOC_PY_10; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_SOC_PY_11; } void init_vad_pins(void) { - HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = IOC_PY10_FUNC_CTL_VAD_CLK; - HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = IOC_PY11_FUNC_CTL_VAD_DAT; + HPM_PIOC->PAD[IOC_PAD_PY10].FUNC_CTL = PIOC_PY10_FUNC_CTL_VAD_CLK; + HPM_PIOC->PAD[IOC_PAD_PY11].FUNC_CTL = PIOC_PY11_FUNC_CTL_VAD_DAT; } void init_cam_pins(CAM_Type *ptr) @@ -395,10 +395,10 @@ void init_cam_pins(CAM_Type *ptr) void init_butn_pins(void) { - HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = IOC_PZ02_FUNC_CTL_PBUTN; - HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = IOC_PZ03_FUNC_CTL_WBUTN; - HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = IOC_PZ04_FUNC_CTL_PLED; - HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = IOC_PZ05_FUNC_CTL_WLED; + HPM_BIOC->PAD[IOC_PAD_PZ02].FUNC_CTL = BIOC_PZ02_FUNC_CTL_PBUTN; + HPM_BIOC->PAD[IOC_PAD_PZ03].FUNC_CTL = BIOC_PZ03_FUNC_CTL_WBUTN; + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_PLED; + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_WLED; } void init_acmp_pins(void) @@ -452,14 +452,8 @@ void init_pwm_pins(PWM_Type *ptr) void init_adc12_pins(void) { - /* ADC0/1/2/.VINP7 */ - HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2/.VINP8 */ - HPM_IOC->PAD[IOC_PAD_PE22].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2/.VINP9 */ - HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - /* ADC0/1/2/.VINP10 */ - HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + /* ADC0.VINP14 */ + HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; } void init_adc16_pins(void) @@ -606,3 +600,10 @@ void init_enet_pps_pins(void) HPM_IOC->PAD[IOC_PAD_PF06].FUNC_CTL = IOC_PF06_FUNC_CTL_ETH0_EVTO_1; HPM_IOC->PAD[IOC_PAD_PF09].FUNC_CTL = IOC_PF09_FUNC_CTL_ETH0_EVTO_2; } + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ08].FUNC_CTL = BIOC_PZ08_FUNC_CTL_TAMP_08 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ09].FUNC_CTL = BIOC_PZ09_FUNC_CTL_TAMP_09; + HPM_BIOC->PAD[IOC_PAD_PZ10].FUNC_CTL = BIOC_PZ10_FUNC_CTL_TAMP_10; +} diff --git a/boards/hpm6750evkmini/pinmux.h b/boards/hpm6750evkmini/pinmux.h index 541694826..abe8c7a63 100644 --- a/boards/hpm6750evkmini/pinmux.h +++ b/boards/hpm6750evkmini/pinmux.h @@ -54,6 +54,7 @@ void init_led_pins_as_pwm(void); void init_led_pins_as_gpio(void); void init_trgmux_pins(uint32_t pin); void init_enet_pps_pins(void); +void init_tamper_pins(void); #ifdef __cplusplus } diff --git a/boards/hpm6800evk/README_en.md b/boards/hpm6800evk/README_en.md index 36abd47fc..c52e4f679 100644 --- a/boards/hpm6800evk/README_en.md +++ b/boards/hpm6800evk/README_en.md @@ -2,7 +2,7 @@ ## Overview -The HPM6800 is a dual-core flashless MCU running 600Mhz. It has a 1MB continuous on-chip ram. Also, it provides various memory interfaces, including SDRAM, Quad SPI NOR Flash, SD/eMMC. It integrates rich audio and video interfaces, including LCD, pixel DMA, camera, and I2S audio interfaces. +The HPM6800 is a single-core flashless MCU running 600Mhz. It has a 1MB continuous on-chip ram. Also, it provides various memory interfaces, including SDRAM, Quad SPI NOR Flash, SD/eMMC. It integrates rich audio and video interfaces, including LCD, pixel DMA, camera, and I2S audio interfaces. ![hpm6800evk](doc/hpm6800evk.png "hpm6800evk") @@ -10,9 +10,9 @@ The HPM6800 is a dual-core flashless MCU running 600Mhz. It has a 1MB continuous - HPM6800 MCU (600MHz, 1MB SRAM) - Onboard Memory - - 256MB SDRAM + - 512MB SDRAM (DDR3L 16bits) - 16MB Quad SPI NOR Flash - - 8GB eMMC + - 16GB eMMC - Display & Camera - LCD connector - MIPI-DSI @@ -72,13 +72,31 @@ Note: User should short VCCQ and 1.8V pin for eMMC testing - UART0 Pin: -The UART0 pin leads to two positions: +The UART0 use for debugger console: -| Function | Pin | Position2 | +| Function | Pin | Position | | -------- | ---- | ----------| | UART0.TX | PA00 | DEBUGUART0 | | UART0.RX | PA01 | DEBUGUART0 | +- UART3 Pin: + + The UART3 is used for some functional testing using UART, such as MICROROS_UART, USB_CDC_ACM_UART, MODBUS_RTU etc. + +| Function | Pin | Position | +| -------- | ---- | ----------| +| UART3.TX | PE15 | P2[8] | +| UART3.RX | PE14 | P2[10] | + +- PUART Pin: + + The PUART is used for low power mode testing, such as wakeup, etc. + +| Function | Pin | Position | +| -------- | ---- | --------- | +| PUART.TX | PY00 | P2[32] | +| PUART.RX | PY01 | P2[29] | + - SPI Pin: | Function | Pin | Position | @@ -141,3 +159,11 @@ The UART0 pin leads to two positions: | MCAN3.TXD | PD15 | U25[1] | CAN.H J13[3] | | MCAN3.RXD | PD14 | U25[4] | CAN.L J13[2] | | MCAN3.STBY | PD13 | U25[8] | | + +- Tamper Pin + +| Function | Pin | Position | Mode | +|----------|--------|--------|----------| +| TAMP.04 | PZ04 | P2[35] | Active Mode | +| TAMP.05 | PZ05 | P2[38] | Active Mode | +| TAMP.06 | PZ06 | P2[37] | Passive Mode | diff --git a/boards/hpm6800evk/README_zh.md b/boards/hpm6800evk/README_zh.md index 86125c156..3e3e828da 100644 --- a/boards/hpm6800evk/README_zh.md +++ b/boards/hpm6800evk/README_zh.md @@ -2,7 +2,7 @@ ## 概述 -HPM6800是一款主频达816MHz的双核微控制器。该芯片拥有最大1M字节的连续片上RAM,并集成了丰富的存储接口,如SDRAM,Quad SPI NOR flash, SD/eMMC卡。同时它也提供多种音视频接口包括LCD显示,像素DMA,摄像头以及I2S音频接口。 +HPM6800是一款主频达600MHz的单核微控制器。该芯片拥有最大1M字节的连续片上RAM,并集成了丰富的存储接口,如SDRAM,Quad SPI NOR flash, SD/eMMC卡。同时它也提供多种音视频接口包括LCD显示,像素DMA,摄像头以及I2S音频接口。 ![hpm6800evk](doc/hpm6800evk.png "hpm6800evk") @@ -10,9 +10,9 @@ HPM6800是一款主频达816MHz的双核微控制器。该芯片拥有最大1M - HPM6800 微控制器 (主频600Mhz, 1M片上SRAM) - 板载存储 - - 256MB SDRAM + - 512MB SDRAM (DDR3L 16bits) - 16MB Quad SPI NOR Flash - - 8GB eMMC + - 16GB eMMC - 显示/摄像头 - LCD接口 - MIPI-DSI @@ -73,13 +73,31 @@ HPM6800是一款主频达816MHz的双核微控制器。该芯片拥有最大1M - UART0串口引脚: - UART0的引脚引出至两个位置: + UART0用于调试控制台串口。 | 功能 | 引脚 | 位置 | | -------- | ---- | --------- | | UART0.TX | PA00 | DEBUGUART0 | | UART0.RX | PA01 | DEBUGUART0 | +- UART3串口引脚: + + UART3用于一些使用UART的功能测试,例如MICROROS_UART,USB_CDC_ACM_UART, MODBUS_RTU等。 + +| 功能 | 引脚 | 位置 | +| -------- | ---- | --------- | +| UART3.TX | PE15 | P2[8] | +| UART3.RX | PE14 | P2[10] | + +- PUART串口引脚: + + PUART用于低功耗测试,例如唤醒等。 + +| 功能 | 引脚 | 位置 | +| -------- | ---- | --------- | +| PUART.TX | PY00 | P2[32] | +| PUART.RX | PY01 | P2[29] | + - SPI引脚: | 功能 | 引脚 | 位置 | @@ -142,3 +160,11 @@ HPM6800是一款主频达816MHz的双核微控制器。该芯片拥有最大1M | MCAN3.TXD | PD15 | U25[1] | CAN.H J13[3] | | MCAN3.RXD | PD14 | U25[4] | CAN.L J13[2] | | MCAN3.STBY | PD13 | U25[8] | | + +- Tamper 接口 + +| 功能 | 引脚 | 位置 | 模式 | +|----------|--------|--------|---------| +| TAMP.04 | PZ04 | P2[35] | 主动模式 | +| TAMP.05 | PZ05 | P2[38] | 主动模式 | +| TAMP.06 | PZ06 | P2[37] | 被动模式 | diff --git a/boards/hpm6800evk/board.c b/boards/hpm6800evk/board.c index b6e5899b8..65aa765fc 100644 --- a/boards/hpm6800evk/board.c +++ b/boards/hpm6800evk/board.c @@ -100,16 +100,16 @@ void board_init_console(void) * uart rx pin when configuring pin function will cause a wrong data to be received. * And a uart rx dma request will be generated by default uart fifo dma trigger level. */ - init_uart_pins((UART_Type *) BOARD_CONSOLE_BASE); + init_uart_pins((UART_Type *) BOARD_CONSOLE_UART_BASE); /* Configure the UART clock to 24MHz */ - clock_set_source_divider(BOARD_CONSOLE_CLK_NAME, clk_src_osc24m, 1U); - clock_add_to_group(BOARD_CONSOLE_CLK_NAME, 0); + clock_set_source_divider(BOARD_CONSOLE_UART_CLK_NAME, clk_src_osc24m, 1U); + clock_add_to_group(BOARD_CONSOLE_UART_CLK_NAME, 0); cfg.type = BOARD_CONSOLE_TYPE; - cfg.base = (uint32_t) BOARD_CONSOLE_BASE; - cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_CLK_NAME); - cfg.baudrate = BOARD_CONSOLE_BAUDRATE; + cfg.base = (uint32_t) BOARD_CONSOLE_UART_BASE; + cfg.src_freq_in_hz = clock_get_frequency(BOARD_CONSOLE_UART_CLK_NAME); + cfg.baudrate = BOARD_CONSOLE_UART_BAUDRATE; if (status_success != console_init(&cfg)) { /* failed to initialize debug console */ @@ -495,6 +495,8 @@ void board_init_clock(void) clock_add_to_group(clock_eth0, 0); clock_add_to_group(clock_ffa, 0); + clock_add_to_group(clock_tsns, 0); + board_init_display_system_clock(); /* Connect Group0 to CPU0 */ @@ -580,6 +582,10 @@ uint32_t board_init_uart_clock(UART_Type *ptr) clock_set_source_divider(clock_uart2, clk_src_osc24m, 1); clock_add_to_group(clock_uart2, 0); freq = clock_get_frequency(clock_uart2); + } else if (ptr == HPM_UART3) { + clock_set_source_divider(clock_uart3, clk_src_osc24m, 1); + clock_add_to_group(clock_uart3, 0); + freq = clock_get_frequency(clock_uart3); } else { /* Not supported */ } @@ -1001,7 +1007,7 @@ void init_ddr2_800(void) | (15UL << 12) | (50UL << 16) | (10UL << 22) - | (60 << 26); + | (60UL << 26); HPM_DDRPHY->DTPR1 = (2UL << 0) | (31UL << 5) | (80UL << 11) @@ -1160,6 +1166,8 @@ void board_init_usb_pins(void) { init_usb_pins(); usb_hcd_set_power_ctrl_polarity(BOARD_USB, true); + /* Wait USB_PWR pin control vbus power stable. Time depend on decoupling capacitor, you can decrease or increase this time */ + board_delay_ms(100); } void board_usb_vbus_ctrl(uint8_t usb_index, uint8_t level) @@ -1402,23 +1410,3 @@ uint32_t board_init_adc16_clock(ADC16_Type *ptr, bool clk_src_ahb) return freq; } - -uint32_t board_init_sadc_clock(SDADC_Type *ptr, bool clk_src_ahb) -{ - uint32_t freq = 0; - - if (ptr == HPM_ADC1) { - if (clk_src_ahb) { - /* Configure the ADC clock from AXI (@200MHz by default)*/ - clock_set_adc_source(clock_adc1, clk_adc_src_ahb0); - } else { - /* Configure the ADC clock from pll1_clk1 divided by 2 (@200MHz by default) */ - clock_set_adc_source(clock_adc1, clk_adc_src_ana1); - clock_set_source_divider(clock_ana1, clk_src_pll1_clk0, 4U); - } - - freq = clock_get_frequency(clock_adc1); - } - - return freq; -} diff --git a/boards/hpm6800evk/board.h b/boards/hpm6800evk/board.h index e60d6438b..112256f34 100644 --- a/boards/hpm6800evk/board.h +++ b/boards/hpm6800evk/board.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 HPMicro + * Copyright (c) 2023-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -21,133 +21,145 @@ #include "hpm_debug_console.h" #endif -#define BOARD_NAME "hpm6800evk" +#define BOARD_NAME "hpm6800evk" #define BOARD_UF2_SIGNATURE (0x0A4D5048UL) /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA -#define BOARD_APP_XDMA_IRQ IRQn_XDMA -#define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA_IRQ IRQn_XDMA +#define BOARD_APP_HDMA_IRQ IRQn_HDMA +#define BOARD_APP_DMAMUX HPM_DMAMUX #define TEST_DMA_CONTROLLER HPM_HDMA -#define TEST_DMA_IRQ IRQn_HDMA +#define TEST_DMA_IRQ IRQn_HDMA -/* uart section */ #ifndef BOARD_RUNNING_CORE #define BOARD_RUNNING_CORE HPM_CORE0 #endif + +/* uart section */ #ifndef BOARD_APP_UART_BASE -#define BOARD_APP_UART_BASE HPM_UART0 -#define BOARD_APP_UART_IRQ IRQn_UART0 -#else -#ifndef BOARD_APP_UART_IRQ -#warning no IRQ specified for application uart -#endif +#define BOARD_APP_UART_BASE HPM_UART3 +#define BOARD_APP_UART_IRQ IRQn_UART3 +#define BOARD_APP_UART_BAUDRATE (115200UL) +#define BOARD_APP_UART_CLK_NAME clock_uart3 +#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART3_RX +#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART3_TX #endif -#define BOARD_APP_UART_BAUDRATE (115200UL) -#define BOARD_APP_UART_CLK_NAME clock_uart0 -#define BOARD_APP_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX -#define BOARD_APP_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +/* uart lin sample section */ +#define BOARD_UART_LIN BOARD_APP_UART_BASE +#define BOARD_UART_LIN_IRQ BOARD_APP_UART_IRQ +#define BOARD_UART_LIN_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_UART_LIN_TX_PORT GPIO_DI_GPIOE +#define BOARD_UART_LIN_TX_PIN (15U) /* PE15 should align with used pin in pinmux configuration */ + #if !defined(CONFIG_NDEBUG_CONSOLE) || !CONFIG_NDEBUG_CONSOLE #ifndef BOARD_CONSOLE_TYPE #define BOARD_CONSOLE_TYPE CONSOLE_TYPE_UART #endif - #if BOARD_CONSOLE_TYPE == CONSOLE_TYPE_UART -#ifndef BOARD_CONSOLE_BASE -#if BOARD_RUNNING_CORE == HPM_CORE0 -#define BOARD_CONSOLE_BASE HPM_UART0 -#define BOARD_CONSOLE_CLK_NAME clock_uart0 -#else -#define BOARD_CONSOLE_BASE HPM_UART3 -#define BOARD_CONSOLE_CLK_NAME clock_uart3 -#endif +#ifndef BOARD_CONSOLE_UART_BASE +#define BOARD_CONSOLE_UART_BASE HPM_UART0 +#define BOARD_CONSOLE_UART_CLK_NAME clock_uart0 +#define BOARD_CONSOLE_UART_IRQ IRQn_UART0 +#define BOARD_CONSOLE_UART_TX_DMA_REQ HPM_DMA_SRC_UART0_TX +#define BOARD_CONSOLE_UART_RX_DMA_REQ HPM_DMA_SRC_UART0_RX #endif -#define BOARD_CONSOLE_BAUDRATE (115200UL) +#define BOARD_CONSOLE_UART_BAUDRATE (115200UL) #endif #endif -#define BOARD_FREEMASTER_UART_BASE HPM_UART0 -#define BOARD_FREEMASTER_UART_IRQ IRQn_UART0 -#define BOARD_FREEMASTER_UART_CLK_NAME clock_uart0 - /* uart microros sample section */ -#define BOARD_MICROROS_UART_BASE HPM_UART2 -#define BOARD_MICROROS_UART_IRQ IRQn_UART2 -#define BOARD_MICROROS_UART_CLK_NAME clock_uart2 +#define BOARD_MICROROS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MICROROS_UART_IRQ BOARD_APP_UART_IRQ +#define BOARD_MICROROS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME + +/* rtthread-nano finsh section */ +#define BOARD_RT_CONSOLE_BASE BOARD_CONSOLE_UART_BASE + +/* usb cdc acm uart section */ +#define BOARD_USB_CDC_ACM_UART BOARD_APP_UART_BASE +#define BOARD_USB_CDC_ACM_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_USB_CDC_ACM_UART_TX_DMA_SRC BOARD_APP_UART_TX_DMA_REQ +#define BOARD_USB_CDC_ACM_UART_RX_DMA_SRC BOARD_APP_UART_RX_DMA_REQ + +/* modbus sample section */ +#define BOARD_MODBUS_UART_BASE BOARD_APP_UART_BASE +#define BOARD_MODBUS_UART_CLK_NAME BOARD_APP_UART_CLK_NAME +#define BOARD_MODBUS_UART_RX_DMA_REQ BOARD_APP_UART_RX_DMA_REQ +#define BOARD_MODBUS_UART_TX_DMA_REQ BOARD_APP_UART_TX_DMA_REQ /* lin section */ -#define BOARD_LIN HPM_LIN0 -#define BOARD_LIN_CLK_NAME clock_lin0 -#define BOARD_LIN_IRQ IRQn_LIN0 -#define BOARD_LIN_BAUDRATE (19200U) +#define BOARD_LIN HPM_LIN0 +#define BOARD_LIN_CLK_NAME clock_lin0 +#define BOARD_LIN_IRQ IRQn_LIN0 +#define BOARD_LIN_BAUDRATE (19200U) /* nor flash section */ #define BOARD_FLASH_BASE_ADDRESS (0x80000000UL) -#define BOARD_FLASH_SIZE (16 * SIZE_1MB) +#define BOARD_FLASH_SIZE (16 * SIZE_1MB) /* i2c section */ -#define BOARD_APP_I2C_BASE HPM_I2C1 -#define BOARD_APP_I2C_IRQ IRQn_I2C1 -#define BOARD_APP_I2C_CLK_NAME clock_i2c1 -#define BOARD_APP_I2C_DMA HPM_HDMA -#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX -#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C1 +#define BOARD_APP_I2C_BASE HPM_I2C1 +#define BOARD_APP_I2C_IRQ IRQn_I2C1 +#define BOARD_APP_I2C_CLK_NAME clock_i2c1 +#define BOARD_APP_I2C_DMA HPM_HDMA +#define BOARD_APP_I2C_DMAMUX HPM_DMAMUX +#define BOARD_APP_I2C_DMA_SRC HPM_DMA_SRC_I2C1 #define BOARD_APP_I2C_DMAMUX_CH DMAMUX_MUXCFG_HDMA_MUX0 /* cam */ -#define BOARD_CAM_I2C_BASE HPM_I2C0 +#define BOARD_CAM_I2C_BASE HPM_I2C0 #define BOARD_CAM_I2C_CLK_NAME clock_i2c0 #define BOARD_SUPPORT_CAM_RESET #define BOARD_SUPPORT_CAM_PWDN -#define BOARD_CAM_RST_GPIO_CTRL HPM_GPIO0 -#define BOARD_CAM_RST_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_CAM_RST_GPIO_PIN 22 -#define BOARD_CAM_PWDN_GPIO_CTRL HPM_GPIO0 +#define BOARD_CAM_RST_GPIO_CTRL HPM_GPIO0 +#define BOARD_CAM_RST_GPIO_INDEX GPIO_DI_GPIOA +#define BOARD_CAM_RST_GPIO_PIN 22 +#define BOARD_CAM_PWDN_GPIO_CTRL HPM_GPIO0 #define BOARD_CAM_PWDN_GPIO_INDEX GPIO_DI_GPIOA -#define BOARD_CAM_PWDN_GPIO_PIN 21 +#define BOARD_CAM_PWDN_GPIO_PIN 21 /* touch panel */ -#define BOARD_CAP_I2C_BASE (HPM_I2C0) -#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 -#define BOARD_CAP_RST_GPIO (HPM_GPIO0) -#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOY) -#define BOARD_CAP_RST_GPIO_PIN (7) -#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_Y) -#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) -#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOY) -#define BOARD_CAP_INTR_GPIO_PIN (6) -#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_Y) -#define BOARD_CAP_I2C_GPIO HPM_GPIO0 +#define BOARD_CAP_I2C_BASE (HPM_I2C0) +#define BOARD_CAP_I2C_CLK_NAME clock_i2c0 +#define BOARD_CAP_RST_GPIO (HPM_GPIO0) +#define BOARD_CAP_RST_GPIO_INDEX (GPIO_DI_GPIOY) +#define BOARD_CAP_RST_GPIO_PIN (7) +#define BOARD_CAP_RST_GPIO_IRQ (IRQn_GPIO0_Y) +#define BOARD_CAP_INTR_GPIO (HPM_GPIO0) +#define BOARD_CAP_INTR_GPIO_INDEX (GPIO_DI_GPIOY) +#define BOARD_CAP_INTR_GPIO_PIN (6) +#define BOARD_CAP_INTR_GPIO_IRQ (IRQn_GPIO0_Y) +#define BOARD_CAP_I2C_GPIO HPM_GPIO0 #define BOARD_CAP_I2C_SDA_GPIO_INDEX (GPIO_DI_GPIOF) -#define BOARD_CAP_I2C_SDA_GPIO_PIN (9) +#define BOARD_CAP_I2C_SDA_GPIO_PIN (9) #define BOARD_CAP_I2C_CLK_GPIO_INDEX (GPIO_DI_GPIOF) -#define BOARD_CAP_I2C_CLK_GPIO_PIN (8) +#define BOARD_CAP_I2C_CLK_GPIO_PIN (8) /* i2s section */ -#define BOARD_APP_I2S_BASE HPM_I2S3 -#define BOARD_APP_I2S_DATA_LINE (2U) -#define BOARD_APP_I2S_CLK_NAME clock_i2s3 -#define BOARD_APP_I2S_TX_DMA_REQ HPM_DMA_SRC_I2S3_TX -#define BOARD_APP_I2S_IRQ IRQn_I2S3 -#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 -#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 +#define BOARD_APP_I2S_BASE HPM_I2S3 +#define BOARD_APP_I2S_DATA_LINE (2U) +#define BOARD_APP_I2S_CLK_NAME clock_i2s3 +#define BOARD_APP_I2S_TX_DMA_REQ HPM_DMA_SRC_I2S3_TX +#define BOARD_APP_I2S_IRQ IRQn_I2S3 +#define BOARD_APP_AUDIO_CLK_SRC clock_source_pll3_clk0 +#define BOARD_APP_AUDIO_CLK_SRC_NAME clk_pll3clk0 #define BOARD_PDM_SINGLE_CHANNEL_MASK (0x02U) #define BOARD_PDM_DUAL_CHANNEL_MASK (0x22U) /* i2c for i2s codec section */ -#define BOARD_CODEC_I2C_BASE HPM_I2C3 +#define BOARD_CODEC_I2C_BASE HPM_I2C3 #define BOARD_CODEC_I2C_CLK_NAME clock_i2c3 /* dma section */ -#define BOARD_APP_XDMA HPM_XDMA -#define BOARD_APP_HDMA HPM_HDMA +#define BOARD_APP_XDMA HPM_XDMA +#define BOARD_APP_HDMA HPM_HDMA #define BOARD_APP_XDMA_IRQ IRQn_XDMA #define BOARD_APP_HDMA_IRQ IRQn_HDMA -#define BOARD_APP_DMAMUX HPM_DMAMUX +#define BOARD_APP_DMAMUX HPM_DMAMUX /* gptmr section */ #define BOARD_GPTMR HPM_GPTMR2 @@ -168,10 +180,10 @@ #define USING_GPIO0_FOR_GPIOZ #ifndef USING_GPIO0_FOR_GPIOZ #define BOARD_APP_GPIO_CTRL HPM_BGPIO -#define BOARD_APP_GPIO_IRQ IRQn_BGPIO +#define BOARD_APP_GPIO_IRQ IRQn_BGPIO #else #define BOARD_APP_GPIO_CTRL HPM_GPIO0 -#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_F +#define BOARD_APP_GPIO_IRQ IRQn_GPIO0_F #endif /* gpiom section */ @@ -182,7 +194,7 @@ * in errata, for gpiom, setting the ASSIGN register of GPIOF is invalid. * so need to configure GPIOE to make it effective at the same time. */ -#define BOARD_LED_GPIOM_GPIO_INDEX GPIO_DI_GPIOE +#define BOARD_LED_GPIOM_GPIO_INDEX GPIO_DI_GPIOE /* spi section */ #define BOARD_APP_SPI_BASE HPM_SPI3 @@ -191,20 +203,17 @@ #define BOARD_APP_SPI_SCLK_FREQ (20000000UL) #define BOARD_APP_SPI_ADDR_LEN_IN_BYTES (1U) #define BOARD_APP_SPI_DATA_LEN_IN_BITS (8U) -#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI3_RX -#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI3_TX -#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 -#define BOARD_SPI_CS_PIN IOC_PAD_PE04 -#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) - -/* mtimer section */ -#define BOARD_MCHTMR_FREQ_IN_HZ (1000000UL) +#define BOARD_APP_SPI_RX_DMA HPM_DMA_SRC_SPI3_RX +#define BOARD_APP_SPI_TX_DMA HPM_DMA_SRC_SPI3_TX +#define BOARD_SPI_CS_GPIO_CTRL HPM_GPIO0 +#define BOARD_SPI_CS_PIN IOC_PAD_PE04 +#define BOARD_SPI_CS_ACTIVE_LEVEL (0U) /* Flash section */ -#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) -#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) -#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) +#define BOARD_APP_XPI_NOR_XPI_BASE (HPM_XPI0) +#define BOARD_APP_XPI_NOR_CFG_OPT_HDR (0xfcf90001U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT0 (0x00000005U) +#define BOARD_APP_XPI_NOR_CFG_OPT_OPT1 (0x00001000U) /* ADC section */ #define BOARD_APP_ADC16_NAME "ADC0" @@ -213,70 +222,70 @@ #define BOARD_APP_ADC16_CH_1 (8U) #define BOARD_APP_ADC16_CLK_NAME (clock_adc0) -#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A +#define BOARD_APP_ADC16_PMT_TRIG_CH ADC16_CONFIG_TRG0A /* CAN section */ -#define BOARD_APP_CAN_BASE HPM_MCAN3 -#define BOARD_APP_CAN_IRQn IRQn_CAN3 +#define BOARD_APP_CAN_BASE HPM_MCAN3 +#define BOARD_APP_CAN_IRQn IRQn_MCAN3 /* * timer for board delay */ -#define BOARD_DELAY_TIMER (HPM_GPTMR3) -#define BOARD_DELAY_TIMER_CH 0 +#define BOARD_DELAY_TIMER (HPM_GPTMR3) +#define BOARD_DELAY_TIMER_CH 0 #define BOARD_DELAY_TIMER_CLK_NAME (clock_gptmr3) -#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) -#define BOARD_CALLBACK_TIMER_CH 1 -#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 +#define BOARD_CALLBACK_TIMER (HPM_GPTMR3) +#define BOARD_CALLBACK_TIMER_CH 1 +#define BOARD_CALLBACK_TIMER_IRQ IRQn_GPTMR3 #define BOARD_CALLBACK_TIMER_CLK_NAME (clock_gptmr3) #define BOARD_CPU_FREQ (500000000UL) /* LED */ -#define BOARD_R_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_CTRL HPM_GPIO0 #define BOARD_R_GPIO_INDEX GPIO_DI_GPIOF -#define BOARD_R_GPIO_PIN 1 -#define BOARD_G_GPIO_CTRL HPM_GPIO0 +#define BOARD_R_GPIO_PIN 1 +#define BOARD_G_GPIO_CTRL HPM_GPIO0 #define BOARD_G_GPIO_INDEX GPIO_DI_GPIOF -#define BOARD_G_GPIO_PIN 2 -#define BOARD_B_GPIO_CTRL HPM_GPIO0 +#define BOARD_G_GPIO_PIN 2 +#define BOARD_B_GPIO_CTRL HPM_GPIO0 #define BOARD_B_GPIO_INDEX GPIO_DI_GPIOF -#define BOARD_B_GPIO_PIN 5 +#define BOARD_B_GPIO_PIN 5 -#define BOARD_RGB_RED 0 +#define BOARD_RGB_RED 0 #define BOARD_RGB_GREEN (BOARD_RGB_RED + 1) #define BOARD_RGB_BLUE (BOARD_RGB_RED + 2) -#define BOARD_LED_GPIO_CTRL BOARD_G_GPIO_CTRL +#define BOARD_LED_GPIO_CTRL BOARD_G_GPIO_CTRL #define BOARD_LED_GPIO_INDEX BOARD_G_GPIO_INDEX -#define BOARD_LED_GPIO_PIN BOARD_G_GPIO_PIN +#define BOARD_LED_GPIO_PIN BOARD_G_GPIO_PIN -#define BOARD_LED_OFF_LEVEL 0 -#define BOARD_LED_ON_LEVEL !BOARD_LED_OFF_LEVEL +#define BOARD_LED_OFF_LEVEL 0 +#define BOARD_LED_ON_LEVEL !BOARD_LED_OFF_LEVEL #define BOARD_LED_TOGGLE_RGB 1 /* Key */ #define BOARD_APP_GPIO_INDEX GPIO_DI_GPIOF -#define BOARD_APP_GPIO_PIN 6 +#define BOARD_APP_GPIO_PIN 6 /* ACMP desction */ -#define BOARD_ACMP 0 -#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 -#define BOARD_ACMP_IRQ 0 -#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ +#define BOARD_ACMP 0 +#define BOARD_ACMP_CHANNEL ACMP_CHANNEL_CHN1 +#define BOARD_ACMP_IRQ 0 +#define BOARD_ACMP_PLUS_INPUT ACMP_INPUT_DAC_OUT /* use internal DAC */ #define BOARD_ACMP_MINUS_INPUT ACMP_INPUT_ANALOG_6 /* align with used pin */ -#define BOARD_GWC_BASE HPM_GWC0 -#define BOARD_GWC_FUNC_IRQ IRQn_GWCK0_FUNC -#define BOARD_GWC_ERR_IRQ IRQn_GWCK0_ERR -#define BOARD_GWC_PIXEL_WIDTH 1920 +#define BOARD_GWC_BASE HPM_GWC0 +#define BOARD_GWC_FUNC_IRQ IRQn_GWCK0_FUNC +#define BOARD_GWC_ERR_IRQ IRQn_GWCK0_ERR +#define BOARD_GWC_PIXEL_WIDTH 1920 #define BOARD_GWC_PIXEL_HEIGHT 1080 /* lcd section */ #define BOARD_LCD_BASE HPM_LCDC #define BOARD_LCD_IRQ IRQn_LCDC -#define clock_display clock_lcd0 +#define clock_display clock_lcd0 #ifndef BOARD_LCD_WIDTH #define BOARD_LCD_WIDTH PANEL_SIZE_WIDTH @@ -302,47 +311,52 @@ #define BOARD_USB HPM_USB0 /* FreeRTOS Definitions */ -#define BOARD_FREERTOS_TIMER HPM_GPTMR2 -#define BOARD_FREERTOS_TIMER_CHANNEL 1 -#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR2 -#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr2 - +#define BOARD_FREERTOS_TIMER HPM_GPTMR2 +#define BOARD_FREERTOS_TIMER_CHANNEL 1 +#define BOARD_FREERTOS_TIMER_IRQ IRQn_GPTMR2 +#define BOARD_FREERTOS_TIMER_CLK_NAME clock_gptmr2 + +/* Threadx Definitions */ +#define BOARD_THREADX_TIMER HPM_GPTMR2 +#define BOARD_THREADX_TIMER_CHANNEL 1 +#define BOARD_THREADX_TIMER_IRQ IRQn_GPTMR2 +#define BOARD_THREADX_TIMER_CLK_NAME clock_gptmr2 /* SDXC section */ -#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) -#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) -#define BOARD_APP_SDCARD_SUPPORT_1V8 (1) -#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) -#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) -#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (1) -#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (1) - -#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (1) -#define BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO (1) -#define BOARD_APP_SDCARD_VOLTAGE_SWITCH_USING_GPIO (1) +#define BOARD_APP_SDCARD_SDXC_BASE (HPM_SDXC1) +#define BOARD_APP_SDCARD_SUPPORT_3V3 (1) +#define BOARD_APP_SDCARD_SUPPORT_1V8 (1) +#define BOARD_APP_SDCARD_SUPPORT_4BIT (1) +#define BOARD_APP_SDCARD_SUPPORT_CARD_DETECTION (1) +#define BOARD_APP_SDCARD_SUPPORT_POWER_SWITCH (1) +#define BOARD_APP_SDCARD_SUPPORT_VOLTAGE_SWITCH (1) + +#define BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO (1) +#define BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO (1) +#define BOARD_APP_SDCARD_VOLTAGE_SWITCH_USING_GPIO (1) #if BOARD_APP_SDCARD_CARD_DETECTION_USING_GPIO -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN IOC_PAD_PD05 -#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_POL (1) /* pin value 0 means card was detected*/ +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN IOC_PAD_PD05 +#define BOARD_APP_SDCARD_CARD_DETECTION_PIN_POL (1) /* pin value 0 means card was detected*/ #endif #ifdef BOARD_APP_SDCARD_POWER_SWITCH_USING_GPIO -#define BOARD_APP_SDCARD_POWER_SWITCH_PIN IOC_PAD_PD07 +#define BOARD_APP_SDCARD_POWER_SWITCH_PIN IOC_PAD_PD07 #endif #ifdef BOARD_APP_SDCARD_VOLTAGE_SWITCH_USING_GPIO -#define BOARD_APP_SDCARD_VSEL_PIN IOC_PAD_PD12 +#define BOARD_APP_SDCARD_VSEL_PIN IOC_PAD_PD12 #endif -#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC0) -#define BOARD_APP_EMMC_SUPPORT_3V3 (0) -#define BOARD_APP_EMMC_SUPPORT_1V8 (1) -#define BOARD_APP_EMMC_SUPPORT_4BIT (1) -#define BOARD_APP_EMMC_SUPPORT_8BIT (1) -#define BOARD_APP_EMMC_SUPPORT_DS (1) -#define BOARD_APP_EMMC_HOST_USING_IRQ (0) +#define BOARD_APP_EMMC_SDXC_BASE (HPM_SDXC0) +#define BOARD_APP_EMMC_SUPPORT_3V3 (0) +#define BOARD_APP_EMMC_SUPPORT_1V8 (1) +#define BOARD_APP_EMMC_SUPPORT_4BIT (1) +#define BOARD_APP_EMMC_SUPPORT_8BIT (1) +#define BOARD_APP_EMMC_SUPPORT_DS (1) +#define BOARD_APP_EMMC_HOST_USING_IRQ (0) /* enet section */ -#define BOARD_ENET_COUNT (1U) -#define BOARD_ENET_PPS HPM_ENET0 -#define BOARD_ENET_PPS_IDX enet_pps_0 -#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 +#define BOARD_ENET_COUNT (1U) +#define BOARD_ENET_PPS HPM_ENET0 +#define BOARD_ENET_PPS_IDX enet_pps_0 +#define BOARD_ENET_PPS_PTP_CLOCK clock_ptp0 #define BOARD_ENET_RGMII_PHY_ITF enet_inf_rgmii #define BOARD_ENET_RGMII_RST_GPIO HPM_GPIO0 @@ -355,17 +369,20 @@ #define BOARD_ENET_RGMII_PPS0_PINOUT (1) /* dram section */ -#define DDR_TYPE_DDR2 (0U) -#define DDR_TYPE_DDR3L (1U) -#define BOARD_DDR_TYPE DDR_TYPE_DDR3L +#define DDR_TYPE_DDR2 (0U) +#define DDR_TYPE_DDR3L (1U) +#define BOARD_DDR_TYPE DDR_TYPE_DDR3L -#define BOARD_SDRAM_ADDRESS (0x40000000UL) +#define BOARD_SDRAM_ADDRESS (0x40000000UL) #if (BOARD_DDR_TYPE == DDR_TYPE_DDR2) -#define BOARD_SDRAM_SIZE (256UL * 1024UL * 1024UL) +#define BOARD_SDRAM_SIZE (256UL * 1024UL * 1024UL) #else -#define BOARD_SDRAM_SIZE (512UL * 1024UL * 1024UL) +#define BOARD_SDRAM_SIZE (512UL * 1024UL * 1024UL) #endif +/* Tamper Section */ +#define BOARD_TAMP_ACTIVE_CH 4 +#define BOARD_TAMP_LOW_LEVEL_CH 6 #if defined(__cplusplus) extern "C" { @@ -398,8 +415,8 @@ void board_init_clock(void); uint32_t board_init_spi_clock(SPI_Type *ptr); uint32_t board_init_can_clock(MCAN_Type *ptr); -void board_init_enet_pps_pins(ENET_Type *ptr); -uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); +void board_init_enet_pps_pins(ENET_Type *ptr); +uint8_t board_get_enet_dma_pbl(ENET_Type *ptr); hpm_stat_t board_reset_enet_phy(ENET_Type *ptr); hpm_stat_t board_init_enet_pins(ENET_Type *ptr); hpm_stat_t board_init_enet_rmii_reference_clock(ENET_Type *ptr, bool internal); @@ -443,7 +460,6 @@ uint32_t board_config_i2s_clock(I2S_Type *ptr, uint32_t sample_rate); void board_init_adc16_pins(void); uint32_t board_init_adc16_clock(ADC16_Type *ptr, bool clk_src_ahb); -uint32_t board_init_sadc_clock(SDADC_Type *ptr, bool clk_src_ahb); void board_init_cam_pins(void); void board_write_cam_rst(uint8_t state); diff --git a/boards/hpm6800evk/hpm6800evk.yaml b/boards/hpm6800evk/hpm6800evk.yaml index 8ab947404..5ede10901 100644 --- a/boards/hpm6800evk/hpm6800evk.yaml +++ b/boards/hpm6800evk/hpm6800evk.yaml @@ -15,39 +15,11 @@ board: type: qspi-nor-flash size: 16M feature: - - lcd - - cam - - spi - - sdp - - rng - - uart - - i2c - - gpio - - sdxc - - dmav2 - - ewdg - - mcan - - crc - - audio-codec - - i2s - - dao - - pdm - - ptp - - gpiom - - enet - - enet_pps_pinout - - enet_phy_on_board - - gwc - - adc16 - - gpu - - smix - - rtc - - usb-otg - - gpt_pin - - mipi_csi - - mipi_dsi - - sdram - - sdcard - - ffa - - tsns - - ptpc + - board_audio_in + - board_audio_out + - board_audio_codec + - board_gpt_pin + - board_enet_pps_pin + - board_enet_phy + - board_sdcard + - board_sdram diff --git a/boards/hpm6800evk/pinmux.c b/boards/hpm6800evk/pinmux.c index 3557467ec..ea24a7b6d 100644 --- a/boards/hpm6800evk/pinmux.c +++ b/boards/hpm6800evk/pinmux.c @@ -23,23 +23,37 @@ void init_uart_pins(UART_Type *ptr) HPM_IOC->PAD[IOC_PAD_PE14].FUNC_CTL = IOC_PE14_FUNC_CTL_UART3_RXD; HPM_IOC->PAD[IOC_PAD_PE15].FUNC_CTL = IOC_PE15_FUNC_CTL_UART3_TXD; } else if (ptr == HPM_PUART) { - HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = IOC_PY00_FUNC_CTL_PURT_TXD; - HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = IOC_PY01_FUNC_CTL_PURT_RXD; + HPM_PIOC->PAD[IOC_PAD_PY00].FUNC_CTL = PIOC_PY00_FUNC_CTL_PURT_TXD; + HPM_PIOC->PAD[IOC_PAD_PY01].FUNC_CTL = PIOC_PY01_FUNC_CTL_PURT_RXD; } else { ; } } +/* for uart_lin case, need to configure pin as gpio to sent break signal */ +void init_uart_pin_as_gpio(UART_Type *ptr) +{ + /* pull-up */ + uint32_t pad_ctl = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1); + + if (ptr == HPM_UART3) { + HPM_IOC->PAD[IOC_PAD_PE14].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PE15].PAD_CTL = pad_ctl; + HPM_IOC->PAD[IOC_PAD_PE14].FUNC_CTL = IOC_PE14_FUNC_CTL_GPIO_E_14; + HPM_IOC->PAD[IOC_PAD_PE15].FUNC_CTL = IOC_PE15_FUNC_CTL_GPIO_E_15; + } +} + void init_cap_pins(void) { /* CAP_INT */ HPM_IOC->PAD[IOC_PAD_PY06].PAD_CTL = IOC_PAD_PAD_CTL_PE_MASK; HPM_IOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_GPIO_Y_06; - HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = IOC_PY06_FUNC_CTL_SOC_PY_06; + HPM_PIOC->PAD[IOC_PAD_PY06].FUNC_CTL = PIOC_PY06_FUNC_CTL_SOC_PY_06; /* CAP_RST */ HPM_IOC->PAD[IOC_PAD_PY07].PAD_CTL = IOC_PAD_PAD_CTL_PE_MASK; HPM_IOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_GPIO_Y_07; - HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = IOC_PY07_FUNC_CTL_SOC_PY_07; + HPM_PIOC->PAD[IOC_PAD_PY07].FUNC_CTL = PIOC_PY07_FUNC_CTL_SOC_PY_07; } void init_i2c_pins_as_gpio(I2C_Type *ptr) @@ -124,10 +138,10 @@ void init_gpio_pins(void) /* configure pad setting: pull enable and pull up, schmitt trigger enable */ /* enable schmitt trigger to eliminate jitter of pin used as button */ HPM_IOC->PAD[IOC_PAD_PF06].FUNC_CTL = IOC_PF06_FUNC_CTL_GPIO_F_06; - HPM_IOC->PAD[IOC_PAD_PF06].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_HYS_MASK; + HPM_IOC->PAD[IOC_PAD_PF06].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_HYS_MASK | IOC_PAD_PAD_CTL_PRS_SET(11); HPM_IOC->PAD[IOC_PAD_PF07].FUNC_CTL = IOC_PF07_FUNC_CTL_GPIO_F_07; - HPM_IOC->PAD[IOC_PAD_PF07].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_HYS_MASK; + HPM_IOC->PAD[IOC_PAD_PF07].PAD_CTL = IOC_PAD_PAD_CTL_PE_SET(1) | IOC_PAD_PAD_CTL_PS_SET(1) | IOC_PAD_PAD_CTL_HYS_MASK | IOC_PAD_PAD_CTL_PRS_SET(11); } void init_spi_pins(SPI_Type *ptr) @@ -152,8 +166,8 @@ void init_spi_pins_with_gpio_as_cs(SPI_Type *ptr) void init_pins(void) { -#ifdef BOARD_CONSOLE_BASE - init_uart_pins(BOARD_CONSOLE_BASE); +#ifdef BOARD_CONSOLE_UART_BASE + init_uart_pins(BOARD_CONSOLE_UART_BASE); #endif } @@ -252,7 +266,7 @@ void init_sdxc_clk_data_pins(SDXC_Type *ptr, uint32_t width, bool is_1v8) #define SDXC_PIN_SETTING_COMMON (IOC_PAD_PAD_CTL_PE_SET(1) \ | IOC_PAD_PAD_CTL_SPD_SET(3) \ | IOC_PAD_PAD_CTL_SR_SET(1)) -#define SDXC_PIN_SETTING (IOC_PAD_PAD_CTL_DS_SET(3) \ +#define SDXC_PIN_SETTING (IOC_PAD_PAD_CTL_DS_SET(7) \ | SDXC_PIN_SETTING_COMMON \ | IOC_PAD_PAD_CTL_PS_SET(1) \ | IOC_PAD_PAD_CTL_PRS_SET(3)) @@ -317,9 +331,9 @@ void init_usb_pins(void) void init_can_pins(MCAN_Type *ptr) { if (ptr == HPM_MCAN3) { - HPM_IOC->PAD[IOC_PAD_PD15].FUNC_CTL = IOC_PD15_FUNC_CTL_CAN3_TXD; - HPM_IOC->PAD[IOC_PAD_PD14].FUNC_CTL = IOC_PD14_FUNC_CTL_CAN3_RXD; - HPM_IOC->PAD[IOC_PAD_PD13].FUNC_CTL = IOC_PD13_FUNC_CTL_CAN3_STBY; + HPM_IOC->PAD[IOC_PAD_PD15].FUNC_CTL = IOC_PD15_FUNC_CTL_MCAN3_TXD; + HPM_IOC->PAD[IOC_PAD_PD14].FUNC_CTL = IOC_PD14_FUNC_CTL_MCAN3_RXD; + HPM_IOC->PAD[IOC_PAD_PD13].FUNC_CTL = IOC_PD13_FUNC_CTL_MCAN3_STBY; } } @@ -417,7 +431,7 @@ void init_lcd_rgb_ctl_pins(void) HPM_IOC->PAD[IOC_PAD_PY05].PAD_CTL = IOC_PAD_PAD_CTL_PE_MASK; HPM_IOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_GPIO_Y_05; - HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = IOC_PY05_FUNC_CTL_SOC_PY_05; + HPM_PIOC->PAD[IOC_PAD_PY05].FUNC_CTL = PIOC_PY05_FUNC_CTL_SOC_PY_05; } void init_lcd_rgb_pins(void) @@ -510,19 +524,13 @@ void init_enet_pps_pins(void) void init_adc_pins(void) { - HPM_IOC->PAD[IOC_PAD_PE16].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE17].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE18].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE19].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE21].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE22].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE23].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; + /* ADC0.INA12 */ HPM_IOC->PAD[IOC_PAD_PE24].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE25].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE26].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE27].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE28].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE29].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE30].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; - HPM_IOC->PAD[IOC_PAD_PE31].FUNC_CTL = IOC_PAD_FUNC_CTL_ANALOG_MASK; +} + +void init_tamper_pins(void) +{ + HPM_BIOC->PAD[IOC_PAD_PZ04].FUNC_CTL = BIOC_PZ04_FUNC_CTL_TAMP_PZ_04 | IOC_PAD_FUNC_CTL_LOOP_BACK_MASK; + HPM_BIOC->PAD[IOC_PAD_PZ05].FUNC_CTL = BIOC_PZ05_FUNC_CTL_TAMP_PZ_05; + HPM_BIOC->PAD[IOC_PAD_PZ06].FUNC_CTL = BIOC_PZ06_FUNC_CTL_TAMP_PZ_06; } diff --git a/boards/hpm6800evk/pinmux.h b/boards/hpm6800evk/pinmux.h index b3c043af1..e71c10396 100644 --- a/boards/hpm6800evk/pinmux.h +++ b/boards/hpm6800evk/pinmux.h @@ -12,6 +12,7 @@ extern "C" { #endif void init_uart_pins(UART_Type *ptr); +void init_uart_pin_as_gpio(UART_Type *ptr); void init_cap_pins(void); void init_i2c_pins_as_gpio(I2C_Type *ptr); void init_i2c_pins(I2C_Type *ptr); @@ -53,6 +54,7 @@ void init_pdm_pins(void); void init_enet_pins(ENET_Type *ptr); void init_enet_pps_pins(void); void init_adc_pins(void); +void init_tamper_pins(void); #ifdef __cplusplus } diff --git a/boards/openocd/boards/hpm6800evk.cfg b/boards/openocd/boards/hpm6800evk.cfg index 849d67f41..e5f25c0ee 100644 --- a/boards/openocd/boards/hpm6800evk.cfg +++ b/boards/openocd/boards/hpm6800evk.cfg @@ -205,11 +205,6 @@ proc init_dram {} { echo "ddr has been enabled!" } -$_TARGET0 configure -event reset-end { - init_clock - init_ddr3 -} - $_TARGET0 configure -event reset-init { init_clock init_ddr3 diff --git a/boards/openocd/hpm5300_all_in_one.cfg b/boards/openocd/hpm5300_all_in_one.cfg index d9ede39f3..97bf5adcd 100644 --- a/boards/openocd/hpm5300_all_in_one.cfg +++ b/boards/openocd/hpm5300_all_in_one.cfg @@ -7,7 +7,10 @@ # # usage: # # connect hpm5300evk via ft2232, debugging single core -# $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm5300vk; set PROBE ft2232;" -f hpm5300_all_in_one.cfg +# *unix: +# $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm5300evk; set PROBE ft2232;" -f hpm5300_all_in_one.cfg +# Windows DOS batch: +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm5300evk; set PROBE ft2232;" -f hpm5300_all_in_one.cfg # # # supported board to be set to BOARD: # - hpm5300evk @@ -29,5 +32,5 @@ if { ![info exists BOARD] } { } source ${HPM_OPENOCD_CONFIG}/probes/${PROBE}.cfg -source ${HPM_OPENOCD_CONFIG}/soc/hpm5361.cfg +source ${HPM_OPENOCD_CONFIG}/soc/hpm5300.cfg source ${HPM_OPENOCD_CONFIG}/boards/${BOARD}.cfg diff --git a/boards/openocd/hpm6280_all_in_one.cfg b/boards/openocd/hpm6280_all_in_one.cfg index 506cb8e84..f6de8ced4 100644 --- a/boards/openocd/hpm6280_all_in_one.cfg +++ b/boards/openocd/hpm6280_all_in_one.cfg @@ -7,10 +7,16 @@ # # usage: # # connect hpm6200evk via ft2232, debugging single core +# *unix: # $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm6200evk; set PROBE ft2232;" -f hpm6280_all_in_one.cfg # # connect hpm6200evk via ft2232, debugging dual core # $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm6200evk; set PROBE ft2232; set ENABLE_DUALCORE 1" -f hpm6280_all_in_one.cfg # +# Windows DOS batch: +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm6200evk; set PROBE ft2232;" -f hpm6280_all_in_one.cfg +# # connect hpm6200evk via ft2232, debugging dual core +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm6200evk; set PROBE ft2232; set ENABLE_DUALCORE 1" -f hpm6280_all_in_one.cfg +# # # supported board to be set to BOARD: # - hpm6200evk # # supported probes to be set to PROBE: diff --git a/boards/openocd/hpm6300_all_in_one.cfg b/boards/openocd/hpm6300_all_in_one.cfg index 6e3882823..5d26132e6 100644 --- a/boards/openocd/hpm6300_all_in_one.cfg +++ b/boards/openocd/hpm6300_all_in_one.cfg @@ -7,7 +7,10 @@ # # usage: # # connect hpm6300evk via ft2232, debugging single core +# *unix: # $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm6300evk; set PROBE ft2232;" -f hpm6300_all_in_one.cfg +# Windows DOS batch: +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm6300evk; set PROBE ft2232;" -f hpm6300_all_in_one.cfg # # # supported board to be set to BOARD: # - hpm6300evk diff --git a/boards/openocd/hpm6750_all_in_one.cfg b/boards/openocd/hpm6750_all_in_one.cfg index 04d164bd9..3eb7c05c2 100644 --- a/boards/openocd/hpm6750_all_in_one.cfg +++ b/boards/openocd/hpm6750_all_in_one.cfg @@ -6,11 +6,18 @@ # - current directory is ${HPM_SDK_BASE}/boards/openocd # # usage: +# *unix: # # connect hpm6750evkmini via ft2232, debugging single core # $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm6750evkmini; set PROBE ft2232;" -f hpm6750_all_in_one.cfg # # connect hpm6750evkmini via ft2232, debugging dual core # $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm6750evkmini; set PROBE ft2232; set ENABLE_DUALCORE 1" -f hpm6750_all_in_one.cfg # +# Windows DOS batch: +# # connect hpm6750evkmini via ft2232, debugging single core +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm6750evkmini; set PROBE ft2232;" -f hpm6750_all_in_one.cfg +# # connect hpm6750evkmini via ft2232, debugging dual core +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm6750evkmini; set PROBE ft2232; set ENABLE_DUALCORE 1" -f hpm6750_all_in_one.cfg +# # # supported board to be set to BOARD: # - hpm6750evk # - hpm6750evkmini diff --git a/boards/openocd/hpm6800_all_in_one.cfg b/boards/openocd/hpm6800_all_in_one.cfg new file mode 100644 index 000000000..364c69d4f --- /dev/null +++ b/boards/openocd/hpm6800_all_in_one.cfg @@ -0,0 +1,36 @@ +# Copyright (c) 2024 HPMicro +# SPDX-License-Identifier: BSD-3-Clause +# +# assumptions: +# - HPM_SDK_BASE has been defined as environment variable pointing to correct hpm_sdk path +# - current directory is ${HPM_SDK_BASE}/boards/openocd +# +# usage: +# # connect hpm6800evk via ft2232, debugging single core +# *unix: +# $ openocd -c "set HPM_SDK_BASE ${HPM_SDK_BASE}; set BOARD hpm6800evk; set PROBE ft2232;" -f hpm6800_all_in_one.cfg +# Windows DOS batch: +# $ openocd -c "set HPM_SDK_BASE %HPM_SDK_BASE:\=/%; set BOARD hpm6800evk; set PROBE ft2232;" -f hpm6800_all_in_one.cfg +# +# # supported board to be set to BOARD: +# - hpm6800evk +# # supported probes to be set to PROBE: +# - ft2232 +# - ft232 +# - jlink +# - cmsis_dap +# - nds_aice_micro + +set HPM_OPENOCD_CONFIG ${HPM_SDK_BASE}/boards/openocd + +if { ![info exists PROBE ] } { + set PROBE ft2232 +} + +if { ![info exists BOARD] } { + set BOARD hpm6800evk +} + +source ${HPM_OPENOCD_CONFIG}/probes/${PROBE}.cfg +source ${HPM_OPENOCD_CONFIG}/soc/hpm6880.cfg +source ${HPM_OPENOCD_CONFIG}/boards/${BOARD}.cfg diff --git a/boards/openocd/soc/hpm5300.cfg b/boards/openocd/soc/hpm5300.cfg index ad949dcb9..ea686e684 100644 --- a/boards/openocd/soc/hpm5300.cfg +++ b/boards/openocd/soc/hpm5300.cfg @@ -11,3 +11,8 @@ target create $_TARGET0 riscv -chain-position $_CHIP.cpu -coreid 0 $_TARGET0 configure -work-area-phys 0x00000000 -work-area-size 0x20000 -work-area-backup 0 targets $_TARGET0 + +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF410001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/boards/openocd/soc/hpm6280-dual-core.cfg b/boards/openocd/soc/hpm6280-dual-core.cfg index 6f64b654a..d2096324f 100644 --- a/boards/openocd/soc/hpm6280-dual-core.cfg +++ b/boards/openocd/soc/hpm6280-dual-core.cfg @@ -52,3 +52,7 @@ $_TARGET1 configure -event reset-deassert-pre { release_core1 } +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF40C001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/boards/openocd/soc/hpm6280-single-core.cfg b/boards/openocd/soc/hpm6280-single-core.cfg index 4c5abc05b..90c587333 100644 --- a/boards/openocd/soc/hpm6280-single-core.cfg +++ b/boards/openocd/soc/hpm6280-single-core.cfg @@ -11,3 +11,8 @@ target create $_TARGET0 riscv -chain-position $_CHIP.cpu -coreid 0 $_TARGET0 configure -work-area-phys 0x00000000 -work-area-size 0x20000 -work-area-backup 0 targets $_TARGET0 + +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF40C001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/boards/openocd/soc/hpm6360.cfg b/boards/openocd/soc/hpm6360.cfg index 472466ce8..aad1ee808 100644 --- a/boards/openocd/soc/hpm6360.cfg +++ b/boards/openocd/soc/hpm6360.cfg @@ -11,3 +11,8 @@ target create $_TARGET0 riscv -chain-position $_CHIP.cpu -coreid 0 $_TARGET0 configure -work-area-phys 0x00000000 -work-area-size 0x20000 -work-area-backup 0 targets $_TARGET0 + +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF40C001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/boards/openocd/soc/hpm6750-dual-core.cfg b/boards/openocd/soc/hpm6750-dual-core.cfg index ab2e39d3c..e7aefb3cb 100644 --- a/boards/openocd/soc/hpm6750-dual-core.cfg +++ b/boards/openocd/soc/hpm6750-dual-core.cfg @@ -65,3 +65,8 @@ $_TARGET1 configure -event reset-deassert-pre { $::_TARGET0 arp_poll release_core1 } + +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF40C001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/boards/openocd/soc/hpm6750-single-core.cfg b/boards/openocd/soc/hpm6750-single-core.cfg index f873527fb..bb498150b 100644 --- a/boards/openocd/soc/hpm6750-single-core.cfg +++ b/boards/openocd/soc/hpm6750-single-core.cfg @@ -11,3 +11,8 @@ target create $_TARGET0 riscv -chain-position $_CHIP.cpu -coreid 0 $_TARGET0 configure -work-area-phys 0x00000000 -work-area-size 0x20000 -work-area-backup 0 targets $_TARGET0 + +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF40C001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/boards/openocd/soc/hpm6880.cfg b/boards/openocd/soc/hpm6880.cfg index f1785609b..893feb285 100644 --- a/boards/openocd/soc/hpm6880.cfg +++ b/boards/openocd/soc/hpm6880.cfg @@ -11,3 +11,8 @@ target create $_TARGET0 riscv -chain-position $_CHIP.cpu -coreid 0 $_TARGET0 configure -work-area-phys 0x00000000 -work-area-size 0x20000 -work-area-backup 0 targets $_TARGET0 + +proc reset_soc {} { + $::_TARGET0 riscv dmi_write 0x39 0xF410001C + $::_TARGET0 riscv dmi_write 0x3C 24000000 +} diff --git a/cmake/application.cmake b/cmake/application.cmake index 255809924..8735bd068 100644 --- a/cmake/application.cmake +++ b/cmake/application.cmake @@ -71,11 +71,19 @@ if(NOT RV_ARCH) set(RV_ARCH "rv32imac") endif() -# add extention +# add basic extentions include(${HPM_SDK_BASE}/cmake/python.cmake) include(${HPM_SDK_BASE}/cmake/cmake-ext.cmake) + +if(APP_YAML_PATH) + get_app_linked_project_name("${APP_YAML_PATH}/app.yaml" LINKED_PROJECT_NAME) + get_app_linked_project_path("${APP_YAML_PATH}/app.yaml" LINKED_PROJECT_PATH) + get_app_excluded_ides("${APP_YAML_PATH}/app.yaml" EXCLUDED_IDES) +endif() + +# include more advanced extentions include(${HPM_SDK_BASE}/cmake/toolchain.cmake) -include(${HPM_SDK_BASE}/cmake/ide/segger.cmake) +include(${HPM_SDK_BASE}/cmake/ide.cmake) include(${HPM_SDK_BASE}/cmake/extra_flags.cmake) include(${HPM_SDK_BASE}/cmake/ccache.cmake) include(${HPM_SDK_BASE}/cmake/version.cmake) @@ -87,6 +95,14 @@ add_custom_target( -DSRC_DIR=${APP_SRC_DIR} -P ${HPM_SDK_BASE}/cmake/cleanup.cmake ) +if(NOT LOCALIZATION_DST) + set(LOCALIZATION_DST ${APP_SRC_DIR}) +endif() + +if(NOT EXISTS ${LOCALIZATION_DST}) + message(FATAL_ERROR "localization dest folder: \"${LOCALIZATION_DST}\" can not be found") +endif() + add_custom_command( TARGET ${APP_ELF_NAME} COMMAND "${CROSS_COMPILE}objcopy" -O binary -S ${EXECUTABLE_OUTPUT_PATH}/${APP_ELF_NAME} ${EXECUTABLE_OUTPUT_PATH}/${APP_BIN_NAME} @@ -102,6 +118,9 @@ if(APP_YAML_PATH) if(${result} STREQUAL "1") message(FATAL_ERROR "${BOARD} can not support this sample") endif() + if(${result} STREQUAL "2") + message(FATAL_ERROR "Failed to build core1 project for this sample") + endif() check_excluded_targets("${APP_YAML_PATH}/app.yaml" excluded_targets) # check if specific minimum SDK version is needed get_app_min_sdk_version("${APP_YAML_PATH}/app.yaml" app_min_sdk_version) @@ -126,6 +145,34 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "") set(CMAKE_BUILD_TYPE debug) endif() +# target of "localize_sdk" +add_custom_target( + localize_sdk + COMMAND ${CMAKE_COMMAND} + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DHPM_SDK_BASE=${HPM_SDK_BASE} + -DSRC_DIR=${APP_SRC_DIR} + -DDST_DIR=${LOCALIZATION_DST} + -DBIN_DIR=${APP_BIN_DIR} + -DBUILD_TYPE=${CMAKE_BUILD_TYPE} + -DGENERATOR=${CMAKE_GENERATOR} + -DBOARD=${BOARD} + -P ${HPM_SDK_BASE}/cmake/localize_sdk.cmake +) + +add_custom_target( + unlocalize_sdk + COMMAND ${CMAKE_COMMAND} + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DHPM_SDK_BASE=${HPM_SDK_BASE} + -DSRC_DIR=${APP_SRC_DIR} + -DBIN_DIR=${APP_BIN_DIR} + -DDST_DIR=${LOCALIZATION_DST} + -DGENERATOR=${CMAKE_GENERATOR} + -DUNLOCALIZE_PROJECT=1 + -P ${HPM_SDK_BASE}/cmake/localize_sdk.cmake +) + if((excluded_targets) AND (NOT ${CMAKE_BUILD_TYPE} STREQUAL "")) foreach(t IN ITEMS ${excluded_targets}) string(COMPARE EQUAL ${CMAKE_BUILD_TYPE} ${t} result) @@ -168,7 +215,6 @@ set(CMAKE_C_COMPILER_FORCED 1) set(CMAKE_CXX_COMPILER_FORCED 1) enable_language(C CXX ASM) - add_subdirectory(${HPM_SDK_BASE} ${__build_dir}) if (DEFINED GEN_SEC_CORE_IMG_C_ARRAY) @@ -179,7 +225,7 @@ if (DEFINED GEN_SEC_CORE_IMG_C_ARRAY) endif() # link final executable -target_link_libraries(app PUBLIC ${HPM_SDK_LIB_ITF}) +target_link_libraries(app PUBLIC ${HPM_SDK_LIB_ITF} ${HPM_SDK_GCC_LIB_ITF}) if(${APP_SRC_DIR} STREQUAL ${APP_BIN_DIR}) message(FATAL_ERROR "source directory is the same with binary directory.\ diff --git a/cmake/cmake-ext.cmake b/cmake/cmake-ext.cmake index 35fe42cd2..b5521065c 100644 --- a/cmake/cmake-ext.cmake +++ b/cmake/cmake-ext.cmake @@ -1,10 +1,15 @@ -# Copyright (c) 2021-2022 HPMicro +# Copyright (c) 2021-2024 HPMicro # SPDX-License-Identifier: BSD-3-Clause - cmake_policy(SET CMP0079 NEW) -# add source file to sdk core (HPM_SDK_LIB) +# Add source file to sdk core (HPM_SDK_LIB) +# +# Example: +# sdk_src(SOURCE_FILE) +# :param SOURCE_FILE: source files to be added to HPM_SDK_LIB +# @public +# function(sdk_src) foreach(file ${ARGN}) if(IS_DIRECTORY ${file}) @@ -19,7 +24,13 @@ function(sdk_src) endforeach() endfunction() -# add include path +# Add include path +# +# Example: +# sdk_inc(INC_PATH) +# :param INC_PATH: add include path +# @public +# function(sdk_inc) foreach(inc ${ARGN}) if(IS_ABSOLUTE ${inc}) @@ -31,7 +42,13 @@ function(sdk_inc) endforeach() endfunction() -# add system include path +# Add system include path +# +# Example: +# sdk_sys_inc(SYS_INC_PATH) +# :param SYS_INC_PATH: add system include path +# @public +# function(sdk_sys_inc) foreach(inc ${ARGN}) if(IS_ABSOLUTE ${inc}) @@ -43,14 +60,26 @@ function(sdk_sys_inc) endforeach() endfunction() -# return all compiler options, separated by single space +# Return all compiler options, separated by single space +# +# Example: +# sdk_get_copmile_options(opts) +# :param opts: all compile options configured for current project +# @public +# function(sdk_get_compile_options opts) get_target_property(all_opts ${HPM_SDK_LIB_ITF} INTERFACE_COMPILE_OPTIONS) string(JOIN " " output_opts ${all_opts}) set(${opts} ${output_opts} PARENT_SCOPE) endfunction() -# define symbols for linker +# Define global symbols for linker +# +# Example: +# sdk_linker_global_symbols(syms) +# :param syms: symboles for linker +# @public +# function(sdk_linker_global_symbols) foreach(sym ${ARGN}) target_link_libraries(${HPM_SDK_LIB_ITF} INTERFACE "-Xlinker --defsym=${sym}") @@ -60,14 +89,26 @@ function(sdk_linker_global_symbols) endforeach() endfunction() -# set compile options +# Set compile options +# +# Example: +# sdk_compile_options(opts) +# :param opts: compile options +# @public +# function(sdk_compile_options) foreach(opt ${ARGN}) target_compile_options(${HPM_SDK_LIB_ITF} INTERFACE ${opt}) endforeach() endfunction() -# set compile definitions +# Set compile definitions +# +# Example: +# sdk_compile_definitions(def) +# :param def: compiler preprocesing definition +# @public +# function(sdk_compile_definitions) foreach(def ${ARGN}) target_compile_definitions(${HPM_SDK_LIB_ITF} INTERFACE ${def}) @@ -75,43 +116,81 @@ function(sdk_compile_definitions) endfunction() # set compile definitions if feature is true +# +# Example: +# sdk_compile_definitions(def) +# :param def: compiler preprocesing definition +# @public +# function(sdk_compile_definitions_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) sdk_compile_definitions(${ARGN}) endif() endfunction() -# link libraries +# Link libraries +# +# Example: +# sdk_link_libraries(libs) +# :param libs: libraries to be linked, support both file path +# (like USER_LIB.a) and standard libraries provided by toolchain (like m) +# @public +# function(sdk_link_libraries) foreach(l ${ARGN}) - if(IS_ABSOLUTE ${l}) - set(lib ${l}) - else() - set(lib ${CMAKE_CURRENT_SOURCE_DIR}/${l}) - endif() - if(NOT EXISTS ${lib}) - message(WARNING "library ${lib} can't be found") + string(REGEX MATCH "\.[a-zA-Z]+$" is_file_name ${l}) + if(NOT ${is_file_name} STREQUAL "") + # given library is an actual file name + if(IS_ABSOLUTE ${l}) + set(lib ${l}) + else() + set(lib ${CMAKE_CURRENT_SOURCE_DIR}/${l}) + endif() + if(NOT EXISTS ${lib}) + message(WARNING "library ${lib} can't be found") + else() + target_link_libraries(${HPM_SDK_LIB_ITF} INTERFACE ${lib}) + endif() else() - target_link_libraries(${HPM_SDK_LIB_ITF} INTERFACE ${lib}) + target_link_libraries(${HPM_SDK_LIB_ITF} INTERFACE ${l}) endif() endforeach() endfunction() # link libraries if feature is true +# +# Example: +# sdk_ld_options(opts) +# :param opts: linker options +# @public +# function(sdk_link_libraries_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) sdk_link_libraries(${ARGN}) endif() endfunction() -# set linker options +# Set linker options +# +# Example: +# sdk_ld_options(opts) +# :param opts: linker options +# @public +# function(sdk_ld_options) foreach(opt ${ARGN}) target_link_libraries(${HPM_SDK_LIB_ITF} INTERFACE ${opt}) endforeach() endfunction() -# set linker options if feature is true +# Set linker options if feature is true +# +# Example: +# sdk_ld_options_ifdef(FEATUREA opts) +# :param FEATUREA: if FEATUREA is true, opts will be added for linker +# :param opts: linker options +# @public +# function(sdk_ld_options_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) sdk_ld_options(${ARGN}) @@ -119,6 +198,7 @@ function(sdk_ld_options_ifdef feature) endfunction() # get board information from board yaml +# @private function(get_board_info board_yaml info_type info_value) execute_process( COMMAND @@ -137,60 +217,41 @@ function(get_board_info board_yaml info_type info_value) endfunction() # get probe name for openocd from board yaml +# @private function(get_openocd_probe_name_of_board board_yaml out) get_board_info(${board_yaml} openocd-probe r) set(${out} ${r} PARENT_SCOPE) endfunction() # get soc name for openocd from board yaml +# @private function(get_openocd_soc_name_of_board board_yaml out) get_board_info(${board_yaml} openocd-soc r) set(${out} ${r} PARENT_SCOPE) endfunction() # get soc name from board yaml +# @private function(get_soc_name_of_board board_yaml out) get_board_info(${board_yaml} soc r) set(${out} ${r} PARENT_SCOPE) endfunction() # get device name from board yaml +# @private function(get_device_name_of_board board_yaml out) get_board_info(${board_yaml} device r) set(${out} ${r} PARENT_SCOPE) endfunction() -# get compiler version -function(get_compiler_version compiler version_text compiler_version) - if("${compiler}" STREQUAL "gcc") - execute_process( - COMMAND - ${PYTHON_EXECUTABLE} - ${HPM_SDK_BASE}/scripts/get_gcc_version.py - "${version_text}" - RESULT_VARIABLE result - OUTPUT_VARIABLE v - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - set(${compiler_version} ${v} PARENT_SCOPE) - elseif("${compiler}" STREQUAL "clang") - execute_process( - COMMAND - ${PYTHON_EXECUTABLE} - ${HPM_SDK_BASE}/scripts/get_gcc_version.py - "${version_text}" - RESULT_VARIABLE result - OUTPUT_VARIABLE v - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - set(${compiler_version} ${v} PARENT_SCOPE) - - else() - message(FATAL_ERROR "Unsupported compiler ${compiler}") - endif() -endfunction() - -# add subdirectory if feature is true +# Add subdirectory if feature is true +# +# Example: +# add_subdirectory_ifdef(FEATUREA paths) +# :param FEATUREA: if FEATUREA is defined, paths will be added +# :param paths: directories to be added +# @public +# function(add_subdirectory_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) foreach(d ${ARGN}) @@ -199,40 +260,56 @@ function(add_subdirectory_ifdef feature) endif() endfunction() -# add include path if feature is true +# Add include path if feature is true +# @public +# function(sdk_inc_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) sdk_inc(${ARGN}) endif() endfunction() -# add include path if feature is false +# Add include path if feature is false +# @public +# function(sdk_inc_ifndef feature) if((NOT DEFINED ${feature}) OR (${feature} EQUAL 0)) sdk_inc(${ARGN}) endif() endfunction() -# add source to SDK core if feature is true +# Add source to SDK core if feature is true +# @public +# function(sdk_src_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) sdk_src(${ARGN}) endif() endfunction() -# add source to SDK core if feature is false +# Add source to SDK core if feature is false +# @public +# function(sdk_src_ifndef feature) if((NOT DEFINED ${feature}) OR (${feature} EQUAL 0)) sdk_src(${ARGN}) endif() endfunction() -# clear all compile options +# Clear all compile options +# @public +# function(sdk_clear_compile_options) set_target_properties(${HPM_SDK_LIB_ITF} PROPERTIES INTERFACE_COMPILE_OPTIONS "") endfunction() -# add application specific include path +# Add application specific include path +# +# Example: +# sdk_app_inc(INC_PATH) +# :param INC_PATH: add include path for application +# @public +# function(sdk_app_inc) foreach(inc ${ARGN}) if(IS_ABSOLUTE ${inc}) @@ -244,7 +321,13 @@ function(sdk_app_inc) endforeach() endfunction() -# add application source +# Add application source +# +# Example: +# sdk_app_src(SOURCE_FILE) +# :param SOURCE_FILE: source files to be added to application +# @public +# function(sdk_app_src) foreach(file ${ARGN}) if(IS_DIRECTORY ${file}) @@ -260,6 +343,8 @@ function(sdk_app_src) endfunction() # check board capability based on board yaml and app.yaml +# @private +# function(check_board_capability board_yaml app_yaml result) execute_process( COMMAND @@ -274,17 +359,23 @@ function(check_board_capability board_yaml app_yaml result) endfunction() # get flash size from board yaml +# @private +# function(get_flash_size_of_board board_yaml out) get_board_info(${board_yaml} flash_size r) set(${out} ${r} PARENT_SCOPE) endfunction() # get on-board external ram size +# @private +# function(get_extram_size_of_board board_yaml out) get_board_info(${board_yaml} extram_size r) set(${out} ${r} PARENT_SCOPE) endfunction() +# @private +# function(get_ses_debug_auto_start_gdb_server app_yaml start) execute_process( COMMAND @@ -300,6 +391,8 @@ function(get_ses_debug_auto_start_gdb_server app_yaml start) set(${start} ${auto_start} PARENT_SCOPE) endfunction() +# @private +# function(get_ses_debug_gdb_server_port app_yaml port) execute_process( COMMAND @@ -315,6 +408,8 @@ function(get_ses_debug_gdb_server_port app_yaml port) set(${port} ${p} PARENT_SCOPE) endfunction() +# @private +# function(get_ses_debug_gdb_server_reset_command app_yaml rst_cmd) execute_process( COMMAND @@ -330,6 +425,8 @@ function(get_ses_debug_gdb_server_reset_command app_yaml rst_cmd) set(${rst_cmd} ${p} PARENT_SCOPE) endfunction() +# @private +# function(check_excluded_targets app_yaml result) execute_process( COMMAND @@ -343,6 +440,8 @@ function(check_excluded_targets app_yaml result) endfunction() # set compile definitions for soc modules +# @private +# function(import_soc_modules soc_module_list) file( STRINGS @@ -368,7 +467,13 @@ function(import_soc_modules soc_module_list) endforeach() endfunction() -# raise fatal error if symbols given are all not set or set to 0 or n +# Raise fatal error if symbols given are all not set or set to 0 or n +# +# Example: +# sdk_raise_fatal_error_if_all_invalid(FEATUREA FEATUREB) +# :param FEATUREA FEAUTREB: features to be checked +# @public +# function(sdk_raise_fatal_error_if_all_invalid) foreach(feature ${ARGN}) if(NOT (${feature} AND (NOT ${${feature}} EQUAL 0))) @@ -377,7 +482,13 @@ function(sdk_raise_fatal_error_if_all_invalid) endforeach() endfunction() -# raise fatal error if symbols given are all set or set to 1 or y +# Raise fatal error if symbols given are all set or set to 1 or y +# +# Example: +# sdk_raise_fatal_error_if_all_valid(FEATUREA FEATUREB) +# :param FEATUREA FEAUTREB: features to be checked +# @public +# function(sdk_raise_fatal_error_if_all_valid) foreach(feature ${ARGN}) if(${feature} AND (NOT ${${feature}} EQUAL 0)) @@ -386,7 +497,13 @@ function(sdk_raise_fatal_error_if_all_valid) endforeach() endfunction() -# raise fatal error if at least one of them given symbols is set or set to 1 or y +# Raise fatal error if at least one of them given symbols is set or set to 1 or y +# +# Example: +# sdk_raise_fatal_error_if_valid_at_least_one(FEATUREA FEATUREB) +# :param FEATUREA FEAUTREB: features to be checked +# @public +# function(sdk_raise_fatal_error_if_valid_at_least_one) foreach(feature ${ARGN}) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) @@ -396,38 +513,92 @@ function(sdk_raise_fatal_error_if_valid_at_least_one) message(FATAL_ERROR "ERROR: at least one of ${ARGN} needs to set") endfunction() -# NDSGCC sections +#### NDSGCC sections #### + +# Set compile options for nds toolchain +# +# Example: +# sdk_nds_compile_options(opts) +# :param opts: options for nds toolchain +# @public +# function(sdk_nds_compile_options) foreach(opt ${ARGN}) target_compile_options(${HPM_SDK_NDSGCC_LIB_ITF} INTERFACE ${opt}) endforeach() endfunction() +# Set defnitions for nds toolchain +# +# Example: +# sdk_nds_compie_definitions(defs) +# :param defs: definitions for andes toolchain +# @public +# function(sdk_nds_compile_definitions) foreach(def ${ARGN}) target_compile_definitions(${HPM_SDK_NDSGCC_LIB_ITF} INTERFACE ${def}) endforeach() endfunction() +# Link libraries for andes toolchains +# +# Example: +# sdk_nds_link_libraries(libs) +# :param libs: libraries to be linked, support both file path +# (like USER_LIB.a) and standard libraries provided by toolchain (like m) +# @public function(sdk_nds_link_libraries) foreach(lib ${ARGN}) target_link_libraries(${HPM_SDK_NDSGCC_LIB_ITF} INTERFACE ${lib}) endforeach() endfunction() +# Set linker options +# +# Example: +# sdk_nds_ld_options(opts) +# :param opts: linker options +# @public +# function(sdk_nds_ld_options) foreach(opt ${ARGN}) target_link_libraries(${HPM_SDK_NDSGCC_LIB_ITF} INTERFACE ${opt}) endforeach() endfunction() +# Add directory if feature is false function(add_subdirectory_ifndef feature dir) if(NOT DEFINED ${feature} OR "${${feature}}" EQUAL "0") add_subdirectory(${dir}) endif() endfunction() -# add source specifically for gcc +# Add include path for gcc +# +# Example: +# sdk_gcc_inc(INC_PATH) +# :param INC_PATH: add include path +# @public +# +function(sdk_gcc_inc) + foreach(inc ${ARGN}) + if(IS_ABSOLUTE ${inc}) + set(path ${inc}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${inc}) + endif() + target_include_directories(${HPM_SDK_GCC_LIB_ITF} INTERFACE ${path}) + endforeach() +endfunction() + +# Add source specifically for gcc +# +# Example: +# sdk_gcc_src(SOURCE_FILE) +# :param SOURCE_FILE: source files to be added to HPM_SDK_LIB +# @public +# function(sdk_gcc_src) foreach(file ${ARGN}) if(IS_DIRECTORY ${file}) @@ -443,6 +614,8 @@ function(sdk_gcc_src) endfunction() # get minimal SDK version needed by application +# @private +# function(get_app_min_sdk_version app_yaml result) execute_process( COMMAND @@ -455,4 +628,112 @@ function(get_app_min_sdk_version app_yaml result) set(${result} ${r} PARENT_SCOPE) endfunction() +# @private +# +function(get_app_linked_project_path app_yaml result) + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} + ${HPM_SDK_BASE}/scripts/get_app_info.py + ${app_yaml} + "linked_project_path" + OUTPUT_VARIABLE r + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(${result} ${r} PARENT_SCOPE) +endfunction() + +# @private +# +function(get_app_linked_project_name app_yaml result) + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} + ${HPM_SDK_BASE}/scripts/get_app_info.py + ${app_yaml} + "linked_project_name" + OUTPUT_VARIABLE r + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(${result} ${r} PARENT_SCOPE) +endfunction() + +# @private +# +function(get_app_excluded_ides app_yaml result) + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} + ${HPM_SDK_BASE}/scripts/get_app_info.py + ${app_yaml} + "excluded_ides" + OUTPUT_VARIABLE r + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(${result} ${r} PARENT_SCOPE) +endfunction() + +# Add source file (glob pattern) to sdk core (HPM_SDK_LIB) +# +# Example: +# sdk_src_glob(SOURCE_FILE_GLOB) +# :param SOURCE_FILE_GLOB: source files to be added to HPM_SDK_LIB, +# like ./**/*.c to add all .c files under current directory recursively +# @public +# +function(sdk_src_glob) + foreach(g ${ARGN}) + file(GLOB src ${g}) + list(APPEND globbed_src ${src}) + endforeach() + sdk_src(${globbed_src}) +endfunction() + +# Add application source file (glob pattern) +# +# Example: +# sdk_app_src_glob(SOURCE_FILE_GLOB) +# :param SOURCE_FILE_GLOB: source files to be added to application, +# like ./**/*.c to add all .c files under current directory recursively +# @public +# +function(sdk_app_src_glob) + foreach(g ${ARGN}) + file(GLOB src ${g}) + list(APPEND globbed_src ${src}) + endforeach() + sdk_app_src(${globbed_src}) +endfunction() + +# Add source file (glob pattern) for gcc +# +# Example: +# sdk_gcc_src_glob(SOURCE_FILE_GLOB) +# :param SOURCE_FILE_GLOB: source files to be added to gcc, +# like ./**/*.c to add all .c files under current directory recursively +# @public +# +function(sdk_gcc_src_glob) + foreach(g ${ARGN}) + file(GLOB src ${g}) + list(APPEND globbed_src ${src}) + endforeach() + sdk_gcc_src(${globbed_src}) +endfunction() + +# Add source file (glob pattern) for gcc if feature is true +# @public +function(sdk_src_glob_ifdef feature) + if((${feature}) AND (NOT ${${feature}} EQUAL 0)) + sdk_src_glob(${ARGN}) + endif() +endfunction() + +# Add source file (glob pattern) for gcc if feature is false +# @public +function(sdk_src_glob_ifndef feature) + if((NOT DEFINED ${feature}) OR (${feature} EQUAL 0)) + sdk_src_glob(${ARGN}) + endif() +endfunction() diff --git a/cmake/extra_flags.cmake b/cmake/extra_flags.cmake index c1eafd4c9..fa878e071 100644 --- a/cmake/extra_flags.cmake +++ b/cmake/extra_flags.cmake @@ -20,7 +20,7 @@ endif() if(EXTRA_LD_FLAGS_LIST) foreach(flag ${EXTRA_LD_FLAGS_LIST}) - sdk_link_libraries(${EXTRA_LD_FLAGS}) + sdk_ld_options(${EXTRA_LD_FLAGS}) endforeach() endif() diff --git a/cmake/ide.cmake b/cmake/ide.cmake new file mode 100644 index 000000000..6da19e878 --- /dev/null +++ b/cmake/ide.cmake @@ -0,0 +1,24 @@ +# Copyright 2023 hpmicro +# SPDX-License-Identifier: BSD-3-Clause + +if(EXCLUDED_IDES) + foreach(ide IN ITEMS ${EXCLUDED_IDES}) + if(${ide} STREQUAL "iar") + set(EXCLUDED_IDE_IAR 1) + elseif(${ide} STREQUAL "ses") + set(EXCLUDED_IDE_SES 1) + endif() + endforeach() +endif() + +include(${HPM_SDK_BASE}/cmake/ide/iar.cmake) +include(${HPM_SDK_BASE}/cmake/ide/segger.cmake) + +function (generate_ide_projects) + if(NOT EXCLUDED_IDE_IAR OR NOT ${EXCLUDED_IDE_IAR}) + generate_iar_project() + endif() + if(NOT EXCLUDED_IDE_SES OR NOT ${EXCLUDED_IDE_SES}) + generate_ses_project() + endif() +endfunction() diff --git a/cmake/ide/iar.cmake b/cmake/ide/iar.cmake new file mode 100644 index 000000000..df74de280 --- /dev/null +++ b/cmake/ide/iar.cmake @@ -0,0 +1,573 @@ +# Copyright 2023-2024 hpmicro +# SPDX-License-Identifier: BSD-3-Clause + +# add iar library interface to store iar specific configurations +set(HPM_SDK_IAR_LIB_ITF hpm_sdk_iar_lib_itf) +add_library(${HPM_SDK_IAR_LIB_ITF} INTERFACE) + +set(HPM_SDK_IAR_LIB hpm_sdk_iar_lib) +define_property(GLOBAL PROPERTY ${HPM_SDK_IAR_LIB} BRIEF_DOCS "iar library" FULL_DOCS "iar library") + +set(IAR_OPT_LIB_IO_TYPE LIBRARY_IO_TYPE) +set(IAR_OPT_DBG_TGT_CONN debug_target_connection) +set(IAR_OPT_LINKER_PRINTF_FP_ENABLED linker_printf_fp_enabled) +set(IAR_OPT_LINKER_SCANF_FP_ENABLED linker_scanf_fp_enabled) +set(IAR_OPT_LINKER_PRINTF_FMT_LEVEL linker_printf_fmt_level) +set(IAR_OPT_LINKER_SCANF_FMT_LEVEL linker_scanf_fmt_level) +set(IAR_OPT_DBG_JLINK_SPEED speed) +set(IAR_DBG_CONN_GDB_SRV "GDB Server") + +set(HPM_SDK_IAR_OPTS hpm_sdk_iar_opts) +define_property(GLOBAL PROPERTY ${HPM_SDK_IAR_OPTS} BRIEF_DOCS "iar options" FULL_DOCS "iar options") + +# Set compile options for IAR +# +# Example: +# sdk_iar_compile_options(opts) +# :param opts: compile options +# @public +# +function(sdk_iar_compile_options) + foreach(opt ${ARGN}) + target_compile_options(${HPM_SDK_IAR_LIB_ITF} INTERFACE ${opt}) + endforeach() +endfunction() + +# Set compile definitions for IAR +# +# Example: +# sdk_iar_compile_definitions(def) +# :param def: compiler preprocesing definition +# @public +# +function(sdk_iar_compile_definitions) + foreach(def ${ARGN}) + target_compile_definitions(${HPM_SDK_IAR_LIB_ITF} INTERFACE ${def}) + endforeach() +endfunction() + +# link libraries for IAR +# +# Example: +# sdk_iar_link_libraries(libs) +# :param libs: standard libraries to be linked for IAR +# @public +# +function(sdk_iar_link_libraries) + foreach(lib ${ARGN}) + target_link_libraries(${HPM_SDK_IAR_LIB_ITF} INTERFACE ${lib}) + endforeach() +endfunction() + +# @private +# +function(sdk_iar_ld_options) + foreach(opt ${ARGN}) + target_link_libraries(${HPM_SDK_IAR_LIB_ITF} INTERFACE ${opt}) + endforeach() +endfunction() + +# link libraries for IAR +# +# Example: +# sdk_iar_ld_libs(libs) +# :param libs: libraries to be linked for IAR +# @private +# +function(sdk_iar_ld_lib) + foreach(opt ${ARGN}) + set_property(TARGET ${HPM_SDK_IAR_LIB_ITF} APPEND PROPERTY INTERFACE_IAR_LD_INPUTS ${opt}) + endforeach() +endfunction() + +# Add include path for IAR +# +# Example: +# sdk_iar_link_libraries(libs) +# :param libs: libraries to be linked for IAR +# @public +# +function(sdk_iar_inc) + foreach(inc ${ARGN}) + if(IS_ABSOLUTE ${inc}) + set(path ${inc}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${inc}) + endif() + target_include_directories(${HPM_SDK_IAR_LIB_ITF} INTERFACE ${path}) + endforeach() +endfunction() + +# @private +# +function(sdk_iar_ld_lib_ifdef feature) + if((${feature}) AND (NOT ${${feature}} EQUAL 0)) + sdk_iar_ld_lib(${ARGN}) + endif() +endfunction() + +# Add source file for IAR +# +# Example: +# sdk_iar_src(SOURCE_FILE) +# :param SOURCE_FILE: source file added for IAR +# @public +# +function(sdk_iar_src) + foreach(file ${ARGN}) + if(IS_DIRECTORY ${file}) + message(FATAL_ERROR "directory ${file} can't be added to sdk_lib_src") + endif() + if(IS_ABSOLUTE ${file}) + set(path ${file}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${file}) + endif() + set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_IAR_LIB} ${path}) + endforeach() +endfunction() + +# Add source file (glob pattern) for IAR +# +# Example: +# sdk_gcc_src_glob(SOURCE_FILE_GLOB) +# :param SOURCE_FILE_GLOB: source files to be added to IAR, +# like ./**/*.c to add all .c files under current directory recursively +# @public +# +function(sdk_iar_src_glob) + foreach(g ${ARGN}) + file(GLOB src ${g}) + list(APPEND globbed_src ${src}) + endforeach() + sdk_iar_src(${globbed_src}) +endfunction() + +# Enable DSP in IAR +# @public +# +function(sdk_iar_enable_dsp) + set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_IAR_OPTS} "enable_dsp=1") +endfunction() + +# Set preinclude for IAR +# +# Example: +# sdk_iar_preinclude(TYPE FILE) +# :param TYPE: different preinclude type, cc or asm +# :param FILE: different preinclude type, cc or asm +# @private +# +function(sdk_iar_preinclude type file) + if(IS_DIRECTORY ${file}) + message(FATAL_ERROR "directory ${file} can't be added as preinclude") + endif() + if(IS_ABSOLUTE ${file}) + set(path ${file}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${file}) + endif() + set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_IAR_OPTS} "${type}_preinclude=${path}") +endfunction() + +# Set cc preinclude for IAR +# @public +# +function(sdk_iar_cc_preinclude file) + sdk_iar_preinclude("cc" ${file}) +endfunction() + +# Set asm preinclude for IAR +# @public +# +function(sdk_iar_asm_preinclude file) + sdk_iar_preinclude("asm" ${file}) +endfunction() + +# Enable no size constraints +# @public +# +function(sdk_iar_enable_no_size_constraints) + set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_IAR_OPTS} "iar_opt_no_size_const=1") +endfunction() + +# Enable iar andes performance ext +# @public +# +function(sdk_iar_enable_andesperf) + set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_IAR_OPTS} "enable_andesperf=1") +endfunction() + +# Set IAR optioins +# @private +# +function(sdk_iar_options) + foreach(opt ${ARGN}) + set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_IAR_OPTS} ${opt}) + endforeach() +endfunction() + +function (generate_iar_project) + get_property(target_source_files TARGET app PROPERTY SOURCES) + get_property(target_app_include_dirs TARGET app PROPERTY INCLUDE_DIRECTORIES) + get_property(target_lib_sources TARGET ${HPM_SDK_LIB} PROPERTY SOURCES) + get_property(target_include_dirs TARGET ${HPM_SDK_LIB_ITF} PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + get_property(target_defines TARGET ${HPM_SDK_LIB_ITF} PROPERTY INTERFACE_COMPILE_DEFINITIONS) + get_property(target_link_sym TARGET ${HPM_SDK_LIB_ITF} PROPERTY INTERFACE_LINK_SYMBOLS) + get_property(target_gcc_cflags TARGET ${HPM_SDK_LIB_ITF} PROPERTY INTERFACE_COMPILE_OPTIONS) + get_property(target_iar_cflags TARGET ${HPM_SDK_IAR_LIB_ITF} PROPERTY INTERFACE_COMPILE_OPTIONS) + get_property(target_iar_ld_lib TARGET ${HPM_SDK_IAR_LIB_ITF} PROPERTY INTERFACE_IAR_LD_INPUTS) + get_property(target_iar_source_files GLOBAL PROPERTY ${HPM_SDK_IAR_LIB}) + get_property(target_iar_options GLOBAL PROPERTY ${HPM_SDK_IAR_OPTS}) + get_property(target_gcc_source_files TARGET ${HPM_SDK_GCC_LIB} PROPERTY SOURCES) + get_property(target_iar_include_dirs TARGET ${HPM_SDK_IAR_LIB_ITF} PROPERTY INTERFACE_INCLUDE_DIRECTORIES) + + if(target_iar_ld_lib) + foreach(f IN ITEMS ${target_iar_ld_lib}) + if("${target_iar_ld_input}" STREQUAL "") + set(target_iar_ld_input ${f}) + else() + set(target_iar_ld_input "${target_iar_ld_input};${f}") + endif() + endforeach() + else() + set(target_iar_ld_input "") + endif() + + set(gcc_opt_level "") + STRING(REGEX REPLACE ".*(-O[0-3s]).*" "\\1" RESULT ${target_gcc_cflags}) + if(NOT "${RESULT}" STREQUAL "${target_gcc_cflags}") + LIST(GET RESULT 0 gcc_opt_level) + endif() + + set(target_cflags "") + set(target_source_files "${target_source_files};${target_iar_source_files}") + + foreach(f IN ITEMS ${target_iar_cflags}) + if(NOT target_cflags) + set(target_cflags ${f}) + else() + set(target_cflags "${target_cflags};${f}") + endif() + endforeach() + + # fallback option + if(NOT RV_ABI) + set(RV_ABI ilp32) + endif() + if(NOT RV_ARCH) + set(RV_ARCH rv32ima) + endif() + + if(NOT IAR_COMPILER_ABI) + set(IAR_COMPILER_ABI ${RV_ABI}) + endif() + if(NOT IAR_COMPILER_ARCH) + STRING(REGEX REPLACE "imafd" "g" RV_ARCH ${RV_ARCH}) + STRING(REGEX REPLACE "imadf" "g" RV_ARCH ${RV_ARCH}) + set(IAR_COMPILER_ARCH ${RV_ARCH}) + endif() + + STRING(FIND ${IAR_COMPILER_ARCH} "_" exist) + if(NOT ${exist} EQUAL -1) + set(target_compiler_arch_exts_csr 0) + set(target_compiler_arch_exts_fencei 0) + # isa extenions will be processed according to given arch, user should be responsible for ext settings + STRING(REGEX REPLACE "(rv[A-Za-z0-9]+)_(zi[A-Za-z0-9_]+)" "\\1;\\2" RESULT ${IAR_COMPILER_ARCH}) + LIST(GET RESULT 0 IAR_COMPILER_ARCH) + LIST(GET RESULT 1 IAR_COMPILER_ARCH_EXTS) + else() + # zicsr and zifencei will be set if no isa extension specified + set(target_compiler_arch_exts_csr 1) + set(target_compiler_arch_exts_fencei 1) + endif() + + set(post_build_command "") + set(is_secondary_core 0) + if (DEFINED BUILD_FOR_SECONDARY_CORE) + if (BUILD_FOR_SECONDARY_CORE) + if (NOT DEFINED SEC_CORE_IMG_C_ARRAY_OUTPUT) + set (SEC_CORE_IMG_C_ARRAY_OUTPUT "sec_core_img.c") + endif() + set(post_build_command "${PYTHON_EXECUTABLE} $(HPM_SDK_BASE)/scripts/bin2c.py $(OutDir)/demo.bin sec_core_img > ${SEC_CORE_IMG_C_ARRAY_OUTPUT}") + string(REPLACE "\\" "/" post_build_command ${post_build_command}) + set(is_secondary_core 1) + endif() + endif() + + set(target_link_symbols "") + foreach(sym IN ITEMS ${target_link_sym}) + string(FIND ${sym} "_heap_size" exist) + if(NOT ${exist} EQUAL -1) + continue() + endif() + string(FIND ${sym} "_stack_size" exist) + if(NOT ${exist} EQUAL -1) + continue() + endif() + if("${target_link_symbols}" STREQUAL "") + set(target_link_symbols ${sym}) + else() + set(target_link_symbols "${target_link_symbols},${sym}") + endif() + endforeach() + + set(target_sources "") + foreach(src IN ITEMS ${target_source_files}) + if("${target_sources}" STREQUAL "") + set(target_sources ${src}) + else() + set(target_sources "${target_sources},${src}") + endif() + endforeach() + + get_property(target_linker_script TARGET ${APP_ELF_NAME} PROPERTY LINK_DEPENDS) + if(CUSTOM_IAR_LINKER_FILE) + set(target_linker ${CUSTOM_IAR_LINKER_FILE}) + else() + # if no specific linker file is set, try to locate it + string(REPLACE ".ld" ".icf" target_linker ${target_linker_script}) + string(REPLACE "/gcc/" "/iar/" target_linker ${target_linker}) + endif() + + # suppress warning + set(iar_extra_options "--diag_suppress Pa089, --diag_suppress Pe236, --diag_suppress Pe188, --diag_suppress Pe546, --diag_suppress Pe111") + set(enable_dsp "0") + foreach(opt IN ITEMS ${target_iar_options}) + string(REPLACE "\"" "" opt ${opt}) # remove any quotes + + STRING(REGEX REPLACE "enable_dsp[space]*=[space]*([01])" "\\1" RESULT ${opt}) + if(NOT "${RESULT}" STREQUAL "${opt}") + LIST(GET RESULT 0 enable_dsp) + continue() + endif() + + STRING(REGEX REPLACE "cc_preinclude[space]*=[space]*([a-zA-Z0-9/]*)" "\\1" RESULT ${opt}) + if(NOT "${RESULT}" STREQUAL "${opt}") + LIST(GET RESULT 0 cc_preinclude) + continue() + endif() + + STRING(REGEX REPLACE "iar_opt_no_size_const[space]*=[space]*([01]*)" "\\1" RESULT ${opt}) + if(NOT "${RESULT}" STREQUAL "${opt}") + LIST(GET RESULT 0 iar_opt_no_size_const) + continue() + endif() + + STRING(REGEX REPLACE "asm_preinclude[space]*=[space]*([a-zA-Z0-9/]*)" "\\1" RESULT ${opt}) + if(NOT "${RESULT}" STREQUAL "${opt}") + LIST(GET RESULT 0 asm_preinclude) + continue() + endif() + if("${iar_extra_options}" STREQUAL "") + set(iar_extra_options "${opt}") + else() + set(iar_extra_options "${iar_extra_options},${opt}") + endif() + endforeach() + + set(enable_andesperf "0") + if(${enable_dsp} STREQUAL "1") + set(enable_andesperf "1") + endif() + + if(NOT lib_io_type) + set(lib_io_type STD) + endif() + + if(NOT debug_target_conn) + set(debug_target_conn ${IAR_DBG_CONN_GDB_SRV}) + endif() + + foreach (lib_src IN ITEMS ${target_lib_sources}) + set(target_sources "${target_sources},${lib_src}") + endforeach () + + if (NOT IS_ABSOLUTE ${target_linker}) + set(target_linker ${CMAKE_CURRENT_SOURCE_DIR}/${target_linker}) + endif() + + if(EXISTS ${target_linker}) + message(STATUS "IAR linker script: " ${target_linker}) + else() + message(WARNING "IAR: can not locate linker script: " ${target_linker}) + return() + endif() + + # Remove duplicates + list(REMOVE_DUPLICATES target_sources) + list(REMOVE_DUPLICATES target_include_dirs) + list(REMOVE_DUPLICATES target_iar_include_dirs) + + set(target_sources_with_macro "") + foreach (target_source IN ITEMS ${target_sources}) + if(NOT IS_ABSOLUTE ${target_source}) + set(target_source ${CMAKE_CURRENT_SOURCE_DIR}/${target_source}) + endif() + if("${target_source_with_macro}" STREQUAL "") + set(target_sources_with_macro "${target_source}") + else() + set(target_sources_with_macro "${target_sources_with_macro},${target_source}") + endif() + endforeach () + + list(REMOVE_DUPLICATES target_sources_with_macro) + + set(target_include_dirs_with_macro "") + foreach (target_source IN ITEMS ${target_include_dirs} ${target_iar_include_dirs} ${target_app_include_dirs}) + string(FIND ${target_source} $ENV{GNURISCV_TOOLCHAIN_PATH} position) + if(${position} EQUAL 0) + continue() + endif() + if(NOT IS_ABSOLUTE ${target_source}) + set(target_source ${CMAKE_CURRENT_SOURCE_DIR}/${target_source}) + endif() + if("${target_include_dirs_with_macro}" STREQUAL "") + set(target_include_dirs_with_macro ${target_source}) + else() + set(target_include_dirs_with_macro "${target_include_dirs_with_macro},${target_source}") + endif() + endforeach () + + if(NOT "${target_defines}" STREQUAL "") + set(target_defines_escaped "") + foreach (defs IN ITEMS ${target_defines}) + string(REGEX REPLACE "\"" "\\\\\"" escaped ${defs}) + if("${target_defines_escaped}" STREQUAL "") + set(target_defines_escaped ${escaped}) + else() + set(target_defines_escaped "${target_defines_escaped},${escaped}") + endif() + endforeach() + else() + set(target_defines_escaped ${target_defines}) + endif() + + set(target_register_definition "${HPM_SDK_BASE}/soc/${HPM_SOC}/hpm_iar_reg.xml") + set(target_cpu_register_definition "${HPM_SDK_BASE}/soc/${HPM_SOC}/hpm_iar_riscv_cpu_regs.xml") + + string(REPLACE "\\" "/" target_sources_with_macro ${target_sources_with_macro}) + string(REPLACE "\\" "/" target_include_dirs_with_macro ${target_include_dirs_with_macro}) + string(REPLACE "\\" "/" target_linker ${target_linker}) + string(REPLACE "\\" "/" target_register_definition ${target_register_definition}) + string(REPLACE "\\" "/" target_cpu_register_definition ${target_cpu_register_definition}) + string(REPLACE "\\" "/" hpm_sdk_base_path ${HPM_SDK_BASE}) + string(REPLACE "\\" "/" hpm_board_path ${HPM_BOARD_DIR}) + + if(IAR_COMPILER_ABI) + set(target_compiler_abi ${IAR_COMPILER_ABI}) + else() + set(target_compiler_abi "ilp32") + endif() + + if(IAR_COMPILER_ARCH) + set(target_compiler_arch ${IAR_COMPILER_ARCH}) + else() + set(target_compiler_arch "rv32ima") + endif() + + if(${enable_dsp}) + set(target_compiler_arch "${target_compiler_arch}_Xandesdsp") + endif() + + if(${enable_andesperf}) + set(target_compiler_arch "${target_compiler_arch}_Xandesperf") + endif() + + if(IAR_COMPILER_ARCH_EXTS) + STRING(REPLACE "_" ";" RESULT ${IAR_COMPILER_ARCH_EXTS}) + FOREACH(i IN LISTS RESULT) + if(${i} STREQUAL "zicsr") + set(target_compiler_arch_exts_csr 1) + endif() + if(${i} STREQUAL "zifencei") + set(target_compiler_arch_exts_fencei 1) + endif() + ENDFOREACH() + endif() + + + # Specify IAR target device name to be defined in IAR project file + if (NOT HPM_DEVICE_NAME) + set(IAR_DEVICE_NAME "${HPM_SOC}XXXX") + else() + set(IAR_DEVICE_NAME ${HPM_DEVICE_NAME}) + endif() + + if (${is_secondary_core}) + set(IAR_DEVICE_NAME "${HPM_DEVICE_NAME}_CPU1") + endif() + + message(STATUS "IAR device name: ${IAR_DEVICE_NAME}") + set(IAR_DEVICE_NAME "${IAR_DEVICE_NAME}\\tHPMicro ${IAR_DEVICE_NAME}") + + set(linkded_project_name "") + set(linkded_project_path "") + if (LINKED_PROJECT_NAME) + set(linked_project_name ${LINKED_PROJECT_NAME}) + else() + set(linkded_project_name "Untitled") + endif() + if (IS_ABSOLUTE ${LINKED_PROJECT_PATH}) + set(linked_project_path ${LINKED_PROJECT_PATH}) + else() + set(linked_project_path "${CMAKE_CURRENT_SOURCE_DIR}/${LINKED_PROJECT_PATH}") + endif() + string(REPLACE "\\" "/" linked_project_path ${linked_project_path}) + + if (NOT EXISTS ${linked_project_path}) + message(WARNING "linked project ${linked_project_path} can not be located") + endif() + + set(target_data " + \"name\": \"${CMAKE_PROJECT_NAME}\", + \"sources\": \"${target_sources_with_macro}\", + \"includes\": \"${target_include_dirs_with_macro}\", + \"defines\":\"${target_defines_escaped}\", + \"linker\":\"${target_linker}\", + \"link_symbols\":\"${target_link_symbols}\", + \"sdk_base\":\"${hpm_sdk_base_path}\", + \"board\":\"${BOARD}\", + \"board_dir\":\"${hpm_board_path}\", + \"soc\":\"${HPM_SOC}\", + \"register_definition\":\"${target_register_definition}\", + \"cpu_register_definition\":\"${target_cpu_register_definition}\", + \"post_build_command\":\"${post_build_command}\", + \"heap_size\":\"${HEAP_SIZE}\", + \"stack_size\":\"${STACK_SIZE}\", + \"cplusplus\":\"${CMAKE_CXX_STANDARD}\", + \"gcc_opt_level\":\"${gcc_opt_level}\", + \"target_device_name\":\"${IAR_DEVICE_NAME}\", + \"cflags\":\"${target_cflags}\", + \"compiler_abi\":\"${target_compiler_abi}\", + \"compiler_arch\":\"${target_compiler_arch}\", + \"compiler_arch_exts_csr\":\"${target_compiler_arch_exts_csr}\", + \"compiler_arch_exts_fencei\":\"${target_compiler_arch_exts_fencei}\", + \"iar_link_input\":\"${target_iar_ld_input}\", + \"enable_dsp\":\"${enable_dsp}\", + \"enable_andesperf\":\"${enable_andesperf}\", + \"enable_cpp_exceptions\":\"${enable_cpp_exceptions}\", + \"extra_iar_options\":\"${iar_extra_options}\", + \"linked_project_name\":\"${linked_project_name}\", + \"linked_project_path\":\"${linked_project_path}\", + \"is_secondary_core\":\"${is_secondary_core}\", + \"cc_preinclude\":\"${cc_preinclude}\", + \"asm_preinclude\":\"${asm_preinclude}\", + \"iar_opt_no_size_const\":\"${iar_opt_no_size_const}\" + ") + + set(IAR_PROJECT_PATH "${CMAKE_CURRENT_BINARY_DIR}/iar_embedded_workbench") + set(IAR_JSON_FILE_PATH "${IAR_PROJECT_PATH}/${CMAKE_PROJECT_NAME}.json") + set(SDK_SCRIPT_IDE_PATH "${HPM_SDK_BASE}/scripts/ide") + file(WRITE ${IAR_JSON_FILE_PATH} + "{ + \"target\": { + ${target_data} + } + }") + + execute_process( + COMMAND ${PYTHON_EXECUTABLE} ${SDK_SCRIPT_IDE_PATH}/iar/embedded_workbench_proj_gen.py "${IAR_JSON_FILE_PATH}" "${IAR_PROJECT_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}" + WORKING_DIRECTORY ${SDK_SCRIPT_IDE_PATH}/iar + ) +endfunction () diff --git a/cmake/ide/segger.cmake b/cmake/ide/segger.cmake index 5be4fd7aa..19200d1f1 100644 --- a/cmake/ide/segger.cmake +++ b/cmake/ide/segger.cmake @@ -1,4 +1,4 @@ -# Copyright (c) 2021-2022 HPMicro +# Copyright (c) 2021-2024 HPMicro # SPDX-License-Identifier: BSD-3-Clause # add ses library interface to store ses specific configurations @@ -20,30 +20,60 @@ set(SES_DBG_CONN_GDB_SRV "GDB Server") set(HPM_SDK_SES_OPTS hpm_sdk_ses_opts) define_property(GLOBAL PROPERTY ${HPM_SDK_SES_OPTS} BRIEF_DOCS "ses options" FULL_DOCS "ses options") +# Set compile options for SES +# +# Example: +# sdk_ses_compile_options(opts) +# :param opts: compile options +# @public +# function(sdk_ses_compile_options) foreach(opt ${ARGN}) target_compile_options(${HPM_SDK_SES_LIB_ITF} INTERFACE ${opt}) endforeach() endfunction() +# Set compile definitions for SES +# +# Example: +# sdk_ses_compile_definitions(def) +# :param def: compiler preprocesing definition +# @public +# function(sdk_ses_compile_definitions) foreach(def ${ARGN}) target_compile_definitions(${HPM_SDK_SES_LIB_ITF} INTERFACE ${def}) endforeach() endfunction() +# link libraries for SES +# +# Example: +# sdk_ses_link_libraries(libs) +# :param libs: standard libraries to be linked for SES +# @public +# function(sdk_ses_link_libraries) foreach(lib ${ARGN}) target_link_libraries(${HPM_SDK_SES_LIB_ITF} INTERFACE ${lib}) endforeach() endfunction() +# @private +# function(sdk_ses_ld_options) foreach(opt ${ARGN}) target_link_libraries(${HPM_SDK_SES_LIB_ITF} INTERFACE ${opt}) endforeach() endfunction() +# link libraries for SES +# +# Example: +# sdk_ses_ld_libs(libs) +# :param libs: libraries to be linked for SES +# @private +# function(sdk_ses_ld_lib) foreach(l ${ARGN}) if(IS_ABSOLUTE ${l}) @@ -59,12 +89,39 @@ function(sdk_ses_ld_lib) endforeach() endfunction() +# Add include path for SES +# +# Example: +# sdk_ses_link_libraries(libs) +# :param libs: libraries to be linked for SES +# @public +# +function(sdk_ses_inc) + foreach(inc ${ARGN}) + if(IS_ABSOLUTE ${inc}) + set(path ${inc}) + else() + set(path ${CMAKE_CURRENT_SOURCE_DIR}/${inc}) + endif() + target_include_directories(${HPM_SDK_SES_LIB_ITF} INTERFACE ${path}) + endforeach() +endfunction() + +# @private +# function(sdk_ses_ld_lib_ifdef feature) if((${feature}) AND (NOT ${${feature}} EQUAL 0)) sdk_ses_ld_lib(${ARGN}) endif() endfunction() +# Add source file for SES +# +# Example: +# sdk_ses_src(SOURCE_FILE) +# :param SOURCE_FILE: source file added for SES +# @public +# function(sdk_ses_src) foreach(file ${ARGN}) if(IS_DIRECTORY ${file}) @@ -79,6 +136,22 @@ function(sdk_ses_src) endforeach() endfunction() +# Add source file (glob pattern) for SES +# +# Example: +# sdk_gcc_src_glob(SOURCE_FILE_GLOB) +# :param SOURCE_FILE_GLOB: source files to be added to SES, +# like ./**/*.c to add all .c files under current directory recursively +# @public +# +function(sdk_ses_src_glob) + foreach(g ${ARGN}) + file(GLOB src ${g}) + list(APPEND globbed_src ${src}) + endforeach() + sdk_ses_src(${globbed_src}) +endfunction() + function(sdk_ses_options) foreach(opt ${ARGN}) set_property(GLOBAL APPEND PROPERTY ${HPM_SDK_SES_OPTS} ${opt}) @@ -111,6 +184,7 @@ function (generate_ses_project) get_property(target_ses_source_files GLOBAL PROPERTY ${HPM_SDK_SES_LIB}) get_property(target_ses_options GLOBAL PROPERTY ${HPM_SDK_SES_OPTS}) get_property(target_gcc_source_files TARGET ${HPM_SDK_GCC_LIB} PROPERTY SOURCES) + get_property(target_ses_include_dirs TARGET ${HPM_SDK_SES_LIB_ITF} PROPERTY INTERFACE_INCLUDE_DIRECTORIES) if(NOT SES_TOOLCHAIN_VARIANT) set(SES_TOOLCHAIN_VARIANT "Standard") @@ -301,12 +375,10 @@ function (generate_ses_project) # if Andes toolchain has not been specified, gcc linker script should be used set(target_linker ${target_linker_script}) else() - if(SEGGER_LINKER_FILE) - # SEGGER_LINKER_FILE is specified - set(target_linker ${SEGGER_LINKER_FILE}) + if(CUSTOM_SES_LINKER_FILE) + set(target_linker ${CUSTOM_SES_LINKER_FILE}) else() - # if SEGGER_LINKER_FILE is not specified, try to locate segger linker - # located in segger folder naming with ".icf" rather than ".ld" + # if no specific linker file is set, try to locate it string(REPLACE ".ld" ".icf" target_linker ${target_linker_script}) string(REPLACE "/gcc/" "/segger/" target_linker ${target_linker}) endif() @@ -440,6 +512,21 @@ function (generate_ses_project) endif() endforeach () + foreach (target_source IN ITEMS ${target_ses_include_dirs}) + string(FIND ${target_source} $ENV{GNURISCV_TOOLCHAIN_PATH} position) + if(${position} EQUAL 0) + continue() + endif() + if(NOT IS_ABSOLUTE ${target_source}) + set(target_source ${CMAKE_CURRENT_SOURCE_DIR}/${target_source}) + endif() + if("${target_include_dirs_with_macro}" STREQUAL "") + set(target_include_dirs_with_macro ${target_source}) + else() + set(target_include_dirs_with_macro "${target_include_dirs_with_macro},${target_source}") + endif() + endforeach () + foreach (target_source IN ITEMS ${target_app_include_dirs}) string(FIND ${target_source} $ENV{GNURISCV_TOOLCHAIN_PATH} position) if(${position} EQUAL 0) @@ -511,6 +598,7 @@ function (generate_ses_project) else() set(SES_DEVICE_NAME ${HPM_DEVICE_NAME}) endif() + message(STATUS "Segger device name: ${SES_DEVICE_NAME}") if(${is_secondary_core}) set(SES_DEVICE_NAME "${HPM_DEVICE_NAME}_CPU1") @@ -571,8 +659,10 @@ function (generate_ses_project) endif() endif() - message(STATUS "Segger device name: ${SES_DEVICE_NAME}") - file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.json + set(SES_PROJECT_PATH "${CMAKE_CURRENT_BINARY_DIR}/segger_embedded_studio") + set(SES_JSON_FILE_PATH "${SES_PROJECT_PATH}/${CMAKE_PROJECT_NAME}.json") + set(SDK_SCRIPT_IDE_PATH "${HPM_SDK_BASE}/scripts/ide") + file(WRITE ${SES_JSON_FILE_PATH} "{ \"target\": { ${target_data} @@ -580,7 +670,7 @@ function (generate_ses_project) }") execute_process( - COMMAND ${PYTHON_EXECUTABLE} ${HPM_SDK_BASE}/scripts/segger/embedded_studio_proj_gen.py "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_PROJECT_NAME}.json" "${CMAKE_CURRENT_BINARY_DIR}/segger_embedded_studio" "${CMAKE_CURRENT_SOURCE_DIR}" - WORKING_DIRECTORY ${HPM_SDK_BASE}/scripts/segger + COMMAND ${PYTHON_EXECUTABLE} ${SDK_SCRIPT_IDE_PATH}/segger/embedded_studio_proj_gen.py "${SES_JSON_FILE_PATH}" "${SES_PROJECT_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}" + WORKING_DIRECTORY ${SDK_SCRIPT_IDE_PATH}/segger ) endfunction () diff --git a/cmake/localize_sdk.cmake b/cmake/localize_sdk.cmake new file mode 100644 index 000000000..718cd3e44 --- /dev/null +++ b/cmake/localize_sdk.cmake @@ -0,0 +1,42 @@ +# Copyright (c) 2024 HPMicro +# SPDX-License-Identifier: BSD-3-Clause + +if(UNLOCALIZE_PROJECT) + if(EXISTS "${SRC_DIR}/CMakeLists.txt.localized.bak") + file(TO_CMAKE_PATH ${HPM_SDK_BASE}/scripts/localize_sdk.py LOCALIZE_PYTHON_SCRIPT) + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} + ${LOCALIZE_PYTHON_SCRIPT} + --gnt=${GENERATOR} + --sdk=${HPM_SDK_BASE} + --src=${SRC_DIR} + --bld=${BIN_DIR} + --dst=${DST_DIR} + --brd=${BOARD} + --unlocalize + WORKING_DIRECTORY ${BIN_DIR} + ) + else() + message(WARNING "\nproject has not been localized yet, localize it first!") + endif() +else() + if(NOT EXISTS "${SRC_DIR}/CMakeLists.txt.localized.bak") + file(TO_CMAKE_PATH ${HPM_SDK_BASE}/scripts/localize_sdk.py LOCALIZE_PYTHON_SCRIPT) + execute_process( + COMMAND + ${PYTHON_EXECUTABLE} + ${LOCALIZE_PYTHON_SCRIPT} + --gnt=${GENERATOR} + --sdk=${HPM_SDK_BASE} + --src=${SRC_DIR} + --bld=${BIN_DIR} + --dst=${DST_DIR} + --brd=${BOARD} + -f + WORKING_DIRECTORY ${BIN_DIR} + ) + else() + message(WARNING "\nproject has been localized already, unlocalize it first!") + endif() +endif() diff --git a/cmake/toolchain.cmake b/cmake/toolchain.cmake index 81e02098e..421c14ae7 100644 --- a/cmake/toolchain.cmake +++ b/cmake/toolchain.cmake @@ -80,7 +80,9 @@ else() endif() set(CROSS_COMPILE ${TOOLCHAIN_HOME}/bin/${CROSS_COMPILE_TARGET}-) -set(SYSROOT_DIR ${TOOLCHAIN_HOME}/${SYSROOT_TARGET}) +if(SYSROOT_TARGET) + set(SYSROOT_DIR ${TOOLCHAIN_HOME}/${SYSROOT_TARGET}/include/c++/${COMPILER_VERSION}) +endif() message(STATUS "Found toolchain: gnu (${GNURISCV_TOOLCHAIN_PATH})") @@ -154,3 +156,9 @@ find_program(CMAKE_CXX_COMPILER ${CROSS_COMPILE}${CXX} PATHS ${TOOLCHAIN_HOME} # include toolchain specific settings include(${HPM_SDK_BASE}/cmake/toolchain/${TOOLCHAIN_CMAKE}) +function (generate_bin2c_array c_array_path) + add_custom_command( + TARGET ${APP_ELF_NAME} + COMMAND ${PYTHON_EXECUTABLE} $ENV{HPM_SDK_BASE}/scripts/bin2c.py ${EXECUTABLE_OUTPUT_PATH}/${APP_BIN_NAME} sec_core_img > ${c_array_path} + ) +endfunction () diff --git a/cmake/toolchain/gcc.cmake b/cmake/toolchain/gcc.cmake index 47b309625..650b56fd4 100644 --- a/cmake/toolchain/gcc.cmake +++ b/cmake/toolchain/gcc.cmake @@ -1,9 +1,6 @@ # Copyright (c) 2021 HPMicro # SPDX-License-Identifier: BSD-3-Clause - -sdk_inc(${TOOLCHAIN_HOME}/lib/gcc/${CROSS_COMPILE_TARGET}/${COMPILER_VERSION}/include) -sdk_sys_inc(${TOOLCHAIN_HOME}/${CROSS_COMPILE_TARGET}/include/c++/${COMPILER_VERSION}) sdk_compile_options("-Wall") sdk_compile_options("-Wundef") sdk_compile_options("-Wno-format") @@ -34,9 +31,3 @@ endif() endif() -function (generate_bin2c_array c_array_path) - add_custom_command( - TARGET ${APP_ELF_NAME} - COMMAND ${PYTHON_EXECUTABLE} $ENV{HPM_SDK_BASE}/scripts/bin2c.py ${EXECUTABLE_OUTPUT_PATH}/${APP_BIN_NAME} sec_core_img > ${c_array_path} - ) -endfunction () diff --git a/cmake/toolchain/llvm.cmake b/cmake/toolchain/llvm.cmake index eb56b5334..6bea1ffa4 100644 --- a/cmake/toolchain/llvm.cmake +++ b/cmake/toolchain/llvm.cmake @@ -11,9 +11,3 @@ sdk_compile_options("-fdata-sections") include(${HPM_SDK_BASE}/cmake/toolchain/lld.cmake) -function (generate_bin2c_array c_array_path) - add_custom_command( - TARGET ${APP_ELF_NAME} - COMMAND ${PYTHON_EXECUTABLE} $ENV{HPM_SDK_BASE}/scripts/bin2c.py ${APP_BIN_NAME} sec_core_img > ${c_array_path} - ) -endfunction () \ No newline at end of file diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index d37d5099c..5be1edfba 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -7,7 +7,6 @@ add_subdirectory(enet_phy) add_subdirectory_ifndef(CONFIG_NDEBUG_CONSOLE debug_console) add_subdirectory_ifdef(CONFIG_CAMERA camera) add_subdirectory_ifdef(CONFIG_CODEC codec) -add_subdirectory_ifdef(CONFIG_USB_HOST usb/host) add_subdirectory_ifdef(CONFIG_USB_DEVICE usb/device) add_subdirectory_ifdef(CONFIG_TOUCH touch) add_subdirectory_ifdef(CONFIG_HPM_ADC adc) diff --git a/components/codec/sgtl5000/hpm_sgtl5000.h b/components/codec/sgtl5000/hpm_sgtl5000.h index 96e676b30..dbf146933 100644 --- a/components/codec/sgtl5000/hpm_sgtl5000.h +++ b/components/codec/sgtl5000/hpm_sgtl5000.h @@ -836,7 +836,7 @@ typedef struct _sgtl_config { } sgtl_config_t; typedef struct { - I2C_Type *ptr;; /*!< sgtl I2C pointer */ + I2C_Type *ptr; /*!< sgtl I2C pointer */ uint8_t slave_address; /*!< code device slave address */ } sgtl_context_t; diff --git a/components/codec/wm8960/hpm_wm8960.c b/components/codec/wm8960/hpm_wm8960.c index 9f96f2640..25493d128 100644 --- a/components/codec/wm8960/hpm_wm8960.c +++ b/components/codec/wm8960/hpm_wm8960.c @@ -52,6 +52,9 @@ hpm_stat_t wm8960_init(wm8960_control_t *control, wm8960_config_t *config) /* set wm8960 as slave */ HPM_CHECK_RET(wm8960_modify_reg(control, WM8960_IFACE1, WM8960_IFACE1_MS_MASK, WM8960_IFACE1_MS_SET(0))); + /* invert LRCLK */ + HPM_CHECK_RET(wm8960_modify_reg(control, WM8960_IFACE1, WM8960_IFACE1_LRP_MASK, WM8960_IFACE1_LRP_SET(1))); + HPM_CHECK_RET(wm8960_write_reg(control, WM8960_ADDCTL1, 0xC0)); HPM_CHECK_RET(wm8960_write_reg(control, WM8960_ADDCTL4, 0x40)); diff --git a/components/codec/wm8960/hpm_wm8960.h b/components/codec/wm8960/hpm_wm8960.h index 10d4be18e..6b8540736 100644 --- a/components/codec/wm8960/hpm_wm8960.h +++ b/components/codec/wm8960/hpm_wm8960.h @@ -81,7 +81,7 @@ typedef struct wm8960_config { } wm8960_config_t; typedef struct { - I2C_Type *ptr;; /* I2C bus */ + I2C_Type *ptr; /* I2C bus */ uint8_t slave_address; /* code device address */ } wm8960_control_t; diff --git a/components/debug_console/hpm_debug_console.c b/components/debug_console/hpm_debug_console.c index 60087a1eb..d23935db9 100644 --- a/components/debug_console/hpm_debug_console.c +++ b/components/debug_console/hpm_debug_console.c @@ -5,7 +5,9 @@ * */ +#ifndef __ICCRISCV__ #include +#endif #include "hpm_debug_console.h" #include "hpm_uart_drv.h" @@ -146,9 +148,26 @@ int _read(int file, char *s, int size) return 1; } +#ifndef __ICCRISCV__ int _fstat(int file, struct stat *s) { (void) file; s->st_mode = S_IFCHR; return 0; } +#else + +#ifndef _DLIB_FILE_DESCRIPTOR +#define _DLIB_FILE_DESCRIPTOR 0 +#endif + +int __write(int file, char *data, int size) +{ + return _write(file, data, size); +} + +int __read(int file, char *s, int size) +{ + return _read(file, s, size); +} +#endif diff --git a/components/dma_mgr/hpm_dma_mgr.c b/components/dma_mgr/hpm_dma_mgr.c index ec8e39b6b..19068e5c3 100644 --- a/components/dma_mgr/hpm_dma_mgr.c +++ b/components/dma_mgr/hpm_dma_mgr.c @@ -83,7 +83,7 @@ static dma_mgr_context_t s_dma_mngr_ctx; * Codes * *****************************************************************************************************************/ -static inline void handle_dma_isr(DMA_Type *ptr, uint32_t instance) +void dma_mgr_isr_handler(DMA_Type *ptr, uint32_t instance) { uint32_t int_disable_mask; uint32_t chn_int_stat; @@ -119,13 +119,13 @@ static inline void handle_dma_isr(DMA_Type *ptr, uint32_t instance) void dma0_isr(void) { - handle_dma_isr(HPM_HDMA, 0); + dma_mgr_isr_handler(HPM_HDMA, 0); } #if defined(DMA_SOC_MAX_COUNT) && (DMA_SOC_MAX_COUNT > 1) void dma1_isr(void) { - handle_dma_isr(HPM_XDMA, 1); + dma_mgr_isr_handler(HPM_XDMA, 1); } #endif diff --git a/components/dma_mgr/hpm_dma_mgr.h b/components/dma_mgr/hpm_dma_mgr.h index 84cf87f34..783ed4504 100644 --- a/components/dma_mgr/hpm_dma_mgr.h +++ b/components/dma_mgr/hpm_dma_mgr.h @@ -143,6 +143,11 @@ typedef struct hpm_dma_mgr_linked_descriptor { uint32_t descriptor[8]; } dma_mgr_linked_descriptor_t; +/** + * @brief DMA Manager ISR handler + */ +void dma_mgr_isr_handler(DMA_Type *ptr, uint32_t instance); + /** * @brief Initialize DMA Manager Context */ diff --git a/components/enet_phy/CMakeLists.txt b/components/enet_phy/CMakeLists.txt index 9055e4e8c..9b398aa40 100644 --- a/components/enet_phy/CMakeLists.txt +++ b/components/enet_phy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2022-2023 HPMicro +# Copyright (c) 2022-2024 HPMicro # SPDX-License-Identifier: BSD-3-Clause sdk_inc(.) @@ -21,4 +21,9 @@ endif() if($ENV{CONFIG_ENET_PHY_DP83848}) add_subdirectory(dp83848) message(STATUS "ENet PHY Enabled: DP83848") +endif() + +if($ENV{CONFIG_ENET_PHY_LAN8720}) + add_subdirectory(lan8720) + message(STATUS "ENet PHY Enabled: LAN8720") endif() \ No newline at end of file diff --git a/components/enet_phy/dp83848/hpm_dp83848.c b/components/enet_phy/dp83848/hpm_dp83848.c index eedf0702a..b48617bda 100644 --- a/components/enet_phy/dp83848/hpm_dp83848.c +++ b/components/enet_phy/dp83848/hpm_dp83848.c @@ -12,6 +12,7 @@ #include "hpm_enet_drv.h" #include "hpm_dp83848_regs.h" #include "hpm_dp83848.h" + /*--------------------------------------------------------------------- * Internal API *--------------------------------------------------------------------- diff --git a/components/enet_phy/hpm_enet_phy.h b/components/enet_phy/hpm_enet_phy.h index e2ff32796..5047258db 100644 --- a/components/enet_phy/hpm_enet_phy.h +++ b/components/enet_phy/hpm_enet_phy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -8,6 +8,11 @@ #define HPM_ENET_PHY_H #include +typedef enum { + enet_phy_link_down = 0, + enet_phy_link_up +} enet_phy_link_status_t; + typedef enum { enet_phy_port_speed_10mbps = 0, enet_phy_port_speed_100mbps, diff --git a/components/enet_phy/hpm_enet_phy_common.h b/components/enet_phy/hpm_enet_phy_common.h index 7557733e9..5bb3b0add 100644 --- a/components/enet_phy/hpm_enet_phy_common.h +++ b/components/enet_phy/hpm_enet_phy_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -27,4 +27,9 @@ #include "hpm_rtl8201_regs.h" #endif +#if defined(__USE_LAN8720) && __USE_LAN8720 + #include "hpm_lan8720.h" + #include "hpm_lan8720_regs.h" +#endif + #endif /* HPM_ENET_PHY_H */ diff --git a/components/enet_phy/lan8720/CMakeLists.txt b/components/enet_phy/lan8720/CMakeLists.txt new file mode 100644 index 000000000..407d93e3e --- /dev/null +++ b/components/enet_phy/lan8720/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 HPMicro +# SPDX-License-Identifier: BSD-3-Clause + +sdk_compile_definitions(-D__USE_LAN8720=1) + +sdk_inc(.) +sdk_inc(../) +sdk_src(hpm_lan8720.c) diff --git a/components/enet_phy/lan8720/hpm_lan8720.c b/components/enet_phy/lan8720/hpm_lan8720.c new file mode 100644 index 000000000..e487972eb --- /dev/null +++ b/components/enet_phy/lan8720/hpm_lan8720.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/*--------------------------------------------------------------------- + * Includes + *--------------------------------------------------------------------- + */ +#include "hpm_enet_drv.h" +#include "hpm_lan8720_regs.h" +#include "hpm_lan8720.h" + +/*--------------------------------------------------------------------- + * Internal API + *--------------------------------------------------------------------- + */ +static bool lan8720_check_id(ENET_Type *ptr) +{ + uint16_t id1, id2; + + id1 = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_PHYID1); + id2 = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_PHYID2); + + if (LAN8720_PHYID1_OUI_MSB_GET(id1) == LAN8720_ID1 && LAN8720_PHYID2_OUI_LSB_GET(id2) == LAN8720_ID2) { + return true; + } else { + return false; + } +} + +/*--------------------------------------------------------------------- + * API + *--------------------------------------------------------------------- + */ +void lan8720_reset(ENET_Type *ptr) +{ + uint16_t data; + + /* PHY reset */ + enet_write_phy(ptr, LAN8720_ADDR, LAN8720_BMCR, LAN8720_BMCR_RESET_SET(1)); + + /* wait until the reset is completed */ + do { + data = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_BMCR); + } while (LAN8720_BMCR_RESET_GET(data)); +} + +void lan8720_basic_mode_default_config(ENET_Type *ptr, lan8720_config_t *config) +{ + config->loopback = false; /* Disable PCS loopback mode */ + #if defined(__DISABLE_AUTO_NEGO) && __DISABLE_AUTO_NEGO + config->auto_negotiation = false; /* Disable Auto-Negotiation */ + config->speed = enet_phy_port_speed_100mbps; + config->duplex = enet_phy_duplex_full; + #else + config->auto_negotiation = true; /* Enable Auto-Negotiation */ + #endif +} + +bool lan8720_basic_mode_init(ENET_Type *ptr, lan8720_config_t *config) +{ + uint16_t data = 0; + + data |= LAN8720_BMCR_RESET_SET(0) /* Normal operation */ + | LAN8720_BMCR_LOOPBACK_SET(config->loopback) /* configure PCS loopback mode */ + | LAN8720_BMCR_ANE_SET(config->auto_negotiation) /* configure Auto-Negotiation */ + | LAN8720_BMCR_PWD_SET(0) /* Normal operation */ + | LAN8720_BMCR_ISOLATE_SET(0) /* Normal operation */ + | LAN8720_BMCR_RESTART_AN_SET(0); /* Normal operation (ignored when Auto-Negotiation is disabled) */ + + if (config->auto_negotiation == 0) { + data |= LAN8720_BMCR_SPEED_SET(config->speed); /* Set port speed */ + data |= LAN8720_BMCR_DUPLEX_SET(config->duplex); /* Set duplex mode */ + } + + /* check the id of lan8720 */ + if (lan8720_check_id(ptr) == false) { + return false; + } + + enet_write_phy(ptr, LAN8720_ADDR, LAN8720_BMCR, data); + + return true; +} + +void lan8720_get_phy_status(ENET_Type *ptr, enet_phy_status_t *status) +{ + uint16_t data; + + data = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_BMSR); + status->enet_phy_link = LAN8720_BMSR_LINK_STATUS_GET(data); + + data = enet_read_phy(ptr, LAN8720_ADDR, LAN8720_PSCSR); + status->enet_phy_speed = LAN8720_PSCSR_SPEED_GET(data) == 1 ? enet_phy_port_speed_10mbps : enet_phy_port_speed_100mbps; + status->enet_phy_duplex = LAN8720_PSCSR_DUPLEX_GET(data); +} diff --git a/components/enet_phy/lan8720/hpm_lan8720.h b/components/enet_phy/lan8720/hpm_lan8720.h new file mode 100644 index 000000000..2f31ca906 --- /dev/null +++ b/components/enet_phy/lan8720/hpm_lan8720.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef HPM_LAN8720_H +#define HPM_LAN8720_H + +/*--------------------------------------------------------------------- + * Includes + *--------------------------------------------------------------------- + */ +#include "hpm_enet_phy.h" +#include "hpm_common.h" +#include "hpm_enet_regs.h" +/*--------------------------------------------------------------------- + * Macro Const Definitions + *--------------------------------------------------------------------- + */ +#ifndef LAN8720_ADDR +#define LAN8720_ADDR (0U) +#endif + +#define LAN8720_ID1 (0x0007U) +#define LAN8720_ID2 (0x30U) + +/*--------------------------------------------------------------------- + * Typedef Struct Declarations + *--------------------------------------------------------------------- + */ +typedef struct { + bool loopback; + uint8_t speed; + bool auto_negotiation; + uint8_t duplex; +} lan8720_config_t; + +#if defined(__cplusplus) +extern "C" { +#endif /* __cplusplus */ +/*--------------------------------------------------------------------- + * Exported Functions + *--------------------------------------------------------------------- + */ +void lan8720_reset(ENET_Type *ptr); +void lan8720_basic_mode_default_config(ENET_Type *ptr, lan8720_config_t *config); +bool lan8720_basic_mode_init(ENET_Type *ptr, lan8720_config_t *config); +void lan8720_get_phy_status(ENET_Type *ptr, enet_phy_status_t *status); + +#if defined(__cplusplus) +} +#endif /* __cplusplus */ +#endif /* HPM_LAN8720_H */ diff --git a/components/enet_phy/lan8720/hpm_lan8720_regs.h b/components/enet_phy/lan8720/hpm_lan8720_regs.h new file mode 100644 index 000000000..522057cce --- /dev/null +++ b/components/enet_phy/lan8720/hpm_lan8720_regs.h @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef HPM_LAN8720_REGS_H +#define HPM_LAN8720_REGS_H + +typedef enum { + LAN8720_BMCR = 0, /* 0x0: Basic Mode Control Register */ + LAN8720_BMSR = 1, /* 0x1: Basic Mode Status Register */ + LAN8720_PHYID1 = 2, /* 0x2: PHY Identifier Register 1 */ + LAN8720_PHYID2 = 3, /* 0x3: PHY Identifier Register 2 */ + LAN8720_SMR = 18, /* 0x12: Special Modes Register */ + LAN8720_SECR = 26, /* 0x1A: Symbol Error Counter Register */ + LAN8720_ISFR = 29, /* 0x1D: Interrupt Source Flag Register */ + LAN8720_IMR = 30, /* 0x1E: Interrupt Mask Register */ + LAN8720_PSCSR = 31, /* 0x1F: PHY Special Control/Status Register */ +} LAN8720_REG_Type; + + +/* Bitfield definition for register: BMCR */ +/* + * RESET (RW/SC) + * + * 1 = software reset. Bit is self-clearing. When setting this bit do not set other + * bits in this register. The configuration is set from the register bit values, and not + * from the mode pins. + */ +#define LAN8720_BMCR_RESET_MASK (0x8000U) +#define LAN8720_BMCR_RESET_SHIFT (15U) +#define LAN8720_BMCR_RESET_SET(x) (((uint16_t)(x) << LAN8720_BMCR_RESET_SHIFT) & LAN8720_BMCR_RESET_MASK) +#define LAN8720_BMCR_RESET_GET(x) (((uint16_t)(x) & LAN8720_BMCR_RESET_MASK) >> LAN8720_BMCR_RESET_SHIFT) + +/* + * LOOPBACK (RW) + * + * 0 = normal operation + * 1 = loopback mode + */ +#define LAN8720_BMCR_LOOPBACK_MASK (0x4000U) +#define LAN8720_BMCR_LOOPBACK_SHIFT (14U) +#define LAN8720_BMCR_LOOPBACK_SET(x) (((uint16_t)(x) << LAN8720_BMCR_LOOPBACK_SHIFT) & LAN8720_BMCR_LOOPBACK_MASK) +#define LAN8720_BMCR_LOOPBACK_GET(x) (((uint16_t)(x) & LAN8720_BMCR_LOOPBACK_MASK) >> LAN8720_BMCR_LOOPBACK_SHIFT) + +/* + * SPEED (RW) + * + * 0 = 10Mbps + * 1 = 100Mbps + * Ignored if Auto-negotiation is enabled (0.12 = 1). + */ +#define LAN8720_BMCR_SPEED_MASK (0x2000U) +#define LAN8720_BMCR_SPEED_SHIFT (13U) +#define LAN8720_BMCR_SPEED_SET(x) (((uint16_t)(x) << LAN8720_BMCR_SPEED_SHIFT) & LAN8720_BMCR_SPEED_MASK) +#define LAN8720_BMCR_SPEED_GET(x) (((uint16_t)(x) & LAN8720_BMCR_SPEED_MASK) >> LAN8720_BMCR_SPEED_SHIFT) + +/* + * ANE (RW) + * + * Auto-Negotiation Enable + * 0 = disable auto-negotiate process + * 1 = enable auto-negotiate process (overrides 0.13 and 0.8) + */ +#define LAN8720_BMCR_ANE_MASK (0x1000U) +#define LAN8720_BMCR_ANE_SHIFT (12U) +#define LAN8720_BMCR_ANE_SET(x) (((uint16_t)(x) << LAN8720_BMCR_ANE_SHIFT) & LAN8720_BMCR_ANE_MASK) +#define LAN8720_BMCR_ANE_GET(x) (((uint16_t)(x) & LAN8720_BMCR_ANE_MASK) >> LAN8720_BMCR_ANE_SHIFT) + +/* + * PWD (RW) + * + * 0 = normal operation + * 1 = General power down mode + * The Auto-Negotiation Enable must be cleared before setting the Power + * Down. + */ +#define LAN8720_BMCR_PWD_MASK (0x800U) +#define LAN8720_BMCR_PWD_SHIFT (11U) +#define LAN8720_BMCR_PWD_SET(x) (((uint16_t)(x) << LAN8720_BMCR_PWD_SHIFT) & LAN8720_BMCR_PWD_MASK) +#define LAN8720_BMCR_PWD_GET(x) (((uint16_t)(x) & LAN8720_BMCR_PWD_MASK) >> LAN8720_BMCR_PWD_SHIFT) + +/* + * ISOLATE (RW) + * + * 0 = normal operation + * 1 = electrical isolation of PHY from the RMII + */ +#define LAN8720_BMCR_ISOLATE_MASK (0x400U) +#define LAN8720_BMCR_ISOLATE_SHIFT (10U) +#define LAN8720_BMCR_ISOLATE_SET(x) (((uint16_t)(x) << LAN8720_BMCR_ISOLATE_SHIFT) & LAN8720_BMCR_ISOLATE_MASK) +#define LAN8720_BMCR_ISOLATE_GET(x) (((uint16_t)(x) & LAN8720_BMCR_ISOLATE_MASK) >> LAN8720_BMCR_ISOLATE_SHIFT) + +/* + * RESTART_AN (RW/SC) + * + * 0 = normal operation + * 1 = restart auto-negotiate process + * Bit is self-clearing. + */ +#define LAN8720_BMCR_RESTART_AN_MASK (0x200U) +#define LAN8720_BMCR_RESTART_AN_SHIFT (9U) +#define LAN8720_BMCR_RESTART_AN_SET(x) (((uint16_t)(x) << LAN8720_BMCR_RESTART_AN_SHIFT) & LAN8720_BMCR_RESTART_AN_MASK) +#define LAN8720_BMCR_RESTART_AN_GET(x) (((uint16_t)(x) & LAN8720_BMCR_RESTART_AN_MASK) >> LAN8720_BMCR_RESTART_AN_SHIFT) + +/* + * DUPLEX (RW) + * + * 0 = half duplex + * 1 = full duplex + * Ignored if Auto-Negotiation is enabled (0.12 = 1). + */ +#define LAN8720_BMCR_DUPLEX_MASK (0x100U) +#define LAN8720_BMCR_DUPLEX_SHIFT (8U) +#define LAN8720_BMCR_DUPLEX_SET(x) (((uint16_t)(x) << LAN8720_BMCR_DUPLEX_SHIFT) & LAN8720_BMCR_DUPLEX_MASK) +#define LAN8720_BMCR_DUPLEX_GET(x) (((uint16_t)(x) & LAN8720_BMCR_DUPLEX_MASK) >> LAN8720_BMCR_DUPLEX_SHIFT) + +/* Bitfield definition for register: BMSR */ +/* + * 100BASE_T4 (RO) + * + * 0 = no T4 ability + * 1 = T4 able + */ +#define LAN8720_BMSR_100BASE_T4_MASK (0x8000U) +#define LAN8720_BMSR_100BASE_T4_SHIFT (15U) +#define LAN8720_BMSR_100BASE_T4_GET(x) (((uint16_t)(x) & LAN8720_BMSR_100BASE_T4_MASK) >> LAN8720_BMSR_100BASE_T4_SHIFT) + +/* + * 100BASE_TX_FULL (RO) + * + * 0 = no TX full duplex ability + * 1 = TX with full duplex + */ +#define LAN8720_BMSR_100BASE_TX_FULL_MASK (0x4000U) +#define LAN8720_BMSR_100BASE_TX_FULL_SHIFT (14U) +#define LAN8720_BMSR_100BASE_TX_FULL_GET(x) (((uint16_t)(x) & LAN8720_BMSR_100BASE_TX_FULL_MASK) >> LAN8720_BMSR_100BASE_TX_FULL_SHIFT) + +/* + * 100BASE_TX_HALF (RO) + * + * 0 = no TX half duplex ability + * 1 = TX with half duplex + */ +#define LAN8720_BMSR_100BASE_TX_HALF_MASK (0x2000U) +#define LAN8720_BMSR_100BASE_TX_HALF_SHIFT (13U) +#define LAN8720_BMSR_100BASE_TX_HALF_GET(x) (((uint16_t)(x) & LAN8720_BMSR_100BASE_TX_HALF_MASK) >> LAN8720_BMSR_100BASE_TX_HALF_SHIFT) + +/* + * 10BASE_T_FULL (RO) + * + * 0 = no 10Mbps with full duplex ability + * 1 = 10Mbps with full duplex + */ +#define LAN8720_BMSR_10BASE_T_FULL_MASK (0x1000U) +#define LAN8720_BMSR_10BASE_T_FULL_SHIFT (12U) +#define LAN8720_BMSR_10BASE_T_FULL_GET(x) (((uint16_t)(x) & LAN8720_BMSR_10BASE_T_FULL_MASK) >> LAN8720_BMSR_10BASE_T_FULL_SHIFT) + +/* + * 10BASE_T_HALF (RO) + * + * 0 = no 10Mbps with half duplex ability + * 1 = 10Mbps with half duplex + */ +#define LAN8720_BMSR_10BASE_T_HALF_MASK (0x800U) +#define LAN8720_BMSR_10BASE_T_HALF_SHIFT (11U) +#define LAN8720_BMSR_10BASE_T_HALF_GET(x) (((uint16_t)(x) & LAN8720_BMSR_10BASE_T_HALF_MASK) >> LAN8720_BMSR_10BASE_T_HALF_SHIFT) + +/* + * 100BASE_T2_FULL (RO) + * + * 0 = PHY not able to perform full duplex 100BASE-T2 + * 1 = PHY able to perform full duplex 100BASE-T2 + */ +#define LAN8720_BMSR_100BASE_T2_FULL_MASK (0x400U) +#define LAN8720_BMSR_100BASE_T2_FULL_SHIFT (10U) +#define LAN8720_BMSR_100BASE_T2_FULL_GET(x) (((uint16_t)(x) & LAN8720_BMSR_100BASE_T2_FULL_MASK) >> LAN8720_BMSR_100BASE_T2_FULL_SHIFT) + +/* + * 100BASE_T2_HALF (RO) + * + * 0 = PHY not able to perform half duplex 100BASE-T2 + * 1 = PHY able to perform half duplex 100BASE-T2 + */ +#define LAN8720_BMSR_100BASE_T2_HALF_MASK (0x200U) +#define LAN8720_BMSR_100BASE_T2_HALF_SHIFT (9U) +#define LAN8720_BMSR_100BASE_T2_HALF_GET(x) (((uint16_t)(x) & LAN8720_BMSR_100BASE_T2_HALF_MASK) >> LAN8720_BMSR_100BASE_T2_HALF_SHIFT) + +/* + * EXTENDED_STATUS (RO) + * + * 0 = no extended status information in register 15 + * 1 = extended status information in register 15 + */ +#define LAN8720_BMSR_EXTENDED_STATUS_MASK (0x100U) +#define LAN8720_BMSR_EXTENDED_STATUS_SHIFT (8U) +#define LAN8720_BMSR_EXTENDED_STATUS_GET(x) (((uint16_t)(x) & LAN8720_BMSR_EXTENDED_STATUS_MASK) >> LAN8720_BMSR_EXTENDED_STATUS_SHIFT) + +/* + * AUTO_NEGOTIATION_COMPLETE (RO) + * + * 0 = auto-negotiate process not completed + * 1 = auto-negotiate process completed + */ +#define LAN8720_BMSR_AUTO_NEGOTIATION_COMPLETE_MASK (0x20U) +#define LAN8720_BMSR_AUTO_NEGOTIATION_COMPLETE_SHIFT (5U) +#define LAN8720_BMSR_AUTO_NEGOTIATION_COMPLETE_GET(x) (((uint16_t)(x) & LAN8720_BMSR_AUTO_NEGOTIATION_COMPLETE_MASK) >> LAN8720_BMSR_AUTO_NEGOTIATION_COMPLETE_SHIFT) + +/* + * REMOTE_FAULT (RC) + * + * 1 = remote fault condition detected + * 0 = no remote fault + */ +#define LAN8720_BMSR_REMOTE_FAULT_MASK (0x10U) +#define LAN8720_BMSR_REMOTE_FAULT_SHIFT (4U) +#define LAN8720_BMSR_REMOTE_FAULT_GET(x) (((uint16_t)(x) & LAN8720_BMSR_REMOTE_FAULT_MASK) >> LAN8720_BMSR_REMOTE_FAULT_SHIFT) + +/* + * AUTO_NEGOTIATION_ABILITY (RO) + * + * 0 = unable to perform auto-negotiation function + * 1 = able to perform auto-negotiation function + */ +#define LAN8720_BMSR_AUTO_NEGOTIATION_ABILITY_MASK (0x8U) +#define LAN8720_BMSR_AUTO_NEGOTIATION_ABILITY_SHIFT (3U) +#define LAN8720_BMSR_AUTO_NEGOTIATION_ABILITY_GET(x) (((uint16_t)(x) & LAN8720_BMSR_AUTO_NEGOTIATION_ABILITY_MASK) >> LAN8720_BMSR_AUTO_NEGOTIATION_ABILITY_SHIFT) + +/* + * LINK_STATUS (RO) + * + * 0 = link is down + * 1 = link is up + */ +#define LAN8720_BMSR_LINK_STATUS_MASK (0x4U) +#define LAN8720_BMSR_LINK_STATUS_SHIFT (2U) +#define LAN8720_BMSR_LINK_STATUS_GET(x) (((uint16_t)(x) & LAN8720_BMSR_LINK_STATUS_MASK) >> LAN8720_BMSR_LINK_STATUS_SHIFT) + +/* + * JABBER_DETECT (RO) + * + * 0 = no jabber condition detected + * 1 = jabber condition detected + */ +#define LAN8720_BMSR_JABBER_DETECT_MASK (0x2U) +#define LAN8720_BMSR_JABBER_DETECT_SHIFT (1U) +#define LAN8720_BMSR_JABBER_DETECT_GET(x) (((uint16_t)(x) & LAN8720_BMSR_JABBER_DETECT_MASK) >> LAN8720_BMSR_JABBER_DETECT_SHIFT) + +/* + * EXTENDED_CAPABILITY (RO) + * + * 0 = does not support extended capabilities registers + * 1 = supports extended capabilities registers + */ +#define LAN8720_BMSR_EXTENDED_CAPABILITY_MASK (0x1U) +#define LAN8720_BMSR_EXTENDED_CAPABILITY_SHIFT (0U) +#define LAN8720_BMSR_EXTENDED_CAPABILITY_GET(x) (((uint16_t)(x) & LAN8720_BMSR_EXTENDED_CAPABILITY_MASK) >> LAN8720_BMSR_EXTENDED_CAPABILITY_SHIFT) + +/* Bitfield definition for register: PHYID1 */ +/* + * OUI_MSB (RO) + * + * Assigned to the 3rd through 18th bits of the Organizationally Unique Identifier + * (OUI), respectively. + */ +#define LAN8720_PHYID1_OUI_MSB_MASK (0xFFFFU) +#define LAN8720_PHYID1_OUI_MSB_SHIFT (0U) +#define LAN8720_PHYID1_OUI_MSB_GET(x) (((uint16_t)(x) & LAN8720_PHYID1_OUI_MSB_MASK) >> LAN8720_PHYID1_OUI_MSB_SHIFT) + +/* Bitfield definition for register: PHYID2 */ +/* + * OUI_LSB (RO) + * + * Assigned to the 19th through 24th bits of the OUI. + */ +#define LAN8720_PHYID2_OUI_LSB_MASK (0xFC00U) +#define LAN8720_PHYID2_OUI_LSB_SHIFT (10U) +#define LAN8720_PHYID2_OUI_LSB_GET(x) (((uint16_t)(x) & LAN8720_PHYID2_OUI_LSB_MASK) >> LAN8720_PHYID2_OUI_LSB_SHIFT) + +/* + * MODEL_NUMBER (RO) + * + * Six-bit manufacturer’s model number. + */ +#define LAN8720_PHYID2_MODEL_NUMBER_MASK (0x3F0U) +#define LAN8720_PHYID2_MODEL_NUMBER_SHIFT (4U) +#define LAN8720_PHYID2_MODEL_NUMBER_GET(x) (((uint16_t)(x) & LAN8720_PHYID2_MODEL_NUMBER_MASK) >> LAN8720_PHYID2_MODEL_NUMBER_SHIFT) + +/* + * REVISION_NUMBER (RO) + * + * Four-bit manufacturer’s revision number. + */ +#define LAN8720_PHYID2_REVISION_NUMBER_MASK (0xFU) +#define LAN8720_PHYID2_REVISION_NUMBER_SHIFT (0U) +#define LAN8720_PHYID2_REVISION_NUMBER_GET(x) (((uint16_t)(x) & LAN8720_PHYID2_REVISION_NUMBER_MASK) >> LAN8720_PHYID2_REVISION_NUMBER_SHIFT) + +/* Bitfield definition for register: SMR */ +/* + * MODE (R/W) + * + * Transceiver mode of operation + */ +#define LAN8720_SMR_MODE_MASK (0xE0U) +#define LAN8720_SMR_MODE_SHIFT (5U) +#define LAN8720_SMR_MODE_SET(x) (((uint16_t)(x) << LAN8720_SMR_MODE_SHIFT) & LAN8720_SMR_MODE_MASK) +#define LAN8720_SMR_MODE_GET(x) (((uint16_t)(x) & LAN8720_SMR_MODE_MASK) >> LAN8720_SMR_MODE_SHIFT) + +/* + * PHYAD (R/W) + * + * PHY Address. The PHY Address is used for the SMI address and for initial- + * ization of the Cipher (Scrambler) key. + */ +#define LAN8720_SMR_PHYAD_MASK (0x1FU) +#define LAN8720_SMR_PHYAD_SHIFT (0U) +#define LAN8720_SMR_PHYAD_SET(x) (((uint16_t)(x) << LAN8720_SMR_PHYAD_SHIFT) & LAN8720_SMR_PHYAD_MASK) +#define LAN8720_SMR_PHYAD_GET(x) (((uint16_t)(x) & LAN8720_SMR_PHYAD_MASK) >> LAN8720_SMR_PHYAD_SHIFT) + +/* Bitfield definition for register: SECR */ +/* + * SYM_ERR_CNT (RO) + * + * The symbol error counter increments whenever an invalid code symbol is + * received (including IDLE symbols) in 100BASE-TX mode. The counter is + * incremented only once per packet, even when the received packet contains + * more than one symbol error. This counter increments up to 65,536 (2^16) and + * rolls over to 0 after reaching the maximum value. + * Note: This register is cleared on reset, but is not cleared by reading the + * register. This register does not increment in 10BASE-T mode. + */ +#define LAN8720_SECR_SYM_ERR_CNT_MASK (0xFFFFU) +#define LAN8720_SECR_SYM_ERR_CNT_SHIFT (0U) +#define LAN8720_SECR_SYM_ERR_CNT_GET(x) (((uint16_t)(x) & LAN8720_SECR_SYM_ERR_CNT_MASK) >> LAN8720_SECR_SYM_ERR_CNT_SHIFT) + +/* Bitfield definition for register: ISFR */ +/* + * INT7 (RO) + * + * 0 = not source of interrupt + * 1 = ENERGYON generated + */ +#define LAN8720_ISFR_INT7_MASK (0x80U) +#define LAN8720_ISFR_INT7_SHIFT (7U) +#define LAN8720_ISFR_INT7_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT7_MASK) >> LAN8720_ISFR_INT7_SHIFT) + +/* + * INT6 (RO) + * + * 0 = not source of interrupt + * 1 = Auto-Negotiation complete + */ +#define LAN8720_ISFR_INT6_MASK (0x40U) +#define LAN8720_ISFR_INT6_SHIFT (6U) +#define LAN8720_ISFR_INT6_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT6_MASK) >> LAN8720_ISFR_INT6_SHIFT) + +/* + * INT5 (RO) + * + * 0 = not source of interrupt + * 1 = Remote Fault Detected + */ +#define LAN8720_ISFR_INT5_MASK (0x20U) +#define LAN8720_ISFR_INT5_SHIFT (5U) +#define LAN8720_ISFR_INT5_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT5_MASK) >> LAN8720_ISFR_INT5_SHIFT) + +/* + * INT4 (RO) + * + * 0 = not source of interrupt + * 1 = Link Down (link status negated) + */ +#define LAN8720_ISFR_INT4_MASK (0x10U) +#define LAN8720_ISFR_INT4_SHIFT (4U) +#define LAN8720_ISFR_INT4_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT4_MASK) >> LAN8720_ISFR_INT4_SHIFT) + +/* + * INT3 (RO) + * + * 0 = not source of interrupt + * 1 = Auto-Negotiation LP Acknowledge + */ +#define LAN8720_ISFR_INT3_MASK (0x8U) +#define LAN8720_ISFR_INT3_SHIFT (3U) +#define LAN8720_ISFR_INT3_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT3_MASK) >> LAN8720_ISFR_INT3_SHIFT) + +/* + * INT2 (RO) + * + * 0 = not source of interrupt + * 1 = Parallel Detection Fault + */ +#define LAN8720_ISFR_INT2_MASK (0x4U) +#define LAN8720_ISFR_INT2_SHIFT (2U) +#define LAN8720_ISFR_INT2_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT2_MASK) >> LAN8720_ISFR_INT2_SHIFT) + +/* + * INT1 (RO) + * + * 0 = not source of interrupt + * 1 = Auto-Negotiation Page Received + */ +#define LAN8720_ISFR_INT1_MASK (0x2U) +#define LAN8720_ISFR_INT1_SHIFT (1U) +#define LAN8720_ISFR_INT1_GET(x) (((uint16_t)(x) & LAN8720_ISFR_INT1_MASK) >> LAN8720_ISFR_INT1_SHIFT) + +/* Bitfield definition for register: IMR */ +/* + * MASK (R/W) + * + * 0 = interrupt source is masked + * 1 = interrupt source is enabled + */ +#define LAN8720_IMR_MASK_MASK (0xFEU) +#define LAN8720_IMR_MASK_SHIFT (1U) +#define LAN8720_IMR_MASK_SET(x) (((uint16_t)(x) << LAN8720_IMR_MASK_SHIFT) & LAN8720_IMR_MASK_MASK) +#define LAN8720_IMR_MASK_GET(x) (((uint16_t)(x) & LAN8720_IMR_MASK_MASK) >> LAN8720_IMR_MASK_SHIFT) + +/* Bitfield definition for register: PSCSR */ +/* + * AUTODONE (RO) + * + * 0 = Auto-negotiation is not done or disabled (or not active) + * 1 = Auto-negotiation is done + */ +#define LAN8720_PSCSR_AUTODONE_MASK (0x1000U) +#define LAN8720_PSCSR_AUTODONE_SHIFT (12U) +#define LAN8720_PSCSR_AUTODONE_GET(x) (((uint16_t)(x) & LAN8720_PSCSR_AUTODONE_MASK) >> LAN8720_PSCSR_AUTODONE_SHIFT) + +/* + * DUPLEX (RO) + * + * 0: Half duplex + * 1: Full duplex + */ +#define LAN8720_PSCSR_DUPLEX_MASK (0x10U) +#define LAN8720_PSCSR_DUPLEX_SHIFT (4U) +#define LAN8720_PSCSR_DUPLEX_GET(x) (((uint16_t)(x) & LAN8720_PSCSR_DUPLEX_MASK) >> LAN8720_PSCSR_DUPLEX_SHIFT) + +/* + * SPEED (RO) + * + * HCDSPEED value: + * 01 = 10BASE-T + * 10 = 100BASE-TX + */ +#define LAN8720_PSCSR_SPEED_MASK (0xCU) +#define LAN8720_PSCSR_SPEED_SHIFT (2U) +#define LAN8720_PSCSR_SPEED_GET(x) (((uint16_t)(x) & LAN8720_PSCSR_SPEED_MASK) >> LAN8720_PSCSR_SPEED_SHIFT) + + + + +#endif /* HPM_LAN8720_REGS_H */ \ No newline at end of file diff --git a/components/enet_phy/rtl8201/hpm_rtl8201.c b/components/enet_phy/rtl8201/hpm_rtl8201.c index aafd52c9c..63d70432c 100644 --- a/components/enet_phy/rtl8201/hpm_rtl8201.c +++ b/components/enet_phy/rtl8201/hpm_rtl8201.c @@ -12,7 +12,6 @@ #include "hpm_enet_drv.h" #include "hpm_rtl8201_regs.h" #include "hpm_rtl8201.h" -#include "board.h" /*--------------------------------------------------------------------- * Internal API @@ -53,13 +52,13 @@ void rtl8201_basic_mode_default_config(ENET_Type *ptr, rtl8201_config_t *config) { (void)ptr; - config->loopback = 0; /* Disable PCS loopback mode */ + config->loopback = false; /* Disable PCS loopback mode */ #if defined(__DISABLE_AUTO_NEGO) && (__DISABLE_AUTO_NEGO) config->auto_negotiation = false; /* Disable Auto-Negotiation */ config->speed = enet_phy_port_speed_100mbps; config->duplex = enet_phy_duplex_full; #else - config->auto_negotiation = 1; /* Enable Auto-Negotiation */ + config->auto_negotiation = true; /* Enable Auto-Negotiation */ #endif config->txc_input = true; /* Set TXC as input mode */ } diff --git a/components/enet_phy/rtl8201/hpm_rtl8201_regs.h b/components/enet_phy/rtl8201/hpm_rtl8201_regs.h index 404aaa6e6..17e237806 100644 --- a/components/enet_phy/rtl8201/hpm_rtl8201_regs.h +++ b/components/enet_phy/rtl8201/hpm_rtl8201_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -11,7 +11,7 @@ typedef enum { RTL8201_BMCR = 0, /* 0x0: Basic Mode Control Register */ - RTL8201_BMSR = 1, /* 0x1: (Basic Mode Status Register */ + RTL8201_BMSR = 1, /* 0x1: Basic Mode Status Register */ RTL8201_PHYID1 = 2, /* 0x2: PHY Identifier Register 1 */ RTL8201_PHYID2 = 3, /* 0x3: PHY Identifier Register 2 */ RTL8201_RMSR_P7 = 16, /* 0x10: RMII Mode Setting Register */ diff --git a/components/enet_phy/rtl8211/hpm_rtl8211.c b/components/enet_phy/rtl8211/hpm_rtl8211.c index a79f5d155..d7422f22b 100644 --- a/components/enet_phy/rtl8211/hpm_rtl8211.c +++ b/components/enet_phy/rtl8211/hpm_rtl8211.c @@ -12,7 +12,6 @@ #include "hpm_enet_drv.h" #include "hpm_rtl8211_regs.h" #include "hpm_rtl8211.h" -#include "board.h" /*--------------------------------------------------------------------- * Internal API @@ -53,13 +52,13 @@ void rtl8211_basic_mode_default_config(ENET_Type *ptr, rtl8211_config_t *config) { (void)ptr; - config->loopback = 0; /* Disable PCS loopback mode */ - #if defined(__DISABLE_AUTO_NEGO) && (__DISABLE_AUTO_NEGO) + config->loopback = false; /* Disable PCS loopback mode */ + #if defined(__DISABLE_AUTO_NEGO) && (__DISABLE_AUTO_NEGO) config->auto_negotiation = false; /* Disable Auto-Negotiation */ config->speed = enet_phy_port_speed_100mbps; config->duplex = enet_phy_duplex_full; #else - config->auto_negotiation = 1; /* Enable Auto-Negotiation */ + config->auto_negotiation = true; /* Enable Auto-Negotiation */ #endif } diff --git a/components/enet_phy/rtl8211/hpm_rtl8211_regs.h b/components/enet_phy/rtl8211/hpm_rtl8211_regs.h index dabd89a6b..ac2343579 100644 --- a/components/enet_phy/rtl8211/hpm_rtl8211_regs.h +++ b/components/enet_phy/rtl8211/hpm_rtl8211_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -11,7 +11,7 @@ typedef enum { RTL8211_BMCR = 0, /* 0x0: Basic Mode Control Register */ - RTL8211_BMSR = 1, /* 0x1: (Basic Mode Status Register */ + RTL8211_BMSR = 1, /* 0x1: Basic Mode Status Register */ RTL8211_PHYID1 = 2, /* 0x2: PHY Identifier Register 1 */ RTL8211_PHYID2 = 3, /* 0x3: PHY Identifier Register 2 */ RTL8211_PHYSR = 17, /* 0x11: PHY Specific Status Register */ diff --git a/components/panel/panels/mc10128007_31b.c b/components/panel/panels/mc10128007_31b.c index 12c4e976b..1f9b5bf31 100644 --- a/components/panel/panels/mc10128007_31b.c +++ b/components/panel/panels/mc10128007_31b.c @@ -15,7 +15,7 @@ typedef struct mipi_cmd_list { uint8_t cmd[4]; } mipi_cmd_list_t; -const static mipi_cmd_list_t mipi_panel_cmd[] = { +static const mipi_cmd_list_t mipi_panel_cmd[] = { {4, {0xFF, 0x98, 0x81, 0x03}}, {2, {0x01, 0x00}}, {2, {0x02, 0x00}}, diff --git a/components/uart_lin/hpm_uart_lin.c b/components/uart_lin/hpm_uart_lin.c index 766941c37..8367d2823 100644 --- a/components/uart_lin/hpm_uart_lin.c +++ b/components/uart_lin/hpm_uart_lin.c @@ -12,7 +12,11 @@ #endif #ifndef HPM_UART_LIN_BREAK_LENGTH -#define HPM_UART_LIN_BREAK_LENGTH (13U) +#define HPM_UART_LIN_BREAK_LENGTH (13U) /* bits */ +#endif + +#ifndef HPM_UART_LIN_WAKEUP_LENGTH +#define HPM_UART_LIN_WAKEUP_LENGTH (400U) /* us */ #endif @@ -86,6 +90,16 @@ static void hpm_uart_lin_send_sync(UART_Type *ptr) uart_write_byte(ptr, 0x55); /* sync phase */ } +void hpm_uart_lin_send_wakeup(UART_Type *ptr, uart_lin_master_pin_ctrl_t *pin_ctrl) +{ + pin_ctrl->config_uart_pin_as_gpio(ptr); + gpio_set_pin_output(pin_ctrl->ptr, pin_ctrl->tx_port, pin_ctrl->tx_pin); + gpio_write_pin(pin_ctrl->ptr, pin_ctrl->tx_port, pin_ctrl->tx_pin, 0); + pin_ctrl->delay_us(HPM_UART_LIN_WAKEUP_LENGTH); + gpio_write_pin(pin_ctrl->ptr, pin_ctrl->tx_port, pin_ctrl->tx_pin, 1); + pin_ctrl->config_uart_pin(ptr); +} + uart_lin_stat_t hpm_uart_lin_master_send_frame(uart_lin_master_config_t *config) { uint32_t retry; diff --git a/components/uart_lin/hpm_uart_lin.h b/components/uart_lin/hpm_uart_lin.h index 812aabef8..f79790b5d 100644 --- a/components/uart_lin/hpm_uart_lin.h +++ b/components/uart_lin/hpm_uart_lin.h @@ -143,6 +143,16 @@ void hpm_uart_lin_slave_send_data(uart_lin_slave_config_t *config); */ uart_lin_stat_t hpm_uart_lin_slave_receive_data(uart_lin_slave_config_t *config); +/** + * @brief uart_lin send break signal + * + * @note The low-level length of the wakeup signal is defined as HPM_UART_LIN_WAKEUP_LENGTH + * + * @param [in] ptr UART base address + * @param [in] pin_ctrl uart_lin_master_pin_ctrl_t + */ +void hpm_uart_lin_send_wakeup(UART_Type *ptr, uart_lin_master_pin_ctrl_t *pin_ctrl); + #ifdef __cplusplus } #endif diff --git a/components/usb/host/CMakeLists.txt b/components/usb/host/CMakeLists.txt deleted file mode 100644 index d93594926..000000000 --- a/components/usb/host/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021 HPMicro -# SPDX-License-Identifier: BSD-3-Clause - -sdk_inc(.) -sdk_src(hpm_usb_host.c) diff --git a/components/usb/host/hpm_usb_host.c b/components/usb/host/hpm_usb_host.c deleted file mode 100644 index 2b661df2d..000000000 --- a/components/usb/host/hpm_usb_host.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * Copyright (c) 2021 HPMicro - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -/*--------------------------------------------------------------------- - * Includes - *--------------------------------------------------------------------- - */ -#include "hpm_usb_host.h" -#include "hpm_misc.h" -#include "hpm_common.h" -#include "board.h" - -/*--------------------------------------------------------------------- - * Macros - *--------------------------------------------------------------------- - */ - -#define USB_QHD_TYP_SHIFT (1U) - -#define USB_PERIOD_1MS (1U) -#define USB_PERIOD_2MS (2U) -#define USB_PERIOD_4MS (4U) -#define USB_PERIOD_8MS (8U) - -#define USB_DEFAULT_ADDR (0U) -#define USB_HIGH_SPPED_INTERVAL_MAX (16) -#define USB_SETUP_PACKET_LEN (8U) - -#define USB_BIN8(x) ((uint8_t) (0b##x)) -#define USB_BIN16(b1, b2) ((uint16_t) (0b##b1##b2)) -#define USB_BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4)) - -/* helper functions */ -static uint8_t usb_log2(uint32_t value) -{ - uint8_t result = 0; - - while (value >>= 1) { - result++; - } - - return result; -} - -/*****************************************************************************/ -/* list functions */ -/*****************************************************************************/ -static void usb_host_list_insert(hcd_link_t *current, hcd_link_t *new, uint8_t new_type) -{ - new->address = current->address; - current->address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)new) | (new_type << USB_QHD_TYP_SHIFT); -} - -static void usb_host_list_remove_qhd_by_addr(hcd_link_t *list_head, uint8_t dev_addr) -{ - hcd_qhd_t *qhd; - - for (hcd_link_t *prev = list_head; - !prev->terminate && (sys_address_to_core_local_mem(USB_HOST_MCU_CORE, usb_host_align32(prev->address)) != (uint32_t)list_head); - prev = (hcd_link_t *)sys_address_to_core_local_mem(USB_HOST_MCU_CORE, (uint32_t)usb_host_list_next(prev))) { - - /* TODO check type for ISO iTD and siTD */ - qhd = (hcd_qhd_t *)sys_address_to_core_local_mem(USB_HOST_MCU_CORE, (uint32_t)usb_host_list_next(prev)); - - if (qhd->dev_addr == dev_addr) { - /* TODO deactive all TD, wait for QHD to inactive before removal */ - prev->address = qhd->next.address; - - /* EHCI link the removed qhd to async head (which always reachable by Host Controller) */ - qhd->next.address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)list_head) | (usb_qtype_qhd << USB_QHD_TYP_SHIFT); - - if (qhd->int_smask) { - /* period list queue element is guarantee to be free in the next frame (1 ms) */ - qhd->used = 0; - } else { - /* async list use async advance handshake */ - /* mark as removing, will completely re-usable when async advance isr occurs */ - qhd->removing = 1; - } - } - } -} - -hcd_link_t *usb_host_list_next(hcd_link_t *p_link_pointer) -{ - return (hcd_link_t *)usb_host_align32(p_link_pointer->address); -} - -/*************************************************************/ -/* qhd functions */ -/*************************************************************/ -static hcd_qhd_t *usb_host_qhd_control(usb_host_handle_t *handle, uint8_t dev_addr) -{ - return &handle->hcd_data->control[dev_addr].qhd; -} - -hcd_qhd_t *usb_host_qhd_next(hcd_qhd_t const *p_qhd) -{ - return (hcd_qhd_t *)usb_host_align32(p_qhd->next.address); -} - -static hcd_qhd_t *usb_host_qhd_find_free(usb_host_handle_t *handle) -{ - for (uint32_t i = 0; i < USB_HCD_MAX_QHD_COUNT; i++) { - if (!handle->hcd_data->qhd_pool[i].used) { - return &handle->hcd_data->qhd_pool[i]; - } - } - - return NULL; -} - -static hcd_qhd_t *usb_host_qhd_get_from_addr(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr) -{ - hcd_qhd_t *qhd_pool = handle->hcd_data->qhd_pool; - - for (uint32_t i = 0; i < USB_HCD_MAX_QHD_COUNT; i++) { - if ((qhd_pool[i].dev_addr == dev_addr) && - ep_addr == usb_edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid)) { - return &qhd_pool[i]; - } - } - - return NULL; -} - -static bool usb_host_qhd_init(usb_host_handle_t *handle, hcd_qhd_t *p_qhd, uint8_t dev_addr, usb_desc_endpoint_t const *ep_desc) -{ - uint8_t const xfer_type = ep_desc->bmAttributes.xfer; - uint8_t const interval = ep_desc->bInterval; - - /* address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise) */ - if (dev_addr != 0) { - memset(p_qhd, 0, sizeof(hcd_qhd_t)); - } - - p_qhd->dev_addr = dev_addr; - p_qhd->fl_inactive_next_xact = 0; - p_qhd->ep_number = usb_edpt_number(ep_desc->bEndpointAddress); - p_qhd->ep_speed = handle->ep_speed; - p_qhd->data_toggle_control = (xfer_type == usb_xfer_control) ? 1 : 0; - p_qhd->head_list_flag = (dev_addr == USB_DEFAULT_ADDR) ? 1 : 0; /* addr0's endpoint is the static async list head */ - p_qhd->max_packet_size = ep_desc->wMaxPacketSize.size; - p_qhd->fl_ctrl_ep_flag = ((xfer_type == usb_xfer_control) && (p_qhd->ep_speed != usb_speed_high)) ? 1 : 0; - p_qhd->nak_reload = 0; - - if (usb_xfer_interrupt == xfer_type) { - if (usb_speed_high == p_qhd->ep_speed) { - if (interval > USB_HIGH_SPPED_INTERVAL_MAX) { - return false; - } - - if (interval < 4) { /* sub millisecond interval */ - p_qhd->interval_ms = 0; - p_qhd->int_smask = (interval == 1) ? USB_BIN8(11111111) : - (interval == 2) ? USB_BIN8(10101010) : USB_BIN8(01000100); - } else { - p_qhd->interval_ms = (uint8_t)MIN(1 << (interval - 4), 255); - p_qhd->int_smask = HPM_BITSMASK(1, interval % 8); - } - } else { - if (interval == 0) { - return false; - } - - /* Full/Low:(EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes */ - p_qhd->int_smask = 0x01; - p_qhd->fl_int_cmask = USB_BIN8(11100); - p_qhd->interval_ms = interval; - } - } else { - /* Bulk/Control -> smask = cmask = 0 */ - p_qhd->int_smask = p_qhd->fl_int_cmask = 0; - } - - p_qhd->fl_hub_addr = handle->hub_addr; - p_qhd->fl_hub_port = handle->hub_port; - p_qhd->mult = 1; - - /* HCD Management Data */ - p_qhd->used = 1; - p_qhd->removing = 0; - p_qhd->p_qtd_list_head = NULL; - p_qhd->p_qtd_list_tail = NULL; - p_qhd->pid = usb_edpt_dir(ep_desc->bEndpointAddress) ? usb_pid_in : usb_pid_out; /* PID for TD under this endpoint */ - - /* Active, but no TD list */ - p_qhd->qtd_overlay.halted = 0; - p_qhd->qtd_overlay.next.terminate = 1; - p_qhd->qtd_overlay.alternate.terminate = 1; - - if (usb_xfer_bulk == xfer_type && p_qhd->ep_speed == usb_speed_high && p_qhd->pid == usb_pid_out) { - p_qhd->qtd_overlay.ping_err = 1; /* Do PING for Highspeed Bulk OUT, EHCI */ - } - - return true; -} - -hcd_qhd_t *usb_host_qhd_async_head(usb_host_handle_t *handle) -{ - /* control qhd of dev0 is used as async head */ - return usb_host_qhd_control(handle, 0); -} - -bool usb_host_qhd_has_xact_error(hcd_qhd_t *p_qhd) -{ - return (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err); -} - -hcd_link_t *usb_host_get_period_head(usb_host_handle_t *handle, uint8_t interval_ms) -{ - return (hcd_link_t *)&handle->hcd_data->period_head_arr[usb_log2(MIN(USB_HOST_FRAMELIST_SIZE, interval_ms))]; -} - -/*************************************************************/ -/* qtd functions */ -/*************************************************************/ -static hcd_qtd_t *usb_host_qtd_find_free(usb_host_handle_t *handle) -{ - for (uint32_t i = 0; i < USB_HCD_MAX_QTD_COUNT; i++) { - if (!handle->hcd_data->qtd_pool[i].used) { - return &handle->hcd_data->qtd_pool[i]; - } - } - - return NULL; -} - -static hcd_qtd_t *usb_host_qtd_next(hcd_qtd_t const *p_qtd) -{ - return (hcd_qtd_t *)usb_host_align32(p_qtd->next.address); -} - -static void usb_host_qtd_insert_to_qhd(hcd_qhd_t *p_qhd, hcd_qtd_t *p_qtd_new) -{ - if (p_qhd->p_qtd_list_head == NULL) { /* empty list */ - p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new; - } else { - p_qhd->p_qtd_list_tail->next.address = (uint32_t)p_qtd_new; - p_qhd->p_qtd_list_tail = p_qtd_new; - } -} - -static void usb_host_qtd_init(hcd_qtd_t *p_qtd, void *buffer, uint16_t total_bytes) -{ - memset(p_qtd, 0, sizeof(hcd_qtd_t)); - - p_qtd->used = 1; - p_qtd->next.terminate = 1; /* init to null */ - p_qtd->alternate.terminate = 1; /* not used, always set to terminated */ - p_qtd->active = 1; - p_qtd->err_count = 3; - p_qtd->data_toggle = 0; - p_qtd->total_bytes = total_bytes; - p_qtd->expected_bytes = total_bytes; - - if (buffer != NULL) { - p_qtd->buffer[0] = (uint32_t)buffer; - - for (uint8_t i = 1; i < USB_SOC_HCD_QTD_BUFFER_COUNT; i++) { - p_qtd->buffer[i] |= usb_host_align4k(p_qtd->buffer[i-1]) + 4096UL; - } - } -} - -void usb_host_qtd_remove_1st_from_qhd(hcd_qhd_t *p_qhd) -{ - if (p_qhd->p_qtd_list_head == p_qhd->p_qtd_list_tail) { /* last TD --> make it NULL */ - p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = NULL; - } else { - p_qhd->p_qtd_list_head = usb_host_qtd_next(p_qhd->p_qtd_list_head); - } -} - -hcd_qtd_t *usb_host_qtd_control(usb_host_handle_t *handle, uint8_t dev_addr) -{ - return &handle->hcd_data->control[dev_addr].qtd; -} - -static void usb_host_init_async_list(usb_host_handle_t *handle) -{ - hcd_qhd_t *async_head = usb_host_qhd_async_head(handle); - - memset(async_head, 0, sizeof(hcd_qhd_t)); - - async_head->next.address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)async_head); /* circular list, next is itself */ - async_head->next.type = usb_qtype_qhd; - async_head->head_list_flag = 1; - async_head->qtd_overlay.halted = 1; - async_head->qtd_overlay.next.terminate = 1; - - usb_hcd_set_async_list_addr(handle->regs, core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)async_head)); -} - -static void usb_host_init_periodic_list(usb_host_handle_t *handle) -{ - hcd_link_t *framelist; - hcd_link_t *period_1ms; - - /* Build the polling interval tree with 1 ms, 2 ms, 4 ms and 8 ms (framesize) only */ - for (uint32_t i = 0; i < 4; i++) { - handle->hcd_data->period_head_arr[i].int_smask = 1; /* queue head in period list must have non-zero smask */ - handle->hcd_data->period_head_arr[i].qtd_overlay.halted = 1; /* dummy node, always inactive */ - } - - framelist = handle->hcd_data->period_framelist; - period_1ms = usb_host_get_period_head(handle, USB_PERIOD_1MS); - - /* all links --> period_head_arr[0] (1ms) - * 0, 2, 4, 6 etc --> period_head_arr[1] (2ms) - * 1, 5 --> period_head_arr[2] (4ms) - * 3 --> period_head_arr[3] (8ms) - */ - for (uint32_t i = 0; i < USB_HOST_FRAMELIST_SIZE; i++) { - framelist[i].address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)period_1ms); - framelist[i].type = usb_qtype_qhd; - } - - for (uint32_t i = 0; i < USB_HOST_FRAMELIST_SIZE; i += 2) { - usb_host_list_insert(framelist + i, usb_host_get_period_head(handle, USB_PERIOD_2MS), usb_qtype_qhd); - } - - for (uint32_t i = 1; i < USB_HOST_FRAMELIST_SIZE; i += 4) { - usb_host_list_insert(framelist + i, usb_host_get_period_head(handle, USB_PERIOD_4MS), usb_qtype_qhd); - } - - for (uint32_t i = 3; i < USB_HOST_FRAMELIST_SIZE; i += 8) { - usb_host_list_insert(framelist + i, usb_host_get_period_head(handle, USB_PERIOD_8MS), usb_qtype_qhd); - } - - period_1ms->terminate = 1; - - usb_hcd_set_periodic_list_addr(handle->regs, core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)framelist)); -} - -/* enable vbus output */ -static void usb_host_vbus_ctrl(usb_host_handle_t *handle) -{ - handle->hcd_vbus_ctrl_cb(handle->rhport, 1); -} - -bool usb_host_init(usb_host_handle_t *handle, uint32_t int_mask, uint16_t framelist_size) -{ - usb_hcd_init(handle->regs, int_mask, framelist_size); - memset(handle->hcd_data, 0, sizeof(hcd_data_t)); - usb_host_init_async_list(handle); - usb_host_init_periodic_list(handle); - usb_host_vbus_ctrl(handle); - usb_hcd_run(handle->regs); - usb_hcd_enable_port_power(handle->regs); - return true; -} - -void usb_host_port_reset(usb_host_handle_t *handle) -{ - usb_hcd_port_reset(handle->regs); -} - -uint32_t usb_host_uframe_number(usb_host_handle_t *handle) -{ - return handle->hcd_data->uframe_number + usb_hcd_get_frame_index(handle->regs); -} - -bool usb_host_get_port_ccs(usb_host_handle_t *handle) -{ - return usb_get_port_ccs(handle->regs); -} - -bool usb_host_port_csc(usb_host_handle_t *handle) -{ - return usb_hcd_get_port_csc(handle->regs); -} - -uint32_t usb_host_status_flags(usb_host_handle_t *handle) -{ - return usb_get_status_flags(handle->regs); -} - -uint32_t usb_host_interrupts(usb_host_handle_t *handle) -{ - return usb_get_interrupts(handle->regs); -} - -void usb_host_clear_status_flags(usb_host_handle_t *handle, uint32_t status) -{ - usb_clear_status_flags(handle->regs, status); -} - -uint8_t usb_host_get_port_speed(usb_host_handle_t *handle) -{ - return usb_get_port_speed(handle->regs); -} - -/* Close all opened endpoint belong to this device */ -void usb_host_device_close(usb_host_handle_t *handle, uint8_t dev_addr) -{ - /* skip dev0 */ - if (dev_addr == USB_DEFAULT_ADDR) { - return; - } - - /* Remove from async list */ - usb_host_list_remove_qhd_by_addr((hcd_link_t *) usb_host_qhd_async_head(handle), dev_addr); - - /* Remove from all interval period list */ - for (uint8_t i = 0; i < ARRAY_SIZE(handle->hcd_data->period_head_arr); i++) { - usb_host_list_remove_qhd_by_addr((hcd_link_t *)&handle->hcd_data->period_head_arr[i], dev_addr); - } - - /* Async doorbell (EHCI for operational details) */ - usb_hcd_set_command(handle->regs, USB_USBCMD_IAA_MASK); -} - -/*--------------------------------------------------------------------- - * Control Pipe API - *--------------------------------------------------------------------- - */ -bool usb_host_edpt_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) -{ - uint8_t const epnum = usb_edpt_number(ep_addr); - uint8_t const dir = usb_edpt_dir(ep_addr); - hcd_qhd_t *qhd; - hcd_qtd_t *qtd; - hcd_qhd_t *p_qhd; - hcd_qtd_t *p_qtd; - - if (buffer != NULL) { - buffer = (uint8_t *)core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)buffer); - } - - if (epnum == 0) { - qhd = usb_host_qhd_control(handle, dev_addr); - qtd = usb_host_qtd_control(handle, dev_addr); - - usb_host_qtd_init(qtd, buffer, buflen); - - /* first first data toggle is always 1 (data & setup stage) */ - qtd->data_toggle = 1; - qtd->pid = dir ? usb_pid_in : usb_pid_out; - - qtd->int_on_complete = 1; - qtd->next.terminate = 1; - - /* sw region */ - qhd->p_qtd_list_head = qtd; - qhd->p_qtd_list_tail = qtd; - - /* attach TD */ - qhd->qtd_overlay.next.address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)qtd); - } else { - p_qhd = usb_host_qhd_get_from_addr(handle, dev_addr, ep_addr); - p_qtd = usb_host_qtd_find_free(handle); - - if (p_qhd == NULL || p_qtd == NULL) { - return false; - } - - usb_host_qtd_init(p_qtd, buffer, buflen); - p_qtd->pid = p_qhd->pid; - - /* Insert TD to QH */ - usb_host_qtd_insert_to_qhd(p_qhd, p_qtd); - p_qhd->p_qtd_list_tail->int_on_complete = 1; - - /* attach head QTD to QHD start transferring */ - p_qhd->qtd_overlay.next.address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)p_qhd->p_qtd_list_head); - } - - return true; -} - -bool usb_host_setup_send(usb_host_handle_t *handle, uint8_t dev_addr, const uint8_t *setup_packet) -{ - uint32_t *p = NULL; - - hcd_qhd_t *qhd = &handle->hcd_data->control[dev_addr].qhd; - hcd_qtd_t *td = &handle->hcd_data->control[dev_addr].qtd; - - if (setup_packet != NULL) { - p = (uint32_t *)core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)setup_packet); - } - - usb_host_qtd_init(td, (void *)p, USB_SETUP_PACKET_LEN); - td->pid = usb_pid_setup; - td->int_on_complete = 1; - td->next.terminate = 1; - - /* sw region */ - qhd->p_qtd_list_head = td; - qhd->p_qtd_list_tail = td; - - /* attach TD */ - qhd->qtd_overlay.next.address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)td); - - return true; -} - -bool usb_host_edpt_open(usb_host_handle_t *handle, uint8_t dev_addr, usb_desc_endpoint_t const *ep_desc) -{ - hcd_qhd_t *p_qhd = NULL; - hcd_link_t *list_head = NULL; - - if (ep_desc->bmAttributes.xfer == usb_xfer_isochronous) { - return false; - } - - /* Prepare Queue Head */ - if (ep_desc->bEndpointAddress == 0) { - p_qhd = usb_host_qhd_control(handle, dev_addr); - } else { - p_qhd = usb_host_qhd_find_free(handle); - } - - /* Initialize Qhd */ - usb_host_qhd_init(handle, p_qhd, dev_addr, ep_desc); - - switch (ep_desc->bmAttributes.xfer) { - case usb_xfer_control: - case usb_xfer_bulk: - list_head = (hcd_link_t *)usb_host_qhd_async_head(handle); /* control of dev0 is always present as async head */ - break; - - case usb_xfer_interrupt: - list_head = usb_host_get_period_head(handle, p_qhd->interval_ms); - break; - - case usb_xfer_isochronous: - break; - - default: - break; - } - - /* Insert to list */ - usb_host_list_insert(list_head, (hcd_link_t *)p_qhd, usb_qtype_qhd); - - return true; -} - -bool usb_host_pipe_queue_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - hcd_qhd_t *p_qhd = usb_host_qhd_get_from_addr(handle, dev_addr, ep_addr); - hcd_qtd_t *p_qtd = usb_host_qtd_find_free(handle); - - if (p_qhd == NULL || p_qtd == NULL) { - return false; - } - - /* Initialize QTD */ - usb_host_qtd_init(p_qtd, buffer, total_bytes); - p_qtd->pid = p_qhd->pid; - - /* Insert TD to TD list */ - usb_host_qtd_insert_to_qhd(p_qhd, p_qtd); - - return true; -} - -bool usb_host_pipe_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - hcd_qhd_t *p_qhd = usb_host_qhd_get_from_addr(handle, dev_addr, ep_addr); - - if (usb_host_pipe_queue_xfer(handle, dev_addr, ep_addr, buffer, total_bytes) == false) { - return false; - } - - if (int_on_complete) { - /* the just added qtd is pointed by list_tail */ - p_qhd->p_qtd_list_tail->int_on_complete = 1; - } - - /* attach head QTD to QHD start transferring */ - p_qhd->qtd_overlay.next.address = core_local_mem_to_sys_address(USB_HOST_MCU_CORE, (uint32_t)p_qhd->p_qtd_list_head); - - return true; -} - -bool usb_host_edpt_busy(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr) -{ - hcd_qhd_t *p_qhd = usb_host_qhd_get_from_addr(handle, dev_addr, ep_addr); - - return ((!p_qhd->qtd_overlay.halted) && (p_qhd->p_qtd_list_head != NULL)); -} - -bool usb_host_edpt_stalled(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr) -{ - hcd_qhd_t *p_qhd = usb_host_qhd_get_from_addr(handle, dev_addr, ep_addr); - - return p_qhd->qtd_overlay.halted && !usb_host_qhd_has_xact_error(p_qhd); -} - -bool usb_host_edpt_clear_stall(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr) -{ - hcd_qhd_t *p_qhd = usb_host_qhd_get_from_addr(handle, dev_addr, ep_addr); - - p_qhd->qtd_overlay.halted = 0; - - return true; -} diff --git a/components/usb/host/hpm_usb_host.h b/components/usb/host/hpm_usb_host.h deleted file mode 100644 index 91dd5e4fa..000000000 --- a/components/usb/host/hpm_usb_host.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2021 HPMicro - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef HPM_USB_HOST_H -#define HPM_USB_HOST_H - -/*--------------------------------------------------------------------- - * Includes - *--------------------------------------------------------------------- - */ -#include "hpm_usb_drv.h" -#include "hpm_common.h" -#include "hpm_soc_feature.h" - -/*--------------------------------------------------------------------- - * Macros - *--------------------------------------------------------------------- - */ - - -#ifndef USB_HCD_PERIODIC_ARR_COUNT -#define USB_HCD_PERIODIC_ARR_COUNT (4U) -#endif - -#ifndef USB_HCD_MAX_CONNECTED_DEVICES -#define USB_HCD_MAX_CONNECTED_DEVICES (5U) -#endif - -#ifndef USB_HCD_MAX_QHD_COUNT -#define USB_HCD_MAX_QHD_COUNT (USB_HCD_MAX_CONNECTED_DEVICES * 16U * 2U) -#endif - -#ifndef USB_HCD_MAX_QTD_COUNT -#define USB_HCD_MAX_QTD_COUNT (USB_HCD_MAX_QHD_COUNT * 2U) -#endif -/*--------------------------------------------------------------------- - * Enum Declarations - *--------------------------------------------------------------------- - */ -typedef enum { - usb_max_itd = 4, - usb_max_sitd = 16 -} usb_max_xtd_t; - -typedef enum { - usb_qtype_itd = 0, - usb_qtype_qhd, - usb_qtype_sitd, - usb_qtype_fstn -} usb_qtype_t; - -typedef enum { - usb_pid_out = 0, - usb_pid_in, - usb_pid_setup -} usb_pid_t; - -typedef enum { - usb_speed_full = 0, - usb_speed_low, - usb_speed_high, - usb_speed_invalid = 0xff, -} usb_speed_t; - -typedef enum { - usb_cmd_pos_run_stop = 0, - usb_cmd_pos_framelist_szie = 2, - usb_cmd_pos_period_enable = 4, - usb_cmd_pos_async_enable = 5, - usb_cmd_pos_framelist_size_msb = 15, - usb_cmd_pos_interrupt_threshold = 16 -} usb_cmd_pos_t; - -typedef enum { - usb_portsc_mask_current_connect_status = HPM_BITSMASK(1, 0), - usb_portsc_mask_connect_status_change = HPM_BITSMASK(1, 1), - usb_portsc_mask_port_eanbled = HPM_BITSMASK(1, 2), - usb_portsc_mask_port_enable_chagne = HPM_BITSMASK(1, 3), - usb_portsc_mask_over_current_change = HPM_BITSMASK(1, 5), - usb_portsc_mask_port_reset = HPM_BITSMASK(1, 8), - - usb_portsc_mask_all = usb_portsc_mask_connect_status_change - | usb_portsc_mask_port_enable_chagne - | usb_portsc_mask_over_current_change -} usb_portsc_change_mask_t; - -/* Link pointer */ -typedef union { - volatile uint32_t address; - struct { - volatile uint32_t terminate : 1; - volatile uint32_t type : 2; - }; -} hcd_link_t; - -/* Queue Element Transfer Descriptor */ -/* Qtd is used to declare overlay in hcd_qhd_t */ -typedef struct { - /* Word 0: Next QTD Pointer */ - volatile hcd_link_t next; - - /* Word 1: Alternate Next QTD Pointer (not used) */ - union{ - volatile hcd_link_t alternate; - struct { - volatile uint32_t : 5; - volatile uint32_t used : 1; - volatile uint32_t : 10; - volatile uint32_t expected_bytes : 16; - }; - }; - - /* Word 2: qTQ Token */ - volatile uint32_t ping_err : 1 ; /* For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator */ - volatile uint32_t non_hs_split_state : 1 ; /* Used by HC to track the state of slipt transaction */ - volatile uint32_t non_hs_missed_uframe : 1 ; /* HC misses a complete slip transaction */ - volatile uint32_t xact_err : 1 ; /* Error (Timeout, CRC, Bad PID ... ) */ - volatile uint32_t babble_err : 1 ; /* Babble detected, also set Halted bit to 1 */ - volatile uint32_t buffer_err : 1 ; /* Data overrun/underrun error */ - volatile uint32_t halted : 1 ; /* Serious error or STALL received */ - volatile uint32_t active : 1 ; /* Start transfer, clear by HC when complete */ - volatile uint32_t pid : 2 ; /* 0: OUT, 1: IN, 2 Setup */ - volatile uint32_t err_count : 2 ; /* Error Counter of consecutive errors */ - volatile uint32_t current_page : 3 ; /* Index into the qTD buffer pointer list */ - volatile uint32_t int_on_complete : 1 ; /* Interrupt on complete */ - volatile uint32_t total_bytes : 15 ; /* Transfer bytes, decreased during transaction */ - volatile uint32_t data_toggle : 1 ; /* Data Toggle bit */ - - /* Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page */ - volatile uint32_t buffer[USB_SOC_HCD_QTD_BUFFER_COUNT]; -} hcd_qtd_t; - -/* Queue Head */ -typedef struct { - /* Word 0: Next QHD */ - hcd_link_t next; - - /* Word 1: Endpoint Characteristics */ - volatile uint32_t dev_addr : 7 ; /* device address */ - volatile uint32_t fl_inactive_next_xact : 1 ; /* Only valid for Periodic with Full/Slow speed */ - volatile uint32_t ep_number : 4 ; /* EP number */ - volatile uint32_t ep_speed : 2 ; /* 0: Full, 1: Low, 2: High */ - volatile uint32_t data_toggle_control : 1 ; /* 0: use DT in qHD, 1: use DT in qTD */ - volatile uint32_t head_list_flag : 1 ; /* Head of the queue */ - volatile uint32_t max_packet_size : 11 ; /* Max packet size */ - volatile uint32_t fl_ctrl_ep_flag : 1 ; /* 1 if is Full/Low speed control endpoint */ - volatile uint32_t nak_reload : 4 ; /* Used by HC */ - - /* Word 2: Endpoint Capabilities */ - volatile uint32_t int_smask : 8 ; /* Interrupt Schedule Mask */ - volatile uint32_t fl_int_cmask : 8 ; /* Split Completion Mask for Full/Slow speed */ - volatile uint32_t fl_hub_addr : 7 ; /* Hub Address for Full/Slow speed */ - volatile uint32_t fl_hub_port : 7 ; /* Hub Port for Full/Slow speed */ - volatile uint32_t mult : 2 ; /* Transaction per micro frame */ - - /* Word 3: Current qTD Pointer */ - volatile uint32_t qtd_addr; - - /* Word 4-11: Transfer Overlay */ - volatile hcd_qtd_t qtd_overlay; - - /*-------------------------------------------------------------------- - * Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes - * thus there are 16 bytes padding free that we can make use of. - *-------------------------------------------------------------------- - */ - uint8_t used; - uint8_t removing; /* removed from async list, waiting for async advance */ - uint8_t pid; - uint8_t interval_ms; /* polling interval in frames (or millisecond) */ - - uint16_t total_xferred_bytes; /* number of bytes xferred until a qtd with ioc bit set */ - uint8_t reserved2[2]; - - hcd_qtd_t * volatile p_qtd_list_head; /* head of the scheduled TD list */ - hcd_qtd_t * volatile p_qtd_list_tail; /* tail of the scheduled TD list */ -} hcd_qhd_t; - -typedef struct { - hcd_link_t period_framelist[USB_HOST_FRAMELIST_SIZE]; - - /* for ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) - * [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms - */ - hcd_qhd_t period_head_arr[USB_HCD_PERIODIC_ARR_COUNT]; - - /* Note control qhd of dev0 is used as head of async list */ - struct { - hcd_qhd_t qhd; - hcd_qtd_t qtd; - } control[USB_HCD_MAX_CONNECTED_DEVICES + 1]; - - hcd_qhd_t qhd_pool[USB_HCD_MAX_QHD_COUNT]; - hcd_qtd_t qtd_pool[USB_HCD_MAX_QTD_COUNT]; - - uint32_t uframe_number; -} hcd_data_t; - -typedef struct { - uint8_t rhport; - uint8_t ep_speed; - uint8_t hub_addr; - uint8_t hub_port; - USB_Type *regs; - hcd_data_t *hcd_data; - void (*hcd_vbus_ctrl_cb)(uint8_t rhport, uint8_t level); -} usb_host_handle_t; - -/* USB Endpoint Descriptor */ -typedef struct __attribute__ ((packed)) -{ - uint8_t bLength; - uint8_t bDescriptorType; - uint8_t bEndpointAddress; - - struct __attribute__ ((packed)) { - uint8_t xfer : 2; - uint8_t sync : 2; - uint8_t usage : 2; - uint8_t : 2; - } bmAttributes; - - struct __attribute__ ((packed)) { - uint16_t size : 11; - uint16_t hs_period_mult : 2; - uint16_t : 3; - } wMaxPacketSize; - - uint8_t bInterval; -} usb_desc_endpoint_t; - -#if defined(__cplusplus) -extern "C" { -#endif /* __cplusplus */ - -/* Get direction from Endpoint address */ -static inline usb_dir_t usb_edpt_dir(uint8_t addr) -{ - return (addr & usb_dir_in_mask) ? usb_dir_in : usb_dir_out; -} - -/* Get Endpoint number from address */ -static inline uint8_t usb_edpt_number(uint8_t addr) -{ - return (uint8_t)(addr & (~usb_dir_in_mask)); -} - -/* Get Endpoint address */ -static inline uint8_t usb_edpt_addr(uint8_t num, uint8_t dir) -{ - return (uint8_t)(num | (dir ? usb_dir_in_mask : 0)); -} - -static inline uint32_t usb_host_align16(uint32_t value) { return (value & 0xFFFFFFF0UL); } -static inline uint32_t usb_host_align32(uint32_t value) { return (value & 0xFFFFFFE0UL); } -static inline uint32_t usb_host_align4k(uint32_t value) { return (value & 0xFFFFF000UL); } -static inline uint32_t usb_host_offset4k(uint32_t value) { return (value & 0xFFFUL); } - -bool usb_host_qhd_has_xact_error(hcd_qhd_t *p_qhd); -bool usb_host_qhd_has_xact_error(hcd_qhd_t *p_qhd); -void usb_host_qtd_remove_1st_from_qhd(hcd_qhd_t *p_qhd); -hcd_link_t *usb_host_list_next(hcd_link_t *p_link_pointer); -hcd_link_t *usb_host_get_period_head(usb_host_handle_t *handle, uint8_t interval_ms); -hcd_qhd_t *usb_host_qhd_async_head(usb_host_handle_t *handle); -hcd_qhd_t *usb_host_qhd_next(hcd_qhd_t const *p_qhd); -hcd_qtd_t *usb_host_qtd_control(usb_host_handle_t *handle, uint8_t dev_addr); -uint32_t usb_host_uframe_number(usb_host_handle_t *handle); -uint32_t usb_host_status_flags(usb_host_handle_t *handle); -uint32_t usb_host_interrupts(usb_host_handle_t *handle); -void usb_host_clear_status_flags(usb_host_handle_t *handle, uint32_t status); -uint8_t usb_host_get_port_speed(usb_host_handle_t *handle); -void usb_host_port_reset(usb_host_handle_t *handle); -bool usb_host_init(usb_host_handle_t *handle, uint32_t int_mask, uint16_t framelist_size); -bool usb_host_get_port_ccs(usb_host_handle_t *handle); -bool usb_host_port_csc(usb_host_handle_t *handle); -void usb_host_device_close(usb_host_handle_t *handle, uint8_t dev_addr); -bool usb_host_edpt_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen); -bool usb_host_setup_send(usb_host_handle_t *handle, uint8_t dev_addr, const uint8_t *setup_packet); -bool usb_host_edpt_open(usb_host_handle_t *handle, uint8_t dev_addr, usb_desc_endpoint_t const *ep_desc); -bool usb_host_pipe_queue_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); -bool usb_host_pipe_xfer(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete); -bool usb_host_edpt_busy(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr); -bool usb_host_edpt_stalled(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr); -bool usb_host_edpt_clear_stall(usb_host_handle_t *handle, uint8_t dev_addr, uint8_t ep_addr); - -#if defined(__cplusplus) -} -#endif /* __cplusplus */ -#endif /* HPM_USB_HOST_H */ diff --git a/docs/Makefile b/docs/Makefile index caa38710c..95c33a4cc 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -6,9 +6,25 @@ SPHINXOPTS ?= #SPHINXBUILD ?= sphinx-build SPHINXBUILD ?= python3 -m sphinx.cmd.build +CMAKE_RST_GEN ?= python3 ../scripts/generate_cmake_rst.py --skip_private --skip_undocumented --headline="SDK CMake API Reference" ../cmake + +all: html + +cmake_intro: + @$(CMAKE_RST_GEN) -o cmake_intro.rst # Catch-all target: route all unknown targets to Sphinx using the new # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -html: Makefile +html: Makefile cmake_intro @$(SPHINXBUILD) -M $@ "en" "output/en" $(SPHINXOPTS) $(O) @$(SPHINXBUILD) -M $@ "zh" "output/zh" $(SPHINXOPTS) $(O) + + +.PHONY: all + +clean: + @rm -rf output + @rm -rf en/boards + @rm -rf en/samples + @rm -rf zh/boards + @rm -rf zh/samples diff --git a/docs/doxygen/Doxyfile b/docs/doxygen/Doxyfile index 15a02f9cd..10e50d6a1 100644 --- a/docs/doxygen/Doxyfile +++ b/docs/doxygen/Doxyfile @@ -2226,7 +2226,22 @@ INCLUDE_FILE_PATTERNS = # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. PREDEFINED = "HPM_EN_MATH_NN_LIB=1" \ - "HPM_EN_MATH_DSP_LIB=1" + "HPM_EN_MATH_DSP_LIB=1" \ + "HPM_IP_FEATURE_UART_RX_IDLE_DETECT=1" \ + "HPM_IP_FEATURE_UART_FCRR=1" \ + "HPM_IP_FEATURE_UART_RX_EN=1" \ + "HPM_IP_FEATURE_UART_E00018_FIX=1" \ + "HPM_IP_FEATURE_UART_9BIT_MODE=1" \ + "HPM_IP_FEATURE_UART_ADDR_MATCH=1" \ + "HPM_IP_FEATURE_UART_TRIG_MODE=1" \ + "HPM_IP_FEATURE_UART_FINE_FIFO_THRLD=1" \ + "HPM_IP_FEATURE_UART_IIR2=1" \ + "HPM_IP_FEATURE_PWM_COUNTER_RESET=1" \ + "HPM_IP_FEATURE_PWM_HRPWM=1" \ + "HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT=1" \ + "HPM_IP_FEATURE_SPI_CS_SELECT=1" \ + "HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO=1" \ + "HPM_IP_FEATURE_I2C_SUPPORT_RESET=1" \ # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The diff --git a/docs/en/conf.py b/docs/en/conf.py index 26c77274e..535b96b80 100644 --- a/docs/en/conf.py +++ b/docs/en/conf.py @@ -12,6 +12,7 @@ import shutil import re import sys +import datetime from pathlib import Path import sphinx_rtd_theme @@ -20,10 +21,10 @@ DOXY_OUT = HTML_STATIC_DIR / "api_doc" sys.path.insert(0, str(HPM_SDK_BASE / "docs" / "_ext")) - + os.environ["HPM_SDK_BASE"] = str(HPM_SDK_BASE) project = 'HPMicro Software Development Kit' -copyright = '2020-2023, HPMicro' +copyright = '2020-%s, HPMicro' % datetime.date.today().year author = 'HPMicro Software Team' # -- General configuration --------------------------------------------------- @@ -37,6 +38,7 @@ 'sphinx.ext.duration', 'sphinx_inline_tabs', "sphinx.ext.viewcode", + 'sphinxcontrib.moderncmakedomain', "external_content", "doxyrunner", ] @@ -47,8 +49,6 @@ doxyrunner_doxygen = os.environ.get("DOXYGEN_EXECUTABLE", "doxygen") doxyrunner_doxyfile = HPM_SDK_BASE / "docs" / "doxygen" / "Doxyfile" doxyrunner_outdir = DOXY_OUT -doxyrunner_fmt = True -doxyrunner_fmt_vars = {"HPM_SDK_BASE": str(HPM_SDK_BASE)} doxyrunner_outdir_var = "DOXYGEN_OUTPUT_DIR" # List of patterns, relative to source directory, that match files and @@ -63,6 +63,8 @@ } external_content_contents = [ + (HPM_SDK_BASE, "CHANGELOG.md"), + (HPM_SDK_BASE, "docs/*.rst"), (HPM_SDK_BASE / "docs/en", "[!_]*"), (HPM_SDK_BASE, "boards/**/*_en.md",), (HPM_SDK_BASE, "boards/**/doc"), diff --git a/docs/en/index.rst b/docs/en/index.rst index d7aa0737d..66d59beaf 100644 --- a/docs/en/index.rst +++ b/docs/en/index.rst @@ -18,7 +18,9 @@ Sections boards/index_en samples/index_en samples/drivers/index_en + docs/cmake_intro api_doc + CHANGELOG .. _BSD 3-Clause license: https://github.com/hpmicro/hpm_sdk/blob/main/LICENSE diff --git a/docs/requirements.txt b/docs/requirements.txt index 0fa7c6f56..c167f319f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -2,3 +2,4 @@ Sphinx==5.3.0 sphinx-rtd-theme myst-parser==0.18.1 sphinx-inline-tabs +sphinxcontrib-moderncmakedomain diff --git a/docs/zh/conf.py b/docs/zh/conf.py index 081b911a7..0657263cc 100644 --- a/docs/zh/conf.py +++ b/docs/zh/conf.py @@ -12,6 +12,7 @@ import shutil import re import sys +import datetime from pathlib import Path import sphinx_rtd_theme @@ -23,7 +24,7 @@ os.environ["HPM_SDK_BASE"] = str(HPM_SDK_BASE) project = 'HPMico Software Development Kit' -copyright = '2020-2023, HPMicro' +copyright = '2020-%s, HPMicro' % datetime.date.today().year author = '先楫半导体软件组' # -- General configuration --------------------------------------------------- @@ -37,6 +38,7 @@ 'sphinx.ext.duration', 'sphinx_inline_tabs', "sphinx.ext.viewcode", + 'sphinxcontrib.moderncmakedomain', "external_content", "doxyrunner", ] @@ -63,6 +65,8 @@ } external_content_contents = [ + (HPM_SDK_BASE, "CHANGELOG.md"), + (HPM_SDK_BASE, "docs/*.rst"), (HPM_SDK_BASE / "docs/zh", "[!_]*"), (HPM_SDK_BASE, "boards/**/*_zh.md",), (HPM_SDK_BASE, "boards/**/doc"), diff --git a/docs/zh/index.rst b/docs/zh/index.rst index 79fb2c7cc..be6fdca5a 100644 --- a/docs/zh/index.rst +++ b/docs/zh/index.rst @@ -18,7 +18,9 @@ hpm_sdk遵循 `BSD 3-Clause license`_ 许可 (许可文件具体内容请 查看 boards/index_zh samples/index_zh samples/drivers/index_zh + docs/cmake_intro api_doc + CHANGELOG .. _BSD 3-Clause license: https://github.com/hpmicro/hpm_sdk/blob/main/LICENSE diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index 4ab95d3c6..cbc883f0d 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -64,3 +64,4 @@ sdk_src_ifdef(HPMSOC_HAS_HPMSDK_MIPI_DSI_PHY src/hpm_mipi_dsi_phy_drv.c) sdk_src_ifdef(HPMSOC_HAS_HPMSDK_MIPI_CSI src/hpm_mipi_csi_drv.c) sdk_src_ifdef(HPMSOC_HAS_HPMSDK_MIPI_CSI_PHY src/hpm_mipi_csi_phy_drv.c) sdk_src_ifdef(HPMSOC_HAS_HPMSDK_OPAMP src/hpm_opamp_drv.c) +sdk_src_ifdef(HPMSOC_HAS_HPMSDK_TAMP src/hpm_tamp_drv.c) diff --git a/drivers/inc/hpm_adc12_drv.h b/drivers/inc/hpm_adc12_drv.h index 1e12f7bfa..ad49a8bcc 100644 --- a/drivers/inc/hpm_adc12_drv.h +++ b/drivers/inc/hpm_adc12_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -25,6 +25,9 @@ /** @brief Define ADC12 validity check for the channel number */ #define ADC12_IS_CHANNEL_INVALID(CH) (CH > ADC12_SOC_MAX_CH_NUM) +/** @brief Define ADC12 validity check for the channel sample cycle */ +#define ADC12_IS_CHANNEL_SAMPLE_CYCLE_INVALID(CYC) (CYC == 0) + /** @brief Define ADC12 validity check for the trigger number */ #define ADC12_IS_TRIG_CH_INVLAID(CH) (CH > ADC_SOC_MAX_TRIG_CH_NUM) diff --git a/drivers/inc/hpm_adc16_drv.h b/drivers/inc/hpm_adc16_drv.h index ab2f1bd49..47e5afcbd 100644 --- a/drivers/inc/hpm_adc16_drv.h +++ b/drivers/inc/hpm_adc16_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -26,6 +26,9 @@ #define ADC16_IS_CHANNEL_INVALID(CH) (CH > ADC16_SOC_MAX_CH_NUM) #endif +/** @brief Define ADC16 validity check for the channel sample cycle */ +#define ADC16_IS_CHANNEL_SAMPLE_CYCLE_INVALID(CYC) (CYC == 0) + /** @brief Define ADC16 validity check for the trigger number */ #define ADC16_IS_TRIG_CH_INVLAID(CH) (CH > ADC_SOC_MAX_TRIG_CH_NUM) diff --git a/drivers/inc/hpm_bgpr_drv.h b/drivers/inc/hpm_bgpr_drv.h index 42b385074..83d9b67a2 100644 --- a/drivers/inc/hpm_bgpr_drv.h +++ b/drivers/inc/hpm_bgpr_drv.h @@ -12,6 +12,14 @@ #include "hpm_soc_feature.h" #include "hpm_bgpr_regs.h" +/** + * + * @brief BGPR driver APIs + * @defgroup bgpr_interfaces BGPR driver APIs + * @ingroup io_interfaces + * @{ + */ + #if defined(__cplusplus) extern "C" { #endif /* __cplusplus */ diff --git a/drivers/inc/hpm_cam_drv.h b/drivers/inc/hpm_cam_drv.h index 2f46a8e8d..1e7156630 100644 --- a/drivers/inc/hpm_cam_drv.h +++ b/drivers/inc/hpm_cam_drv.h @@ -85,7 +85,6 @@ typedef struct { bool vsync_active_low; bool color_ext; bool data_pack_msb; - bool enable_buffer2; uint16_t data_store_mode; uint8_t color_format; uint8_t sensor_bitwidth; @@ -190,7 +189,27 @@ void cam_start(CAM_Type *ptr); */ void cam_stop(CAM_Type *ptr); -void cam_update_buffer(CAM_Type *ptr, uint32_t buffer); +/** + * @brief CAM update DMASA_FB1 buffer + * + * @param [in] ptr CAM base address + * @param [in] buffer buffer point address + */ +static inline void cam_update_buffer(CAM_Type *ptr, uint32_t buffer) +{ + ptr->DMASA_FB1 = buffer; +} + +/** + * @brief CAM update DMASA_FB2 buffer + * + * @param [in] ptr CAM base address + * @param [in] buffer buffer point address + */ +static inline void cam_update_buffer2(CAM_Type *ptr, uint32_t buffer) +{ + ptr->DMASA_FB2 = buffer; +} /** * @brief CAM enable binary output diff --git a/drivers/inc/hpm_can_drv.h b/drivers/inc/hpm_can_drv.h index a94bf0a35..db9ff7156 100644 --- a/drivers/inc/hpm_can_drv.h +++ b/drivers/inc/hpm_can_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -239,12 +239,12 @@ typedef struct { }; }; - can_node_mode_t mode; /**< CAN work mode */ + can_node_mode_t mode; /**< CAN work mode */ bool use_lowlevel_timing_setting; /**< Use low-level timing setting */ bool enable_canfd; /**< Enable CAN FD */ bool enable_self_ack; /**< CAN self-ack flag */ - bool disable_re_transmission_for_ptb; /**< disable re-transmission for primary transmit buffer */ - bool disable_re_transmission_for_stb; /**< disable re-transmission for secondary transmit buffer */ + bool disable_ptb_retransmission; /**< disable re-transmission for primary transmit buffer */ + bool disable_stb_retransmission; /**< disable re-transmission for secondary transmit buffer */ bool enable_tdc; /**< Enable transmittor delay compensation */ uint8_t filter_list_num; /**< element number of CAN filters in filter list */ @@ -336,6 +336,61 @@ static inline void can_enter_standby_mode(CAN_Type *base, bool enable) } } +/** + * @brief Disable the re-transmission for the primary transmission buffer + * + * @param [in] base CAN base address + * @param [in] enable Flag for disabling re-transmission for PTB + */ +static inline void can_disable_ptb_retransmission(CAN_Type *base, bool enable) +{ + if (enable) { + base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPSS_MASK; + } else { + base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TPSS_MASK; + } +} + +/** + * @brief Check whether re-transmission is disabled for PTB or not + * + * @param [in] base CAN base address + * @return true Re-transmission is disabled for PTB + * @return false Re-transmission is enabled for PTB + */ +static inline bool can_is_ptb_retransmission_disabled(CAN_Type *base) +{ + return ((base->CMD_STA_CMD_CTRL & CAN_CMD_STA_CMD_CTRL_TPSS_MASK) != 0); +} + +/** + * @brief Disable the re-transmission for the secondary transmission buffer + * + * @param [in] base CAN base address + * @param [in] enable Flag for disabling re-transmission for STB + */ +static inline void can_disable_stb_retransmission(CAN_Type *base, bool enable) +{ + if (enable) { + base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSSS_MASK; + } else { + base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TSSS_MASK; + } +} + +/** + * @brief Check whether re-transmission is disabled for STB or not + * + * @param [in] base CAN base address + * @return true Re-transmission is disabled for STB + * @return false Re-transmission is enabled for STB + */ +static inline bool can_is_stb_retransmission_disabled(CAN_Type *base) +{ + return ((base->CMD_STA_CMD_CTRL & CAN_CMD_STA_CMD_CTRL_TSSS_MASK) != 0); +} + + /** * @brief Select CAN TX buffer * @param [in] base CAN base address diff --git a/drivers/inc/hpm_common.h b/drivers/inc/hpm_common.h index 4536a576d..d89bae160 100644 --- a/drivers/inc/hpm_common.h +++ b/drivers/inc/hpm_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 HPMicro + * Copyright (c) 2021-2023 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -212,6 +212,60 @@ ATTR_PLACE_AT(section_name) ATTR_ALIGN(alignment) #define NOP() __asm volatile("nop") #define WFI() __asm volatile("wfi") +#define HPM_ATTR_MACHINE_INTERRUPT __attribute__ ((section(".isr_vector"), interrupt("machine"), aligned(4))) +#define HPM_ATTR_SUPERVISOR_INTERRUPT __attribute__ ((section(".isr_s_vector"), interrupt("supervisor"), aligned(4))) + +#elif defined(__ICCRISCV__) + + +/* alway_inline */ +#define ATTR_ALWAYS_INLINE __attribute__((always_inline)) + +/* weak */ +#define ATTR_WEAK __weak + +/* alignment */ +#define ATTR_ALIGN(alignment) __attribute__((aligned(alignment))) + +/* place var_declare at section_name, e.x. PLACE_AT(".target_section", var); */ +#define ATTR_PLACE_AT(section_name) __attribute__((section(section_name))) + +#define ATTR_PLACE_AT_WITH_ALIGNMENT(section_name, alignment) \ +ATTR_PLACE_AT(section_name) ATTR_ALIGN(alignment) + +#define ATTR_PLACE_AT_NONCACHEABLE ATTR_PLACE_AT(".noncacheable.bss") +#define ATTR_PLACE_AT_NONCACHEABLE_WITH_ALIGNMENT(alignment) \ + ATTR_PLACE_AT_NONCACHEABLE ATTR_ALIGN(alignment) + +#define ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_PLACE_AT(".noncacheable.bss") +#define ATTR_PLACE_AT_NONCACHEABLE_BSS_WITH_ALIGNMENT(alignment) \ + ATTR_PLACE_AT_NONCACHEABLE_BSS ATTR_ALIGN(alignment) + +/* initialize variable x with y using PLACE_AT_NONCACHEABLE_INIT(x) = {y}; */ +#define ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_PLACE_AT(".noncacheable.init") +#define ATTR_PLACE_AT_NONCACHEABLE_INIT_WITH_ALIGNMENT(alignment) \ + ATTR_PLACE_AT_NONCACHEABLE_INIT ATTR_ALIGN(alignment) + +#define ATTR_RAMFUNC ATTR_PLACE_AT(".fast") +#define ATTR_RAMFUNC_WITH_ALIGNMENT(alignment) \ + ATTR_RAMFUNC ATTR_ALIGN(alignment) + +#define ATTR_SHARE_MEM ATTR_PLACE_AT(".sh_mem") + +#define NOP() __asm volatile("nop") +#define WFI() __asm volatile("wfi") + +#define HPM_ATTR_MACHINE_INTERRUPT __machine __interrupt +#define HPM_ATTR_SUPERVISOR_INTERRUPT __supervisor __interrupt + +#ifndef __TIMEVAL_DEFINED +#define __TIMEVAL_DEFINED 1 +struct timeval { + long tv_sec; /* Seconds since the Epoch */ + long tv_usec; /* Microseconds */ +}; +#endif + #else #error Unknown toolchain #endif diff --git a/drivers/inc/hpm_crc_drv.h b/drivers/inc/hpm_crc_drv.h index 90a0f1931..a4d91124f 100644 --- a/drivers/inc/hpm_crc_drv.h +++ b/drivers/inc/hpm_crc_drv.h @@ -110,22 +110,9 @@ typedef struct crc_channel_config { extern "C" { #endif -/** - * @brief Reset CRC channel - * - * @param[in] ptr CRC base address - * @param[in] ch_index Index of the channel to be reset - * - */ -static inline void crc_reset(CRC_Type *ptr, uint32_t ch_index) -{ - ptr->CHN[ch_index].CLR |= CRC_CHN_CLR_CLR_MASK; -} - /** * @brief Get default channel config * - * @param[in] ptr CRC base address * @param[in] cfg Channel config */ void crc_get_default_channel_config(crc_channel_config_t *cfg); diff --git a/drivers/inc/hpm_display_common.h b/drivers/inc/hpm_display_common.h index 303174661..0e576e25c 100644 --- a/drivers/inc/hpm_display_common.h +++ b/drivers/inc/hpm_display_common.h @@ -148,6 +148,29 @@ typedef struct display_rgb2yuv_config { uint16_t y_offset; } display_rgb2yuv_config_t; +typedef enum display_buf_format { + display_buf_format_argb8888, /*!< memory layout in byte(low->high): b0[7:0], g0[7:0], r0[7:0], a0[7:0], b1[7:1], g1[7:1], r1[7:0], a1[7:0], ... */ + display_buf_format_bgra8888, /*!< memory layout in byte(low->high): a0[7:0], r0[7:0], g0[7:0], b0[7:0], a1[7:1], r1[7:1], g1[7:0], b1[7:0], ... */ + display_buf_format_rgb565, /*!< memory layout in byte(low->high): g0[2:0]:b0[4:0], r0[4:0]:g0[5:3], g1[2:0]:b1[4:0], r1[4:0]:g1[5:3], ... */ + display_buf_format_rgb565_swap, /*!< memory layout in byte(low->high): r0[4:0]:g0[5:3], g0[2:0]:b0[4:0], r2[4:0]:g2[5:3], g1[2:0]:b1[4:0], ... */ + display_buf_format_yuyv, /*!< memory layout in byte(low->high): y0, u0, y1, v0, y2, u2, y3, v2, ... */ + display_buf_format_uyvy, /*!< memory layout in byte(low->high): u0, y0, v0, y1, u2, y2, v2, y3, ... */ + display_buf_format_y8, /*!< memory layout in byte(low->high): y0, y1, y2, y3, y4, y5, ... */ + display_buf_format_max, +} display_buf_format_t; + +typedef struct display_buf { + void *buf; /*!< point pixel memory */ + uint16_t width; /*!< width in pixel */ + uint16_t height; /*!< height in pixel */ + uint32_t stride; /*!< stride each line, in byte */ + display_buf_format_t format; + struct { + display_alpha_op_t op; + uint8_t val; + } alpha; +} display_buf_t; + #ifdef __cplusplus extern "C" { #endif diff --git a/drivers/inc/hpm_dma_drv.h b/drivers/inc/hpm_dma_drv.h index 6cad7f570..d33f2afe9 100644 --- a/drivers/inc/hpm_dma_drv.h +++ b/drivers/inc/hpm_dma_drv.h @@ -208,8 +208,8 @@ static inline bool dma_channel_is_enable(DMA_Type *ptr, uint32_t ch_index) * @param[in] ptr DMA base address * @param[in] ch_index Index of the channel * @param[in] priority dma priority - * @arg @ref DMA_PRIORITY_LOW - * @arg @ref DMA_PRIORITY_HIGH + * @arg @ref DMA_CHANNEL_PRIORITY_LOW + * @arg @ref DMA_CHANNEL_PRIORITY_HIGH * */ static inline void dma_set_priority(DMA_Type *ptr, uint32_t ch_index, uint8_t priority) diff --git a/drivers/inc/hpm_dmav2_drv.h b/drivers/inc/hpm_dmav2_drv.h index 01058964e..407818608 100644 --- a/drivers/inc/hpm_dmav2_drv.h +++ b/drivers/inc/hpm_dmav2_drv.h @@ -219,8 +219,8 @@ static inline bool dma_channel_is_enable(DMAV2_Type *ptr, uint32_t ch_index) * @param[in] ptr DMA base address * @param[in] ch_index Index of the channel * @param[in] priority dma priority - * @arg @ref DMA_PRIORITY_LOW - * @arg @ref DMA_PRIORITY_HIGH + * @arg @ref DMA_CHANNEL_PRIORITY_LOW + * @arg @ref DMA_CHANNEL_PRIORITY_HIGH * */ static inline void dma_set_priority(DMAV2_Type *ptr, uint32_t ch_index, uint8_t priority) diff --git a/drivers/inc/hpm_enc_pos_drv.h b/drivers/inc/hpm_enc_pos_drv.h index b886f802e..677c39433 100644 --- a/drivers/inc/hpm_enc_pos_drv.h +++ b/drivers/inc/hpm_enc_pos_drv.h @@ -10,6 +10,14 @@ #include "hpm_common.h" +/** + * + * @brief enc pos driver APIs + * @defgroup enc_pos_interface Encode Position driver APIs + * @ingroup io_interface + * @{ + */ + #ifdef __cplusplus extern "C" { #endif @@ -49,7 +57,9 @@ uint32_t encoder_rad_to_position(float rad); #ifdef __cplusplus } #endif + /** * @} */ + #endif /* HPM_ENC_POS_COMMON_H */ diff --git a/drivers/inc/hpm_enet_drv.h b/drivers/inc/hpm_enet_drv.h index adb2a518a..395fdc4eb 100644 --- a/drivers/inc/hpm_enet_drv.h +++ b/drivers/inc/hpm_enet_drv.h @@ -557,7 +557,7 @@ uint32_t enet_get_interrupt_status(ENET_Type *ptr); * @brief Mask the specified mmc interrupt evenets of received frames * * @param[in] ptr An Ethernet peripheral base address - * @param[in] config A mask of the specified evenets + * @param[in] mask A mask of the specified evenets */ void enet_mask_mmc_rx_interrupt_event(ENET_Type *ptr, uint32_t mask); @@ -565,7 +565,7 @@ void enet_mask_mmc_rx_interrupt_event(ENET_Type *ptr, uint32_t mask); * @brief Mask the specified mmc interrupt evenets of transmitted frames * * @param[in] ptr An Ethernet peripheral base address - * @param[in] config A mask of the specified evenets + * @param[in] mask A mask of the specified evenets */ void enet_mask_mmc_tx_interrupt_event(ENET_Type *ptr, uint32_t mask); @@ -591,7 +591,7 @@ uint32_t enet_get_mmc_tx_interrupt_status(ENET_Type *ptr); * @param[in] inf_type the specified interface * @param[in] desc A pointer to descriptor config * @param[in] cfg A pointer to mac config - * @param[in] int_cfg A pointer to the masks of the specified enabled interrupts and the specified masked interrupts + * @param[in] int_config A pointer to the masks of the specified enabled interrupts and the specified masked interrupts * @return A result of the specified controller initialization */ hpm_stat_t enet_controller_init(ENET_Type *ptr, enet_inf_type_t inf_type, enet_desc_t *desc, enet_mac_config_t *cfg, enet_int_config_t *int_config); @@ -600,7 +600,7 @@ hpm_stat_t enet_controller_init(ENET_Type *ptr, enet_inf_type_t inf_type, enet_d * @brief Set port line speed * * @param[in] ptr An Ethernet peripheral base address - * @param[in] line_speed An enum variable of @ref enet_line_speed_t + * @param[in] speed An enum variable of @ref enet_line_speed_t */ void enet_set_line_speed(ENET_Type *ptr, enet_line_speed_t speed); @@ -809,7 +809,7 @@ void enet_set_snapshot_ptp_message_type(ENET_Type *ptr, enet_ts_ss_ptp_msg_t ts_ * @brief Set the pps0 control output * * @param[in] ptr An Ethernet peripheral base address - * @param[in] enet_pps_ctrl_t An enum value indicating the specified pps frequency + * @param[in] freq An enum value indicating the specified pps frequency */ void enet_set_pps0_control_output(ENET_Type *ptr, enet_pps_ctrl_t freq); @@ -827,7 +827,7 @@ hpm_stat_t enet_set_ppsx_command(ENET_Type *ptr, enet_pps_cmd_t cmd, enet_pps_id * @brief Set a pps config for ppsx * * @param[in] ptr An Ethernet peripheral base address - * @param[in] cmd An enum value indicating the specified pps config + * @param[in] cmd_cfg An enum value indicating the specified pps config * @param[in] idx An enum value indicating the index of pps instance * @retval hpm_stat_t @ref status_invalid_argument or @ref status_success */ diff --git a/drivers/inc/hpm_ewdg_drv.h b/drivers/inc/hpm_ewdg_drv.h index cb538cfc5..6c6398982 100644 --- a/drivers/inc/hpm_ewdg_drv.h +++ b/drivers/inc/hpm_ewdg_drv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 HPMicro + * Copyright (c) 2023-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -32,8 +32,7 @@ enum { /** * @brief EWDG Password Definitions * - * @defgroup ewdg_password_def - * @ingroup ewdg_password_def + * @defgroup ewdg_password_def EWDG Password definitions * @{ */ #define EWDG_REFRESH_UNLOCK_PASSWORD_DEFAULT (0xED09U) /*!< Default EWDG Refresh Password */ @@ -47,8 +46,7 @@ enum { /** * @brief EWDG Events * - * @defgroup ewdg_event - * @ingroup ewdg_event + * @defgroup ewdg_event EWDG Event definitions * @{ */ #define EWDG_EVENT_PARITY_ERROR (1UL << 6) /*!< Parity Error Event */ @@ -64,8 +62,7 @@ enum { /** * @brief EWDG Interrupts - * @defgroup ewdg_interrupt - * @ingroup ewdg_interrupt + * @defgroup ewdg_interrupt EWDG interrupt definitions * @{ */ #define EWDG_INT_PARITY_FAIL (1UL << 2) /*!< Parity Error Interrupt */ @@ -84,8 +81,7 @@ enum { /** * @brief EWDG Resets * - * @defgroup ewdg_reset_source - * @ingroup ewdg_reset_source + * @defgroup ewdg_reset_source EWDG reset source definitions * @{ */ #define EWDG_RST_PARITY_FAIL (1UL << 3) /*!< Parity Error Reset */ @@ -149,14 +145,14 @@ typedef enum { * The Actual Upper Window = Lower Window + Upper Window Limit */ typedef enum { - ewdg_window_upper_timeout_period_8_div_16 = 0, /*!< 8/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_1_div_16 = 1, /*!< 1/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_2_div_16 = 2, /*!< 2/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_3_div_16 = 3, /*!< 3/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_4_div_16 = 4, /*!< 4/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_5_div_16 = 5, /*!< 5/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_6_div_16 = 6, /*!< 6/16 of @ref timeout_reset_val */ - ewdg_window_upper_timeout_period_7_div_16 = 8, /*!< 7/16 of @ref timeout_reset_val */ + ewdg_window_upper_timeout_period_8_div_16 = 0, /*!< 8/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_1_div_16 = 1, /*!< 1/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_2_div_16 = 2, /*!< 2/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_3_div_16 = 3, /*!< 3/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_4_div_16 = 4, /*!< 4/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_5_div_16 = 5, /*!< 5/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_6_div_16 = 6, /*!< 6/16 of timeout_reset_val */ + ewdg_window_upper_timeout_period_7_div_16 = 8, /*!< 7/16 of timeout_reset_val */ /*! Maximum allowed upper limit */ ewdg_window_upper_timeout_period_max = ewdg_window_upper_timeout_period_7_div_16 } ewdg_window_upper_limit_t; @@ -387,6 +383,7 @@ void ewdg_disable(EWDG_Type *ptr); * * @param [in] ptr EWDG base * @param [in] config Control Function Configuration + * @param [in] cnt_src_freq Source frequency for EWDG counter * * @retval status_invalid_argument Invalid argument was detected * @retval status_success No error happened @@ -471,7 +468,7 @@ uint64_t ewdg_convert_timeout_us_to_timeout_ticks(uint32_t src_clk_freq, uint32_ * * @return timeout in terms of counter clock ticks */ -uint32_t ewdg_convert_timeout_ticks_to_timeout_us(EWDG_Type *ptr, uint32_t srk_clk_freq, uint32_t timeout_ticks); +uint32_t ewdg_convert_timeout_ticks_to_timeout_us(EWDG_Type *ptr, uint32_t src_clk_freq, uint32_t timeout_ticks); /** * @brief Enable EWDG interrupt diff --git a/drivers/inc/hpm_femc_drv.h b/drivers/inc/hpm_femc_drv.h index 4d532ad4b..e9f3af771 100644 --- a/drivers/inc/hpm_femc_drv.h +++ b/drivers/inc/hpm_femc_drv.h @@ -127,6 +127,7 @@ typedef struct { uint8_t idle_timeout_in_ns; uint8_t data_width_in_byte; uint8_t auto_refresh_count_in_one_burst; + bool delay_cell_disable; /**< Delay cell disable */ uint8_t delay_cell_value; /**< Delay cell value */ } femc_sdram_config_t; diff --git a/drivers/inc/hpm_gptmr_drv.h b/drivers/inc/hpm_gptmr_drv.h index a2a40af0d..ca1e1731b 100644 --- a/drivers/inc/hpm_gptmr_drv.h +++ b/drivers/inc/hpm_gptmr_drv.h @@ -330,6 +330,7 @@ static inline void gptmr_disable_cmp_output(GPTMR_Type *ptr, uint8_t ch_index) * * @param [in] ptr GPTMR base address * @param [in] ch_index channel index + * @param [in] mode enum gptmr_work_mode_capture_at_rising_edge or gptmr_work_mode_capture_at_falling_edge and so on */ static inline void gptmr_channel_set_capmode(GPTMR_Type *ptr, uint8_t ch_index, gptmr_work_mode_t mode) { diff --git a/drivers/inc/hpm_gwc_drv.h b/drivers/inc/hpm_gwc_drv.h index 13df9cf16..dc4da1278 100644 --- a/drivers/inc/hpm_gwc_drv.h +++ b/drivers/inc/hpm_gwc_drv.h @@ -145,7 +145,7 @@ void gwc_freeze_interrupt_control(GWC_Type *ptr); * @brief init gwc channel * * @param[in] ptr GWC base address - * @param[in] ch_index channel index @ref GWC_CHANNEL_CHn + * @param[in] ch_index channel index ref GWC_CHANNEL_CHn * @param[in] cfg config of gwc channel * * @note the function is called while gwc channel is disable only @@ -156,7 +156,7 @@ void gwc_ch_init(GWC_Type *ptr, uint8_t ch_index, gwc_ch_config_t *cfg); * @brief enable gwc channel * * @param[in] ptr GWC base address - * @param[in] ch_index channel index @ref GWC_CHANNEL_CHn + * @param[in] ch_index channel index ref GWC_CHANNEL_CHn */ static inline void gwc_ch_enable(GWC_Type *ptr, uint8_t ch_index) { @@ -168,7 +168,7 @@ static inline void gwc_ch_enable(GWC_Type *ptr, uint8_t ch_index) * @brief disable gwc channel * * @param[in] ptr GWC base address - * @param[in] ch_index channel index @ref GWC_CHANNEL_CHn + * @param[in] ch_index channel index ref GWC_CHANNEL_CHn */ static inline void gwc_ch_disable(GWC_Type *ptr, uint8_t ch_index) { @@ -180,7 +180,7 @@ static inline void gwc_ch_disable(GWC_Type *ptr, uint8_t ch_index) * @brief get gwc channel calc crc * * @param[in] ptr GWC base address - * @param[in] ch_index channel index @ref GWC_CHANNEL_CHn + * @param[in] ch_index channel index ref GWC_CHANNEL_CHn */ static inline uint32_t gwc_ch_get_crc(GWC_Type *ptr, uint8_t ch_index) { diff --git a/drivers/inc/hpm_i2c_drv.h b/drivers/inc/hpm_i2c_drv.h index 47bf751c8..aefc95079 100644 --- a/drivers/inc/hpm_i2c_drv.h +++ b/drivers/inc/hpm_i2c_drv.h @@ -85,6 +85,13 @@ enum { #define I2C_STATUS_BUS_BUSY I2C_STATUS_BUSBUSY_MASK #define I2C_STATUS_ACK I2C_STATUS_ACK_MASK +#define I2C_WR 0x0000 /* not operable with read flags*/ +#define I2C_RD (1u << 0) /* not operable with write flags*/ +#define I2C_ADDR_10BIT (1u << 2) /* this is a ten bit chip address */ +#define I2C_NO_START (1u << 4) /* no start */ +#define I2C_NO_READ_ACK (1u << 6) /* when I2C reading, we do not ACK */ +#define I2C_NO_STOP (1u << 7) /* no stop */ + /** * @brief I2C config */ @@ -158,7 +165,8 @@ static inline void i2c_clear_fifo(I2C_Type *ptr) */ static inline uint8_t i2c_get_data_count(I2C_Type *ptr) { - return (I2C_CTRL_DATACNT_HIGH_GET(ptr->CTRL) << 8U) + I2C_CTRL_DATACNT_GET(ptr->CTRL); + uint32_t i2c_ctrl = ptr->CTRL; + return (I2C_CTRL_DATACNT_HIGH_GET(i2c_ctrl) << 8U) + I2C_CTRL_DATACNT_GET(i2c_ctrl); } /** @@ -599,8 +607,8 @@ hpm_stat_t i2c_master_configure_transfer(I2C_Type *i2c_ptr, const uint16_t devic /** * @brief sequential transmit in master I2C mode an amount of data in blocking * - * @param i2c_ptr [in] ptr I2C base address - * @param device_address [in] I2C slave address + * @param [in] ptr ptr I2C base address + * @param [in] device_address I2C slave address * @param [in] buf pointer of the buffer to store data sent from device * @param [in] size size of data to be sent in bytes * @param [in] opt I2c sequential transfer options @@ -612,8 +620,8 @@ hpm_stat_t i2c_master_seq_transmit(I2C_Type *ptr, const uint16_t device_address, /** * @brief sequential receive in master I2C mode an amount of data in blocking * - * @param i2c_ptr [in] ptr I2C base address - * @param device_address [in] I2C slave address + * @param [in] ptr ptr I2C base address + * @param [in] device_address I2C slave address * @param [in] buf pointer of the buffer to store data sent from device * @param [in] size size of data to be sent in bytes * @param [in] opt I2c sequential transfer options @@ -622,11 +630,11 @@ hpm_stat_t i2c_master_seq_transmit(I2C_Type *ptr, const uint16_t device_address, hpm_stat_t i2c_master_seq_receive(I2C_Type *ptr, const uint16_t device_address, uint8_t *buf, const uint32_t size, i2c_seq_transfer_opt_t opt); -#if defined(I2C_SOC_SUPPORT_RESET) && (I2C_SOC_SUPPORT_RESET == 1) +#if defined(HPM_IP_FEATURE_I2C_SUPPORT_RESET) && (HPM_IP_FEATURE_I2C_SUPPORT_RESET == 1) /** * @brief generate SCL clock as reset signal * - * @param i2c_ptr [in] ptr I2C base address + * @param ptr [in] ptr I2C base address * @param [in] clk_len SCL clock length */ static inline void i2s_gen_reset_signal(I2C_Type *ptr, uint8_t clk_len) @@ -636,6 +644,18 @@ static inline void i2s_gen_reset_signal(I2C_Type *ptr, uint8_t clk_len) } #endif +/** + * @brief data transfer on master I2C mode in blocking + * + * @param [in] ptr ptr I2C base address + * @param [in] device_address I2C slave address + * @param [in] buf pointer of the buffer to store data sent from device + * @param [in] size size of data to be sent in bytes + * @param [in] flags flag bit, which can be other flag bits except I2C_WR I2C_RD, and can perform "|" operation + * @retval hpm_stat_t status_success if receive is completed without any error + */ +hpm_stat_t i2c_master_transfer(I2C_Type *ptr, const uint16_t device_address, + uint8_t *buf, const uint32_t size, uint16_t flags); /** * @} */ diff --git a/drivers/inc/hpm_i2s_drv.h b/drivers/inc/hpm_i2s_drv.h index 28d4c0d81..10fbf5631 100644 --- a/drivers/inc/hpm_i2s_drv.h +++ b/drivers/inc/hpm_i2s_drv.h @@ -43,7 +43,8 @@ typedef struct i2s_config { bool use_external_fclk; bool enable_mclk_out; bool frame_start_at_rising_edge; - uint16_t fifo_threshold; + uint16_t tx_fifo_threshold; + uint16_t rx_fifo_threshold; } i2s_config_t; /** @@ -327,6 +328,7 @@ static inline void i2s_reset_clock_gen(I2S_Type *ptr) * @brief I2S reset tx function * * @note This API will disable I2S, reset tx function + * Please ensure that there is a valid BCLK when calling this function * * @param [in] ptr I2S base address */ @@ -344,6 +346,7 @@ static inline void i2s_reset_tx(I2S_Type *ptr) * @brief I2S reset rx function * * @note This API will disable I2S, reset rx function + * Please ensure that there is a valid BCLK when calling this function * * @param [in] ptr I2S base address */ @@ -361,6 +364,7 @@ static inline void i2s_reset_rx(I2S_Type *ptr) * @brief I2S reset tx and rx function * * @note This API will disable I2S, reset tx/rx function + * Please ensure that there is a valid BCLK when calling this function * * @param [in] ptr I2S base address */ @@ -374,6 +378,17 @@ static inline void i2s_reset_tx_rx(I2S_Type *ptr) ptr->CTRL &= ~(I2S_CTRL_TXFIFOCLR_MASK | I2S_CTRL_RXFIFOCLR_MASK | I2S_CTRL_SFTRST_TX_MASK | I2S_CTRL_SFTRST_RX_MASK); } +/** + * @brief I2S reset tx/rx and clock generator module + * + * @note This API will disable I2S, reset tx/rx and clock generator module + * This function uses an internal clock to generate BCLK, then do reset operation, + * and finally restores the previous clock settings + * + * @param [in] ptr I2S base address + */ +void i2s_reset_all(I2S_Type *ptr); + /** * @brief I2S get tx fifo level * diff --git a/drivers/inc/hpm_lcdc_drv.h b/drivers/inc/hpm_lcdc_drv.h index dace3fd8a..c6bc1bae3 100644 --- a/drivers/inc/hpm_lcdc_drv.h +++ b/drivers/inc/hpm_lcdc_drv.h @@ -101,6 +101,7 @@ typedef struct lcdc_layer_config { uint16_t position_y; /**< Layer output position Y coord */ display_color_32b_t background; /**< Background color */ uint32_t buffer; /**< Pointer of layer display buffer */ + uint32_t stride; /**< stride of lines in bytes. stride is calculated by driver if stride == 0. */ } lcdc_layer_config_t; #ifdef __cplusplus diff --git a/drivers/inc/hpm_linv2_drv.h b/drivers/inc/hpm_linv2_drv.h index bb26fd74f..57ce9e637 100644 --- a/drivers/inc/hpm_linv2_drv.h +++ b/drivers/inc/hpm_linv2_drv.h @@ -13,18 +13,18 @@ #include "hpm_linv2_regs.h" #include "hpm_soc_feature.h" -/** bit4 and bit5 encode data length in ID */ -#define LIN_ID_DATA_LEN_SHIFT 4U -#define LIN_ID_DATA_LEN_MASK 0x30U -#define LIN_ID_DATA_LEN_GET(x) (((uint8_t)(x) & LIN_ID_DATA_LEN_MASK) >> LIN_ID_DATA_LEN_SHIFT) - /** * @brief LINV2 driver APIs * @defgroup linv2_interface LINV2 driver APIs - * @ingroup linv2_interface + * @ingroup linv2_interfaces * @{ */ +/** bit4 and bit5 encode data length in ID */ +#define LIN_ID_DATA_LEN_SHIFT 4U +#define LIN_ID_DATA_LEN_MASK 0x30U +#define LIN_ID_DATA_LEN_GET(x) (((uint8_t)(x) & LIN_ID_DATA_LEN_MASK) >> LIN_ID_DATA_LEN_SHIFT) + /** * @brief data length in ID bit4 and bit5 */ @@ -191,7 +191,7 @@ static inline void lin_set_mode(LINV2_Type *ptr, bool master) * @brief lin set checksum mode * * @param ptr lin base address - * @param enhance_check true for enhance checksum mode, false for normal checksum mode + * @param enhance_checksum true for enhance checksum mode, false for normal checksum mode */ static inline void lin_set_checksum_mode(LINV2_Type *ptr, bool enhance_checksum) { @@ -364,13 +364,13 @@ hpm_stat_t lin_slave_receive(LINV2_Type *ptr, lin_trans_config_t *config); */ void lin_slave_dma_transfer(LINV2_Type *ptr, lin_trans_config_t *config); -/** - * @} - */ - #ifdef __cplusplus } #endif +/** + * @} + */ + #endif /* HPM_LINV2_DRV_H */ diff --git a/drivers/inc/hpm_lvb_drv.h b/drivers/inc/hpm_lvb_drv.h index 6a8586e3b..efc5f7b33 100644 --- a/drivers/inc/hpm_lvb_drv.h +++ b/drivers/inc/hpm_lvb_drv.h @@ -175,7 +175,7 @@ void lvb_init(LVB_Type *ptr, lvb_config_t *cfg); /** * @brief get LVB channel of default config * - * @param[out] cfg config of LVB + * @param[out] ch_cfg config of LVB */ void lvb_get_ch_default_config(lvb_ch_config_t *ch_cfg); @@ -184,7 +184,7 @@ void lvb_get_ch_default_config(lvb_ch_config_t *ch_cfg); * * @param[in] ptr LVB base address * @param[in] ch_num LVB channel number - * @param[in] cfg config of LVB channel + * @param[in] ch_cfg config of LVB channel */ void lvb_ch_config(LVB_Type *ptr, lvb_ch_num_t ch_num, lvb_ch_config_t *ch_cfg); diff --git a/drivers/inc/hpm_mcan_drv.h b/drivers/inc/hpm_mcan_drv.h index 00319da7e..766fb73a7 100644 --- a/drivers/inc/hpm_mcan_drv.h +++ b/drivers/inc/hpm_mcan_drv.h @@ -38,6 +38,7 @@ enum { status_mcan_tx_evt_fifo_empty, status_mcan_timestamp_not_exist, status_mcan_ram_out_of_range, + status_mcan_timeout, }; /** @@ -78,12 +79,12 @@ enum { #define MCAN_INT_RXFIFO0_MSG_LOST MCAN_IR_RF0L_MASK /*!< RX FIFO0 Message Lost */ #define MCAN_INT_RXFIFO0_FULL MCAN_IR_RF0F_MASK /*!< RX FIFO0 Full */ #define MCAN_INT_RXFIFO0_WMK_REACHED MCAN_IR_RF0W_MASK /*!< RX FIFO0 Watermark Reached */ -#define MCAN_INT_RXFIFI0_NEW_MSG MCAN_IR_RF0N_MASK /*!< RX FIFO0 New Message */ +#define MCAN_INT_RXFIFO0_NEW_MSG MCAN_IR_RF0N_MASK /*!< RX FIFO0 New Message */ /** * @brief MCAN Receive Event Flags */ -#define MCAN_EVENT_RECEIVE (MCAN_INT_RXFIFI0_NEW_MSG | MCAN_INT_RXFIFO1_NEW_MSG | MCAN_INT_MSG_STORE_TO_RXBUF) +#define MCAN_EVENT_RECEIVE (MCAN_INT_RXFIFO0_NEW_MSG | MCAN_INT_RXFIFO1_NEW_MSG | MCAN_INT_MSG_STORE_TO_RXBUF) /** * @brief MCAN Transmit Event Flags @@ -410,7 +411,7 @@ typedef union { /** * @brief MCAN RAM Flexible Configuration * - * @Note This Configuration provides the full MCAN RAM configuration, this configuration is recommended only for + * @note This Configuration provides the full MCAN RAM configuration, this configuration is recommended only for * experienced developers who is skilled at the MCAN IP */ typedef struct mcan_ram_flexible_config_struct { @@ -438,7 +439,7 @@ typedef struct mcan_ram_flexible_config_struct { /** * @brief MCAN RAM configuration * - * @Note: This Configuration focuses on the minimum required information for MCAN RAM configuration + * @note: This Configuration focuses on the minimum required information for MCAN RAM configuration * The Start address of each BUF/FIFO will be automatically calculated by the MCAN Driver API * This RAM configuration is recommended for the most developers */ @@ -561,7 +562,7 @@ typedef struct mcan_filter_elem_list_struct { /** * @brief MCAN Configuration for all filters * - * @Note The MCAN RAM related settings are excluded + * @note The MCAN RAM related settings are excluded */ typedef struct mcan_all_filters_config_struct { mcan_global_filter_config_t global_filter_config; /*!< Global Filter configuration */ @@ -626,12 +627,31 @@ typedef struct mcan_internal_timestamp_config_struct { uint8_t timestamp_selection; /*!< Timestamp Select */ } mcan_internal_timestamp_config_t; +/** + * @brief MCAN Timeout Selection Options + */ +typedef enum mcan_timeout_sel_enum { + mcan_timeout_continuous_operation = 0, /*!< Continuously count down timeout after writing to TOCV register */ + mcan_timeout_triggered_by_tx_evt_fifo = 1, /*!< Count down if the TX EVT FIFO is not empty */ + mcan_timeout_triggered_by_rx_fifo0 = 2, /*!< Count down if the RX FIFO0 is not empty */ + mcan_timeout_triggered_by_rx_fifo1 = 3, /*!< Count down if the RX FIFO1 is not empty */ +} mcan_timeout_sel_t; + +/** + * @brief MCAN Timeout configuration structure + */ +typedef struct mcan_timeout_config_struct { + bool enable_timeout_counter; /*!< Enable Timeout Counter */ + mcan_timeout_sel_t timeout_sel; /*!< Timeout source selection */ + uint16_t timeout_period; /*!< Timeout period */ +} mcan_timeout_config_t; + /** * @brief MCAN Configuration Structure */ typedef struct mcan_config_struct { union { - /* This struct takes effect if use_lowlevl_timing_setting = false */ + /* This struct takes effect if "use_lowlevel_timing_setting = false" */ struct { uint32_t baudrate; /*!< CAN 2.0 baudrate/CAN-FD Nominal Baudrate, in terms of bps */ uint32_t baudrate_fd; /*!< CANFD data baudrate, in terms of bps */ @@ -640,7 +660,7 @@ typedef struct mcan_config_struct { uint16_t canfd_samplepoint_min; /*!< Value = Minimum CANFD sample point * 10 */ uint16_t canfd_samplepoint_max; /*!< Value = Maximum CANFD sample point * 10 */ }; - /* This struct takes effect if use_lowlevl_timing_setting = true */ + /* This struct takes effect if "use_lowlevel_timing_setting = true" */ struct { mcan_bit_timing_param_t can_timing; /*!< CAN2.0/CANFD nominal timing setting */ mcan_bit_timing_param_t canfd_timing; /*!< CANFD data timing setting */ @@ -656,7 +676,7 @@ typedef struct mcan_config_struct { bool use_timestamping_unit; /*!< Use external Timestamp Unit */ bool enable_canfd; /*!< Enable CANFD mode */ bool enable_tdc; /*!< Enable transmitter delay compensation */ - bool enable_restricted_operation_mode; /*!< Enable Resricted Operation Mode: Receive only */ + bool enable_restricted_operation_mode; /*!< Enable Restricted Operation Mode: Receive only */ bool disable_auto_retransmission; /*!< Disable auto retransmission */ uint8_t padding[2]; mcan_internal_timestamp_config_t timestamp_cfg; /*!< Internal Timestamp Configuration */ @@ -664,6 +684,8 @@ typedef struct mcan_config_struct { mcan_ram_config_t ram_config; /*!< MCAN RAM configuration */ mcan_all_filters_config_t all_filters_config; /*!< All Filter configuration */ + mcan_timeout_config_t timeout_cfg; /*!< Timeout configuration */ + uint32_t interrupt_mask; /*!< Interrupt Enable mask */ uint32_t txbuf_trans_interrupt_mask; /*!< Tx Buffer Transmission Interrupt Enable mask */ uint32_t txbuf_cancel_finish_interrupt_mask; /*!< TX Buffer Cancellation Finished Interrupt Enable Mask */ @@ -1011,6 +1033,16 @@ static inline uint16_t mcan_get_timeout_counter_value(MCAN_Type *ptr) return ptr->TOCV; } +/** + * @brief Reset Timeout counter value + * + * @param [in] ptr MCAN base + */ +static inline void mcan_reset_timeout_counter_value(MCAN_Type *ptr) +{ + *((volatile uint32_t *) &ptr->TOCV) = 0; +} + /** * @brief Get Error Counter Information * @param [in] ptr MCAN base @@ -1436,16 +1468,21 @@ uint8_t mcan_get_data_field_size(uint8_t data_field_size_option); * - Dedicated TXBUF element count: 16 * - TXFIFO/QQueue element count: 16 * - Data Field Size: 8 + * . * - RXFIFO0 Elements Info: * - Element Count :32 * - Data Field Size: 8 + * . * - RXFIFO1 Elements Info: * - Element Count : 32 * - Data Field Size: 8 + * . * - RXBUF Element Info: * - Element Count: 16 * - Data Field Size : 8 + * . * - TX Event FIFO Element Count: 32 + * . * If the device is configured as CANFD node, the default CAN RAM settings are as below: * - Standard Identifier Filter Elements: 16 * - Extended Identifier Filter Elements: 16 @@ -1454,17 +1491,21 @@ uint8_t mcan_get_data_field_size(uint8_t data_field_size_option); * - Dedicated TXBUF element count: 4 * - TXFIFO/QQueue element count: 4 * - Data Field Size: 64 + * . * - RXFIFO0 Elements Info: * - Element Count : 8 * - Data Field Size: 64 + * . * - RXFIFO1 Elements Info: * - Element Count : 8 * - Data Field Size: 64 + * . * - RXBUF Element Info: * - Element Count: 4 * - Data Field Size : 64 + * . * - TX Event FIFO Element Count: 8 - * + * . * @param [in] ptr MCAN base * @param [out] ram_config CAN RAM Configuration * @param [in] enable_canfd CANFD enable flag @@ -1481,16 +1522,21 @@ void mcan_get_default_ram_flexible_config(MCAN_Type *ptr, mcan_ram_flexible_conf * - Dedicated TXBUF element count: 16 * - TXFIFO/QQueue element count: 16 * - Data Field Size: 8 + * . * - RXFIFO0 Elements Info: * - Element Count :32 * - Data Field Size: 8 + * . * - RXFIFO1 Elements Info: * - Element Count : 32 * - Data Field Size: 8 + * . * - RXBUF Element Info: * - Element Count: 16 * - Data Field Size : 8 + * . * - TX Event FIFO Element Count: 32 + * . * If the device is configured as CANFD node, the default CAN RAM settings are as below: * - Standard Identifier Filter Elements: 16 * - Extended Identifier Filter Elements: 16 @@ -1499,19 +1545,23 @@ void mcan_get_default_ram_flexible_config(MCAN_Type *ptr, mcan_ram_flexible_conf * - Dedicated TXBUF element count: 4 * - TXFIFO/QQueue element count: 4 * - Data Field Size: 64 + * . * - RXFIFO0 Elements Info: * - Element Count : 8 * - Data Field Size: 64 + * . * - RXFIFO1 Elements Info: * - Element Count : 8 * - Data Field Size: 64 + * . * - RXBUF Element Info: * - Element Count: 4 * - Data Field Size : 64 + * . * - TX Event FIFO Element Count: 8 - * + * . * @param [in] ptr MCAN base - * @param [out] ram_config CAN RAM Configuration + * @param [out] simple_config Simple CAN RAM Configuration * @param [in] enable_canfd CANFD enable flag */ void mcan_get_default_ram_config(MCAN_Type *ptr, mcan_ram_config_t *simple_config, bool enable_canfd); diff --git a/drivers/inc/hpm_mipi_csi_drv.h b/drivers/inc/hpm_mipi_csi_drv.h index 12b097a1b..e04d7feb0 100644 --- a/drivers/inc/hpm_mipi_csi_drv.h +++ b/drivers/inc/hpm_mipi_csi_drv.h @@ -45,7 +45,7 @@ extern "C" { /** * @brief get MIPI_CSI default config * - * @cfg: MIPI_CSI default config + * @param cfg: MIPI_CSI default config */ void mipi_csi_get_defconfig(mipi_csi_config_t *cfg); @@ -71,7 +71,7 @@ void mipi_csi_phy_poweron(MIPI_CSI_Type *ptr); */ void mipi_csi_phy_powerdown(MIPI_CSI_Type *ptr); -/* +/** * @brief MIPI_CSI check clklane whether on HS state * * @param ptr MIPI_DCI base address diff --git a/drivers/inc/hpm_mipi_dsi_drv.h b/drivers/inc/hpm_mipi_dsi_drv.h index 34cbbf7fd..6060aa457 100644 --- a/drivers/inc/hpm_mipi_dsi_drv.h +++ b/drivers/inc/hpm_mipi_dsi_drv.h @@ -107,21 +107,14 @@ typedef enum mipi_dsi_video_mode { /** * mipi_dsi_msg_t - read/write DSI buffer - * @channel: virtual channel id - * @type: payload data type - * @flags: flags controlling this message transmission - * @tx_len: length of @tx_buf - * @tx_buf: data to be written - * @rx_len: length of @rx_buf - * @rx_buf: data to be read, or NULL */ typedef struct mipi_dsi_msg { - uint8_t channel; - uint8_t type; - uint16_t tx_len; - const void *tx_buf; - uint16_t rx_len; - void *rx_buf; + uint8_t channel; /*!< virtual channel id */ + uint8_t type; /*!< payload data type */ + uint16_t tx_len; /*!< length of tx_buf */ + const void *tx_buf; /*!< data to be written */ + uint16_t rx_len; /*!< length of rx_buf */ + void *rx_buf; /*!< data to be read, or NULL */ } mipi_dsi_msg_t; typedef struct mipi_video_para { @@ -155,7 +148,7 @@ extern "C" { /** * @brief get MIPI_DSI default config on video mode * - * @cfg: MIPI_DSI default config + * @param cfg: MIPI_DSI default config */ void mipi_dsi_get_defconfig_on_video(mipi_dsi_config_t *cfg); @@ -211,9 +204,9 @@ int mipi_dsi_lp_cmd_transfer(MIPI_DSI_Type *ptr, const mipi_dsi_msg_t *msg); * the payload in a long packet transmitted from the peripheral back to the * host processor * - * @ptr: MIPI_DSI base address - * @channel: virtual channel - * @value: the maximum size of the payload + * @param ptr: MIPI_DSI base address + * @param channel: virtual channel + * @param value: the maximum size of the payload * * @return: true on success or false on failure. */ @@ -222,10 +215,10 @@ int mipi_dsi_set_maximum_return_packet_size(MIPI_DSI_Type *ptr, uint8_t channel, /** * @brief transmit data using a generic write packet * - * @ptr: MIPI_DSI base address - * @channel: virtual channel - * @payload: buffer containing the payload - * @size: size of payload buffer + * @param ptr: MIPI_DSI base address + * @param channel: virtual channel + * @param payload: buffer containing the payload + * @param size: size of payload buffer * * This function will automatically choose the right data type depending on * the payload length. @@ -239,12 +232,12 @@ int mipi_dsi_generic_write(MIPI_DSI_Type *ptr, uint8_t channel, const void *payl /** * @brief receive data using a generic read packet * - * @ptr: MIPI_DSI base address - * @channel: virtual channel - * @params: buffer containing the request parameters - * @num_params: number of request parameters - * @data: buffer in which to return the received data - * @size: size of receive buffer + * @param ptr: MIPI_DSI base address + * @param channel: virtual channel + * @param params: buffer containing the request parameters + * @param num_params: number of request parameters + * @param data: buffer in which to return the received data + * @param size: size of receive buffer * * This function will automatically choose the right data type depending on * the number of parameters passed in. @@ -258,10 +251,10 @@ int mipi_dsi_generic_read(MIPI_DSI_Type *ptr, uint8_t channel, const void *param /** * @brief transmit a DCS command with payload * - * @ptr: MIPI_DSI base address - * @channel: virtual channel - * @data: buffer containing data to be transmitted - * @len: size of transmission buffer + * @param ptr: MIPI_DSI base address + * @param channel: virtual channel + * @param data: buffer containing data to be transmitted + * @param len: size of transmission buffer * * This function will automatically choose the right data type depending on * the command payload length. @@ -275,11 +268,11 @@ int mipi_dsi_dcs_write_buffer(MIPI_DSI_Type *ptr, uint8_t channel, /** * @brief send DCS write command * - * @ptr: MIPI_DSI base address - * @channel: virtual channel - * @cmd: DCS command - * @data: buffer containing the command payload - * @len: command payload length + * @param ptr: MIPI_DSI base address + * @param channel: virtual channel + * @param cmd: DCS command + * @param data: buffer containing the command payload + * @param len: command payload length * * This function will automatically choose the right data type depending on * the command payload length. @@ -293,11 +286,11 @@ int mipi_dsi_dcs_write(MIPI_DSI_Type *ptr, uint8_t channel, uint8_t cmd, /** * @brief send DCS read request command * - * @ptr: MIPI_DSI base address - * @channel: virtual channel - * @cmd: DCS command - * @data: buffer in which to receive data - * @len: size of receive buffer + * @param ptr: MIPI_DSI base address + * @param channel: virtual channel + * @param cmd: DCS command + * @param data: buffer in which to receive data + * @param len: size of receive buffer * * @return: The number of bytes read or a negative error code on failure. */ diff --git a/drivers/inc/hpm_mmc_drv.h b/drivers/inc/hpm_mmc_drv.h index a7417b797..aec551480 100644 --- a/drivers/inc/hpm_mmc_drv.h +++ b/drivers/inc/hpm_mmc_drv.h @@ -13,7 +13,7 @@ /** * @brief MMC driver APIs * @defgroup mmc_interface MMC driver APIs - * @ingroup mmc_interface + * @ingroup mmc_interfaces * @{ */ @@ -360,14 +360,14 @@ void mmc_track_config_coef_para(MMC_Type *base, mmc_coef_input_t *para); /** * @brief MMC track config position trigger * @param [in] base MMC base address - * @param [in] para mmc_pos_trig_t + * @param [in] trig mmc_pos_trig_t */ void mmc_track_config_position_trig(MMC_Type *base, mmc_pos_trig_t *trig); /** * @brief MMC track config speed trigger * @param [in] base MMC base address - * @param [in] para mmc_speed_trig_t + * @param [in] trig mmc_speed_trig_t */ void mmc_track_config_speed_trig(MMC_Type *base, mmc_speed_trig_t *trig); @@ -392,6 +392,7 @@ static inline void mmc_track_disable_speed_trig(MMC_Type *base) /** * @brief MMC track config multiple coef trigger * @param [in] base MMC base address + * @param [in] index coef trigger index(0/1/2) * @param [in] config mmc_coef_trig_config_t */ void mmc_track_config_coef_trig(MMC_Type *base, uint8_t index, mmc_coef_trig_config_t *config); diff --git a/drivers/inc/hpm_mono_drv.h b/drivers/inc/hpm_mono_drv.h index eaa2a39fa..e711dcfb5 100644 --- a/drivers/inc/hpm_mono_drv.h +++ b/drivers/inc/hpm_mono_drv.h @@ -24,56 +24,19 @@ extern "C" { #endif -/** - * @brief Get counter high - * - * @param[in] ptr MONO base address - * - * @return counter value high 16 bits - */ -static inline uint16_t mono_get_counter_high(MONO_Type *ptr) -{ - return MONO_MONOH_COUNTER_GET(ptr->MONOH); -} - -/** - * @brief Get counter low - * - * @param[in] ptr MONO base address - * - * @return counter value low 32 bits - */ -static inline uint32_t mono_get_counter_low(MONO_Type *ptr) -{ - return MONO_MONOL_COUNTER_GET(ptr->MONOL); -} - /** * @brief Get counter * * @param[in] ptr MONO base address * - * @return 48 bits counter value + * @return 64 bits counter value */ static inline uint64_t mono_get_counter(MONO_Type *ptr) { - return (uint64_t)((uint64_t)mono_get_counter_high(ptr) << 32) - | (uint64_t)mono_get_counter_low(ptr); -} - -/** - * @brief Get epoch - * - * @param[in] ptr MONO Base address - * - * @return epoch value 16 bits - */ -static inline uint32_t mono_get_epoch(MONO_Type *ptr) -{ - return MONO_MONOH_EPOCH_GET(ptr->MONOH); + return (uint64_t)((uint64_t)((ptr->MONOH) << 32)) + | (uint64_t)((ptr->MONOL)); } - /** * @brief Update MONO counter by 1 * diff --git a/drivers/inc/hpm_opamp_drv.h b/drivers/inc/hpm_opamp_drv.h index 3ebf93048..329db9f02 100644 --- a/drivers/inc/hpm_opamp_drv.h +++ b/drivers/inc/hpm_opamp_drv.h @@ -216,7 +216,7 @@ static inline void opamp_preset_opamp_disable(OPAMP_Type *opamp, uint8_t preset_ * @brief opamp miller cap selection * * @param opamp @ref OPAMP_Type - * @param select @ref opamp_iref_select_t + * @param select @ref opamp_miller_cap_t */ static inline void opamp_miller_cap_select(OPAMP_Type *opamp, opamp_miller_cap_t select) { @@ -228,7 +228,7 @@ static inline void opamp_miller_cap_select(OPAMP_Type *opamp, opamp_miller_cap_t * * @param opamp @ref OPAMP_Type * @param preset_chn preset channel - * @param select @ref opamp_iref_select_t + * @param select @ref opamp_miller_cap_t */ static inline void opamp_preset_miller_cap_select(OPAMP_Type *opamp, uint8_t preset_chn, opamp_miller_cap_t select) { @@ -515,7 +515,7 @@ static inline void opamp_preset_disable_hw_trig(OPAMP_Type *opamp, uint8_t prese * @brief opamp set mode * * @param opamp @ref OPAMP_Type - * @param mode @ref OPAMP_MODE_XX + * @param mode OPAMP_MODE_XX */ static inline void opamp_mode_set(OPAMP_Type *opamp, uint8_t mode) { @@ -527,7 +527,7 @@ static inline void opamp_mode_set(OPAMP_Type *opamp, uint8_t mode) * * @param opamp @ref OPAMP_Type * @param preset_chn preset channel - * @param mode @ref OPAMP_MODE_XX + * @param mode OPAMP_MODE_XX */ static inline void opamp_preset_mode_set(OPAMP_Type *opamp, uint8_t preset_chn, uint8_t mode) { diff --git a/drivers/inc/hpm_pdgo_drv.h b/drivers/inc/hpm_pdgo_drv.h index 40e6cdfb1..d36edc9dc 100644 --- a/drivers/inc/hpm_pdgo_drv.h +++ b/drivers/inc/hpm_pdgo_drv.h @@ -182,7 +182,7 @@ static inline void pdgo_disable_pulldown_resistor_for_wakeup_pin(PDGO_Type *ptr) /** * @brief Set DGO wakeup counter * @param [in] ptr DGO base address - * @param [in] counter Wakeup counter value. clock source is 32K + * @param [in] wakeup_ctr Wakeup counter value. clock source is 32K */ static inline void pdgo_set_wakeup_counter(PDGO_Type *ptr, uint32_t wakeup_ctr) { @@ -282,4 +282,4 @@ static inline uint32_t pdgo_get_us_from_turnoff_counter(uint32_t counter) #endif -#endif /* HPM_DGO_DRV_H */ \ No newline at end of file +#endif /* HPM_DGO_DRV_H */ diff --git a/drivers/inc/hpm_pdma_drv.h b/drivers/inc/hpm_pdma_drv.h index c7ab9729a..8917a2694 100644 --- a/drivers/inc/hpm_pdma_drv.h +++ b/drivers/inc/hpm_pdma_drv.h @@ -150,6 +150,21 @@ typedef struct pdma_plane_info { display_pixel_format_t format; /**< pixel format */ } pdma_plane_info_t; + +typedef struct pdma_blit_option { + display_alphablend_mode_t blend; + struct { + uint16_t x; + uint16_t y; + } translate; + pdma_flip_t flip; + pdma_rotate_t rotate; + struct { + float x; /* 0.0625 - 4095 */ + float y; /* 0.0625 - 4095 */ + } scale; +} pdma_blit_option_t; + #ifdef __cplusplus extern "C" { #endif @@ -344,6 +359,29 @@ hpm_stat_t pdma_scale(PDMA_Type *ptr, uint8_t alpha, display_pixel_format_t format, bool wait, uint32_t *status); +/** + * @brief PDMA get default blit option + * + * @param op option of blit + */ +void pdma_get_default_blit_option(pdma_blit_option_t *op); + +/** + * @brief PDMA blit plane by option + * + * @param ptr PDMA base address + * @param dst target buff address + * @param src source buff address + * @param op option of blit + * @param wait wait for execution to complete + * @param status pdma status + * @retval hpm_stat_t: status_success if flip and rotate plane without any error + */ +hpm_stat_t pdma_blit_ex(PDMA_Type *ptr, + display_buf_t *dst, + display_buf_t *src, + pdma_blit_option_t *op, + bool wait, uint32_t *status); /** * @brief PDMA set block size diff --git a/drivers/inc/hpm_pla_drv.h b/drivers/inc/hpm_pla_drv.h index f3be449bf..33f7f814d 100644 --- a/drivers/inc/hpm_pla_drv.h +++ b/drivers/inc/hpm_pla_drv.h @@ -275,7 +275,7 @@ extern "C" { * @brief Configure one channel of aoi_16to8 * * @param pla @ref PLA_Type - * @param cfg @ref pla_aoi_16to8_cfg_t + * @param cfg @ref pla_aoi_16to8_chn_cfg_t */ void pla_set_aoi_16to8_one_channel(PLA_Type * pla, pla_aoi_16to8_chn_cfg_t *cfg); @@ -353,7 +353,7 @@ void pla_get_aoi_8to7_one_channel(PLA_Type *pla, * * @param pla @ref PLA_Type * @param chn @ref pla_channel_type_t - * @param aoi_16to8_chn @ref pla_aoi_8to7_channel_type_t + * @param aoi_8to7_chn @ref pla_aoi_8to7_channel_type_t * @param cfg @ref pla_aoi_8to7_cfg_unit_t */ void pla_set_aoi_8to7_input_signal(PLA_Type *pla, diff --git a/drivers/inc/hpm_plb_drv.h b/drivers/inc/hpm_plb_drv.h index 421418bfe..e85fc2821 100644 --- a/drivers/inc/hpm_plb_drv.h +++ b/drivers/inc/hpm_plb_drv.h @@ -13,11 +13,17 @@ /** * @brief PLB driver APIs - * @defgroup pla_interface PLB driver APIs + * @defgroup plb_interface PLB driver APIs * @ingroup io_interfaces * @{ */ +#define PLB_SLICE_MASK (0xf) +#define PLB_SLICE_HIGH_BIT_MASK_SET(slice) (PLB_SLICE_MASK << ((slice - plb_type_b_slice_8) << 2)) +#define PLB_SLICE_HIGH_BIT_SHIFT(slice) ((slice - plb_type_b_slice_8) << 2) +#define PLB_SLICE_LOW_BIT_MASK_SET(slice) (PLB_SLICE_MASK << (slice << 2)) +#define PLB_SLICE_LOW_BIT_SHIFT(slice) (slice << 2) + /** * @brief plb channels * diff --git a/drivers/inc/hpm_qeiv2_drv.h b/drivers/inc/hpm_qeiv2_drv.h index 681a75e13..36cca85e4 100644 --- a/drivers/inc/hpm_qeiv2_drv.h +++ b/drivers/inc/hpm_qeiv2_drv.h @@ -349,7 +349,7 @@ static inline void qeiv2_release_counter(QEIV2_Type *qeiv2_x) * @brief select spd and tmr register content * * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) - * @param[in] mode @ref qeiv2_spd_tmr_content_select_t + * @param[in] content @ref qeiv2_spd_tmr_content_t */ static inline void qeiv2_select_spd_tmr_register_content(QEIV2_Type *qeiv2_x, qeiv2_spd_tmr_content_t content) { @@ -889,23 +889,6 @@ static inline void qeiv2_set_cmp2_match_option(QEIV2_Type *qeiv2_x, bool ignore_ | QEIV2_MATCH_CFG_POS_MATCH2_OPT_SET(!ignore_pos_dir) | QEIV2_MATCH_CFG_POS_MATCH2_DIR_SET(pos_dir); } -/** - * @brief config signal filter - * - * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) - * @param[in] idx filter index - * @arg @ref qeiv2_filter_phase_t - * @param[in] outinv Filter will invert the output - * @param[in] mode qeiv2_filter_mode_t - * @param[in] sync set to enable sychronization input signal with TRGM clock - * @param[in] filtlen defines the filter counter length. - */ -static inline void qeiv2_config_filter(QEIV2_Type *qeiv2_x, qeiv2_filter_phase_t phase, bool outinv, qeiv2_filter_mode_t mode, bool sync, uint16_t filtlen) -{ - qeiv2_x->FILT_CFG[phase] = - QEIV2_FILT_CFG_OUTINV_SET(outinv) | QEIV2_FILT_CFG_MODE_SET(mode) | QEIV2_FILT_CFG_SYNCEN_SET(sync) | QEIV2_FILT_CFG_FILTLEN_SET(filtlen); -} - /** * @brief config signal enablement and edge * @@ -1120,6 +1103,7 @@ static inline void qeiv2_clear_counter_when_dir_chg(QEIV2_Type *qeiv2_x, bool en * * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) * @param[in] config qeiv2_adc_config_t + * @param[in] enable enable or disable adcx */ static inline void qeiv2_config_adcx(QEIV2_Type *qeiv2_x, qeiv2_adc_config_t *config, bool enable) { @@ -1140,6 +1124,7 @@ static inline void qeiv2_config_adcx(QEIV2_Type *qeiv2_x, qeiv2_adc_config_t *co * * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) * @param[in] config qeiv2_adc_config_t + * @param[in] enable enable or disable adcy */ static inline void qeiv2_config_adcy(QEIV2_Type *qeiv2_x, qeiv2_adc_config_t *config, bool enable) { @@ -1281,7 +1266,7 @@ static inline uint32_t qeiv2_get_phase_cnt(QEIV2_Type *qeiv2_x) * * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) * @param[in] inc set to add value to phase_cnt - * @param[in] inc set to minus value to phase_cnt (set inc and dec same time willl act inc) + * @param[in] dec set to minus value to phase_cnt (set inc and dec same time willl act inc) * @param[in] value value to be added or minus from phase_cnt. only valid when inc or dec is set in one 32bit write operation. */ static inline void qeiv2_update_phase_cnt(QEIV2_Type *qeiv2_x, bool inc, bool dec, uint32_t value) @@ -1316,7 +1301,7 @@ static inline uint32_t qeiv2_get_postion(QEIV2_Type *qeiv2_x) * * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) * @param[in] inc set to add value to position - * @param[in] inc set to minus cnt value to position (set inc and dec same time willl act inc) + * @param[in] dec set to minus cnt value to position (set inc and dec same time willl act inc) * @param[in] value value to be added or minus from position. only valid when inc or dec is set in one 32bit write operation. */ static inline void qeiv2_update_position(QEIV2_Type *qeiv2_x, bool inc, bool dec, uint32_t value) @@ -1417,6 +1402,19 @@ void qeiv2_get_uvw_position_defconfig(qeiv2_uvw_config_t *config); */ hpm_stat_t qeiv2_config_uvw_position(QEIV2_Type *qeiv2_x, qeiv2_uvw_config_t *config); +/** + * @brief config signal filter + * + * @param[in] qeiv2_x QEIV2 base address, HPM_QEIV2x(x=0...n) + * @param[in] phase filter phase + * @arg @ref qeiv2_filter_phase_t + * @param[in] outinv Filter will invert the output + * @param[in] mode qeiv2_filter_mode_t + * @param[in] sync set to enable sychronization input signal with TRGM clock + * @param[in] filtlen defines the filter counter length. + */ +void qeiv2_config_filter(QEIV2_Type *qeiv2_x, qeiv2_filter_phase_t phase, bool outinv, qeiv2_filter_mode_t mode, bool sync, uint32_t filtlen); + #ifdef __cplusplus } #endif diff --git a/drivers/inc/hpm_qeo_drv.h b/drivers/inc/hpm_qeo_drv.h index 23ed2a21c..e6f98b4df 100644 --- a/drivers/inc/hpm_qeo_drv.h +++ b/drivers/inc/hpm_qeo_drv.h @@ -13,7 +13,7 @@ /** * @brief QEO driver APIs * @defgroup qeo_interface QEO driver APIs - * @ingroup qeo_interface + * @ingroup qeo_interfaces * @{ */ @@ -182,7 +182,7 @@ static inline void qeo_wave_enable_vd_vq_inject(QEO_Type *base, uint8_t index, i { (void) vd_val; assert(index < 3); - base->WAVE.MODE |= (1U << (QEO_WAVE_MODE_EN_WAVE0_VD_VQ_INJECT_MASK + index)); + base->WAVE.MODE |= (1U << (QEO_WAVE_MODE_EN_WAVE0_VD_VQ_INJECT_SHIFT + index)); base->WAVE.VD_VQ_INJECT[index] = QEO_WAVE_VD_VQ_INJECT_VQ_VAL_SET(vq_val) | QEO_WAVE_VD_VQ_INJECT_VD_VAL_SET(vq_val); } @@ -194,7 +194,7 @@ static inline void qeo_wave_enable_vd_vq_inject(QEO_Type *base, uint8_t index, i static inline void qeo_wave_disable_vd_vq_inject(QEO_Type *base, uint8_t index) { assert(index < 3); - base->WAVE.MODE &= ~(1U << (QEO_WAVE_MODE_EN_WAVE0_VD_VQ_INJECT_MASK + index)); + base->WAVE.MODE &= ~(1U << (QEO_WAVE_MODE_EN_WAVE0_VD_VQ_INJECT_SHIFT + index)); } /** @@ -508,6 +508,7 @@ void qeo_pwm_config_safety_table(QEO_Type *base, qeo_pwm_safety_output_table_t * /** * @brief QEO PWM onfig phase table * @param [in] base QEO base address + * @param [in] index phase table index * @param [in] table qeo_pwm_phase_output_table_t */ void qeo_pwm_config_phase_table(QEO_Type *base, uint8_t index, qeo_pwm_phase_output_table_t *table); @@ -524,7 +525,7 @@ static inline void qeo_enable_software_position_inject(QEO_Type *base) /** * @brief QEO software inject position * @param [in] base QEO base address - * @param [in] base position value + * @param [in] position position value */ static inline void qeo_software_position_inject(QEO_Type *base, uint32_t position) { diff --git a/drivers/inc/hpm_rdc_drv.h b/drivers/inc/hpm_rdc_drv.h index 1abbb55df..cc118e642 100644 --- a/drivers/inc/hpm_rdc_drv.h +++ b/drivers/inc/hpm_rdc_drv.h @@ -691,7 +691,7 @@ static inline void rdc_interrupt_clear_flag_bits(RDC_Type *ptr, uint32_t mask) * @brief Get the interrupt status object * * @param ptr @ref RDC_Type base - * @retval @ref rdc_interrupt_stat_t + * @return @ref rdc_interrupt_stat_t */ static inline uint32_t get_interrupt_status(RDC_Type *ptr) { diff --git a/drivers/inc/hpm_sdm_drv.h b/drivers/inc/hpm_sdm_drv.h index a31dfc564..3c5f54b92 100644 --- a/drivers/inc/hpm_sdm_drv.h +++ b/drivers/inc/hpm_sdm_drv.h @@ -11,6 +11,13 @@ #include "hpm_common.h" #include "hpm_sdm_regs.h" +/** + * @brief SDM APIs + * @defgroup sdm_interface SDM driver APIs + * @ingroup sdm_interfaces + * @{ + */ + /* defined channel mask macro */ #define SAMPLING_MODE_MASK (0x7U) #define CHN_SAMPLING_MODE_SHIFT(ch) ((ch) * 3U + SDM_CTRL_CHMD_SHIFT) diff --git a/drivers/inc/hpm_sdxc_drv.h b/drivers/inc/hpm_sdxc_drv.h index 0287b48b0..e4b4bd89a 100644 --- a/drivers/inc/hpm_sdxc_drv.h +++ b/drivers/inc/hpm_sdxc_drv.h @@ -23,7 +23,7 @@ /** * @brief Generic Definitions - * @Note: + * @note: * If the Host support 1.8V, it means: * 1. For SD card, it supports: * - SDR12 @@ -1045,7 +1045,7 @@ hpm_stat_t sdxc_send_command(SDXC_Type *base, sdxc_command_t *cmd); /** * @brief Receive command response * @param [in] base SDXC base address - * @param [in/out] cmd Command + * @param [in,out] cmd Command * @return status_success if no error happened */ hpm_stat_t sdxc_receive_cmd_response(SDXC_Type *base, sdxc_command_t *cmd); @@ -1127,7 +1127,7 @@ void sdxc_init(SDXC_Type *base, const sdxc_config_t *config); * @brief Set the Data Timeout Counter value for an SD/eMMC device * @param [in] base SDXC base address * @param [in] timeout_in_ms Required timeout value in milliseconds, maximum value is 131,072ms - * @param [out] actual_timeout_us Actual timeout in milliseconds, reported by this API + * @param [out] actual_timeout_ms Actual timeout in milliseconds, reported by this API */ void sdxc_set_data_timeout(SDXC_Type *base, uint32_t timeout_in_ms, uint32_t *actual_timeout_ms); diff --git a/drivers/inc/hpm_sei_drv.h b/drivers/inc/hpm_sei_drv.h index 8eb323d2b..fe1fffd93 100644 --- a/drivers/inc/hpm_sei_drv.h +++ b/drivers/inc/hpm_sei_drv.h @@ -453,7 +453,6 @@ static inline void sei_set_trig_input_period_enable(SEI_Type *ptr, uint8_t idx, * @brief Set the SEI trigger input soft enable or disable * @param [in] ptr SEI base address * @param [in] idx SEI ctrl index, such as SEI_CTRL_0, SEI_CTRL_1, etc. - * @param [in] enable enable or disable * @arg true enable * @arg false disable */ diff --git a/drivers/inc/hpm_smix_drv.h b/drivers/inc/hpm_smix_drv.h index 0b0b367e6..bf8255ccd 100644 --- a/drivers/inc/hpm_smix_drv.h +++ b/drivers/inc/hpm_smix_drv.h @@ -16,7 +16,7 @@ /** * @brief SMIX driver APIs * @defgroup smix_interface SMIX driver APIs - * @ingroup smix_interface + * @ingroup smix_interfaces * @{ */ @@ -499,17 +499,17 @@ hpm_stat_t smix_mixer_config_source_ch(SMIX_Type *ptr, uint8_t ch, smix_mixer_so * * @param [in] ptr SMIX base address * @param [in] ch dst channel - * @param [in] src smix_mixer_dst_config_t + * @param [in] dst smix_mixer_dst_config_t * @retval status_success if no error occurs */ hpm_stat_t smix_mixer_config_dst_ch(SMIX_Type *ptr, uint8_t ch, smix_mixer_dst_config_t *dst); -/** - * @} - */ - #ifdef __cplusplus } #endif +/** + * @} + */ + #endif /* HPM_SMIX_DRV_H */ diff --git a/drivers/inc/hpm_spi_drv.h b/drivers/inc/hpm_spi_drv.h index 1438a18eb..13709be60 100644 --- a/drivers/inc/hpm_spi_drv.h +++ b/drivers/inc/hpm_spi_drv.h @@ -216,7 +216,7 @@ typedef struct { uint8_t trans_mode; uint8_t data_phase_fmt; uint8_t dummy_cnt; -#if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1) +#if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1) uint8_t cs_index; #endif } spi_common_control_config_t; /*!< value in spi_cs_index_t */ @@ -230,7 +230,7 @@ typedef struct { spi_common_control_config_t common_config; } spi_control_config_t; -#if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1) +#if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1) typedef enum { spi_cs_0 = 1, spi_cs_1 = 2, @@ -246,7 +246,7 @@ typedef enum { addrlen_32bit } spi_address_len_t; -#if defined(SPI_SOC_SUPPORT_DIRECTIO) && (SPI_SOC_SUPPORT_DIRECTIO == 1) +#if defined(HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO) && (HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO == 1) typedef enum { hold_pin = 0, wp_pin, @@ -646,7 +646,7 @@ static inline void spi_disable_rx_dma(SPI_Type *ptr) */ static inline uint32_t spi_slave_get_sent_data_count(SPI_Type *ptr) { -#if defined(SPI_SOC_HAS_NEW_TRANS_COUNT) && (SPI_SOC_HAS_NEW_TRANS_COUNT == 1) +#if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1) return ptr->SLVDATAWCNT; #else return SPI_SLVDATACNT_WCNT_GET(ptr->SLVDATACNT); @@ -661,7 +661,7 @@ static inline uint32_t spi_slave_get_sent_data_count(SPI_Type *ptr) */ static inline uint32_t spi_slave_get_received_data_count(SPI_Type *ptr) { -#if defined(SPI_SOC_HAS_NEW_TRANS_COUNT) && (SPI_SOC_HAS_NEW_TRANS_COUNT == 1) +#if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1) return ptr->SLVDATARCNT; #else return SPI_SLVDATACNT_RCNT_GET(ptr->SLVDATACNT); @@ -716,7 +716,7 @@ static inline spi_sclk_idle_state_t spi_get_clock_polarity(SPI_Type *ptr) * @brief set spi the length of each data unit in bits * * @param [in] ptr SPI base address - * @param [in] nbit the actual bits number of a data + * @param [in] nbits the actual bits number of a data * @retval hpm_stat_t status_success if spi transfer without any error */ static inline hpm_stat_t spi_set_data_bits(SPI_Type *ptr, uint8_t nbits) @@ -790,7 +790,7 @@ static inline void spi_disable_data_merge(SPI_Type *ptr) ptr->TRANSFMT &= ~SPI_TRANSFMT_DATAMERGE_MASK; } -#if defined(SPI_SOC_SUPPORT_DIRECTIO) && (SPI_SOC_SUPPORT_DIRECTIO == 1) +#if defined(HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO) && (HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO == 1) /** * @brief enable specific pin output for spi directio * diff --git a/drivers/inc/hpm_tamp_drv.h b/drivers/inc/hpm_tamp_drv.h new file mode 100644 index 000000000..2dbc0d441 --- /dev/null +++ b/drivers/inc/hpm_tamp_drv.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef HPM_TAMP_DRV_H +#define HPM_TAMP_DRV_H + +#include "hpm_common.h" +#include "hpm_tamp_regs.h" + +/** + * + * @brief TAMPER driver APIs + * @defgroup tamper_interface TAMPER driver APIs + * @ingroup io_interfaces + * @{ + */ + +typedef enum { + spd_1_time_per_sec = 0, + spd_2_times_per_sec, + spd_4_times_per_sec, + spd_8_times_per_sec, + spd_16_times_per_sec, + spd_32_times_per_sec, + spd_64_times_per_sec, + spd_128_times_per_sec, + spd_256_times_per_sec, + spd_512_times_per_sec, + spd_1024_times_per_sec, + spd_2048_times_per_sec, + spd_4096_times_per_sec, + spd_8192_times_per_sec, + spd_16384_times_per_sec, + spd_32768_times_per_sec, +} tamper_speed_t; + +typedef enum { + filter_len_1_cycle = 0, + filter_len_2_cycles, + filter_len_4_cycles, + filter_len_8_cycles, + filter_len_16_cycles, + filter_len_32_cycles, + filter_len_64_cycles, + filter_len_128_cycles, + filter_len_256_cycles, + filter_len_512_cycles, + filter_len_1024_cycles, + filter_len_2048_cycles, + filter_len_4096_cycles, + filter_len_8192_cycles, + filter_len_16384_cycles, + filter_len_32768_cycles, +} tamper_filter_len_t; + + typedef struct { + bool enable; + bool active_mode; + bool filter_bypass; + bool expect_high_level; + tamper_speed_t speed; + tamper_filter_len_t filter_len; + bool auto_recover; /* used in active mode */ + uint32_t poly; /* used in active mode */ + uint32_t lfsr; /* used in active mode */ +} tamper_ch_config_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Init tamper channel config + * + * @param[in] ptr tamper base address + * @param[in] ch tamper channel + * @param[in] config tamper channel config struct pointer + * + */ +void tamp_init_ch_config(TAMP_Type *ptr, uint8_t ch, tamper_ch_config_t *config); + +/** + * @brief Get tamper default channel config + * + * @param[in] ptr tamper base address + * @param[in] config tamper default channel config struct pointer + * + */ +void tamp_get_default_ch_config(TAMP_Type *ptr, tamper_ch_config_t *config); + +/** + * @brief Set tamper channel enable or disable + * + * @param[in] ptr tamper base address + * @param[in] ch tamper channel + * @param[in] enable true - enable tamper, false - disable tamper + * + */ +static inline void tamp_set_ch_enable(TAMP_Type *ptr, uint8_t ch, bool enable) +{ + ch >>= 1u; + if (enable) { + ptr->TAMP[ch].CONTROL |= TAMP_TAMP_CONTROL_ENABLE_MASK; + } else { + ptr->TAMP[ch].CONTROL &= ~TAMP_TAMP_CONTROL_ENABLE_MASK; + } +} + +/** + * @brief Set tamper channel config lock or unlock + * + * @param[in] ptr tamper base address + * @param[in] ch tamper channel + * @param[in] lock true - config lock, false - config unlock + * + */ +static inline void tamp_set_ch_config_lock(TAMP_Type *ptr, uint8_t ch, bool lock) +{ + ch >>= 1u; + if (lock) { + ptr->TAMP[ch].CONTROL |= TAMP_TAMP_CONTROL_LOCK_MASK; + } else { + ptr->TAMP[ch].CONTROL &= ~TAMP_TAMP_CONTROL_LOCK_MASK; + } +} + +/** + * @brief Get tamper all channel flags + * + * @param[in] ptr tamper base address + * + * @return all channel flags + */ +static inline uint32_t tamp_get_flags(TAMP_Type *ptr) +{ + return TAMP_TAMP_FLAG_FLAG_GET(ptr->TAMP_FLAG); +} + +/** + * @brief Clear tamper flags + * + * @param[in] ptr tamper base address + * @param[in] flags clear channel flags + * + */ +static inline void tamp_clear_flags(TAMP_Type *ptr, uint32_t flags) +{ + ptr->TAMP_FLAG = TAMP_TAMP_FLAG_FLAG_SET(flags); +} + +/** + * @brief Check tamper channel flag + * + * @param[in] ptr TAMPER base address + * @param[in] ch tamper channel + * + * @return true - flag is set, false - falg is unset. + */ +static inline bool tamp_check_ch_flag(TAMP_Type *ptr, uint8_t ch) +{ + return ((TAMP_TAMP_FLAG_FLAG_GET(ptr->TAMP_FLAG) & (1u << ch)) != 0u) ? true : false; +} + +/** + * @brief Clear tamper channel flag + * + * @param[in] ptr TAMPER base address + * @param[in] ch tamper channel + * + */ +static inline void tamp_clear_ch_flag(TAMP_Type *ptr, uint8_t ch) +{ + ptr->TAMP_FLAG = TAMP_TAMP_FLAG_FLAG_SET(1u << ch); +} + +/** + * @brief Set tamper channel irq enable or disable + * + * @param[in] ptr TAMPER base address + * @param[in] ch tamper channel + * @param[in] enable true - irq enable, false - irq disable + * + */ +static inline void tamp_enable_ch_irq(TAMP_Type *ptr, uint8_t ch, bool enable) +{ + if (enable) { + ptr->IRQ_EN |= TAMP_IRQ_EN_IRQ_EN_SET(1u << ch); + } else { + ptr->IRQ_EN &= ~TAMP_IRQ_EN_IRQ_EN_SET(1u << ch); + } +} + +/** + * @brief Set tamper irq lock or unlock + * + * @param[in] ptr tamper base address + * @param[in] lock true - irq lock, false - irq unlock + * + */ +static inline void tamp_set_irq_lock(TAMP_Type *ptr, bool lock) +{ + if (lock) { + ptr->IRQ_EN |= TAMP_IRQ_EN_LOCK_MASK; + } else { + ptr->IRQ_EN &= ~TAMP_IRQ_EN_LOCK_MASK; + } +} + +#ifdef __cplusplus +} +#endif +/** + * @} + */ +#endif /* HPM_TAMP_DRV_H */ + diff --git a/drivers/inc/hpm_trgm_drv.h b/drivers/inc/hpm_trgm_drv.h index 8c86f9cd2..8561ccb4d 100644 --- a/drivers/inc/hpm_trgm_drv.h +++ b/drivers/inc/hpm_trgm_drv.h @@ -123,7 +123,7 @@ static inline void trgm_input_filter_set_filter_length(TRGM_Type *ptr, uint8_t i * * @param[in] ptr TRGM base address * @param[in] input Input selection - * @param[in] length Filter length in TRGM clock cycles (0 ~ 0xFFF) + * @param[in] shift Filter length shift */ static inline void trgm_input_filter_set_filter_shift(TRGM_Type *ptr, uint8_t input, uint8_t shift) { diff --git a/drivers/inc/hpm_uart_drv.h b/drivers/inc/hpm_uart_drv.h index 3adc8e5bf..fe7ee944a 100644 --- a/drivers/inc/hpm_uart_drv.h +++ b/drivers/inc/hpm_uart_drv.h @@ -52,7 +52,7 @@ typedef enum word_length { /* @brief UART fifo trigger levels */ typedef enum uart_fifo_trg_lvl { -#if defined(UART_SOC_HAS_FINE_FIFO_THR) && (UART_SOC_HAS_FINE_FIFO_THR == 1) +#if defined(HPM_IP_FEATURE_UART_FINE_FIFO_THRLD) && (HPM_IP_FEATURE_UART_FINE_FIFO_THRLD == 1) uart_fifo_1_byte = 0, uart_fifo_2_bytes = 1, uart_fifo_3_bytes = 2, @@ -115,13 +115,13 @@ typedef enum uart_intr_enable { uart_intr_tx_slot_avail = UART_IER_ETHEI_MASK, uart_intr_rx_line_stat = UART_IER_ELSI_MASK, uart_intr_modem_stat = UART_IER_EMSI_MASK, -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) uart_intr_rx_line_idle = UART_IER_ERXIDLE_MASK, #endif -#if defined(UART_SOC_HAS_TXLINE_IDLE_DETECTION) && (UART_SOC_HAS_TXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_9BIT_MODE) && (HPM_IP_FEATURE_UART_9BIT_MODE == 1) uart_intr_tx_line_idle = UART_IER_ETXIDLE_MASK, #endif -#if defined(UART_SOC_HAS_ADDR_MATCH) && (UART_SOC_HAS_ADDR_MATCH == 1) +#if defined(HPM_IP_FEATURE_UART_ADDR_MATCH) && (HPM_IP_FEATURE_UART_ADDR_MATCH == 1) uart_intr_addr_match = UART_IER_EADDRM_MASK, uart_intr_addr_match_and_rxidle = UART_IER_EADDRM_IDLE_MASK, uart_intr_addr_datalost = UART_IER_EDATLOST_MASK, @@ -158,7 +158,7 @@ typedef struct uart_modem_config { bool set_rts_high; /**< Set signal RTS level high flag */ } uart_modem_config_t; -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) /** * @brief UART Idle detection conditions, suitable for RX and TX */ @@ -192,18 +192,18 @@ typedef struct hpm_uart_config { bool dma_enable; /**< DMA Enable flag */ bool fifo_enable; /**< Fifo Enable flag */ uart_modem_config_t modem_config; /**< Modem config */ -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) uart_rxline_idle_config_t rxidle_config; /**< RX Idle configuration */ #endif -#if defined(UART_SOC_HAS_TXLINE_IDLE_DETECTION) && (UART_SOC_HAS_TXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_9BIT_MODE) && (HPM_IP_FEATURE_UART_9BIT_MODE == 1) uart_rxline_idle_config_t txidle_config; /**< TX Idle configuration */ #endif -#if defined(UART_SOC_HAS_RXEN_CFG) && (UART_SOC_HAS_RXEN_CFG == 1) +#if defined(HPM_IP_FEATURE_UART_RX_EN) && (HPM_IP_FEATURE_UART_RX_EN == 1) bool rx_enable; /**< RX Enable configuration */ #endif } uart_config_t; -#if defined(UART_SOC_HAS_TRIG_MODE) && (UART_SOC_HAS_TRIG_MODE == 1) +#if defined(HPM_IP_FEATURE_UART_TRIG_MODE) && (HPM_IP_FEATURE_UART_TRIG_MODE == 1) typedef struct { uint16_t stop_bit_len; bool en_stop_bit_insert; @@ -269,7 +269,7 @@ static inline void uart_clear_rx_fifo(UART_Type *ptr) */ static inline void uart_reset_tx_fifo(UART_Type *ptr) { -#if defined(UART_SOC_HAS_FCCR_REG) && (UART_SOC_HAS_FCCR_REG == 1) +#if defined(HPM_IP_FEATURE_UART_FCRR) && (HPM_IP_FEATURE_UART_FCRR == 1) ptr->FCRR |= UART_FCRR_TFIFORST_MASK; #else ptr->FCR = UART_FCR_TFIFORST_MASK | (ptr->GPR); @@ -283,7 +283,7 @@ static inline void uart_reset_tx_fifo(UART_Type *ptr) */ static inline void uart_reset_rx_fifo(UART_Type *ptr) { -#if defined(UART_SOC_HAS_FCCR_REG) && (UART_SOC_HAS_FCCR_REG == 1) +#if defined(HPM_IP_FEATURE_UART_FCRR) && (HPM_IP_FEATURE_UART_FCRR == 1) ptr->FCRR |= UART_FCRR_RFIFORST_MASK; #else ptr->FCR = UART_FCR_RFIFORST_MASK | (ptr->GPR); @@ -297,7 +297,7 @@ static inline void uart_reset_rx_fifo(UART_Type *ptr) */ static inline void uart_reset_all_fifo(UART_Type *ptr) { -#if defined(UART_SOC_HAS_FCCR_REG) && (UART_SOC_HAS_FCCR_REG == 1) +#if defined(HPM_IP_FEATURE_UART_FCRR) && (HPM_IP_FEATURE_UART_FCRR == 1) ptr->FCRR |= UART_FCRR_TFIFORST_MASK | UART_FCRR_RFIFORST_MASK; #else ptr->FCR = UART_FCR_RFIFORST_MASK | UART_FCR_TFIFORST_MASK | (ptr->GPR); @@ -449,10 +449,10 @@ static inline uint8_t uart_get_irq_id(UART_Type *ptr) return (ptr->IIR & UART_IIR_INTRID_MASK); } -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) -/* if UART_SOC_HAS_IIR2_REG = 1, the IIR2 register exists, should use IIR2 to get/clear rx idle status */ -#if !defined(UART_SOC_HAS_IIR2_REG) || (UART_SOC_HAS_IIR2_REG == 0) +/* if HPM_IP_FEATURE_UART_E00018_FIX = 1, the IIR2 register exists, should use IIR2 to get/clear rx idle status */ +#if !defined(HPM_IP_FEATURE_UART_E00018_FIX) || (HPM_IP_FEATURE_UART_E00018_FIX == 0) /** * @brief Determine whether UART RX Line is idle * @param [in] ptr UART base address @@ -502,7 +502,7 @@ hpm_stat_t uart_init_rxline_idle_detection(UART_Type *ptr, uart_rxline_idle_conf #endif -#if defined(UART_SOC_HAS_IIR2_REG) && (UART_SOC_HAS_IIR2_REG == 1) +#if defined(HPM_IP_FEATURE_UART_E00018_FIX) && (HPM_IP_FEATURE_UART_E00018_FIX == 1) /** * @brief Determine whether UART TX Line is idle * @param [in] ptr UART base address @@ -540,7 +540,7 @@ static inline void uart_clear_rxline_idle_flag(UART_Type *ptr) } #endif -#if defined(UART_SOC_HAS_TXLINE_IDLE_DETECTION) && (UART_SOC_HAS_TXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_9BIT_MODE) && (HPM_IP_FEATURE_UART_9BIT_MODE == 1) /** * @brief Enable UART TX Idle Line detection logic * @param [in] ptr UART base address @@ -586,6 +586,7 @@ static inline uint8_t uart_get_status(UART_Type *ptr) /** * @brief Check uart status according to the given status mask * + * @note maybe clear other bits, such as PE/OE/LBREAK/ERRF bit. use uart_get_status API if you need to get these bits * @param [in] ptr UART base address * @param mask Status mask value to be checked against * @retval true if any bit in given mask is set @@ -685,14 +686,14 @@ hpm_stat_t uart_send_data(UART_Type *ptr, uint8_t *buf, uint32_t size_in_byte); hpm_stat_t uart_set_baudrate(UART_Type *ptr, uint32_t baudrate, uint32_t src_clock_hz); -#if defined(UART_SOC_HAS_TRIG_MODE) && (UART_SOC_HAS_TRIG_MODE == 1) +#if defined(HPM_IP_FEATURE_UART_TRIG_MODE) && (HPM_IP_FEATURE_UART_TRIG_MODE == 1) /** * @brief uart configure transfer trigger mode * * This function can configure uart to send data in fifo after being triggered * * @param ptr UART base address - * @param uart_trig_config_t config + * @param config uart_trig_config_t config */ void uart_config_transfer_trig_mode(UART_Type *ptr, uart_trig_config_t *config); @@ -749,7 +750,7 @@ static inline uint8_t uart_get_data_count_in_tx_fifo(UART_Type *ptr) } #endif -#if defined(UART_SOC_HAS_ADDR_MATCH) && (UART_SOC_HAS_ADDR_MATCH == 1) +#if defined(HPM_IP_FEATURE_UART_ADDR_MATCH) && (HPM_IP_FEATURE_UART_ADDR_MATCH == 1) /** * @brief uart enable 9bit transmit mode * diff --git a/drivers/inc/hpm_usb_drv.h b/drivers/inc/hpm_usb_drv.h index ea1b459c9..71692eb4d 100644 --- a/drivers/inc/hpm_usb_drv.h +++ b/drivers/inc/hpm_usb_drv.h @@ -217,6 +217,16 @@ static inline uint8_t usb_get_port_speed(USB_Type *ptr) */ void usb_phy_init(USB_Type *ptr); +/** + * @brief USB phy get line status + * + * @param[in] ptr A USB peripheral base address + */ +static inline uint8_t usb_phy_get_line_state(USB_Type *ptr) +{ + return USB_PHY_STATUS_LINE_STATE_GET(ptr->PHY_STATUS); +} + /** * @brief USB phy using internal vbus * diff --git a/drivers/src/hpm_adc12_drv.c b/drivers/src/hpm_adc12_drv.c index cb5e52460..c433e01d2 100644 --- a/drivers/src/hpm_adc12_drv.c +++ b/drivers/src/hpm_adc12_drv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -39,10 +39,11 @@ static hpm_stat_t adc12_do_calibration(ADC12_Type *ptr, adc12_sample_signal_t di } /*Set diff_sel temporarily */ - ptr->SAMPLE_CFG[0] = ADC12_SAMPLE_CFG_DIFF_SEL_SET(diff_sel); + ptr->SAMPLE_CFG[0] &= ~ADC12_SAMPLE_CFG_DIFF_SEL_MASK; + ptr->SAMPLE_CFG[0] |= ADC12_SAMPLE_CFG_DIFF_SEL_SET(diff_sel); /* Set resetcal and resetadc */ - ptr->ANA_CTRL0 |= ADC12_ANA_CTRL0_RESETCAL_MASK; + ptr->ANA_CTRL0 |= ADC12_ANA_CTRL0_RESETCAL_MASK | ADC12_ANA_CTRL0_RESETADC_MASK; /* Clear resetcal and resetadc */ ptr->ANA_CTRL0 &= ~(ADC12_ANA_CTRL0_RESETCAL_MASK | ADC12_ANA_CTRL0_RESETADC_MASK); @@ -172,6 +173,11 @@ hpm_stat_t adc12_init_channel(ADC12_Type *ptr, adc12_channel_config_t *config) return status_invalid_argument; } + /* Check sample cycle */ + if (ADC12_IS_CHANNEL_SAMPLE_CYCLE_INVALID(config->sample_cycle)) { + return status_invalid_argument; + } + /* Set warning threshold */ ptr->PRD_CFG[config->ch].PRD_THSHD_CFG = ADC12_PRD_CFG_PRD_THSHD_CFG_THSHDH_SET(config->thshdh) | ADC12_PRD_CFG_PRD_THSHD_CFG_THSHDL_SET(config->thshdl); diff --git a/drivers/src/hpm_adc16_drv.c b/drivers/src/hpm_adc16_drv.c index 402178971..b4795c98b 100644 --- a/drivers/src/hpm_adc16_drv.c +++ b/drivers/src/hpm_adc16_drv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -209,6 +209,11 @@ hpm_stat_t adc16_init_channel(ADC16_Type *ptr, adc16_channel_config_t *config) return status_invalid_argument; } + /* Check sample cycle */ + if (ADC16_IS_CHANNEL_SAMPLE_CYCLE_INVALID(config->sample_cycle)) { + return status_invalid_argument; + } + /* Set warning threshold */ ptr->PRD_CFG[config->ch].PRD_THSHD_CFG = ADC16_PRD_CFG_PRD_THSHD_CFG_THSHDH_SET(config->thshdh) | ADC16_PRD_CFG_PRD_THSHD_CFG_THSHDL_SET(config->thshdl); diff --git a/drivers/src/hpm_cam_drv.c b/drivers/src/hpm_cam_drv.c index b49f445cb..f318799b4 100644 --- a/drivers/src/hpm_cam_drv.c +++ b/drivers/src/hpm_cam_drv.c @@ -14,13 +14,14 @@ void cam_get_default_config(CAM_Type *ptr, cam_config_t *config, display_pixel_f (void) ptr; config->width = 320; config->height = 240; + config->buffer1 = -1; + config->buffer2 = -1; config->pixclk_sampling_falling = false; config->hsync_active_low = false; config->vsync_active_low = false; config->de_active_low = false; config->color_ext = false; config->data_pack_msb = false; - config->enable_buffer2 = false; config->data_store_mode = CAM_DATA_STORE_MODE_NORMAL; config->color_format = pixel_format; config->sensor_bitwidth = CAM_SENSOR_BITWIDTH_10BITS; @@ -80,6 +81,10 @@ hpm_stat_t cam_init(CAM_Type *ptr, cam_config_t *config) pixel_format = config->color_format; width = config->width; + if ((int)config->buffer1 < 0) { + return status_invalid_argument; + } + if (pixel_format == CAM_COLOR_FORMAT_RAW8) { if ((width % 2) != 0) { return status_invalid_argument; @@ -115,7 +120,9 @@ hpm_stat_t cam_init(CAM_Type *ptr, cam_config_t *config) ptr->CR2 = CAM_CR2_DMA_REQ_EN_RFF_MASK | CAM_CR2_RXFF_LEVEL_SET(CAM_RX_FIFO_THRESHOLD); ptr->DMASA_FB1 = config->buffer1; - if (config->enable_buffer2) { + if ((int)config->buffer2 < 0) { + ptr->DMASA_FB2 = config->buffer1; + } else { ptr->DMASA_FB2 = config->buffer2; } @@ -132,11 +139,6 @@ hpm_stat_t cam_init(CAM_Type *ptr, cam_config_t *config) return stat; } -void cam_update_buffer(CAM_Type *ptr, uint32_t buffer) -{ - ptr->DMASA_FB1 = buffer; -} - void cam_stop(CAM_Type *ptr) { ptr->CR18 &= ~CAM_CR18_CAM_ENABLE_MASK; diff --git a/drivers/src/hpm_can_drv.c b/drivers/src/hpm_can_drv.c index 520b417ea..284840f43 100644 --- a/drivers/src/hpm_can_drv.c +++ b/drivers/src/hpm_can_drv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2023 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -611,8 +611,8 @@ hpm_stat_t can_get_default_config(can_config_t *config) config->mode = can_mode_normal; config->enable_self_ack = false; - config->disable_re_transmission_for_stb = false; - config->disable_re_transmission_for_ptb = false; + config->disable_stb_retransmission = false; + config->disable_ptb_retransmission = false; config->enable_tx_buffer_priority_mode = false; config->enable_tdc = false; @@ -671,17 +671,6 @@ hpm_stat_t can_init(CAN_Type *base, can_config_t *config, uint32_t src_clk_freq) HPM_BREAK_IF(status != status_success); - if (config->disable_re_transmission_for_ptb) { - base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TPSS_MASK; - } else { - base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TPSS_MASK; - } - - if (config->disable_re_transmission_for_stb) { - base->CMD_STA_CMD_CTRL |= CAN_CMD_STA_CMD_CTRL_TSSS_MASK; - } else { - base->CMD_STA_CMD_CTRL &= ~CAN_CMD_STA_CMD_CTRL_TSSS_MASK; - } /* Configure CAN filters */ if (config->filter_list_num > CAN_FILTER_NUM_MAX) { @@ -710,6 +699,13 @@ hpm_stat_t can_init(CAN_Type *base, can_config_t *config, uint32_t src_clk_freq) can_reset(base, false); + /* The following mode must be set when the CAN controller is not in reset mode */ + + /* Disable re-transmission on PTB on demand */ + can_disable_ptb_retransmission(base, config->disable_ptb_retransmission); + /* Disable re-transmission on STB on demand */ + can_disable_stb_retransmission(base, config->disable_stb_retransmission); + /* Set Self-ack mode*/ can_enable_self_ack(base, config->enable_self_ack); diff --git a/drivers/src/hpm_crc_drv.c b/drivers/src/hpm_crc_drv.c index 862666bc4..f329c1b97 100644 --- a/drivers/src/hpm_crc_drv.c +++ b/drivers/src/hpm_crc_drv.c @@ -23,7 +23,6 @@ void crc_get_default_channel_config(crc_channel_config_t *cfg) hpm_stat_t crc_setup_channel_config(CRC_Type *ptr, uint32_t ch_index, crc_channel_config_t *cfg) { - ptr->CHN[ch_index].CLR |= CRC_CHN_CLR_CLR_MASK; ptr->CHN[ch_index].PRE_SET = cfg->preset; if (!ptr->CHN[ch_index].PRE_SET) { diff --git a/drivers/src/hpm_femc_drv.c b/drivers/src/hpm_femc_drv.c index cd63fc5b3..598968abf 100644 --- a/drivers/src/hpm_femc_drv.c +++ b/drivers/src/hpm_femc_drv.c @@ -18,10 +18,10 @@ #define FEMC_PRESCALER_MAX (256UL) -static void femc_config_delay_cell(FEMC_Type *ptr, uint32_t delay_cell_value) +static void femc_config_delay_cell(FEMC_Type *ptr, bool delay_cell_en, uint32_t delay_cell_value) { ptr->DLYCFG &= ~FEMC_DLYCFG_OE_MASK; - ptr->DLYCFG = FEMC_DLYCFG_DLYSEL_SET(delay_cell_value) | FEMC_DLYCFG_DLYEN_MASK; + ptr->DLYCFG = FEMC_DLYCFG_DLYSEL_SET(delay_cell_value) | FEMC_DLYCFG_DLYEN_SET(delay_cell_en); ptr->DLYCFG |= FEMC_DLYCFG_OE_MASK; } @@ -310,7 +310,7 @@ hpm_stat_t femc_config_sdram(FEMC_Type *ptr, uint32_t clk_in_hz, femc_sdram_conf /* * config delay cell */ - femc_config_delay_cell(ptr, config->delay_cell_value); + femc_config_delay_cell(ptr, !config->delay_cell_disable, config->delay_cell_value); cmd.opcode = FEMC_CMD_SDRAM_PRECHARGE_ALL; cmd.data = 0; diff --git a/drivers/src/hpm_i2c_drv.c b/drivers/src/hpm_i2c_drv.c index e44e5115e..1b77e721b 100644 --- a/drivers/src/hpm_i2c_drv.c +++ b/drivers/src/hpm_i2c_drv.c @@ -992,3 +992,106 @@ hpm_stat_t i2c_master_seq_receive(I2C_Type *ptr, const uint16_t device_address, return status_success; } +hpm_stat_t i2c_master_transfer(I2C_Type *ptr, const uint16_t device_address, + uint8_t *buf, const uint32_t size, uint16_t flags) +{ + uint32_t ctrl = 0; + uint32_t retry = 0; + uint32_t left = 0; + if (((size == 0) || (size > I2C_SOC_TRANSFER_COUNT_MAX))) { + return status_invalid_argument; + } + if (flags & I2C_ADDR_10BIT) { + i2c_enable_10bit_address_mode(ptr, true); + } else { + i2c_enable_10bit_address_mode(ptr, false); + } + /* W1C, clear CMPL bit to avoid blocking the transmission */ + ptr->STATUS = I2C_STATUS_CMPL_MASK; + ptr->CMD = I2C_CMD_CLEAR_FIFO; + ptr->ADDR = I2C_ADDR_ADDR_SET(device_address); + + if (flags & I2C_RD) { + ctrl |= I2C_CTRL_DIR_SET(I2C_DIR_MASTER_READ); + } else { + ctrl |= I2C_CTRL_DIR_SET(I2C_DIR_MASTER_WRITE);/* is write flag */ + } + /* start signal */ + if (flags & I2C_NO_START) { + ctrl |= I2C_CTRL_PHASE_START_SET(false); + } else { + ctrl |= I2C_CTRL_PHASE_START_SET(true); + } + /* end signal*/ + if (flags & I2C_NO_STOP) { + ctrl |= I2C_CTRL_PHASE_STOP_SET(false); + } else { + ctrl |= I2C_CTRL_PHASE_STOP_SET(true); + } + + ptr->CTRL = ctrl | I2C_CTRL_PHASE_DATA_SET(true) \ + | I2C_CTRL_PHASE_ADDR_SET(true) \ + | I2C_CTRL_DATACNT_HIGH_SET(I2C_DATACNT_MAP(size) >> 8U) \ + | I2C_CTRL_DATACNT_SET(I2C_DATACNT_MAP(size)); + /* disable auto ack */ + ptr->INTEN |= I2C_EVENT_BYTE_RECEIVED; + ptr->CMD = I2C_CMD_ISSUE_DATA_TRANSMISSION; + retry = 0; + left = size; + if (flags & I2C_RD) { + while (left) { + if (!(ptr->STATUS & I2C_STATUS_FIFOEMPTY_MASK)) { + *(buf++) = ptr->DATA; + left--; + if (left == 0) { + ptr->CMD = I2C_CMD_NACK; + } else { + /* ACK is sent when reading */ + if (!(flags & I2C_NO_READ_ACK)) { + ptr->CMD = I2C_CMD_ACK; + } + } + retry = 0; + } else { + if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) { + break; + } + retry++; + } + } + if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) { + return status_timeout; + } + } else { + while (left) { + if (!(ptr->STATUS & I2C_STATUS_FIFOFULL_MASK)) { + ptr->DATA = *(buf++); + left--; + retry = 0; + } else { + if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) { + break; + } + retry++; + } + } + if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) { + return status_timeout; + } + } + retry = 0; + while (!(ptr->STATUS & I2C_STATUS_CMPL_MASK)) { + if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) { + break; + } + retry++; + } + if (retry > HPM_I2C_DRV_DEFAULT_RETRY_COUNT) { + return status_timeout; + } + + if (i2c_get_data_count(ptr) && (size)) { + return status_i2c_transmit_not_completed; + } + return status_success; +} diff --git a/drivers/src/hpm_i2s_drv.c b/drivers/src/hpm_i2s_drv.c index e460c13a4..73e93c179 100644 --- a/drivers/src/hpm_i2s_drv.c +++ b/drivers/src/hpm_i2s_drv.c @@ -47,7 +47,7 @@ hpm_stat_t i2s_fill_tx_dummy_data(I2S_Type *ptr, uint8_t data_line, uint8_t data while (i2s_get_tx_line_fifo_level(ptr, data_line) < data_count) { ptr->TXD[data_line] = 0; if (retry > HPM_I2S_DRV_DEFAULT_RETRY_COUNT * data_count) { - return false; + return status_timeout; } retry++; } @@ -55,18 +55,28 @@ hpm_stat_t i2s_fill_tx_dummy_data(I2S_Type *ptr, uint8_t data_line, uint8_t data return status_success; } +/* The I2S software reset function relies on a working BCLK */ void i2s_reset_all(I2S_Type *ptr) { + uint32_t cfgr_temp, misc_cfgr_temp; + /* disable I2S */ ptr->CTRL &= ~I2S_CTRL_I2S_EN_MASK; - /* gate off bclk */ - ptr->CFGR |= I2S_CFGR_BCLK_GATEOFF_MASK; - /* gate off mclk */ - ptr->MISC_CFGR |= I2S_MISC_CFGR_MCLK_GATEOFF_MASK; + + /* enable internal clock for software reset function */ + cfgr_temp = ptr->CFGR; + ptr->CFGR |= I2S_CFGR_BCLK_DIV_SET(1); + ptr->CFGR &= ~(I2S_CFGR_MCK_SEL_OP_MASK | I2S_CFGR_BCLK_SEL_OP_MASK | I2S_CFGR_FCLK_SEL_OP_MASK | I2S_CFGR_BCLK_GATEOFF_MASK); + misc_cfgr_temp = ptr->MISC_CFGR; + ptr->MISC_CFGR &= ~I2S_MISC_CFGR_MCLK_GATEOFF_MASK; /* reset function block and clear fifo */ ptr->CTRL |= (I2S_CTRL_TXFIFOCLR_MASK | I2S_CTRL_RXFIFOCLR_MASK | I2S_CTRL_SFTRST_CLKGEN_MASK | I2S_CTRL_SFTRST_TX_MASK | I2S_CTRL_SFTRST_RX_MASK); ptr->CTRL &= ~(I2S_CTRL_TXFIFOCLR_MASK | I2S_CTRL_RXFIFOCLR_MASK | I2S_CTRL_SFTRST_CLKGEN_MASK | I2S_CTRL_SFTRST_TX_MASK | I2S_CTRL_SFTRST_RX_MASK); + + /* Restore the value of the register */ + ptr->CFGR = cfgr_temp; + ptr->MISC_CFGR = misc_cfgr_temp; } void i2s_get_default_config(I2S_Type *ptr, i2s_config_t *config) @@ -83,7 +93,8 @@ void i2s_get_default_config(I2S_Type *ptr, i2s_config_t *config) config->use_external_fclk = false; config->enable_mclk_out = false; config->frame_start_at_rising_edge = false; - config->fifo_threshold = 4; + config->tx_fifo_threshold = 4; + config->rx_fifo_threshold = 4; } void i2s_init(I2S_Type *ptr, i2s_config_t *config) @@ -104,8 +115,8 @@ void i2s_init(I2S_Type *ptr, i2s_config_t *config) & ~(I2S_MISC_CFGR_MCLKOE_MASK | I2S_MISC_CFGR_MCLK_GATEOFF_MASK)) | I2S_MISC_CFGR_MCLKOE_SET(config->enable_mclk_out); - ptr->FIFO_THRESH = I2S_FIFO_THRESH_TX_SET(config->fifo_threshold) - | I2S_FIFO_THRESH_RX_SET(config->fifo_threshold); + ptr->FIFO_THRESH = I2S_FIFO_THRESH_TX_SET(config->tx_fifo_threshold) + | I2S_FIFO_THRESH_RX_SET(config->rx_fifo_threshold); } static void i2s_config_cfgr(I2S_Type *ptr, diff --git a/drivers/src/hpm_lcdc_drv.c b/drivers/src/hpm_lcdc_drv.c index 9c83365ca..6ce29f861 100644 --- a/drivers/src/hpm_lcdc_drv.c +++ b/drivers/src/hpm_lcdc_drv.c @@ -71,6 +71,7 @@ void lcdc_get_default_layer_config(LCDC_Type *ptr, lcdc_layer_config_t *layer, d layer->alphablend.src_alpha_op = display_alpha_op_invalid; layer->alphablend.dst_alpha_op = display_alpha_op_invalid; layer->alphablend.mode = display_alphablend_mode_clear; + layer->stride = 0; switch (pixel_format) { case display_pixel_format_yuv422: @@ -214,7 +215,7 @@ hpm_stat_t lcdc_config_layer(LCDC_Type *ptr, ptr->LAYER[layer_index].ALPHAS = LCDC_LAYER_ALPHAS_LOCD_SET(layer->alphablend.src_alpha) | LCDC_LAYER_ALPHAS_IND_SET(layer->alphablend.dst_alpha); - pitch = display_get_pitch_length_in_byte(layer->pixel_format, layer->width); + pitch = layer->stride > 0 ? layer->stride : display_get_pitch_length_in_byte(layer->pixel_format, layer->width); ptr->LAYER[layer_index].LINECFG = LCDC_LAYER_LINECFG_MPT_SIZE_SET(layer->max_bytes) | LCDC_LAYER_LINECFG_MAX_OT_SET(layer->max_ot) | LCDC_LAYER_LINECFG_PITCH_SET(pitch); diff --git a/drivers/src/hpm_linv2_drv.c b/drivers/src/hpm_linv2_drv.c index 5c1fba1c0..0129cd4ec 100644 --- a/drivers/src/hpm_linv2_drv.c +++ b/drivers/src/hpm_linv2_drv.c @@ -23,7 +23,7 @@ hpm_stat_t lin_master_configure_timing(LINV2_Type *ptr, lin_timing_t *timing) ptr->TIMING_CONTROL &= ~LINV2_TIMING_CONTROL_LIN_INITIAL_MASK; bt_mul = 20000U / timing->baudrate - 1U; - prescaler = log((timing->src_freq_in_hz / ((bt_mul + 1U) * timing->baudrate * 200U))) / log(2U) - 1U; + prescaler = (uint8_t)(log((timing->src_freq_in_hz / ((bt_mul + 1U) * timing->baudrate * 200U))) / log(2U) - 1U); bt_div = timing->src_freq_in_hz / ((1U << (prescaler + 1U)) * (bt_mul + 1U) * timing->baudrate); if ((bt_div < 200) || (bt_div > 512)) { @@ -51,7 +51,7 @@ hpm_stat_t lin_slave_configure_timing(LINV2_Type *ptr, uint32_t src_freq_in_hz) ptr->TIMING_CONTROL |= LINV2_TIMING_CONTROL_LIN_INITIAL_MASK; ptr->TIMING_CONTROL &= ~LINV2_TIMING_CONTROL_LIN_INITIAL_MASK; - prescaler = log((src_freq_in_hz / (20000U * 200U))) / log(2U) - 1U; + prescaler = (uint8_t)(log((src_freq_in_hz / (20000U * 200U))) / log(2U) - 1U); bt_div = src_freq_in_hz / ((1U << (prescaler + 1U)) * 20000U); if ((bt_div < 200) || (bt_div >= 512)) { diff --git a/drivers/src/hpm_mcan_drv.c b/drivers/src/hpm_mcan_drv.c index 3f160ae3b..a0ca301d2 100644 --- a/drivers/src/hpm_mcan_drv.c +++ b/drivers/src/hpm_mcan_drv.c @@ -644,6 +644,10 @@ void mcan_get_default_config(MCAN_Type *ptr, mcan_config_t *config) tsu_config->use_ext_timebase = false; tsu_config->capture_on_sof = false; tsu_config->enable_tsu = false; + + config->timeout_cfg.enable_timeout_counter = false; + config->timeout_cfg.timeout_period = 0xFFFFU; + config->timeout_cfg.timeout_sel = mcan_timeout_continuous_operation; } static void mcan_config_rxfifo(MCAN_Type *ptr, uint32_t index, uint32_t reg_val) @@ -1176,6 +1180,12 @@ hpm_stat_t mcan_init(MCAN_Type *ptr, mcan_config_t *config, uint32_t src_clk_fre /* Clear all Interrupt Flags */ mcan_clear_interrupt_flags(ptr, ~0UL); + /* Configure timeout */ + const mcan_timeout_config_t *timeout_cfg = &config->timeout_cfg; + ptr->TOCC = MCAN_TOCC_RP_SET(timeout_cfg->enable_timeout_counter) | + MCAN_TOCC_TOP_SET(timeout_cfg->timeout_period) | + MCAN_TOCC_TOS_SET(timeout_cfg->timeout_sel); + ptr->CCCR &= ~MCAN_CCCR_INIT_MASK; while ((ptr->CCCR & MCAN_CCCR_INIT_MASK) != 0U) { } diff --git a/drivers/src/hpm_mipi_dsi_drv.c b/drivers/src/hpm_mipi_dsi_drv.c index 9fd8a5325..3262758cd 100644 --- a/drivers/src/hpm_mipi_dsi_drv.c +++ b/drivers/src/hpm_mipi_dsi_drv.c @@ -21,23 +21,15 @@ (cond) ? true : false; \ }) -/** - * struct mipi_dsi_packet - represents a MIPI DSI packet in protocol format - * @size: size (in bytes) of the packet - * @header: the four bytes that make up the header (Data ID, Word Count or - * Packet Data, and ECC) - * @payload_length: number of bytes in the payload - * @payload: a pointer to a buffer containing the payload, if any - */ typedef struct mipi_dsi_packet { - uint8_t header[4]; - uint16_t payload_length; - const uint8_t *payload; + uint8_t header[4]; /*!< the four bytes that make up the header (Data ID, Word Count or Packet Data, and ECC) */ + uint16_t payload_length; /*!< number of bytes in the payload */ + const uint8_t *payload; /*!< a pointer to a buffer containing the payload, if any */ } mipi_dsi_packet_t; /** * mipi_dsi_packet_format_is_short - check if a packet is of the short format - * @type: MIPI DSI data type of the packet + * @param type: MIPI DSI data type of the packet * * @return: true if the packet for the given data type is a short packet, false * otherwise. @@ -65,7 +57,7 @@ static bool mipi_dsi_packet_format_is_short(uint8_t type) /** * mipi_dsi_packet_format_is_long - check if a packet is of the long format - * @type: MIPI DSI data type of the packet + * @param type: MIPI DSI data type of the packet * * @return: true if the packet for the given data type is a long packet, false * otherwise. @@ -84,8 +76,8 @@ static bool mipi_dsi_packet_format_is_long(uint8_t type) /** * mipi_dsi_create_packet - create a packet from a message according to the * DSI protocol - * @packet: pointer to a DSI packet structure - * @msg: message to translate into a packet + * @param packet: pointer to a DSI packet structure + * @param msg: message to translate into a packet * * @return: true on success or false on failure. */ diff --git a/drivers/src/hpm_opamp_drv.c b/drivers/src/hpm_opamp_drv.c index 0a6cc00ba..4f41e2951 100644 --- a/drivers/src/hpm_opamp_drv.c +++ b/drivers/src/hpm_opamp_drv.c @@ -97,7 +97,7 @@ hpm_stat_t opamp_init(OPAMP_Type *opamp, opamp_cfg_t *cfg) opamp_mode_set(opamp, OPAMP_MODE_NON_INVERT_INDEX4_KEY); break; case mode_user: - return status_success; + opamp_mode_set(opamp, OPAMP_MODE_USER_DEFINE_KEY); break; default: return status_invalid_argument; diff --git a/drivers/src/hpm_pdma_drv.c b/drivers/src/hpm_pdma_drv.c index b61dcee0e..5980406a6 100644 --- a/drivers/src/hpm_pdma_drv.c +++ b/drivers/src/hpm_pdma_drv.c @@ -383,12 +383,12 @@ void pdma_config_output(PDMA_Type *ptr, pdma_output_config_t *config) | PDMA_OUT_LRC_Y_SET(config->height); ptr->OUT_PS[0].ULC = PDMA_OUT_PS_ULC_X_SET(config->plane[0].x) | PDMA_OUT_PS_ULC_Y_SET(config->plane[0].y); - ptr->OUT_PS[0].LRC = PDMA_OUT_PS_LRC_X_SET(config->plane[0].width) - | PDMA_OUT_PS_LRC_Y_SET(config->plane[0].height); + ptr->OUT_PS[0].LRC = PDMA_OUT_PS_LRC_X_SET(config->plane[0].x + config->plane[0].width - 1) + | PDMA_OUT_PS_LRC_Y_SET(config->plane[0].y + config->plane[0].height - 1); ptr->OUT_PS[1].ULC = PDMA_OUT_PS_ULC_X_SET(config->plane[1].x) | PDMA_OUT_PS_ULC_Y_SET(config->plane[1].y); - ptr->OUT_PS[1].LRC = PDMA_OUT_PS_LRC_X_SET(config->plane[1].width) - | PDMA_OUT_PS_LRC_Y_SET(config->plane[1].height); + ptr->OUT_PS[1].LRC = PDMA_OUT_PS_LRC_X_SET(config->plane[1].x + config->plane[1].width - 1) + | PDMA_OUT_PS_LRC_Y_SET(config->plane[1].y + config->plane[1].height - 1); ptr->OUT_CTRL = PDMA_OUT_CTRL_DSTALPHA_SET(config->alphablend.dst_alpha) | PDMA_OUT_CTRL_SRCALPHA_SET(config->alphablend.src_alpha) | PDMA_OUT_CTRL_DSTALPHA_OP_SET(config->alphablend.dst_alpha_op) @@ -790,3 +790,137 @@ hpm_stat_t pdma_scale(PDMA_Type *ptr, return status_success; } + +typedef struct pdma_buf2plane_format { + display_pixel_format_t format; + display_byteorder_t byteorder; +} pdma_buf2plane_format_t; + +static const pdma_buf2plane_format_t plane_format_tab[display_buf_format_max] = { + [display_buf_format_argb8888] = {display_pixel_format_argb8888, display_byteorder_a3a2a1a0}, + [display_buf_format_bgra8888] = {display_pixel_format_argb8888, display_byteorder_a0a1a2a3}, + [display_buf_format_rgb565] = {display_pixel_format_rgb565, display_byteorder_a3a2a1a0}, + [display_buf_format_rgb565_swap] = {display_pixel_format_rgb565, display_byteorder_a2a3a0a1}, + [display_buf_format_yuyv] = {display_pixel_format_ycbcr422, display_byteorder_a3a2a1a0}, + [display_buf_format_uyvy] = {display_pixel_format_ycbcr422, display_byteorder_a2a3a0a1}, + [display_buf_format_y8] = {display_pixel_format_y8, display_byteorder_a3a2a1a0}, +}; + +static const pdma_buf2plane_format_t out_format_tab[display_buf_format_max] = { + [display_buf_format_argb8888] = {display_pixel_format_argb8888, display_byteorder_a3a2a1a0}, + [display_buf_format_bgra8888] = {display_pixel_format_argb8888, display_byteorder_a0a1a2a3}, + [display_buf_format_rgb565] = {display_pixel_format_rgb565, display_byteorder_a3a2a1a0}, + [display_buf_format_rgb565_swap] = {display_pixel_format_rgb565, display_byteorder_a2a3a0a1}, + [display_buf_format_yuyv] = {display_pixel_format_ycbcr422, display_byteorder_a2a3a0a1}, + [display_buf_format_uyvy] = {display_pixel_format_ycbcr422, display_byteorder_a3a2a1a0}, + [display_buf_format_y8] = {display_pixel_format_y8, display_byteorder_a3a2a1a0}, +}; + +void pdma_get_default_blit_option(pdma_blit_option_t *op) +{ + op->blend = display_alphablend_mode_src_over; + op->flip = pdma_flip_none; + op->rotate = pdma_rotate_0_degree; + op->scale.x = 1.0; + op->scale.y = 1.0; + op->translate.x = 0; + op->translate.y = 0; +} + +hpm_stat_t pdma_blit_ex(PDMA_Type *ptr, + display_buf_t *dst, + display_buf_t *src, + pdma_blit_option_t *op, + bool wait, uint32_t *status) +{ + if ((!dst) || (!src) || (!src->buf) || (!dst->buf) || + (op->scale.x > 4096) || (op->scale.y > 4096) || + /* YUV422 requires width to be 2-pixel aligned */ + ((display_pixel_format_is_yuv_format(plane_format_tab[src->format].format)) && (src->width & 1)) || + ((display_pixel_format_is_yuv_format(plane_format_tab[dst->format].format)) && (dst->width & 1))) { + return status_invalid_argument; + } + + pdma_decimation_t x_dec; + pdma_decimation_t y_dec; + uint32_t x_scale; + uint32_t y_scale; + + pdma_config_t config; + pdma_plane_config_t plane_src; + pdma_plane_config_t plane_dst; + display_yuv2rgb_coef_t yuv2rgb_coef; + pdma_output_config_t output; + + pdma_calculate_scale(65536, (uint32_t)(65536 * op->scale.x), &x_dec, &x_scale); + pdma_calculate_scale(65536, (uint32_t)(65536 * op->scale.y), &y_dec, &y_scale); + + pdma_get_default_plane_config(ptr, &plane_src, plane_format_tab[src->format].format); + pdma_get_default_plane_config(ptr, &plane_dst, plane_format_tab[dst->format].format); + pdma_get_default_yuv2rgb_coef_config(ptr, &yuv2rgb_coef, plane_format_tab[src->format].format); + pdma_get_default_output_config(ptr, &output, out_format_tab[dst->format].format); + + config.enable_plane = pdma_plane_both; + config.block_size = pdma_blocksize_8x8; + config.byteorder = out_format_tab[dst->format].byteorder; + pdma_init(ptr, &config); + + plane_src.buffer = (uint32_t)src->buf; + plane_src.byteorder = plane_format_tab[src->format].byteorder; + plane_src.width = src->width; + plane_src.height = src->height; + plane_src.pitch = src->stride; + plane_src.x_scale = x_scale; + plane_src.x_dec = x_dec; + plane_src.y_scale = y_scale; + plane_src.y_dec = y_dec; + plane_src.background = 0x00000000; /* alpha must be 0 */ + plane_src.x_offset = PDMA_YUV_SCALE_DEFAULT_X_OFFSET; + plane_src.flip = op->flip; + plane_src.rotate = op->rotate; + + plane_dst.buffer = (uint32_t)dst->buf; + plane_dst.byteorder = plane_format_tab[dst->format].byteorder; + plane_dst.width = dst->width; + plane_dst.height = dst->height; + plane_dst.pitch = dst->stride; + pdma_config_planes(ptr, &plane_src, &plane_dst, &yuv2rgb_coef); + + output.buffer = plane_dst.buffer; + output.plane[pdma_plane_src].x = op->translate.x; + output.plane[pdma_plane_src].y = op->translate.y; + + /* + * aligned to lower right of dst window and non-overlapping area is filled by background of src. + * so alpha that background of src must be 0. + */ + output.plane[pdma_plane_src].width = dst->width - op->translate.x; + output.plane[pdma_plane_src].height = dst->height - op->translate.y; + + output.plane[pdma_plane_dst].x = 0; + output.plane[pdma_plane_dst].y = 0; + output.plane[pdma_plane_dst].width = plane_dst.width; + output.plane[pdma_plane_dst].height = plane_dst.height; + + output.alphablend.src_alpha = src->alpha.val; + output.alphablend.src_alpha_op = src->alpha.op; + output.alphablend.dst_alpha = dst->alpha.val; + output.alphablend.dst_alpha_op = dst->alpha.op; + output.alphablend.mode = op->blend; + + output.width = plane_dst.width; + output.height = plane_dst.height; + output.pitch = plane_dst.pitch; + + pdma_config_output(ptr, &output); + pdma_start(ptr); + if (wait) { + hpm_stat_t stat; + do { + stat = pdma_check_status(ptr, status); + } while ((stat != status_pdma_done) && (stat != status_pdma_error)); + pdma_stop(ptr); + return stat; + } + return status_success; +} \ No newline at end of file diff --git a/drivers/src/hpm_plb_drv.c b/drivers/src/hpm_plb_drv.c index 6a26cb221..60f8066a6 100644 --- a/drivers/src/hpm_plb_drv.c +++ b/drivers/src/hpm_plb_drv.c @@ -17,8 +17,8 @@ void plb_type_b_set_lut(PLB_Type *plb, plb_chn_t chn, plb_type_b_lut_slice_t sli plb->TYPE_B[chn].MODE &= ~PLB_TYPE_B_MODE_OPT_SEL_MASK; } if (slice >= plb_type_b_slice_8) { - plb->TYPE_B[chn].LUT[1] = (plb->TYPE_B[chn].LUT[1] & (~((uint32_t)0xf))) | PLB_TYPE_B_LUT_LOOKUP_TABLE_SET(opt << ((slice - plb_type_b_slice_8) << 2)); + plb->TYPE_B[chn].LUT[1] = (plb->TYPE_B[chn].LUT[1] & (~PLB_TYPE_B_LUT_LOOKUP_TABLE_SET(PLB_SLICE_HIGH_BIT_MASK_SET(slice)))) | PLB_TYPE_B_LUT_LOOKUP_TABLE_SET(opt << PLB_SLICE_HIGH_BIT_SHIFT(slice)); } else { - plb->TYPE_B[chn].LUT[0] = (plb->TYPE_B[chn].LUT[0] & (~((uint32_t)0xf))) | PLB_TYPE_B_LUT_LOOKUP_TABLE_SET(opt << (slice << 2)); + plb->TYPE_B[chn].LUT[0] = (plb->TYPE_B[chn].LUT[0] & (~PLB_TYPE_B_LUT_LOOKUP_TABLE_SET(PLB_SLICE_LOW_BIT_MASK_SET(slice)))) | PLB_TYPE_B_LUT_LOOKUP_TABLE_SET(opt << PLB_SLICE_LOW_BIT_SHIFT(slice)); } } diff --git a/drivers/src/hpm_pllctl_drv.c b/drivers/src/hpm_pllctl_drv.c index 7a120b89d..3b6fe2e43 100644 --- a/drivers/src/hpm_pllctl_drv.c +++ b/drivers/src/hpm_pllctl_drv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 HPMicro + * Copyright (c) 2021-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * @@ -25,6 +25,9 @@ hpm_stat_t pllctl_set_pll_work_mode(PLLCTL_Type *ptr, uint8_t pll, bool int_mode) { + if ((ptr == NULL) || (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) { + return status_invalid_argument; + } if (int_mode) { if (!(ptr->PLL[pll].CFG0 & PLLCTL_PLL_CFG0_DSMPD_MASK)) { /* it was at frac mode, then it needs to be power down */ @@ -48,9 +51,10 @@ hpm_stat_t pllctl_set_refdiv(PLLCTL_Type *ptr, uint8_t pll, uint8_t div) { uint32_t min_ref; - if ((pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) - || (!div) - || (div > (PLLCTL_PLL_CFG0_REFDIV_MASK >> PLLCTL_PLL_CFG0_REFDIV_SHIFT))) { + if ((ptr == NULL) + || (pll > (PLLCTL_SOC_PLL_MAX_COUNT - 1)) + || (div == 0U) + || (div > (PLLCTL_PLL_CFG0_REFDIV_MASK >> PLLCTL_PLL_CFG0_REFDIV_SHIFT))) { return status_invalid_argument; } @@ -77,6 +81,9 @@ hpm_stat_t pllctl_set_refdiv(PLLCTL_Type *ptr, uint8_t pll, uint8_t div) hpm_stat_t pllctl_init_int_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz) { + if ((ptr == NULL) || (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) { + return status_invalid_argument; + } uint32_t freq, fbdiv, refdiv, postdiv; if ((freq_in_hz < PLLCTL_PLL_VCO_FREQ_MIN) || (freq_in_hz > PLLCTL_PLL_VCO_FREQ_MAX)) { @@ -141,6 +148,9 @@ hpm_stat_t pllctl_init_int_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, hpm_stat_t pllctl_init_frac_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t freq_in_hz) { + if ((ptr == NULL) || (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) { + return status_invalid_argument; + } uint32_t frac, refdiv, fbdiv, freq, postdiv; double div; if ((freq_in_hz < PLLCTL_PLL_VCO_FREQ_MIN) @@ -187,7 +197,7 @@ hpm_stat_t pllctl_init_frac_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, div = (double) freq / PLLCTL_SOC_PLL_REFCLK_FREQ * (refdiv * postdiv); fbdiv = freq / (PLLCTL_SOC_PLL_REFCLK_FREQ / (refdiv * postdiv)); - frac = (div - fbdiv) * (1 << 24); + frac = (uint32_t)((div - fbdiv) * (1 << 24)); /* * pll has to be powered down to configure frac mode @@ -209,6 +219,9 @@ hpm_stat_t pllctl_init_frac_pll_with_freq(PLLCTL_Type *ptr, uint8_t pll, uint32_t pllctl_get_pll_freq_in_hz(PLLCTL_Type *ptr, uint8_t pll) { + if ((ptr == NULL) || (pll >= PLLCTL_SOC_PLL_MAX_COUNT)) { + return status_invalid_argument; + } uint32_t fbdiv, frac, refdiv, postdiv, refclk, freq; if (ptr->PLL[pll].CFG1 & PLLCTL_PLL_CFG1_PLLPD_SW_MASK) { /* pll is powered down */ @@ -227,7 +240,7 @@ uint32_t pllctl_get_pll_freq_in_hz(PLLCTL_Type *ptr, uint8_t pll) /* pll frac mode */ fbdiv = PLLCTL_PLL_FREQ_FBDIV_FRAC_GET(ptr->PLL[pll].FREQ); frac = PLLCTL_PLL_FREQ_FRAC_GET(ptr->PLL[pll].FREQ); - freq = (refclk * (fbdiv + ((double) frac / (1 << 24)))) + 0.5; + freq = (uint32_t)((refclk * (fbdiv + ((double) frac / (1 << 24)))) + 0.5); } return freq; } diff --git a/drivers/src/hpm_qeiv2_drv.c b/drivers/src/hpm_qeiv2_drv.c index a3c3dfbfc..0c0ff8237 100644 --- a/drivers/src/hpm_qeiv2_drv.c +++ b/drivers/src/hpm_qeiv2_drv.c @@ -116,3 +116,24 @@ hpm_stat_t qeiv2_config_uvw_position(QEIV2_Type *qeiv2_x, qeiv2_uvw_config_t *co return status_success; } + +void qeiv2_config_filter(QEIV2_Type *qeiv2_x, qeiv2_filter_phase_t phase, bool outinv, qeiv2_filter_mode_t mode, bool sync, uint32_t filtlen) +{ + uint32_t len = filtlen; + uint8_t shift; + for (shift = 0; shift <= 7u; shift++) { + if (shift > 0) { + len >>= 1u; + } + if (len <= 0x1FFu) { + break; + } + } + if (len > 0x1FFu) { + len = 0x1FFu; + shift = 7u; + } + + qeiv2_x->FILT_CFG[phase] = + QEIV2_FILT_CFG_OUTINV_SET(outinv) | QEIV2_FILT_CFG_MODE_SET(mode) | QEIV2_FILT_CFG_SYNCEN_SET(sync) | QEIV2_FILT_CFG_FILTLEN_SET(((shift << 9u) | len)); +} diff --git a/drivers/src/hpm_rng_drv.c b/drivers/src/hpm_rng_drv.c index d0efa7510..c3a0565a5 100644 --- a/drivers/src/hpm_rng_drv.c +++ b/drivers/src/hpm_rng_drv.c @@ -69,7 +69,7 @@ static hpm_stat_t rng_rand(RNG_Type *ptr, void *buf, uint32_t count_in_byte, boo } while (!fifo_level && wait); if (fifo_level) { - *(uint32_t *)(buf + i * sizeof(uint32_t)) = ptr->FO2B; + *(uint32_t *)((uint32_t)buf + i * sizeof(uint32_t)) = ptr->FO2B; } else { stat = status_rng_not_available; break; diff --git a/drivers/src/hpm_sdxc_drv.c b/drivers/src/hpm_sdxc_drv.c index 7be4c9b5a..46757c417 100644 --- a/drivers/src/hpm_sdxc_drv.c +++ b/drivers/src/hpm_sdxc_drv.c @@ -112,10 +112,14 @@ hpm_stat_t sdxc_receive_cmd_response(SDXC_Type *base, sdxc_command_t *cmd) /* R3-R2-R1-R0 (lowest 8 bits are invalid bits) has the same format as R2 format in SD spec * after removing internal CRC7 and end bit */ - cmd->response[0] = (base->RESP[0] << 8); - cmd->response[1] = (base->RESP[1] << 8) | (base->RESP[0] >> 24); - cmd->response[2] = (base->RESP[2] << 8) | (base->RESP[1] >> 24); - cmd->response[3] = (base->RESP[3] << 8) | (base->RESP[2] >> 24); + uint32_t resp0 = base->RESP[0]; + uint32_t resp1 = base->RESP[1]; + uint32_t resp2 = base->RESP[2]; + uint32_t resp3 = base->RESP[3]; + cmd->response[0] = (resp0 << 8); + cmd->response[1] = (resp1 << 8) | (resp0 >> 24); + cmd->response[2] = (resp2 << 8) | (resp1 >> 24); + cmd->response[3] = (resp3 << 8) | (resp2 >> 24); } if (SDXC_CMD_XFER_AUTO_CMD_ENABLE_GET(base->CMD_XFER) == sdxc_auto_cmd12_enabled) { @@ -772,7 +776,7 @@ void sdxc_select_voltage(SDXC_Type *base, sdxc_bus_voltage_option_t option) base->PROT_CTRL = (base->PROT_CTRL & ~SDXC_PROT_CTRL_SD_BUS_VOL_VDD1_MASK) | SDXC_PROT_CTRL_SD_BUS_VOL_VDD1_SET(option_u32); - if ((option == sdxc_bus_voltage_sd_1v8) || (option == sdxc_bus_voltage_emmc_1v8)) { + if (option == sdxc_bus_voltage_sd_1v8) { base->AC_HOST_CTRL |= SDXC_AC_HOST_CTRL_SIGNALING_EN_MASK; } else { base->AC_HOST_CTRL &= ~SDXC_AC_HOST_CTRL_SIGNALING_EN_MASK; diff --git a/drivers/src/hpm_spi_drv.c b/drivers/src/hpm_spi_drv.c index be6aebbbc..fb16e371e 100644 --- a/drivers/src/hpm_spi_drv.c +++ b/drivers/src/hpm_spi_drv.c @@ -305,7 +305,7 @@ void spi_master_get_default_control_config(spi_control_config_t *config) config->common_config.trans_mode = spi_trans_write_only; config->common_config.data_phase_fmt = spi_single_io_mode; config->common_config.dummy_cnt = spi_dummy_count_2; -#if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1) +#if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1) config->common_config.cs_index = spi_cs_0; #endif } @@ -318,7 +318,7 @@ void spi_slave_get_default_control_config(spi_control_config_t *config) config->common_config.trans_mode = spi_trans_read_only; config->common_config.data_phase_fmt = spi_single_io_mode; config->common_config.dummy_cnt = spi_dummy_count_2; -#if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1) +#if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1) config->common_config.cs_index = spi_cs_0; #endif } @@ -364,10 +364,11 @@ void spi_format_init(SPI_Type *ptr, spi_format_config_t *config) hpm_stat_t spi_control_init(SPI_Type *ptr, spi_control_config_t *config, uint32_t wcount, uint32_t rcount) { - if (wcount > SPI_SOC_TRANSFER_COUNT_MAX || rcount > SPI_SOC_TRANSFER_COUNT_MAX) { +#if defined (SPI_SOC_TRANSFER_COUNT_MAX) && (SPI_SOC_TRANSFER_COUNT_MAX == 512) + if ((wcount > SPI_SOC_TRANSFER_COUNT_MAX) || (rcount > SPI_SOC_TRANSFER_COUNT_MAX)) { return status_invalid_argument; } - +#endif /* slave data only mode only works on write read together transfer mode */ if (config->slave_config.slave_data_only == true && config->common_config.trans_mode != spi_trans_write_read_together) { return status_invalid_argument; @@ -385,11 +386,11 @@ hpm_stat_t spi_control_init(SPI_Type *ptr, spi_control_config_t *config, uint32_ SPI_TRANSCTRL_DUMMYCNT_SET(config->common_config.dummy_cnt) | SPI_TRANSCTRL_RDTRANCNT_SET(rcount - 1); -#if defined(SPI_SOC_HAS_CS_SELECT) && (SPI_SOC_HAS_CS_SELECT == 1) +#if defined(HPM_IP_FEATURE_SPI_CS_SELECT) && (HPM_IP_FEATURE_SPI_CS_SELECT == 1) ptr->CTRL = (ptr->CTRL & ~SPI_CTRL_CS_EN_MASK) | SPI_CTRL_CS_EN_SET(config->common_config.cs_index); #endif -#if defined(SPI_SOC_HAS_NEW_TRANS_COUNT) && (SPI_SOC_HAS_NEW_TRANS_COUNT == 1) +#if defined(HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT) && (HPM_IP_FEATURE_SPI_NEW_TRANS_COUNT == 1) ptr->WR_TRANS_CNT = wcount - 1; ptr->RD_TRANS_CNT = rcount - 1; #endif @@ -504,7 +505,7 @@ hpm_stat_t spi_setup_dma_transfer(SPI_Type *ptr, } -#if defined(SPI_SOC_SUPPORT_DIRECTIO) && (SPI_SOC_SUPPORT_DIRECTIO == 1) +#if defined(HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO) && (HPM_IP_FEATURE_SPI_SUPPORT_DIRECTIO == 1) hpm_stat_t spi_directio_enable_output(SPI_Type *ptr, spi_directio_pin_t pin) { hpm_stat_t stat = status_success; diff --git a/drivers/src/hpm_tamp_drv.c b/drivers/src/hpm_tamp_drv.c new file mode 100644 index 000000000..ffb838dda --- /dev/null +++ b/drivers/src/hpm_tamp_drv.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include "hpm_tamp_drv.h" + +void tamp_init_ch_config(TAMP_Type *ptr, uint8_t ch, tamper_ch_config_t *config) +{ + ch >>= 1u; + ptr->TAMP[ch].CONTROL = TAMP_TAMP_CONTROL_BYPASS_SET(config->filter_bypass) + | TAMP_TAMP_CONTROL_FILTER_SET(config->filter_len) + | TAMP_TAMP_CONTROL_VALUE_SET(config->expect_high_level) + | TAMP_TAMP_CONTROL_SPEED_SET(config->speed) + | TAMP_TAMP_CONTROL_RECOVER_SET(config->auto_recover) + | TAMP_TAMP_CONTROL_ACTIVE_SET(config->active_mode) + | TAMP_TAMP_CONTROL_ENABLE_SET(config->enable); + ptr->TAMP[ch].POLY = config->poly; + ptr->TAMP[ch].LFSR = config->lfsr; +} + +void tamp_get_default_ch_config(TAMP_Type *ptr, tamper_ch_config_t *config) +{ + (void) ptr; + config->enable = false; + config->active_mode = false; + config->expect_high_level = false; + config->filter_bypass = false; + config->filter_len = filter_len_128_cycles; + config->speed = spd_1_time_per_sec; + config->auto_recover = false; + config->poly = 0; + config->lfsr = 0; +} diff --git a/drivers/src/hpm_uart_drv.c b/drivers/src/hpm_uart_drv.c index a80d444d2..3202fefbb 100644 --- a/drivers/src/hpm_uart_drv.c +++ b/drivers/src/hpm_uart_drv.c @@ -38,19 +38,20 @@ void uart_default_config(UART_Type *ptr, uart_config_t *config) config->modem_config.auto_flow_ctrl_en = false; config->modem_config.loop_back_en = false; config->modem_config.set_rts_high = false; -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) config->rxidle_config.detect_enable = false; config->rxidle_config.detect_irq_enable = false; config->rxidle_config.idle_cond = uart_rxline_idle_cond_rxline_logic_one; config->rxidle_config.threshold = 10; /* 10-bit for typical UART configuration (8-N-1) */ #endif -#if defined(UART_SOC_HAS_TXLINE_IDLE_DETECTION) && (UART_SOC_HAS_TXLINE_IDLE_DETECTION == 1) + /* if have 9bit_mode function, it's has be tx_idle function */ +#if defined(HPM_IP_FEATURE_UART_9BIT_MODE) && (HPM_IP_FEATURE_UART_9BIT_MODE == 1) config->txidle_config.detect_enable = false; config->txidle_config.detect_irq_enable = false; config->txidle_config.idle_cond = uart_rxline_idle_cond_rxline_logic_one; config->txidle_config.threshold = 10; /* 10-bit for typical UART configuration (8-N-1) */ #endif -#if defined(UART_SOC_HAS_RXEN_CFG) && (UART_SOC_HAS_RXEN_CFG == 1) +#if defined(HPM_IP_FEATURE_UART_RX_EN) && (HPM_IP_FEATURE_UART_RX_EN == 1) config->rx_enable = true; #endif } @@ -77,9 +78,9 @@ static bool uart_calculate_baudrate(uint32_t freq, uint32_t baudrate, uint16_t * continue; } if (div * osc > tmp) { - delta = div * osc - tmp; + delta = (uint16_t)(div * osc - tmp); } else if (div * osc < tmp) { - delta = tmp - div * osc; + delta = (uint16_t)(tmp - div * osc); } if (delta && ((delta * 100 / tmp) > HPM_UART_BAUDRATE_TOLERANCE)) { continue; @@ -158,7 +159,7 @@ hpm_stat_t uart_init(UART_Type *ptr, uart_config_t *config) ptr->LCR = tmp | UART_LCR_WLS_SET(config->word_length); -#if defined(UART_SOC_HAS_FINE_FIFO_THR) && (UART_SOC_HAS_FINE_FIFO_THR == 1) +#if defined(HPM_IP_FEATURE_UART_FINE_FIFO_THRLD) && (HPM_IP_FEATURE_UART_FINE_FIFO_THRLD == 1) /* reset TX and RX fifo */ ptr->FCRR = UART_FCRR_TFIFORST_MASK | UART_FCRR_RFIFORST_MASK; /* Enable FIFO */ @@ -183,10 +184,10 @@ hpm_stat_t uart_init(UART_Type *ptr, uart_config_t *config) uart_modem_config(ptr, &config->modem_config); -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) uart_init_rxline_idle_detection(ptr, config->rxidle_config); #endif -#if defined(UART_SOC_HAS_RXEN_CFG) && (UART_SOC_HAS_RXEN_CFG == 1) +#if defined(HPM_IP_FEATURE_UART_RX_EN) && (HPM_IP_FEATURE_UART_RX_EN == 1) if (config->rx_enable) { ptr->IDLE_CFG |= UART_IDLE_CFG_RXEN_MASK; } @@ -301,7 +302,7 @@ hpm_stat_t uart_send_data(UART_Type *ptr, uint8_t *source, uint32_t size_in_byte } -#if defined(UART_SOC_HAS_RXLINE_IDLE_DETECTION) && (UART_SOC_HAS_RXLINE_IDLE_DETECTION == 1) +#if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) hpm_stat_t uart_init_rxline_idle_detection(UART_Type *ptr, uart_rxline_idle_config_t rxidle_config) { ptr->IDLE_CFG &= ~(UART_IDLE_CFG_RX_IDLE_EN_MASK @@ -321,7 +322,8 @@ hpm_stat_t uart_init_rxline_idle_detection(UART_Type *ptr, uart_rxline_idle_conf } #endif -#if defined(UART_SOC_HAS_TXLINE_IDLE_DETECTION) && (UART_SOC_HAS_TXLINE_IDLE_DETECTION == 1) +/* if have 9bit_mode function, it's has be tx_idle function */ +#if defined(HPM_IP_FEATURE_UART_9BIT_MODE) && (HPM_IP_FEATURE_UART_9BIT_MODE == 1) hpm_stat_t uart_init_txline_idle_detection(UART_Type *ptr, uart_rxline_idle_config_t txidle_config) { ptr->IDLE_CFG &= ~(UART_IDLE_CFG_TX_IDLE_EN_MASK @@ -341,7 +343,7 @@ hpm_stat_t uart_init_txline_idle_detection(UART_Type *ptr, uart_rxline_idle_conf } #endif -#if defined(UART_SOC_HAS_TRIG_MODE) && (UART_SOC_HAS_TRIG_MODE == 1) +#if defined(HPM_IP_FEATURE_UART_TRIG_MODE) && (HPM_IP_FEATURE_UART_TRIG_MODE == 1) void uart_config_transfer_trig_mode(UART_Type *ptr, uart_trig_config_t *config) { ptr->MOTO_CFG = UART_MOTO_CFG_TXSTP_BITS_SET(config->stop_bit_len) @@ -355,7 +357,7 @@ void uart_config_transfer_trig_mode(UART_Type *ptr, uart_trig_config_t *config) /* fifo control register(FCR) is WO access, if support FCCR register, it is RW access. */ void uart_config_fifo_ctrl(UART_Type *ptr, uart_fifo_ctrl_t *ctrl) { -#if defined(UART_SOC_HAS_FINE_FIFO_THR) && (UART_SOC_HAS_FINE_FIFO_THR == 1) +#if defined(HPM_IP_FEATURE_UART_FINE_FIFO_THRLD) && (HPM_IP_FEATURE_UART_FINE_FIFO_THRLD == 1) ptr->FCRR = UART_FCRR_FIFOT4EN_MASK | UART_FCRR_TFIFOT4_SET(ctrl->tx_fifo_level) | UART_FCRR_RFIFOT4_SET(ctrl->rx_fifo_level) diff --git a/drivers/src/hpm_usb_drv.c b/drivers/src/hpm_usb_drv.c index 2535973fb..146c03495 100644 --- a/drivers/src/hpm_usb_drv.c +++ b/drivers/src/hpm_usb_drv.c @@ -44,11 +44,6 @@ static void usb_phy_deinit(USB_Type *ptr) ptr->PHY_CTRL1 &= ~USB_PHY_CTRL1_UTMI_OTG_SUSPENDM_MASK; /* clear otg_suspendm */ } -static uint8_t usb_phy_get_line_state(USB_Type *ptr) -{ - return USB_PHY_STATUS_LINE_STATE_GET(ptr->PHY_STATUS); -} - /*--------------------------------------------------------------------- * Driver API *--------------------------------------------------------------------- diff --git a/middleware/CMSIS/CMakeLists.txt b/middleware/CMSIS/CMakeLists.txt index 5e4628c1b..e0bfb7247 100644 --- a/middleware/CMSIS/CMakeLists.txt +++ b/middleware/CMSIS/CMakeLists.txt @@ -1,4 +1,4 @@ # Copyright (c) 2023 HPMicro # SPDX-License-Identifier: BSD-3-Clause -add_subdirectory(RTOS2) +add_subdirectory_ifdef(CONFIG_CMSIS_RTOS2 RTOS2) diff --git a/middleware/CMSIS/RTOS2/CMakeLists.txt b/middleware/CMSIS/RTOS2/CMakeLists.txt index 10c2b3dbe..9718fe897 100644 --- a/middleware/CMSIS/RTOS2/CMakeLists.txt +++ b/middleware/CMSIS/RTOS2/CMakeLists.txt @@ -3,3 +3,6 @@ sdk_inc(Include) add_subdirectory_ifdef(CONFIG_FREERTOS FreeRTOS) +add_subdirectory_ifdef(CONFIG_RTTHREAD_NANO RTThread) +add_subdirectory_ifdef(CONFIG_ECLIPSE_THREADX ThreadX) +add_subdirectory_ifdef(CONFIG_UCOS_III MicriumOS) diff --git a/middleware/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c b/middleware/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c index bffc084e4..eb5d10a13 100644 --- a/middleware/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c +++ b/middleware/CMSIS/RTOS2/FreeRTOS/Source/cmsis_os2.c @@ -34,9 +34,10 @@ #include "freertos_mpool.h" // osMemoryPool definitions #include "freertos_os2.h" // Configuration check and setup -#include "hpm_csr_regs.h" -#include "hpm_csr_drv.h" +#include "hpm_soc.h" #include "hpm_mchtmr_drv.h" + + /*---------------------------------------------------------------------------*/ #ifndef __ARM_ARCH_6M__ #define __ARM_ARCH_6M__ 0 diff --git a/middleware/CMSIS/RTOS2/FreeRTOS/Source/os_systick.c b/middleware/CMSIS/RTOS2/FreeRTOS/Source/os_systick.c deleted file mode 100644 index ecfe24867..000000000 --- a/middleware/CMSIS/RTOS2/FreeRTOS/Source/os_systick.c +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************//** - * @file os_systick.c - * @brief CMSIS OS Tick SysTick implementation - * @version V1.0.1 - * @date 29. November 2017 - ******************************************************************************/ -/* - * Copyright (c) 2017-2017 Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an AS IS BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "os_tick.h" - -#include "RTE_Components.h" -#include CMSIS_device_header - -#ifdef SysTick - -#ifndef SYSTICK_IRQ_PRIORITY -#define SYSTICK_IRQ_PRIORITY 0xFFU -#endif - -static uint8_t PendST; - -// Setup OS Tick. -__WEAK int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) { - uint32_t load; - (void)handler; - - if (freq == 0U) { - return (-1); - } - - load = (SystemCoreClock / freq) - 1U; - if (load > 0x00FFFFFFU) { - return (-1); - } - - NVIC_SetPriority(SysTick_IRQn, SYSTICK_IRQ_PRIORITY); - - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk; - SysTick->LOAD = load; - SysTick->VAL = 0U; - - PendST = 0U; - - return (0); -} - -/// Enable OS Tick. -__WEAK void OS_Tick_Enable (void) { - - if (PendST != 0U) { - PendST = 0U; - SCB->ICSR = SCB_ICSR_PENDSTSET_Msk; - } - - SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; -} - -/// Disable OS Tick. -__WEAK void OS_Tick_Disable (void) { - - SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; - - if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0U) { - SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; - PendST = 1U; - } -} - -// Acknowledge OS Tick IRQ. -__WEAK void OS_Tick_AcknowledgeIRQ (void) { - (void)SysTick->CTRL; -} - -// Get OS Tick IRQ number. -__WEAK int32_t OS_Tick_GetIRQn (void) { - return ((int32_t)SysTick_IRQn); -} - -// Get OS Tick clock. -__WEAK uint32_t OS_Tick_GetClock (void) { - return (SystemCoreClock); -} - -// Get OS Tick interval. -__WEAK uint32_t OS_Tick_GetInterval (void) { - return (SysTick->LOAD + 1U); -} - -// Get OS Tick count value. -__WEAK uint32_t OS_Tick_GetCount (void) { - uint32_t load = SysTick->LOAD; - return (load - SysTick->VAL); -} - -// Get OS Tick overflow status. -__WEAK uint32_t OS_Tick_GetOverflow (void) { - return ((SysTick->CTRL >> 16) & 1U); -} - -#endif // SysTick diff --git a/middleware/CMSIS/RTOS2/Include/cmsis_os2.h b/middleware/CMSIS/RTOS2/Include/cmsis_os2.h index 91b393101..12ca33701 100644 --- a/middleware/CMSIS/RTOS2/Include/cmsis_os2.h +++ b/middleware/CMSIS/RTOS2/Include/cmsis_os2.h @@ -70,7 +70,7 @@ #define __NO_RETURN __attribute__((__noreturn__)) #elif defined(__GNUC__) #define __NO_RETURN __attribute__((__noreturn__)) -#elif defined(__ICCARM__) +#elif defined(__ICCARM__) || defined(__ICCRISCV__) #define __NO_RETURN __noreturn #else #define __NO_RETURN diff --git a/middleware/CMSIS/RTOS2/MicriumOS/CMakeLists.txt b/middleware/CMSIS/RTOS2/MicriumOS/CMakeLists.txt new file mode 100644 index 000000000..73164c29e --- /dev/null +++ b/middleware/CMSIS/RTOS2/MicriumOS/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2023 HPMicro +# SPDX-License-Identifier: BSD-3-Clause + +sdk_inc(./include) +sdk_src(cmsis_os2.c) diff --git a/middleware/CMSIS/RTOS2/MicriumOS/cmsis_os2.c b/middleware/CMSIS/RTOS2/MicriumOS/cmsis_os2.c new file mode 100644 index 000000000..df9a08a7b --- /dev/null +++ b/middleware/CMSIS/RTOS2/MicriumOS/cmsis_os2.c @@ -0,0 +1,4412 @@ +/* + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/***************************************************************************//** + * @file cmsis_os2.c + * @brief CMSIS-RTOS2 -> MicriumOS Emulation Layer + ******************************************************************************/ + +/***************************************************************************//** + * # License + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is Third Party Software licensed by Silicon Labs from a third party + * and is governed by the sections of the MSLA applicable to Third Party + * Software and the additional terms set forth below. + * + ******************************************************************************/ + +/***************************************************************************//** + * Copyright (c) , Arm Limited and affiliates. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************/ + +/* + **************************************************************************************************** + **************************************************************************************************** + * I N C L U D E S + **************************************************************************************************** + **************************************************************************************************** + */ + +#include +#include +#include + +#include "sl_cmsis_os2_common.h" +#include "rtos_utils_priv.h" +#include "cmsis_os2.h" + +#include "hpm_soc.h" +#include "hpm_mchtmr_drv.h" +#include "hpm_clock_drv.h" + +/* + **************************************************************************************************** + **************************************************************************************************** + * F I L E G L O B A L S + **************************************************************************************************** + **************************************************************************************************** + */ + +#ifndef RTOS2_DEFAULT_THREAD_STACK_SIZE +#define RTOS2_DEFAULT_THREAD_STACK_SIZE 1024 +#endif + +#define RTOS_MODULE_CUR RTOS_CFG_MODULE_KERNEL + +#define osMinNumPriority 56 +#if OS_CFG_PRIO_MAX < osMinNumPriority +#error CMSIS-RTOS2 requires atleast 56 priority levels. OS_CFG_PRIO_MAX must be >= 56. +#endif + +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + +#ifndef CMSIS_RTOS2_TIMER_TASK_STACK_SIZE +#error CMSIS Timer task stack size not configured +#endif + +#ifndef CMSIS_RTOS2_TIMER_TASK_PRIO +#error CMSIS Timer task priority not configured +#endif + +#ifndef CMSIS_RTOS2_TIMER_TASK_QUEUE_SIZE +#error CMSIS Timer task queue size not configured +#endif + +static OS_TCB timer_task_tcb; +static CPU_STK timer_task_stack[CMSIS_RTOS2_TIMER_TASK_STACK_SIZE]; +static OS_Q timer_msg_queue; + +#endif + +/******************************************************************************************************** + ******************************************************************************************************** + * C O R E F U N C T I O N S + ******************************************************************************************************** + *******************************************************************************************************/ +/** Allocate storage for PRIMASK or BASEPRI value for use by + * CORE_ENTER/EXIT_ATOMIC() and CORE_ENTER/EXIT_CRITICAL() macros. */ +#define CORE_DECLARE_IRQ_STATE CPU_SR_ALLOC() + +/** Enter ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in + * scope. */ +#define CORE_ENTER_ATOMIC CPU_CRITICAL_ENTER + +/** Exit ATOMIC section. Assumes that a @ref CORE_DECLARE_IRQ_STATE exist in + * scope. */ +#define CORE_EXIT_ATOMIC CPU_CRITICAL_EXIT + + /***************************************************************************//** + * @brief + * Check whether the current CPU operation mode is handler mode. + * + * @return + * True if the CPU is in handler mode (currently executing an interrupt handler). + * @n False if the CPU is in thread mode. + ******************************************************************************/ +static bool CORE_InIrqContext(void) +{ + return (read_csr(CSR_MSCRATCH) != 0U) ? true : false; +} + +/******************************************************************************************************** + ******************************************************************************************************** + * L O C A L F U N C T I O N S + ******************************************************************************************************** + *******************************************************************************************************/ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + +static void sleeptimer_callback(sl_sleeptimer_timer_handle_t *handle, void *data) +{ + OS_ERR err; + (void)handle; + + OSQPost(&timer_msg_queue, + (void *)data, + sizeof(void *), + OS_OPT_POST_FIFO, + &err + ); + RTOS_ASSERT_CRITICAL((RTOS_ERR_CODE_GET(err) == OS_ERR_NONE), RTOS_ERR_CODE_GET(err),; ); +} + +static void timer_task(void *arg) +{ + OS_ERR err; + OS_MSG_SIZE size; + osTimer_t *p_tmr; + (void)arg; + + while (1) { + p_tmr = (osTimer_t *)OSQPend(&timer_msg_queue, + 0, + OS_OPT_PEND_BLOCKING, + &size, + NULL, + &err); + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + continue; + } + + if (p_tmr != NULL) { + p_tmr->callback(p_tmr->callback_data); + } + } +} +#endif + +/******************************************************************************************************** + ******************************************************************************************************** + * G L O B A L F U N C T I O N S + ******************************************************************************************************** + *******************************************************************************************************/ + +/* + **************************************************************************************************** + **************************************************************************************************** + * I N F O R M A T I O N A N D C O N T R O L + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osKernelInitialize() + * + * Description: The function 'osKernelInitialize()' initializes the RTOS Kernel. Before it is successfully + * executed, only the functions 'osKernelGetInfo()' and 'osKernelGetState()' may be called. + * + * Arguments : None + * + * Returns : osOK in case of success. + * osError if an unspecific error occurred. + * osErrorISR if called from an Interrupt Service Routine. + * osErrorNoMemory if no memory could be reserved for the operation. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osKernelInitialize(void) +{ + OS_ERR err; + + CPU_Init(); + + if (OSRunning == OS_STATE_OS_RUNNING) { + if (CORE_InIrqContext() == true) { + return osErrorISR; + } else { + return osError; + } + } + + OSInit(&err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + +#if (OS_CFG_SCHED_ROUND_ROBIN_EN == DEF_ENABLED) + OSSchedRoundRobinCfg(DEF_TRUE, 0, &err); +#endif + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + OSTaskCreate(&timer_task_tcb, + "CMSIS RTOS2 Timer Task", + timer_task, + (void *)0, + CMSIS_RTOS2_TIMER_TASK_PRIO, + &timer_task_stack[0], + ((CMSIS_RTOS2_TIMER_TASK_STACK_SIZE * 10u) / 100u), + CMSIS_RTOS2_TIMER_TASK_STACK_SIZE, + 0, + 0, + (void *)0, + OS_OPT_TASK_STK_CHK + OS_OPT_TASK_STK_CLR, + &err); + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + + OSQCreate(&timer_msg_queue, + "CMSIS RTOS2 Timer Queue", + CMSIS_RTOS2_TIMER_TASK_QUEUE_SIZE, + &err); + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + +#endif + return osOK; +} + +/* + **************************************************************************************************** + * osKernelGetInfo() + * + * Description: The function 'osKernelGetInfo()' retrieves the API and kernel version of the underlying + * RTOS kernel and a human readable identifier string for the kernel. It can be safely + * called before the RTOS is initialized or started (call to 'osKernelInitialize()' or + * 'osKernelStart()'). + * + * Arguments : version pointer to a buffer for retrieving the version information. + * Format (decimal): + * MMmmmrrrr + * MM : Major + * mmm : Minor + * rrrr: Revision + * + * id_buf pointer to the buffer for retrieving kernel identification string. + * + * id_size size of the buffer for the kernel identification string + * + * Returns : osOK in case of success. + * osError if an unspecific error occurred. + * + * Note(s) : None + **************************************************************************************************** + */ +osStatus_t osKernelGetInfo(osVersion_t *version, + char *id_buf, + uint32_t id_size) +{ + CPU_INT16U os_version; + OS_ERR err; + uint32_t os_major; + uint32_t os_minor; + uint32_t os_revision; + + if (id_buf == (char *)0) { + return osError; + } + + if (id_size < 20u) { + return osError; + } + + os_version = OSVersion(&err); + + os_major = os_version / 10000u; + os_minor = (os_version - os_major * 10000u) / 100u; + os_revision = os_version % 100u; + version->api = (os_major * 10000000u) + + (os_minor * 10000u) + + os_revision; + version->kernel = version->api; + + strcpy(id_buf, "MicriumOS"); + + return osOK; +} + +/* + **************************************************************************************************** + * osKernelGetState() + * + * Description: The function 'osKernelGetState()' returns the current state of the kernel and can be + * safely called before the RTOS is initialized or started (call to 'osKernelInitialize()' + * or 'osKernelStart()'). + * + * In case it fails it will return 'osKernelError', otherwise it returns the kernel state + * (refer to 'osKernelState_t' for the list of kernel states). + * + * Arguments : None + * + * Returns : osKernelInactive The kernel is not ready yet + * osKernelReady The kernel is not running yet + * osKernelRunning The kernel is initialized and running + * osKernelLocked The kernel was locked by 'OSKernelLock()' + * osKernelSuspended The kernel was suspended by 'OSKernelSuspend()' (NOT SUPPORTED) + * osKernelError An error occurred + * osKernelReserved Prevents enum down-size compiler optimization + * + * Note(s) : None + **************************************************************************************************** + */ +osKernelState_t osKernelGetState(void) +{ + if (OSInitialized == DEF_TRUE) { + if (OSRunning == OS_STATE_OS_RUNNING) { + if (OSSchedLockNestingCtr > 0u) { + return osKernelLocked; + } else { + return osKernelRunning; + } + } else { + return osKernelReady; + } + } + + return osKernelInactive; +} + +/* + **************************************************************************************************** + * osKernelStart() + * + * Description: The function 'osKernelStart()' starts the RTOS kernel and begins thread switching. + * It will not return to its calling function in case of success. Before it is successfully + * executed, only the functions 'osKernelGetInfo()', 'osKernelGetState()', and object creation + * functions ('osXxxNew()') may be called. + * + * At least one initial thread should be created prior 'osKernelStart()', see 'osThreadNew()'. + * + * Arguments : None + * + * Returns : osError If an unspecified error occurs + * osErrorISR If called from an ISR + * + * Note(s) : 1) This function cannot be called from Interrupt Service Routines + * + * 2) This function should not be called because MicriumOS should already be initialized. + * + * 3) CMSIS-RTOS2 requires atleast 56 priority levels. OS_CFG_PRIO_MAX must be >= 56. + **************************************************************************************************** + */ +osStatus_t osKernelStart(void) +{ + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + if (OSRunning == OS_STATE_OS_RUNNING) { + return osError; + } + +#if OS_CFG_PRIO_MAX >= osMinNumPriority + OSStart(&err); + + (void)err; // There is no point in checking the error here + // because the function will not return in case of success + + return osError; +#else + (void)err; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); // CMSIS-RTOS2 requires atleast 56 priority levels + return osError; +#endif +} + +/* + **************************************************************************************************** + * osKernelLock() + * + * Description: The function 'osKernelLock()' allows to lock all task switches. It returns the previous + * value of the lock state (1 if it was locked, 0 if it was unlocked), or a negative number + * representing an error code otherwise (refer to 'osStatus_t'). + * + * Arguments : None + * + * Returns : osError If an unspecified error occurs + * osErrorISR If called from an ISR + * + * Note(s) : 1) This function cannot be called from Interrupt Service Routines + * + * 2) The MicriumOS equivalent function can be called from an ISR. + **************************************************************************************************** + */ +int32_t osKernelLock(void) +{ + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + if (OSSchedLockNestingCtr > 0u) { + return 1u; + } + + OSSchedLock(&err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + + return 0u; +} + +/* + **************************************************************************************************** + * osKernelUnlock() + * + * Description: The function 'osKernelUnlock()' resumes from 'osKernelLock()'. It returns the previous + * value of the lock state (1 if it was locked, 0 if it was unlocked), or a negative number + * representing an error code otherwise (refer to 'osStatus_t'). + * + * Arguments : None + * + * Returns : osError If an unspecified error occurs + * osErrorISR If called from an ISR + * + * Note(s) : 1) This function cannot be called from Interrupt Service Routines + * + * 2) The MicriumOS equivalent function can be called from an ISR. + * + * 3) MicriumOS supports multiple lock levels but CMSIS-RTOS doesn't + **************************************************************************************************** + */ +int32_t osKernelUnlock(void) +{ + OS_NESTING_CTR ctr; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + ctr = OSSchedLockNestingCtr; // Get the current value of the lock counter + + if (ctr > 1u) { // CMSIS-RTOS only supports 1 lock level + ctr = 1u; + } + + OSSchedUnlock(&err); + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + + return ctr; +} + +/* + **************************************************************************************************** + * osKernelRestoreLock() + * + * Description: The function 'osKernelRestoreLock()' restores the previous lock state after 'osKernelLock()' + * or 'osKernelUnlock()'. + * + * The argument lock specifies the lock state as obtained by 'osKernelLock()' or 'osKernelUnlock()'. + * + * The function returns the new value of the lock state (1 if it was locked, 0 if it was unlocked), + * or a negative number representing an error code otherwise (refer to 'osStatus_t'). + * + * Arguments : lock new lock state: 1 == locked, 0 == not locked + * + * Returns : osError If an unspecified error occurs + * osErrorISR If called from an ISR + * + * Note(s) : 1) This function cannot be called from Interrupt Service Routines + * + * 2) There are no MicriumOS equivalent function to emulate this behavior. + **************************************************************************************************** + */ +int32_t osKernelRestoreLock(int32_t lock) +{ + int32_t new_state; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + if (lock > 0) { + OSSchedLock(&err); + new_state = 1u; + } else { + OSSchedUnlock(&err); + new_state = 0u; + } + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + + return new_state; +} + +/* + **************************************************************************************************** + * osKernelSuspend() + * + * Description: CMSIS-RTOS provides extension for tick-less operation which is useful for applications + * that use extensively low-power modes where the SysTick timer is also disabled. To provide + * a time-tick in such power-saving modes a wake-up timer is used to derive timer intervals. + * The function 'osKernelSuspend()' suspends the RTX kernel scheduler and thus enables sleep + * modes. + * + * The return value can be used to determine the amount of system ticks until the next + * tick-based kernel event will occure, i.e. a delayed thread becomed ready again. It is + * recommended to set up the low power timer to generate a wake-up interrupt based on this + * return value. + * + * Arguments : None + * + * Returns : time in 'ticks', for how long the system can sleep or power-down + * + * Note(s) : 1) This function cannot be called from Interrupt Service Routines + * + * 2) There are no MicriumOS equivalent function to emulate this behavior. + **************************************************************************************************** + */ +uint32_t osKernelSuspend(void) +{ + if (CORE_InIrqContext() == true) { + return 0u; + } + + return 0u; +} + +/* + **************************************************************************************************** + * osKernelResume() + * + * Description: CMSIS-RTOS provides extension for tick-less operation which is useful for applications + * that use extensively low-power modes where the SysTick timer is also disabled. To provide + * a time-tick in such power-saving modes a wake-up timer is used to derive timer intervals. + * The function 'osKernelSuspend()' suspends the RTX kernel scheduler and thus enables sleep + * modes. + * + * Arguments : time in 'ticks', for how long the system can sleep or power-down + * + * Returns : None + * + * Note(s) : 1) This function cannot be called from Interrupt Service Routines + * + * 2) There are no MicriumOS equivalent function to emulate this behavior. + **************************************************************************************************** + */ +void osKernelResume(uint32_t sleep_ticks) +{ + (void)sleep_ticks; + + if (CORE_InIrqContext() == true) { + return; + } +} + +/* + **************************************************************************************************** + * osKernelGetTickCount() + * + * Description: The function 'osKernelGetTickCount()' returns the current RTOS kernel tick count. + * + * Arguments : None + * + * Returns : the kernel current tick count + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osKernelGetTickCount(void) +{ +#if (OS_CFG_TICK_EN == DEF_ENABLED) + OS_ERR err; + OS_TICK ticks; + + ticks = OSTimeGet(&err); + (void)err; // CMSIS RTOS API does not give us a way to propagate errors here + + return ticks; +#else + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif //#if (OS_CFG_TICK_EN == DEF_ENABLED) +} + +/* + **************************************************************************************************** + * osKernelGetTickFreq() + * + * Description: The function 'osKernelGetTickFreq()' returns the frequency of the current RTOS kernel tick. + * + * Arguments : None + * + * Returns : the kernel tick frequency in Hz + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osKernelGetTickFreq(void) +{ +#if (OS_CFG_TICK_EN == DEF_ENABLED) + return OS_CFG_TICK_RATE_HZ; +#else + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + * osKernelGetSysTimerCount() + * + * Description: The function 'osKernelGetSysTimerCount() returns the current RTOS kernel system timer + * as a 32-bit value. The value is a rolling 32-bit counter that is composed of the kernel + * system interrupt timer value and the counter that counts these interrupts (RTOS kernel ticks). + * + * This function allows the implementation of very short timeout checks below the RTOS tick + * granularity. Such checks might be required when checking for a busy status in a device + * or peripheral initialization routine. + * + * Arguments : None + * + * Returns : the kernel timer tick count + **************************************************************************************************** + */ +uint32_t osKernelGetSysTimerCount(void) +{ +#if (OS_CFG_TICK_EN == DEF_ENABLED) + return (uint32_t)(mchtmr_get_count(HPM_MCHTMR)); +#else + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + * osKernelGetSysTimerFreq() + * + * Description: The function 'osKernelGetSysTimerFreq()' returns the frequency of the current RTOS + * kernel system timer. + * + * Arguments : None + * + * Returns : the kernel system timer frequency in Hz + **************************************************************************************************** + */ +uint32_t osKernelGetSysTimerFreq(void) +{ +#if (OS_CFG_TICK_EN == DEF_ENABLED) + return (clock_get_frequency(clock_mchtmr0)); +#else + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * G E N E R I C W A I T + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osDelay() + * + * Description: The function 'osDelay()' waits for a time period specified in kernel ticks. For a value + * of 1 the system waits until the next timer tick occurs. The actual time delay may be up + * to one timer tick less than specified, i.e. calling 'osDelay(1)' right before the next + * system tick occurs the thread is rescheduled immediately. + * + * The delayed thread is put into the BLOCKED state and a context switch occurs immediately. + * The thread is automatically put back to the READY state after the given amount of ticks + * has elapsed. If the thread will have the highest priority in READY state it will being + * scheduled immediately. + * + * Arguments : ticks is the amount of time (in ticks) that the task will be blocked + * + * Returns : osOK if the call is successful + * osErrorISR if called from an ISR + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osDelay(uint32_t ticks) +{ +#if (OS_CFG_TICK_EN == DEF_ENABLED) + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + OSTimeDly((OS_TICK)ticks, OS_OPT_TIME_DLY, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + + return osOK; +#else + (void)ticks; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif // #if (OS_CFG_TICK_EN == DEF_ENABLED) +} + +/* + **************************************************************************************************** + * osDelayUntil() + * + * Description: The function 'osDelayUntil()' waits until an absolute time (specified in kernel ticks) + * is reached. + * + * The corner case when the kernel tick counter overflows is handled by 'osDelayUntil()'. + * Thus it is absolutely legal to provide a value which is lower than the current tick + * value, i.e. returned by 'osKernelGetTickCount()'. Typically as a user you do not have + * to take care about the overflow. The only limitation you have to have in mind is that + * the maximum delay is limited to 0x7FFFFFFF ticks. + * + * The delayed thread is put into the BLOCKED state and a context switch occurs immediately. + * The thread is automatically put back to the READY state when the given time is reached. + * If the thread will have the highest priority in READY state it will being scheduled immediately. + * + * Arguments : ticks is the absolute time (in ticks) at which the task will wake up. + * + * Returns : osOK if the call is successful + * osParameter if time cannot be handled (out of bounds) + * osErrorISR if called from an ISR + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osDelayUntil(uint32_t ticks) +{ +#if (OS_CFG_TICK_EN == DEF_ENABLED) + OS_ERR err; + OS_TICK until; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + until = ticks - OSTimeGet(&err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osError; + } + + if (until > 0x7FFFFFF0u) { // Allow for 16 ticks of latency + until = 0u; + } + + OSTimeDly((OS_TICK)until, OS_OPT_TIME_DLY, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + return osErrorParameter; + } else { + return osOK; + } +#else + (void)ticks; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif // #if (OS_CFG_TICK_EN == DEF_ENABLED) +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * E V E N T F L A G S + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osEventFlagsNew() + * + * Description: The function 'osEventFlagsNew()' creates a new event flags object that is used to send + * events across threads and returns the pointer to the event flags object identifier or + * NULL in case of an error. It can be safely called before the RTOS is started + * (call to 'osKernelStart()'), but not before it is initialized (call to 'osKernelInitialize()'). + * + * The parameter 'attr' sets the event flags attributes (refer to 'osEventFlagsAttr_t'). + * Default attributes will be used if set to NULL, i.e. kernel memory allocation is used for + * the event control block. + * + * Arguments : attr sets the event flags attributes or default values if NULL + * + * .name is an ASCII string used to name the mutex + * + * .attr_bits Not currently used, MUST be set to 0 + * + * .cb_mem Pointer to storage area for the event flags control block + * + * .cb_size Size of the memory storage for the event flags control block + * + * Returns : The event flags ID + * + * Note(s) : 1) The event flags control block is assumed to be of type 'osEentFlags_t' which for the + * CMSIS-RTOS adaptation layer is defined as an OS_FLAG_GRP in MicriumOS. + **************************************************************************************************** + */ +osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + CPU_CHAR *p_name; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return (osEventFlagsId_t)0; + } + + p_name = (CPU_CHAR *)"EventFlags"; + if (attr == 0) { + p_flags = (osEventFlags_t *)malloc(sizeof(osEventFlags_t)); + if (p_flags == (osEventFlags_t *)0) { + return (osEventFlagsId_t)0; + } + p_flags->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_mem == (void *)0) { + p_flags = (osEventFlags_t *)malloc(sizeof(osEventFlags_t)); + if (p_flags == (osEventFlags_t *)0) { + return (osEventFlagsId_t)0; + } + p_flags->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_size < sizeof(osEventFlags_t) || (uint32_t)attr->cb_mem % sizeof(CPU_ALIGN)) { + return (osEventFlagsId_t)0; + } + p_flags = (osEventFlags_t*)attr->cb_mem; + p_flags->dyn_alloc = DEF_FALSE; + } + if (attr->name != (const char *)0) { + p_name = (CPU_CHAR *)attr->name; + } + } + + p_flags->flags = 0; + + OSFlagCreate(&p_flags->flag_grp, p_name, p_flags->flags, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_flags->dyn_alloc == DEF_TRUE) { + free(p_flags); + } + return (osEventFlagsId_t)0; + } + + return (osEventFlagsId_t)p_flags; +#else + (void)attr; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, (osEventFlagsId_t)0); + return (osEventFlagsId_t)0; +#endif +} + +/* + **************************************************************************************************** + * osEventFlagsSet() + * + * Description: The function 'osEventFlagsSet()' sets the event flags specified by the parameter 'flags' + * in an event flags object specified by parameter 'ef_id'. All threads waiting for the + * flag set will be notified to resume from BLOCKED state. + * + * The function returns the event flags stored in the event control block or an error code + * (highest bit is set, refer to Flags Functions Error Codes). + * + * Arguments : ef_id Is the events flags ID + * + * flags The flags to set + * + * Returns : The new state of the event flags + * osFlagsErrorUnknown unspecified error. + * osFlagsErrorParameter parameter ef_id does not identify a valid event flags object or flags has highest bit set. + * osFlagsErrorResource the event flags object is in an invalid state. + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, + uint32_t flags) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + OS_FLAG_GRP *p_grp; + OS_TCB *p_tcb; + OS_ERR err; + uint32_t rdy_flags; + uint32_t new_flags; + uint32_t ret_flags; + CORE_DECLARE_IRQ_STATE; + + p_flags = (osEventFlags_t *)ef_id; + if (p_flags == (osEventFlags_t *)0) { + return osFlagsErrorParameter; + } + p_grp = &p_flags->flag_grp; + + if ((flags & 0x80000000u) == 0x80000000u) { // MSB cannot be set + return osFlagsErrorParameter; + } + + CORE_ENTER_ATOMIC(); + + p_flags->flags |= flags; + new_flags = p_flags->flags; // New flags after set + + p_tcb = p_grp->PendList.HeadPtr; // Loop over pending tasks + while (p_tcb != DEF_NULL) { + if (p_tcb->FlagsOpt & OS_OPT_PEND_FLAG_CONSUME) { // Pender might consume the flags? + switch (p_tcb->FlagsOpt & OS_OPT_PEND_FLAG_MASK) { + case OS_OPT_PEND_FLAG_SET_ALL: // -> Pender waiting for all flags to be set + rdy_flags = (new_flags & p_tcb->FlagsPend); + if (rdy_flags == p_tcb->FlagsPend) { // -> Pender will really consume? + new_flags &= ~rdy_flags; // -> Simulate the consumption + } + break; + + case OS_OPT_PEND_FLAG_SET_ANY: // -> Pender waiting for any flags to be set + rdy_flags = (new_flags & p_tcb->FlagsPend); + if (rdy_flags != 0u) { // -> Pender will really consume? + new_flags &= ~rdy_flags; // -> Simulate the consumption + } + break; + + default: + break; + } + } + p_tcb = p_tcb->PendNextPtr; // Point to next task waiting for event flag(s) + } + + CORE_EXIT_ATOMIC(); + + OSFlagPost(p_grp, flags, OS_OPT_POST_FLAG_SET, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + ret_flags = new_flags; + break; + + default: + ret_flags = osFlagsErrorResource; + break; + } + return ret_flags; +#else + (void)ef_id; + (void)flags; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osEventFlagsClear() + * + * Description: The function 'osEventFlagsClear()' clears the event flags specified by the parameter 'flags' + * in an event flags object specified by parameter 'ef_id'. + * + * The function returns the event flags stored in the event control block prior to clearing + * the flags or an error code (highest bit is set, refer to Flags Functions Error Codes). + * + * Arguments : ef_id Is the events flags ID + * + * flags The flags to clear + * + * Returns : osFlagsErrorUnknown unspecified error. + * osFlagsErrorParameter parameter ef_id does not identify a valid event flags + * object or flags has highest bit set. + * osFlagsErrorResource the event flags object is in an invalid state. + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, + uint32_t flags) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + OS_ERR err; + uint32_t old_flags; + CORE_DECLARE_IRQ_STATE; + + p_flags = (osEventFlags_t *)ef_id; + if (p_flags == (osEventFlags_t *)0) { + return osFlagsErrorParameter; + } + + CORE_ENTER_ATOMIC(); + old_flags = p_flags->flags; // Get previous value of flags + p_flags->flags &= ~flags; + CORE_EXIT_ATOMIC(); + + OSFlagPost(&p_flags->flag_grp, flags, OS_OPT_POST_FLAG_CLR, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + old_flags = osFlagsErrorUnknown; + } + + return old_flags; +#else + (void)ef_id; + (void)flags; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osEventFlagsGet() + * + * Description: The function 'osEventFlagsGet()' gets the current state of the event flags in an event + * flags object specified by parameter 'ef_id'. + * + * Arguments : ef_id Is the events flags ID + * + * flags The flags to clear + * + * Returns : osFlagsErrorUnknown unspecified error. + * osFlagsErrorParameter parameter ef_id does not identify a valid event flags object or flags has highest bit set. + * osFlagsErrorResource the event flags object is in an invalid state. + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osEventFlagsGet(osEventFlagsId_t ef_id) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + uint32_t flags; + + p_flags = (osEventFlags_t *)ef_id; + if (p_flags == (osEventFlags_t *)0) { + return 0u; + } + + flags = (uint32_t)p_flags->flags; // Get current value of flags + return flags; +#else + (void)ef_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osEventFlagsWait() + * + * Description: The function 'osEventFlagsWait()' suspends the execution of the currently RUNNING thread + * until any or all event flags specified by the parameter 'flags' in the event object + * specified by parameter 'ef_id' are set. When these event flags are already set, the + * function returns instantly. Otherwise, the thread is put into the state BLOCKED. + * + * Arguments : ef_id Is the events flags ID + * + * flags The desired flag(s) to wait for + * + * options + * osFlagsWaitAny Wait for any flag (default). + * osFlagsWaitAny | osFlagsNoClear Wait for any flag specified but do not consume + * osFlagsWaitAll Wait for all flags. + * osFlagsWaitAll | osFlagsNoClear Wait for all flags specified but do not consume + * + * timeout + * The parameter timeout specifies how long the system waits for event flags. + * While the system waits, the thread that is calling this function is put into the + * BLOCKED state. The parameter timeout can have the following values: + * + * when timeout is 0, the function returns instantly (i.e. try semantics). + * when timeout is set to 'osWaitForever' the function will wait for an infinite time until + * the event flags become available (i.e. wait semantics). + * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * + * Returns : The + * osFlagsErrorUnknown unspecified error. + * osFlagsErrorTimeout awaited flags have not been set in the given time. + * osFlagsErrorResource awaited flags have not been set when no timeout was specified. + * osFlagsErrorParameter parameter 'ef_id' does not identify a valid event flags object or flags has highest bit set. + * + * Note(s) : 1) May be called from Interrupt Service Routines if the parameter timeout is set to 0. + * + * 2) MicriumOS does NOT return the flags prior to clearing but instead, the flags that + * made the task ready-to-run. + **************************************************************************************************** + */ +uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, + uint32_t flags, + uint32_t options, + uint32_t timeout) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + OS_TICK os_timeout; + OS_OPT opt; + OS_ERR err; + CPU_TS ts; + uint32_t rtn_flags; + CORE_DECLARE_IRQ_STATE; + + p_flags = (osEventFlags_t *)ef_id; + if (p_flags == (osEventFlags_t *)0) { + return osFlagsErrorParameter; + } + + if ((flags & 0x80000000u) == 0x80000000u) { // MSB cannot be set + return osFlagsErrorParameter; + } + opt = OS_OPT_PEND_BLOCKING; + if (timeout == osWaitForever) { // Convert CMSIS-RTOS timeout to MicriumOS + if (CORE_InIrqContext() == true) { + return osFlagsErrorParameter; + } + os_timeout = 0u; // 0 for MicriumOS means forever + } else if (timeout == 0u) { + opt = OS_OPT_PEND_NON_BLOCKING; // No timeout, non-blocking + os_timeout = 0u; // timeout for MicriumOS in non-blocking mode is ignored + } else { + if (CORE_InIrqContext() == true) { + return osFlagsErrorParameter; + } + os_timeout = (OS_TICK)timeout; + } + + if (options & osFlagsWaitAll) { + opt |= OS_OPT_PEND_FLAG_SET_ALL; + } else { + opt |= OS_OPT_PEND_FLAG_SET_ANY; + } + + if (!(options & osFlagsNoClear)) { + opt |= OS_OPT_PEND_FLAG_CONSUME; + } + + OSFlagPend(&p_flags->flag_grp, (OS_FLAGS)flags, os_timeout, opt, &ts, &err); + + CORE_ENTER_ATOMIC(); + rtn_flags = p_flags->flags; + if (!(options & osFlagsNoClear)) { + p_flags->flags &= ~flags; + } + CORE_EXIT_ATOMIC(); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return rtn_flags; + + case OS_ERR_TIMEOUT: + return osFlagsErrorTimeout; + + case OS_ERR_PEND_WOULD_BLOCK: + if (rtn_flags != (uint32_t)0u) { + return rtn_flags; + } else { + return osFlagsErrorResource; + } + + default: + return osFlagsErrorUnknown; + } +#else + (void)ef_id; + (void)flags; + (void)options; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osEventFlagsDelete() + * + * Description: The function 'osEventFlagsDelete()' deletes the event flags object specified by parameter + * 'ef_id' and releases the internal memory obtained for the event flags handling. + * + * After this call, the 'ef_id' is no longer valid and cannot be used. This can cause starvation + * of threads that are waiting for flags of this event object. The 'ef_id' may be created again + * using the function 'osEventFlagsNew()'. + * + * Arguments : ef_id Is the ID of the events flags to delete + * + * Returns : osOK the specified event flags object was deleted + * osErrorISR the function was called from an ISR + * osErrorParameter parameter 'ef_id' does not identify a valid event flags object + * osErrorResource the event flags object is in an invalid state. + * + * Note(s) : 1) This function cannot be called from an ISR. + **************************************************************************************************** + */ +osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_flags = (osEventFlags_t *)ef_id; + if (p_flags == (osEventFlags_t *)0) { + return osErrorParameter; + } + + OSFlagDel(&p_flags->flag_grp, OS_OPT_DEL_ALWAYS, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + if (p_flags->dyn_alloc == DEF_TRUE) { + free(p_flags); + } + return osOK; + + default: + return osErrorResource; + } +#else + (void)ef_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osEventFlagsGetName() + * + * Description: The function 'osEventFlagsGetName()' gets the name of the event flags object specified + * by parameter 'ef_id'. + * + * Arguments : ef_id Is the events flags ID + * + * Returns : A pointer to the name upon success + * NULL upon failure + * + * Note(s) : 1) This function cannot be called from an ISR + **************************************************************************************************** + */ +const char *osEventFlagsGetName(osEventFlagsId_t ef_id) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) && (OS_CFG_DBG_EN == DEF_ENABLED) + osEventFlags_t *p_flags; + CPU_CHAR *p_name; + + p_flags = (osEventFlags_t *)ef_id; + if (p_flags == (osEventFlags_t *)0) { + return 0u; + } + + p_name = p_flags->flag_grp.NamePtr; // Get name of the event flags + return p_name; +#else + (void)ef_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * M U T U A L E X C L U S I O N S E M A P H O R E S + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osMutexNew() + * + * Description: The function 'osMutexNew()' creates and initializes a new mutex object and returns the + * pointer to the mutex object identifier or NULL in case of an error. It can be safely + * called before the RTOS is started (call to 'osKernelStart()'), but not before it is + * initialized (call to 'osKernelInitialize()'). + * + * The parameter 'attr' sets the mutex object attributes (refer to 'osMutexAttr_t'). + * Default attributes will be used if set to NULL. + * + * Arguments : attr sets the mutex attributes or default values if NULL + * + * .name is an ASCII string used to name the mutex + * + * .attr_bits can have the following attributes: + * + * osMutexRecursive + * osMutexPrioInherit + * osMutexRobust + * + * .cb_mem Pointer to storage area for the mutex control block + * + * .cb_size Size of the memory storage for the mutex control block + * + * Returns : The mutex ID + * + * Note(s) : 1) MicriumOS does NOT support the osMutexRobust attribute. The user must explicitely + * release ownership of the mutex before deleting a task. + * + * 2) MicriumOS mutexes are always recursive and support priority inheritance. Those + * attributes cannot be disabled. + * + * 3) The memory control block is assumed to be of type 'osMutex_t' which for the CMSIS-RTOS + * adaptation layer is defined as an OS_MUTEX in MicriumOS. + **************************************************************************************************** + */ +osMutexId_t osMutexNew(const osMutexAttr_t *attr) +{ +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) + osMutex_t *p_mutex; + CPU_CHAR *p_name; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return (osMutexId_t)0; + } + + p_name = (CPU_CHAR *)"Mutex"; + if (attr == 0) { + p_mutex = (osMutex_t *)malloc(sizeof(osMutex_t)); + if (p_mutex == (osMutex_t *)0) { + return (osMutexId_t)0; + } + p_mutex->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_mem == (void *)0) { + p_mutex = (osMutex_t*)malloc(sizeof(osMutex_t)); + if (p_mutex == (osMutex_t*)0) { + return (osMutexId_t)0; + } + p_mutex->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_size < sizeof(osMutex_t) || (uint32_t)attr->cb_mem % sizeof(CPU_ALIGN)) { + return (osMutexId_t)0; + } + p_mutex = (osMutex_t *)attr->cb_mem; + p_mutex->dyn_alloc = DEF_FALSE; + } + if (attr->name != (const char *)0) { + p_name = (CPU_CHAR *)attr->name; + } + } + + OSMutexCreate(&p_mutex->mutex, p_name, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_mutex->dyn_alloc == DEF_TRUE) { + free(p_mutex); + } + return (osMutexId_t)0; + } + + if (attr != NULL && (attr->attr_bits & osMutexRecursive)) { + p_mutex->recursive = DEF_TRUE; + } else { + p_mutex->recursive = DEF_FALSE; + } + + return (osMutexId_t)p_mutex; +#else + (void)attr; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, (osMutexId_t)0); + return (osMutexId_t)0; +#endif +} + +/* + **************************************************************************************************** + * osMutexGetName() + * + * Description: The function 'osMutexGetName()' returns the pointer to the name string of the mutex + * identified by parameter 'mutex_id' or NULL in case of an error. + * + * Arguments : mutex_id is the mutex ID returned by 'osMutexNew()' + * + * Returns : A pointer to the ASCII string containing the name of the mutex. + * NULL upon error + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +const char *osMutexGetName(osMutexId_t mutex_id) +{ +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) && (OS_CFG_DBG_EN == DEF_ENABLED) + osMutex_t *p_mutex; + + if (CORE_InIrqContext() == true) { + return NULL; + } + + p_mutex = (osMutex_t *)mutex_id; + if (p_mutex == (osMutex_t *)0) { + return NULL; + } + + return p_mutex->mutex.NamePtr; +#else + (void)mutex_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, NULL); + return NULL; +#endif +} + +/* + **************************************************************************************************** + * osMutexAcquire() + * + * Description: The blocking function 'osMutexAcquire()' waits until a mutex object specified by parameter + * mutex_id becomes available. If no other thread has obtained the mutex, the function + * instantly returns and blocks the mutex object. + * + * The parameter timeout specifies how long the system waits to acquire the mutex. While + * the system waits, the thread that is calling this function is put into the BLOCKED state. + * The parameter timeout can have the following values: + * + * Arguments : mutex_id is the mutex ID returned by 'osMutexNew()' + * + * timeout when timeout is 0, the function returns instantly (i.e. try semantics). + * when timeout is set to osWaitForever the function will wait for an infinite + * time until the mutex becomes available (i.e. wait semantics). + * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics).Timeout Value or 0 in case of no time-out. + * + * Returns : osOK the token has been obtained and the token count decremented. + * osErrorTimeout the token could not be obtained in the given time. + * osErrorResource the token could not be obtained when no timeout was specified. + * osErrorParameter the parameter semaphore_id is NULL or invalid. + * osErrorISR cannot be called from an ISR + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osMutexAcquire(osMutexId_t mutex_id, + uint32_t timeout) +{ +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) + OS_OPT opt; + osMutex_t *p_mutex; + OS_ERR err; + CPU_TS ts; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_mutex = (osMutex_t *)mutex_id; + if (p_mutex == (osMutex_t *)0) { + return osErrorParameter; + } + if (timeout == 0u) { + opt = OS_OPT_PEND_NON_BLOCKING; + } else { + opt = OS_OPT_PEND_BLOCKING; + } + + if (timeout == osWaitForever) { + timeout = 0u; + } + + OSMutexPend(&p_mutex->mutex, (OS_TICK)timeout, opt, &ts, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_MUTEX_OWNER: + if (p_mutex->recursive == DEF_FALSE) { + return osErrorResource; + } + return osOK; + + case OS_ERR_NONE: + return osOK; + + case OS_ERR_TIMEOUT: + return osErrorTimeout; + + default: + return osErrorResource; + } +#else + (void)mutex_id; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osMutexRelease() + * + * Description: The function 'osMutexRelease()' releases a mutex specified by parameter 'mutex_id'. + * Other threads that currently wait for this mutex will be put into the READY state. + * + * Arguments : mutex_id is the mutex ID returned by 'osMutexNew()' + * + * Returns : osOK the mutex has been released and the count incremented. + * osErrorResource the mutex could not be released + * osErrorParameter the parameter mutex_id is NULL or invalid. + * osErrorISR if called from an ISR + * + * Note(s) : 1) This function CANNOT be called from an ISR + * + * 2) MicriumOS always allows mutex nesting and thus that feature cannot be disabled. + **************************************************************************************************** + */ +osStatus_t osMutexRelease(osMutexId_t mutex_id) +{ +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) + osMutex_t *p_mutex; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_mutex = (osMutex_t *)mutex_id; + + if (p_mutex == (osMutex_t *)0) { + return osErrorParameter; + } + + OSMutexPost(&p_mutex->mutex, OS_OPT_POST_NONE, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + case OS_ERR_MUTEX_OWNER: + return osOK; + + default: + return osErrorResource; + } +#else + (void)mutex_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osMutexGetOwner() + * + * Description: The function 'osMutexGetOwner()' returns the thread ID of the thread that acquired a + * mutex specified by parameter 'mutex_id'. In case of an error or if the mutex is not + * blocked by any thread, it returns NULL. + * + * Arguments : mutex_id is the mutex ID returned by 'osMutexNew()' + * + * Returns : the theard ID of the mutex owner + * + * Note(s) : None + **************************************************************************************************** + */ +osThreadId_t osMutexGetOwner(osMutexId_t mutex_id) +{ +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) + osMutex_t *p_mutex; + osThread_t *p_thread; + CORE_DECLARE_IRQ_STATE; + + p_mutex = (osMutex_t *)mutex_id; + + if (p_mutex == (osMutex_t *)0) { + return 0u; + } + + CORE_ENTER_ATOMIC(); + p_thread = (osThread_t *)p_mutex->mutex.OwnerTCBPtr; + CORE_EXIT_ATOMIC(); + return (osThreadId_t)p_thread; +#else + (void)mutex_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + * osMutexDelete() + * + * Description: The function 'osMutexDelete()' deletes a mutex object specified by parameter 'mutex_id'. + * It releases internal memory obtained for mutex handling. After this call, the 'mutex_id' + * is no longer valid and cannot be used. + * + * The mutex may be created again using the function 'osMutexNew()'. + * + * Arguments : mutex_id is the mutex ID returned by 'osMutexNew()' + * + * Returns : osOK the mutex object has been deleted. + * osErrorParameter the parameter mutex_id is NULL or invalid. + * osErrorResource the mutex is in an invalid state. + * osErrorISR osMutexDelete() cannot be called from interrupt service routines. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osMutexDelete(osMutexId_t mutex_id) +{ +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) + osMutex_t *p_mutex; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_mutex = (osMutex_t *)mutex_id; + if (p_mutex == (osMutex_t *)0) { + return osErrorParameter; + } + + OSMutexDel(&p_mutex->mutex, OS_OPT_DEL_ALWAYS, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + if (p_mutex->dyn_alloc == DEF_TRUE) { + free(p_mutex); + } + return osOK; + + default: + return osErrorResource; + } +#else + (void)mutex_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * S E M A P H O R E M A N A G E M E N T + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osSemaphoreNew() + * + * Description: The function 'osSemaphoreNew()' creates and initializes a semaphore object that is used + * to manage access to shared resources and returns the pointer to the semaphore object + * identifier or NULL in case of an error. + * + * It can be safely called before the RTOS is started (call to 'osKernelStart()'), but not + * before it is initialized (call to 'osKernelInitialize()'). + * + * The parameter 'max_count' specifies the maximum number of available tokens. A 'max_count' + * value of 1 creates a binary semaphore. + * + * The parameter 'initial_count' sets the initial number of available tokens. + * + * The parameter 'attr' specifies additional semaphore attributes. Default attributes will + * be used if set to NULL. + * + * Arguments : max_count maximum number of available tokens. + * + * initial_count initial number of available tokens. + * + * attr semaphore attributes; NULL: default values. + * + * Returns : semaphore ID for reference by other functions or NULL in case of error. + * + * Note(s) : 1) This function CANNOT be called from an ISR + * + * 2) MicriumOS does not support a maximum count so the first argument is ignored. + **************************************************************************************************** + */ +osSemaphoreId_t osSemaphoreNew(uint32_t max_count, + uint32_t initial_count, + const osSemaphoreAttr_t *attr) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osSemaphore_t *p_sem; + CPU_CHAR *p_name; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return (osSemaphoreId_t)0; + } + + if (max_count == 0u) { + return (osSemaphoreId_t)0; // Cannot specify a 0 value for max count + } + + p_name = (CPU_CHAR *)"Semaphore"; + if (attr == 0) { + p_sem = (osSemaphore_t *)malloc(sizeof(osSemaphore_t)); + if (p_sem == (osSemaphore_t *)0) { + return (osSemaphoreId_t)0; + } + p_sem->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_mem == (void *)0) { + p_sem = (osSemaphore_t *)malloc(sizeof(osSemaphore_t)); + if (p_sem == (osSemaphore_t *)0) { + return (osSemaphoreId_t)0; + } + p_sem->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_size < sizeof(osSemaphore_t) || (uint32_t)attr->cb_mem % sizeof(CPU_ALIGN)) { + return (osSemaphoreId_t)0; + } + p_sem = (osSemaphore_t *)attr->cb_mem; + p_sem->dyn_alloc = DEF_FALSE; + } + if (attr->name != (const char *)0) { + p_name = (CPU_CHAR *)attr->name; + } + } + + OSSemCreate(&p_sem->sem, p_name, initial_count, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_sem->dyn_alloc == DEF_TRUE) { + free(p_sem); + } + return (osSemaphoreId_t)0; + } + + return (osSemaphoreId_t)p_sem; +#else + (void)max_count; + (void)initial_count; + (void)attr; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, (osSemaphoreId_t)0); + return (osSemaphoreId_t)0; +#endif +} + +/* + **************************************************************************************************** + * osSemaphoreGetName() + * + * Description: The function 'osSemaphoreGetName()' returns the pointer to the name string of the semaphore + * identified by parameter 'semaphore_id' or NULL in case of an error. + * + * Arguments : semaphore_id is the semaphore ID returned by 'osSemaphoreNew()' + * + * Returns : A pointer to the ASCII string containing the name of the semaphore. + * NULL upon error + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) && (OS_CFG_DBG_EN == DEF_ENABLED) + osSemaphore_t *p_sem; + + if (CORE_InIrqContext() == true) { + return NULL; + } + p_sem = (osSemaphore_t *)semaphore_id; + if (p_sem == (osSemaphore_t *)0) { + return NULL; + } + + return p_sem->sem.NamePtr; +#else + (void)semaphore_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, NULL); + return NULL; +#endif +} + +/* + **************************************************************************************************** + * osSemaphoreAcquire() + * + * Description: The blocking function 'osSemaphoreAcquire() waits until a token of the semaphore object + * specified by parameter 'semaphore_id' becomes available. If a token is available, the + * function instantly returns and decrements the token count. + * + * The parameter timeout specifies how long the system waits to acquire the token. While the + * system waits, the thread that is calling this function is put into the BLOCKED state. + * The parameter timeout can have the following values: + * + * when timeout is 0, the function returns instantly (i.e. try semantics). + * + * when timeout is set to 'osWaitForever' the function will wait for an infinite time until + * the semaphore becomes available (i.e. wait semantics). + * + * all other values specify a time in kernel ticks for a timeout (i.e. timed-wait semantics). + * + * Arguments : semaphore_id is the semaphore ID returned by 'osSemaphoreNew()' + * + * timeout Timeout Value or 0 in case of no time-out. + * + * Returns : osOK the token has been obtained and the token count decremented. + * osErrorTimeout the token could not be obtained in the given time. + * osErrorResource the token could not be obtained when no timeout was specified. + * osErrorParameter the parameter semaphore_id is NULL or invalid. + * + * Note(s) : 1) This function CANNOT be called from an ISR if you specify an NON-Zero timeout + **************************************************************************************************** + */ +osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, + uint32_t timeout) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osSemaphore_t *p_sem; + OS_ERR err; + CPU_TS ts; + + p_sem = (osSemaphore_t *)semaphore_id; + if (p_sem == (osSemaphore_t *)0) { + return osErrorParameter; + } + if (timeout == 0u) { + OSSemPend(&p_sem->sem, (OS_TICK)0u, OS_OPT_PEND_NON_BLOCKING, &ts, &err); + } else { + if (CORE_InIrqContext() == true) { + return osErrorParameter; + } else { + if (timeout == osWaitForever) { + timeout = 0u; + } + OSSemPend(&p_sem->sem, (OS_TICK)timeout, OS_OPT_PEND_BLOCKING, &ts, &err); + } + } + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + case OS_ERR_TIMEOUT: + return osErrorTimeout; + + default: + return osErrorResource; + } +#else + (void)semaphore_id; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osSemaphoreRelease() + * + * Description: The function 'osSemaphoreRelease()' releases a token of the semaphore object specified + * by parameter 'semaphore_id'. Tokens can only be released up to the maximum count + * specified at creation time, see 'osSemaphoreNew()'. Other threads that currently wait + * for a token of this semaphore object will be put into the READY state. + * + * Arguments : semaphore_id is the semaphore ID returned by 'osSemaphoreNew()' + * + * Returns : osOK the token has been released and the count incremented. + * osErrorResource the token could not be released (maximum token count has been reached). + * osErrorParameter the parameter semaphore_id is NULL or invalid. + * + * Note(s) : None + **************************************************************************************************** + */ +osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osSemaphore_t *p_sem; + OS_ERR err; + + p_sem = (osSemaphore_t *)semaphore_id; + if (p_sem == (osSemaphore_t *)0) { + return osErrorParameter; + } + (void)OSSemPost(&p_sem->sem, OS_OPT_POST_1, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +#else + (void)semaphore_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osSemaphoreGetCount() + * + * Description: The function 'osSemaphoreGetCount()' returns the number of available tokens of the + * semaphore object specified by parameter 'semaphore_id'. + * + * In case of an error it returns 0. + * + * Arguments : semaphore_id is the semaphore ID returned by 'osSemaphoreNew()' + * + * Returns : the number of tokens available + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osSemaphore_t *p_sem; + uint32_t count; + CORE_DECLARE_IRQ_STATE; + + p_sem = (osSemaphore_t*)semaphore_id; + + if (p_sem == (osSemaphore_t *)0) { + return 0u; + } + + CORE_ENTER_ATOMIC(); + count = p_sem->sem.Ctr; + CORE_EXIT_ATOMIC(); + return count; +#else + (void)semaphore_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + * osSemaphoreDelete() + * + * Description: The function 'osSemaphoreDelete()' deletes a semaphore object specified by parameter + * 'semaphore_id'. It releases internal memory obtained for semaphore handling. After + * this call, the 'semaphore_id' is no longer valid and cannot be used. + * + * The semaphore may be created again using the function 'osSemaphoreNew()'. + * + * Arguments : semaphore_id is the semaphore ID returned by 'osSemaphoreNew()' + * + * Returns : osOK the semaphore object has been deleted. + * osErrorParameter the parameter semaphore_id is NULL or invalid. + * osErrorResource the semaphore is in an invalid state. + * osErrorISR osSemaphoreDelete() cannot be called from interrupt service routines. + * + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osSemaphore_t *p_sem; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_sem = (osSemaphore_t *)semaphore_id; + + if (p_sem == (osSemaphore_t *)0) { + return osErrorParameter; + } + + OSSemDel(&p_sem->sem, OS_OPT_DEL_ALWAYS, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + if (p_sem->dyn_alloc == DEF_TRUE) { + free(p_sem); + } + return osOK; + + default: + return osErrorResource; + } +#else + (void)semaphore_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * T A S K M A N A G E M E N T + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osThreadNew() + * + * Description: The function 'osThreadNew()' starts a thread function by adding it to the list of active + * threads and sets it to state READY. Arguments for the thread function are passed using + * the parameter pointer *argument. When the priority of the created thread function is + * higher than the current RUNNING thread, the created thread function starts instantly + * and becomes the new RUNNING thread. + * + * Thread attributes are defined with the parameter pointer 'attr'. Attributes include + * settings for thread priority, stack size, or memory allocation. + * + * Arguments : func is a pointer to the task code + * + * argument is a pointer to an argument that is passed to the task when the task + * starts execution. + * + * attr attribute structure passed to the task creation code. + * specifying NULL assumes defaults. + * + * Thread attributes are: + * + * .name name of the thread + * .attr_bits values: + * osThreadDetached (default) 0x00000000 + * osThreadJoinable 0x00000001 + * .cb_mem pointer to TCB + * (allocated dynamically if NULL or not specified) + * .cb_size size of the TCB (in bytes) + * .stack_mem pointer to the base address of the stack + * (allocated dynamically if NULL or not specified) + * .stack_size size of stack (in bytes) + * (defaults to RTOS2_DEFAULT_THREAD_STACK_SIZE bytes + * if 0 specified or not specified) + * .priority Thread priority (0 = lowest, 55 = highest) + * .tz_module TrustZone Module Identified + * .reserved Must be 0 + * + * Returns : The thread ID upon success + * NULL upon error + * + * Note(s) : 1) '.tz_module' is ignored in this implementation + * + * 2) if '.cb_mem' is specified it must point to MicriumOS OS_TCB. + * also, '.cb_size' MUST be declared as 'sizeof(OS_TCB)' + * + * 3) 'attr_bits' are not supported and tasks are always assumed to be 'detached' + **************************************************************************************************** + */ +osThreadId_t osThreadNew(osThreadFunc_t func, + void *argument, + const osThreadAttr_t *attr) +{ + osThread_t *p_thread; + CPU_STK *p_stk_base; + uint32_t stk_size_in_bytes; + CPU_CHAR *p_name; + OS_PRIO prio; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return (osThreadId_t)0; // Can't create a thread from an ISR + } + if (func == (osThreadFunc_t)0) { // Make sure a thread is specified + return (osThreadId_t)0; + } + p_name = (CPU_CHAR *)"TaskName?"; + if (attr == 0) { + p_thread = (osThread_t *)malloc(sizeof(osThread_t)); + if (p_thread == (osThread_t *)0) { + return (osThreadId_t)0; + } else { + p_thread->obj_dyn_alloc = DEF_TRUE; + p_stk_base = (CPU_STK *)malloc(RTOS2_DEFAULT_THREAD_STACK_SIZE); + if (p_stk_base == (CPU_STK *)0) { + free(p_thread); + return (osThreadId_t)0; + } + p_thread->stack_dyn_alloc = DEF_TRUE; + stk_size_in_bytes = RTOS2_DEFAULT_THREAD_STACK_SIZE; + prio = (OS_PRIO)(osPriorityRealtime7 - osPriorityNormal); + } + } else { + if (attr->cb_mem == (void *)0) { + p_thread = (osThread_t *)malloc(sizeof(osThread_t)); + if (p_thread == (osThread_t *)0) { + return (osThreadId_t)0; + } + p_thread->obj_dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_size < sizeof(osThread_t) || (uint32_t)attr->cb_mem % sizeof(CPU_ALIGN)) { + return (osThreadId_t)0; + } + p_thread = attr->cb_mem; + p_thread->obj_dyn_alloc = DEF_FALSE; + } + if (attr->stack_size == 0u) { + p_stk_base = (CPU_STK *)malloc(RTOS2_DEFAULT_THREAD_STACK_SIZE); + if (p_stk_base == (CPU_STK *)0) { + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return (osThreadId_t)0; + } + stk_size_in_bytes = RTOS2_DEFAULT_THREAD_STACK_SIZE; + p_thread->stack_dyn_alloc = DEF_TRUE; + } else if ((attr->stack_size != 0u) + && (attr->stack_mem == NULL)) { + stk_size_in_bytes = attr->stack_size; + p_stk_base = (CPU_STK *)malloc(stk_size_in_bytes); + if (p_stk_base == (CPU_STK *)0) { + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return (osThreadId_t)0; + } + p_thread->stack_dyn_alloc = DEF_TRUE; + } else { + if (attr->stack_mem == NULL || ((uint32_t)attr->stack_mem % CPU_CFG_STK_ALIGN_BYTES)) { + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return (osThreadId_t)0; + } + p_stk_base = (CPU_STK *)attr->stack_mem; + stk_size_in_bytes = attr->stack_size; + p_thread->stack_dyn_alloc = DEF_FALSE; + } + if (attr->name != (const char *)0) { + p_name = (CPU_CHAR *)attr->name; + } + if (attr->priority == osPriorityNone) { + prio = (OS_PRIO)(osPriorityRealtime7 - osPriorityNormal); + } else { + if (attr->priority == osPriorityError) { + prio = (OS_PRIO)(OS_CFG_PRIO_MAX); // Set to an invalid priority level for MicriumOS + } else { + if (attr->priority > osPriorityRealtime7) { + if (p_thread->stack_dyn_alloc == DEF_TRUE) { + free(p_stk_base); + } + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return (osThreadId_t)0; + } + prio = (OS_PRIO)(osPriorityRealtime7 - attr->priority); + } + } + } + +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + // Create thread flags + OSFlagCreate(&p_thread->flag_grp, "ThreadFlags", 0, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_thread->stack_dyn_alloc == DEF_TRUE) { + free(p_stk_base); + } + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return (osThreadId_t)0; + } +#endif + + // Round down the stack size to a multiple of the cpu stack size + stk_size_in_bytes -= (stk_size_in_bytes % CPU_CFG_STK_ALIGN_BYTES); + + OSTaskCreate(&p_thread->tcb, p_name, func, argument, prio, p_stk_base, 0, + stk_size_in_bytes / sizeof(CPU_STK), 0u, 0u, 0u, + OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP, + &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_thread->stack_dyn_alloc == DEF_TRUE) { + free(p_stk_base); + } + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return (osThreadId_t)0; + } + + return (osThreadId_t)p_thread; +} + +/* + **************************************************************************************************** + * osThreadGetName() + * + * Description: The function osThreadGetName returns the pointer to the name string of the thread + * identified by parameter 'thread_id' or NULL in case of an error. + * + * Arguments : thread_id is the thread ID returned by osThreadNew() when the thread is created + * + * Returns : A pointer to the ASCII string containing the name of the thread. + * NULL upon error + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +const char *osThreadGetName(osThreadId_t thread_id) +{ +#if (OS_CFG_DBG_EN == DEF_ENABLED) + osThread_t *p_thread; + + p_thread = (osThread_t *)thread_id; + if (p_thread == (osThread_t *)0) { + return NULL; + } else { + return p_thread->tcb.NamePtr; + } +#else + (void)thread_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, NULL); + return NULL; +#endif +} + +/* + **************************************************************************************************** + * osThreadGetId() + * + * Description: The function 'osThreadGetId()' returns the thread object ID of the currently running + * thread or NULL in case of an error. + * + * Arguments : None + * + * Returns : The thread ID + * NULL upon error + **************************************************************************************************** + */ +osThreadId_t osThreadGetId(void) +{ + if (OSRunning == OS_STATE_OS_RUNNING) { + return (osThreadId_t)OSTCBCurPtr; + } + + return (osThreadId_t)0; +} + +/* + **************************************************************************************************** + * osThreadGetState() + * + * Description: The function osThreadGetState() returns the state of the thread identified by parameter + * 'thread_id'. In case it fails or if it is called from an ISR, it will return + * osThreadError, otherwise it returns the thread state (refer to 'osThreadState_t' for + * the list of thread states). + * + * Arguments : thread_id is the ID of the desired thread + * + * Returns : The thread state (see below) + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osThreadState_t osThreadGetState(osThreadId_t thread_id) +{ + osThread_t *p_thread; + osThreadState_t state; + + if (CORE_InIrqContext() == true) { + return osThreadError; + } + p_thread = (osThread_t *)thread_id; + if (p_thread == (osThread_t *)0) { + return osThreadError; + } + + if (OSRunning == OS_STATE_OS_RUNNING) { + switch (p_thread->tcb.TaskState) { + case OS_TASK_STATE_RDY: + state = osThreadReady; + break; + + case OS_TASK_STATE_DEL: + state = osThreadInactive; + break; + + case OS_TASK_STATE_DLY: + case OS_TASK_STATE_PEND: + case OS_TASK_STATE_PEND_TIMEOUT: + case OS_TASK_STATE_SUSPENDED: + case OS_TASK_STATE_DLY_SUSPENDED: + case OS_TASK_STATE_PEND_SUSPENDED: + case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED: + state = osThreadBlocked; + break; + + default: + state = osThreadError; + break; + } + } else { + state = osThreadError; + } + return state; +} + +/* + **************************************************************************************************** + * osThreadSetPriority() + * + * Description: The function 'osThreadSetPriority()' changes the priority of an active thread specified + * by the parameter 'thread_id' to the priority specified by the parameter 'priority'. + * + * Arguments : thread_id is the thread ID + * + * priority is the desired new priority for the specified thread + * + * Returns : osOK the priority of the specified thread has been changed + * osErrorParameter an invalid parameter was specified + * osErrorResource the thread is in an invalid state + * osErrorISR if called from an ISR + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osThreadSetPriority(osThreadId_t thread_id, + osPriority_t priority) +{ + OS_PRIO prio; + osThread_t *p_thread; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + if (thread_id == (osThreadId_t)0) { + return osErrorParameter; + } + if (priority == osPriorityError) { + return osErrorParameter; + } + if (priority > osPriorityRealtime7) { + return osErrorParameter; + } + prio = (OS_PRIO)(osPriorityRealtime7 - priority); + p_thread = (osThread_t *)thread_id; + + OSTaskChangePrio(&p_thread->tcb, prio, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +} + +/* + **************************************************************************************************** + * osThreadGetPriority() + * + * Description: The function 'osThreadGetPriority()' returns the priority of an active thread specified + * by the parameter 'thread_id'. + * + * Arguments : None + * + * Returns : The thread ID upon success + * osPriorityError upon error + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osPriority_t osThreadGetPriority(osThreadId_t thread_id) +{ + osPriority_t priority; + osThread_t *p_thread; + + if (OSRunning != OS_STATE_OS_RUNNING) { + return osPriorityError; + } + if (CORE_InIrqContext() == true) { + return osPriorityError; + } + p_thread = (osThread_t *)thread_id; + if (p_thread == (osThread_t *)0) { + return osPriorityError; + } + priority = (osPriority_t)((OS_PRIO)osPriorityRealtime7 - p_thread->tcb.Prio); + return priority; +} + +/* + **************************************************************************************************** + * osThreadYield() + * + * Description: The function 'osThreadYield()' passes control to the next thread with the same priority + * that is in the READY state. I f there is no other thread with the same priority in state + * READY, then the current thread continues execution and no thread switch occurs. + * + * 'osThreadYield()' does not set the thread to state BLOCKED. Thus no thread with a lower + * priority will be scheduled even if threads in state READY are available. + * + * Arguments : None + * + * Returns : osOK control has passed to the next thread + * osError an unspecified error occurred + * osErrorISR if called from an ISR + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osThreadYield(void) +{ +#if (OS_CFG_SCHED_ROUND_ROBIN_EN == DEF_ENABLED) + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + OSSchedRoundRobinYield(&err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osError; + } +#else + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osThreadSuspend() + * + * Description: The function 'osThreadSuspend()' suspends the execution of the thread identified by + * parameter 'thread_id'. The thread is put into the BLOCKED state (osThreadBlocked). + * Suspending the running thread will cause a context switch to another thread in READY + * state immediately. The suspended thread is not executed until explicitly resumed + * by the function 'osThreadResume()'. + * + * Threads that are already BLOCKED are removed from any wait list and become ready when + * they are resumed. Thus it is not recommended to suspend an already blocked thread. + * + * Arguments : thread_id is the ID of the thread + * + * Returns : osOK the thread has been suspended successfully. + * osErrorParameter thread_id is NULL or invalid. + * osErrorResource the thread is in an invalid state. + * osErrorISR the function osThreadSuspend cannot be called from interrupt service routines. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osThreadSuspend(osThreadId_t thread_id) +{ + OS_ERR err; + osThread_t *p_thread; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_thread = (osThread_t *)thread_id; + if (p_thread == (osThread_t *)0) { + return osErrorParameter; + } + + OSTaskSuspend(&p_thread->tcb, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +} + +/* + **************************************************************************************************** + * osThreadResume() + * + * Description: The function 'osThreadResume()' puts the thread identified by parameter 'thread_id' + * (which has to be in BLOCKED state) back to the READY state. If the resumed thread + * has a higher priority than the running thread a context switch occurs immediately. + * + * The thread becomes ready regardless of the reason why the thread was blocked. Thus + * it is not recommended to resume a thread not suspended by 'osThreadSuspend()'. + * + * Functions that will put a thread into BLOCKED state are: + * + * 'osEventFlagsWait()' and 'osThreadFlagsWait()', + * 'osDelay()' and 'osDelayUntil()', + * 'osMutexAcquire()' and 'osSemaphoreAcquire()', + * 'osMessageQueueGet()' + * 'osMemoryPoolAlloc(), + * 'osThreadJoin()' Function NOT supported + * 'osThreadSuspend()' + * + * Arguments : thread_id is the ID of the thread + * + * Returns : osOK the thread has been resumed successfully. + * osErrorParameter thread_id is NULL or invalid. + * osErrorResource the thread is in an invalid state. + * osErrorISR the function osThreadSuspend cannot be called from interrupt service routines. + * + * Note(s) : 1) This function CANNOT be called from an ISR + * + * 2) MicriumOS cannot emulate this function exactly as described above. In fact, + * MicriumOS doesn't cancel pending on an object. The suspension is simply removed if + * the task was suspended by 'osThreadSuspend()'. + **************************************************************************************************** + */ +osStatus_t osThreadResume(osThreadId_t thread_id) +{ + OS_ERR err; + osThread_t *p_thread; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_thread = (osThread_t *)thread_id; + + if (p_thread == (osThread_t *)0) { + return osErrorParameter; + } + + OSTaskResume(&p_thread->tcb, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +} +/* + **************************************************************************************************** + * osThreadDetach() + * + * Description: The function 'osThreadDetach()' changes the attribute of a thread (specified by 'thread_id') + * to 'osThreadDetached'. Detached threads are not joinable with 'osThreadJoin()'. + * + * When a detached thread is terminated, all resources are returned to the system. + * + * The behavior of 'osThreadDetach()' on an already detached thread is undefined. + * + * Arguments : thread_id is the ID of the thread + * + * Returns : osOK the thread has been detached successfully. + * osErrorParameter thread_id is NULL or invalid. + * osErrorResource the thread is in an invalid state. + * osErrorISR the function osThreadSuspend cannot be called from interrupt service routines. + * + * Note(s) : 1) This function CANNOT be called from an ISR + * + * 2) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +osStatus_t osThreadDetach(osThreadId_t thread_id) +{ + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + if (thread_id == (osThreadId_t)0) { + return osErrorParameter; + } + + (void)thread_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +} + +/* + **************************************************************************************************** + * osThreadJoin() + * + * Description: The function 'osThreadJoin()' waits for the thread specified by 'thread_id' to terminate. + * + * If that thread has already terminated, then 'osThreadJoin()' returns immediately. + * + * The thread must be joinable. By default threads are created with the attribute 'osThreadDetached'. + * + * Arguments : thread_id is the ID of the thread + * + * Returns : osOK the thread has been joined successfully. + * osErrorParameter thread_id is NULL or invalid. + * osErrorResource the thread is in an invalid state. + * osErrorISR the function osThreadSuspend cannot be called from interrupt service routines. + * + * Note(s) : 1) This function CANNOT be called from an ISR + * + * 2) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +osStatus_t osThreadJoin(osThreadId_t thread_id) +{ + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + if (thread_id == (osThreadId_t)0) { + return osErrorParameter; + } + + (void)thread_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +} + +/* + **************************************************************************************************** + * osThreadExit() + * + * Description: The function 'osThreadExit()' terminates the calling thread. + * + * This allows the thread to be synchronized with 'osThreadJoin()'. + * + * Arguments : None + * + * Returns : None + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +void osThreadExit(void) +{ + OS_ERR err; + + if (CORE_InIrqContext() == false) { + OSTaskDel((OS_TCB *)0, &err); + } + for (;; ) { + ; // This function cannot return + } +} + +/* + **************************************************************************************************** + * osThreadTerminate() + * + * Description: The function 'osThreadTerminate()' removes the thread specified by parameter 'thread_id' + * from the list of active threads. If the thread is currently RUNNING, the thread + * terminates and the execution continues with the next READY thread. + * + * If no such thread exists, the function will not terminate the running thread, but return + * 'osErrorResource'. + * + * Arguments : thread_id is the ID of the thread + * + * Returns : osOK the thread has been joined successfully. + * osErrorParameter thread_id is NULL or invalid. + * osErrorResource the thread is in an invalid state. + * osErrorISR the function osThreadSuspend cannot be called from interrupt service routines. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osThreadTerminate(osThreadId_t thread_id) +{ + osThread_t *p_thread; + CPU_STK *p_stk_base; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_thread = (osThread_t *)thread_id; + + if (p_thread == (osThread_t *)0) { + return osErrorParameter; + } + + p_stk_base = p_thread->tcb.StkBasePtr; + + OSTaskDel(&p_thread->tcb, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + if (p_thread->stack_dyn_alloc == DEF_TRUE) { + free(p_stk_base); + } + if (p_thread->obj_dyn_alloc == DEF_TRUE) { + free(p_thread); + } + return osOK; + + default: + return osErrorResource; + } +} + +/* + **************************************************************************************************** + * osThreadGetStackSize() + * + * Description: The function 'osThreadGetStackSize()' returns the stack size of the thread specified + * by parameter 'thread_id'. In case of an error, it returns 0. + * + * Arguments : thread_id is the ID of the thread + * + * Returns : The stack size (in bytes) + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +uint32_t osThreadGetStackSize(osThreadId_t thread_id) +{ + osThread_t *p_thread; + uint32_t stk_size; + CORE_DECLARE_IRQ_STATE; + + if (CORE_InIrqContext() == true) { + return 0u; + } + + p_thread = (osThread_t *)thread_id; + + if (p_thread == (osThread_t *)0) { + return 0u; + } + + CORE_ENTER_ATOMIC(); + stk_size = (uint32_t)p_thread->tcb.StkSize * sizeof(CPU_STK); + CORE_EXIT_ATOMIC(); + return stk_size; +} + +/* + **************************************************************************************************** + * osThreadGetStackSpace() + * + * Description: The function 'osThreadGetStackSize()' returns the unused stack space still available + * for the thread specified by parameter 'thread_id'. In case of an error, it returns 0. + * + * Arguments : thread_id is the ID of the thread + * + * Returns : The stack size (in bytes) + * + * Note(s) : 1) This function CANNOT be called from an ISR + * 2) This function will likely return an incorrect value if called for the currently running task + **************************************************************************************************** + */ +uint32_t osThreadGetStackSpace(osThreadId_t thread_id) +{ +#if (OS_CFG_STAT_TASK_STK_CHK_EN == DEF_ENABLED) + osThread_t *p_thread; + uint32_t free_space; + CORE_DECLARE_IRQ_STATE; + + if (CORE_InIrqContext() == true) { + return 0u; + } + + p_thread = (osThread_t *)thread_id; + + if (p_thread == (osThread_t *)0) { + return 0u; + } + + CORE_ENTER_ATOMIC(); + free_space = (uint32_t)(p_thread->tcb.StkSize - p_thread->tcb.StkUsed) * sizeof(CPU_STK); + CORE_EXIT_ATOMIC(); + return free_space; +#else + (void)thread_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + * osThreadGetCount() + * + * Description: The function 'osThreadGetCount()' returns the number of active threads or 0 in case of an error. + * + * Arguments : None + * + * Returns : The number of active tasks + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +uint32_t osThreadGetCount(void) +{ + if (CORE_InIrqContext() == true) { + return 0u; + } + return (uint32_t)OSTaskQty; +} + +/* + **************************************************************************************************** + * osThreadEnumerate() + * + * Description: The function 'osThreadEnumerate()' returns the number of enumerated threads or 0 in case + * of an error. + * + * Arguments : thread_array pointer to array for retrieving thread IDs. + * array_items maximum number of items in array for retrieving thread IDs. + * + * Returns : The number of active tasks + * + * Note(s) : 1) This function CANNOT be called from an ISR + * 2) This feature require OS_CFG_DBG_EN + **************************************************************************************************** + */ +uint32_t osThreadEnumerate(osThreadId_t *thread_array, + uint32_t array_items) +{ +#if (OS_CFG_DBG_EN == DEF_ENABLED) + OS_TCB *p_tcb; + uint32_t items; + + if (CORE_InIrqContext() == true) { + return 0u; + } + items = 0u; + + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + p_tcb = OSTaskDbgListPtr; + while ((p_tcb != (OS_TCB *)0) && (items < array_items)) { + *thread_array = p_tcb; + thread_array++; + p_tcb = p_tcb->DbgNextPtr; + items++; + } + CORE_EXIT_CRITICAL(); + return items; +#else + (void)thread_array; + (void)array_items; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * T H R E A D F L A G S + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osThreadFlagsSet() + * + * Description: Thread Flags are a more specialized version of the Event Flags. See Event Flags. + * While Event Flags can be used to globally signal a number of threads, thread flags are + * only sent to a single specific thread. Every thread instance can receive thread flags + * without any additional allocation of a thread flags object. + * + * Arguments : thread_id is the desired theard ID + * + * flags are the flags to set + * the upper bit (i.e. bit 31, is not allowed to be set) + * + * Returns : osFlagsErrorUnknown unspecified error. + * osFlagsErrorParameter parameter 'thread_id' is not a valid thread or flags has highest bit set. + * osFlagsErrorResource the thread is in invalid state. + * + * Note(s) : None + **************************************************************************************************** + */ +uint32_t osThreadFlagsSet(osThreadId_t thread_id, + uint32_t flags) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + OS_ERR err; + osThread_t *p_thread; + OS_FLAG_GRP *p_grp; + OS_TCB *p_tcb; + uint32_t rdy_flags; + uint32_t new_flags; + uint32_t ret_flags; + CORE_DECLARE_IRQ_STATE; + + p_thread = (osThread_t*)thread_id; + if (p_thread == (osThread_t *)0) { + return osFlagsErrorParameter; + } + p_grp = &p_thread->flag_grp; + + if ((flags & 0x80000000u) == 0x80000000u) { // Upper bit is not allowed to be set + return osFlagsErrorParameter; + } + + CORE_ENTER_ATOMIC(); + + new_flags = p_grp->Flags |= flags; // New flags after set + + p_tcb = p_grp->PendList.HeadPtr; // Loop over pending tasks + while (p_tcb != DEF_NULL) { + if (p_tcb->FlagsOpt & OS_OPT_PEND_FLAG_CONSUME) { // Pender might consume the flags? + switch (p_tcb->FlagsOpt & OS_OPT_PEND_FLAG_MASK) { + case OS_OPT_PEND_FLAG_SET_ALL: // -> Pender waiting for all flags to be set + rdy_flags = (new_flags & p_tcb->FlagsPend); + if (rdy_flags == p_tcb->FlagsPend) { // -> Pender will really consume? + new_flags &= ~rdy_flags; // -> Simulate the consumption + } + break; + + case OS_OPT_PEND_FLAG_SET_ANY: // -> Pender waiting for any flags to be set + rdy_flags = (new_flags & p_tcb->FlagsPend); + if (rdy_flags != 0u) { // -> Pender will really consume? + new_flags &= ~rdy_flags; // -> Simulate the consumption + } + break; + + default: + break; + } + } + p_tcb = p_tcb->PendNextPtr; // Point to next task waiting for event flag(s) + } + + CORE_EXIT_ATOMIC(); + + OSFlagPost(p_grp, (OS_FLAGS)flags, OS_OPT_POST_FLAG_SET, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + ret_flags = new_flags; + break; + + default: + ret_flags = osFlagsErrorResource; + break; + } + return ret_flags; +#else + (void)thread_id; + (void)flags; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osThreadFlagsClear() + * + * Description: The function 'osThreadFlagsClear()' clears the specified flags for the currently running + * thread. It returns the flags before clearing, or an error code if highest bit is set + * (refer to Flags Functions Error Codes). + * + * Arguments : flags are the flags to clear + * + * Returns : osFlagsErrorUnknown unspecified error, i.e. not called from a running threads context. + * osFlagsErrorParameter parameter flags has highest bit set. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +uint32_t osThreadFlagsClear(uint32_t flags) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osThread_t *p_thread; + OS_FLAG_GRP *p_grp; + OS_ERR err; + uint32_t old_flags; + + if (CORE_InIrqContext() == true) { + return (uint32_t)osErrorISR; + } + + if ((flags & 0x80000000u) == 0x80000000u) { // Upper bit is not allowed to be set + return osFlagsErrorParameter; + } + + p_thread = (osThread_t*)OSTCBCurPtr; + p_grp = &p_thread->flag_grp; + old_flags = p_grp->Flags; + (void)OSFlagPost(p_grp, (OS_FLAGS)flags, OS_OPT_POST_FLAG_CLR, &err); + + return old_flags; +#else + (void)flags; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osThreadFlagsGet() + * + * Description: The function 'osThreadFlagsGet()' returns the flags currently set for the currently + * running thread. If called without a active and currently running thread + * 'osThreadFlagsGet()' return zero. + * + * Arguments : None + * + * Returns : the flags + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +uint32_t osThreadFlagsGet(void) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osThread_t *p_thread; + OS_FLAG_GRP *p_grp; + uint32_t flags; + + if (CORE_InIrqContext() == true) { + return (uint32_t)osErrorISR; + } + + p_thread = (osThread_t*)OSTCBCurPtr; + p_grp = &p_thread->flag_grp; + flags = p_grp->Flags; + + return flags; +#else + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + * osThreadFlagsWait() + * + * Description: The function 'osThreadFlagsWait()' suspends the execution of the currently RUNNING + * thread until any or all of the thread flags specified with the parameter flags are set. + * + * When these thread flags are already set, the function returns instantly. Otherwise the + * thread is put into the state BLOCKED. + * + * Arguments : flags are the flags to wait for + * + * options wait for: + * osFlagsWaitAny + * osFlagsWaitAnyNoClear + * osFlagsWaitAll + * osFlagsWaitAllNoClear + * + * timeout the amount of time to wait for the desired flags + * + * Returns : osFlagsErrorUnknown unspecified error, i.e. not called from a running threads context. + * osFlagsErrorTimeout awaited flags have not been set in the given time. + * osFlagsErrorResource awaited flags have not been set when no timeout was specified. + * osFlagsErrorParameter Parameter flags has highest bit set. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +uint32_t osThreadFlagsWait(uint32_t flags, + uint32_t options, + uint32_t timeout) +{ +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + osThread_t *p_thread; + OS_FLAG_GRP *p_grp; + OS_ERR err; + OS_TICK os_timeout; + OS_OPT opt; + CPU_TS ts; + uint32_t old_flags; + uint32_t rdy_flags; + uint32_t rtn_flags; + + if (CORE_InIrqContext() == true) { + return (uint32_t)osErrorISR; + } + + if ((flags & 0x80000000u) == 0x80000000u) { // Upper bit is not + // allowed to be set + return osFlagsErrorParameter; + } + + if (timeout == osWaitForever) { + opt = OS_OPT_PEND_BLOCKING; + os_timeout = 0u; // Specifying 0 in MicriumOS + // means wait forever w/ blocking + } else if (timeout == 0u) { + opt = OS_OPT_PEND_NON_BLOCKING; + os_timeout = 0u; // The timeout parameter is + // ignored by MicriumOS in + // non-blocking mode + } else { + opt = OS_OPT_PEND_BLOCKING; + os_timeout = timeout; + } + + if (options & osFlagsWaitAll) { + opt |= OS_OPT_PEND_FLAG_SET_ALL; + } else { + opt |= OS_OPT_PEND_FLAG_SET_ANY; + } + + if (!(options & osFlagsNoClear)) { + opt |= OS_OPT_PEND_FLAG_CONSUME; + } + + p_thread = (osThread_t *)OSTCBCurPtr; + p_grp = &p_thread->flag_grp; + old_flags = p_grp->Flags; // Get flags + + rdy_flags = (uint32_t)OSFlagPend(p_grp, (OS_FLAGS)flags, os_timeout, opt, &ts, &err); + rtn_flags = rdy_flags | old_flags; + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_TIMEOUT: + return osFlagsErrorTimeout; + + case OS_ERR_NONE: + return rtn_flags; + + case OS_ERR_PEND_WOULD_BLOCK: + if (rdy_flags != (uint32_t)0u) { + return rtn_flags; + } else { + return osFlagsErrorResource; + } + + default: + return osFlagsErrorResource; + } +#else + (void)flags; + (void)options; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osFlagsErrorUnknown); + return osFlagsErrorUnknown; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * T I M E R M A N A G E M E N T + ***************************************************************************************************/ +/**************************************************************************************************** + * osTimerNew() + * + * Description: The function 'osTimerNew()' creates an one-shot or periodic timer and associates it with + * a callback function with argument. The timer is in stopped state until it is started + * with 'osTimerStart()'. The function can be safely called before the RTOS is started + * (call to 'osKernelStart()'), but not before it is initialized (call to 'osKernelInitialize()'). + * + * The function 'osTimerNew()' returns the pointer to the timer object identifier or NULL + * in case of an error. + * + * Arguments : func pointer to function that will be called when the timer expires + * + * type the type of timer created: + * osTimerOnce A one-shot timer + * osTimerPeriodic A periodic timer + * + * argument a pointer to arguments passed to the callback function (func) when the + * timer expires. + * + * attr timer attributes or NULL to use default values + * + * Returns : timer ID for reference by other functions or NULL in case of error. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osTimerId_t osTimerNew(osTimerFunc_t func, + osTimerType_t type, + void *argument, + const osTimerAttr_t *attr) +{ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + osTimer_t *p_tmr; + const char *p_name; + + if (CORE_InIrqContext() == true) { + return (osTimerId_t)0; + } + + if (func == (osTimerFunc_t)0) { // Caller must specify a callback + return (osTimerId_t)0; + } + + p_name = "Timer"; + if (attr == NULL) { + p_tmr = (osTimer_t *)malloc(sizeof(osTimer_t)); + if (p_tmr == (osTimer_t *)0) { + return (osTimerId_t)0; + } + p_tmr->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_mem == (void *)0) { + p_tmr = (osTimer_t *)malloc(sizeof(osTimer_t)); + if (p_tmr == (osTimer_t *)0) { + return (osTimerId_t)0; + } + p_tmr->dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_size < sizeof(osTimer_t) || (uint32_t)attr->cb_mem % sizeof(CPU_ALIGN)) { + return (osTimerId_t)0; + } + p_tmr = (osTimer_t *)attr->cb_mem; + p_tmr->dyn_alloc = DEF_FALSE; + } + if (attr->name != (const char *)0) { + p_name = attr->name; + } + } + + p_tmr->type = type; + p_tmr->name = p_name; + p_tmr->callback = func; + p_tmr->callback_data = argument; + + return (osTimerId_t)p_tmr; +#else + (void)func; + (void)type; + (void)argument; + (void)attr; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, (osTimerId_t)0); + return (osTimerId_t)0; +#endif +} + +/* + **************************************************************************************************** + * osTimerGetName() + * + * Description: The function 'osTimerGetName()' returns the pointer to the name string of the timer + * identified by parameter 'timer_id' or NULL in case of an error. + * + * Arguments : timer_id is the timer ID returned by 'osTimerNew()' + * + * Returns : A pointer to the ASCII string containing the name of the timer. + * NULL upon error + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +const char *osTimerGetName(osTimerId_t timer_id) +{ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) && (OS_CFG_DBG_EN == DEF_ENABLED) + osTimer_t *p_tmr; + + if (CORE_InIrqContext() == true) { + return NULL; + } + p_tmr = (osTimer_t *)timer_id; + if (p_tmr == (osTimer_t *)0) { + return NULL; + } + + return p_tmr->name; +#else + (void)timer_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, NULL); + return NULL; +#endif +} + +/* + **************************************************************************************************** + * osTimerStart() + * + * Description: The function 'osTimerStart()' starts or restarts a timer specified by the parameter + * 'timer_id'. The parameter ticks specifies the value of the timer in time ticks. + * + * Arguments : timer_id is the timer ID returned by 'osTimerNew()' + * + * ticks is the one shot delay (osTimerOnce) or + * the period of timer repeat (osTimerPeriodic) + * + * Returns : osOK the specified timer has been started or restarted. + * osErrorISR osTimerStart() cannot be called from interrupt service routines. + * osErrorParameter parameter 'timer_id' is either NULL or invalid or ticks is incorrect. + * osErrorResource the timer is in an invalid state. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osTimerStart(osTimerId_t timer_id, + uint32_t ticks) +{ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + osTimer_t *p_tmr; + sl_status_t status; + uint32_t delay; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + if (ticks == 0u) { // Cannot be 0 ticks + return osErrorParameter; + } + + p_tmr = (osTimer_t *)timer_id; + + if (p_tmr == (osTimer_t *)0) { + return osErrorParameter; + } + + // Convert from OS tick to sleeptimer ticks + delay = (uint64_t)(((uint64_t)ticks * (uint64_t)sl_sleeptimer_get_timer_frequency()) + ((uint64_t)OSCfg_TickRate_Hz - 1u)) / OSCfg_TickRate_Hz; + + if (p_tmr->type == osTimerOnce) { + status = sl_sleeptimer_start_timer(&p_tmr->handle, delay, sleeptimer_callback, (void *)p_tmr, 0, 0); + } else { + status = sl_sleeptimer_start_periodic_timer(&p_tmr->handle, delay, sleeptimer_callback, (void *)p_tmr, 0, 0); + } + if (status == SL_STATUS_OK) { + return osOK; + } else { + return osErrorResource; + } + +#else + (void)timer_id; + (void)ticks; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osTimerStop() + * + * Description: The function 'osTimerStop()' stops the timer specified by the parameter 'timer_id'. + * + * Arguments : timer_id is the timer ID returned by 'osTimerNew()' + * + * Returns : osOK the specified timer has been stopped + * osErrorISR osTimerStop() cannot be called from interrupt service routines. + * osErrorParameter parameter 'timer_id' is either NULL or invalid or ticks is incorrect. + * osErrorResource the timer is in an invalid state. + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osTimerStop(osTimerId_t timer_id) +{ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + osTimer_t *p_tmr; + sl_status_t status; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_tmr = (osTimer_t *)timer_id; + if (p_tmr == (osTimer_t *)0) { + return osErrorParameter; + } + + status = sl_sleeptimer_stop_timer(&p_tmr->handle); + if (status == SL_STATUS_OK) { + return osOK; + } else { + return osErrorResource; + } + +#else + (void)timer_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osTimerIsRunning() + * + * Description: The function 'osTimerIsRunning()' checks whether a timer specified by parameter 'timer_id' + * is running. + * + * Arguments : timer_id is the timer ID returned by 'osTimerNew()' + * + * Returns : 1 if the timer is running + * 0 if stopped or an error occurs + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +uint32_t osTimerIsRunning(osTimerId_t timer_id) +{ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + osTimer_t *p_tmr; + sl_status_t status; + bool running; + + if (CORE_InIrqContext() == true) { + return 0u; + } + + p_tmr = (osTimer_t*)timer_id; + if (p_tmr == (osTimer_t*)0) { + return 0u; + } + + status = sl_sleeptimer_is_timer_running(&p_tmr->handle, &running); + + if (status != SL_STATUS_OK) { + return 0u; + } + + return (uint32_t)running; + +#else + (void)timer_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, 0u); + return 0u; +#endif +} + +/* + **************************************************************************************************** + * osTimerDelete() + * + * Description: The function 'osTimerDelete()' deletes the timer object specified by parameter 'timer_id'. + * + * Arguments : timer_id is the timer ID returned by 'osTimerNew()' + * + * Returns : osOK the timer object has been deleted. + * osErrorParameter the parameter timer_id is NULL or invalid. + * osErrorResource the timer is in an invalid state. + * osErrorISR osTimerDelete() cannot be called from interrupt service routines. + * + * + * Note(s) : 1) This function CANNOT be called from an ISR + **************************************************************************************************** + */ +osStatus_t osTimerDelete(osTimerId_t timer_id) +{ +#if defined CMSIS_RTOS2_TIMER_TASK_EN && (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) + osTimer_t *p_tmr; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_tmr = (osTimer_t *)timer_id; + if (p_tmr == (osTimer_t *)0) { + return osErrorParameter; + } + + sl_sleeptimer_stop_timer(&p_tmr->handle); + + if (p_tmr->dyn_alloc == DEF_TRUE) { + free(p_tmr); + } + return osOK; + +#else + (void)timer_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * M E M O R Y P O O L M A N A G E M E N T + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osMemoryPoolNew() + * + * Description: The function 'osMemoryPoolNew()' creates and initializes a memory pool object and returns + * the pointer to the memory pool object identifier or NULL in case of an error. + * + * It can be safely called before the RTOS is started (call to 'osKernelStart()'), but not + * before it is initialized (call to 'osKernelInitialize()'). + * + * Arguments : block_count maximum number of memory blocks in memory pool. + * block_size memory block size in bytes. + * attr memory pool attributes. If NULL, use default values. + * + * Returns : Memory Pool ID for reference by other functions or NULL in case of error. + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, + uint32_t block_size, + const osMemoryPoolAttr_t *attr) +{ + (void)block_count; + (void)block_size; + (void)attr; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, NULL); + return NULL; +} + +/* + **************************************************************************************************** + * osMemoryPoolGetName() + * + * Description: The function 'osMemoryPoolName()' returns the pointer to the name string of the memory + * pool identified by parameter 'mp_id' or NULL in case of an error. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * Returns : A pointer to the ASCII string containing the name of the memory pool. + * NULL upon error + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +const char * osMemoryPoolGetName(osMemoryPoolId_t mp_id) +{ + (void)mp_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, NULL); + return NULL; +} + +/* + **************************************************************************************************** + * osMemoryPoolAlloc() + * + * Description: The blocking function 'osMemoryPoolAlloc()' allocates the memory pool parameter 'mp_id' + * and returns a pointer to the address of the allocated memory or 0 in case of an error. + * + * The parameter 'timeout' specifies how long the system waits to allocate the memory. + * While the system waits, the thread that is calling this function is put into the + * BLOCKED state. The thread will become READY as soon as at least one block of memory + * gets available. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * timeout when timeout is 0, the function returns instantly (i.e. try semantics). + * when timeout is set to 'osWaitForever' the function will wait for an infinite + * time until the memory is allocated (i.e. wait semantics). + * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * + * Returns : The result is the pointer to the memory block allocated, or NULL if no memory is available. + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +void * osMemoryPoolAlloc(osMemoryPoolId_t mp_id, + uint32_t timeout) +{ + (void)mp_id; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, NULL); + return NULL; +} + +/* + **************************************************************************************************** + * osMemoryPoolFree() + * + * Description: The function 'osMemoryPoolFree()' frees the memory pool block specified by the parameter + * 'block' in the memory pool object specified by the parameter 'mp_id'. The memory block + * is put back to the list of available blocks. + * + * If another thread is waiting for memory to become available the thread is put to READY state. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * block address of the allocated memory block to be returned to the memory pool. + * + * Returns : osOK the memory has been freed. + * osErrorParameter parameter mp_id is NULL or invalid, block points to invalid memory. + * osErrorResource the memory pool is in an invalid state. + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, + void *block) +{ + (void)mp_id; + (void)block; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, NULL); + return osError; +} + +/* + **************************************************************************************************** + * osMemoryPoolGetCapacity() + * + * Description: The function 'osMemoryPoolGetCapacity()' returns the maximum number of memory blocks + * in the memory pool object specified by parameter 'mp_id' or 0 in case of an error. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * Returns : Maximum number of memory blocks + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id) +{ + (void)mp_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +} + +/* + **************************************************************************************************** + * osMemoryPoolGetBlockSize() + * + * Description: The function 'osMemoryPoolGetBlockSize()' returns the memory block size in bytes in + * the memory pool object specified by parameter 'mp_id' or 0 in case of an error. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * Returns : Size (in bytes) of each block + * 0 upon error + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id) +{ + (void)mp_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +} + +/* + **************************************************************************************************** + * osMemoryPoolGetCount() + * + * Description: The function 'osMemoryPoolGetCount()' returns the number of memory blocks used in the + * memory pool object specified by parameter 'mp_id' or 0 in case of an error. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * Returns : number of memory blocks used. + * 0 upon error + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id) +{ + (void)mp_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +} + +/* + **************************************************************************************************** + * osMemoryPoolGetSpace() + * + * Description: The function 'osMemoryPoolGetSpace()' returns the number of memory blocks available + * in the memory pool object specified by parameter 'mp_id' or 0 in case of an error. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * Returns : number of memory blocks available. + * 0 upon error + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id) +{ + (void)mp_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +} + +/* + **************************************************************************************************** + * osMemoryPoolDelete() + * + * Description: The function 'osMemoryPoolDelete()' deletes a memory pool object specified by parameter + * 'mp_id'. It releases internal memory obtained for memory pool handling. + * + * After this call, the 'mp_id' is no longer valid and cannot be used. The memory pool + * may be created again using the function 'osMemoryPoolNew()'. + * + * Arguments : mp_id is the memory pool ID returned by 'osMemoryPoolNew()' + * + * Returns : osOK the memory pool object has been deleted. + * osErrorParameter parameter mp_id is NULL or invalid. + * osErrorResource the memory pool is in an invalid state. + * osErrorISR 'osMemoryPoolDelete()' cannot be called from an ISR + * + * Note(s) : 1) MicriumOS DOES NOT support this functionality + **************************************************************************************************** + */ +osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id) +{ + (void)mp_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +} + +/* + **************************************************************************************************** + **************************************************************************************************** + * M E S S A G E Q U E U E M A N A G E M E N T + **************************************************************************************************** + **************************************************************************************************** + */ + +/* + **************************************************************************************************** + * osMessageQueueNew() + * + * Description: The function 'osMessageQueueNew()' creates and initializes a message queue object. + * The function returns a message queue object identifier or NULL in case of an error. + * + * The function can be called after kernel initialization with 'osKernelInitialize()'. + * It is possible to create message queue objects before the RTOS kernel is started with + * 'osKernelStart()'. + * + * The total amount of memory required for the message queue data is at least 'msg_count * msg_size'. + * The 'msg_size' is rounded up to a double even number to ensure 32-bit alignment of the memory blocks. + * + * The memory blocks allocated from the message queue have a fixed size defined with the parameter 'msg_size'. + * + * Arguments : msg_count is the maximum number of messages in the queue + * + * msg_size maximum message size (in bytes) + * + * attr attribute structure passed to the message queue creation code. + * specifying NULL assumes defaults. + * + * Message queue attributes are: + * + * .name name of the message queue + * .attr_bits reserved (should be 0) + * .cb_mem pointer to message queue control block + * (allocated dynamically if NULL or not specified) + * .cb_size size of the message queue control block (in bytes) + * .mq_mem pointer to storage of messages + * (allocated dynamically if NULL or not specified) + * .mq_size size of each message (in bytes) + * (the minimum is 'msg_count' * 'msg_size') + * + * Returns : The message queue ID upon success + * NULL upon error + **************************************************************************************************** + */ +osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, + uint32_t msg_size, + const osMessageQueueAttr_t *attr) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + CPU_CHAR *p_name; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return (osMessageQueueId_t)0; // Can't create a msgqueue from an ISR + } + if (msg_count == 0) { // Validate msg_count + return (osMessageQueueId_t)0; + } + if (msg_size == 0) { // Validate msg_size + return (osMessageQueueId_t)0; + } else { + msg_size = (msg_size + sizeof(CPU_ALIGN) - 1) & ~(sizeof(CPU_ALIGN) - 1); // Align to 4 bytes + } + p_name = (CPU_CHAR *)"QueueName?"; + if (attr == 0) { + p_msgqueue = (osMessageQueue_t *)malloc(sizeof(osMessageQueue_t)); + if (p_msgqueue == (osMessageQueue_t *)0) { + return (osMessageQueueId_t)0; + } else { + p_msgqueue->obj_dyn_alloc = DEF_TRUE; + p_msgqueue->buf = (uint8_t *) malloc(msg_size * msg_count); + if (p_msgqueue->buf == (uint8_t *)0) { + free(p_msgqueue); + return (osMessageQueueId_t)0; + } + p_msgqueue->buf_dyn_alloc = DEF_TRUE; + } + } else { + if (attr->cb_mem == (void *)0) { + p_msgqueue = (osMessageQueue_t *)malloc(sizeof(osMessageQueue_t)); + if (p_msgqueue == (osMessageQueue_t *)0) { + return (osMessageQueueId_t)0; + } + p_msgqueue->obj_dyn_alloc = DEF_TRUE; + } else { + if (attr->cb_size < sizeof(osMessageQueue_t) || (uint32_t)attr->cb_mem % sizeof(CPU_ALIGN)) { + return (osMessageQueueId_t)0; + } + p_msgqueue = attr->cb_mem; + p_msgqueue->obj_dyn_alloc = DEF_FALSE; + } + if (attr->mq_size == 0u) { + p_msgqueue->buf = (uint8_t *)malloc(msg_size * msg_count); + if (p_msgqueue->buf == (uint8_t *)0) { + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return (osMessageQueueId_t)0; + } + p_msgqueue->buf_dyn_alloc = DEF_TRUE; + } else if ((attr->mq_size != 0u) && (attr->mq_mem == NULL)) { + if (attr->mq_size < msg_size * msg_count) { + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return (osMessageQueueId_t)0; + } + p_msgqueue->buf = (uint8_t *)malloc(attr->mq_size); + if (p_msgqueue->buf == (uint8_t *)0) { + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return (osMessageQueueId_t)0; + } + p_msgqueue->buf_dyn_alloc = DEF_TRUE; + } else { + if (attr->mq_mem == NULL + || attr->mq_size < msg_size * msg_count + || (uint32_t)attr->mq_mem % sizeof(CPU_ALIGN)) { + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return (osMessageQueueId_t)0; + } + p_msgqueue->buf = (uint8_t *)attr->mq_mem; + p_msgqueue->buf_dyn_alloc = DEF_FALSE; + } + if (attr->name != (const char *)0) { + p_name = (CPU_CHAR *)attr->name; + } + } + p_msgqueue->msg_count = msg_count; + p_msgqueue->msg_size = msg_size; + p_msgqueue->msg_queued = 0; + p_msgqueue->msg_head = 0; + p_msgqueue->msg_tail = 0; + + OSSemCreate(&p_msgqueue->sem_put, p_name, msg_count, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_msgqueue->buf_dyn_alloc == DEF_TRUE) { + free(p_msgqueue->buf); + } + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return (osMessageQueueId_t)0; + } + + OSSemCreate(&p_msgqueue->sem_get, p_name, 0, &err); + + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + if (p_msgqueue->buf_dyn_alloc == DEF_TRUE) { + free(p_msgqueue->buf); + } + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return (osMessageQueueId_t)0; + } + + return (osMessageQueueId_t)p_msgqueue; +#else + (void) msg_count; + (void) msg_size; + (void) attr; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_AVAIL, (osMessageQueueId_t)0); + return (osMessageQueueId_t)0; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueGetName() + * + * Description: The function 'osMessageQueueGetName()' returns the pointer to the name string of the + * message queue identified by parameter 'mq_id' or NULL in case of an error. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : A pointer to the ASCII string containing the name of the mutex. + * NULL upon error + **************************************************************************************************** + */ +const char * osMessageQueueGetName(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) && (OS_CFG_DBG_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + + if (CORE_InIrqContext() == true) { + return NULL; + } + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return NULL; + } + + return p_msgqueue->sem_put.NamePtr; +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, NULL); + return NULL; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueuePut() + * + * Description: The blocking function 'osMessageQueuePut()' puts the message pointed to by 'msg_ptr' + * into the message queue specified by parameter 'mq_id'. + * + * The parameter 'msg_prio' is used to sort message according their priority + * (higher numbers indicate a higher priority) on insertion. + * + * The parameter 'timeout' specifies how long the system waits to put the message into + * the queue. While the system waits, the thread that is calling this function is put + * into the BLOCKED state. The parameter timeout can have the following values: + * + * when timeout is 0, the function returns instantly (i.e. try semantics). + * when timeout is set to osWaitForever the function will wait for an infinite time + * until the message is delivered (i.e. wait semantics). + * all other values specify a time in kernel ticks for a timeout (i.e. timed-wait semantics). + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * msg_ptr pointer to message to send + * + * msg_prio priority of message sent + * + * timeout when timeout is 0, the function returns instantly (i.e. try semantics). + * when timeout is set to 'osWaitForever()' the function will wait for an + * infinite time until the message is delivered (i.e. wait semantics). + * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * + * Returns : osOK the message has been put in the queue + * osErrorTimeout the message could not be put into the queue within the timeout specified + * osErrorParameter the parameter 'mq_id' is NULL or invalid. + * osErrorResource not enough space in the queue + **************************************************************************************************** + */ +osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, + const void *msg_ptr, + uint8_t msg_prio, + uint32_t timeout) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + CPU_TS ts; + OS_ERR err; + uint32_t msg_id, msg_size; + CORE_DECLARE_IRQ_STATE; + + (void) msg_prio; + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return osErrorParameter; + } + + if (timeout == 0u) { + OSSemPend(&p_msgqueue->sem_put, (OS_TICK)0u, OS_OPT_PEND_NON_BLOCKING, &ts, &err); + } else { + if (CORE_InIrqContext() == true) { + return osErrorParameter; + } else { + OSSemPend(&p_msgqueue->sem_put, (OS_TICK)timeout, OS_OPT_PEND_BLOCKING, &ts, &err); + } + } + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + break; + + case OS_ERR_TIMEOUT: + return osErrorTimeout; + + default: + return osErrorResource; + } + + CORE_ENTER_ATOMIC(); + msg_id = p_msgqueue->msg_head; + msg_size = p_msgqueue->msg_size; + p_msgqueue->msg_head = (p_msgqueue->msg_head + 1) % p_msgqueue->msg_count; + memcpy(&p_msgqueue->buf[msg_id * msg_size], msg_ptr, msg_size); + p_msgqueue->msg_queued++; + CORE_EXIT_ATOMIC(); + + OSSemPost(&p_msgqueue->sem_get, OS_OPT_POST_1, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +#else + (void)mq_id; + (void)msg_ptr; + (void)msg_prio; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueGet() + * + * Description: The function 'osMessageQueueGet()' retrieves a message from the message queue specified + * by the parameter 'mq_id' and saves it to the buffer pointed to by the parameter 'msg_ptr'. + * + * The message priority is stored to parameter 'msg_prio' if not token{NULL}. + * + * The parameter 'timeout' specifies how long the system waits to retrieve the message from + * the queue. While the system waits, the thread that is calling this function is put into + * the BLOCKED state. The parameter 'timeout' can have the following values: + * + * + * + * + * Arguments : mq_id the message queue ID + * + * msg_ptr a pointer to where the message will be placed + * + * msg_prio a pointer to where the message priority will be deposited to. + * + * timeout when timeout is 0, the function returns instantly (i.e. try semantics). + * + * when timeout is set to 'osWaitForever' the function will wait for an infinite + * time until the message is retrieved (i.e. wait semantics). + * + * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * + * Returns : osOK the message has been retrieved from the queue. + * osErrorTimeout the message could not be retrieved from the queue in the given time + * (timed-wait semantics). + * osErrorResource nothing to get from the queue (try semantics). + * osErrorParameter parameter 'mq_id' is NULL or invalid, non-zero timeout specified in an ISR. + **************************************************************************************************** + */ +osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, + void *msg_ptr, + uint8_t *msg_prio, + uint32_t timeout) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + CPU_TS ts; + OS_ERR err; + uint32_t msg_id, msg_size; + CORE_DECLARE_IRQ_STATE; + + (void) msg_prio; + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return osErrorParameter; + } + + if (timeout == 0u) { + OSSemPend(&p_msgqueue->sem_get, (OS_TICK)0u, OS_OPT_PEND_NON_BLOCKING, &ts, &err); + } else { + if (CORE_InIrqContext() == true) { + return osErrorParameter; + } else { + OSSemPend(&p_msgqueue->sem_get, (OS_TICK)timeout, OS_OPT_PEND_BLOCKING, &ts, &err); + } + } + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + break; + + case OS_ERR_TIMEOUT: + return osErrorTimeout; + + default: + return osErrorResource; + } + + CORE_ENTER_ATOMIC(); + msg_id = p_msgqueue->msg_tail; + msg_size = p_msgqueue->msg_size; + p_msgqueue->msg_tail = (p_msgqueue->msg_tail + 1) % p_msgqueue->msg_count; + memcpy(msg_ptr, &p_msgqueue->buf[msg_id * msg_size], msg_size); + p_msgqueue->msg_queued--; + if (msg_prio != NULL) { + *msg_prio = 0; + } + CORE_EXIT_ATOMIC(); + + OSSemPost(&p_msgqueue->sem_put, OS_OPT_POST_1, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +#else + (void)mq_id; + (void)msg_ptr; + (void)msg_prio; + (void)timeout; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueGetCapacity() + * + * Description: The function 'osMessageQueueGetCapacity()' returns the maximum number of messages in + * the message queue object specified by parameter 'mq_id' or 0 in case of an error. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : The maximum number of messages + * 0 upon error + **************************************************************************************************** + */ +uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return 0; + } + + return p_msgqueue->msg_count; +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueGetMsgSize() + * + * Description: The function 'osMessageQueueGetMsgSize()' returns the maximum message size in bytes + * for the message queue object specified by parameter 'mq_id' or 0 in case of an error. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : The maximum message size (in bytes) + * 0 upon error + **************************************************************************************************** + */ +uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return 0; + } + + return p_msgqueue->msg_size; +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueGetCount() + * + * Description: The function 'osMessageQueueGetCount()' returns the number of queued messages in the + * message queue object specified by parameter 'mq_id' or 0 in case of an error. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : The number of messages in the queue + * 0 upon error + **************************************************************************************************** + */ +uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return 0; + } + + return p_msgqueue->msg_queued; +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueGetSpace() + * + * Description: The function 'osMessageQueueGetSpace()' returns the number available slots for messages + * in the message queue object specified by parameter 'mq_id' or 0 in case of an error. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : The number of available slots in the queue + * 0 upon error + **************************************************************************************************** + */ +uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return 0; + } + + return p_msgqueue->msg_count - p_msgqueue->msg_queued; +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, 0); + return 0; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueReset() + * + * Description: The function 'osMessageQueueReset()' resets the message queue specified by the parameter + * 'mq_id'. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : osOK the queue has been reset + * osErrorParameter parameter 'mq_id' is NULL or invalid. + * osErrorResource the message queue is in an invalid state. + * osErrorISR 'osMessageQueueReset()' cannot be called from interrupt service routines. + **************************************************************************************************** + */ +osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + CPU_TS ts; + OS_ERR err; + CORE_DECLARE_IRQ_STATE; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return osErrorParameter; + } + + while (p_msgqueue->msg_queued != 0) { + OSSemPend(&p_msgqueue->sem_get, (OS_TICK)0u, OS_OPT_PEND_BLOCKING, &ts, &err); + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + break; + } + CORE_ENTER_ATOMIC(); + p_msgqueue->msg_queued--; + p_msgqueue->msg_tail = (p_msgqueue->msg_tail + 1) % p_msgqueue->msg_count; + CORE_EXIT_ATOMIC(); + OSSemPost(&p_msgqueue->sem_put, OS_OPT_POST_1, &err); + if (RTOS_ERR_CODE_GET(err) != OS_ERR_NONE) { + break; + } + } + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + return osOK; + + default: + return osErrorResource; + } +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +#endif +} + +/* + **************************************************************************************************** + * osMessageQueueDelete() + * + * Description: The function 'osMessageQueueDelete() deletes a message queue object specified by + * parameter 'mq_id'. It releases internal memory obtained for message queue handling. + * + * After this call, the 'mq_id' is no longer valid and cannot be used. + * + * The message queue may be created again using the function 'osMessageQueueNew()'. + * + * Arguments : mq_id is the message queue ID returned by 'osMessageQueueNew()' + * + * Returns : osOK the message queue object has been deleted. + * osErrorParameter parameter 'mq_id' is NULL or invalid. + * osErrorResource the message queue is in an invalid state. + * osErrorISR 'osMessageQueueDelete()' cannot be called from interrupt service routines. + **************************************************************************************************** + */ +osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id) +{ +#if (OS_CFG_SEM_EN == DEF_ENABLED) + osMessageQueue_t *p_msgqueue; + OS_ERR err; + + if (CORE_InIrqContext() == true) { + return osErrorISR; + } + + p_msgqueue = (osMessageQueue_t *)mq_id; + if (p_msgqueue == (osMessageQueue_t *)0) { + return osErrorParameter; + } + + OSSemDel(&p_msgqueue->sem_put, OS_OPT_DEL_ALWAYS, &err); + OSSemDel(&p_msgqueue->sem_get, OS_OPT_DEL_ALWAYS, &err); + + switch (RTOS_ERR_CODE_GET(err)) { + case OS_ERR_NONE: + if (p_msgqueue->buf_dyn_alloc == DEF_TRUE) { + free(p_msgqueue->buf); + } + if (p_msgqueue->obj_dyn_alloc == DEF_TRUE) { + free(p_msgqueue); + } + return osOK; + + default: + return osErrorResource; + } +#else + (void)mq_id; + RTOS_ASSERT_CRITICAL(DEF_FALSE, RTOS_ERR_NOT_SUPPORTED, osError); + return osError; +#endif +} diff --git a/middleware/CMSIS/RTOS2/MicriumOS/include/rtos_utils_priv.h b/middleware/CMSIS/RTOS2/MicriumOS/include/rtos_utils_priv.h new file mode 100644 index 000000000..2e8707c17 --- /dev/null +++ b/middleware/CMSIS/RTOS2/MicriumOS/include/rtos_utils_priv.h @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/***************************************************************************//** + * @file + * @brief Common - Rtos Utilities + ******************************************************************************* + * # License + * Copyright 2018 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * The licensor of this software is Silicon Laboratories Inc. Your use of this + * software is governed by the terms of Silicon Labs Master Software License + * Agreement (MSLA) available at + * www.silabs.com/about-us/legal/master-software-license-agreement. This + * software is distributed to you in Source Code format and is governed by the + * sections of the MSLA applicable to Source Code. + * + ******************************************************************************/ + +/******************************************************************************************************** + ******************************************************************************************************** + * MODULE + ******************************************************************************************************** + *******************************************************************************************************/ + +#ifndef _RTOS_UTILS_PRIV_H_ +#define _RTOS_UTILS_PRIV_H_ + + +/******************************************************************************************************** + ******************************************************************************************************** + * DEFINES + ******************************************************************************************************** + *******************************************************************************************************/ + +#define RTOS_ASSERT_DBG_FAILED_END_CALL(ret_val) while (1) { ; } +#define RTOS_ASSERT_CRITICAL_FAILED_END_CALL(ret_val) CPU_SW_EXCEPTION(ret_val) + +#define RTOS_ERR_CODE_GET(err_var) (err_var) +#define RTOS_ERR_SET(err_var, err_code) (err_var) = (err_code) + +#define RTOS_ERR_NOT_AVAIL -1 +#define RTOS_ERR_NOT_SUPPORTED -2 + + +/******************************************************************************************************** + * ARG CHK DEFINES + *******************************************************************************************************/ + +#define RTOS_ARG_CHK_EXT_EN (DEF_BIT_IS_SET_ANY(RTOS_CFG_ASSERT_DBG_ARG_CHK_EXT_MASK, (RTOS_MODULE_CUR))) + +/******************************************************************************************************** + * EXT ERR DEFINES + *******************************************************************************************************/ + +/****************************************************************************************************//** + * RTOS_ERR_CODE_LOG_ARG_GET() + * + * @brief Returns logging argument corresponding to the given error code. The logging argument is + * either a string or an integer depending on whether the error strings are enabled or not. + * + * @param err_code Error code to generate logging argument from. + * + * @return Log argument for error code. + *******************************************************************************************************/ + +#define RTOS_ERR_CODE_LOG_ARG_GET(err_code) (u)(err_code) + +/****************************************************************************************************//** + * RTOS_ERR_LOG_ARG_GET() + * + * @brief Returns logging argument corresponding to the given error (extended or not depending on + * extended error configuration). The logging argument is either a string or an integer + * depending on whether the error strings are enabled or not. + * + * @param err_var Error (of type RTOS_ERR) to generate logging argument from. + * + * @return Log argument for error variable. + *******************************************************************************************************/ + +#define RTOS_ERR_LOG_ARG_GET(err_var) RTOS_ERR_CODE_LOG_ARG_GET(RTOS_ERR_CODE_GET((err_var))) + +/******************************************************************************************************** + * LOG_SYNC() / LOG_ASYNC() + * + * Description : Synchronously/asynchronously write message through an associated output function. Expands + * to an output function call preceded by a compile time argument checking. + * + * Argument(s) : __VA_ARGS__ List of print variables (see LOG_ERR()/LOG_DBG()/LOG_VRB()). + * + * Note(s) : See LOG_ERR()/LOG_DBG()/LOG_VRB(). + *******************************************************************************************************/ + +#define LOG_SYNC(output_func, arg) + +#define LOG_ASYNC(output_func, arg) + +#define PP_SCAN(...) __VA_ARGS__ + +/******************************************************************************************************** + * ASSERT LOGGING DEFINES + ******************************************************************************************************** + * Note(s) : (1) The assert logging is handled differently than the others, since it MUST output its + * information directly and the event CANNOT be posted in queue, since a CPU_SW_EXCEPTION + * will be triggered right after the log. It also includes additional info (file, line, + * function) that may not be required by all other logging events. + *******************************************************************************************************/ + +#define RTOS_ASSERT_ERR_CODE_FAIL_LOG(expr, err_code) LOG_SYNC(_LOG_CH_CFG_EFFECTIVE_OUTPUT_FUNC_GET(PP_SCAN LOG_DFLT_CH), \ + ("Assert ", #expr, \ + " failed in file ", __FILE__, \ + " at line ", (d)__LINE__, \ + " in function ", (s) & __func__[0], \ + ". Reported error is : ", RTOS_ERR_CODE_LOG_ARG_GET((err_code)))); + +#if (RTOS_ERR_CFG_EXT_EN == DEF_DISABLED) + + #define RTOS_ASSERT_ERR_VAR_FAIL_LOG(expr, err_var) RTOS_ASSERT_ERR_CODE_FAIL_LOG(expr, RTOS_ERR_CODE_GET((err_var))) + +#else + + #define RTOS_ASSERT_ERR_VAR_FAIL_LOG(expr, err_var) LOG_SYNC(_LOG_CH_CFG_EFFECTIVE_OUTPUT_FUNC_GET(PP_SCAN LOG_DFLT_CH), \ + ("Assert ", #expr, \ + " failed due to err: ", RTOS_ERR_LOG_ARG_GET((err_var)), \ + ", coming from file ", (s)err_var.FileName, \ + " at line ", (d)err_var.LineNbr, \ + " in function ", (s)err_var.FnctName)); + +#endif + +/******************************************************************************************************** + * ASSERT DEFINES + ******************************************************************************************************** + * Note(s) : (1) The macros have been done so that they could be overridden with as much flexibility as + * possible. The default behavior is the same for every level of assertion, the notes below + * indicate how to override for each level. + * + * (a) Overriding the RTOS_ASSERT_{DBG|CRITICAL} macro will have an impact for that level + * (either DBG or CRITICAL) only. + * + * (2) The macro RTOS_ASSERT_DBG_ERR_PTR_VALIDATE has a different behavior, since no error can + * be reported if error pointer passed to function is NULL. In that case, a CPU_SW_EXCEPTION + * is ALWAYS executed. + * + * (3) The 'ret_val' parameter cannot have parentheses added to it when receiving it as a + * parameter, since in the case of a void return value, ';' is given as parameter, to be + * directly added after a potential 'return' call. + *******************************************************************************************************/ + +/******************************************************************************************************** + * RTOS_ASSERT_CRITICAL / RTOS_ASSERT_DBG + * + * Description : Assert given expression. In case of failure, log error, and call corresponding + * RTOS_ASSERT_xxx_FAILED_END_CALL(ret_val). + * + * Argument(s) : expr Expression to assert. If expression is false, the error will be logged, and + * the error caught call made. + * + * err_code Error code associated with assert. + * + * ret_val Value that would be returned from the function, ';' if void. + * + * Return(s) : none. + * + * Note(s) : (1) Usage of assert is as follows: + * RTOS_ASSERT_CRITICAL((p_buf != DEF_NULL), RTOS_ERR_NULL_PTR, DEF_NULL); + * RTOS_ASSERT_DBG((p_buf != DEF_NULL), RTOS_ERR_NULL_PTR, DEF_FAIL); + *******************************************************************************************************/ + +#define RTOS_ASSERT_CRITICAL(expr, err_code, ret_val) RTOS_ASSERT_CRITICAL_EXEC(expr, ret_val, \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG(expr, (err_code)); \ + ) + +#define RTOS_ASSERT_DBG(expr, err_code, ret_val) RTOS_ASSERT_DBG_EXEC(expr, ret_val, \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG(expr, (err_code)); \ + ) + +/****************************************************************************************************//** + * RTOS_ASSERT_DBG_ERR_PTR_VALIDATE() + * + * @brief Validate an error pointer received, to see if it can be used to report an error. + * + * @param p_err Error pointer to validate. + * + * @param ret_val Value that would be returned from the function, ';' if void. + * + * @note (1) Since no error can be reported if the error pointer is NULL, a CPU_SW_EXCEPTION is + * ALWAYS executed if this assert fails. See ASSERT DEFINES's Note #2. + * + * @note (2) Usage of RTOS_ASSERT_DBG_ERR_PTR_VALIDATE is as follows: + * RTOS_ASSERT_DBG_ERR_PTR_VALIDATE(p_err, ;); The error will be RTOS_ERR_ASSERT_ERR_PTR_NULL. + * RTOS_ASSERT_DBG_ERR_PTR_VALIDATE(p_err, DEF_NULL); The error will be RTOS_ERR_ASSERT_ERR_PTR_NULL. + *******************************************************************************************************/ + +#define RTOS_ASSERT_DBG_ERR_PTR_VALIDATE(p_err, ret_val) if (RTOS_ARG_CHK_EXT_EN) { \ + if ((p_err) == DEF_NULL) { \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG((p_err == DEF_NULL), RTOS_ERR_ASSERT_ERR_PTR_NULL); \ + CPU_SW_EXCEPTION(ret_val); \ + } \ +} + +/****************************************************************************************************//** + * RTOS_ASSERT_CRITICAL_ERR_SET() / RTOS_ASSERT_DBG_ERR_SET() + * + * @brief Assert given expression. In case of failure, log, set error and call + * RTOS_ASSERT_FAILED_END_CALL(ret_val). + * + * @param expr Expression to assert. If expression is false, the error will be logged, set + * and the error caught call made. + * + * @param err_var Error variable to set. + * + * @param err_code Error code to log and set 'err_var' to. + * + * @param ret_val Value that would be returned from the function, ';' if void. + * + * @note (1) Usage of RTOS_ASSERT_CRITICAL_ERR_SET / RTOS_ASSERT_DBG_ERR_SET / + * RTOS_ASSERT_CRITICAL_ERR_PTR_SET / RTOS_ASSERT_DBG_ERR_PTR_SETis as follows: + * RTOS_ASSERT_CRITICAL_ERR_SET((p_buf != DEF_NULL), local_err, RTOS_ERR_NULL_PTR, ;); + * RTOS_ASSERT_DBG_ERR_SET((p_arg != DEF_NULL), local_err, RTOS_ERR_NULL_PTR, DEF_NULL); + *******************************************************************************************************/ + +#define RTOS_ASSERT_CRITICAL_ERR_SET(expr, err_var, err_code, ret_val) RTOS_ASSERT_CRITICAL_EXEC(expr, ret_val, \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG(expr, (err_code)); \ + RTOS_ERR_SET((err_var), (err_code)); \ + ) + +#define RTOS_ASSERT_DBG_ERR_SET(expr, err_var, err_code, ret_val) RTOS_ASSERT_DBG_EXEC(expr, ret_val, \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG(expr, (err_code)); \ + RTOS_ERR_SET((err_var), (err_code)); \ + ) + +/******************************************************************************************************** + * RTOS_DBG_FAIL_EXEC + * RTOS_CRITICAL_FAIL_EXEC + * + * Description : Checks if assert is enabled for current module, logs error and calls END_CALL as + * configured by user. + * + * Argument(s) : err_code Error code to log. + * + * ret_val Value that would be returned from the function, ';' if void. + * + * Return(s) : none. + * + * Note(s) : none. + *******************************************************************************************************/ + +#define RTOS_DBG_FAIL_EXEC(err_code, ret_val) RTOS_ASSERT_DBG_EXEC(0, ret_val, \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG((no condition), (err_code)); \ + ) + +#define RTOS_CRITICAL_FAIL_EXEC(err_code, ret_val) RTOS_ASSERT_ERR_CODE_FAIL_LOG((no condition), (err_code)); \ + RTOS_ASSERT_CRITICAL_FAILED_END_CALL(ret_val); \ + + +/******************************************************************************************************** + * RTOS_DBG_FAIL_EXEC_ERR + * + * Description : Checks if assert is enabled for current module, logs and sets error and calls END_CALL as + * configured by user. + * + * Argument(s) : err_var Error variable to set. + * + * err_code Error code to log and set 'err_var' to. + * + * ret_val Value that would be returned from the function, ';' if void. + * + * Return(s) : none. + * + * Note(s) : none. + *******************************************************************************************************/ + +#define RTOS_DBG_FAIL_EXEC_ERR(err_var, err_code, ret_val) RTOS_ASSERT_DBG_EXEC(0, ret_val, \ + RTOS_ASSERT_ERR_CODE_FAIL_LOG((no condition), (err_code)); \ + RTOS_ERR_SET((err_var), (err_code)); \ + ) + +/******************************************************************************************************** + * RTOS_ASSERT_CRITICAL_EXEC / RTOS_ASSERT_DBG_EXEC + * + * Description : Checks if assert is enabled for current module, tests the assertion, executes the failure + * operation(s) if assert failed and calls END_CALL as configured by user. + * + * Argument(s) : expr Expression to assert. If expression is false, the error will be logged, set + * and the error caught call made. + * + * ret_val Value that would be returned from the function, ';' if void. + * + * fail_oper Operation(s) to execute in case of failure. + * + * Return(s) : none. + * + * Note(s) : (1) These macros MUST not be used by anything else than higher-level assert macros. + *******************************************************************************************************/ + +#define RTOS_ASSERT_CRITICAL_EXEC(expr, ret_val, fail_oper) if ((expr) == 0u) { \ + fail_oper \ + RTOS_ASSERT_CRITICAL_FAILED_END_CALL(ret_val); \ +} + +#define RTOS_ASSERT_DBG_EXEC(expr, ret_val, fail_oper) if (RTOS_ARG_CHK_EXT_EN) { \ + if ((expr) == 0u) { \ + fail_oper \ + RTOS_ASSERT_DBG_FAILED_END_CALL(ret_val); \ + } \ +} + +/******************************************************************************************************** + ******************************************************************************************************** + * MODULE END + ******************************************************************************************************** + *******************************************************************************************************/ + +#endif // End of rtos utils priv module include. diff --git a/middleware/CMSIS/RTOS2/MicriumOS/include/sl_cmsis_os2_common.h b/middleware/CMSIS/RTOS2/MicriumOS/include/sl_cmsis_os2_common.h new file mode 100644 index 000000000..9e5e65ce2 --- /dev/null +++ b/middleware/CMSIS/RTOS2/MicriumOS/include/sl_cmsis_os2_common.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/***************************************************************************//** + * @file sl_cmsis_os2_common.h + * @brief OS-agnostic header to provide CMSIS OS-Specific APIs like typedefs. + * @version x.y.z + ******************************************************************************* + * # License + * Copyright 2020 Silicon Laboratories Inc. www.silabs.com + ******************************************************************************* + * + * SPDX-License-Identifier: Zlib + * + * The licensor of this software is Silicon Laboratories Inc. + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. + * + ******************************************************************************/ + +#ifndef SL_CMSIS_OS2_COMMON_H +#define SL_CMSIS_OS2_COMMON_H + +#include + +#define SL_CATALOG_MICRIUMOS_KERNEL_PRESENT + +// Validate the chosen RTOS +#if !defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && !defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) +#error "The extended CMSIS RTOS2 API currently only supports FreeRTOS or MicriumOS" +#endif + +#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) +#include "FreeRTOS.h" +#elif defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) +#include "os.h" +#if (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) +// needed for osTimer_t struct +#include "cmsis_os2.h" +#endif +#endif + +#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) + +#define osEventFlagsCbSize sizeof(StaticEventGroup_t) +#define osThreadCbSize sizeof(StaticTask_t) +#define osTimerCbSize sizeof(StaticTimer_t) +#define osMutexCbSize sizeof(StaticSemaphore_t) +#define osSemaphoreCbSize sizeof(StaticSemaphore_t) +#define osMessageQueueCbSize sizeof(StaticQueue_t) +#define osAlignment (portBYTE_ALIGNMENT) + +typedef StaticEventGroup_t osEventFlags_t; +typedef StaticTask_t osThread_t; +typedef StaticTimer_t osTimer_t; +typedef StaticSemaphore_t osMutex_t; +typedef StaticSemaphore_t osSemaphore_t; +typedef StaticQueue_t osMessageQueue_t; + +#elif defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) + +typedef struct { + OS_TCB tcb; // This must be the first element, used by OSTCBCurPtr +#if (OS_CFG_FLAG_EN == DEF_ENABLED) + OS_FLAG_GRP flag_grp; +#endif +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) + OS_MUTEX join_mutex; +#endif + uint8_t obj_dyn_alloc; + uint8_t stack_dyn_alloc; + uint32_t attr_bits; +} osThread_t; + +#if (CMSIS_RTOS2_TIMER_TASK_EN == DEF_ENABLED) +typedef struct { + sl_sleeptimer_timer_handle_t handle; + osTimerFunc_t callback; + void *callback_data; + osTimerType_t type; + const char *name; + uint8_t dyn_alloc; +} osTimer_t; +#endif + +#if (OS_CFG_FLAG_EN == DEF_ENABLED) +typedef struct { + OS_FLAG_GRP flag_grp; + uint8_t dyn_alloc; + uint32_t flags; +} osEventFlags_t; +#endif + +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) +typedef struct { + OS_MUTEX mutex; + uint8_t dyn_alloc; + uint8_t recursive; +} osMutex_t; +#endif + +#if (OS_CFG_SEM_EN == DEF_ENABLED) +typedef struct { + OS_SEM sem; + uint8_t dyn_alloc; + uint32_t max_ctr; +} osSemaphore_t; +#endif + +#if (OS_CFG_SEM_EN == DEF_ENABLED) +typedef struct { + OS_SEM sem_put; + OS_SEM sem_get; + uint8_t *buf; + uint8_t obj_dyn_alloc; + uint8_t buf_dyn_alloc; + uint32_t msg_count; + uint32_t msg_size; + uint32_t msg_queued; + uint32_t msg_head; + uint32_t msg_tail; +} osMessageQueue_t; +#endif + +#if (OS_CFG_SEM_EN == DEF_ENABLED) +typedef struct { + OS_SEM sem; + uint8_t *buf; + uint8_t obj_dyn_alloc; + uint8_t buf_dyn_alloc; + uint32_t block_count; + uint32_t block_size; + uint32_t free_count; + uint32_t free_head; +} osMemoryPool_t; +#endif + +#if (OS_CFG_FLAG_EN == DEF_ENABLED) +#define osEventFlagsCbSize sizeof(osEventFlags_t) +#endif + +#define osThreadCbSize sizeof(osThread_t) + +#if (OS_CFG_TMR_EN == DEF_ENABLED) +#define osTimerCbSize sizeof(osTimer_t) +#endif + +#if (OS_CFG_MUTEX_EN == DEF_ENABLED) +#define osMutexCbSize sizeof(osMutex_t) +#endif + +#if (OS_CFG_SEM_EN == DEF_ENABLED) +#define osSemaphoreCbSize sizeof(osSemaphore_t) +#endif + +#if (OS_CFG_SEM_EN == DEF_ENABLED) +#define osMessageQueueCbSize sizeof(osMessageQueue_t) +#endif + +#if (OS_CFG_SEM_EN == DEF_ENABLED) +#define osMemoryPoolCbSize sizeof(osMemoryPool_t) +#endif + +#define osAlignment sizeof(CPU_ALIGN) + +#endif // SL_CATALOG_MICRIUMOS_KERNEL_PRESENT + +#endif // SL_CMSIS_OS2_COMMON_H diff --git a/middleware/CMSIS/RTOS2/README_en.md b/middleware/CMSIS/RTOS2/README_en.md new file mode 100644 index 000000000..320bd087f --- /dev/null +++ b/middleware/CMSIS/RTOS2/README_en.md @@ -0,0 +1,63 @@ +# CMSIS-RTOS2 API Supported In HPM_SDK + +## FreeRTOS + +| Feature | Supported | Short Description | +|-------------------------------|------------|------------------------------| +|Kernel Information and Control | Y | It provide version/system information and starts/controls the RTOS Kernel. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__KernelCtrl.html) | +|Thread Management | Y | It define, create, and control thread functions.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadMgmt.html) | +|Thread Flags | Y | It synchronize threads using flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadFlagsMgmt.html) | +|Event Flags | Y | It synchronize threads using event flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__EventFlags.html) | +|Generic Wait Functions | Y | It wait for a certain period of time.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Wait.html) | +|Timer Management | Y | It create and control timer and timer callback functions. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__TimerMgmt.html) | +|Mutex Management | Y | It synchronize resource access using Mutual Exclusion (Mutex). [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__MutexMgmt.html) | +|Semaphores | Y | It access shared resources simultaneously from different threads. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html) | +|Memory Pool | Y | It manage thread-safe fixed-size blocks of dynamic memory. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__PoolMgmt.html) | +|Message Queue | Y | It exchange messages between threads in a FIFO-like operation. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Message.html) | + + +## RTThread + +| Feature | Supported | Short Description | +|-------------------------------|------------|------------------------------| +|Kernel Information and Control | Y | It provide version/system information and starts/controls the RTOS Kernel. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__KernelCtrl.html) | +|Thread Management | Y | It define, create, and control thread functions.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadMgmt.html) | +|Thread Flags | Y | It synchronize threads using flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadFlagsMgmt.html) | +|Event Flags | Y | It synchronize threads using event flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__EventFlags.html) | +|Generic Wait Functions | Y | It wait for a certain period of time.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Wait.html) | +|Timer Management | Y | It create and control timer and timer callback functions. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__TimerMgmt.html) | +|Mutex Management | Y | It synchronize resource access using Mutual Exclusion (Mutex). [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__MutexMgmt.html) | +|Semaphores | Y | It access shared resources simultaneously from different threads. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html) | +|Memory Pool | Y | It manage thread-safe fixed-size blocks of dynamic memory. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__PoolMgmt.html) | +|Message Queue | Y | It exchange messages between threads in a FIFO-like operation. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Message.html) | + + +## ThreadX + +| Feature | Supported | Short Description | +|-------------------------------|------------|------------------------------| +|Kernel Information and Control | Y | It provide version/system information and starts/controls the RTOS Kernel. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__KernelCtrl.html) | +|Thread Management | Y | It define, create, and control thread functions.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadMgmt.html) | +|Thread Flags | N | It synchronize threads using flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadFlagsMgmt.html) | +|Event Flags | Y | It synchronize threads using event flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__EventFlags.html) | +|Generic Wait Functions | Y | It wait for a certain period of time.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Wait.html) | +|Timer Management | Y | It create and control timer and timer callback functions. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__TimerMgmt.html) | +|Mutex Management | Y | It synchronize resource access using Mutual Exclusion (Mutex). [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__MutexMgmt.html) | +|Semaphores | Y | It access shared resources simultaneously from different threads. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html) | +|Memory Pool | Y | It manage thread-safe fixed-size blocks of dynamic memory. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__PoolMgmt.html) | +|Message Queue | Y | It exchange messages between threads in a FIFO-like operation. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Message.html) | + +## MicriumOS(ucOS-III) + +| Feature | Supported | Short Description | +|-------------------------------|------------|------------------------------| +|Kernel Information and Control | Y | It provide version/system information and starts/controls the RTOS Kernel. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__KernelCtrl.html) | +|Thread Management | Y | It define, create, and control thread functions.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadMgmt.html) | +|Thread Flags | Y | It synchronize threads using flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__ThreadFlagsMgmt.html) | +|Event Flags | Y | It synchronize threads using event flags. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__EventFlags.html) | +|Generic Wait Functions | Y | It wait for a certain period of time.. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Wait.html) | +|Timer Management | N | It create and control timer and timer callback functions. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__TimerMgmt.html) | +|Mutex Management | Y | It synchronize resource access using Mutual Exclusion (Mutex). [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__MutexMgmt.html) | +|Semaphores | Y | It access shared resources simultaneously from different threads. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__SemaphoreMgmt.html) | +|Memory Pool | N | It manage thread-safe fixed-size blocks of dynamic memory. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__PoolMgmt.html) | +|Message Queue | Y | It exchange messages between threads in a FIFO-like operation. [More...](https://www.keil.com/pack/doc/cmsis/RTOS2/html/group__CMSIS__RTOS__Message.html) | diff --git a/middleware/CMSIS/RTOS2/RTThread/CMakeLists.txt b/middleware/CMSIS/RTOS2/RTThread/CMakeLists.txt new file mode 100644 index 000000000..e51f53c9b --- /dev/null +++ b/middleware/CMSIS/RTOS2/RTThread/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2023 HPMicro +# SPDX-License-Identifier: BSD-3-Clause + +sdk_inc(.) +sdk_src(cmsis_rtthread.c) diff --git a/middleware/CMSIS/RTOS2/RTThread/cmsis_rtthread.c b/middleware/CMSIS/RTOS2/RTThread/cmsis_rtthread.c new file mode 100644 index 000000000..a3c797599 --- /dev/null +++ b/middleware/CMSIS/RTOS2/RTThread/cmsis_rtthread.c @@ -0,0 +1,2080 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-04-12 misonyo the first version + * 2019-04-04 misonyo fix some bugs + * 2023-12-18 zhihongchen fix some bugs + */ + +#include "cmsis_rtthread.h" +#include +#include "hpm_soc.h" +#include "hpm_mchtmr_drv.h" +#include "hpm_clock_drv.h" + +///< RT-Thread Kernel version +#define KERNEL_VERSION (((rt_uint32_t)RT_VERSION * 10000000UL) | \ + ((rt_uint32_t)RT_SUBVERSION * 10000UL) | \ + ((rt_uint32_t)RT_REVISION * 1UL)) +#define KERNEL_Id "RT-Thread" ///< Kernel identification string + +#ifndef RTOS2_DEFAULT_THREAD_STACK_SIZE +#define RTOS2_DEFAULT_THREAD_STACK_SIZE 1024 +#endif + +#define DEFAULT_TICK 5 +#define WAITING_THREAD_FLAGS 0x08 +#define MALLOC_CB 0x10 +#define MALLOC_STACK 0x04 +#define MALLOC_MEM 0x02 + +static osKernelState_t kernel_state = osKernelInactive; + +static void thread_cleanup(rt_thread_t thread) +{ + thread_cb_t *thread_cb; + thread_cb = (thread_cb_t *)(thread->user_data); + + /* clear cleanup function */ + thread->cleanup = RT_NULL; + if (thread_cb->flags & osThreadJoinable) + { + rt_sem_release(thread_cb->joinable_sem); + } + else + { + if (thread_cb->flags & MALLOC_STACK) + rt_free(thread_cb->thread.stack_addr); + + if (thread_cb->flags & MALLOC_CB) + rt_free(thread_cb); + } +} + +/// Initialize the RTOS Kernel. +/// \return status code that indicates the execution status of the function. +osStatus_t osKernelInitialize(void) +{ + kernel_state = osKernelReady; + + return osOK; +} + +/// Get RTOS Kernel Information. +/// \param[out] version pointer to buffer for retrieving version information. +/// \param[out] id_buf pointer to buffer for retrieving kernel identification string. +/// \param[in] id_size size of buffer for kernel identification string. +/// \return status code that indicates the execution status of the function. +osStatus_t osKernelGetInfo(osVersion_t *version, char *id_buf, uint32_t id_size) +{ + if ((RT_NULL == version) || (RT_NULL == id_buf) || id_size < sizeof(KERNEL_Id)) + return osErrorParameter; + + version->api = KERNEL_VERSION; + version->kernel = KERNEL_VERSION; + + id_size = sizeof(KERNEL_Id); + rt_strncpy(id_buf, KERNEL_Id, id_size); + + return osOK; +} + +/// Get the current RTOS Kernel state. +/// \return current RTOS Kernel state. +osKernelState_t osKernelGetState(void) +{ + return kernel_state; +} + +/// Start the RTOS Kernel scheduler. +/// \return status code that indicates the execution status of the function. +osStatus_t osKernelStart(void) +{ + osStatus_t state; + + if (osKernelReady == kernel_state) + { + kernel_state = osKernelRunning; + + state = osOK; + } + else + { + state = osError; + } + + return state; +} + +/// Lock the RTOS Kernel scheduler. +/// \return previous lock state (1 - locked, 0 - not locked, error code if negative). +int32_t osKernelLock(void) +{ + rt_uint16_t level; + + level = rt_critical_level(); + + rt_enter_critical(); + + kernel_state = osKernelLocked; + + if (level) + { + return 1; + } + else + { + return 0; + } +} + +/// Unlock the RTOS Kernel scheduler. +/// \return previous lock state (1 - locked, 0 - not locked, error code if negative). +int32_t osKernelUnlock(void) +{ + rt_uint16_t level; + + level = rt_critical_level(); + + if (0U == level) + { + return 0; + } + else + { + rt_exit_critical(); + if (1u == level) + kernel_state = osKernelRunning; + + return 1; + } +} + +/// Restore the RTOS Kernel scheduler lock state. +/// \param[in] lock lock state obtained by \ref osKernelLock or \ref osKernelUnlock. +/// \return new lock state (1 - locked, 0 - not locked, error code if negative). +int32_t osKernelRestoreLock(int32_t lock) +{ + if (1u == lock) + { + osKernelLock(); + + return 1; + } + else + { + osKernelUnlock(); + + return 0; + } +} + +/// Get the RTOS kernel tick count. +/// \return RTOS kernel current tick count. +uint32_t osKernelGetTickCount(void) +{ + return (uint32_t)rt_tick_get(); +} + +/// Get the RTOS kernel tick frequency. +/// \return frequency of the kernel tick. +uint32_t osKernelGetTickFreq(void) +{ + + return RT_TICK_PER_SECOND; +} + +/// The function returns the current RTOS kernel system timer as a 32-bit value. +/// \return RTOS kernel current system timer count as 32-bit value +uint32_t osKernelGetSysTimerCount(void) +{ + return (uint32_t)(mchtmr_get_count(HPM_MCHTMR)); +} + +/// Get the RTOS kernel system timer frequency. +/// \return frequency of the system timer. +uint32_t osKernelGetSysTimerFreq(void) +{ + return clock_get_frequency(clock_mchtmr0); +} + +// ==== Thread Management Functions ==== + +/// Create a thread and add it to Active Threads. +/// \param[in] func thread function. +/// \param[in] argument pointer that is passed to the thread function as start argument. +/// \param[in] attr thread attributes; NULL: default values. +/// \return thread ID for reference by other functions or NULL in case of error. +osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) +{ + void *stack; + rt_uint8_t rtt_prio; + rt_uint32_t stack_size; + thread_cb_t *thread_cb; + char name[RT_NAME_MAX]; + static rt_uint16_t thread_number = 1U; + + /* Check parameters */ + if (RT_NULL == func) + { + return RT_NULL; + } + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + thread_cb = rt_malloc(sizeof(thread_cb_t)); + if (RT_NULL == thread_cb) + return RT_NULL; + rt_memset(thread_cb, 0, sizeof(thread_cb_t)); + thread_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(thread_cb_t)) + { + thread_cb = attr->cb_mem; + thread_cb->flags = 0; + } + else + return RT_NULL; + } + + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + rt_snprintf(name, sizeof(name), "th%02d", thread_number ++); + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (osPriorityNone == attr->priority)) + { + thread_cb->prio = osPriorityNormal; + } + else + { + if ((attr->priority < osPriorityIdle) || (attr->priority > osPriorityISR)) + return RT_NULL; + + thread_cb->prio = attr->priority; + } + if ((RT_NULL == attr) || (0U == attr->stack_size)) + stack_size = RTOS2_DEFAULT_THREAD_STACK_SIZE; + else + stack_size = attr->stack_size; + + if ((RT_NULL == attr) || (RT_NULL == attr->stack_mem)) + { + stack = rt_malloc(stack_size); + if (RT_NULL == stack) + { + if (thread_cb->flags & MALLOC_CB) + rt_free(thread_cb); + return RT_NULL; + } + thread_cb->flags |= MALLOC_STACK; + } + else + { + stack = (void *)(attr->stack_mem); + } + + if ((RT_NULL != attr) && (0 != attr->attr_bits)) + thread_cb->flags |= attr->attr_bits; + + rtt_prio = (osPriorityISR - thread_cb->prio) * RT_THREAD_PRIORITY_MAX / osPriorityISR; + rt_thread_init(&(thread_cb->thread), name, func, argument, stack, stack_size, rtt_prio, DEFAULT_TICK); + + if (thread_cb->flags & osThreadJoinable) + { + thread_cb->joinable_sem = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO); + if (RT_NULL == thread_cb->joinable_sem) + { + if (thread_cb->flags & MALLOC_CB) + rt_free(thread_cb); + if (thread_cb->flags & MALLOC_STACK) + rt_free(stack); + + return RT_NULL; + } + } + else + thread_cb->joinable_sem = RT_NULL; + + thread_cb->thread.cleanup = thread_cleanup; + thread_cb->thread.user_data = (rt_uint32_t)thread_cb; + + rt_thread_startup(&(thread_cb->thread)); + + return thread_cb; +} + +/// Get name of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return name as NULL terminated string. +const char *osThreadGetName(osThreadId_t thread_id) +{ + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return RT_NULL; + } + + return thread_cb->thread.name; +} + +/// Return the thread ID of the current running thread. +/// \return thread ID for reference by other functions or NULL in case of error. +osThreadId_t osThreadGetId(void) +{ + rt_thread_t thread; + + thread = rt_thread_self(); + + return (osThreadId_t)(thread->user_data); +} + +/// Get current thread state of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return current thread state of the specified thread. +osThreadState_t osThreadGetState(osThreadId_t thread_id) +{ + osThreadState_t state; + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return osThreadError; + } + + switch (thread_cb->thread.stat) + { + case RT_THREAD_INIT: + state = osThreadInactive; + break; + case RT_THREAD_READY: + state = osThreadReady; + break; + case RT_THREAD_SUSPEND: + state = osThreadBlocked; + break; + case RT_THREAD_RUNNING: + state = osThreadRunning; + break; + case RT_THREAD_CLOSE: + state = osThreadTerminated; + break; + default: + state = osThreadError; + break; + } + + return state; +} + +/// Get stack size of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return stack size in bytes. +uint32_t osThreadGetStackSize(osThreadId_t thread_id) +{ + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return 0U; + } + + return ((uint32_t)thread_cb->thread.stack_size); +} + +/// Get available stack space of a thread based on stack watermark recording during execution. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return remaining stack space in bytes. +uint32_t osThreadGetStackSpace(osThreadId_t thread_id) +{ + rt_uint8_t *ptr; + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return 0U; + } + + ptr = (rt_uint8_t *)thread_cb->thread.stack_addr; + + while (*ptr == '#')ptr ++; + + return (ptr - (rt_uint8_t *)thread_cb->thread.stack_addr); +} + +/// Change priority of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \param[in] priority new priority value for the thread function. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadSetPriority(osThreadId_t thread_id, osPriority_t priority) +{ + rt_uint8_t rt_priority; + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + // Check parameters + if ((RT_NULL == thread_cb) || (priority < osPriorityIdle) || (priority > osPriorityISR)) + { + return osErrorParameter; + } + + thread_cb->prio = priority; + rt_priority = (osPriorityISR - thread_cb->prio) * RT_THREAD_PRIORITY_MAX / osPriorityISR; + + rt_thread_control(&(thread_cb->thread), RT_THREAD_CTRL_CHANGE_PRIORITY, &rt_priority); + + return osOK; +} + +/// Get current priority of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return current priority value of the specified thread. +osPriority_t osThreadGetPriority(osThreadId_t thread_id) +{ + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return osPriorityError; + } + + return (osPriority_t)thread_cb->prio; +} + +/// Pass control to next thread that is in state \b READY. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadYield(void) +{ + rt_thread_yield(); + + return osOK; +} + +/// Suspend execution of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadSuspend(osThreadId_t thread_id) +{ + rt_err_t result; + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if (RT_NULL == thread_cb) + { + return osErrorParameter; + } + + result = rt_thread_suspend(&(thread_cb->thread)); + + if (RT_EOK == result) + return osOK; + else + return osError; +} + +/// Resume execution of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadResume(osThreadId_t thread_id) +{ + rt_err_t result; + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if (RT_NULL == thread_cb) + { + return osErrorParameter; + } + + result = rt_thread_resume(&(thread_cb->thread)); + + if (RT_EOK == result) + return osOK; + else + return osError; +} + +/// Detach a thread (thread storage can be reclaimed when thread terminates). +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadDetach(osThreadId_t thread_id) +{ + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return osErrorParameter; + } + + /* Check object attributes */ + /* + if ((thread_cb->flags & osThreadJoinable) == 0) + { + return osErrorResource; + } + */ + + if ((thread_cb->thread.stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE) + { + rt_thread_detach(&(thread_cb->thread)); + + if (thread_cb->flags & osThreadJoinable) + rt_sem_delete(thread_cb->joinable_sem); + + if (thread_cb->flags & MALLOC_STACK) + rt_free(thread_cb->thread.stack_addr); + + if (thread_cb->flags & MALLOC_CB) + rt_free(thread_cb); + } + else + { + rt_enter_critical(); + + /* change to detach state */ + thread_cb->flags &= ~osThreadJoinable; + + /* delete joinable semaphore */ + if (RT_NULL != thread_cb->joinable_sem) + { + rt_sem_delete(thread_cb->joinable_sem); + thread_cb->joinable_sem = RT_NULL; + } + + /* detach thread object */ + rt_thread_detach(&thread_cb->thread); + + rt_exit_critical(); + } + + return osOK; +} + +/// Wait for specified thread to terminate. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadJoin(osThreadId_t thread_id) +{ + rt_err_t result; + thread_cb_t *thread_cb = (thread_cb_t *)thread_id; + + /* Check parameters */ + if (RT_NULL == thread_cb) + { + return osErrorParameter; + } + + if (((&thread_cb->thread) == rt_thread_self()) || + (0 == (thread_cb->flags & osThreadJoinable))) + { + /* join self or join a detached thread*/ + return osErrorResource; + } + + result = rt_sem_take(thread_cb->joinable_sem, RT_WAITING_FOREVER); + if (RT_EOK == result) + { + /* release resource */ + if (thread_cb->flags & osThreadJoinable) + rt_sem_delete(thread_cb->joinable_sem); + + if (thread_cb->flags & MALLOC_STACK) + rt_free(thread_cb->thread.stack_addr); + + if (thread_cb->flags & MALLOC_CB) + rt_free(thread_cb); + } + else + return osError; + + return osOK; +} + +/// Terminate execution of current running thread. +__NO_RETURN void osThreadExit(void) +{ + rt_thread_t self = rt_thread_self(); + rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL); + RT_ASSERT(0); + while(1); +} + +/// Terminate execution of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \return status code that indicates the execution status of the function. +osStatus_t osThreadTerminate(osThreadId_t thread_id) +{ + thread_cb_t *thread_cb; + + thread_cb = (thread_cb_t *)(rt_thread_self()->user_data); + + /* Check parameters */ + if (RT_NULL == thread_cb) + { + return osErrorParameter; + } + + rt_thread_detach(&(thread_cb->thread)); + rt_schedule(); + + return osOK; +} + +/// Get number of active threads. +/// \return number of active threads. +uint32_t osThreadGetCount(void) +{ + rt_uint32_t thread_count = 0U; + struct rt_object_information *info; + + info = rt_object_get_information(RT_Object_Class_Thread); + + rt_enter_critical(); + thread_count = rt_list_len(&(info->object_list)); + rt_exit_critical(); + + return thread_count; +} + +/// Enumerate active threads. +/// \param[out] thread_array pointer to array for retrieving thread IDs. +/// \param[in] array_items maximum number of items in array for retrieving thread IDs. +/// \return number of enumerated threads. +uint32_t osThreadEnumerate(osThreadId_t *thread_array, uint32_t array_items) +{ + rt_uint32_t thread_count = 0U; + rt_thread_t thread; + struct rt_object_information *info; + struct rt_list_node *node; + + /* Check parameters */ + if ((RT_NULL == thread_array) || (0U == array_items)) + { + return 0U; + } + + info = rt_object_get_information(RT_Object_Class_Thread); + + rt_enter_critical(); + for (node = info->object_list.next; node != &(info->object_list); node = node->next) + { + thread = rt_list_entry(node, struct rt_thread, list); + thread_array[thread_count] = (osThreadId_t)thread; + thread_count++; + + if (thread_count >= array_items) + break; + } + rt_exit_critical(); + + return thread_count; +} + +// ==== Thread Flags Functions ==== + +/// Set the specified Thread Flags of a thread. +/// \param[in] thread_id thread ID obtained by \ref osThreadNew or \ref osThreadGetId. +/// \param[in] flags specifies the flags of the thread that shall be set. +/// \return thread flags after setting or error code if highest bit set. +uint32_t osThreadFlagsSet(osThreadId_t thread_id, uint32_t flags) +{ + register rt_base_t status; + register rt_ubase_t level; + rt_bool_t need_schedule = RT_FALSE; + thread_cb_t *thread_cb; + rt_uint32_t return_value; + + thread_cb = (thread_cb_t *)(thread_id); + + /* Check parameters */ + if ((RT_NULL == thread_cb) || (rt_object_get_type((rt_object_t)(&thread_cb->thread)) != RT_Object_Class_Thread)) + { + return osFlagsErrorParameter; + } + + level = rt_hw_interrupt_disable(); + + thread_cb->flag_set |= flags; + return_value = thread_cb->flag_set; + + /* Check if Thread is waiting for Thread Flags */ + if (thread_cb->thread.event_info & WAITING_THREAD_FLAGS) + { + status = -RT_ERROR; + if (thread_cb->thread.event_info & osFlagsWaitAll) + { + if ((thread_cb->thread.event_set & thread_cb->flag_set) == thread_cb->thread.event_set) + { + /* received an AND event */ + status = RT_EOK; + } + } + else + { + if (thread_cb->thread.event_set & thread_cb->flag_set) + { + /* save recieved event set */ + thread_cb->thread.event_set &= thread_cb->flag_set; + /* received an OR event */ + status = RT_EOK; + } + } + + /* condition is satisfied, resume thread */ + if (RT_EOK == status) + { + thread_cb->thread.event_info &= ~WAITING_THREAD_FLAGS; + /* clear event */ + if (!(thread_cb->thread.event_info & osFlagsNoClear)) + thread_cb->flag_set &= ~thread_cb->thread.event_set; + + /* resume thread, and thread list breaks out */ + rt_thread_resume(&thread_cb->thread); + need_schedule = RT_TRUE; + } + } + + rt_hw_interrupt_enable(level); + + if (need_schedule == RT_TRUE) + rt_schedule(); + + return return_value; +} + +/// Clear the specified Thread Flags of current running thread. +/// \param[in] flags specifies the flags of the thread that shall be cleared. +/// \return thread flags before clearing or error code if highest bit set. +uint32_t osThreadFlagsClear(uint32_t flags) +{ + rt_thread_t thread = rt_thread_self(); + thread_cb_t *thread_cb; + rt_uint32_t flag; + + /* Check parameters */ + if (RT_NULL == thread) + { + return osFlagsErrorParameter; + } + + thread_cb = (thread_cb_t *)(thread->user_data); + + rt_enter_critical(); + + flag = thread_cb->flag_set; + thread_cb->flag_set &= ~flags; + + rt_exit_critical(); + + return flag; +} + +/// Get the current Thread Flags of current running thread. +/// \return current thread flags. +uint32_t osThreadFlagsGet(void) +{ + rt_thread_t thread = rt_thread_self(); + thread_cb_t *thread_cb; + + /* Check parameters */ + if (RT_NULL == thread) + { + return osFlagsErrorParameter; + } + + thread_cb = (thread_cb_t *)(thread->user_data); + + return thread_cb->flag_set; +} + +/// Wait for one or more Thread Flags of the current running thread to become signaled. +/// \param[in] flags specifies the flags to wait for. +/// \param[in] options specifies flags options (osFlagsXxxx). +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return thread flags before clearing or error code if highest bit set. +uint32_t osThreadFlagsWait(uint32_t flags, uint32_t options, uint32_t timeout) +{ + rt_uint32_t return_value; + register rt_ubase_t level; + register rt_base_t status = -RT_ERROR; + rt_thread_t thread = rt_thread_self(); + thread_cb_t *thread_cb; + + /* Check parameters */ + if (RT_NULL == thread) + { + return osFlagsErrorParameter; + } + + thread->error = RT_EOK; + thread_cb = (thread_cb_t *)(thread->user_data); + + level = rt_hw_interrupt_disable(); + + if (options & osFlagsWaitAll) + { + if ((thread_cb->flag_set & flags) == flags) + status = RT_EOK; + } + else + { + if (thread_cb->flag_set & flags) + status = RT_EOK; + } + + if (RT_EOK == status) + { + return_value = thread_cb->flag_set & flags; + if (!(options & osFlagsNoClear)) + thread_cb->flag_set &= ~flags; + } + else if (0U == timeout) + { + rt_hw_interrupt_enable(level); + return osFlagsErrorResource; + } + else + { + thread->event_set = flags; + thread->event_info = options | WAITING_THREAD_FLAGS; + rt_thread_suspend(thread); + /* if there is a waiting timeout, active thread timer */ + if ((timeout > 0U) && (timeout != osWaitForever)) + { + /* reset the timeout of thread timer and start it */ + rt_timer_control(&(thread->thread_timer), + RT_TIMER_CTRL_SET_TIME, + &timeout); + rt_timer_start(&(thread->thread_timer)); + } + + rt_hw_interrupt_enable(level); + rt_schedule(); + + if (thread->error != RT_EOK) + { + return thread->error; + } + + level = rt_hw_interrupt_disable(); + return_value = thread->event_set; + } + + rt_hw_interrupt_enable(level); + + return return_value; +} + +// ==== Generic Wait Functions ==== + +/// Wait for Timeout (Time Delay). +/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value +/// \return status code that indicates the execution status of the function. +osStatus_t osDelay(uint32_t ticks) +{ + rt_thread_delay(ticks); + + return osOK; +} + +/// Wait until specified time. +/// \param[in] ticks absolute time in ticks +/// \return status code that indicates the execution status of the function. +osStatus_t osDelayUntil(uint32_t ticks) +{ + uint64_t cur_ticks; + + cur_ticks = rt_tick_get(); + + if (ticks == cur_ticks) + { + + } + else if (ticks > cur_ticks) + { + rt_thread_delay(ticks - cur_ticks); + } + else + { + rt_thread_delay(((rt_uint32_t) - 1) - cur_ticks + ticks); + } + + return osOK; +} + +// ==== Timer Management Functions ==== + +/// Create and Initialize a timer. +/// \param[in] func start address of a timer call back function. +/// \param[in] type osTimerOnce for one-shot or osTimerPeriodic for periodic behavior. +/// \param[in] argument argument to the timer call back function. +/// \param[in] attr timer attributes; NULL: default values. +/// \return timer ID for reference by other functions or NULL in case of error. + +osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) +{ + timer_cb_t *timer_cb; + char name[RT_NAME_MAX]; + static rt_uint16_t timer_number = 0U; + rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER; + + /* Check parameters */ + if ((RT_NULL == func) || ((type != osTimerOnce) && (type != osTimerPeriodic))) + { + return RT_NULL; + } + + /* RT-Thread object's name can't be NULL */ + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + rt_snprintf(name, sizeof(name), "timer%02d", timer_number++); + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + timer_cb = rt_malloc(sizeof(timer_cb_t)); + if (RT_NULL == timer_cb) + return RT_NULL; + rt_memset(timer_cb, 0, sizeof(timer_cb_t)); + timer_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(timer_cb_t)) + { + timer_cb = attr->cb_mem; + timer_cb->flags = 0; + } + else + return RT_NULL; + } + + if (osTimerPeriodic == type) + { + flag |= RT_TIMER_FLAG_PERIODIC; + } + + rt_timer_init(&(timer_cb->timer), name, func, argument, 0, flag); + + return timer_cb; +} + +/// Get name of a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return name as NULL terminated string. +const char *osTimerGetName(osTimerId_t timer_id) +{ + timer_cb_t *timer_cb; + + timer_cb = (timer_cb_t *)timer_id; + + /* Check parameters */ + if ((RT_NULL == timer_cb) || (rt_object_get_type(&timer_cb->timer.parent) != RT_Object_Class_Timer)) + { + return RT_NULL; + } + + return timer_cb->timer.parent.name; +} + +/// Start or restart a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \param[in] ticks \ref CMSIS_RTOS_TimeOutValue "time ticks" value of the timer. +/// \return status code that indicates the execution status of the function. +osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks) +{ + rt_err_t result; + timer_cb_t *timer_cb; + + timer_cb = (timer_cb_t *)timer_id; + /* Check parameters */ + if ((RT_NULL == timer_cb) || (ticks == 0)) + { + return osErrorParameter; + } + + rt_timer_control(&(timer_cb->timer), RT_TIMER_CTRL_SET_TIME, &ticks); + + result = rt_timer_start(&(timer_cb->timer)); + if (RT_EOK == result) + return osOK; + else + return osError; +} + +/// Stop a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osTimerStop(osTimerId_t timer_id) +{ + rt_err_t result; + timer_cb_t *timer_cb; + + timer_cb = (timer_cb_t *)timer_id; + + /* Check parameters */ + if (RT_NULL == timer_cb) + { + return osErrorParameter; + } + + result = rt_timer_stop(&(timer_cb->timer)); + + if (RT_EOK == result) + return osOK; + else + return osError; +} + +/// Check if a timer is running. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return 0 not running, 1 running. +uint32_t osTimerIsRunning(osTimerId_t timer_id) +{ + timer_cb_t *timer_cb; + + timer_cb = (timer_cb_t *)timer_id; + + /* Check parameters */ + if ((RT_NULL == timer_cb) || (rt_object_get_type(&timer_cb->timer.parent) != RT_Object_Class_Timer)) + { + return 0U; + } + + if ((timer_cb->timer.parent.flag & RT_TIMER_FLAG_ACTIVATED) == 1u) + { + return 1; + } + else + return 0U; +} + +/// Delete a timer. +/// \param[in] timer_id timer ID obtained by \ref osTimerNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osTimerDelete(osTimerId_t timer_id) +{ + timer_cb_t *timer_cb; + + timer_cb = (timer_cb_t *)timer_id; + + /* Check parameters */ + if (RT_NULL == timer_cb) + { + return osErrorParameter; + } + + rt_timer_detach(&(timer_cb->timer)); + + if (timer_cb->flags & MALLOC_CB) + rt_free(timer_cb); + + return osOK; +} + +#ifdef RT_USING_EVENT +// ==== Event Flags Management Functions ==== + +/// Create and Initialize an Event Flags object. +/// \param[in] attr event flags attributes; NULL: default values. +/// \return event flags ID for reference by other functions or NULL in case of error. +osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr) +{ + char name[RT_NAME_MAX]; + event_cb_t *event_cb; + static rt_uint16_t event_number = 0U; + + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + { + rt_snprintf(name, sizeof(name), "event%02d", event_number++); + } + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + event_cb = rt_malloc(sizeof(event_cb_t)); + if (RT_NULL == event_cb) + return RT_NULL; + rt_memset(event_cb, 0, sizeof(event_cb_t)); + event_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(event_cb_t)) + { + event_cb = attr->cb_mem; + event_cb->flags = 0; + } + else + return RT_NULL; + } + + rt_event_init(&(event_cb->event), name, RT_IPC_FLAG_FIFO); + + return event_cb; +} + +/// Get name of an Event Flags object. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return name as NULL terminated string. +const char *osEventFlagsGetName(osEventFlagsId_t ef_id) +{ + event_cb_t *event_cb = (event_cb_t *)ef_id; + + /* Check parameters */ + if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event)) + { + return RT_NULL; + } + + return event_cb->event.parent.parent.name; +} + +/// Set the specified Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags that shall be set. +/// \return event flags after setting or error code if highest bit set. +uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags) +{ + rt_err_t result; + rt_uint32_t set_flags; + event_cb_t *event_cb = (event_cb_t *)ef_id; + + /* Check parameters */ + if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event)) + { + return ((uint32_t)osFlagsErrorParameter); + } + + set_flags = event_cb->event.set |= flags; + + result = rt_event_send(&(event_cb->event), flags); + + if (RT_EOK == result) + return set_flags; + else + return osFlagsError; +} + +/// Clear the specified Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags that shall be cleared. +/// \return event flags before clearing or error code if highest bit set. +uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags) +{ + rt_uint32_t set_flags; + register rt_ubase_t level; + event_cb_t *event_cb = (event_cb_t *)ef_id; + + /* Check parameters */ + if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event)) + { + return ((uint32_t)osFlagsErrorParameter); + } + + set_flags = event_cb->event.set; + + level = rt_hw_interrupt_disable(); + + event_cb->event.set &= ~flags; + + rt_hw_interrupt_enable(level); + + return set_flags; +} + +/// Get the current Event Flags. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return current event flags. +uint32_t osEventFlagsGet(osEventFlagsId_t ef_id) +{ + event_cb_t *event_cb = (event_cb_t *)ef_id; + + /* Check parameters */ + if ((RT_NULL == event_cb) || (rt_object_get_type(&event_cb->event.parent.parent) != RT_Object_Class_Event)) + { + return 0U; + } + + return event_cb->event.set; +} + +/// Wait for one or more Event Flags to become signaled. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \param[in] flags specifies the flags to wait for. +/// \param[in] options specifies flags options (osFlagsXxxx). +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return event flags before clearing or error code if highest bit set. +uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options, uint32_t timeout) +{ + rt_err_t result; + rt_uint32_t rt_recv; + rt_uint8_t rt_options = 0U; + event_cb_t *event_cb = (event_cb_t *)ef_id; + + /* Check parameters */ + if (RT_NULL == event_cb) + { + return ((uint32_t)osFlagsErrorParameter); + } + + if (options & osFlagsWaitAll) + { + rt_options |= RT_EVENT_FLAG_AND; + } + else + { + rt_options |= RT_EVENT_FLAG_OR; + } + + if (!(options & osFlagsNoClear)) + { + rt_options |= RT_EVENT_FLAG_CLEAR; + } + + result = rt_event_recv(&(event_cb->event), flags, (rt_uint8_t)rt_options, timeout, &rt_recv); + + if (RT_EOK == result) + return rt_recv; + else if (-RT_ETIMEOUT == result) + { + if (0U == timeout) + return osFlagsErrorResource; + else + return osFlagsErrorTimeout; + } + else + return osFlagsErrorUnknown; +} + +/// Delete an Event Flags object. +/// \param[in] ef_id event flags ID obtained by \ref osEventFlagsNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id) +{ + event_cb_t *event_cb = (event_cb_t *)ef_id; + + /* Check parameters */ + if (RT_NULL == event_cb) + { + return osErrorParameter; + } + + rt_event_detach(&(event_cb->event)); + + if (event_cb->flags & MALLOC_CB) + rt_free(event_cb); + + return osOK; +} + +#endif + +#ifdef RT_USING_MUTEX +// ==== Mutex Management Functions ==== + +/// Create and Initialize a Mutex object. +/// \param[in] attr mutex attributes; NULL: default values. +/// \return mutex ID for reference by other functions or NULL in case of error. +osMutexId_t osMutexNew(const osMutexAttr_t *attr) +{ + char name[RT_NAME_MAX]; + mutex_cb_t *mutex_cb; + static rt_uint16_t mutex_number = 0U; + + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + { + rt_snprintf(name, sizeof(name), "mutex%02d", mutex_number++); + } + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + mutex_cb = rt_malloc(sizeof(mutex_cb_t)); + if (RT_NULL == mutex_cb) + return RT_NULL; + rt_memset(mutex_cb, 0, sizeof(mutex_cb_t)); + mutex_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(mutex_cb_t)) + { + mutex_cb = attr->cb_mem; + mutex_cb->flags = 0; + } + else + return RT_NULL; + } + + if ((RT_NULL == attr) || (0 == attr->attr_bits)) + { + mutex_cb->flags |= osMutexRecursive; + } + else + mutex_cb->flags |= attr->attr_bits; + + rt_mutex_init(&(mutex_cb->mutex), name, RT_IPC_FLAG_FIFO); + + return mutex_cb; +} + +/// Get name of a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return name as NULL terminated string. +const char *osMutexGetName(osMutexId_t mutex_id) +{ + mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id; + + /* Check parameters */ + if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex)) + { + return RT_NULL; + } + + return mutex_cb->mutex.parent.parent.name; +} + +/// Acquire a Mutex or timeout if it is locked. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) +{ + rt_err_t result; + mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id; + + /* Check parameters */ + if (RT_NULL == mutex_cb) + { + return osErrorParameter; + } + + rt_enter_critical(); + if ((mutex_cb->mutex.owner == rt_thread_self()) && !(mutex_cb->flags & osMutexRecursive)) + { + rt_exit_critical(); + return osError; + } + rt_exit_critical(); + + result = rt_mutex_take(&(mutex_cb->mutex), timeout); + + if (RT_EOK == result) + return osOK; + else if (-RT_ETIMEOUT == result) + { + if (0U == timeout) + return osErrorResource; + else + return osErrorTimeout; + } + else + return osError; +} + +/// Release a Mutex that was acquired by \ref osMutexAcquire. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexRelease(osMutexId_t mutex_id) +{ + rt_err_t result; + mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id; + + /* Check parameters */ + if (RT_NULL == mutex_cb) + { + return osErrorParameter; + } + + result = rt_mutex_release(&(mutex_cb->mutex)); + + if (RT_EOK == result) + return osOK; + else + return osErrorResource; +} + +/// Get Thread which owns a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return thread ID of owner thread or NULL when mutex was not acquired. +osThreadId_t osMutexGetOwner(osMutexId_t mutex_id) +{ + mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id; + + /* Check parameters */ + if ((RT_NULL == mutex_cb) || (rt_object_get_type(&mutex_cb->mutex.parent.parent) != RT_Object_Class_Mutex)) + { + return RT_NULL; + } + + return mutex_cb->mutex.owner; +} + +/// Delete a Mutex object. +/// \param[in] mutex_id mutex ID obtained by \ref osMutexNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMutexDelete(osMutexId_t mutex_id) +{ + mutex_cb_t *mutex_cb = (mutex_cb_t *)mutex_id; + + /* Check parameters */ + if (RT_NULL == mutex_cb) + { + return osErrorParameter; + } + + rt_mutex_detach(&(mutex_cb->mutex)); + + if (mutex_cb->flags & MALLOC_CB) + rt_free(mutex_cb); + + return osOK; +} + +#endif + +#ifdef RT_USING_SEMAPHORE +osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) +{ + char name[RT_NAME_MAX]; + sem_cb_t *sem_cb; + static rt_uint16_t semaphore_number = 0U; + + /* Check parameters */ + if ((0U == max_count) || (initial_count > max_count)) + { + return RT_NULL; + } + + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + { + rt_snprintf(name, sizeof(name), "sem%02d", semaphore_number++); + } + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + sem_cb = rt_malloc(sizeof(sem_cb_t)); + if (RT_NULL == sem_cb) + return RT_NULL; + rt_memset(sem_cb, 0, sizeof(sem_cb_t)); + sem_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(sem_cb_t)) + { + sem_cb = attr->cb_mem; + sem_cb->flags = 0; + } + else + return RT_NULL; + } + + rt_sem_init(&(sem_cb->sem), name, initial_count, RT_IPC_FLAG_FIFO); + + return sem_cb; +} + +/// Get name of a Semaphore object. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return name as NULL terminated string. +const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id) +{ + sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id; + + /* Check parameters */ + if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore)) + { + return RT_NULL; + } + + return sem_cb->sem.parent.parent.name; +} + +/// Acquire a Semaphore token or timeout if no tokens are available. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) +{ + rt_err_t result; + sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id; + + /* Check parameters */ + if (RT_NULL == sem_cb) + { + return osErrorParameter; + } + + result = rt_sem_take(&(sem_cb->sem), timeout); + + if (RT_EOK == result) + return osOK; + else if (-RT_ETIMEOUT == result) + { + if (0U == timeout) + return osErrorResource; + else + return osErrorTimeout; + } + else + return osError; +} + +/// Release a Semaphore token that was acquired by \ref osSemaphoreAcquire. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) +{ + rt_err_t result; + sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id; + + /* Check parameters */ + if (RT_NULL == sem_cb) + { + return osErrorParameter; + } + + result = rt_sem_release(&(sem_cb->sem)); + + if (RT_EOK == result) + return osOK; + else + return osError; +} + +/// Get current Semaphore token count. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return number of tokens available. +uint32_t osSemaphoreGetCount(osSemaphoreId_t semaphore_id) +{ + sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id; + + /* Check parameters */ + if ((RT_NULL == sem_cb) || (rt_object_get_type(&sem_cb->sem.parent.parent) != RT_Object_Class_Semaphore)) + { + return 0U; + } + + return sem_cb->sem.value; +} + +/// Delete a Semaphore object. +/// \param[in] semaphore_id semaphore ID obtained by \ref osSemaphoreNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) +{ + sem_cb_t *sem_cb = (sem_cb_t *)semaphore_id; + + /* Check parameters */ + if (RT_NULL == sem_cb) + { + return osErrorParameter; + } + + rt_sem_detach(&(sem_cb->sem)); + + if (sem_cb->flags & MALLOC_CB) + rt_free(sem_cb); + + return osOK; +} + +#endif + +#ifdef RT_USING_MEMPOOL +// ==== Memory Pool Management Functions ==== + +/// Create and Initialize a Memory Pool object. +/// \param[in] block_count maximum number of memory blocks in memory pool. +/// \param[in] block_size memory block size in bytes. +/// \param[in] attr memory pool attributes; NULL: default values. +/// \return memory pool ID for reference by other functions or NULL in case of error. +osMemoryPoolId_t osMemoryPoolNew(uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) +{ + char name[RT_NAME_MAX]; + void *mp_addr; + rt_uint32_t mp_size; + mempool_cb_t *mempool_cb; + static rt_uint16_t memory_pool_number = 0U; + + /* Check parameters */ + if ((0U == block_count) || (0U == block_size)) + { + return RT_NULL; + } + + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + { + rt_snprintf(name, sizeof(name), "mp%02d", memory_pool_number++); + } + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + mempool_cb = rt_malloc(sizeof(mempool_cb_t)); + if (RT_NULL == mempool_cb) + return RT_NULL; + rt_memset(mempool_cb, 0, sizeof(mempool_cb_t)); + mempool_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(mempool_cb_t)) + { + mempool_cb = attr->cb_mem; + mempool_cb->flags = 0; + } + else + return RT_NULL; + } + + if ((RT_NULL == attr) || (RT_NULL == attr->mp_mem)) + { + block_size = RT_ALIGN(block_size, RT_ALIGN_SIZE); + mp_size = (block_size + sizeof(rt_uint8_t *)) * block_count; + mp_addr = rt_malloc((block_size + sizeof(rt_uint8_t *)) * block_count); + + if (RT_NULL == mp_addr) + { + if (mempool_cb->flags & MALLOC_CB) + rt_free(mempool_cb); + return RT_NULL; + } + mempool_cb->flags |= MALLOC_MEM; + } + else + { + mp_addr = (void *)(attr->mp_mem); + mp_size = attr->mp_size; + } + + rt_mp_init(&(mempool_cb->mp), name, mp_addr, mp_size, block_size); + + return mempool_cb; +} + +/// Get name of a Memory Pool object. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return name as NULL terminated string. +const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool)) + { + return RT_NULL; + } + + return mempool_cb->mp.parent.name; +} + +/// Allocate a memory block from a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return address of the allocated memory block or NULL in case of no memory is available. +void *osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if (RT_NULL == mempool_cb) + { + return RT_NULL; + } + + return rt_mp_alloc(&(mempool_cb->mp), timeout); +} + +/// Return an allocated memory block back to a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \param[in] block address of the allocated memory block to be returned to the memory pool. +/// \return status code that indicates the execution status of the function. +osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void *block) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if (RT_NULL == mempool_cb) + { + return osErrorParameter; + } + + rt_mp_free(block); + + return osOK; +} + +/// Get maximum number of memory blocks in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return maximum number of memory blocks. +uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool)) + { + return 0U; + } + + return mempool_cb->mp.block_total_count; +} + +/// Get memory block size in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return memory block size in bytes. +uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool)) + { + return 0U; + } + + return mempool_cb->mp.block_size; +} + +/// Get number of memory blocks used in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return number of memory blocks used. +uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id) +{ + rt_size_t used_blocks; + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool)) + { + return 0U; + } + + used_blocks = mempool_cb->mp.block_total_count - mempool_cb->mp.block_free_count; + + return (uint32_t)used_blocks; +} + +/// Get number of memory blocks available in a Memory Pool. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return number of memory blocks available. +uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if ((RT_NULL == mempool_cb) || (rt_object_get_type(&mempool_cb->mp.parent) != RT_Object_Class_MemPool)) + { + return 0U; + } + + return mempool_cb->mp.block_free_count; +} + +/// Delete a Memory Pool object. +/// \param[in] mp_id memory pool ID obtained by \ref osMemoryPoolNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id) +{ + mempool_cb_t *mempool_cb = (mempool_cb_t *)mp_id; + + /* Check parameters */ + if (RT_NULL == mempool_cb) + { + return osErrorParameter; + } + + rt_mp_detach(&(mempool_cb->mp)); + + if (mempool_cb->flags & MALLOC_CB) + rt_free(mempool_cb); + + if (mempool_cb->flags & MALLOC_MEM) + rt_free(mempool_cb->mp.start_address); + + return osOK; +} + +#endif + +#ifdef RT_USING_MESSAGEQUEUE +// ==== Message Queue Management Functions ==== +/// Create and Initialize a Message Queue object. +/// \param[in] msg_count maximum number of messages in queue. +/// \param[in] msg_size maximum message size in bytes. +/// \param[in] attr message queue attributes; NULL: default values. +/// \return message queue ID for reference by other functions or NULL in case of error. +osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) +{ + char name[RT_NAME_MAX]; + mq_cb_t *mq_cb; + void *mq_addr; + rt_uint32_t mq_size; + static rt_uint16_t mq_number = 0U; + + /* Check parameters */ + if ((0U == msg_count) || (0U == msg_size)) + { + return RT_NULL; + } + + if ((RT_NULL == attr) || (RT_NULL == attr->name)) + { + rt_snprintf(name, sizeof(name), "mq%02d", mq_number++); + } + else + rt_snprintf(name, sizeof(name), "%s", attr->name); + + if ((RT_NULL == attr) || (RT_NULL == attr->cb_mem)) + { + mq_cb = rt_malloc(sizeof(mq_cb_t)); + if (RT_NULL == mq_cb) + return RT_NULL; + rt_memset(mq_cb, 0, sizeof(mq_cb_t)); + mq_cb->flags |= MALLOC_CB; + } + else + { + if (attr->cb_size >= sizeof(mq_cb_t)) + { + mq_cb = attr->cb_mem; + mq_cb->flags = 0; + } + else + return RT_NULL; + } + + msg_size = RT_ALIGN(msg_size, RT_ALIGN_SIZE); + mq_cb->init_msg_size = msg_size; + + if ((RT_NULL == attr) || (RT_NULL == attr->mq_mem)) + { + mq_size = (msg_size + sizeof(void*)) * msg_count; + mq_addr = rt_malloc(mq_size); + + if (RT_NULL == mq_addr) + { + if (mq_cb->flags & MALLOC_CB) + rt_free(mq_cb); + return RT_NULL; + } + rt_memset(mq_addr, 0, sizeof(mq_size)); + mq_cb->flags |= MALLOC_MEM; + } + else + { + mq_addr = (void *)(attr->mq_mem); + mq_size = attr->mq_size; + } + + rt_mq_init(&(mq_cb->mq), name, mq_addr, msg_size, mq_size, RT_IPC_FLAG_FIFO); + + return mq_cb; +} + +/// Get name of a Message Queue object. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return name as NULL terminated string. +const char *osMessageQueueGetName(osMessageQueueId_t mq_id) +{ + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */ + if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue)) + { + return RT_NULL; + } + + return mq_cb->mq.parent.parent.name; +} + +/// Put a Message into a Queue or timeout if Queue is full. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \param[in] msg_ptr pointer to buffer with message to put into a queue. +/// \param[in] msg_prio message priority. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) +{ + rt_err_t result; + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */ + if (RT_NULL == mq_cb || (RT_NULL == msg_ptr)) + { + return osErrorParameter; + } + + result = rt_mq_send(&(mq_cb->mq), (void *)msg_ptr, mq_cb->init_msg_size); + + if (RT_EOK == result) + return osOK; + else if (-RT_EFULL == result) + return osErrorResource; + else + return osError; +} + +/// Get a Message from a Queue or timeout if Queue is empty. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \param[out] msg_ptr pointer to buffer for message to get from a queue. +/// \param[out] msg_prio pointer to buffer for message priority or NULL. +/// \param[in] timeout \ref CMSIS_RTOS_TimeOutValue or 0 in case of no time-out. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) +{ + rt_err_t result; + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */ + if (RT_NULL == mq_cb || (RT_NULL == msg_ptr)) + { + return osErrorParameter; + } + result = rt_mq_recv(&(mq_cb->mq), msg_ptr, mq_cb->init_msg_size, timeout); + + if (RT_EOK == result) + return osOK; + else if (-RT_ETIMEOUT == result) + { + if (0U == timeout) + return osErrorResource; + return osErrorTimeout; + } + else + return osError; +} + +/// Get maximum number of messages in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return maximum number of messages. +uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id) +{ + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */ + if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue)) + { + return 0U; + } + + return mq_cb->mq.max_msgs; +} + +/// Get maximum message size in a Memory Pool. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return maximum message size in bytes. +uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id) +{ + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */; + if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue)) + { + return 0U; + } + + return mq_cb->mq.msg_size; +} + +/// Get number of queued messages in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return number of queued messages. +uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id) +{ + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */; + if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue)) + { + return 0U; + } + + return mq_cb->mq.entry; +} + +/// Get number of available slots for messages in a Message Queue. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return number of available slots for messages. +uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id) +{ + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */; + if ((RT_NULL == mq_cb) || (rt_object_get_type(&mq_cb->mq.parent.parent) != RT_Object_Class_MessageQueue)) + { + return 0U; + } + + return (mq_cb->mq.max_msgs - mq_cb->mq.entry); +} + +/// Reset a Message Queue to initial empty state. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id) +{ + rt_err_t result; + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */; + if (RT_NULL == mq_cb) + { + return osErrorParameter; + } + + result = rt_mq_control(&(mq_cb->mq), RT_IPC_CMD_RESET, RT_NULL); + + if (RT_EOK == result) + return osOK; + else + return osError; +} + +/// Delete a Message Queue object. +/// \param[in] mq_id message queue ID obtained by \ref osMessageQueueNew. +/// \return status code that indicates the execution status of the function. +osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id) +{ + mq_cb_t *mq_cb = (mq_cb_t *)mq_id; + + /* Check parameters */; + if (RT_NULL == mq_cb) + { + return osErrorParameter; + } + + rt_mq_detach(&(mq_cb->mq)); + + if (mq_cb->flags & MALLOC_CB) + rt_free(mq_cb); + + if (mq_cb->flags & MALLOC_MEM) + rt_free(mq_cb->mq.msg_pool); + + return osOK; +} + +#endif diff --git a/middleware/CMSIS/RTOS2/RTThread/cmsis_rtthread.h b/middleware/CMSIS/RTOS2/RTThread/cmsis_rtthread.h new file mode 100644 index 000000000..f3203ec44 --- /dev/null +++ b/middleware/CMSIS/RTOS2/RTThread/cmsis_rtthread.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2018-04-12 misonyo the first version + * 2023-12-18 zhihongchen change flags type from uint8_t to uint32_t + */ + +#ifndef __RTTHREAD_OS2_H__ +#define __RTTHREAD_OS2_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + rt_uint32_t flags; + struct rt_thread thread; + rt_sem_t joinable_sem; ///< semaphore for joinable thread + rt_uint32_t flag_set; ///< thread flag set + rt_uint32_t prio; +}thread_cb_t; + +typedef struct +{ + rt_uint32_t flags; + struct rt_timer timer; +}timer_cb_t; + +#ifdef RT_USING_EVENT +typedef struct +{ + rt_uint32_t flags; + struct rt_event event; +}event_cb_t; +#endif + +#ifdef RT_USING_MUTEX +typedef struct +{ + rt_uint32_t flags; + struct rt_mutex mutex; +}mutex_cb_t; +#endif + +#ifdef RT_USING_SEMAPHORE +typedef struct +{ + rt_uint32_t flags; + struct rt_semaphore sem; +}sem_cb_t; +#endif + +#ifdef RT_USING_MEMPOOL +typedef struct +{ + rt_uint32_t flags; + struct rt_mempool mp; +}mempool_cb_t; +#endif + +#ifdef RT_USING_MESSAGEQUEUE +typedef struct +{ + rt_uint32_t init_msg_size; + rt_uint32_t flags; + struct rt_messagequeue mq; +}mq_cb_t; +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/middleware/CMSIS/RTOS2/ThreadX/CMakeLists.txt b/middleware/CMSIS/RTOS2/ThreadX/CMakeLists.txt new file mode 100644 index 000000000..c930af3ba --- /dev/null +++ b/middleware/CMSIS/RTOS2/ThreadX/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2023 HPMicro +# SPDX-License-Identifier: BSD-3-Clause + +sdk_src(cmsis_os2.c) diff --git a/middleware/CMSIS/RTOS2/ThreadX/LICENSE.md b/middleware/CMSIS/RTOS2/ThreadX/LICENSE.md new file mode 100644 index 000000000..1af523307 --- /dev/null +++ b/middleware/CMSIS/RTOS2/ThreadX/LICENSE.md @@ -0,0 +1,80 @@ +SLA0044 Rev5/February 2018 + +## Software license agreement + +### __ULTIMATE LIBERTY SOFTWARE LICENSE AGREEMENT__ + +BY INSTALLING, COPYING, DOWNLOADING, ACCESSING OR OTHERWISE USING THIS SOFTWARE +OR ANY PART THEREOF (AND THE RELATED DOCUMENTATION) FROM STMICROELECTRONICS +INTERNATIONAL N.V, SWISS BRANCH AND/OR ITS AFFILIATED COMPANIES +(STMICROELECTRONICS), THE RECIPIENT, ON BEHALF OF HIMSELF OR HERSELF, OR ON +BEHALF OF ANY ENTITY BY WHICH SUCH RECIPIENT IS EMPLOYED AND/OR ENGAGED AGREES +TO BE BOUND BY THIS SOFTWARE LICENSE AGREEMENT. + +Under STMicroelectronics’ intellectual property rights, the redistribution, +reproduction and use in source and binary forms of the software or any part +thereof, with or without modification, are permitted provided that the following +conditions are met: + +1. Redistribution of source code (modified or not) must retain any copyright +notice, this list of conditions and the disclaimer set forth below as items 10 +and 11. + +2. Redistributions in binary form, except as embedded into microcontroller or +microprocessor device manufactured by or for STMicroelectronics or a software +update for such device, must reproduce any copyright notice provided with the +binary code, this list of conditions, and the disclaimer set forth below as +items 10 and 11, in documentation and/or other materials provided with the +distribution. + +3. Neither the name of STMicroelectronics nor the names of other contributors to +this software may be used to endorse or promote products derived from this +software or part thereof without specific written permission. + +4. This software or any part thereof, including modifications and/or derivative +works of this software, must be used and execute solely and exclusively on or in +combination with a microcontroller or microprocessor device manufactured by or +for STMicroelectronics. + +5. No use, reproduction or redistribution of this software partially or totally +may be done in any manner that would subject this software to any Open Source +Terms. “Open Source Terms” shall mean any open source license which requires as +part of distribution of software that the source code of such software is +distributed therewith or otherwise made available, or open source license that +substantially complies with the Open Source definition specified at +www.opensource.org and any other comparable open source license such as for +example GNU General Public License (GPL), Eclipse Public License (EPL), Apache +Software License, BSD license or MIT license. + +6. STMicroelectronics has no obligation to provide any maintenance, support or +updates for the software. + +7. The software is and will remain the exclusive property of STMicroelectronics +and its licensors. The recipient will not take any action that jeopardizes +STMicroelectronics and its licensors' proprietary rights or acquire any rights +in the software, except the limited rights specified hereunder. + +8. The recipient shall comply with all applicable laws and regulations affecting +the use of the software or any part thereof including any applicable export +control law or regulation. + +9. Redistribution and use of this software or any part thereof other than as +permitted under this license is void and will automatically terminate your +rights under this license. + +10. THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY RIGHTS, WHICH ARE +DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT SHALL +STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +11. EXCEPT AS EXPRESSLY PERMITTED HEREUNDER, NO LICENSE OR OTHER RIGHTS, WHETHER +EXPRESS OR IMPLIED, ARE GRANTED UNDER ANY PATENT OR OTHER INTELLECTUAL PROPERTY +RIGHTS OF STMICROELECTRONICS OR ANY THIRD PARTY. diff --git a/middleware/CMSIS/RTOS2/ThreadX/cmsis_os2.c b/middleware/CMSIS/RTOS2/ThreadX/cmsis_os2.c new file mode 100644 index 000000000..629fe2b40 --- /dev/null +++ b/middleware/CMSIS/RTOS2/ThreadX/cmsis_os2.c @@ -0,0 +1,4340 @@ +/* + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +/** + ****************************************************************************** + * @file cmsis_os2.c + * @author MCD Application Team + * @brief CMSIS RTOS2 wrapper for AzureRTOS ThreadX + ****************************************************************************** + * @attention + * + * Copyright (c) 2020 STMicroelectronics. + * All rights reserved. + * + * This software is licensed under terms that can be found in the LICENSE file + * in the root directory of this software component. + * If no LICENSE file comes with this software, it is provided AS-IS. + * + ****************************************************************************** + */ +/** + * Important note + * -------------- + * This file is the implementation of functions to wrap CMSIS RTOS2 onto + * AzureRTOS ThreadX based on API published by Arm Limited in cmsis_os2.h. + * The implementation of these functions is inspired from an original work from + * Arm Limited to wrap CMSIS RTOS2 onto FreeRTOS (see copyright and license + * information below). + * The whole contents of this file is a creation by STMicroelectronics licensed + * to you under the License as specified above. However, some functions + * originally created by Arm Limited have not been strongly reworked by + * STMicroelectronics and are still available under their Apache License, + * Version 2.0 original terms; these original functions are: + * - osKernelGetInfo + * - osKernelStart + * - osKernelGetTickCount + * - osKernelGetTickFreq + * - osKernelGetSysTimerFreq + * - osDelay + * - osDelayUntil + * - osThreadGetId + * - osTimerIsRunning + */ +/* -------------------------------------------------------------------------- + * Copyright (c) 2013-2019 Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Name: cmsis_os2.c + * Purpose: CMSIS RTOS2 wrapper for AzureRTOS ThreadX + * + *---------------------------------------------------------------------------*/ + +#include + +/* ::CMSIS:RTOS2 */ +#include "cmsis_os2.h" + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_byte_pool.h" +#include "tx_event_flags.h" +#include "tx_mutex.h" +#include "tx_semaphore.h" +#include "tx_queue.h" +#include "tx_block_pool.h" + +#include "hpm_soc.h" +#include "hpm_mchtmr_drv.h" +#include "hpm_clock_drv.h" + +/*---------------------------------------------------------------------------*/ + +/* Kernel version and identification string definition (major.minor.rev: mmnnnrrrr dec) */ +#define KERNEL_VERSION (((uint32_t)THREADX_MAJOR_VERSION * 10000000UL) + \ + ((uint32_t)THREADX_MINOR_VERSION * 10000UL) + \ + ((uint32_t)THREADX_PATCH_VERSION * 1UL)) + +#define KERNEL_ID ("Azure RTOS ThreadX") + +#define IS_IRQ_MODE() (read_csr(CSR_MSCRATCH) != 0U) + +/* Default thread stack size */ +#ifndef RTOS2_DEFAULT_THREAD_STACK_SIZE +#define RTOS2_DEFAULT_THREAD_STACK_SIZE 1024 +#endif + +/* Default thread stack size */ +#define RTOS2_INTERNAL_BYTE_POOL_SIZE 256 + +/* Default use memory pool allocation */ +#define USE_MEMORY_POOL_ALLOCATION 1 + +#ifndef USE_DYNAMIC_MEMORY_ALLOCATION + #ifndef USE_MEMORY_POOL_ALLOCATION + #error "CMSIS RTOS ThreadX Wrapper cmsis_os2.c: USE_DYNAMIC_MEMORY_ALLOCATION or USE_MEMORY_POOL_ALLOCATION must be defined" + #endif +#endif + +/* Default stack byte pool memory size */ +#ifndef RTOS2_BYTE_POOL_STACK_SIZE + #define RTOS2_BYTE_POOL_STACK_SIZE 32 * 1024 +#endif + +/* Default stack byte pool memory size */ +#ifndef RTOS2_BYTE_POOL_HEAP_SIZE + #define RTOS2_BYTE_POOL_HEAP_SIZE 4 * 1024 +#endif + +/* Default time slice for the created threads */ +#ifndef RTOS2_DEFAULT_TIME_SLICE +#define RTOS2_DEFAULT_TIME_SLICE 4 +#endif + +/* Default stack byte pool memory type */ +#define RTOS2_BYTE_POOL_STACK_TYPE 1 + +/* Default stack byte pool memory type */ +#define RTOS2_BYTE_POOL_HEAP_TYPE 2 + +#ifndef TX_THREAD_USER_EXTENSION +#error "CMSIS RTOS ThreadX Wrapper: TX_THREAD_USER_EXTENSION must be defined as tx_thread_detached_joinable (ULONG) in tx_user.h file" +#endif + +#ifdef TX_DISABLE_ERROR_CHECKING +#error "CMSIS RTOS ThreadX Wrapper : TX_DISABLE_ERROR_CHECKING must be undefined" +#endif + +/* Ensure the maximum number of priorities is modified by the user to 64. */ +#if(TX_MAX_PRIORITIES != 64) +#error "CMSIS RTOS ThreadX Wrapper: TX_MAX_PRIORITIES must be fixed to 64 in tx_user.h file" +#endif +/*---------------------------------------------------------------------------*/ + +static osKernelState_t KernelState = osKernelInactive; +extern uint32_t SystemCoreClock; + +TX_BYTE_POOL HeapBytePool; +TX_BYTE_POOL StackBytePool; +TX_BLOCK_POOL BlockPool; + +/*---------------------------------------------------------------------------*/ +/*-------------------CMSIS RTOS2 Internal Functions--------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function MemAlloc allocates thread, timer, mutex, semaphore, + * event flags and message queue block object memory. + * Or it allocates the thread or message queue stack memory. + * @param [in] memory size to be allocated from BytePool + * [in] to be allocated memory type (Heap or Stack) + * @retval pointer to the allocated memory or NULL in case of error. + */ +static uint8_t *MemAlloc(uint32_t mem_size, uint8_t pool_type) +{ + /* The output pointer to the allocated memory or NULL in case of error */ + uint8_t *mem_ptr; + /* Allocated memory size */ + uint32_t allocated_mem_size = mem_size; + /* Pointer to the BytePool to be used for memory allocation */ + TX_BYTE_POOL *byte_pool; + + /* Check if the memory size is invalid or the BytePool type is wrong */ + if ((mem_size == 0) || (pool_type > RTOS2_BYTE_POOL_HEAP_TYPE)) + { + /* Return NULL in case of error */ + mem_ptr = NULL; + } + else + { + /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */ + if (allocated_mem_size < TX_BYTE_POOL_MIN) + { + /* We should at least allocate TX_BYTE_POOL_MIN */ + allocated_mem_size = TX_BYTE_POOL_MIN; + } + + /* Assign the BytePool to be used (StackBytePool or HeapBytePool) */ + if (pool_type == RTOS2_BYTE_POOL_STACK_TYPE) + { + /* Point to the Stack BytePool */ + byte_pool = &StackBytePool; + } + else + { + /* Point to the Heap BytePool */ + byte_pool = &HeapBytePool; + } + + /* Allocate the mem_ptr */ + if (tx_byte_allocate(byte_pool, (void **) &mem_ptr, allocated_mem_size, TX_NO_WAIT) != TX_SUCCESS) + { + /* Return NULL in case of error */ + mem_ptr = NULL; + } + } + + return (mem_ptr); +} + +/** + * @brief The function MemFree allocates thread, timer, mutex, semaphore, + * event flags and message queue block object memory. + * Or it allocates the thread or message queue stack memory. + * @param [in] memory size to be allocated from BytePool + * [in] to be allocated memory type (Heap or Stack) + * @retval pointer to the allocated memory or NULL in case of error. + */ +static osStatus_t MemFree(VOID *memory_ptr) +{ + /* The output status code that indicates the execution status */ + osStatus_t status = osOK; + + /* Check if the memory_ptr is invalid */ + if (memory_ptr == NULL) + { + /* Return osError in case of error */ + status = osError; + } + else + { + /* Free the allocated memory_ptr */ + if (tx_byte_release(memory_ptr) != TX_SUCCESS) + { + /* Return osError in case of error */ + status = osError; + } + } + + return (status); +} + +/** + * @brief The function MemInit creates memory pools for stack and heap. + * The stack pool is used for threads and queues stacks allocations. + * The heap pool is used for threads, timers, mutex, semaphores, + * message queues and events flags control block object memory allocations. + * The size of stack and heap pools are user configured using the + * RTOS2_BYTE_POOL_STACK_SIZE and RTOS2_BYTE_POOL_HEAP_SIZE flags. + * @param none. + * @retval status code that indicates the execution status of the function. + */ +static osStatus_t MemInit(void) +{ + /* Allocated memory size */ + uint32_t bytepool_size = RTOS2_BYTE_POOL_STACK_SIZE; +#ifdef USE_DYNAMIC_MEMORY_ALLOCATION + /* Unused memory address */ + CHAR *unused_memory = NULL; +#else + #ifdef USE_MEMORY_POOL_ALLOCATION + CHAR *unused_memory_Stack = NULL; + CHAR *unused_memory_Heap = NULL; + #endif +#endif + + /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */ + if (bytepool_size < TX_BYTE_POOL_MIN) + { + /* We should at least allocate TX_BYTE_POOL_MIN */ + bytepool_size = TX_BYTE_POOL_MIN; + } +/* Initialize the Heap BytePool address */ +#ifdef USE_DYNAMIC_MEMORY_ALLOCATION + unused_memory = (CHAR *)_tx_initialize_unused_memory; +#elif USE_MEMORY_POOL_ALLOCATION + static CHAR freememStack[RTOS2_BYTE_POOL_STACK_SIZE + RTOS2_INTERNAL_BYTE_POOL_SIZE]; + static CHAR freememHeap[RTOS2_BYTE_POOL_HEAP_SIZE + RTOS2_INTERNAL_BYTE_POOL_SIZE]; + unused_memory_Stack = (CHAR *)freememStack; + unused_memory_Heap = (CHAR *)freememHeap; +#endif + +#ifdef USE_DYNAMIC_MEMORY_ALLOCATION + /* Create a byte memory pool from which to allocate the timer control + block */ + if (tx_byte_pool_create(&StackBytePool, "Byte Pool Stack", unused_memory, + RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS) + { + /* Return osError in case of error */ + return (osError); + } + else + { + /* Set the tx_initialize_unused_memory address */ + unused_memory += RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size; + } + + /* Set bytepool_size to the user configured Heap size */ + bytepool_size = RTOS2_BYTE_POOL_HEAP_SIZE; + + /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */ + if (bytepool_size < TX_BYTE_POOL_MIN) + { + /* We should at least allocate TX_BYTE_POOL_MIN */ + bytepool_size = TX_BYTE_POOL_MIN; + } + + /* Create a byte memory pool from which to allocate the timer control + block */ + if (tx_byte_pool_create(&HeapBytePool, "Byte Pool Heap", unused_memory, + RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS) + { + /* Return osError in case of error */ + return (osError); + } + else + { + /* Set the tx_initialize_unused_memory address */ + unused_memory += RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size; + } + + /* Update the _tx_initialize_unused_memory */ + _tx_initialize_unused_memory = unused_memory; + +#else + #ifdef USE_MEMORY_POOL_ALLOCATION + /* Create a byte memory pool from which to allocate the timer control + block */ + if (tx_byte_pool_create(&StackBytePool, "Byte Pool Stack", unused_memory_Stack, + RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS) + { + /* Return osError in case of error */ + return (osError); + } + /* Set bytepool_size to the user configured Heap size */ + bytepool_size = RTOS2_BYTE_POOL_HEAP_SIZE; + + /* If the memory size the be allocated is less then the TX_BYTE_POOL_MIN */ + if (bytepool_size < TX_BYTE_POOL_MIN) + { + /* We should at least allocate TX_BYTE_POOL_MIN */ + bytepool_size = TX_BYTE_POOL_MIN; + } + + /* Create a byte memory pool from which to allocate the timer control + block */ + if (tx_byte_pool_create(&HeapBytePool, "Byte Pool Heap", unused_memory_Heap, + RTOS2_INTERNAL_BYTE_POOL_SIZE + bytepool_size) != TX_SUCCESS) + { + /* Return osError in case of error */ + return (osError); + } + #endif +#endif + return (osOK); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------Kenel Management APIs---------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osKernelInitialize initializes the RTOS Kernel. Before + * it is successfully executed, only the functions osKernelGetInfo and + * osKernelGetState may be called. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param none + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osKernelInitialize(void) +{ + /* The output status code that indicates the execution status */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR in case of error */ + status = osErrorISR; + } + else + { + /* Check if the kernel state is osKernelInactive */ + if (KernelState == osKernelInactive) + { + /* Initialize the kernel */ + _tx_initialize_kernel_setup(); + + /* Initialize the Heap and stack memory BytePools */ + if (MemInit() == osOK) + { + /* Set the kernel state to osKernelReady */ + KernelState = osKernelReady; + + /* Return osOK in case of success */ + status = osOK; + } + else + { + /* Return osError in case of error */ + status = osError; + } + } + else + { + /* Return osError in case of error */ + status = osError; + } + } + + return (status); +} + +/** + * @brief The function osKernelGetInfo retrieves the API and kernel version + * of the underlying RTOS kernel and a human readable identifier string + * for the kernel. It can be safely called before the RTOS is + * initialized or started (call to osKernelInitialize or osKernelStart) + * Note : This function may be called from Interrupt Service + * Routines. + * @param [out] version pointer to buffer for retrieving version information. + * [out] id_buf pointer to buffer for retrieving kernel identification + * string. + * [in] id_size size of buffer for kernel identification string. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osKernelGetInfo(osVersion_t *version, char *id_buf, uint32_t id_size) +{ + /* The output status code that indicates the execution status */ + osStatus_t status = osOK; + + /* Check if input version pointer is not NULL */ + if (version != NULL) + { + /* Version encoding is major.minor.rev: mmnnnrrrr dec */ + version->api = KERNEL_VERSION; + version->kernel = KERNEL_VERSION; + } + else + { + /* Return osError in case of error */ + status = osError; + } + + /* Check if input id_buf pointer is not NULL and id_size != 0 */ + if ((id_buf != NULL) && (id_size != 0U)) + { + if (id_size > sizeof(KERNEL_ID)) + { + id_size = sizeof(KERNEL_ID); + } + memcpy(id_buf, KERNEL_ID, id_size); + } + else + { + /* Return osError in case of error */ + status = osError; + } + + return (status); +} + +/** + * @brief The function osKernelGetState returns the current state of the + * kernel and can be safely called before the RTOS is initialized or + * started (call to osKernelInitialize or osKernelStart). In case it + * fails it will return osKernelError, otherwise it returns the kernel + * state (refer to osKernelState_t for the list of kernel states). + * Note : This function may be called from Interrupt Service + * Routines. + * @param none + * @retval current RTOS Kernel state. + */ +osKernelState_t osKernelGetState(void) +{ + return (KernelState); +} + +/** + * @brief The function osKernelStart starts the RTOS kernel and begins thread + * switching. It will not return to its calling function in case of + * success. Before it is successfully executed, only the functions + * osKernelGetInfo, osKernelGetState, and object creation functions + * (osXxxNew) may be called. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param none + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osKernelStart(void) +{ + /* The output status code that indicates the execution status */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR in case of error */ + status = osErrorISR; + } + else + { + /* Check if the kernel state is osKernelReady */ + if (KernelState == osKernelReady) + { + /* Set the kernel state to osKernelRunning */ + KernelState = osKernelRunning; + + /* Return osOK in case of success */ + status = osOK; + + /* Start the Kernel */ + tx_kernel_enter(); + } + else + { + /* Return osError in case of error */ + status = osError; + } + } + + return (status); +} + +/** + * @brief The function osKernelGetTickCount returns the current RTOS kernel + * tick count. + * Note : This function may be called from Interrupt Service + * Routines. + * @param none + * @retval RTOS kernel current tick count. + */ +uint32_t osKernelGetTickCount(void) +{ + /* The output RTOS kernel current tick count */ + uint32_t ticks; + + /* Get the RTOS kernel current tick count */ + ticks = (uint32_t)tx_time_get(); + + return (ticks); +} + +/** + * @brief The function osKernelGetTickFreq returns the frequency of the + * current RTOS kernel tick. + * Note : This function may be called from Interrupt Service + * Routines. + * @param none + * @retval frequency of the kernel tick in hertz, i.e. kernel ticks per second. + */ +uint32_t osKernelGetTickFreq(void) +{ + return (TX_TIMER_TICKS_PER_SECOND); +} + +/** + * @brief The function osKernelGetSysTimerCount returns the current RTOS + * kernel system timer as a 32-bit value. The value is a rolling 32-bit + * counter that is composed of the kernel system interrupt timer value + * and the counter that counts these interrupts (RTOS kernel ticks). + * This function allows the implementation of very short timeout checks + * below the RTOS tick granularity. Such checks might be required when + * checking for a busy status in a device or peripheral initialization + * routine, see code example below. + * Note : This function may be called from Interrupt Service + * Routines. + * @param none + * @retval RTOS kernel current system timer count as 32-bit value. + */ +uint32_t osKernelGetSysTimerCount(void) +{ + return (uint32_t)(mchtmr_get_count(HPM_MCHTMR)); +} + +/** + * @brief The function osKernelGetSysTimerFreq returns the frequency of the + * current RTOS kernel system timer. + * Note : This function may be called from Interrupt Service + * Routines. + * @param none + * @retval frequency of the system timer in hertz, i.e. timer ticks per second. + */ +uint32_t osKernelGetSysTimerFreq(void) +{ + return (clock_get_frequency(clock_mchtmr0)); +} + +/*---------------------------------------------------------------------------*/ +/*-----------------------------Generic Wait APIs-----------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osDelay waits for a time period specified in kernel + * ticks. For a value of 1 the system waits until the next timer tick + * occurs. The actual time delay may be up to one timer tick less than + * specified, i.e. calling osDelay(1) right before the next system tick + * occurs the thread is rescheduled immediately. + * The delayed thread is put into the BLOCKED state and a context + * switch occurs immediately. The thread is automatically put back to + * the READY state after the given amount of ticks has elapsed. If the + * thread will have the highest priority in READY state it will being + * scheduled immediately. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ticks time ticks value + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osDelay(uint32_t ticks) +{ + /* The output status code that indicates the execution status */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR in case of error */ + status = osErrorISR; + } + else + { + /* Return osOK in case of success */ + status = osOK; + + /* Check that the input ticks != 0 */ + if (ticks != 0U) + { + /* Sleep the thread */ + tx_thread_sleep(ticks); + } + } + + return (status); +} + +/** + * @brief The function osDelayUntil waits until an absolute time (specified + * in kernel ticks) is reached. + * The corner case when the kernel tick counter overflows is handled by + * osDelayUntil. Thus it is absolutely legal to provide a value which + * is lower than the current tick value, i.e. returned by + * osKernelGetTickCount. Typically as a user you do not have to take + * care about the overflow. The only limitation you have to have in + * mind is that the maximum delay is limited to (231)-1 ticks. + * The delayed thread is put into the BLOCKED state and a context + * switch occurs immediately. The thread is automatically put back to + * the READY state when the given time is reached. If the thread will + * have the highest priority in READY state it will being scheduled + * immediately. + * @param [in] ticks absolute time in ticks + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osDelayUntil(uint32_t ticks) +{ + uint32_t tcnt, delay; + /* The output status code that indicates the execution status */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR in case of error */ + status = osErrorISR; + } + else + { + /* Return osOK in case of success */ + status = osOK; + + /* Return osOK in case of success */ + tcnt = (uint32_t)tx_time_get(); + + /* Determine remaining number of ticks to delay */ + delay = ticks - tcnt; + + /* Check if target tick has not expired */ + if ((delay != 0U) && (0 == (delay >> (8 * sizeof(uint32_t) - 1)))) + { + /* Sleep the thread */ + tx_thread_sleep(delay); + } + else + { + /* No delay or already expired */ + status = osErrorParameter; + } + } + + return (status); +} + +/*---------------------------------------------------------------------------*/ +/*--------------------------Thread Management APIs---------------------------*/ +/*---------------------------------------------------------------------------*/ +/** + * @brief The function osThreadNew starts a thread function by adding it to + * the list of active threads and sets it to state READY. Arguments for + * the thread function are passed using the parameter pointer + * *argument. When the priority of the created thread function is + * higher than the current RUNNING thread, the created thread function + * starts instantly and becomes the new RUNNING thread. Thread + * attributes are defined with the parameter pointer attr. Attributes + * include settings for thread priority, stack size, or memory + * allocation. + * The function can be safely called before the RTOS is started + * (call to osKernelStart), but not before it is initialized (call to + * osKernelInitialize). + * The function osThreadNew returns the pointer to the thread object + * identifier or NULL in case of an error. + * Note : This function Cannot be called from Interrupt Service + * Routines. + * @param [in] func thread function. + * [in] argument pointer that is passed to the thread function as + * start argument. + * [in] attr thread attributes; NULL: default values. + * @retval thread ID for reference by other functions or NULL in case of error. + */ +osThreadId_t osThreadNew(osThreadFunc_t func, void *argument, const osThreadAttr_t *attr) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = NULL; + /* Pointer to the thread name */ + CHAR *name_ptr = NULL; + /* Pointer to start address of the thread stack */ + VOID *stack_start; + /* The thread stack size */ + ULONG stack_size; + /* The thread control block size */ + ULONG cb_size; + /* The thread priority */ + UINT priority; + /* The thread entry input */ + ULONG entry_input = 0; + + /* Check if this API is called from Interrupt Service Routines + or the thread_id is NULL */ + if (!IS_IRQ_MODE() && (func != NULL)) + { + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + /* Check if the attr is not NULL */ + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the thread name_ptr */ + name_ptr = (CHAR *)attr->name; + } + + /* Check the input priority value and attribute bits for osThreadJoinable + parameter */ + if ((attr->priority < osPriorityIdle) || (attr->priority > osPriorityISR)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set the thread priority */ + priority = osPriorityISR - attr->priority; + } + + /* Check if the argument is not NULL */ + if (argument != NULL) + { + /* Set the entry_input */ + entry_input = (ULONG) argument; + } + + /* Check if the stack size is equal to 0 */ + if (attr->stack_size == 0U) + { + /* Set stack size to DEFAULT_THREAD_STACK_SIZE */ + stack_size = RTOS2_DEFAULT_THREAD_STACK_SIZE; + } + else if (attr->stack_size < TX_MINIMUM_STACK) + { + /* Set stack size to TX_MINIMUM_STACK */ + stack_size = TX_MINIMUM_STACK; + } + else + { + /* Set stack size to attr->stack_size */ + stack_size = (ULONG)attr->stack_size; + } + + /* Check if the input stack pointer is NULL */ + if (attr->stack_mem == NULL) + { + /* Allocate the stack for the thread to be created */ + stack_start = MemAlloc(stack_size, RTOS2_BYTE_POOL_STACK_TYPE); + if (stack_start == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + if (attr->stack_size == 0U) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set stack size to the input attr->stack_size */ + stack_size = (ULONG)attr->stack_size; + } + + /* The stack shall point to the input stack memory address */ + stack_start = attr->stack_mem; + } + + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_THREAD) */ + cb_size = sizeof(TX_THREAD); + } + else if (attr->cb_size < sizeof(TX_THREAD)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set stack size to attr->cb_size */ + cb_size = (ULONG)attr->cb_size; + } + + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the thread_ptr structure for the thread to be created */ + thread_ptr = (TX_THREAD *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (thread_ptr == NULL) + { + /* Check if the memory for thread stack has been internally + allocated */ + if (attr->stack_mem == NULL) + { + /* Free the already allocated memory for thread stack */ + MemFree(stack_start); + } + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + thread_ptr = attr->cb_mem; + } + } + else + { + /* Set the thread priority to default osPriorityNormal*/ + priority = osPriorityISR - osPriorityNormal; + + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + /* Initialize the stack_size to RTOS2_DEFAULT_THREAD_STACK_SIZE */ + stack_size = RTOS2_DEFAULT_THREAD_STACK_SIZE; + + /* Check if the argument is not NULL */ + if (argument != NULL) + { + /* Set the entry_input */ + entry_input = (ULONG) argument; + } + + /* Allocate the stack for the thread to be created */ + stack_start = MemAlloc(stack_size, RTOS2_BYTE_POOL_STACK_TYPE); + if (stack_start == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + + /* Allocate the thread_ptr structure for the thread to be created */ + thread_ptr = (TX_THREAD *)MemAlloc(sizeof(TX_THREAD), RTOS2_BYTE_POOL_HEAP_TYPE); + if (thread_ptr == NULL) + { + /* Free the already allocated memory for thread stack */ + MemFree(stack_start); + + /* Return NULL pointer in case of error */ + return (NULL); + } + } + + /* Call the tx_thread_create function to create the new thread. + Note: By default the preempt_threshold shall be deactivated by setting + its value to the priority or deactivated using + TX_DISABLE_PREEMPTION_THRESHOLD */ + if (tx_thread_create(thread_ptr, name_ptr, (void(*)(ULONG))func, entry_input, stack_start, stack_size, priority, + priority, RTOS2_DEFAULT_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + /* Check if the memory for thread control block has been internally + allocated */ + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for thread control block */ + MemFree(thread_ptr); + } + + /* Check if the memory for thread stack has been internally allocated */ + if ((attr->stack_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for thread stack */ + MemFree(stack_start); + } + + /* Return NULL pointer in case of error */ + thread_ptr = NULL; + } + else + { + /* Check if the thread shall be created joinable */ + if ((attr != NULL) && (attr->attr_bits == osThreadJoinable)) + { + /* Set the thread to Joinable state */ + thread_ptr->tx_thread_detached_joinable = osThreadJoinable; + } + else + { + /* Set the thread to Detached state */ + thread_ptr->tx_thread_detached_joinable = osThreadDetached; + } + } + } + + return ((osThreadId_t)thread_ptr); +} + +/** + * @brief The function osThreadGetName returns the pointer to the name_ptr + * string of the thread identified by parameter thread_id or NULL in + * case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId + * @retval name_ptr as null-terminated string. + */ +const char *osThreadGetName(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr = NULL; + + /* Check if this API is called from Interrupt Service Routines, the thread_id + is NULL or thread_id->tx_thread_id != TX_THREAD_ID */ + if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_thread_info_get to get the thread name_ptr */ + if (tx_thread_info_get(thread_ptr, &name_ptr, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return (name_ptr); +} + +/** + * @brief The function osThreadGetId returns the thread object ID of the + * currently running thread or NULL in case of an error. + * Note : This function may be called from Interrupt Service Routines. + * @param none + * @retval thread ID for reference by other functions or NULL in case of error. + */ +osThreadId_t osThreadGetId(void) +{ + /* For ThreadX the control block pointer is the thread identifier */ + osThreadId_t thread_id; + + /* Call the tx_thread_identify to get the control block pointer of the + currently executing thread. */ + thread_id = (osThreadId_t)tx_thread_identify(); + + return (thread_id); +} + +/** + * @brief The function osThreadGetState returns the state of the thread + * identified by parameter thread_id. In case it fails or if it is + * called from an ISR, it will return osThreadError, otherwise it + * returns the thread state (refer to osThreadState_t for the list of + * thread states). + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId + * @retval state current thread state of the specified thread. + */ +osThreadState_t osThreadGetState(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The control block pointer of the current running thread */ + TX_THREAD *current_thread = NULL; + /* The current thread state of the specified thread. */ + osThreadState_t state; + /* The current thread state of the specified thread as specified by threadx */ + UINT threadx_state; + + /* Check if this API is called from Interrupt Service Routines, the thread_id + is NULL or thread_id->tx_thread_id != TX_THREAD_ID */ + if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + /* Return osThreadError in case of an error */ + { + state = osThreadError; + } + else + { + /* Get the current running thread */ + TX_THREAD_GET_CURRENT(current_thread); + if (current_thread == thread_id) + { + /* The state is running */ + state = osThreadRunning; + } + else + { + /* Call the tx_thread_info_get to get the thread threadx_state */ + if (tx_thread_info_get(thread_ptr, NULL, &threadx_state, NULL, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return osThreadError in case of an error */ + state = osThreadError; + } + else + { + /* Link the ThreadX thread states to CMSIS RTOS2 states */ + switch (threadx_state) + { + /* The thread is in READY state */ + case TX_READY: + { + state = osThreadReady; + break; + } + /* The thread is in COMPLETED state */ + case TX_COMPLETED: + { + state = osThreadTerminated; + break; + } + /* The thread is in TERMINATED state */ + case TX_TERMINATED: + { + state = osThreadTerminated; + break; + } + /* The thread is in SUSPENDED state */ + case TX_SUSPENDED: + case TX_QUEUE_SUSP: + case TX_SEMAPHORE_SUSP: + case TX_EVENT_FLAG: + case TX_BLOCK_MEMORY: + case TX_BYTE_MEMORY: + case TX_IO_DRIVER: + case TX_FILE: + case TX_TCP_IP: + case TX_MUTEX_SUSP: + case TX_PRIORITY_CHANGE: + { + state = osThreadBlocked; + break; + } + /* The thread is in SLEEP state */ + case TX_SLEEP: + { + state = osThreadBlocked; + break; + } + /* The thread is in unknown state */ + default: + { + state = osThreadError; + break; + } + } + } + } + } + + return (state); +} + +/** + * @brief The function osThreadGetStackSize returns the stack size of the + * thread specified by parameter thread_id. In case of an error, it + * returns 0. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval remaining_stack_space remaining stack space in bytes. + */ +uint32_t osThreadGetStackSize(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The specific thread stack size in bytes */ + unsigned int stack_size; + + /* Check if this API is called from Interrupt Service Routines, the thread_id + is NULL or thread_id->tx_thread_id != TX_THREAD_ID */ + if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return 0 in case of error */ + stack_size = 0U; + } + else + { + /* The stack_size get the allocated thread stack size in the thread creation step */ + stack_size = thread_ptr->tx_thread_stack_size; + } + + return (stack_size); +} + +/** + * @brief The function osThreadGetStackSpace returns the size of unused stack + * space for the thread specified by parameter thread_id. Stack + * watermark recording during execution needs to be enabled (refer to + * Thread Configuration). In case of an error, it returns 0. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval remaining_stack_space remaining stack space in bytes. + */ +uint32_t osThreadGetStackSpace(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* Remaining stack space in bytes */ + uint32_t remaining_stack_space; + + /* Check if this API is called from Interrupt Service Routines, the thread_id + is NULL or thread_id->tx_thread_id != TX_THREAD_ID */ + if (IS_IRQ_MODE() || (thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return 0 in case of error */ + remaining_stack_space = 0U; + } + else + { + /* Compute the remaining free stack size for the given thread */ + remaining_stack_space = (unsigned int)((CHAR *)thread_ptr->tx_thread_stack_ptr - + (CHAR *)thread_ptr->tx_thread_stack_start); + } + + return (remaining_stack_space); +} + +/** + * @brief The function osThreadSetPriority changes the priority of an active + * thread specified by the parameter thread_id to the priority + * specified by the parameter priority. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * [in] priority new priority value for the thread function. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadSetPriority(osThreadId_t thread_id, osPriority_t priority) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* Old priority */ + UINT old_priority; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if thread_ptr is NULL or thread_id->tx_thread_id != TX_THREAD_ID or + the input priority is out of range */ + else if ((thread_ptr == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID) || (priority < osPriorityIdle) + || (priority > osPriorityISR)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Convert input CMSIS osPriority_t to threadX priority */ + priority = (osPriority_t)(osPriorityISR - priority); + + /* Call the tx_thread_priority_change to change the thread priority */ + if (tx_thread_priority_change(thread_ptr, priority, &old_priority) == TX_SUCCESS) + { + /* Return osOK in case of success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osThreadGetPriority returns the priority of an active + * thread specified by the parameter thread_id. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval priority current priority value of the specified thread. + */ +osPriority_t osThreadGetPriority(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The returned thread priority or error */ + osPriority_t priority; + + /* Check if this API is called from Interrupt Service Routines + or the thread_id is NULL */ + if (IS_IRQ_MODE() || (thread_ptr == NULL)) + { + /* Return osPriorityError in case of an error */ + priority = osPriorityError; + } + else + { + /* Call the tx_thread_info_get to get the thread priority */ + if (tx_thread_info_get(thread_ptr, NULL, NULL, NULL, (UINT *)&priority, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return osPriorityError in case of an error */ + priority = osPriorityError; + } + else + { + /* Convert the threadX priority to CMSIS osPriority_t */ + priority = (osPriority_t)(osPriorityISR - priority); + } + } + + return (priority); +} + +/** + * @brief The function osThreadYield passes control to the next thread with + * the same priority that is in the READY state. If there is no other + * thread with the same priority in state READY, then the current + * thread continues execution and no thread switch occurs. + * osThreadYield does not set the thread to state BLOCKED. Thus no + * thread with a lower priority will be scheduled even if threads in + * state READY are available. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param none. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadYield(void) +{ + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + else + { + /* Call the tx_thread_relinquish to relinquishes processor control to + other ready-to-run threads at the same or higher priority. */ + tx_thread_relinquish(); + + /* Return osOK for success */ + status = osOK; + } + + return (status); +} + +/** + * @brief The function osThreadSuspend suspends the execution of the thread + * identified by parameter thread_id. The thread is put into the + * BLOCKED state (osThreadBlocked). Suspending the running thread will + * cause a context switch to another thread in READY state immediately. + * The suspended thread is not executed until explicitly resumed with + * the function osThreadResume. + * Threads that are already BLOCKED are removed from any wait list and + * become ready when they are resumed. Thus it is not recommended to + * suspend an already blocked thread. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadSuspend(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */ + else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_thread_suspend to suspends the specified application + thread. A thread may call this service to suspend itself. */ + if (tx_thread_suspend(thread_ptr) == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osThreadResume puts the thread identified by parameter + * thread_id (which has to be in BLOCKED state) back to the READY + * state. If the resumed thread has a higher priority than the running + * thread a context switch occurs immediately. + * The thread becomes ready regardless of the reason why the thread was + * blocked. Thus it is not recommended to resume a thread not suspended + * by osThreadSuspend. + * Functions that will put a thread into BLOCKED state are: + * osEventFlagsWait and osThreadFlagsWait, osDelay and osDelayUntil, + * osMutexAcquire and osSemaphoreAcquire, osMessageQueueGet, + * osMemoryPoolAlloc, osThreadJoin, osThreadSuspend.. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadResume(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */ + else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_thread_resume to resumes or prepares for execution a thread + that was previously suspended by a tx_thread_suspend call. In addition, + this service resumes threads that were created without an automatic + start. */ + if (tx_thread_resume(thread_ptr) == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osThreadExit terminates the calling thread. This allows + * the thread to be synchronized with osThreadJoin. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param none. + * @retval none. + */ +__NO_RETURN void osThreadExit(void) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = NULL; + + /* Check if this API is called from Interrupt Service Routines */ + if (!IS_IRQ_MODE()) + { + /* Call the tx_thread_identify to get the control block pointer of the + currently executing thread. */ + thread_ptr = tx_thread_identify(); + + /* Check if the current running thread pointer is not NULL */ + if (thread_ptr != NULL) + { + /* Call the tx_thread_terminate to terminates the specified application + thread regardless of whether the thread is suspended or not. A thread + may call this service to terminate itself. */ + tx_thread_terminate(thread_ptr); + } + } + /* Infinite loop */ + for (;;); +} + +/** + * @brief The function osThreadTerminate removes the thread specified by + * parameter thread_id from the list of active threads. If the + * thread is currently RUNNING, the thread terminates and the + * execution continues with the next READY thread. If no such thread + * exists, the function will not terminate the running thread, but + * return osErrorResource. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadTerminate(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */ + else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_thread_terminate to terminates the specified application + thread regardless of whether the thread is suspended or not. A thread + may call this service to terminate itself. */ + if (tx_thread_terminate(thread_ptr) == TX_SUCCESS) + { + /* Free the thread resources if it is Detached */ + if (thread_ptr->tx_thread_detached_joinable == osThreadDetached) + { + /* Free the already allocated memory for thread stack */ + MemFree(thread_ptr->tx_thread_stack_start); + + /* Free the already allocated memory for thread control block */ + MemFree(thread_ptr); + } + + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osThreadDetach changes the attribute of a thread + * (specified by thread_id) to osThreadDetached. Detached threads are + * not joinable with osThreadJoin. When a detached thread is + * terminated, all resources are returned to the system. The behavior + * of osThreadDetach on an already detached thread is undefined. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadDetach(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */ + else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Change the status of the specific thread to Detached */ + thread_ptr->tx_thread_detached_joinable = osThreadDetached; + + /* Return osOK for success */ + status = osOK; + } + + return (status); +} + + +/** + * @brief The function osThreadJoin waits for the thread specified by + * thread_id to terminate. If that thread has already terminated, then + * osThreadJoin returns immediately. The thread must be joinable. + * By default threads are created with the attribute osThreadDetached. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] thread_id thread ID obtained by osThreadNew or osThreadGetId. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osThreadJoin(osThreadId_t thread_id) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = (TX_THREAD *)thread_id; + /* The control block pointer of the current running thread */ + TX_THREAD *current_thread = NULL; + /* The current thread state of the specified thread as specified by threadx */ + UINT threadx_state; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the thread ID is NULL or (tx_thread_id != TX_THREAD_ID) */ + else if ((thread_id == NULL) || (thread_ptr->tx_thread_id != TX_THREAD_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Get the current running thread */ + TX_THREAD_GET_CURRENT(current_thread); + if (current_thread == thread_id) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_thread_info_get to get the thread threadx_state */ + if (tx_thread_info_get(thread_ptr, NULL, &threadx_state, NULL, NULL, NULL, NULL, NULL, NULL) == TX_SUCCESS) + { + /* Check if the thread is joinable */ + if (thread_ptr->tx_thread_detached_joinable == osThreadJoinable) + { + /* Only one thread can Join a thread in the same time so we will + detach it momentally until it will be terminated */ + thread_ptr->tx_thread_detached_joinable = osThreadDetached; + + /* Wait until the state of the specific thread turn to terminated */ + while ((threadx_state != TX_TERMINATED) && (threadx_state != TX_COMPLETED)) + { + /* Call the tx_thread_info_get to get the thread threadx_state */ + tx_thread_info_get(thread_ptr, NULL, &threadx_state, NULL, NULL, NULL, NULL, NULL, NULL); + } + /* Once the thread is terminated it can be again Joinable */ + thread_ptr->tx_thread_detached_joinable = osThreadJoinable; + + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource error */ + status = osErrorResource; + } + } + } + + return (status); +} + +/** + * @brief The function osThreadGetCount returns the number of active threads + * or 0 in case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param none. + * @retval count number of active threads. + */ +uint32_t osThreadGetCount(void) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = NULL; + /* Returned number of active threads */ + unsigned int count = 0U; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return 0 in case of error */ + count = 0; + } + else + { + /* thread_ptr = the head pointer of the created thread list */ + thread_ptr = _tx_thread_created_ptr; + + /* Compute the number of active threads */ + while (thread_ptr != NULL) + { + /* Check the next thread validity */ + if (thread_ptr->tx_thread_id == TX_THREAD_ID) + { + /* Increment the number of active threads */ + count++; + + /* Check the state of next created thread */ + if ((thread_ptr->tx_thread_created_next != thread_ptr) + && (thread_ptr->tx_thread_created_next != _tx_thread_created_ptr)) + { + thread_ptr = thread_ptr->tx_thread_created_next; + } + else + { + break; + } + } + else + { + /* Return 0 in case of error */ + count = 0; + break; + } + } + } + + return (count); +} + +/** + * @brief The function osThreadEnumerate returns the number of enumerated + * threads or 0 in case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [out] thread_array pointer to array for retrieving thread IDs. + * [in] array_items maximum number of items in array for retrieving + * thread IDs. + * @retval count number of enumerated threads. + */ +uint32_t osThreadEnumerate(osThreadId_t *thread_array, uint32_t array_items) +{ + /* For ThreadX the control block pointer is the thread identifier */ + TX_THREAD *thread_ptr = NULL; + /* The number of enumerated threads */ + uint32_t count = 0U; + + /* Check if this API is called from Interrupt Service Routines or + if the thread_array is NULL or the array_items is equal to 0 */ + if (IS_IRQ_MODE() || (thread_array == NULL) || (array_items == 0U)) + { + /* Return 0 in case of error */ + count = 0U; + } + else + { + /* thread_ptr point to the head pointer of the created thread list */ + thread_ptr = _tx_thread_created_ptr; + + /* Compute the number of active threads */ + while ((thread_ptr != NULL) && (count < array_items)) + { + /* Check the next thread validity */ + if (thread_ptr->tx_thread_id == TX_THREAD_ID) + { + /* Retrieve the thread IDs and increment the number of active + threads */ + thread_array[count++] = thread_ptr; + + /* Check the state of next created thread */ + if ((thread_ptr->tx_thread_created_next != thread_ptr) + && (thread_ptr->tx_thread_created_next != _tx_thread_created_ptr)) + { + thread_ptr = thread_ptr->tx_thread_created_next; + } + else + { + break; + } + } + else + { + /* Return 0 in case of error */ + count = 0; + break; + } + } + } + + return (count); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------Timer Management APIs---------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osTimerNew creates an one-shot or periodic timer and + * associates it with a callback function with argument. The timer is + * in stopped state until it is started with osTimerStart. + * The function can be safely called before the RTOS is started (call + * to osKernelStart), but not before it is initialized (call to + * osKernelInitialize). + * The function osTimerNew returns the pointer to the timer object + * identifier or NULL in case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] func function pointer to callback function. + * [in] type osTimerOnce for one-shot or osTimerPeriodic for periodic + * behavior. + * [in] argument argument to the timer callback function. + * [in] attr timer attributes; NULL: default values. + * @retval timer ID for reference by other functions or NULL in case of error. + */ +osTimerId_t osTimerNew(osTimerFunc_t func, osTimerType_t type, void *argument, const osTimerAttr_t *attr) +{ + /* For TX_TIMER the control block pointer is the timer identifier */ + TX_TIMER *timer_ptr = NULL; + /* The name_ptr as null-terminated string */ + CHAR *name_ptr = NULL; + /* The timer expiration input */ + ULONG expiration_input = 0U; + /* The timer reschedule ticks */ + ULONG reschedule_ticks = 0U; + /* The size of control block */ + ULONG cb_size = sizeof(TX_TIMER); + + /* Check if this API is called from Interrupt Service Routines, + the timer callback function handler is NULL or the type is not valid */ + if (!IS_IRQ_MODE() && (func != NULL) && (type <= osTimerPeriodic)) + { + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + /* Check if the attr is not NULL */ + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the timer name_ptr */ + name_ptr = (CHAR *)attr->name; + } + + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_TIMER) */ + cb_size = sizeof(TX_TIMER); + } + else if (attr->cb_size < sizeof(TX_TIMER)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set control block size to attr->cb_size */ + cb_size = (ULONG) attr->cb_size; + } + + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the timer_ptr structure for the timer to be created */ + timer_ptr = (TX_TIMER *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (timer_ptr == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + timer_ptr = attr->cb_mem; + } + } + else + { + /* Allocate the timer_ptr structure for the timer to be created */ + timer_ptr = (TX_TIMER *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + } + + /* Check the timer type to set timer periodicity */ + if (type == osTimerPeriodic) + { + /* Specifies the number of ticks for all timer expirations after the + first. A zero for this parameter makes the timer a one-shot timer. + Otherwise, for periodic timers, legal values range from 1 through + 0xFFFFFFFF. + For periodic timer the reschedule_ticks is initiated to 1 then set to ticks + given as input in osTimerStart APIs */ + reschedule_ticks = 1; + } + + /* Check if the argument is not NULL */ + if (argument != NULL) + { + /* Set the expiration_input */ + expiration_input = (ULONG)argument; + } + + /* Call the tx_timer_create function to create the new timer */ + if (tx_timer_create(timer_ptr, name_ptr, (void(*)(ULONG))func, expiration_input, 1, reschedule_ticks, + TX_NO_ACTIVATE) != TX_SUCCESS) + { + /* Check if the memory for timer control block has been internally + allocated */ + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for timer control block */ + MemFree(timer_ptr); + } + + /* Return NULL pointer in case of error */ + timer_ptr = NULL; + } + } + + return ((osThreadId_t)timer_ptr); +} + +/** + * @brief The function osTimerGetName returns the pointer to the name string + * of the timer identified by parameter timer_id or NULL in case of an + * error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] timer_id timer ID obtained by osTimerNew. + * @retval name as null-terminated string. + */ +const char *osTimerGetName(osTimerId_t timer_id) +{ + /* For TX_TIMER the control block pointer is the timer identifier */ + TX_TIMER *timer_ptr = (TX_TIMER *)timer_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr; + + /* Check if this API is called from Interrupt Service Routines + or the timer_id is NULL */ + if (IS_IRQ_MODE() || (timer_ptr == NULL)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_timer_info_get to get the timer name_ptr */ + if (tx_timer_info_get(timer_ptr, &name_ptr, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return ((const char *)name_ptr); +} + +/** + * @brief The function osTimerIsRunning checks whether a timer specified by + * parameter timer_id is running. It returns 1 if the timer is running + * and 0 if the timer is stopped or an error occurred. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] timer_id timer ID obtained by osTimerNew. + * @retval 0 not running, 1 running. + */ +uint32_t osTimerIsRunning(osTimerId_t timer_id) +{ + /* For TX_TIMER the control block pointer is the timer identifier */ + TX_TIMER *timer_ptr = (TX_TIMER *)timer_id; + /* The active state of the timer */ + UINT active; + + /* Check if this API is called from Interrupt Service Routines or the input + timer_id in NULL */ + if (IS_IRQ_MODE() || (timer_id == NULL)) + { + /* Return 0 in case of error */ + active = 0U; + } + else + { + /* Check if the timer is valid by calling the tx_timer_info_get to get + the timer active state */ + if (tx_timer_info_get(timer_ptr, NULL, &active, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return 0 in case of error */ + active = 0U; + } + } + + return ((uint32_t)active); +} + +/** + * @brief The function osTimerStop stops a timer specified by the parameter + * timer_id. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] timer_id timer ID obtained by osTimerNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osTimerStop(osTimerId_t timer_id) +{ + /* For TX_TIMER the control block pointer is the timer identifier */ + TX_TIMER *timer_ptr = (TX_TIMER *)timer_id; + /* The returned status or error */ + osStatus_t status; + /* The active state of the timer */ + UINT active; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the timer control block is valid */ + else if ((timer_id == NULL) || (timer_ptr->tx_timer_id != TX_TIMER_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Get the timer running state */ + if (tx_timer_info_get(timer_ptr, NULL, &active, NULL, NULL, NULL) == TX_SUCCESS) + { + /* Check if the timer is running (active) */ + if (active == TX_TRUE) + { + /* Call the tx_timer_deactivate to deactivates the specified application + timer. If the timer is already deactivated, this service has no + effect. */ + if (tx_timer_deactivate(timer_ptr) == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osTimerStart starts or restarts a timer specified by + * the parameter timer_id. The parameter ticks specifies the value of + * the timer in time ticks. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] timer_id timer ID obtained by osTimerNew. + * [in] ticks time ticks value of the timer. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osTimerStart(osTimerId_t timer_id, uint32_t ticks) +{ + /* For TX_TIMER the control block pointer is the timer identifier */ + TX_TIMER *timer_ptr = (TX_TIMER *)timer_id; + /* The returned status or error */ + osStatus_t status = osOK; + /* The active state of the timer */ + UINT active; + /* The reschedule ticks of the timer */ + ULONG reschedule_ticks; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the timer control block is valid */ + else if ((timer_id == NULL) || (timer_ptr->tx_timer_id != TX_TIMER_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Get the timer running state and reschedule ticks parameters */ + if (tx_timer_info_get(timer_ptr, NULL, &active, NULL, &reschedule_ticks, NULL) == TX_SUCCESS) + { + /* Check if the timer is active. If so, it shall be stopped before being + activated again */ + if (active == TX_TRUE) + { + /* Call the tx_timer_deactivate to deactivates the specified application + timer. If the timer is already deactivated, this service has no + effect. */ + if (tx_timer_deactivate(timer_ptr) == TX_SUCCESS) + { + /* Set status osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + if (status == osOK) + { + /* Check the timer reschedule_ticks parameter for periodicity */ + if (reschedule_ticks > 0) + { + /* Set the reschedule_ticks to the input ticks */ + reschedule_ticks = ticks; + } + + /* An expired one-shot timer must be reset via tx_timer_change before + it can be activated again. */ + if (tx_timer_change(timer_ptr, ticks, reschedule_ticks) == TX_SUCCESS) + { + /* Call the tx_timer_activate to activates the specified application + timer. The expiration routines of timers that expire at the same + time are executed in the order they were activated. */ + if (tx_timer_activate(timer_ptr) == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + } + else + { + /* Return osErrorResource error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osTimerDelete deletes the timer specified by parameter + * timer_id. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] timer_id timer ID obtained by osTimerNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osTimerDelete(osTimerId_t timer_id) +{ + /* For TX_TIMER the control block pointer is the timer identifier */ + TX_TIMER *timer_ptr = (TX_TIMER *)timer_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the timer control block is valid */ + else if ((timer_id == NULL) || (timer_ptr->tx_timer_id != TX_TIMER_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_timer_delete to delete the specified application timer. */ + if (tx_timer_delete(timer_ptr) == TX_SUCCESS) + { + /* Free the already allocated memory for timer control block */ + MemFree(timer_ptr); + + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/*---------------------------------------------------------------------------*/ +/*-----------------------------Event flags APIs------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osEventFlagsNew creates a new event flags object that + * is used to send events across threads and returns the pointer to the + * event flags object identifier or NULL in case of an error. It can be + * safely called before the RTOS is started (call to osKernelStart), but + * not before it is initialized (call to osKernelInitialize). + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] attr event flags attributes; NULL: default values. + * @retval event flags ID for reference by other functions or NULL in + * case of error. + */ +osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr) +{ + /* For ThreadX the control block pointer is the event flags identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = NULL; + /* Pointer to the event flags name */ + CHAR *name_ptr = NULL; + /* The size of control block */ + ULONG cb_size = sizeof(TX_EVENT_FLAGS_GROUP); + + /* Check if this API is called from Interrupt Service Routines */ + if (!IS_IRQ_MODE()) + { + /* Check if the attr is not NULL */ + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the event flags name_ptr */ + name_ptr = (CHAR *)attr->name; + } + + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_EVENT_FLAGS_GROUP) */ + cb_size = sizeof(TX_EVENT_FLAGS_GROUP); + } + else if (attr->cb_size < sizeof(TX_EVENT_FLAGS_GROUP)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set control block size to attr->cb_size */ + cb_size = (ULONG) attr->cb_size; + } + + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the eventflags_ptr structure for the event flags to be created */ + eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (eventflags_ptr == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + eventflags_ptr = attr->cb_mem; + } + } + else + { + /* Allocate the eventflags_ptr structure for the event flags to be created */ + eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + } + + /* Call the tx_event_flags_create function to create the new event flags */ + if (tx_event_flags_create(eventflags_ptr, name_ptr) != TX_SUCCESS) + { + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for event flags control block */ + MemFree(eventflags_ptr); + } + } + } + + return ((osEventFlagsId_t)eventflags_ptr); +} + +/** + * @brief The function osEventFlagsGetName returns the pointer to the name + * string of the event flags object identified by parameter ef_id or NULL + * in case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ef_id event flags ID obtained by osEventFlagsNew. + * @retval name as null-terminated string. + */ +const char *osEventFlagsGetName(osEventFlagsId_t ef_id) +{ + /* For ThreadX the control block pointer is the event flags identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr; + + /* Check if this API is called from Interrupt Service Routines + or the ef_id is NULL */ + if (IS_IRQ_MODE() || (eventflags_ptr == NULL)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_event_flags_info_get to get the event flags name_ptr */ + if (tx_event_flags_info_get(eventflags_ptr, &name_ptr, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return (name_ptr); +} + +/** + * @brief The function osEventFlagsSet sets the event flags specified by the + * parameter flags in an event flags object specified by parameter ef_id. + * All threads waiting for the flag set will be notified to resume from + * BLOCKED state. The function returns the event flags stored in the event + * control block or an error code (highest bit is set, refer to Flags + * Functions Error Codes). + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ef_id event flags ID obtained by osEventFlagsNew. + * [in] flags specifies the flags that shall be set. + * @retval event flags after setting or error code if highest bit set. + */ +uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id; + /* The returned flags_status or error */ + uint32_t flags_status; + /* Flags to set */ + ULONG flags_to_set = (ULONG) flags; + + /* Check if the event flags ID is NULL or the event flags is invalid */ + if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)) + { + /* Return osFlagsErrorParameter error */ + flags_status = osFlagsErrorParameter; + } + else + { + /* Call the tx_event_flags_set to set flags */ + if (tx_event_flags_set(eventflags_ptr, flags_to_set, TX_OR) == TX_SUCCESS) + { + /* Call the tx_event_flags_info_get to get the current flags */ + if (tx_event_flags_info_get(eventflags_ptr, NULL, (ULONG *) &flags_status, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return osFlagsErrorUnknown in case of an error */ + flags_status = osFlagsErrorUnknown; + } + } + else + { + /* Return osFlagsErrorResource in case of error */ + flags_status = osFlagsErrorResource; + } + } + + return (flags_status); +} + +/** + * @brief The function osEventFlagsClear clears the event flags specified by + * the parameter flags in an event flags object specified by parameter + * ef_id. The function returns the event flags before clearing or an error + * code (highest bit is set, refer to Flags Functions Error Codes). + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ef_id event flags ID obtained by osEventFlagsNew. + * [in] flags specifies the flags that shall be cleared. + * @retval event flags before clearing or error code if highest bit set. + */ +uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id; + /* The returned flags_status or error */ + uint32_t flags_status; + /* Flags to clear */ + ULONG flags_to_clear = (ULONG) ~flags; + + /* Check if the event flags ID is NULL or the event flags is invalid */ + if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)) + { + /* Return osFlagsErrorParameter error */ + flags_status = osFlagsErrorParameter; + } + else + { + /* Call the tx_event_flags_info_get to get the current flags */ + if (tx_event_flags_info_get(eventflags_ptr, NULL, (ULONG *) &flags_status, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return osFlagsErrorUnknown in case of an error */ + flags_status = osFlagsErrorUnknown; + } + else + { + /* Call the tx_event_flags_set to set flags */ + if (tx_event_flags_set(eventflags_ptr, flags_to_clear, TX_AND) != TX_SUCCESS) + { + /* Return osFlagsErrorResource in case of error */ + flags_status = osFlagsErrorResource; + } + } + } + + return (flags_status); +} + +/** + * @brief The function osEventFlagsGet returns the event flags currently set + * in an event flags object specified by parameter ef_id or 0 in case of + * an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ef_id event flags ID obtained by osEventFlagsNew. + * @retval current event flags. + */ +uint32_t osEventFlagsGet(osEventFlagsId_t ef_id) +{ + /* For ThreadX the control block pointer is the event flags identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id; + /* The current flags */ + uint32_t current_flags = 0; + + /* Check if the event flags ID is NULL or the event flags is invalid */ + if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)) + { + /* Return 0 in case of an error */ + current_flags = 0; + } + else + { + /* Call the tx_event_flags_info_get to get the current flags */ + if (tx_event_flags_info_get(eventflags_ptr, NULL, (ULONG *) ¤t_flags, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return 0 in case of an error */ + current_flags = 0; + } + } + + return (current_flags); +} + +/** + * @brief The function osEventFlagsWait suspends the execution of the + * currently RUNNING thread until any or all event flags specified by the + * parameter flags in the event object specified by parameter ef_id are + * set. When these event flags are already set, the function returns + * instantly. Otherwise, the thread is put into the state BLOCKED. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ef_id event flags ID obtained by osEventFlagsNew. + * [in] flags specifies the flags to wait for. + * [in] options specifies flags options (osFlagsXxxx). + * [in] timeout Timeout Value or 0 in case of no time-out. + * @retval event flags before clearing or error code if highest bit set. + */ +uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, + uint32_t options, uint32_t timeout) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id; + /* Flags to get */ + ULONG requested_flags = (ULONG) flags; + /* The ThreadX wait option */ + ULONG wait_option = (ULONG) timeout; + /* The ThreadX get options */ + UINT get_option = 0; + /* The actual flags */ + ULONG actual_flags; + /* ThreadX APIs status */ + UINT status; + + /* Check if the event flags ID is NULL or the event flags is invalid or non-zero timeout specified in an ISR */ + if ((IS_IRQ_MODE() && (timeout != 0)) || (ef_id == NULL) || + (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)) + { + /* Return osFlagsErrorParameter error */ + actual_flags = osFlagsErrorParameter; + } + else + { + /* No clear option is used */ + if ((options & osFlagsNoClear) == osFlagsNoClear) + { + if ((options & osFlagsWaitAll) == osFlagsWaitAll) + { + /* AND event option is used */ + get_option = TX_AND; + } + else + { + /* OR event option is used */ + get_option = TX_OR; + } + } + /* Clear option is used */ + else + { + if ((options & osFlagsWaitAll) == osFlagsWaitAll) + { + /* AND clear event option is used */ + get_option = TX_AND_CLEAR; + } + else + { + /* OR clear event option is used */ + get_option = TX_OR_CLEAR; + } + } + /* Call the tx_event_flags_get to get flags */ + status = tx_event_flags_get(eventflags_ptr, requested_flags, get_option, &actual_flags, wait_option); + /* Check the status */ + if ((status == TX_NO_EVENTS) || (status == TX_WAIT_ERROR)) + { + /* Return osFlagsErrorTimeout for timeout error */ + actual_flags = osFlagsErrorTimeout; + } + else if (status != TX_SUCCESS) + { + /* Return osFlagsErrorResource in case of an error */ + actual_flags = osFlagsErrorResource ; + } + } + + return ((uint32_t)actual_flags); +} + +/** + * @brief The function osEventFlagsDelete deletes the event flags object + * specified by parameter ef_id and releases the internal memory obtained + * for the event flags handling. After this call, the ef_id is no longer + * valid and cannot be used. This can cause starvation of threads that are + * waiting for flags of this event object. The ef_id may be created again + * using the function osEventFlagsNew. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] ef_id event flags ID obtained by osEventFlagsNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id) +{ + /* For ThreadX the control block pointer is the event flags identifier */ + TX_EVENT_FLAGS_GROUP *eventflags_ptr = (TX_EVENT_FLAGS_GROUP *)ef_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the event flags ID is NULL or the event flags is invalid */ + else if ((ef_id == NULL) || (eventflags_ptr -> tx_event_flags_group_id != TX_EVENT_FLAGS_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_event_flags_delete to delete the event flags object */ + if (tx_event_flags_delete(eventflags_ptr) == TX_SUCCESS) + { + /* Free the already allocated memory for thread control block */ + if (MemFree(eventflags_ptr) == osOK) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + return (status); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------Mutex Management APIs---------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osMutexNew creates and initializes a new mutex + * object and returns the pointer to the mutex object identifier or + * NULL in case of an error. It can be safely called before the RTOS + * is started (call to osKernelStart), but not before it is initialized + * call to osKernelInitialize). + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] attr mutex attributes; NULL: default values. + * @retval mutex ID for reference by other functions or NULL in case of error. + */ +osMutexId_t osMutexNew(const osMutexAttr_t *attr) +{ + /* For ThreadX the control block pointer is the mutex identifier */ + TX_MUTEX *mutex_ptr = NULL; + /* Pointer to the mutex name */ + CHAR *name_ptr = NULL; + /* The mutex inherit status */ + UINT inherit = TX_NO_INHERIT; + /* The size of control block */ + ULONG cb_size = sizeof(TX_MUTEX); + + /* Check if this API is called from Interrupt Service Routines */ + if (!IS_IRQ_MODE()) + { + /* Check if the attr is not NULL */ + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the mutex name_ptr */ + name_ptr = (CHAR *)attr->name; + } + /* Check if the attr_bits is not zero */ + if (attr->attr_bits != 0) + { + /* Check the mutex inherit status */ + if ((attr->attr_bits & osMutexPrioInherit) == osMutexPrioInherit) + { + inherit = TX_INHERIT; + } + else + { + inherit = TX_NO_INHERIT; + } + } + else + { + inherit = TX_NO_INHERIT; + } + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_MUTEX) */ + cb_size = sizeof(TX_MUTEX); + } + else if (attr->cb_size < sizeof(TX_MUTEX)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set control block size to attr->cb_size */ + cb_size = (ULONG) attr->cb_size; + } + + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the mutex_ptr structure for the mutex to be created */ + mutex_ptr = (TX_MUTEX *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (mutex_ptr == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + mutex_ptr = attr->cb_mem; + } + } + else + { + /* Allocate the mutex_ptr structure for the mutex to be created */ + mutex_ptr = (TX_MUTEX *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + } + + /* Call the tx_mutex_create function to create the new mutex */ + if (tx_mutex_create(mutex_ptr, name_ptr, inherit) != TX_SUCCESS) + { + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for mutex control block */ + MemFree(mutex_ptr); + } + } + } + + return ((osMutexId_t)mutex_ptr); +} + +/** + * @brief The function osMutexGetName returns the pointer to the name string + * of the mutex identified by parameter mutex_id or NULL in case of + * an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mutex_id mutex ID obtained by osMutexNew. + * @retval name as null-terminated string. + */ +const char *osMutexGetName(osMutexId_t mutex_id) +{ + /* For ThreadX the control block pointer is the mutex identifier */ + TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr; + + /* Check if this API is called from Interrupt Service Routines + or the mutex_id is NULL or the mutex is invalid */ + if (IS_IRQ_MODE() || (mutex_ptr == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_mutex_info_get to get the mutex name_ptr */ + if (tx_mutex_info_get(mutex_ptr, &name_ptr, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return (name_ptr); +} + +/** + * @brief The blocking function osMutexAcquire waits until a mutex object + * specified by parameter mutex_id becomes available. If no other thread + * has obtained the mutex, the function instantly returns and blocks + * the mutex object. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mutex_id mutex ID obtained by osMutexNew. + * [in] timeout Timeout Value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMutexAcquire(osMutexId_t mutex_id, uint32_t timeout) +{ + /* For ThreadX the control block pointer is the mutex identifier */ + TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id; + /* The returned status or error */ + osStatus_t status; + /* The ThreadX wait option */ + ULONG wait_option = (ULONG) timeout; + /* The tx_mutex_get returned status */ + UINT tx_status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the mutex ID is NULL or the mutex is invalid */ + else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_mutex_get to get the mutex object */ + tx_status = tx_mutex_get(mutex_ptr, wait_option); + if (tx_status == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else if ((tx_status == TX_WAIT_ABORTED) || (tx_status == TX_NOT_AVAILABLE)) + { + /* Return osErrorTimeout when the mutex is not obtained in the given time */ + status = osErrorTimeout; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osMutexRelease releases a mutex specified by parameter + * mutex_id. Other threads that currently wait for this mutex will be + * put into the READY state. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mutex_id mutex ID obtained by osMutexNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMutexRelease(osMutexId_t mutex_id) +{ + /* For ThreadX the control block pointer is the mutex identifier */ + TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the mutex ID is NULL or the mutex is invalid */ + else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_mutex_put to put the mutex object */ + if (tx_mutex_put(mutex_ptr) == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osMutexGetOwner returns the thread ID of the thread + * that acquired a mutex specified by parameter mutex_id. In case of an + * error or if the mutex is not blocked by any thread, it returns NULL. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mutex_id mutex ID obtained by osMutexNew. + * @retval thread ID of owner thread or NULL when mutex was not acquired. + */ +osThreadId_t osMutexGetOwner(osMutexId_t mutex_id) +{ + /* For ThreadX the control block pointer is the mutex identifier */ + TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id; + /* The owner thread of the mutex object */ + TX_THREAD *thread_ptr = NULL; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return NULL when the API is called from ISR */ + thread_ptr = NULL; + } + /* Check if the mutex ID is NULL or the mutex is invalid */ + else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)) + { + /* Return NULL when mutex_id is NULL */ + thread_ptr = NULL; + } + else + { + /* Call the tx_mutex_info_get to get the mutex thread owner */ + if (tx_mutex_info_get(mutex_ptr, NULL, NULL, &thread_ptr, NULL, NULL, NULL) == TX_SUCCESS) + { + if (thread_ptr == TX_NULL) + { + /* Return NULL when mutex object is not acquired */ + thread_ptr = NULL; + } + } + else + { + /* Return NULL when mutex_id is invalid */ + thread_ptr = NULL; + } + } + + return ((osThreadId_t)thread_ptr); +} + +/** + * @brief The function osMutexDelete deletes a mutex object specified by + * parameter mutex_id. It releases internal memory obtained for mutex + * handling. After this call, the mutex_id is no longer valid and cannot + * be used. The mutex may be created again using the function osMutexNew. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mutex_id mutex ID obtained by osMutexNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMutexDelete(osMutexId_t mutex_id) +{ + /* For ThreadX the control block pointer is the mutex identifier */ + TX_MUTEX *mutex_ptr = (TX_MUTEX *)mutex_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the mutex ID is NULL or the mutex is invalid*/ + else if ((mutex_id == NULL) || (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_mutex_delete to delete the mutex object */ + if (tx_mutex_delete(mutex_ptr) == TX_SUCCESS) + { + /* Free the already allocated memory for mutex control block */ + if (MemFree(mutex_ptr) == osOK) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/*---------------------------------------------------------------------------*/ +/*------------------------------Semaphores APIs------------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osSemaphoreNew creates and initializes a semaphore + * object that is used to manage access to shared resources and returns + * the pointer to the semaphore object identifier or NULL in case of an + * error. It can be safely called before the RTOS is started + * (call to osKernelStart), but not before it is initialized + * (call to osKernelInitialize). + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] max_count maximum number of available tokens. + * [in] initial_count initial number of available tokens. + * [in] attr semaphore attributes; NULL: default values. + * @retval semaphore ID for reference by other functions or NULL in case of error. + */ +osSemaphoreId_t osSemaphoreNew(uint32_t max_count, uint32_t initial_count, const osSemaphoreAttr_t *attr) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_SEMAPHORE *semaphore_ptr = NULL; + /* Pointer to the semaphore name */ + CHAR *name_ptr = NULL; + /* The semaphore initial count */ + ULONG init_count = (ULONG) initial_count; + /* The size of control block */ + ULONG cb_size = sizeof(TX_SEMAPHORE); + + /* Check if this API is called from Interrupt Service Routines */ + if (!IS_IRQ_MODE()) + { + /* Check if the attr is not NULL */ + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the semaphore name_ptr */ + name_ptr = (CHAR *)attr->name; + } + + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_SEMAPHORE) */ + cb_size = sizeof(TX_SEMAPHORE); + } + else if (attr->cb_size < sizeof(TX_SEMAPHORE)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set control block size to attr->cb_size */ + cb_size = (ULONG) attr->cb_size; + } + + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the semaphore_ptr structure for the semaphore to be created */ + semaphore_ptr = (TX_SEMAPHORE *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (semaphore_ptr == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + semaphore_ptr = attr->cb_mem; + } + } + else + { + /* Allocate the semaphore_ptr structure for the semaphore to be created */ + semaphore_ptr = (TX_SEMAPHORE *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + } + + + /* Call the tx_semaphore_create function to create the new semaphore */ + if (tx_semaphore_create(semaphore_ptr, name_ptr, init_count) != TX_SUCCESS) + { + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for semaphore control block */ + MemFree(semaphore_ptr); + } + } + } + + return ((osSemaphoreId_t)semaphore_ptr); +} + +/** + * @brief The function osSemaphoreGetName returns the pointer to the name + * string of the semaphore identified by parameter semaphore_id or NULL + * in case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew. + * @retval name as null-terminated string. + */ +const char *osSemaphoreGetName(osSemaphoreId_t semaphore_id) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr; + + /* Check if this API is called from Interrupt Service Routines or the semaphore_id is NULL + and the semaphore is invalid */ + if (IS_IRQ_MODE() || (semaphore_ptr == NULL) || (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_semaphore_info_get to get the semaphore name_ptr */ + if (tx_semaphore_info_get(semaphore_ptr, &name_ptr, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return (name_ptr); +} + +/** + * @brief The blocking function osSemaphoreAcquire waits until a token of the + * semaphore object specified by parameter semaphore_id becomes available. + * If a token is available, the function instantly returns and decrements + * the token count. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew. + * [in] timeout Timeout Value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osSemaphoreAcquire(osSemaphoreId_t semaphore_id, uint32_t timeout) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id; + /* The returned status or error */ + osStatus_t status; + /* The ThreadX wait option */ + ULONG wait_option = (ULONG) timeout; + /* The tx_semaphore_get returned status */ + UINT tx_status; + + /* Check if the semaphore ID is NULL or the semaphore is invalid or non-zero timeout specified in an ISR */ + if ((IS_IRQ_MODE() && (timeout != 0)) || (semaphore_id == NULL) || + (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_semaphore_get to get the semaphore object */ + tx_status = tx_semaphore_get(semaphore_ptr, wait_option); + if (tx_status == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else if ((tx_status == TX_WAIT_ABORTED) || (tx_status == TX_NO_INSTANCE)) + { + /* Return osErrorTimeout when the semaphore is not obtained + in the given time */ + status = osErrorTimeout; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osSemaphoreRelease releases a token of the semaphore + * object specified by parameter semaphore_id. Tokens can only be released + * up to the maximum count specified at creation time, see osSemaphoreNew. + * Other threads that currently wait for a token of this semaphore object + * will be put into the READY state. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osSemaphoreRelease(osSemaphoreId_t semaphore_id) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if the semaphore ID is NULL or the semaphore is invalid */ + if ((semaphore_id == NULL) || (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_semaphore_put to put the semaphore object */ + if (tx_semaphore_put(semaphore_ptr) == TX_SUCCESS) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osSemaphoreDelete deletes a semaphore object specified + * by parameter semaphore_id. It releases internal memory obtained for + * semaphore handling. After this call, the semaphore_id is no longer + * valid and cannot be used. The semaphore may be created again using + * the function osSemaphoreNew. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] semaphore_id semaphore ID obtained by osSemaphoreNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osSemaphoreDelete(osSemaphoreId_t semaphore_id) +{ + /* For ThreadX the control block pointer is the semaphore identifier */ + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *)semaphore_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the semaphore ID is NULL or the semaphore is invalid */ + else if ((semaphore_id == NULL) || (semaphore_ptr -> tx_semaphore_id != TX_SEMAPHORE_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_semaphore_delete to delete the semaphore object */ + if (tx_semaphore_delete(semaphore_ptr) == TX_SUCCESS) + { + /* Free the already allocated memory for semaphore control block */ + if (MemFree(semaphore_ptr) == osOK) + { + /* Return osOK for success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + return (status); +} + +/*---------------------------------------------------------------------------*/ +/*------------------------------Message Queue APIs---------------------------*/ +/*---------------------------------------------------------------------------*/ + +/** + * @brief The function osMessageQueueNew creates and initializes a message queue + * object. The function returns a message queue object identifier + * or NULL in case of an error. + * The function can be called after kernel initialization with osKernelInitialize. + * It is possible to create message queue objects before the RTOS kernel is + * started with osKernelStart. + * The total amount of memory required for the message queue data is at least + * msg_count * msg_size. The msg_size is rounded up to a double even number to + * ensure 32-bit alignment of the memory blocks. + * The memory blocks allocated from the message queue have a fixed size defined + * with the parameter msg_size. + * Note : This function Cannot be called from Interrupt Service + * Routines. + * @param [in] msg_count maximum number of messages in queue. + * [in] msg_size maximum message size in bytes. + * [in] attr message queue attributes; NULL: default values. + * @retval message queue ID for reference by other functions or NULL in case of error. + */ +osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = NULL; + /* Pointer to the message queue name */ + CHAR *name_ptr = NULL; + /* Pointer to start address of the message queue data */ + VOID *queue_start = NULL; + /* The message queue data size */ + ULONG queue_size = 0U; + /* The message queue control block size */ + ULONG cb_size = 0U; + + /* Check if this API is called from Interrupt Service Routines or the msg_count + is equal to 0 or msg_size is equal to 0 */ + if (!IS_IRQ_MODE() && (msg_count > 0) && (msg_size > 0)) + { + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + /* The msg_size is rounded up to a double even number to ensure 32-bit alignment of the memory blocks. */ + msg_size = msg_size + (msg_size % sizeof(ULONG)); + + /* Check if the attr is not NULL */ + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the message queue name_ptr */ + name_ptr = (CHAR *)attr->name; + } + + /* Check if the message queue data size is equal to 0 */ + if (attr->mq_size == 0U) + { + /* Set message queue data size to msg_count * msg_size (The total amount of memory required + for the message queue data) */ + queue_size = msg_count * msg_size; + } + else if (attr->mq_size < (msg_count * msg_size)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else if (attr->mq_size < TX_BYTE_POOL_MIN) + { + /* Set message queue data size to TX_BYTE_POOL_MIN */ + queue_size = TX_BYTE_POOL_MIN; + } + else + { + /* Set message queue data size to attr->mq_size */ + queue_size = (ULONG)attr->mq_size; + } + + /* Check if the input message queue data pointer is NULL */ + if (attr->mq_mem == NULL) + { + /* Allocate the data for the message queue to be created */ + queue_start = MemAlloc(queue_size, RTOS2_BYTE_POOL_STACK_TYPE); + if (queue_start == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + if (attr->mq_size == 0U) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set message queue data size to attr->mq_size */ + queue_size = (ULONG)attr->mq_size; + } + + /* The message queue data shall point to the input message queue data memory address */ + queue_start = attr->mq_mem; + } + + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_QUEUE) */ + cb_size = sizeof(TX_QUEUE); + } + else if (attr->cb_size < sizeof(TX_QUEUE)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set message queue data size to attr->cb_size */ + cb_size = (ULONG)attr->cb_size; + } + + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the queue_ptr structure for the message queue to be created */ + queue_ptr = (TX_QUEUE *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (queue_ptr == NULL) + { + /* Check if the memory for message queue data has been internally allocated */ + if (attr->mq_mem == NULL) + { + /* Free the already allocated memory for message queue data */ + MemFree(queue_start); + } + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + queue_ptr = attr->cb_mem; + } + } + else + { + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + /* Initialize the message queue data size to msg_count * msg_size (The total amount of memory required + for the message queue data) */ + queue_size = msg_count * msg_size; + + /* Allocate the data for the message queue to be created */ + queue_start = MemAlloc(queue_size, RTOS2_BYTE_POOL_STACK_TYPE); + if (queue_start == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + + /* Allocate the queue_ptr structure for the message queue to be created */ + queue_ptr = (TX_QUEUE *)MemAlloc(sizeof(TX_QUEUE), RTOS2_BYTE_POOL_HEAP_TYPE); + if (queue_ptr == NULL) + { + /* Free the already allocated memory for message queue data */ + MemFree(queue_start); + + /* Return NULL pointer in case of error */ + return (NULL); + } + } + + /* For threadX the message size is in 32-Bits */ + msg_size = msg_size / sizeof(ULONG); + + /* Call the tx_queue_create function to create the new message queue */ + if (tx_queue_create(queue_ptr, name_ptr, msg_size, queue_start, queue_size) != TX_SUCCESS) + { + /* Check if the memory for message queue control block has been internally + allocated */ + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for message queue control block */ + MemFree(queue_ptr); + } + + /* Check if the memory for message queue data has been internally allocated */ + if ((attr->mq_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for message queue data */ + MemFree(queue_start); + } + + /* Return NULL pointer in case of error */ + queue_ptr = NULL; + } + } + + return ((osMessageQueueId_t)queue_ptr); +} + +/** + * @brief The function osMessageQueueGetName returns the pointer to the name + * string of the message queue identified by parameter mq_id or NULL in + * case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval name_ptr as null-terminated string. + */ +const char *osMessageQueueGetName(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr = NULL; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mq_id->tx_queue_id != TX_QUEUE_ID */ + if (IS_IRQ_MODE() || (queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_queue_info_get to get the queue name_ptr */ + if (tx_queue_info_get(queue_ptr, &name_ptr, NULL, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return (name_ptr); +} + +/** + * @brief The function osMessageQueueGetCapacity returns the maximum number of + * messages in the message queue object specified by parameter mq_id or + * 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval maximum number of messages. + */ +uint32_t osMessageQueueGetCapacity(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The specific maximum number of messages */ + uint32_t max_messages_number; + + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */ + if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return 0 in case of error */ + max_messages_number = 0U; + } + else + { + /* Return the total number of messages in the queue */ + max_messages_number = queue_ptr->tx_queue_capacity; + } + + return (max_messages_number); +} + +/** + * @brief The function osMessageQueueGetMsgSize returns the maximum message + * size in bytes for the message queue object specified by parameter + * mq_id or 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval maximum message size in bytes. + */ +uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The specific maximum message size in bytes */ + uint32_t max_messages_size; + + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */ + if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return 0 in case of error */ + max_messages_size = 0U; + } + else + { + /* Return the message size that was specified in queue creation */ + max_messages_size = queue_ptr->tx_queue_message_size * sizeof(ULONG); + } + + return (max_messages_size); +} + +/** + * @brief The function osMessageQueueGetCount returns the number of queued + * messages in the message queue object specified by parameter mq_id or + * 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval number of queued messages. + */ +uint32_t osMessageQueueGetCount(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The specific number of queued messages */ + uint32_t queued_messages_number = 0U; + + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */ + if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return 0 in case of error */ + queued_messages_number = 0U; + } + else + { + /* Call the tx_queue_info_get to get the number of queued messages */ + if (tx_queue_info_get(queue_ptr, NULL, (ULONG *)&queued_messages_number, NULL, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return 0 in case of error */ + queued_messages_number = 0U; + } + } + + return (queued_messages_number); +} + +/** + * @brief The function osMessageQueueGetSpace returns the number available + * slots for messages in the message queue object specified by + * parameter mq_id or 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval number of available slots for messages. + */ +uint32_t osMessageQueueGetSpace(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The specific number of queued messages */ + uint32_t queue_messages_free_slots = 0U; + + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */ + if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return 0 in case of error */ + queue_messages_free_slots = 0U; + } + else + { + /* Call the tx_queue_info_get to get the number of available slots for + messages */ + if (tx_queue_info_get(queue_ptr, NULL, NULL, (ULONG *)&queue_messages_free_slots, NULL, NULL, NULL) != TX_SUCCESS) + { + /* Return 0 in case of error */ + queue_messages_free_slots = 0U; + } + } + + return (queue_messages_free_slots); +} + +/** + * @brief The function osMessageQueueReset resets the message queue specified + * by the parameter mq_id. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMessageQueueReset(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */ + else if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_queue_flush deletes all messages stored in the specified + message queue */ + if (tx_queue_flush(queue_ptr) == TX_SUCCESS) + { + /* Return osOK in case of success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The function osMessageQueueDelete deletes a message queue object + * specified by parameter mq_id. It releases internal memory obtained + * for message queue handling. After this call, the mq_id is no longer + * valid and cannot be used. The message queue may be created again + * using the function osMessageQueueNew. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMessageQueueDelete(osMessageQueueId_t mq_id) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The returned status or error */ + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines */ + if (IS_IRQ_MODE()) + { + /* Return osErrorISR error */ + status = osErrorISR; + } + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID */ + else if ((queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_queue_delete deletes the specified message queue */ + if (tx_queue_delete(queue_ptr) == TX_SUCCESS) + { + /* Free the already allocated memory for message queue data */ + MemFree(queue_ptr->tx_queue_start); + + /* Free the already allocated memory for message queue control block */ + MemFree(queue_ptr); + + /* Return osOK in case of success */ + status = osOK; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/** + * @brief The blocking function osMessageQueuePut puts the message pointed to + * by msg_ptr into the the message queue specified by parameter mq_id. + * The parameter msg_prio is used to sort message according their + * priority (higher numbers indicate a higher priority) on insertion. + * The parameter timeout specifies how long the system waits to put the + * message into the queue. While the system waits, the thread that is + * calling this function is put into the BLOCKED state. The parameter + * timeout can have the following values: + * * when timeout is 0, the function returns instantly (i.e. try + * semantics). + * * when timeout is set to osWaitForever the function will wait for an + * infinite time until the message is delivered (i.e. wait semantics). + * * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * [in] msg_ptr pointer to buffer with message to put into a queue. + * [in] msg_prio message priority. + * [in] timeout Timeout Value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMessageQueuePut(osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The returned value from ThreadX call */ + UINT tx_status; + /* The returned status or error */ + osStatus_t status; + + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID or non-zero timeout specified in an ISR */ + if ((IS_IRQ_MODE() && (timeout != 0)) || (queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID) || + (msg_ptr == NULL)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_queue_send to send a message to the specified message queue */ + tx_status = tx_queue_send(queue_ptr, (void *)msg_ptr, timeout); + if (tx_status == TX_SUCCESS) + { + /* Return osOK in case of success */ + status = osOK; + } + else if (tx_status == TX_QUEUE_FULL) + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + else + { + /* Return osErrorTimeout in case of error */ + status = osErrorTimeout; + } + } + + return (status); +} + +/** + * @brief The function osMessageQueueGet retrieves a message from the message + * queue specified by the parameter mq_id and saves it to the buffer pointed + * to by the parameter msg_ptr. The message priority is stored to parameter + * msg_prio if not token{NULL}. + * The parameter timeout specifies how long the system waits to retrieve + * the message from the queue. While the system waits, the thread that is + * calling this function is put into the BLOCKED state. + * The parameter timeout can have the following values: + * * when timeout is 0, the function returns instantly (i.e. try + * semantics). + * * when timeout is set to osWaitForever the function will wait for an + * infinite time until the message is delivered (i.e. wait semantics). + * * all other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mq_id message queue ID obtained by osMessageQueueNew. + * [out] msg_ptr pointer to buffer for message to get from a queue. + * [out] msg_prio pointer to buffer for message priority or NULL. + * [in] timeout Timeout Value or 0 in case of no time-out. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMessageQueueGet(osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) +{ + /* For TX_QUEUE the control block pointer is the queue identifier */ + TX_QUEUE *queue_ptr = (TX_QUEUE *)mq_id; + /* The returned value from ThreadX call */ + UINT tx_status; + /* The returned status or error */ + osStatus_t status; + + /* Check if the mq_id is NULL or queue_ptr->tx_queue_id != TX_QUEUE_ID or non-zero timeout specified in an ISR */ + if ((IS_IRQ_MODE() && (timeout != 0)) || (queue_ptr == NULL) || (queue_ptr->tx_queue_id != TX_QUEUE_ID) || + (msg_ptr == NULL)) + { + /* Return osErrorParameter error */ + status = osErrorParameter; + } + else + { + /* Call the tx_queue_receive to retrieves a message from the specified message queue */ + tx_status = tx_queue_receive(queue_ptr, msg_ptr, timeout); + if (tx_status == TX_SUCCESS) + { + /* Return osOK in case of success */ + status = osOK; + } + else if (tx_status == TX_QUEUE_EMPTY) + { + /* Return osErrorTimeout in case of error */ + status = osErrorTimeout; + } + else if (tx_status == TX_WAIT_ERROR) + { + /* Return osErrorParameter when a non-zero timeout is used in ISR context */ + status = osErrorParameter; + } + else + { + /* Return osErrorResource in case of error */ + status = osErrorResource; + } + } + + return (status); +} + +/*---------------------------------------------------------------------------*/ +/*---------------------------Memory Pool Management APIs---------------------*/ +/*---------------------------------------------------------------------------*/ +/** + * @brief The function osMemoryPoolNew creates and initializes a memory pool + * object and returns the pointer to the memory pool object identifier + * or NULL in case of an error. It can be safely called before the RTOS + * is started (call to osKernelStart), but not before it is initialized + * (call to osKernelInitialize). + * The total amount of memory needed is at least block_count * block_size. + * Memory from the pool can only be allocated/freed in fixed portions + * of block_size. + * Note : This function cannot be called from Interrupt Service Routines. + * @param [in] block_count maximum number of memory blocks in memory pool. + * [in] block_size memory block size in bytes. + * [in] attr memory pool attributes; NULL: default values. + * @retval memory pool ID for reference by other functions or NULL in case of error. + */ +osMemoryPoolId_t osMemoryPoolNew (uint32_t block_count, uint32_t block_size, const osMemoryPoolAttr_t *attr) +{ + /* For TX_BLOCK_POOL the control block pointer is the memory pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = NULL; + /* Pointer to memory pool named */ + CHAR *name_ptr = NULL; + /* Pointer to start address of the memory pool storage data */ + VOID * pool_start = NULL; + /* The memory pool data size */ + UINT pool_size = 0U; + /* The memory pool control block size */ + ULONG cb_size = 0U; + + /* Check if this API is called from Interrupt Service Routines or the block_count + is equal to 0 or block_size is equal to 0 */ + if ((!IS_IRQ_MODE() && (block_size != 0) && (block_count != 0))) + { + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + if (attr != NULL) + { + /* Check if the name_ptr is not NULL */ + if (attr->name != NULL) + { + /* Set the message queue name_ptr */ + name_ptr = (CHAR *)attr->name; + } + /* Check if the memory pool data storage size is equal to 0 */ + if (attr->mp_size == 0U) + { + /* Set memory pool data size to block_count * block_size (The total amount of memory required + for the memory pool data storage) */ + pool_size = block_count * block_size; + } + else if (attr->mp_size < (pool_size)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else if (attr->mp_size < TX_BYTE_POOL_MIN) + { + /* Set memory pool data size to TX_BYTE_POOL_MIN */ + pool_size = TX_BYTE_POOL_MIN; + } + else + { + /* Set memory pool data size to attr->mp_size */ + pool_size = (ULONG)attr->mp_size; + } + /* Check if the input memory pool data pointer is NULL */ + if (attr->mp_mem == NULL) + { + /* Allocate the data for the memory pool to be created */ + pool_start = MemAlloc(pool_size, RTOS2_BYTE_POOL_STACK_TYPE); + if (pool_start == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + if (attr->mp_size == 0U) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set memory pool data size to attr->mp_size */ + pool_size = (ULONG)attr->mp_size; + } + + /* The memory pool shall point to the memory pool data memory address */ + pool_start = attr->mp_mem; + } + /* Check if the control block size is equal to 0 */ + if (attr->cb_size == 0U) + { + /* Set control block size to sizeof(TX_BLOCK_POOL) */ + cb_size = sizeof(TX_BLOCK_POOL); + } + else if (attr->cb_size < sizeof(TX_BLOCK_POOL)) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + else + { + /* Set memory pool data size to attr->cb_size */ + cb_size = (ULONG)attr->cb_size; + } + /* Check if the input control block pointer is NULL */ + if (attr->cb_mem == NULL) + { + /* Allocate the block_pool_ptr structure for the memory pool to be created */ + block_pool_ptr = (TX_BLOCK_POOL *)MemAlloc(cb_size, RTOS2_BYTE_POOL_HEAP_TYPE); + if (block_pool_ptr == NULL) + { + /* Check if the memory for memory pool data has been internally allocated */ + if (attr->mp_mem == NULL) + { + /* Free the already allocated memory for memory pool data */ + MemFree(pool_start); + } + /* Return NULL pointer in case of error */ + return (NULL); + } + } + else + { + /* The control block shall point to the input cb_mem memory address */ + block_pool_ptr = attr->cb_mem; + } + } + else /* attr == NULL*/ + { + /* Initialize the name_ptr to NULL */ + name_ptr = NULL; + + /* Initialize the memory pool data size to block_count * block_size (The total amount of memory required + for the memory pool data storage) */ + pool_size = block_count * block_size; + + /* Allocate the data for pool_start to be created */ + pool_start = MemAlloc(pool_size, RTOS2_BYTE_POOL_STACK_TYPE); + + if (pool_start == NULL) + { + /* Return NULL pointer in case of error */ + return (NULL); + } + /* Allocate the block_pool_ptr structure for the block pool to be created */ + block_pool_ptr = (TX_BLOCK_POOL *)MemAlloc(sizeof(TX_BLOCK_POOL), RTOS2_BYTE_POOL_HEAP_TYPE); + + if (block_pool_ptr == NULL) + { + /* Free the already allocated memory for block pool data */ + MemFree(pool_start); + /* Return NULL pointer in case of error */ + return (NULL); + } + } + /* Call the tx_block_pool_create function to create the new memory pool */ + if (tx_block_pool_create(block_pool_ptr, name_ptr, block_size, pool_start, pool_size) != TX_SUCCESS) + { + /* Check if the memory for memory pool control block has been internally + allocated */ + if ((attr->cb_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for memory pool control block */ + MemFree(block_pool_ptr); + } + + /* Check if the memory for memory pool data has been internally allocated */ + if ((attr->mp_mem == NULL) || (attr == NULL)) + { + /* Free the already allocated memory for memory pool data */ + MemFree(pool_start); + } + + /* Return NULL pointer in case of error */ + block_pool_ptr = NULL; + } + } + else + { + block_pool_ptr = NULL; + } + + return((osMemoryPoolId_t)(block_pool_ptr)); +} + +/** + * @brief The function osMemoryPoolGetName returns the pointer to the name + * string of the memory pool identified by parameter mp_id or NULL in + * case of an error. + * Note : This function cannot be called from Interrupt Service + * Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @retval maximum number of memory blocks in the memory pool object. + */ +const char *osMemoryPoolGetName(osMemoryPoolId_t mp_id) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + /* The output name_ptr as null-terminated string */ + CHAR *name_ptr = NULL; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if (IS_IRQ_MODE() || (block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + else + { + /* Call the tx_block_pool_info_get to get the block_pool name_ptr */ + if (tx_block_pool_info_get(block_pool_ptr, &name_ptr, TX_NULL,TX_NULL, TX_NULL,TX_NULL, TX_NULL)!= TX_SUCCESS) + { + /* Return NULL in case of an error */ + name_ptr = NULL; + } + } + + return (name_ptr); +} +/** + * @brief The blocking function osMemoryPoolAlloc allocates the memory pool + * parameter mp_id and returns a pointer to the address of the allocated + * memory or 0 in case of an error. + * The parameter timeout specifies how long the system waits to allocate + * the memory. While the system waits, the thread that is calling this + * function is put into the BLOCKED state. The thread will become READY + * as soon as at least one block of memory gets available. + * The parameter timeout can have the following values: + * - when timeout is 0, the function returns instantly (i.e. try semantics). + * - when timeout is set to osWaitForever the function will wait for an + * infinite time until the memory is allocated (i.e. wait semantics). + * - All other values specify a time in kernel ticks for a timeout + * (i.e. timed-wait semantics). + * Note : + * - This function may be called from Interrupt Service Routines. + * - It is in the responsibility of the user to respect the block size, + * i.e. not access memory beyond the blocks limit. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @param [in] timeout Timeout Value or 0 in case of no time-out. + * @retval address of the allocated memory block or NULL in case of no memory + * is available. + */ +void * osMemoryPoolAlloc(osMemoryPoolId_t mp_id, uint32_t timeout) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + + /* The output name_ptr as null-terminated string */ + void *block; + + /* Check if the mq_id is NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + /* Return NULL in case of an error */ + block = NULL; + } + else + { + block = NULL; + /* Get a block from the free-list */ + if(tx_block_allocate(block_pool_ptr, &block, timeout) != TX_SUCCESS) + { + /* Return NULL in case of an error */ + block = NULL; + } + } + return (block); +} +/** + * @brief The function osMemoryPoolFree frees the memory pool block specified + * by the parameter block in the memory pool object specified by the + * parameter mp_id. The memory block is put back to the list of + * available blocks + * If another thread is waiting for memory to become available the + * thread is put to READY state. + * Possible osStatus_t return values: + * - osOK: the memory has been freed. + * - oosErrorParameter: parameter mp_id is NULL or invalid, block + * points to invalid memory. + * - oosErrorResource: the memory pool is in an invalid state. + * Note : osMemoryPoolFree may perform certain checks on the block + * pointer given. But using osMemoryPoolFree with a pointer other + * than one received from osMemoryPoolAlloc has UNPREDICTED behaviour. + * This function may be called from Interrupt Service Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * [in] [in] block address of the allocated memory block to be + * returned to the memory pool + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMemoryPoolFree(osMemoryPoolId_t mp_id, void * block) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + + osStatus_t status; + + /* Check if the mq_id is NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID) || (block == NULL)) + { + /* Invalid input parameters */ + status = osErrorParameter; + } + else + { + if(tx_block_release((VOID *)block) != TX_SUCCESS) + { + status = osErrorResource; + } + else + { + status = osOK; + } + } + return (status); +} +/** + * @brief The function osMemoryPoolGetCapacity returns the maximum number + * of memory blocks in the memory pool object specified by + * parameter mp_id or 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @retval maximum number of memory blocks in the memory pool object. + */ +uint32_t osMemoryPoolGetCapacity(osMemoryPoolId_t mp_id) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + /* The output name_ptr as null-terminated string */ + ULONG total_blocks = 0; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + /* Return 0 in case of an error */ + total_blocks = 0; + } + else + { + /* Call the tx_block_pool_info_get to get the total_blocks */ + if (tx_block_pool_info_get(block_pool_ptr, TX_NULL, TX_NULL, &total_blocks, TX_NULL,TX_NULL, TX_NULL)!= TX_SUCCESS) + { + /* Return 0 in case of an error */ + total_blocks = 0; + } + } + + return (total_blocks); +} +/** + * @brief The function osMemoryPoolGetBlockSize returns the memory block size + * in bytes in the memory pool object specified by parameter mp_id + * or 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @retval memory block size in bytes. + */ +uint32_t osMemoryPoolGetBlockSize(osMemoryPoolId_t mp_id) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + /* The output name_ptr as null-terminated string */ + uint32_t block_pool_size = 0; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + /* Return 0 in case of an error */ + block_pool_size = 0; + } + else + { + block_pool_size = block_pool_ptr->tx_block_pool_block_size; + } + + return (block_pool_size); +} +/** + * @brief The function osMemoryPoolGetCount returns the number of memory blocks + * used in the memory pool object specified by parameter mp_id or 0 in + * case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @retval number of memory blocks used. + */ +uint32_t osMemoryPoolGetCount(osMemoryPoolId_t mp_id) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + /* The output name_ptr as null-terminated string */ + ULONG block_pool_total = 0; + ULONG block_pool_available = 0; + ULONG block_pool_used = 0; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + /* Return 0 in case of an error */ + block_pool_used = 0; + } + else + { + /* Call the tx_block_pool_info_get to get the block_pool name_ptr */ + if (tx_block_pool_info_get(block_pool_ptr, TX_NULL, &block_pool_available, &block_pool_total, TX_NULL, TX_NULL, TX_NULL)!= TX_SUCCESS) + { + /* Return 0 in case of an error */ + block_pool_used = 0; + } + else + { + /* Return number of used blocks */ + block_pool_used = (block_pool_total - block_pool_available); + } + } + + return ((uint32_t)(block_pool_used)); +} +/** + * @brief The function osMemoryPoolGetSpace returns the number of memory blocks + * available in the memory pool object specified by parameter mp_id + * or 0 in case of an error. + * Note : This function may be called from Interrupt Service + * Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @retval number of memory blocks available. + */ +uint32_t osMemoryPoolGetSpace(osMemoryPoolId_t mp_id) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + /* The output name_ptr as null-terminated string */ + ULONG block_pool_available = 0; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + /* Return 0 in case of an error */ + block_pool_available = 0; + } + else + { + /* Call the tx_block_pool_info_get to get the block_pool name_ptr */ + if (tx_block_pool_info_get(block_pool_ptr, TX_NULL, &block_pool_available, TX_NULL, TX_NULL, TX_NULL, TX_NULL)!= TX_SUCCESS) + { + /* Return 0 in case of an error */ + block_pool_available = 0; + } + } + + return (block_pool_available); +} +/** + * @brief The function osMemoryPoolDelete deletes a memory pool object + * specified by parameter mp_id. It releases internal memory obtained + * for memory pool handling. After this call, the mp_id is no longer + * valid and cannot be used. The memory pool may be created again using + * the function osMemoryPoolNew + * Possible osStatus_t return values: + * - osOK: the memory pool object has been deleted. + * - osErrorParameter: parameter mp_id is NULL or invalid. + * - osErrorResource: the memory pool is in an invalid state. + * - osErrorISR: osMemoryPoolDelete cannot be called from interrupt service routines. + * Note : This function cannot be called from Interrupt Service Routines. + * @param [in] mp_id memory pool ID obtained by osMemoryPoolNew. + * @retval status code that indicates the execution status of the function. + */ +osStatus_t osMemoryPoolDelete(osMemoryPoolId_t mp_id) +{ + /* For TX_BLOCK_POOL the control block pointer is the Block pool identifier */ + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *)mp_id; + + osStatus_t status; + + /* Check if this API is called from Interrupt Service Routines, the mq_id is + NULL or mp_id->tx_block_pool_id != TX_BLOCK_POOL_ID */ + if ((block_pool_ptr == NULL) || (block_pool_ptr->tx_block_pool_id != TX_BLOCK_POOL_ID)) + { + status = osErrorParameter; + } + else if(IS_IRQ_MODE()) + { + status = osErrorISR; + } + else + { + if(tx_block_pool_delete(block_pool_ptr) != TX_SUCCESS) + { + status = osErrorResource; + } + else + { + status = osOK; + } + } + return(status); +} + +/*---------------------------------------------------------------------------*/ +/*------------------------tx_application_define API--------------------------*/ +/*---------------------------------------------------------------------------*/ +__attribute__((weak)) VOID tx_application_define(VOID *first_unused_memory) +{ + /* Empty tx_application_define() */ +} + diff --git a/middleware/CMakeLists.txt b/middleware/CMakeLists.txt index f867342d2..ddfad85f6 100644 --- a/middleware/CMakeLists.txt +++ b/middleware/CMakeLists.txt @@ -21,8 +21,11 @@ add_subdirectory_ifdef(CONFIG_CHERRYUSB cherryusb) add_subdirectory_ifdef(CONFIG_MBEDTLS mbedtls) add_subdirectory_ifdef(CONFIG_UCOS_III ucos_iii) add_subdirectory_ifdef(CONFIG_VGLITE vglite) -add_subdirectory(azure_rtos) +add_subdirectory_ifdef(CONFIG_TINYENGINE tinyengine) +add_subdirectory(eclipse_threadx) add_subdirectory_ifdef(CONFIG_MICROROS microros) add_subdirectory_ifdef(CONFIG_RTTHREAD_NANO rtthread-nano) -add_subdirectory_ifdef(CONFIG_CMSIS_OS2 CMSIS) +add_subdirectory(CMSIS) add_subdirectory(ptpd) +add_subdirectory_ifdef(CONFIG_AGILE_MODBUS agile_modbus) +add_subdirectory_ifdef(CONFIG_CHERRYRB cherryrb) \ No newline at end of file diff --git a/middleware/FreeRTOS/Source/CMakeLists.txt b/middleware/FreeRTOS/Source/CMakeLists.txt index de9e807f3..d1f1f9f08 100644 --- a/middleware/FreeRTOS/Source/CMakeLists.txt +++ b/middleware/FreeRTOS/Source/CMakeLists.txt @@ -2,8 +2,12 @@ # SPDX-License-Identifier: BSD-3-Clause sdk_inc(include) -sdk_inc(portable/GCC/RISC-V) -sdk_inc(portable/GCC/RISC-V/chip_specific_extensions/HPMicro) +sdk_gcc_inc(portable/GCC/RISC-V) +sdk_gcc_inc(portable/GCC/RISC-V/chip_specific_extensions/HPMicro) +sdk_ses_inc(portable/GCC/RISC-V) +sdk_ses_inc(portable/GCC/RISC-V/chip_specific_extensions/HPMicro) +sdk_iar_inc(portable/IAR/RISC-V) +sdk_iar_inc(portable/IAR/RISC-V/chip_specific_extensions/HPMicro) sdk_src( croutine.c list.c diff --git a/middleware/FreeRTOS/Source/portable/CMakeLists.txt b/middleware/FreeRTOS/Source/portable/CMakeLists.txt index bd2d309a2..044093823 100644 --- a/middleware/FreeRTOS/Source/portable/CMakeLists.txt +++ b/middleware/FreeRTOS/Source/portable/CMakeLists.txt @@ -1,13 +1,25 @@ # Copyright (c) 2021 HPMicro # SPDX-License-Identifier: BSD-3-Clause -sdk_inc(GCC/RISC-V) -sdk_src( +sdk_gcc_inc(GCC/RISC-V) +sdk_ses_inc(GCC/RISC-V) +sdk_iar_inc(IAR/RISC-V) + +sdk_gcc_src( GCC/RISC-V/port.c GCC/RISC-V/chip_specific_extensions/HPMicro/hpm_port.c GCC/RISC-V/portASM.S ) - +sdk_ses_src( + GCC/RISC-V/port.c + GCC/RISC-V/chip_specific_extensions/HPMicro/hpm_port.c + GCC/RISC-V/portASM.S + ) +sdk_iar_src( + IAR/RISC-V/port.c + IAR/RISC-V/chip_specific_extensions/HPMicro/hpm_port.c + IAR/RISC-V/portASM.S + ) # If CONFIG_FREERTOS_TIMER_RESOURCE_NOT_MTIMER is not defined, the mtimer is used to generate systic # Otherwise use the gptimer to generate systic if(NOT DEFINED CONFIG_FREERTOS_TIMER_RESOURCE_NOT_MTIMER) diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/Documentation.url b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/Documentation.url new file mode 100644 index 000000000..5546f8707 --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/Documentation.url @@ -0,0 +1,5 @@ +[{000214A0-0000-0000-C000-000000000046}] +Prop3=19,11 +[InternetShortcut] +IDList= +URL=https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/chip_specific_extensions/HPMicro/freertos_risc_v_chip_specific_extensions.h b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/chip_specific_extensions/HPMicro/freertos_risc_v_chip_specific_extensions.h new file mode 100644 index 000000000..be95d1a18 --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/chip_specific_extensions/HPMicro/freertos_risc_v_chip_specific_extensions.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef __FREERTOS_RISC_V_EXTENSIONS_H__ +#define __FREERTOS_RISC_V_EXTENSIONS_H__ + +#define portasmHAS_SIFIVE_CLINT 0 +#define portasmADDITIONAL_CONTEXT_SIZE 0 +#define portasmHANDLE_INTERRUPT irq_handler_trap + +portasmSAVE_ADDITIONAL_REGISTERS MACRO + ENDM + +portasmRESTORE_ADDITIONAL_REGISTERS MACRO + ENDM + + +#endif /* __FREERTOS_RISC_V_EXTENSIONS_H__ */ diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/chip_specific_extensions/HPMicro/hpm_port.c b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/chip_specific_extensions/HPMicro/hpm_port.c new file mode 100644 index 000000000..ab70bc206 --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/chip_specific_extensions/HPMicro/hpm_port.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023 HPMicro + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +/* Used to program the machine timer compare register. */ +extern uint64_t ullNextTime; +extern const size_t uxTimerIncrementsForOneTick; /* Assumes increment won't go over 32-bits. */ +extern volatile uint64_t * pullMachineTimerCompareRegister; + +#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) + +void vPortSetupTimerInterrupt( void ) +{ + uint64_t ulCurrentTime; + + pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( configMTIMECMP_BASE_ADDRESS ); + ulCurrentTime = *( volatile uint64_t * ) ( configMTIME_BASE_ADDRESS ); + + ullNextTime = ulCurrentTime + ( uint64_t ) uxTimerIncrementsForOneTick; + *pullMachineTimerCompareRegister = ullNextTime; + + /* Prepare the time to use after the next tick interrupt. */ + ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick; +} +#else +#include "hpm_gptmr_drv.h" +#ifndef FREERTOS_TIMER_RESOURCE + #define FREERTOS_TIMER_RESOURCE BOARD_FREERTOS_TIMER +#endif + +#ifndef FREERTOS_TIMER_CH + #define FREERTOS_TIMER_CH BOARD_FREERTOS_TIMER_CHANNEL +#endif + +#ifndef FREERTOS_TIMER_IRQ + #define FREERTOS_TIMER_IRQ BOARD_FREERTOS_TIMER_IRQ +#endif + +#ifndef FREERTOS_TIMER_CLOCK + #define FREERTOS_TIMER_CLOCK BOARD_FREERTOS_TIMER_CLK_NAME +#endif +void vPortSysTimerIsr(void) +{ + BaseType_t need_switch; + if (gptmr_check_status(FREERTOS_TIMER_RESOURCE, GPTMR_CH_RLD_STAT_MASK(FREERTOS_TIMER_CH))) { + gptmr_clear_status(FREERTOS_TIMER_RESOURCE, GPTMR_CH_RLD_STAT_MASK(FREERTOS_TIMER_CH)); + need_switch = xTaskIncrementTick(); + if (pdTRUE == need_switch) + vTaskSwitchContext(); + } +} +SDK_DECLARE_EXT_ISR_M(FREERTOS_TIMER_IRQ, vPortSysTimerIsr); + +void vPortSetupTimerInterrupt( void ) +{ + uint32_t gptmr_freq; + gptmr_channel_config_t config; + + gptmr_channel_get_default_config(FREERTOS_TIMER_RESOURCE, &config); + + gptmr_freq = clock_get_frequency(FREERTOS_TIMER_CLOCK); + config.reload = gptmr_freq / configTICK_RATE_HZ; + gptmr_channel_config(FREERTOS_TIMER_RESOURCE, FREERTOS_TIMER_CH, &config, false); + gptmr_start_counter(FREERTOS_TIMER_RESOURCE, FREERTOS_TIMER_CH); + + gptmr_enable_irq(FREERTOS_TIMER_RESOURCE, GPTMR_CH_RLD_IRQ_MASK(FREERTOS_TIMER_CH)); + intc_m_enable_irq_with_priority(FREERTOS_TIMER_IRQ, 1); +} + +#endif \ No newline at end of file diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/port.c b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/port.c new file mode 100644 index 000000000..f370591d8 --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/port.c @@ -0,0 +1,267 @@ +/* + * FreeRTOS Kernel V10.4.4 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/*----------------------------------------------------------- + * Implementation of functions defined in portable.h for the RISC-V RV32 port. + *----------------------------------------------------------*/ + +/* Scheduler includes. */ +#include "FreeRTOS.h" +#include "task.h" +#include "portmacro.h" + +extern const uint32_t CSTACK$$Limit[]; +#define _stack CSTACK$$Limit + +/* Standard includes. */ +#include "string.h" + +#ifdef configCLINT_BASE_ADDRESS + #warning The configCLINT_BASE_ADDRESS constant has been deprecated. configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS are currently being derived from the (possibly 0) configCLINT_BASE_ADDRESS setting. Please update to define configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS dirctly in place of configCLINT_BASE_ADDRESS. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + +#ifndef configMTIME_BASE_ADDRESS + #warning configMTIME_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtime register then set configMTIME_BASE_ADDRESS to the mapped address. Otherwise set configMTIME_BASE_ADDRESS to 0. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + +#ifndef configMTIMECMP_BASE_ADDRESS + #warning configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. If the target chip includes a memory-mapped mtimecmp register then set configMTIMECMP_BASE_ADDRESS to the mapped address. Otherwise set configMTIMECMP_BASE_ADDRESS to 0. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + +/* Let the user override the pre-loading of the initial LR with the address of +prvTaskExitError() in case it messes up unwinding of the stack in the +debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif + +/* The stack used by interrupt service routines. Set configISR_STACK_SIZE_WORDS +to use a statically allocated array as the interrupt stack. Alternative leave +configISR_STACK_SIZE_WORDS undefined and update the linker script so that a +linker variable names __freertos_irq_stack_top has the same value as the top +of the stack used by main. Using the linker script method will repurpose the +stack that was used by main before the scheduler was started for use as the +interrupt stack after the scheduler has started. */ +#ifdef configISR_STACK_SIZE_WORDS + static __attribute__ ((aligned(16))) StackType_t xISRStack[ configISR_STACK_SIZE_WORDS ] = { 0 }; + const StackType_t xISRStackTop = ( StackType_t ) &( xISRStack[ configISR_STACK_SIZE_WORDS & ~portBYTE_ALIGNMENT_MASK ] ); + + /* Don't use 0xa5 as the stack fill bytes as that is used by the kernerl for + the task stacks, and so will legitimately appear in many positions within + the ISR stack. */ + #define portISR_STACK_FILL_BYTE 0xee +#else + extern const uint32_t __freertos_irq_stack_top[]; + const StackType_t xISRStackTop = ( StackType_t ) __freertos_irq_stack_top; +#endif + +/* + * Setup the timer to generate the tick interrupts. The implementation in this + * file is weak to allow application writers to change the timer used to + * generate the tick interrupt. + */ +void vPortSetupTimerInterrupt( void ) __attribute__(( weak )); + +/*-----------------------------------------------------------*/ + +/* Used to program the machine timer compare register. */ +uint64_t ullNextTime = 0ULL; +const uint64_t *pullNextTime = &ullNextTime; +const size_t uxTimerIncrementsForOneTick = ( size_t ) ( ( configCPU_CLOCK_HZ ) / ( configTICK_RATE_HZ ) ); /* Assumes increment won't go over 32-bits. */ +uint32_t const ullMachineTimerCompareRegisterBase = configMTIMECMP_BASE_ADDRESS; +volatile uint64_t * pullMachineTimerCompareRegister = NULL; + +/* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task +stack checking. A problem in the ISR stack will trigger an assert, not call the +stack overflow hook function (because the stack overflow hook is specific to a +task stack, not the ISR stack). */ +#if defined( configISR_STACK_SIZE_WORDS ) && ( configCHECK_FOR_STACK_OVERFLOW > 2 ) + #warning This path not tested, or even compiled yet. + + static const uint8_t ucExpectedStackBytes[] = { + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \ + + #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) +#else + /* Define the function away. */ + #define portCHECK_ISR_STACK() +#endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */ + +/*-----------------------------------------------------------*/ + +#if( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) + + void vPortSetupTimerInterrupt( void ) + { + uint32_t ulCurrentTimeHigh, ulCurrentTimeLow; + volatile uint32_t * const pulTimeHigh = ( volatile uint32_t * ) ( ( configMTIME_BASE_ADDRESS ) + 4UL ); /* 8-byte typer so high 32-bit word is 4 bytes up. */ + volatile uint32_t * const pulTimeLow = ( volatile uint32_t * ) ( configMTIME_BASE_ADDRESS ); + volatile uint32_t ulHartId; + + __asm volatile( "csrr %0, mhartid" : "=r"( ulHartId ) ); + pullMachineTimerCompareRegister = ( volatile uint64_t * ) ( ullMachineTimerCompareRegisterBase + ( ulHartId * sizeof( uint64_t ) ) ); + + do + { + ulCurrentTimeHigh = *pulTimeHigh; + ulCurrentTimeLow = *pulTimeLow; + } while( ulCurrentTimeHigh != *pulTimeHigh ); + + ullNextTime = ( uint64_t ) ulCurrentTimeHigh; + ullNextTime <<= 32ULL; /* High 4-byte word is 32-bits up. */ + ullNextTime |= ( uint64_t ) ulCurrentTimeLow; + ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick; + *pullMachineTimerCompareRegister = ullNextTime; + + /* Prepare the time to use after the next tick interrupt. */ + ullNextTime += ( uint64_t ) uxTimerIncrementsForOneTick; + } + +#endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIME_BASE_ADDRESS != 0 ) */ +/*-----------------------------------------------------------*/ + +BaseType_t xPortStartScheduler( void ) +{ +extern void xPortStartFirstTask( void ); + + #if( configASSERT_DEFINED == 1 ) + { + volatile uint32_t mtvec = 0; + + /* Check the least significant two bits of mtvec are 00 - indicating + single vector mode. */ + __asm volatile( "csrr %0, mtvec" : "=r"( mtvec ) ); + configASSERT( ( mtvec & 0x03UL ) == 0 ); + + /* Check alignment of the interrupt stack - which is the same as the + stack that was being used by main() prior to the scheduler being + started. */ + configASSERT( ( xISRStackTop & portBYTE_ALIGNMENT_MASK ) == 0 ); + + #ifdef configISR_STACK_SIZE_WORDS + { + memset( ( void * ) xISRStack, portISR_STACK_FILL_BYTE, sizeof( xISRStack ) ); + } + #endif /* configISR_STACK_SIZE_WORDS */ + } + #endif /* configASSERT_DEFINED */ + + /* If there is a CLINT then it is ok to use the default implementation + in this file, otherwise vPortSetupTimerInterrupt() must be implemented to + configure whichever clock is to be used to generate the tick interrupt. */ + vPortSetupTimerInterrupt(); + + #if( ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) ) + { + /* Enable mtime and external interrupts. 1<<7 for timer interrupt, 1<<11 + for external interrupt. _RB_ What happens here when mtime is not present as + with pulpino? */ + __asm volatile( "csrs mie, %0" :: "r"(0x880) ); + } + #else + { + /* Enable external interrupts. */ + __asm volatile( "csrs mie, %0" :: "r"(0x800) ); + } + #endif /* ( configMTIME_BASE_ADDRESS != 0 ) && ( configMTIMECMP_BASE_ADDRESS != 0 ) */ + + xPortStartFirstTask(); + + /* Should not get here as after calling xPortStartFirstTask() only tasks + should be executing. */ + return pdFAIL; +} +/*-----------------------------------------------------------*/ + +void vPortEndScheduler( void ) +{ + /* Not implemented. */ + for( ;; ); +} + + +/* configSUPPORT_STATIC_ALLOCATION is set to 1, so the application must provide an +implementation of vApplicationGetIdleTaskMemory() to provide the memory that is +used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, + StackType_t **ppxIdleTaskStackBuffer, + uint32_t *pulIdleTaskStackSize ) +{ + /* If the buffers to be provided to the Idle task are declared inside this + function then they must be declared static - otherwise they will be allocated on + the stack and so not exists after this function exits. */ + static StaticTask_t xIdleTaskTCB; + static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} +/*-----------------------------------------------------------*/ + +/* configSUPPORT_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the +application must provide an implementation of vApplicationGetTimerTaskMemory() +to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, + StackType_t **ppxTimerTaskStackBuffer, + uint32_t *pulTimerTaskStackSize ) +{ + /* If the buffers to be provided to the Timer task are declared inside this + function then they must be declared static - otherwise they will be allocated on + the stack and so not exists after this function exits. */ + static StaticTask_t xTimerTaskTCB; + static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configTIMER_TASK_STACK_DEPTH is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} + + diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/portASM.S b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/portASM.S new file mode 100644 index 000000000..f8c0cfc8a --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/portASM.S @@ -0,0 +1,630 @@ +/* + * FreeRTOS Kernel V10.4.4 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +/* + * The FreeRTOS kernel's RISC-V port is split between the the code that is + * common across all currently supported RISC-V chips (implementations of the + * RISC-V ISA), and code which tailors the port to a specific RISC-V chip: + * + * + The code that is common to all RISC-V chips is implemented in + * FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S. There is only one + * portASM.S file because the same file is used no matter which RISC-V chip is + * in use. + * + * + The code that tailors the kernel's RISC-V port to a specific RISC-V + * chip is implemented in freertos_risc_v_chip_specific_extensions.h. There + * is one freertos_risc_v_chip_specific_extensions.h that can be used with any + * RISC-V chip that both includes a standard CLINT and does not add to the + * base set of RISC-V registers. There are additional + * freertos_risc_v_chip_specific_extensions.h files for RISC-V implementations + * that do not include a standard CLINT or do add to the base set of RISC-V + * registers. + * + * CARE MUST BE TAKEN TO INCLDUE THE CORRECT + * freertos_risc_v_chip_specific_extensions.h HEADER FILE FOR THE CHIP + * IN USE. To include the correct freertos_risc_v_chip_specific_extensions.h + * header file ensure the path to the correct header file is in the assembler's + * include path. + * + * This freertos_risc_v_chip_specific_extensions.h is for use on RISC-V chips + * that include a standard CLINT and do not add to the base set of RISC-V + * registers. + * + */ +#if __riscv_xlen == 64 + #define portWORD_SIZE 8 + #define store_x sd + #define load_x ld +#elif __riscv_xlen == 32 + #define store_x sw + #define load_x lw + #define portWORD_SIZE 4 +#else + #error Assembler did not define __riscv_xlen +#endif + +#include "freertos_risc_v_chip_specific_extensions.h" + +/* Check the freertos_risc_v_chip_specific_extensions.h and/or command line +definitions. */ +#if defined( portasmHAS_CLINT ) && defined( portasmHAS_MTIME ) + #error The portasmHAS_CLINT constant has been deprecated. Please replace it with portasmHAS_MTIME. portasmHAS_CLINT and portasmHAS_MTIME cannot both be defined at once. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + +#ifdef portasmHAS_CLINT + #warning The portasmHAS_CLINT constant has been deprecated. Please replace it with portasmHAS_MTIME and portasmHAS_SIFIVE_CLINT. For now portasmHAS_MTIME and portasmHAS_SIFIVE_CLINT are derived from portasmHAS_CLINT. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html + #define portasmHAS_MTIME portasmHAS_CLINT + #define portasmHAS_SIFIVE_CLINT portasmHAS_CLINT +#endif + +#ifndef portasmHAS_MTIME + #error freertos_risc_v_chip_specific_extensions.h must define portasmHAS_MTIME to either 1 (MTIME clock present) or 0 (MTIME clock not present). See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + +#ifndef portasmHANDLE_INTERRUPT + #error portasmHANDLE_INTERRUPT must be defined to the function to be called to handle external/peripheral interrupts. portasmHANDLE_INTERRUPT can be defined on the assembler command line or in the appropriate freertos_risc_v_chip_specific_extensions.h header file. https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + +#ifndef portasmHAS_SIFIVE_CLINT + #define portasmHAS_SIFIVE_CLINT 0 +#endif + +/* Only the standard core registers are stored by default. Any additional +registers must be saved by the portasmSAVE_ADDITIONAL_REGISTERS and +portasmRESTORE_ADDITIONAL_REGISTERS macros - which can be defined in a chip +specific version of freertos_risc_v_chip_specific_extensions.h. See the notes +at the top of this file. */ +#define portCONTEXT_SIZE ( 30 * portWORD_SIZE ) + + +#ifdef __riscv_flen + +#define MSTATUS_FS 0x00006000 /* Floating-point Status */ + #define MSTATUS_FS_OFF 0x00000000 + #define MSTATUS_FS_INITIAL 0x00002000 + #define MSTATUS_FS_CLEAN 0x00004000 + #define MSTATUS_FS_DIRTY 0x00006000 + +#if __riscv_flen == 32 + #define store_fpu fsw + #define load_fpu flw + #define FREGBYTES 4 +#endif +#if __riscv_flen == 64 + #define store_fpu fsd + #define load_fpu fld + #define FREGBYTES 8 +#endif + +/* offset 0 * FREGBYTES - mepc + * offset 1 * FREGBYTES - mstatus + * offset (2 - 32) * FREGBYTES - float registers + */ +#define portFPU_CONTEXT_WORDS 34 +#define portFPU_CONTEXT_SIZE (portFPU_CONTEXT_WORDS * FREGBYTES) + + SECTION `.isr_vector`:CODE(2) + CODE +portasmSAVE_FPU_REGISTERS: + addi sp, sp, -portFPU_CONTEXT_SIZE + /* get FS field from mstatus */ + li t0, MSTATUS_FS + csrr t1, mstatus + store_x t1, 33 * FREGBYTES(sp) + and t0, t1, t0 + li t2, MSTATUS_FS_DIRTY + bne t2, t0, skip_store_fpu + /* FS == dirty */ + /* Make room for the additional FPU registers. */ + store_fpu f0, 1 * FREGBYTES(sp) + store_fpu f1, 2 * FREGBYTES(sp) + store_fpu f2, 3 * FREGBYTES(sp) + store_fpu f3, 4 * FREGBYTES(sp) + store_fpu f4, 5 * FREGBYTES(sp) + store_fpu f5, 6 * FREGBYTES(sp) + store_fpu f6, 7 * FREGBYTES(sp) + store_fpu f7, 8 * FREGBYTES(sp) + store_fpu f8, 9 * FREGBYTES(sp) + store_fpu f9, 10 * FREGBYTES(sp) + store_fpu f10, 11 * FREGBYTES(sp) + store_fpu f11, 12 * FREGBYTES(sp) + store_fpu f12, 13 * FREGBYTES(sp) + store_fpu f13, 14 * FREGBYTES(sp) + store_fpu f14, 15 * FREGBYTES(sp) + store_fpu f15, 16 * FREGBYTES(sp) + store_fpu f16, 17 * FREGBYTES(sp) + store_fpu f17, 18 * FREGBYTES(sp) + store_fpu f18, 19 * FREGBYTES(sp) + store_fpu f19, 20 * FREGBYTES(sp) + store_fpu f20, 21 * FREGBYTES(sp) + store_fpu f21, 22 * FREGBYTES(sp) + store_fpu f22, 23 * FREGBYTES(sp) + store_fpu f23, 24 * FREGBYTES(sp) + store_fpu f24, 25 * FREGBYTES(sp) + store_fpu f25, 26 * FREGBYTES(sp) + store_fpu f26, 27 * FREGBYTES(sp) + store_fpu f27, 28 * FREGBYTES(sp) + store_fpu f28, 29 * FREGBYTES(sp) + store_fpu f29, 30 * FREGBYTES(sp) + store_fpu f30, 31 * FREGBYTES(sp) + store_fpu f31, 32 * FREGBYTES(sp) + + /* must set FS to clean */ + csrc mstatus, t0 + li t1, MSTATUS_FS_CLEAN + csrs mstatus, t1 +skip_store_fpu: + ret + + SECTION `.isr_vector`:CODE(2) + CODE +portasmRESTORE_FPU_REGISTERS: + load_x t1, 33 * FREGBYTES(sp) + /* get FS field from mstatus */ + li t0, MSTATUS_FS + and t0, t1, t0 + li t2, MSTATUS_FS_DIRTY + bne t2, t0, skip_load_fpu + /* FS == dirty */ + csrs mstatus, t0 + load_fpu f0, 1 * FREGBYTES(sp) + load_fpu f1, 2 * FREGBYTES(sp) + load_fpu f2, 3 * FREGBYTES(sp) + load_fpu f3, 4 * FREGBYTES(sp) + load_fpu f4, 5 * FREGBYTES(sp) + load_fpu f5, 6 * FREGBYTES(sp) + load_fpu f6, 7 * FREGBYTES(sp) + load_fpu f7, 8 * FREGBYTES(sp) + load_fpu f8, 9 * FREGBYTES(sp) + load_fpu f9, 10 * FREGBYTES(sp) + load_fpu f10, 11 * FREGBYTES(sp) + load_fpu f11, 12 * FREGBYTES(sp) + load_fpu f12, 13 * FREGBYTES(sp) + load_fpu f13, 14 * FREGBYTES(sp) + load_fpu f14, 15 * FREGBYTES(sp) + load_fpu f15, 16 * FREGBYTES(sp) + load_fpu f16, 17 * FREGBYTES(sp) + load_fpu f17, 18 * FREGBYTES(sp) + load_fpu f18, 19 * FREGBYTES(sp) + load_fpu f19, 20 * FREGBYTES(sp) + load_fpu f20, 21 * FREGBYTES(sp) + load_fpu f21, 22 * FREGBYTES(sp) + load_fpu f22, 23 * FREGBYTES(sp) + load_fpu f23, 24 * FREGBYTES(sp) + load_fpu f24, 25 * FREGBYTES(sp) + load_fpu f25, 26 * FREGBYTES(sp) + load_fpu f26, 27 * FREGBYTES(sp) + load_fpu f27, 28 * FREGBYTES(sp) + load_fpu f28, 29 * FREGBYTES(sp) + load_fpu f29, 30 * FREGBYTES(sp) + load_fpu f30, 31 * FREGBYTES(sp) + load_fpu f31, 32 * FREGBYTES(sp) + +skip_load_fpu: + /* must set FS to clean */ + csrc mstatus, t0 + li t1, MSTATUS_FS_CLEAN + csrs mstatus, t1 + addi sp, sp, portFPU_CONTEXT_SIZE + ret +#endif + + PUBLIC xPortStartFirstTask + PUBLIC freertos_risc_v_trap_handler + PUBLIC pxPortInitialiseStack + EXTERN pxCurrentTCB + EXTERN ulPortTrapHandler + EXTERN vTaskSwitchContext + EXTERN xTaskIncrementTick + EXTERN Timer_IRQHandler + EXTERN pullMachineTimerCompareRegister + EXTERN pullNextTime + EXTERN uxTimerIncrementsForOneTick /* size_t type so 32-bit on 32-bit core and 64-bits on 64-bit core. */ + EXTERN xISRStackTop + EXTERN portasmHANDLE_INTERRUPT + +/*-----------------------------------------------------------*/ + SECTION `.isr_vector`:CODE(2) +freertos_risc_v_trap_handler: + addi sp, sp, -portCONTEXT_SIZE + store_x x1, 1 * portWORD_SIZE( sp ) + store_x x5, 2 * portWORD_SIZE( sp ) + store_x x6, 3 * portWORD_SIZE( sp ) + store_x x7, 4 * portWORD_SIZE( sp ) + store_x x8, 5 * portWORD_SIZE( sp ) + store_x x9, 6 * portWORD_SIZE( sp ) + store_x x10, 7 * portWORD_SIZE( sp ) + store_x x11, 8 * portWORD_SIZE( sp ) + store_x x12, 9 * portWORD_SIZE( sp ) + store_x x13, 10 * portWORD_SIZE( sp ) + store_x x14, 11 * portWORD_SIZE( sp ) + store_x x15, 12 * portWORD_SIZE( sp ) + store_x x16, 13 * portWORD_SIZE( sp ) + store_x x17, 14 * portWORD_SIZE( sp ) + store_x x18, 15 * portWORD_SIZE( sp ) + store_x x19, 16 * portWORD_SIZE( sp ) + store_x x20, 17 * portWORD_SIZE( sp ) + store_x x21, 18 * portWORD_SIZE( sp ) + store_x x22, 19 * portWORD_SIZE( sp ) + store_x x23, 20 * portWORD_SIZE( sp ) + store_x x24, 21 * portWORD_SIZE( sp ) + store_x x25, 22 * portWORD_SIZE( sp ) + store_x x26, 23 * portWORD_SIZE( sp ) + store_x x27, 24 * portWORD_SIZE( sp ) + store_x x28, 25 * portWORD_SIZE( sp ) + store_x x29, 26 * portWORD_SIZE( sp ) + store_x x30, 27 * portWORD_SIZE( sp ) + store_x x31, 28 * portWORD_SIZE( sp ) + + csrr t0, mstatus /* Required for MPIE bit. */ + store_x t0, 29 * portWORD_SIZE( sp ) + + portasmSAVE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to save any registers unique to the RISC-V implementation. */ + +#ifdef __riscv_flen + call portasmSAVE_FPU_REGISTERS /* Note at this place register ${ra} is already stored in the thread stack, and at this place we will not run {ret}, so there is no need to store the ${ra} register before call function */ +#endif + csrr t0, mscratch + bne t0, x0, skip0 + /* not in isr context, set to tcb stack */ + load_x t0, pxCurrentTCB /* Load pxCurrentTCB. */ + store_x sp, 0( t0 ) /* Write sp to first TCB member. */ +skip0: + + csrr a0, mcause + csrr a1, mepc + +test_if_asynchronous: + srli a2, a0, __riscv_xlen - 1 /* MSB of mcause is 1 if handing an asynchronous interrupt - shift to LSB to clear other bits. */ + beq a2, x0, handle_synchronous /* Branch past interrupt handing if not asynchronous. */ + store_x a1, 0( sp ) /* Asynch so save unmodified exception return address. */ + +handle_asynchronous: + +#if( portasmHAS_MTIME != 0 ) + + test_if_mtimer: /* If there is a CLINT then the mtimer is used to generate the tick interrupt. */ + + addi t0, x0, 1 + + slli t0, t0, __riscv_xlen - 1 /* LSB is already set, shift into MSB. Shift 31 on 32-bit or 63 on 64-bit cores. */ + addi t1, t0, 7 /* 0x8000[]0007 == machine timer interrupt. */ + bne a0, t1, other_interrupts + + load_x t0, pullMachineTimerCompareRegister /* Load address of compare register into t0. */ + load_x t1, pullNextTime /* Load the address of ullNextTime into t1. */ + + #if( __riscv_xlen == 32 ) + + /* Update the 64-bit mtimer compare match value in two 32-bit writes. */ + li t4, -1 + lw t2, 0(t1) /* Load the low word of ullNextTime into t2. */ + lw t3, 4(t1) /* Load the high word of ullNextTime into t3. */ + sw t4, 0(t0) /* Low word no smaller than old value to start with - will be overwritten below. */ + sw t3, 4(t0) /* Store high word of ullNextTime into compare register. No smaller than new value. */ + sw t2, 0(t0) /* Store low word of ullNextTime into compare register. */ + lw t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */ + add t4, t0, t2 /* Add the low word of ullNextTime to the timer increments for one tick (assumes timer increment for one tick fits in 32-bits). */ + sltu t5, t4, t2 /* See if the sum of low words overflowed (what about the zero case?). */ + add t6, t3, t5 /* Add overflow to high word of ullNextTime. */ + sw t4, 0(t1) /* Store new low word of ullNextTime. */ + sw t6, 4(t1) /* Store new high word of ullNextTime. */ + + #endif /* __riscv_xlen == 32 */ + + #if( __riscv_xlen == 64 ) + + /* Update the 64-bit mtimer compare match value. */ + ld t2, 0(t1) /* Load ullNextTime into t2. */ + sd t2, 0(t0) /* Store ullNextTime into compare register. */ + ld t0, uxTimerIncrementsForOneTick /* Load the value of ullTimerIncrementForOneTick into t0 (could this be optimized by storing in an array next to pullNextTime?). */ + add t4, t0, t2 /* Add ullNextTime to the timer increments for one tick. */ + sd t4, 0(t1) /* Store ullNextTime. */ + + #endif /* __riscv_xlen == 64 */ + + csrr t0, mscratch + bne t0, x0, skip1 + /* not in isr context, load use xISRStackTop as isr stack top, otherwise use current sp */ + load_x sp, xISRStackTop /* Switch to ISR stack before function call. */ +skip1: + addi t0, t0, 1 + csrw mscratch, t0 + + call xTaskIncrementTick + beqz a0, processed_source /* Don't switch context if incrementing tick didn't unblock a task. */ + call vTaskSwitchContext + j processed_source + +#endif /* portasmHAS_MTIME */ + +other_interrupts: + csrr t0, mscratch + bne t0, x0, skip2 + /* not in isr context, load use xISRStackTop as isr stack top, otherwise use current sp */ + load_x sp, xISRStackTop /* Switch to ISR stack before function call. */ +skip2: + addi t0, t0, 1 + csrw mscratch, t0 + + call portasmHANDLE_INTERRUPT /* Jump to the interrupt handler if there is no CLINT or if there is a CLINT and it has been determined that an external interrupt is pending. */ + j processed_source + +handle_synchronous: + addi a1, a1, 4 /* Synchronous so updated exception return address to the instruction after the instruction that generated the exeption. */ + store_x a1, 0( sp ) /* Save updated exception return address. */ + +test_if_environment_call: + li t0, 11 /* 11 == environment call. */ + bne a0, t0, is_exception /* Not an M environment call, so some other exception. */ + + csrr t0, mscratch + bne t0, x0, skip3 + /* not in isr context, load use xISRStackTop as isr stack top, otherwise use current sp */ + load_x sp, xISRStackTop /* Switch to ISR stack before function call. */ +skip3: + addi t0, t0, 1 + csrw mscratch, t0 + + /* Disable task scheduler, if it's already in ISR */ + addi t1, t0, -1 + bgtz t1, processed_source + + call vTaskSwitchContext + j processed_source + +is_exception: + csrr t0, mcause /* For viewing in the debugger only. */ + csrr t1, mepc /* For viewing in the debugger only */ + csrr t2, mstatus + j is_exception /* No other exceptions handled yet. */ + +processed_source: + csrr t0, mscratch + beq t0, x0, skip4 + /* in isr context, mscrach needs to be updated */ + addi t0, t0, -1 + csrw mscratch, t0 +skip4: + bne t0, x0, skip5 + /* not in isr context any more, sp needs to be restored from tcb */ + load_x t1, pxCurrentTCB /* Load pxCurrentTCB. */ + load_x sp, 0( t1 ) /* Read sp from first TCB member. */ +skip5: + /* Load mret with the address of the next instruction in the task to run next. */ + load_x t0, 0( sp ) + csrw mepc, t0 + +#ifdef __riscv_flen + call portasmRESTORE_FPU_REGISTERS /* Note at this place register ${ra} is already stored in the thread stack, and at this place we will not run {ret}, so there is no need to store the ${ra} register before call function */ +#endif + portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ + + /* Load mstatus with the interrupt enable bits used by the task. */ + load_x t0, 29 * portWORD_SIZE( sp ) + csrw mstatus, t0 /* Required for MPIE bit. */ + + load_x x1, 1 * portWORD_SIZE( sp ) + load_x x5, 2 * portWORD_SIZE( sp ) /* t0 */ + load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */ + load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */ + load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */ + load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */ + load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */ + load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */ + load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */ + load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */ + load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */ + load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */ + load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */ + load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */ + load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */ + load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */ + load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */ + load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */ + load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */ + load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */ + load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */ + load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */ + load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */ + load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */ + load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */ + load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */ + load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */ + load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */ + addi sp, sp, portCONTEXT_SIZE + + mret + +/*-----------------------------------------------------------*/ + SECTION `.isr_vector` : CODE(2) +xPortStartFirstTask: + +#if( portasmHAS_SIFIVE_CLINT != 0 ) + /* If there is a clint then interrupts can branch directly to the FreeRTOS + trap handler. Otherwise the interrupt controller will need to be configured + outside of this file. */ + la t0, freertos_risc_v_trap_handler + csrw mtvec, t0 +#endif /* portasmHAS_CLILNT */ + + load_x sp, pxCurrentTCB /* Load pxCurrentTCB. */ + load_x sp, 0( sp ) /* Read sp from first TCB member. */ + + load_x x1, 0( sp ) /* Note for starting the scheduler the exception return address is used as the function return address. */ + +#ifdef __riscv_flen + mv s0, ra + call portasmRESTORE_FPU_REGISTERS /* Note at this place ${ra} should be stored and after the function return , ${ra} should be restored */ + mv ra, s0 +#endif + portasmRESTORE_ADDITIONAL_REGISTERS /* Defined in freertos_risc_v_chip_specific_extensions.h to restore any registers unique to the RISC-V implementation. */ + + load_x x6, 3 * portWORD_SIZE( sp ) /* t1 */ + load_x x7, 4 * portWORD_SIZE( sp ) /* t2 */ + load_x x8, 5 * portWORD_SIZE( sp ) /* s0/fp */ + load_x x9, 6 * portWORD_SIZE( sp ) /* s1 */ + load_x x10, 7 * portWORD_SIZE( sp ) /* a0 */ + load_x x11, 8 * portWORD_SIZE( sp ) /* a1 */ + load_x x12, 9 * portWORD_SIZE( sp ) /* a2 */ + load_x x13, 10 * portWORD_SIZE( sp ) /* a3 */ + load_x x14, 11 * portWORD_SIZE( sp ) /* a4 */ + load_x x15, 12 * portWORD_SIZE( sp ) /* a5 */ + load_x x16, 13 * portWORD_SIZE( sp ) /* a6 */ + load_x x17, 14 * portWORD_SIZE( sp ) /* a7 */ + load_x x18, 15 * portWORD_SIZE( sp ) /* s2 */ + load_x x19, 16 * portWORD_SIZE( sp ) /* s3 */ + load_x x20, 17 * portWORD_SIZE( sp ) /* s4 */ + load_x x21, 18 * portWORD_SIZE( sp ) /* s5 */ + load_x x22, 19 * portWORD_SIZE( sp ) /* s6 */ + load_x x23, 20 * portWORD_SIZE( sp ) /* s7 */ + load_x x24, 21 * portWORD_SIZE( sp ) /* s8 */ + load_x x25, 22 * portWORD_SIZE( sp ) /* s9 */ + load_x x26, 23 * portWORD_SIZE( sp ) /* s10 */ + load_x x27, 24 * portWORD_SIZE( sp ) /* s11 */ + load_x x28, 25 * portWORD_SIZE( sp ) /* t3 */ + load_x x29, 26 * portWORD_SIZE( sp ) /* t4 */ + load_x x30, 27 * portWORD_SIZE( sp ) /* t5 */ + load_x x31, 28 * portWORD_SIZE( sp ) /* t6 */ + + load_x x5, 29 * portWORD_SIZE( sp ) /* Initial mstatus into x5 (t0) */ + addi x5, x5, 0x08 /* Set MIE bit so the first task starts with interrupts enabled - required as returns with ret not eret. */ + csrrw x0, mstatus, x5 /* Interrupts enabled from here! */ + load_x x5, 2 * portWORD_SIZE( sp ) /* Initial x5 (t0) value. */ + + addi sp, sp, portCONTEXT_SIZE + ret +/*-----------------------------------------------------------*/ + +/* + * Unlike other ports pxPortInitialiseStack() is written in assembly code as it + * needs access to the portasmADDITIONAL_CONTEXT_SIZE constant. The prototype + * for the function is as per the other ports: + * StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ); + * + * As per the standard RISC-V ABI pxTopcOfStack is passed in in a0, pxCode in + * a1, and pvParameters in a2. The new top of stack is passed out in a0. + * + * RISC-V maps registers to ABI names as follows (X1 to X31 integer registers + * for the 'I' profile, X1 to X15 for the 'E' profile, currently I assumed). + * + * Register ABI Name Description Saver + * x0 zero Hard-wired zero - + * x1 ra Return address Caller + * x2 sp Stack pointer Callee + * x3 gp Global pointer - + * x4 tp Thread pointer - + * x5-7 t0-2 Temporaries Caller + * x8 s0/fp Saved register/Frame pointer Callee + * x9 s1 Saved register Callee + * x10-11 a0-1 Function Arguments/return values Caller + * x12-17 a2-7 Function arguments Caller + * x18-27 s2-11 Saved registers Callee + * x28-31 t3-6 Temporaries Caller + * + * The RISC-V context is saved t FreeRTOS tasks in the following stack frame, + * where the global and thread pointers are currently assumed to be constant so + * are not saved: + * + * mstatus + * x31 + * x30 + * x29 + * x28 + * x27 + * x26 + * x25 + * x24 + * x23 + * x22 + * x21 + * x20 + * x19 + * x18 + * x17 + * x16 + * x15 + * x14 + * x13 + * x12 + * x11 + * pvParameters + * x9 + * x8 + * x7 + * x6 + * x5 + * portTASK_RETURN_ADDRESS + * [chip specific registers go here] + * pxCode + */ + SECTION `.isr_vector` : CODE(2) +pxPortInitialiseStack: + + csrr t0, mstatus /* Obtain current mstatus value. */ + andi t0, t0, ~0x8 /* Ensure interrupts are disabled when the stack is restored within an ISR. Required when a task is created after the schedulre has been started, otherwise interrupts would be disabled anyway. */ +#ifdef __riscv_flen + addi t1, x0, 0x388 /* Generate the value 0x3880, which are the MPIE and MPP bits to set and FS bits to 1 in mstatus. */ +#else + addi t1, x0, 0x188 /* Generate the value 0x1880, which are the MPIE and MPP bits to set in mstatus. */ +#endif + slli t1, t1, 4 + or t0, t0, t1 /* Set MPIE and MPP bits in mstatus value. */ + + addi a0, a0, -portWORD_SIZE + store_x t0, 0(a0) /* mstatus onto the stack. */ + addi a0, a0, -(22 * portWORD_SIZE) /* Space for registers x11-x31. */ + store_x a2, 0(a0) /* Task parameters (pvParameters parameter) goes into register X10/a0 on the stack. */ + addi a0, a0, -(6 * portWORD_SIZE) /* Space for registers x5-x9. */ + store_x x0, 0(a0) /* Return address onto the stack, could be portTASK_RETURN_ADDRESS */ + addi t0, x0, portasmADDITIONAL_CONTEXT_SIZE /* The number of chip specific additional registers. */ +chip_specific_stack_frame: /* First add any chip specific registers to the stack frame being created. */ + beq t0, x0, pxPortInitialiseStack_1 /* No more chip specific registers to save. */ + addi a0, a0, -portWORD_SIZE /* Make space for chip specific register. */ + store_x x0, 0(a0) /* Give the chip specific register an initial value of zero. */ + addi t0, t0, -1 /* Decrement the count of chip specific registers remaining. */ + j chip_specific_stack_frame /* Until no more chip specific registers. */ +pxPortInitialiseStack_1: + +#ifdef __riscv_flen + add a0, a0, -portFPU_CONTEXT_SIZE + mv t2, a0 + addi t0, x0, portFPU_CONTEXT_SIZE +fpu_specific_stack_frame: + beq t0, x0, pxPortInitialiseStack_2 /* No more chip specific registers to save. */ + store_x x0, 0(t2) /* Give the chip specific register an initial value of zero. */ + addi t2, t2, portWORD_SIZE /* Make space for chip specific register. */ + addi t0, t0, -portWORD_SIZE /* Decrement the count of chip specific registers remaining. */ + j fpu_specific_stack_frame /* Until no more chip specific registers. */ +pxPortInitialiseStack_2: +#endif + + addi a0, a0, -portWORD_SIZE + store_x a1, 0(a0) /* mret value (pxCode parameter) onto the stack. */ + ret +/*-----------------------------------------------------------*/ diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/portmacro.h b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/portmacro.h new file mode 100644 index 000000000..6b55cfc92 --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/portmacro.h @@ -0,0 +1,191 @@ +/* + * FreeRTOS Kernel V10.4.4 + * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + + +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * Port specific definitions. + * + * The settings in this file configure FreeRTOS correctly for the + * given hardware and compiler. + * + * These settings should not be altered. + *----------------------------------------------------------- + */ + +/* Type definitions. */ +#if __riscv_xlen == 64 + #define portSTACK_TYPE uint64_t + #define portBASE_TYPE int64_t + #define portUBASE_TYPE uint64_t + #define portMAX_DELAY ( TickType_t ) 0xffffffffffffffffUL + #define portPOINTER_SIZE_TYPE uint64_t +#elif __riscv_xlen == 32 + #define portSTACK_TYPE uint32_t + #define portBASE_TYPE int32_t + #define portUBASE_TYPE uint32_t + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#else + #error Assembler did not define __riscv_xlen +#endif + + +typedef portSTACK_TYPE StackType_t; +typedef portBASE_TYPE BaseType_t; +typedef portUBASE_TYPE UBaseType_t; +typedef portUBASE_TYPE TickType_t; + +/* Legacy type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short + +/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do +not need to be guarded with a critical section. */ +#define portTICK_TYPE_IS_ATOMIC 1 +/*-----------------------------------------------------------*/ + +/* Architecture specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#ifdef __riscv64 + #error This is the RV32 port that has not yet been adapted for 64. + #define portBYTE_ALIGNMENT 16 +#else + #define portBYTE_ALIGNMENT 8 +#endif +/*-----------------------------------------------------------*/ + + +/* Scheduler utilities. */ +extern void vTaskSwitchContext( void ); +#define portYIELD() __asm volatile( "ecall" ); +#define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) vTaskSwitchContext(); } while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +/*-----------------------------------------------------------*/ + + +/* Critical section management. */ +#define portCRITICAL_NESTING_IN_TCB 1 +extern void vTaskEnterCritical( void ); +extern void vTaskExitCritical( void ); + +#define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#define portDISABLE_INTERRUPTS() __asm volatile( "csrrci x0, mstatus, 8" ) +#define portENABLE_INTERRUPTS() __asm volatile( "csrrsi x0, mstatus, 8" ) +#define portENTER_CRITICAL() vTaskEnterCritical() +#define portEXIT_CRITICAL() vTaskExitCritical() + +/*-----------------------------------------------------------*/ + +/* Architecture specific optimisations. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. + #endif + + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /*-----------------------------------------------------------*/ + + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - __builtin_clz( uxReadyPriorities ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ + + +/*-----------------------------------------------------------*/ + +/* Task function macros as described on the FreeRTOS.org WEB site. These are +not necessary for to use this port. They are defined so the common demo files +(which build with all the ports) will build. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) + +/*-----------------------------------------------------------*/ + +#define portNOP() __asm volatile ( " nop " ) + +#define portINLINE __inline + +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__(( always_inline)) +#endif + +#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) +/*-----------------------------------------------------------*/ + +portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) +{ + return (read_csr(CSR_MSCRATCH) > 0) ? 1 : 0; +} + +/* configCLINT_BASE_ADDRESS is a legacy definition that was replaced by the +configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS definitions. For +backward compatibility derive the newer definitions from the old if the old +definition is found. */ +#if defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) && ( configCLINT_BASE_ADDRESS == 0 ) + /* Legacy case where configCLINT_BASE_ADDRESS was defined as 0 to indicate + there was no CLINT. Equivalent now is to set the MTIME and MTIMECMP + addresses to 0. */ + #define configMTIME_BASE_ADDRESS ( 0 ) + #define configMTIMECMP_BASE_ADDRESS ( 0 ) +#elif defined( configCLINT_BASE_ADDRESS ) && !defined( configMTIME_BASE_ADDRESS ) + /* Legacy case where configCLINT_BASE_ADDRESS was set to the base address of + the CLINT. Equivalent now is to derive the MTIME and MTIMECMP addresses + from the CLINT address. */ + #define configMTIME_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0xBFF8UL ) + #define configMTIMECMP_BASE_ADDRESS ( ( configCLINT_BASE_ADDRESS ) + 0x4000UL ) +#elif !defined( configMTIME_BASE_ADDRESS ) || !defined( configMTIMECMP_BASE_ADDRESS ) + #error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html +#endif + + + +#ifdef __cplusplus +} +#endif + +#endif /* PORTMACRO_H */ + diff --git a/middleware/FreeRTOS/Source/portable/IAR/RISC-V/readme.txt b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/readme.txt new file mode 100644 index 000000000..b24c0b9fb --- /dev/null +++ b/middleware/FreeRTOS/Source/portable/IAR/RISC-V/readme.txt @@ -0,0 +1,23 @@ +/* + * The FreeRTOS kernel's RISC-V port is split between the the code that is + * common across all currently supported RISC-V chips (implementations of the + * RISC-V ISA), and code that tailors the port to a specific RISC-V chip: + * + * + FreeRTOS\Source\portable\GCC\RISC-V-RV32\portASM.S contains the code that + * is common to all currently supported RISC-V chips. There is only one + * portASM.S file because the same file is built for all RISC-V target chips. + * + * + Header files called freertos_risc_v_chip_specific_extensions.h contain the + * code that tailors the FreeRTOS kernel's RISC-V port to a specific RISC-V + * chip. There are multiple freertos_risc_v_chip_specific_extensions.h files + * as there are multiple RISC-V chip implementations. + * + * !!!NOTE!!! + * TAKE CARE TO INCLUDE THE CORRECT freertos_risc_v_chip_specific_extensions.h + * HEADER FILE FOR THE CHIP IN USE. This is done using the assembler's (not the + * compiler's!) include path. For example, if the chip in use includes a core + * local interrupter (CLINT) and does not include any chip specific register + * extensions then add the path below to the assembler's include path: + * FreeRTOS\Source\portable\GCC\RISC-V-RV32\chip_specific_extensions\RV32I_CLINT_no_extensions + * + */ diff --git a/middleware/agile_modbus/.gitignore b/middleware/agile_modbus/.gitignore new file mode 100644 index 000000000..35f8e276e --- /dev/null +++ b/middleware/agile_modbus/.gitignore @@ -0,0 +1,58 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb +.vscode + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Documentation +doc/doxygen/output/* +!doc/doxygen/output/index.html +!doc/doxygen/output/figures diff --git a/middleware/agile_modbus/CMakeLists.txt b/middleware/agile_modbus/CMakeLists.txt new file mode 100644 index 000000000..a47fec6c9 --- /dev/null +++ b/middleware/agile_modbus/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (c) 2023 HPMicro +# SPDX-License-Identifier: BSD-3-Clause + +sdk_inc(inc) +sdk_src(src/agile_modbus.c) + +if(CONFIG_AGILE_MODBUS_RTU) + sdk_src(src/agile_modbus_rtu.c) + sdk_compile_definitions(-DAGILE_MODBUS_USING_RTU) +endif() + +if(CONFIG_AGILE_MODBUS_TCP) + sdk_src(src/agile_modbus_tcp.c) + sdk_compile_definitions(-DUAGILE_MODBUS_USING_TCPP) +endif() + +if(CONFIG_AGILE_MODBUS_SLAVE_UTIL) + sdk_inc(util) + sdk_src(util/agile_modbus_slave_util.c) +endif() + diff --git a/middleware/agile_modbus/ChangeLog.md b/middleware/agile_modbus/ChangeLog.md new file mode 100644 index 000000000..254514aab --- /dev/null +++ b/middleware/agile_modbus/ChangeLog.md @@ -0,0 +1,77 @@ +# Update record + +## Agile Modbus 1.1.0 released + +### New function + +2021-12-02: Ma Longwei + +* Add Doxygen comments and generate documentation + +2021-12-28: Ma Longwei + +* Add RTU and TCP host examples +* Add RTU and TCP slave examples +* Add sample document + +2022-01-08: Ma Longwei + +* Add RTU point-to-point transmission file example +* Add RTU broadcast transmission file example + +### Revise + +2022-01-06: Ma Longwei + +* Modify the slave example, RTU and TCP use the same slave callback +* TCP slave supports up to 5 client access +* The TCP slave will automatically disconnect if it does not receive the correct message within 10s. + +2022-01-08: Ma Longwei + +* Remove the length limit in receiving data judgment +* Remove `agile_modbus_serialize_raw_request`'s length limit on raw data + +## Agile Modbus 1.1.1 released + +### Revise + +2022-06-22: Ma Longwei + +* README.md adds a bootloader link that supports Modbus firmware upgrade based on RT-Thread on AT32F437 +* Add HPM6750_Boot link +* Change LICENSE to `Apache-2.0` + +## Agile Modbus 1.1.2 released + +### New function + +2022-07-28: Ma Longwei + +* Provide simple slave access `agile_modbus_slave_util_callback` interface + +### Revise + +2022-07-28: Ma Longwei + +* `agile_modbus_slave_handle` adds `slave callback private data` parameter +* `agile_modbus_slave_callback_t` adds `private data` parameter +* The slave example in `examples` uses the `agile_modbus_slave_util_callback` interface to implement register reading and writing + +## Agile Modbus 1.1.3 released + +### Revise + +2022-11-22: Ma Longwei + +* Writing a single register in `agile_modbus_slave_handle` will point the `slave_info.buf` pointer to the local variable address. This address will be used by other variables after turning on compiler optimization. Modify it to point to the global variable address within the function. + +## Agile Modbus 1.1.4 released + +### Revise + +* fixed some warnings for some compiltion IDE such as ses + +### New function + +* Add API `agile_modbus_compute_response_length_from_request`: Obtain the length of the response from the slave based on the request diff --git a/middleware/agile_modbus/LICENSE b/middleware/agile_modbus/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/middleware/agile_modbus/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/middleware/agile_modbus/README.md b/middleware/agile_modbus/README.md new file mode 100644 index 000000000..74e6c3418 --- /dev/null +++ b/middleware/agile_modbus/README.md @@ -0,0 +1,340 @@ +# Agile Modbus + +## 1. Introduction + +Agile Modbus is a lightweight modbus protocol stack that meets the needs of users in any scenario. + +![ModbusProtocol](./figures/ModbusProtocol.jpg) + +- Online documentation: [API Manual](https://loogg.github.io/agile_modbus/) + +- The `examples` folder provides examples on PC + +- See examples on MCU [mcu_demos](https://github.com/loogg/agile_modbus_mcu_demos) + +- Bootloader based on RT-Thread on AT32F437 that supports Modbus firmware upgrade: [AT32F437_Boot](https://github.com/loogg/AT32F437_Boot) + +- Bootloader based on RT-Thread on HPM6750 that supports Modbus firmware upgrade: [HPM6750_Boot](https://github.com/loogg/HPM6750_Boot) + +### 1.1. Features + +1. Supports rtu and tcp protocols, is developed using pure C, does not involve any hardware interface, and can be used directly on any form of hardware. +2. Since it is developed using pure C and does not involve hardware, it can run the tcp protocol on the serial port and the rtu protocol on the network. +3. Support custom protocols compliant with modbus format. +4. Supports multiple masters and multiple slaves at the same time. +5. It is easy to use. You only need to initialize the rtu or tcp handle and call the corresponding API to package and unpack. + +### 1.2. Directory structure + +| Name | Description | +| ---- | ---- | +| doc | documentation | +| examples | examples | +| figures | materials | +| inc | header file | +| src | source code | +| util | Provides simple and practical components | + +### 1.3. License + +Agile Modbus complies with the `Apache-2.0` license, see the `LICENSE` file for details. + +## 2. Use Agile Modbus + +Please view the help document [doc/doxygen/Agile_Modbus.chm](./doc/doxygen/Agile_Modbus.chm) + +### 2.1. Transplantation + +- Users need to implement the `send data`, `wait for data reception to end` and `clear the receive buffer` functions of the hardware interface + + Regarding `waiting for data reception to end`, the following ideas are provided: + + 1. General method + + Every 20 /50 ms (this time can be set according to the baud rate and hardware, here is just a reference value) reads data from the hardware interface and stores it in the buffer and updates the offset until it cannot be read or the buffer is full. , exit reading. + + This applies to both bare metal and operating systems, which can accomplish blocking via `select` or `semaphore`. + + 2. Serial port `DMA + IDLE` interrupt mode + + Configure the `DMA + IDLE` interrupt, enable the flag in the interrupt, and determine whether the flag is set in the application program. + + However, this solution is prone to problems. If the data bytes are slightly staggered, it will not be a frame. The first option is recommended. + +- Host: + + 1. `agile_modbus_rtu_init` / `agile_modbus_tcp_init` initializes `RTU/TCP` environment + 2. `agile_modbus_set_slave` sets the slave address + 3. `Clear the receive cache` + 4. `agile_modbus_serialize_xxx` package request data + 5. `Send data` + 6. `Waiting for data reception to end` + 7. `agile_modbus_deserialize_xxx` Parse response data + 8. Data processed by users + +- Slave machine: + + 1. Implement the `agile_modbus_slave_callback_t` type callback function + 2. `agile_modbus_rtu_init` / `agile_modbus_tcp_init` initializes `RTU/TCP` environment + 3. `agile_modbus_set_slave` sets the slave address + 4. `Waiting for data reception to end` + 5. `agile_modbus_slave_handle` processes request data + 6. `Clear the receive buffer` (optional) + 7. `Send data` + +- Special function code + + You need to call the `agile_modbus_set_compute_meta_length_after_function_cb` and `agile_modbus_set_compute_data_length_after_meta_cb` APIs to set the callbacks for special function codes to be processed in master-slave mode. + + - `agile_modbus_set_compute_meta_length_after_function_cb` + + `msg_type == AGILE_MODBUS_MSG_INDICATION`: Returns the data element length of the host request message (uint8_t type). If it is not a special function code, 0 must be returned. + + `msg_type == MSG_CONFIRMATION`: Returns the data element length (uint8_t type) of the slave response message. If it is not a special function code, 1 must be returned. + + - `agile_modbus_set_compute_data_length_after_meta_cb` + + `msg_type == AGILE_MODBUS_MSG_INDICATION`: Returns the data length after the data element of the host request message. If it is not a special function code, 0 must be returned. + + `msg_type == MSG_CONFIRMATION`: Returns the data length after the data element of the slave response message. If it is not a special function code, it must return 0. + +- `agile_modbus_rtu_init` / `agile_modbus_tcp_init` + + When initializing the `RTU/TCP` environment, the user needs to pass in the `send buffer` and `receive buffer`. It is recommended that the size of both buffers is `AGILE_MODBUS_MAX_ADU_LENGTH` (260) bytes. `Special function code` is determined by the user according to the agreement. + + But for small memory MCUs, these two buffers can also be set small, and all APIs will judge the buffer size: + + Send buffer setting: If `expected request data length` or `expected response data length` is greater than `set send buffer size`, an exception is returned. + + Receive buffer setting: If the `message length requested by the host` is greater than the `set receive buffer size`, an exception will be returned. This is reasonable. When a small memory MCU is used as a slave, certain function codes must be restricted. + +### 2.2. Host + +See `2.1. Transplantation`. + +### 2.3. Slave machine + +#### 2.3.1. Interface description + +- Introduction to `agile_modbus_slave_handle` + + ```c + + int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict, + agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length) + + ``` + + msg_length: The length of data received after `waiting for the end of data reception`. + + slave_strict: slave address strictness check (0: Do not judge whether the address is consistent, it will be processed by user callback; 1: The address must be consistent, otherwise the callback will not be called and the response data will not be packaged). + + slave_cb: `agile_modbus_slave_callback_t` type callback function, implemented and passed in by the user. If it is NULL, all function codes can respond and are successful, but the register data is still 0. + + slave_data: slave callback function private data. + + frame_length: Get the length of the parsed modbus data frame. The meaning of this parameter is: + 1. There is dirty data at the end: it can still be parsed successfully and tells the user the real modbus frame length, which the user can process. + 2. Data sticky packet: The data consists of a complete frame of modbus data + a partial modbus data frame. After the user obtains the real modbus frame length, he can remove the processed modbus data frame and read the hardware interface data and the current one again. Part of the modbus data frame forms a new frame + 3. This parameter is often used when modbus broadcast transmits big data (such as custom function code broadcast to upgrade firmware). Ordinary slave responses are one question and one answer, and only the complete data frame is processed. It is recommended to Execute `clear receive cache` + +- Introduction to `agile_modbus_slave_callback_t` + + ```c + + /** + * @brief slave callback function + * @param ctx modbus handle + * @param slave_info slave information body + * @param data private data + * @return =0: normal; + * <0: Abnormal + * (-AGILE_MODBUS_EXCEPTION_UNKNOW(-255): Unknown exception, the slave will not package the response data) + * (Other negative exception codes: package exception response data from the opportunity) + */ + typedef int (*agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data); + + ``` + + `agile_modbus_slave_info`: + + sft: Contains slave address and function code attributes, which can be used in callbacks + + rsp_length: response data length pointer, its value needs to be updated when processing `special function code` in the callback, otherwise **not allowed to change** + + address: register address (not used by all function codes) + + nb: number (not used by all function codes) + + buf: data field required by different function codes (not used by all function codes) + + send_index: the current index of the send buffer (not used by all function codes) + +- `agile_modbus_slave_info` used by different function codes + + - AGILE_MODBUS_FC_READ_COILS、AGILE_MODBUS_FC_READ_DISCRETE_INPUTS + + The `address`, `nb`, and `send_index` attributes need to be used, and the `agile_modbus_slave_io_set` API needs to be called to store the IO data in the data area starting from `ctx->send_buf + send_index`. + + - AGILE_MODBUS_FC_READ_HOLDING_REGISTERS、AGILE_MODBUS_FC_READ_INPUT_REGISTERS + + The `address`, `nb`, and `send_index` attributes need to be used, and the `agile_modbus_slave_register_set` API needs to be called to store the register data in the data area starting from `ctx->send_buf + send_index`. + + - AGILE_MODBUS_FC_WRITE_SINGLE_COIL、AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER + + You need to use the `address` and `buf` attributes, force `buf` to the `int *` type, and get the value and store it in a register. + + - AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS + + The `address`, `nb`, `buf` attributes need to be used, and the `agile_modbus_slave_io_get` API needs to be called to obtain the IO data to be written. + + - AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS + + The `address`, `nb`, and `buf` attributes need to be used, and the `agile_modbus_slave_register_get` API needs to be called to obtain the register data to be written. + + - AGILE_MODBUS_FC_MASK_WRITE_REGISTER + + You need to use the `address` and `buf` attributes, pass `(buf[0] << 8) + buf[1]` to get the `and` value, pass `(buf[2] << 8) + buf[3 ]` Gets the `or` value. Get the register value `data`, perform the `data = (data & and) | (or & (~and))` operation to update the `data` value, and write it to the register. + + - AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS + + You need to use the `address`, `buf`, `send_index` attributes, pass `(buf[0] << 8) + buf[1]` to get the number of registers to be read, pass `(buf[2] << 8) + buf[3]` Get the register address to be written, and use `(buf[4] << 8) + buf[5]` to get the number of registers to be written. You need to call the `agile_modbus_slave_register_get` API to obtain the register data to be written, and call the `agile_modbus_slave_register_set` API to store the register data in the data area starting from `ctx->send_buf + send_index`. + + - Custom function code + + You need to use the `send_index`, `nb`, and `buf` attributes, and the user processes the data in the callback. + + send_index: current index of send buffer + + nb: PUD - 1, which is the modbus data field length + + buf: starting position of modbus data field + + **Note**: After the user fills data into the send buffer in the callback, the `rsp_length` value of `agile_modbus_slave_info` needs to be updated. + +#### 2.3.2. Simple slave access interface + +Agile Modbus provides an implementation of `agile_modbus_slave_callback_t`, allowing users to access it simply and conveniently. + +See [examples/slave](./examples/slave) for examples of usage. + +How to use: + +```c + +#include "agile_modbus.h" +#include "agile_modbus_slave_util.h" + +const agile_modbus_slave_util_t slave_util = { + /* User implementation */ + +}; + +agile_modbus_slave_handle(ctx, read_len, 0, agile_modbus_slave_util_callback, &slave_util, NULL); + +``` + +- Introduction to `agile_modbus_slave_util_callback` + + - An implementation of `agile_modbus_slave_callback_t` provided by Agile Modbus, which requires `agile_modbus_slave_util_t` type variable pointer as private data. + + - The private data is NULL, all function codes can respond and are successful, but the register data is still 0. + +- Introduction to `agile_modbus_slave_util_t` + + ```c + + typedef struct agile_modbus_slave_util { + const agile_modbus_slave_util_map_t *tab_bits; /**< Coil register definition array */ + int nb_bits; /**< Number of coil register definition arrays */ + const agile_modbus_slave_util_map_t *tab_input_bits; /**< Discrete input register definition array */ + int nb_input_bits; /**< Number of discrete input register definition arrays */ + const agile_modbus_slave_util_map_t *tab_registers; /**< Holding register definition array */ + int nb_registers; /**< Number of holding register definition arrays */ + const agile_modbus_slave_util_map_t *tab_input_registers; /**< Input register definition array */ + int nb_input_registers; /**< Number of input register definition arrays */ + int (*addr_check)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info); /**< Address check interface */ + int (*special_function)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info); /**< Special function code processing interface */ + int (*done)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, int ret); /**< Processing end interface */ + } agile_modbus_slave_util_t; + + ``` + + - Register related + + Users need to implement the definitions of `bits`, `input_bits`, `registers` and `input_registers`. If a register is defined as NULL, the function code corresponding to the register can respond and is successful, but the register data is all 0. + + - Interface calling process + + ![agile_modbus_slave_util_callback](./figures/agile_modbus_slave_util_callback.png) + +- Introduction to `agile_modbus_slave_util_map` + + ```c + + typedef struct agile_modbus_slave_util_map { + int start_addr; /**< starting address */ + int end_addr; /**< end address */ + int (*get)(void *buf, int bufsz); /**< Get register data interface */ + int (*set)(int index, int len, void *buf, int bufsz); /**< Set register data interface */ + } agile_modbus_slave_util_map_t; + + ``` + + - **Precautions**: + + - The number of registers determined by the start address and end address is limited. Changing the size of the `map_buf` array inside the function can make it larger. + + - bit register < 250 + + - register register < 125 + + - The interface function is NULL, and the function code corresponding to the register can respond and is successful. + + - `get` interface + + Copy all data in the address field to `buf`. + + - `set` interface + + - `index`: offset within the address field + + - `len`: length + + Modify data based on `index` and `len`. + +### 2.4. Example + +- Examples on PC are provided in the [examples](./examples) folder, which can be compiled and run under `WSL` or `Linux`. + + - Examples of RTU/TCP master and slave + + - Examples of special function codes + + RTU point-to-point transmission of files: Demonstrates the use of special function codes + + RTU broadcast transmission file: Demonstrates the use of `frame_length` in `agile_modbus_slave_handle` + +- [mcu_demos](https://github.com/loogg/agile_modbus_mcu_demos) provides examples on MCU. + +- [AT32F437_Boot](https://github.com/loogg/AT32F437_Boot) A Bootloader based on RT-Thread implemented on AT32F437 that supports Modbus firmware upgrade. + +- [HPM6750_Boot](https://github.com/loogg/HPM6750_Boot) A Bootloader based on RT-Thread implemented on HPM6750 that supports Modbus firmware upgrade. + +### 2.5. Doxygen document generation + +- Use `Doxywizard` to open [Doxyfile](./doc/doxygen/Doxyfile) and run it. The generated file will be under [doxygen/output](./doc/doxygen/output). +- `Graphviz` path needs to be changed. +- `HTML` is generated without using `chm` format. If it is enabled, you need to change the `hhc.exe` path. + +## 3. Support + +![zanshang](./figures/zanshang.jpg) + +If Agile Modbus solves your problem, you might as well scan the QR code above and invite me for a **cup of coffee** ~ + +## 4. Contact information & thanks + +- Maintenance: Ma Longwei +- Home page: +- Email: <2544047213@qq.com> diff --git a/middleware/agile_modbus/SConscript b/middleware/agile_modbus/SConscript new file mode 100644 index 000000000..97d9550de --- /dev/null +++ b/middleware/agile_modbus/SConscript @@ -0,0 +1,14 @@ +# RT-Thread building script for bridge + +from building import * + +cwd = GetCurrentDir() +src = Glob('src/*.c') +src += Glob('util/*.c') + +CPPPATH = [cwd + '/inc'] +CPPPATH += [cwd + '/util'] + +group = DefineGroup('agile_modbus', src, depend = ['PKG_USING_AGILE_MODBUS'], CPPPATH = CPPPATH) + +Return('group') diff --git a/middleware/agile_modbus/doc/Modbus_Application_Protocol_V1_1b3.pdf b/middleware/agile_modbus/doc/Modbus_Application_Protocol_V1_1b3.pdf new file mode 100644 index 000000000..b3c61ca46 Binary files /dev/null and b/middleware/agile_modbus/doc/Modbus_Application_Protocol_V1_1b3.pdf differ diff --git a/middleware/agile_modbus/doc/doxygen/Agile_Modbus.chm b/middleware/agile_modbus/doc/doxygen/Agile_Modbus.chm new file mode 100644 index 000000000..92fadf3e7 Binary files /dev/null and b/middleware/agile_modbus/doc/doxygen/Agile_Modbus.chm differ diff --git a/middleware/agile_modbus/doc/doxygen/Doxyfile b/middleware/agile_modbus/doc/doxygen/Doxyfile new file mode 100644 index 000000000..cc45606ff --- /dev/null +++ b/middleware/agile_modbus/doc/doxygen/Doxyfile @@ -0,0 +1,2690 @@ +# Doxyfile 1.9.2 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = "Agile Modbus" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 1.1.3 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Lightweight modbus protocol stack." + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = . + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = YES + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = YES + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = YES + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = YES + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = YES + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = NO + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../.. + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, +# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C +# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.l \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f18 \ + *.f \ + *.for \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ../../examples/build \ + ../../examples/common \ + ../../examples/rtu_master \ + ../../examples/slave \ + ../../examples/tcp_master \ + ../../examples/Makefile \ + ../../examples/rtu_broadcast \ + ../../examples/rtu_p2p + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = ../../README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = output + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = ../Agile_Modbus.chm + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = "D:/Doxygen/HTML Help Workshop/hhc.exe" + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATOR_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /