From 53d949c651ab6612a4b1e982c3c2e1850bc0da03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=AF=E6=95=99=E6=8E=88?= <2530308275@qq.com> Date: Tue, 20 Aug 2024 09:44:27 +0800 Subject: [PATCH 1/2] test --- README2.md | 383 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 README2.md diff --git a/README2.md b/README2.md new file mode 100644 index 00000000..1c3637ff --- /dev/null +++ b/README2.md @@ -0,0 +1,383 @@ +# 3061M/3065H通用生态板嵌入式应用 + +## 3061M介绍 + +3061M系列 生态板由 ECBMCU201MPC(核心板)和 ECBMOTORA(电机驱动板组成)。 + +ECBMCU201MPC是针对 3061M系列 MCU开发的生态核心板,用于 3061M初始评估和设计参考,内嵌一块 USB接口的调试板。 + +ECBMOTORA是电机驱动扩展板,支持一个 BLDC或 PMSM电机控制。该单板支持24V/12V DCIN输入。 + +核心板电机驱动扩展板的常用组装方式是电机驱动板通过两个40pin连接器扣接到核心板,如下图所示。 + +![image-20240715162059747](./pic/image-20240715162059747.png) + +### 3061M硬件说明 + + 3061M通用生态板通过 ECBMCU201MPC核心板实现控制、 ECBMOTORA 扩展板实现接口扩展以及电源接口,同时提供USB TypeC线进行调试 / 供电、12V电源适配器和一个电机。 + +![image-20240715162244103](./pic/image-20240715162244103.png) + +3061M通用生态板用户手册详细内容请查阅:Hi3061M系列 通用生态板用户手册 00B01 + +## 3065H介绍 + +3065H 通用生态板由 ECBMCU105H (核心板)和 ECBMOTORA (电机驱动板)组成。 + +ECBMCU105H是针对 3065H 芯片开发的生态核心板,用于 3065H 芯片初始评估和设计参考,内嵌一块 USB 接口的调试板。 + +ECBMOTORA是电机驱动扩展板,支持一个 BLDC 或 PMSM 电机控制。该单板支持24V/12V DCIN 输入。 + +核心板电机驱动扩展板的常用组装方式是电机驱动板通过两个40pin 连接器扣接到核心板,如下图所示。 + +image-20240530173305431 + +### 3065H硬件说明 + + 3065H通用生态板通过ECBMCU105H 核心板实现控制、 ECBMOTORA 扩展板实现接口扩展以及电源接口,同时提供USB TypeC线进行调试 / 供电、12V电源适配器和一个电机。 + +![image-20240527103127826](./pic/image-20240527103127826.png) + +3065H通用生态板用户手册详细内容请查阅:Hi3065H通用生态板用户手册 V03 + +## 快速上手 + +目前支持在Windows环境下使用本项目的代码。 + +### Windows IDE环境搭建 + +在Windows下搭建编译开发环境, 我们推荐Windows 10 64位系统或以上版本, 简要步骤如下(详细内容参考tools目录下): + +#### 新建工程 + +1.下载 Hispark Studio IDE及独立工具: + +Hispark Studio IDE 版本下载链接(推荐使用):HisparkStudio + +Hispark Studio 独立工具下载链接:SolarA2IDE,具体包括如下独立工具: + +| 文件名 | 描述 | +| ------------------------------------ | ------------------ | +| VariableTrace-1.0.1.7.tar.gz | 实时变量监控工具。 | +| Programmer-1.0.0.1.tar.gz | 烧录工具。 | +| MotorControlWorkbench-1.0.0.0.tar.gz | 电机工具。 | + +Hispark Studio IDE 版本下载链接(历史归档版本):HiSparkStudio_beta + +2.打开 HiSpark Studio IDE,进入欢迎页面,单击“新建工程”,进入新建工程页面。 + +![img](./pic/clip_image002.png) + +3.后续弹窗中,根据所使用的开发板,"芯片"选择"3061MNPICA"或"3065HRPIRZ", 工程名由用户自定义,工程路径选择”用户自定义“,软件包选择工程使用的软件开发驱动包(SDK)文件夹根目录。 + +image-20240711142216428 + +![img](./pic/clip_image002-1719217272703-2.png) + +4.查看工程创建结果。HiSpark-Studio会自动打开新创建的工程,并进入芯片配置器界面(Chip Config界面),自动生成工程代码。 + +![image-20240711145131065](./pic/image-20240711145131065.png) + +#### 导入工程 + +1.打开HiSpark Studio,进入到欢迎页面,单击“导入工程”,进入导入工程页面。 + +![image-20240711142554419](./pic/image-20240711142554419.png) + +2.选择导入的路径,即可查找该路径下所有的工程,勾选需要导入的工程,单击“完成”。 + +![image-20240711145327804](./pic/image-20240711145327804.png) + +3.导入工程完成后,会在工程区展示出工程的文件夹,并在欢迎界面的工程列表中记录所导入的工程。 + +![image-20240711145349624](./pic/image-20240711145349624.png) + +#### 打开工程 + +1.打开HiSpark Studio,进入到欢迎页面,单击![image-20240528171519107](./pic/image-20240528171519107.png),进入打开工程页面。 + +![image-20240624162435476](./pic/image-20240624162435476.png) + +2.选择目标工程打开。 + +![image-20240624162440830](./pic/image-20240624162440830.png) + +①:选择目标工程所在的路径。 +②:选择导入类型为“Project Files(*.hiproj)”。 +③:选择目标文件,例如“demo.hiproj”。 + +④:单击“打开(O)”。 + +3.工作台视图中展示工程下面的文件夹,且在工程列表中出现当前打开的工程,表示打开工程成功。 + +![image-20240624163650613](./pic/image-20240624163650613.png) + +4.工程编译,以3061M与3065H在IDE中的操作步骤相同。下列步骤以3065H使用I2C 驱动模块为例: + +①:打开工程后,单击工具栏中的“芯片配置器”选项,如下图所示。 + +![image-20240624165203521](./pic/image-20240624165203521.png) + +②:使能I2C驱动模块,在配置界面配置I2C驱动模块。 + +![image-20240624165221921](./pic/image-20240624165221921.png)③:修改I2C驱动模块参数配置。 + +![image-20240624165232705](./pic/image-20240624165232705.png) + +④:生成I2C驱动模块代码。 + +![image-20240624165238779](./pic/image-20240624165238779.png) + +⑤:点击编译按钮![image-20240528173107958](./pic/image-20240528173107958.png),编译成功后终端窗口输出如下图所示。 + +![image-20240624165330284](./pic/image-20240624165330284.png) + +#### 工程烧录 + +1.将调试器连接主机端,将开发板接上电源线,连接好调试器与开发板,目前支持的调试器有两种:HiSpark-Trace和HiSpark-Link。下图使用HiSpark-Trace调试器烧录。 + +> 注:HiSpark-Trace调试器有多个连接口,连接错误会导致烧录失败,注意检查。 + +![image-20240624161626814](./pic/image-20240624161626814.png) + +2.进入工程配置界面。打开要烧录的工程后,单击顶部![image-20240624154427635](./pic/image-20240624154427635.png)的图标,进入工程配置界面->进入程序加载。选择传输方式为“swd”或者“jtag”并配置其他参数。 + +![image-20240624161948091](./pic/image-20240624161948091.png) + +3.单击“烧录”![image-20240624162016190](./pic/image-20240624162016190.png) 按钮,开始烧录。烧录成功后终端窗口输出如下图所示。 + +![image-20240624162037834](./pic/image-20240624162037834.png) + +## Demo + +3061M/3065H提供了以下Demo供开发参考,sample存放路径:[application_sample](https://gitee.com/HiSpark/open_mcu/tree/master/src/application) + +**主目录结构说明** + +| 文件夹名 | 描述 | +| ----------------- | -------------- | +| board\_sample | 开发板示例。 | +| drivers_sample | 驱动程序示例。 | +| middleware_sample | 中间件示例。 | +| user | 用户相关。 | + +**表 1 board\_sample目录结构说明** + +| **文件夹名** | **描述** | +| ------------ | -------------------------- | +| dimming | 呼吸灯功能示例。 | +| key | 按键检查功能示例。 | +| led | 数码管功能示例。 | +| pulses | gpio发送pwm波功能示例。 | +| softserial | gpio实现串口通信功能示例。 | + +**表 2 acmp目录结构说明** + +| **文件夹名** | **描述** | +| ------------ | ---------------- | +| sample_acmp | 比较器使用示例。 | + +**表 3 adc目录结构说明** + +| **文件夹名** | **描述** | +| ------------------------------------- | ------------------- | +| sample_adc_associative_trigger_of_apt | APT触发ADC。 | +| sample_adc_continue_trigger | ADC连续采样。 | +| sample_adc_over_sample | ADC过采样。 | +| sample_adc_single_trigger | ADC单次采样。 | +| sample_adc_single_trigger_dma | ADC单次采样带DMA。 | +| sample_adc_single_trigger_it | ADC单次采样带中断。 | +| sample_adc_sync_sample | ADC同步采样。 | +| sample_adc_sync_sample_dma | ADC同步采样带DMA。 | +| sample_adc_sync_sample_it | ADC同步采样带中断。 | + +**表 4 apt目录结构说明** + +| **文件夹名** | **描述** | +| -------------------------- | ------------------------------------------------- | +| sample_apt_single_resistor | APT单电阻采样示例,仅在U相触发ADC采样信号。 | +| sample_apt_three_resistor | APT三电阻采样示例,在U、V和W相都触发ADC采样信号。 | + +**表 5 can目录结构说明** + +| **文件夹名** | **描述** | +| ----------------------- | ----------------------- | +| sample_can_send_receive | CAN发送和接收数据示例。 | + +**表 6 capm目录结构说明** + +| **文件夹名** | **描述** | +| ---------------- | -------------------------- | +| capm_hall_sample | CAPM读取霍尔传感器值示例。 | + +**表 7 cfd目录结构说明** + +| **文件夹名** | **描述** | +| ---------------------- | ------------------------------------- | +| sample_cfd_check_error | cfd注入错误前后监测目标时钟异常功能。 | + +**表 8 cmm目录结构说明** + +| **文件夹名** | **描述** | +| ---------------------- | ------------------------------------- | +| sample_cmm_check_error | cmm注入错误前后监测目标时钟异常功能。 | + +**表 9 crc目录结构说明** + +| **文件夹名** | **描述** | +| ---------------- | -------------------------------------------------------- | +| sample_crc_check | 测试CRC不同算法和输入有效位宽,生成并校验crc值。 | +| sample_crc_gen | 计算并生成CRC数值。 | +| sample_crc_load | 通过load初始值将xmodem算法改为ccit-false算法并校验结果。 | + +**表 10 dac目录结构说明** + +| **文件夹名** | **描述** | +| ------------ | ----------------------- | +| sample_dac | DAC电压输出到管脚示例。 | + +**表 11 dma目录结构说明** + +| **文件夹名** | **描述** | +| --------------------------------- | ------------------------- | +| sample_dma_list_transfer | DMA链式传输。 | +| sample_dma_list_transfer_continue | DMA链式传输实现连续功能。 | +| sample_dma_mem_to_mem | DMA内存到内存传输。 | +| sample_dma_mem_to_per | DMA内存到外设传输。 | +| sample_dma_per_to_mem | DMA外设到内存传输。 | +| sample_dma_per_to_per | DMA外设到外设传输。 | + +**表 12 flash目录结构说明** + +| **文件夹名** | **描述** | +| ---------------------- | ------------------- | +| sample_flash_blocking | 阻塞模式操作flash。 | +| sample_flash_interrupt | 中断方式操作flash。 | + +**表 13 gpio目录结构说明** + +| **文件夹名** | **描述** | +| --------------------- | ---------------------------- | +| sample_gpio_circle | GPIO环回测试电平和方向属性。 | +| sample_gpio_interrupt | 测试GPIO不同中断类型。 | +| sample_gpio_key | GPIO用作按键功能。 | +| sample_gpio_led | GPIO周期控制led亮灭功能。 | + +**表 14 gpt目录结构说明** + +| **文件夹名** | **描述** | +| -------------------- | ---------------- | +| sample_gpt_simplerun | gpt产生PWM波形。 | + +**表 15 i2c目录结构说明** + +| **文件夹名** | **描述** | +| --------------------------- | ------------------------------ | +| sample_i2c_blocking_stlm75 | 使用阻塞的方式读写温度传感器。 | +| sample_i2c_interrupt_stlm75 | 使用中断的方式读写温度传感器。 | +| sample_i2c_dma_stlm75 | 使用dma方式读写温度传感器。 | + +**表 16 iocmg目录结构说明** + +| **文件夹名** | **描述** | +| ------------- | ----------------------------------- | +| iolist_sample | iocmg初始化管脚列表的属性配置功能。 | + +**表 17 pga目录结构说明** + +| **文件夹名** | **描述** | +| ------------------------- | --------------------- | +| sample_pga | PGA内部电阻放大示例。 | +| sample_pga_extra_resistor | PGA外部电阻放大示例。 | + +**表 18 pmc目录结构说明** + +| **文件夹名** | **描述** | +| ----------------- | ------------------- | +| sample_pmc_pvd | PMC掉电检测示例。 | +| sample_pmc_wakeup | PMC定时器唤醒示例。 | + +**表 19 qdm目录结构说明** + +| **文件夹名** | **描述** | +| ------------- | ------------------------------- | +| sample_qdm_m | QDM使用M法读取电机转速的示例。 | +| sample_qdm_mt | QDM使用MT法读取电机转速的示例。 | + +**表 20 spi目录机构说明** + +| **文件夹名** | **描述** | +| ---------------------------- | --------------------------------- | +| sample_spi_blocking_kta7953 | 使用阻塞方式读写ADC。 | +| sample_spi_dma_kta7953 | 使用dma方式读写ADC。 | +| sample_spi_interrupt_kta7953 | 使用中断方式读写ADC。 | +| sample_spi_microwire_master | 演示如何使用microwire master。 | +| sample_spi_microwire_slave | 演示如何使用microwire slave。 | +| sample_spi_slave | 演示如何使用motorola spi slaver。 | + +**表 21 timer目录结构说明** + +| **文件夹名** | **描述** | +| ---------------------- | ------------------------------------- | +| sample_timer_interrupt | timer定时触发中断,执行用户串口打印。 | + +**表 22 tsensor目录结构说明** + +| **文件夹名** | **描述** | +| -------------- | ----------------------- | +| sample_tsensor | tsensor对器件结温采样。 | + +**表 23 uart目录结构说明** + +| **文件夹名** | **描述** | +| ---------------------------------------- | ------------------------------------------ | +| sample_uart_blocking_rx | UART阻塞接收。 | +| sample_uart_blocking_tx | UART阻塞发送。 | +| sample_uart_dma_rx | UART带DMA接收。 | +| sample_uart_dma_tx | UART带DMA发送。 | +| sample_uart_interrupt_tx_after_rx | UART中断接收数据之后,再中断发送此数据。 | +| sample_uart_interrupt_rx | UART中断接收。 | +| sample_uart_interrupt_tx | UART中断发送。 | +| sample_uart_dma_tx_dma_rx_simultaneously | UART全双工模式,DMA同时发送和接收。 | +| sample_uart_dma_tx_int_rx_simultaneously | UART全双工模式,DMA发送的同时,中断接收。 | +| sample_uart_int_tx_dma_rx_simultaneously | UART全双工模式,中断发送的同时,DMA接收。 | +| sample_uart_int_tx_int_rx_simultaneously | UART全双工模式,中断发送的同时,中断接收。 | +| sample_uart_dma_rx_cyclically_stored | UART使用DMA循环搬运数据到指定内存。 | +| sample_uart_single_wire_communication | UART单线通信示例。 | + +**表 24 wdg目录机构说明** + +| **文件夹名** | **描述** | +| ----------------- | ------------------------ | +| sample_wdg_reset | 测试wdg不喂狗复位功能。 | +| sample_iwdg_reset | 测试iwdg不喂狗复位功能。 | + +**表 25 middleware\_sample目录机构说明** + +| **文件夹名** | **描述** | +| -------------------------- | --------------------------------------- | +| mcs_65ldemo | 电机控制算法在AD101HDMA_VER.B板的示例。 | +| mcs_65demo | 电机控制算法在AD105HDMA_VER.B板的示例。 | +| pmsm_sensorless_1shunt_foc | 永磁同步电机单电阻采样无感FOC应用。 | +| pmsm_sensorless_2shunt_foc | 永磁同步电机双电阻采样无感FOC应用。 | + +## **问题与解答** + +如果你对项目中的代码或者文档存在疑问, 欢迎在Issues中提出你的问题(别忘了先在FAQ中看一看是否已经有答案了😎). 如果你自己解决了一个了不起的问题, 非常欢迎你把问题和解决方法发到Issues里, 如果你看到别人的问题而你正好有答案, 也欢迎你帮助解答其他人的问题, 所谓"授人玫瑰手有余香"嘛。 + +## **参与贡献** + +我们非常欢迎你能对这个项目提出代码上的改进或扩展, 方法是: + +1. Fork 本仓库 +2. 下载到本地, 修改, 提交 +3. 推送代码 +4. 在页面点击 Pull Request + +这样我们就能接到你的推送申请。 + +## **最后的话** + +Hispark Studio是一款年轻且处于快速发展的IDE。在使用过程中,你可能会碰到一些棘手的问题,但别担心,你可以尝试多种方法去解决,比如用搜索引擎寻找答案,或者向社区寻求帮助。记住,所有技术大神都是从解决这些问题中成长起来的。我们和其他开发者也会尽力提供帮助。 + +最后的最后, 欢迎来到Hispark Studio的世界探险! \ No newline at end of file -- Gitee From 6db4fc6c8a606189de0aacdde0aeed15f43f2dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=94=AF=E6=95=99=E6=8E=88?= <2530308275@qq.com> Date: Tue, 20 Aug 2024 09:51:21 +0800 Subject: [PATCH 2/2] test --- vendor/build_sample.py | 473 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 473 insertions(+) create mode 100644 vendor/build_sample.py diff --git a/vendor/build_sample.py b/vendor/build_sample.py new file mode 100644 index 00000000..26f17aa6 --- /dev/null +++ b/vendor/build_sample.py @@ -0,0 +1,473 @@ +import os +import sys +import pathlib +from configparser import ConfigParser +import stat +import time +import shutil +import shlex +import subprocess +import platform +import hashlib +import json + +script_a_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../src/build')) +sys.path.append(script_a_path) + +from build_gn import read_json_file +from ide_entry import un_alltools +from build import remove_readonly + +#ws63编译配置 +BUILD_INFO_FILENAME = 'build_config.json' +# 定义要执行的脚本文件和目录 +build_directory_path = 'src' +ws63_log_image_target_directory = 'archives' +global_combined = '' + +# 获取本次git提交目录名称 +def get_changed_folders_in_vendor(): + folder_name= '' + src_folder_name= '' + print(f"start get_changed_folders_in_directory") + try: + # 执行git命令获取本次提交的变更文件列表,除去根目录src目录,其他目录提交都显示 + git_command = "git diff --name-only origin/HEAD..HEAD" + output = subprocess.check_output(git_command, shell=True, text=True) + # 将输出按行分割成文件路径列表 + changed_files = output.strip().split("\n") + # 初始化变量,用于记录是否有改变的文件类型 + has_c_or_h_files = False + # 遍历每个文件路径 + for file_path in changed_files: + if file_path.endswith(".c") or file_path.endswith(".h"): + has_c_or_h_files = True + break + changed_folders = set() + for file_path in changed_files: + # 提取文件夹名称 + if '/' in file_path: + src_folder_name = file_path.split('/')[0] + if '"src' in src_folder_name or 'src' in src_folder_name: + print(f"invalid modify, not allow modify src dir and build script") + sys.exit(0) + if has_c_or_h_files: + for file_path in changed_files: + if file_path.endswith(".c") or file_path.endswith(".h"): + folder_name = file_path.split('/')[1] + '+' + file_path.split('/')[2] + '+' + file_path.split('/')[3] + else: + '' + if folder_name: + changed_folders.add(folder_name) + print(f"[get_changed_folders_in_vendor] changed_folders: {changed_folders}") + return changed_folders + else: + print(f"not need build, only doc or readme been modified") + sys.exit(0) + except subprocess.CalledProcessError as e: + print(f"Error executing Git command: {e}") + return None + + +# 获取代码仓所有build_info.json文件内容,并拼接在一起 +def process_build_info_files(): + print(f"start process_build_info_files") + result_list = [] + # 遍历指定目录及其子目录下的所有文件和文件夹 + for root, dirs, files in os.walk("./"): + for file in files: + if file == BUILD_INFO_FILENAME: + file_path = os.path.join(root, file) + print(file_path) + # 读取JSON文件内容 + with open(file_path, 'r') as f: + try: + data = json.load(f) + for item in data: + # 提取需要的字段值 + build_target = item.get('buildTarget', '') + relative_path = item.get('relativePath', '').replace('/','-') + chip_name = item.get('chip', '') + # 组合成一个字符串并添加到结果列表 + if item.get('buildDef', ''): + build_def = item.get('buildDef', '') + combined_value = f"{file_path}+{build_target}+{relative_path}+{chip_name}+{build_def}" + else: + combined_value = f"{file_path}+{build_target}+{relative_path}+{chip_name}" + result_list.append(combined_value) + except json.JSONDecodeError: + print(f"Error decoding JSON in file: {file_path}") + sys.exit(-1) + return result_list + +# 对比git和json内容,一致则代表提交,不一样代表之前提交 +def extract_exact_match(input_list, match_list): + print(f"start extract_exact_match") + print(f"[extract_exact_match] input_list: {input_list}") + print(f"[extract_exact_match] match_list: {match_list}") + exact_matches = [] + try: + for string in input_list: + # 使用 split 方法获取第二个 + 和第三个 + 之间的内容 + parts = string.split('+') + if len(parts) >= 4: + sample_company_name = parts[0].split('/')[2] + sample_name_field = parts[2].replace('-','+') + combined_string = sample_company_name + "+" + sample_name_field + if combined_string in match_list: + exact_matches.append(string) + print(f"[extract_exact_match] exact_matches: {exact_matches}") + if not exact_matches: + print(f"build-config has not been synchronously updated") + exit(0) # 退出并返回非零状 + else: + print("exact_matche 列表不为空") + return exact_matches + except TypeError as e: + print(f"Error: {e}") + # 在捕获到异常后,可以选择退出程序 + exit(0) # 退出并返回非零状 + +# 如果代码编译cmakelist文件中通过宏控制编译哪些文件,则需要用宏重新组合编译配置信息 +def sample_meunconfig_modify(input_list): + print(f"start sample_meunconfig_modify{input_list}") + # 初始化结果列表 + result_list = [] + combined_string = "" + for string in input_list: + parts = string.split('+') + sample_file_path = parts[0] + build_target = parts[1] + sample_name = parts[2] + platform = parts[3] + if len(parts) == 5: + def_name = parts[4] + # 根据逗号分割字符串 + def_parts = def_name.split(',') + # 遍历分割后的每一个部分,添加到结果列表中,宏的个数,决定编译的次数 + if len(def_parts) == 1 and def_parts[0] == def_name: + result_list.append(sample_file_path+"+"+build_target+"+"+sample_name+"+"+platform+"+"+def_name) + else: + for idx, part in enumerate(def_parts): + if idx == 0: + combined_string = part + else: + combined_string += "+" + part # 在每个部分之前添加加号 + result_list.append(sample_file_path+"+"+build_target+"+"+sample_name+"+"+platform+"+"+combined_string) + # 如果没有逗号,则整个字符串保存到结果列表 + elif len(parts) == 4: + result_list.append(sample_file_path+"+"+build_target+"+"+sample_name+"+"+platform) + return result_list + + +def dest_path_cpoy(copy_path, dirprocesspath, dirpath, filenames): + dest_path = pathlib.Path(copy_path).joinpath(dirprocesspath) + if not dest_path.exists(): + os.makedirs(dest_path) + for file in filenames: + if 'entry.py' in file or 'trustlist.json' in file: + continue + source_file = pathlib.Path(dirpath).joinpath(file) + shutil.copy(source_file, dest_path) + +def filter_copy_adpater(copy_path, dirpath, filenames): + ''' + Function description: project creat. + ''' + ipbefore_list = [] + ipafter_list = [] + cur_sys = platform.system() + if cur_sys == 'Windows': + ipbefore_list = dirpath.split('\\') + elif cur_sys == 'Linux': + ipbefore_list = dirpath.split('/') + ipafter_list = [] + p_vindex = 0 + p_cindex = -1 + for v_index, ipdir in enumerate(ipbefore_list): + if ipdir.startswith('v') and '.' in ipdir: + continue + # Filtering files + if '_v' in ipdir: + p_vindex = v_index + if 'common_v' in ipdir: + p_cindex = v_index + ipafter_list.append(ipdir) + if ipafter_list[p_vindex - 1] + '_v' in ipafter_list[p_vindex]: + ipafter_list.pop(p_vindex) + if p_cindex >= 0: + ipafter_list[p_cindex] = 'common' + p_cindex = -1 + dirprocesspath = '/'.join(ipafter_list) + dest_path_cpoy(copy_path, dirprocesspath, dirpath, filenames) + +def traversal_path(copy_path, module_path, version): + ''' + Function description:creat and copy work + ''' + for (dirpath, _, filenames) in os.walk(module_path): + filter_copy_adpater(copy_path, dirpath, filenames) + +def copy_drive_modules(copy_abspath, product, ip_name, copyjson_content): + ''' + function description: copying drive modules + ''' + source_path = os.path.join('drivers', ip_name) + for ip_content in copyjson_content[ip_name]: + source_path = os.path.join(source_path, ip_content) + if pathlib.Path(source_path).is_dir(): + traversal_path(copy_abspath, source_path, product) + elif pathlib.Path(source_path).is_file(): + parent_path = pathlib.Path(source_path).parent_path + copy_parent_path = pathlib.Path(copy_abspath).joinpath(parent_path) + if not copy_parent_path.exists(): + os.makedirs(copy_parent_path) + shutil.copy(source_path, copy_parent_path) + source_path = '' + source_path = os.path.join('drivers', ip_name) + +def copy_code(product, copy_path): + ''' + Funcuntion + ''' + if not isinstance(copy_path, str): + raise TypeError("copy_path in para type error {}".format(type(copy_path))) + if not isinstance(product, str): + raise TypeError("product in para type error {}".format(type(product))) + # copy file path + if pathlib.Path(copy_path).exists(): + shutil.rmtree(os.path.realpath(copy_path), onerror=remove_readonly) + copy_abspath = pathlib.Path(copy_path).resolve() + copyjson_path = pathlib.Path.cwd().joinpath('chip', "{}".format(product), 'codecopy.json') + print(f"[sample_build_prepare] source_directory: {copyjson_path}") + copyjson_content = read_json_file(copyjson_path) + #Add the basic modules + for module_path in copyjson_content['modules']: + if pathlib.Path(module_path).is_dir(): + traversal_path(copy_abspath, module_path, product) + elif pathlib.Path(module_path).is_file(): + #File copy processing basic module + parent_path = pathlib.Path(module_path).parent + copy_parent_path = pathlib.Path(copy_abspath).joinpath(parent_path) + if not copy_parent_path.exists(): + os.makedirs(copy_parent_path) + shutil.copy(module_path, copy_parent_path) + if str(parent_path) == 'chip\\target' or str(parent_path) == 'chip/target': + userconfig_json_name = module_path.split('/')[-1] + os.rename(pathlib.Path(copy_parent_path).joinpath(userconfig_json_name)),pathlib.Path(copy_parent_path).joinpath('userconfig.json') + #Copying drive modules + for ip_name in copyjson_content['ip_drive_file']: + copy_drive_modules(copy_abspath, product, ip_name, copyjson_content) + +def differ_file_copy(copy_chip, copy_path, tools_path): + ''' + Function description: Projection generation for different chip + ''' + un_alltools(tools_path) + # Detach the chip package + copy_code(copy_chip, copy_path) + os.chdir(pathlib.Path(copy_path).resolve()) + target_pathconfigsource = pathlib.Path().cwd().joinpath('chip', copy_chip, 'target') + target_pathconfigdest = pathlib.Path().cwd().joinpath('chip', 'target') + # Target file replace + if pathlib.Path(target_pathconfigsource).exists(): + shutil.rmtree(target_pathconfigdest) + shutil.copytree(target_pathconfigsource, target_pathconfigdest) + # write the path of the full package tool to the config.ini file. + config_path = pathlib.Path().cwd().joinpath('build', 'config.ini') + config = ConfigParser() + config.read(config_path) + config.set('gn_args', 'tools_path', tools_path) + flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + modes = stat.S_IWUSR | stat.S_IRUSR + flagsone = os.O_RDWR | os.O_CREAT + # File socket of the config.ini file. + with os.fdopen(os.open(config_path, flags, modes), 'w+') as configini: + config.write(configini) + # Executing Build and Compile Commands + cmd = shlex.split('python build/build.py build') + proc = subprocess.Popen(cmd) + proc.wait() + ret_code = proc.returncode + if ret_code != 0: + raise Exception("CI {} failed, return code is {}".format(cmd, ret_code)) + + +def move_file(source_file, new_filename): + print(f"start move_file") + target_file = os.path.join(f'../../archives', new_filename) + os.chmod(source_file, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + try: + # 移动并重命名文件 + shutil.move(source_file, target_file) + os.chmod(target_file, stat.S_IRWXU | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) + print(f"文件 {source_file} 移动并重命名为 {target_file} 成功。") + except FileNotFoundError: + print(f"找不到文件 {source_file}") + except PermissionError: + print(f"权限错误,无法移动文件。") + except Exception as e: + print(f"发生错误:{str(e)}") + +def delete_file(directory, filename): + # 拼接文件路径 + file_path = os.path.join(directory, filename) + + # 检查文件是否存在 + if os.path.isfile(file_path): + try: + # 删除文件 + os.remove(file_path) + print(f"文件 {filename} 已被成功删除。") + except Exception as e: + print(f"删除文件时出错: {e}") + else: + print(f"文件 {filename} 不存在于目录 {directory} 中。") + +def remove_lines(file_path, start_line, end_line): + try: + with open(file_path, 'r') as file: + lines = file.readlines() + + # 删除指定范围的行 + if start_line > 0 and end_line <= len(lines): + del lines[start_line-1:end_line] + else: + print("行号超出范围") + return + + with open(file_path, 'w') as file: + file.writelines(lines) + + print(f"已删除文件 {file_path} 中第 {start_line} 行到第 {end_line} 行的内容。") + except Exception as e: + print(f"处理文件时出错: {e}") + +def has_main_h(directory, file): + for root, dirs, files in os.walk(directory): + if file in files: + return True + return False + +def differ_file_copy(copy_chip, copy_path, tools_path, source_directory): + ''' + Function description: Projection generation for different chip + ''' + un_alltools(tools_path) + # Detach the chip package + + copy_code(copy_chip, copy_path) + os.chdir(pathlib.Path(copy_path).resolve()) + target_pathconfigsource = pathlib.Path().cwd().joinpath('chip', copy_chip, 'target') + target_pathconfigdest = pathlib.Path().cwd().joinpath('chip', 'target') + # Target file replace + if pathlib.Path(target_pathconfigsource).exists(): + shutil.rmtree(target_pathconfigdest) + shutil.copytree(target_pathconfigsource, target_pathconfigdest) + # write the path of the full package tool to the config.ini file. + config_path = pathlib.Path().cwd().joinpath('build', 'config.ini') + config = ConfigParser() + config.read(config_path) + config.set('gn_args', 'tools_path', tools_path) + flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + modes = stat.S_IWUSR | stat.S_IRUSR + flagsone = os.O_RDWR | os.O_CREAT + # File socket of the config.ini file. + with os.fdopen(os.open(config_path, flags, modes), 'w+') as configini: + config.write(configini) + # Executing Build and Compile Commands + + print(f"start compile_sdk_and_save_log") + current_dir = os.getcwd() + print(f"Current working directory: {current_dir}") + delete_file("middleware/thirdparty/sysroot/lib", 'libnostask.a') + if copy_chip == '3061m' or copy_chip == '3065h': + remove_lines("middleware/hisilicon/nostask/kernel/nos_amp_task.c", 48, 63) + if has_main_h(source_directory, "main.h"): + delete_file("generatecode", "main.h") + if has_main_h(source_directory, "system_init.c"): + delete_file("generatecode", "system_init.c") + if has_main_h(source_directory, "feature.h"): + delete_file("generatecode", "feature.h") + if has_main_h(source_directory, "main.c"): + delete_file("application/user", "main.c") + shutil.copytree(source_directory, "generatecode", dirs_exist_ok=True) + # 创建目录archives + if not os.path.exists("../../archives"): + os.mkdir("../../archives") + args = ['build/build.py', "build"] + try: + # 打开日志文件准备写入 + # 使用 subprocess.Popen() 执行命令,并将标准输出和标准错误重定向到日志文件 + start_time = time.time() + subprocess.Popen(['python'] + args, text=False) + end_time = time.time() + # 计算运行时间 + elapsed_time = end_time - start_time + time.sleep(2) + print(f"程序运行时间: {elapsed_time:.2f} 秒") + print(f"Finished: SUCCESS") + move_file("out/build.log", f'{global_combined}.log') + time.sleep(2) + move_file("out/bin/target.bin", f'{global_combined}.bin') + parent_dir = os.path.abspath(os.path.join(current_dir, os.pardir)) + os.chdir(parent_dir) + shutil.rmtree(copy_path) + except Exception as e: + print(f"An error occurred: {str(e)}") + + +def ci_entry(input_list): + ''' + Function description: ci entry function + ''' + os.chdir(build_directory_path) + tools_path = str(pathlib.Path().cwd().joinpath('tools', 'toolchain')) + print(f"start sample_build_prepare") + print(f"[sample_build_prepare] input_list: {input_list}") + global global_combined + for string in input_list: + parts = string.split('+') + sample_file_path = parts[0] + build_target = parts[1] + sample_name = parts[2] + platfor_name = parts[3] + remaining_parts = parts[1:4] + global_combined = '_'.join(remaining_parts) + if len(parts) >= 5: + global_combined += '_' + build_def_sha = hashlib.sha256('-'.join(parts[4:]).encode('utf-8',errors='ignore')) + global_combined += build_def_sha.hexdigest()[:32] + # 获取sample目录路径,并复制到指定目录 + # 截取目标内容 + target_string = sample_file_path.split('/build_config.json')[0] + '/' + samples = sample_name.replace('-','/') + source_directory = "../." + target_string + samples + print(f"[sample_build_prepare] source_directory: {source_directory}") + copy_path = 'mcu_' + platfor_name + '_project' + working_path = pathlib.Path.cwd() + if platfor_name == '3061M' or platfor_name == '3061m': + copy_chip = "3061m" + elif platfor_name == '3065H' or platfor_name == '3065h': + copy_chip = "3065h" + elif platfor_name == '3015' or platfor_name == '3015': + copy_chip = "3015" + elif platfor_name == '3066M' or platfor_name == '3066m': + copy_chip = "3066m" + else: + print(f"Wrong chip name\r\n") + exit(0) + differ_file_copy(copy_chip, copy_path, tools_path, source_directory) + + +def main(): + print(f"start main") + check_list = get_changed_folders_in_vendor() + input_list = process_build_info_files() + sample_name = extract_exact_match(input_list, check_list) + result_list = sample_meunconfig_modify(sample_name) + ci_entry(result_list) + print(f"all build step execute end") + +if __name__ == '__main__': + sys.exit(main()) \ No newline at end of file -- Gitee