feat(ci): check LL functions not read write register by half word

This commit is contained in:
morris 2024-06-07 19:03:01 +08:00
parent 5e4abfdf09
commit dd46392a66
14 changed files with 189 additions and 0 deletions

View File

@ -66,6 +66,8 @@
- "tools/ci/check_esp_memory_utils_headers.sh" - "tools/ci/check_esp_memory_utils_headers.sh"
- "tools/ci/check_blobs.sh" - "tools/ci/check_blobs.sh"
- "tools/ci/check_public_headers.py" - "tools/ci/check_public_headers.py"
- "tools/ci/check_register_rw_half_word.cmake"
- "tools/ci/check_register_rw_half_word.py"
.patterns-host_test: &patterns-host_test .patterns-host_test: &patterns-host_test
- ".gitlab/ci/host-test.yml" - ".gitlab/ci/host-test.yml"

View File

@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
DEPENDS ${elf} DEPENDS ${elf}
) )
endif() endif()
message(STATUS "Checking gptimer registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "timer_group" "pcr" "hp_sys_clkrst"
HAL_MODULES "timer")

View File

@ -23,3 +23,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
DEPENDS ${elf} DEPENDS ${elf}
) )
endif() endif()
message(STATUS "Checking i2c registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "i2c" "pcr" "hp_sys_clkrst" "lpperi" "lp_clkrst"
HAL_MODULES "i2c")

View File

@ -12,3 +12,8 @@ project(jpeg_test)
target_add_binary_data(jpeg_test.elf "${IDF_PATH}/examples/peripherals/jpeg/jpeg_decode/resources/esp720.jpg" BINARY) target_add_binary_data(jpeg_test.elf "${IDF_PATH}/examples/peripherals/jpeg/jpeg_decode/resources/esp720.jpg" BINARY)
target_add_binary_data(jpeg_test.elf "${IDF_PATH}/examples/peripherals/jpeg/jpeg_decode/resources/esp1080.jpg" BINARY) target_add_binary_data(jpeg_test.elf "${IDF_PATH}/examples/peripherals/jpeg/jpeg_decode/resources/esp1080.jpg" BINARY)
target_add_binary_data(jpeg_test.elf "resources/esp480.rgb" BINARY) target_add_binary_data(jpeg_test.elf "resources/esp480.rgb" BINARY)
message(STATUS "Checking jpeg registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "jpeg" "hp_sys_clkrst"
HAL_MODULES "jpeg")

View File

@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
DEPENDS ${elf} DEPENDS ${elf}
) )
endif() endif()
message(STATUS "Checking mcpwm registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "mcpwm" "pcr" "hp_sys_clkrst"
HAL_MODULES "mcpwm")

View File

@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
DEPENDS ${elf} DEPENDS ${elf}
) )
endif() endif()
message(STATUS "Checking parlio registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "parl*io" "pcr" "hp_sys_clkrst"
HAL_MODULES "parlio")

View File

@ -7,3 +7,8 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main) set(COMPONENTS main)
project(ppa_test) project(ppa_test)
message(STATUS "Checking ppa registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "ppa" "hp_sys_clkrst"
HAL_MODULES "ppa")

View File

@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
DEPENDS ${elf} DEPENDS ${elf}
) )
endif() endif()
message(STATUS "Checking rmt registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "rmt" "pcr" "hp_sys_clkrst"
HAL_MODULES "rmt")

View File

@ -11,3 +11,8 @@ set(EXTRA_COMPONENT_DIRS
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(sdio) project(sdio)
message(STATUS "Checking sdio registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "host" "hinf" "slc" "pcr"
HAL_MODULES "sdio")

View File

@ -8,3 +8,8 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main esp_psram) set(COMPONENTS main esp_psram)
project(dma_test) project(dma_test)
message(STATUS "Checking dma registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "*gdma" "pcr" "hp_sys_clkrst"
HAL_MODULES "*gdma")

View File

@ -8,3 +8,8 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main esp_pm) set(COMPONENTS main esp_pm)
project(etm_test) project(etm_test)
message(STATUS "Checking etm registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "*etm" "pcr" "hp_sys_clkrst"
HAL_MODULES "etm")

View File

@ -19,3 +19,8 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
DEPENDS ${elf} DEPENDS ${elf}
) )
endif() endif()
message(STATUS "Checking mipi_dsi registers are not read-write by half-word")
include($ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.cmake)
check_register_rw_half_word(SOC_MODULES "*dsi*" "hp_sys_clkrst"
HAL_MODULES "*dsi*")

View File

@ -0,0 +1,33 @@
function(check_register_rw_half_word)
set(options)
set(oneValueArgs)
set(multiValueArgs SOC_MODULES HAL_MODULES)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT ARG_SOC_MODULES)
message(FATAL_ERROR "SOC_MODULES are required")
endif()
if(NOT ARG_HAL_MODULES)
message(FATAL_ERROR "HAL_MODULES are required")
endif()
idf_build_get_property(python PYTHON)
idf_build_get_property(idf_target IDF_TARGET)
execute_process(
COMMAND ${python} $ENV{IDF_PATH}/tools/ci/check_register_rw_half_word.py
--target-chip ${idf_target}
--soc-modules ${ARG_SOC_MODULES}
--hal-modules ${ARG_HAL_MODULES}
RESULT_VARIABLE result
OUTPUT_VARIABLE output
ERROR_VARIABLE error
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
if(result)
message(FATAL_ERROR "${output}")
endif()
endfunction()

View File

@ -0,0 +1,99 @@
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
import argparse
import os
import re
import sys
from pathlib import Path
from typing import Iterator
from typing import List
idf_path = os.environ.get('IDF_PATH', None)
def find_files(base_path: str, patterns: List[str]) -> Iterator[Path]:
for pattern in patterns:
yield from Path(base_path).rglob(f'**/{pattern}')
def read_and_capture_suspicious_fields(file_path: Path) -> List[str]:
with open(file_path, 'r') as file:
content = file.read()
captures = re.findall(r'uint32_t\s+(\w+)\s*:\s*(16|8)\s*;', content)
return [capture[0] for capture in captures if not capture[0].startswith('reserve')]
def main(
target_chip: str, soc_module_patterns: List[str], hal_module_patterns: List[str]
) -> None:
soc_path = f'{idf_path}/components/soc/{target_chip}/'
hal_path = f'{idf_path}/components/hal/{target_chip}/'
struct_file_patterns = [f'{pattern}_struct.h' for pattern in soc_module_patterns]
ll_file_patterns = [f'{pattern}_ll.h' for pattern in hal_module_patterns]
# Find `xxx_struct.h` files and `hal/yyy_ll.h` files
struct_files = find_files(soc_path, struct_file_patterns)
no_violation_found = True
for struct_file in struct_files:
# Capture suspicious fields from `xxx_struct.h`
captures = read_and_capture_suspicious_fields(struct_file)
# if no suspicious fields found, continue to next struct file
if not captures:
continue
# check if any of the captured fields are being read/written as half-words
ll_files = find_files(hal_path, ll_file_patterns)
for ll_file in ll_files:
with open(ll_file, 'r') as f:
content = f.read()
for capture in captures:
error_usages = [f'.{capture}', f'->{capture}']
for error_usage in error_usages:
word_bound_pattern = rf'{re.escape(error_usage)}\b'
# print the line number where the error_usage is found
for match in re.finditer(word_bound_pattern, content, re.MULTILINE):
no_violation_found = False
start_line = content.count('\n', 0, match.start()) + 1
print(
f'Found pattern {error_usage} at line {start_line} in file {ll_file}'
)
if no_violation_found:
print('No violations found')
else:
sys.exit(1)
if __name__ == '__main__':
if idf_path is None:
print('IDF_PATH must be set before running this script', file=sys.stderr)
sys.exit(1)
parser = argparse.ArgumentParser(
description='Check if any register fields are being read/written as half-words.'
)
parser.add_argument(
'--target-chip',
type=str,
required=True,
help='The name of the chip. e.g. esp32s3',
)
parser.add_argument(
'--soc-modules',
required=True,
type=str,
nargs='+', # allow multiple soc modules
help='Name pattern for the SOC module. e.g. spi means spi_struct.h',
)
parser.add_argument(
'--hal-modules',
required=True,
type=str,
nargs='+', # allow multiple hal modules
help='Name pattern for the HAL module. e.g. spi means spi_ll.h',
)
args = parser.parse_args()
main(args.target_chip, args.soc_modules, args.hal_modules)