ARM (6) - I.MX6ULL 匯編點燈遷移至 C 語言 + SDK 移植與 BSP 工程搭建

回顧

一、核心關鍵字:volatile

1.1 作用

  • 告訴編譯器:被修飾的變量會被 “意外修改”(如硬件寄存器的值可能被外設自動更新),禁止編譯器對該變量進行優化(如緩存到寄存器、刪除未顯式修改的代碼)。
  • 本質:確保每次訪問變量時,都直接讀取 / 寫入內存地址,而非使用編譯器緩存的 “舊值”。

1.2 寄存器操作中的必要性

以 GPIO 寄存器為例,若不加volatile

// 錯誤:編譯器可能優化為“只寫一次”,后續操作失效
#define GPIO1_DR *((unsigned int *)0x0209C000) 
GPIO1_DR &= ~(1<<3); // 期望拉低引腳
GPIO1_DR |= (1<<3);  // 期望拉高引腳(編譯器可能認為“無用”,直接刪除)

volatile后:

// 正確:每次操作都直接訪問0x0209C000地址
#define GPIO1_DR *((volatile unsigned int *)0x0209C000) 

二、基礎 C 語言點燈實現

2.1 寄存器地址定義

兩種常見方式:直接宏定義、結構體封裝(推薦后者,更易維護)。

方式 1:直接宏定義
// I.MX6ULL 關鍵寄存器(引腳復用、GPIO控制)
//int 指令/寄存器是四個字節 
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03   *((volatile unsigned int *)0x020E0068) // 引腳復用控制
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03   *((volatile unsigned int *)0x020E02F4) // 引腳電氣屬性(上拉/驅動能力)
#define GPIO1_DR   *((volatile unsigned int *)0x0209C000) // GPIO數據寄存器
#define GPIO1_GDIR  *((volatile unsigned int *)0x0209C004) // GPIO方向寄存器(輸入/輸出) // volatile 防止編譯器優化:  reg = reg //會被優化掉
// const char *p;
// char * const p;// ------定義時鐘門寄存器地址
#define CCM_CCGR0 *((volatile unsigned int *)0x020C4068)
#define CCM_CCGR1 *((volatile unsigned int *)0x020C406C)
#define CCM_CCGR2 *((volatile unsigned int *)0x020C4070)
#define CCM_CCGR3 *((volatile unsigned int *)0x020C4074)
#define CCM_CCGR4 *((volatile unsigned int *)0x020C4078)
#define CCM_CCGR5 *((volatile unsigned int *)0x020C407C)
#define CCM_CCGR6 *((volatile unsigned int *)0x020C4080)
方式 2:結構體封裝(優化訪問)

按寄存器地址偏移順序定義結構體,直接映射到基地址:

// GPIO寄存器結構體(對應I.MX6ULL GPIO模塊寄存器偏移)
struct GPIO_t {volatile unsigned int DR;        // 數據寄存器(0x00)volatile unsigned int GDIR;      // 方向寄存器(0x04)volatile unsigned int PSR;       // 狀態寄存器(0x08)volatile unsigned int ICR1;      // 中斷控制1(0x0C)volatile unsigned int ICR2;      // 中斷控制2(0x10)volatile unsigned int IMR;       // 中斷屏蔽(0x14)volatile unsigned int ISR;       // 中斷狀態(0x18)volatile unsigned int EDGE_SEL;  // 邊沿選擇(0x1C)
};
// 宏定義GPIO1:結構體指針指向GPIO1基地址0x0209C000
#define GPIO1 (*((struct GPIO_t *)0x0209C000))

2.2 核心功能代碼

1. 時鐘初始化(必須先使能)

I.MX6ULL 外設默認時鐘關閉,需打開對應時鐘門控CCM_CCGRx):

void clock_init(void) {// 打開所有外設時鐘(簡化操作,實際可按需使能)CCM_CCGR0 = 0xFFFFFFFF;CCM_CCGR1 = 0xFFFFFFFF;CCM_CCGR2 = 0xFFFFFFFF;CCM_CCGR3 = 0xFFFFFFFF;CCM_CCGR4 = 0xFFFFFFFF;CCM_CCGR5 = 0xFFFFFFFF;CCM_CCGR6 = 0xFFFFFFFF;
}

2. LED 初始化(引腳復用 + GPIO 配置)
void led_init(void) {// 1. 引腳復用:將GPIO1_IO03配置為GPIO功能(復用值0x05)IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x05;// 2. 引腳電氣屬性:上拉、100MHz驅動、速度等級1(0x10B0為標準配置)IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0;// 3. GPIO方向:設置GPIO1_IO03為輸出(GDIR對應位寫1)GPIO1_GDIR |= (1 << 3)
}
3. LED 控制函數

4.整體main.c

2.3? makefile 編譯圖表講解

2.4?優化 Makefile(交叉編譯)

針對 ARM 架構(I.MX6ULL)的交叉編譯腳本,支持編譯、鏈接、生成 bin 文件、下載:

makefile

# 交叉編譯器前綴(需確保環境變量已配置)
COMPLITER = arm-linux-gnueabihf-
CC = $(COMPLITER)gcc       # 編譯器
LD = $(COMPLITER)ld        # 鏈接器
OBJCOPY = $(COMPLITER)objcopy # 格式轉換(elf→bin)
OBJDUMP = $(COMPLITER)objdump # 反匯編(elf→dis)# 目標文件與最終目標
OBJS = start.o main.o      # 依賴的目標文件(start.S是啟動匯編)
TARGET = led               # 目標名稱# 生成bin文件:依賴elf,elf依賴o文件
$(TARGET).bin : $(OBJS)$(LD) -Ttext 0x87800000 $^ -o $(TARGET).elf # 鏈接到I.MX6ULL運行地址0x87800000$(OBJCOPY) -O binary -S -g $(TARGET).elf $@ #  elf轉bin(刪除調試信息)$(OBJDUMP) -D $(TARGET).elf  > $(TARGET).dis # 生成反匯編文件(調試用)# 匯編文件(.S)編譯為.o
%.o : %.S$(CC) -c $^ -o $@ -g # -g:保留調試信息# C文件(.c)編譯為.o
%.o : %.c$(CC) -c $^ -o $@ -g# 清理目標文件
clean:rm $(OBJS) $(TARGET).elf $(TARGET).bin $(TARGET).dis -f# 下載到SD卡(使用imxdownload工具)
load:./imxdownload $(TARGET).bin /dev/sdb # /dev/sdb是SD卡設備節點

三、NXP I.MX6ULL SDK 移植

3.1 SDK 使用原則

  • SDK(Software Development Kit)包含完整 IDE(需下載器 / 仿真器,成本高),實際僅使用其頭文件(標準化寄存器定義,避免硬編碼)。
  • 1.SDK文件存放位置
    路徑:IMAX6ULL/SDK/
    (1).SDK(Software development tools)移植?
    (2).完整開發工具就是一個IDE, 集代碼編寫、編譯、下載于一體的集成開發環境, 類似于keil這種工具,要是用這個需要額外購買一些設備如下載器、編程器、仿真器
    (3).所以只用它的頭文件
  • 關鍵文件:
    • cc.h?? ? ? ? ? ? ? ? ? ? ? 時鐘相關定義;
      core_ca7.h? ? ? ? ? ? ? ? ? ?ARM Cortex-A7 內核相關定義;
      fsl_common.h? ? ? ? ? ? ? ? ?通用工具函數定義;
      fsl_iomuxc.h? ? ? ? ? ? ? ? ?引l腳復用配置函數定義;
      MCIMX6Y2.h? ? ? ? ? ? ? ? ? ?I.MX6ULL 寄存器映射結構體定義

3.2 移植步驟(新建工程led_sdk

  1. 工程結構初始化

    • 拷貝舊工程的start.S(啟動匯編)、main.cMakefileled_sdk
    • 拷貝 SDK 所有頭文件到工程根目錄(或單獨文件夾)。
  2. 用 SDK 重構代碼(簡化寄存器操作)
    SDK 頭文件已封裝CCMIOMUXCGPIO為結構體,直接用->訪問:

    #include "MCIMX6Y2.h"   // 包含SDK芯片定義
    #include "fsl_iomuxc.h" // 包含引腳復用函數void clock_init(void) {// SDK已定義CCM結構體,直接訪問CCGR寄存器CCM->CCGR0 = 0xFFFFFFFF;CCM->CCGR1 = 0xFFFFFFFF;// ... 其余CCGR寄存器同上
    }void led_init(void) {// 1. SDK函數:設置引腳復用(GPIO1_IO03→GPIO功能,參數2為額外配置)IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0);// 2. SDK函數:設置引腳電氣屬性(0x10B0為標準配置)IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0x10B0);// 3. GPIO方向配置(SDK已定義GPIO1結構體)GPIO1->GDIR |= (1 << 3);
    }
    

3.3 ----led_sdk------更新程序

1、查閱手冊?

main.c

led.c

--------------------------------------------------------------

實現io復用功能配置 -- sdk fsl_iomuxc.h?

實現電氣特性配置 -- 對應sdk fsl_iomuxc.h 部分

配置方向寄存器 -- 對應sdk MCIMX6Y2.h 部分

led.h

start.S

四、BSP(板級支持包)工程管理

4.1 工程目錄結構(模塊化,易維護)

????1.project :存放必要程序
main.c start.S
?? ?2.imx6ull :存放NXP提供的i.mx6ull頭文件
cc.h ?core_ca7.h? ?fsl_common.h? fsl_iomuxc.h? MCIMX6Y2.h
?? ?3.bsp :存放硬件外設相關功能模塊
led.c led.h beep.c beep.h
?4.Makefile: 需要遍目錄

led_bsp/
├── project/          # 主程序目錄
│   ├── main.c        # 主函數(調用BSP模塊)
│   └── start.S       # 啟動匯編(初始化棧、清BSS)
├── imx6ull/          # SDK頭文件目錄
│   ├── cc.h
│   ├── core_ca7.h
│   ├── fsl_common.h
│   ├── fsl_iomuxc.h
│   └── MCIMX6Y2.h
├── bsp/              # 硬件外設模塊目錄(按外設拆分)
│   ├── led/
│   │   ├── led.c     # LED驅動實現
│   │   └── led.h     # LED驅動聲明
│   └── beep/
│       ├── beep.c    # 蜂鳴器驅動實現
│       └── beep.h    # 蜂鳴器驅動聲明
├── Makefile          # 多目錄編譯腳本(需支持遍歷bsp/)
└── imx6ull.lds       # 鏈接腳本

4.2 BEEP 蜂鳴器驅動(程序)

  • 硬件:S8550(PNP型三極管)基極高電平導通(蜂鳴器響)。
  • 引腳:假設使用GPIO1_IO04,驅動邏輯與 LED 類似。

beep.h

#ifndef __BEEP_H
#define __BEEP_H#include "MCIMX6Y2.h"void beep_init(void);  // 蜂鳴器初始化
void beep_on(void);    // 蜂鳴器響
void beep_off(void);   // 蜂鳴器停#endif

beep.c

#include "beep.h"
#include "fsl_iomuxc.h"void beep_init(void) {// 1. 引腳復用:GPIO1_IO04→GPIO功能IOMUXC_SetPinMux(IOMUXC_GPIO1_IO04_GPIO1_IO04, 0);// 2. 引腳電氣屬性配置IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO04_GPIO1_IO04, 0x10B0);// 3. GPIO方向:輸出(默認熄滅,先拉低)GPIO1->GDIR |= (1 << 4);GPIO1->DR &= ~(1 << 4);
}void beep_on(void) {GPIO1->DR |= (1 << 4); // 基極高電平→PNP導通→蜂鳴器響
}void beep_off(void) {GPIO1->DR &= ~(1 << 4); // 基極低電平→PNP截止→蜂鳴器停
}

main.c

makefile 第一次改動

makefile 第二次改動

五、鏈接腳本(imx6ull.lds)

5.1 作用

  • 告訴鏈接器:代碼段、數據段、BSS 段的存放地址和順序(為 I.MX6ULL 啟動做準備)。
  • 關鍵:start.S(啟動代碼)需放在最前面,且需初始化BSS段(未初始化全局變量清 0)。
  • 1.鏈接腳本: imx6ull.lds
  • ?2.鏈接主要在鏈接階段,為連接器提供藍圖;
  • ?3.啟動代碼需要在進入C語言第一條指令前,將.bss COMMON段初始化清0

5.2 內存段總結----------鏈接腳本知識點

5.3?腳本內容

SECTIONS
{. = 0x87800000;  // 程序運行起始地址(I.MX6ULL DDR地址)// 代碼段(.text):先放start.o(啟動匯編),再放其他代碼.text :{obj/start.o   // 啟動代碼優先(需確保編譯時生成到obj目錄)*(.*)         // 其他所有.text段(C代碼、SDK函數等)} // 只讀數據段(.rodata):對齊4字節.rodata ALIGN(4) : {*(.rodata*)}// 已初始化數據段(.data):對齊4字節.data ALIGN(4) : {*(.data)}// BSS段(未初始化全局變量):標記起始/結束地址,供啟動代碼清0__bss_start = .;  // BSS段起始地址.bss ALIGN(4) : {*(.bss) *(COMMON)} // 包含BSS和COMMON段__bss_end = .;    // BSS段結束地址
}

5.4?關鍵注意點

  • 啟動代碼(start.S)需添加BSS段清0邏輯:
    // 清BSS段:從__bss_start到__bss_end,逐個字節寫0
    ldr r0, =__bss_start
    ldr r1, =__bss_end
    mov r2, #0
    bss_loop:cmp r0, r1bge bss_endstr r2, [r0], #4b bss_loop
    bss_end:
    

1.鏈接腳本的作用?各個段存放什么類型數據

鏈接腳本的核心作用
  • 告訴鏈接器:代碼段、數據段、BSS 段的存放地址和順序(為 I.MX6ULL 啟動做準備)。
  • 關鍵:start.S(啟動代碼)需放在最前面,且需初始化BSS段(未初始化全局變量清 0)。
  • 定義程序的加載地址(如嵌入式系統中指定程序在 RAM 中的運行地址,如 i.MX6ULL 的0x87800000);
  • 規定目標文件中各個 “段(Section)” 的排列順序和內存分配;
  • 標記特殊段(如.bss)的起始和結束地址,供啟動代碼初始化(如將.bss段清 0);
  • 確保代碼段、數據段等按正確的內存對齊方式(如 4 字節對齊)排列,避免硬件訪問錯誤。
各段的作用及存放數據類型

程序被編譯后會拆分為多個 “段”,鏈接腳本通過SECTIONS命令定義這些段的位置和內容:

段名稱作用及存放數據類型
.text代碼段,存放可執行代碼,包括:匯編指令(如start.S中的初始化代碼)、C 語言函數(如mainled_init)。
.rodata只讀數據段,存放常量數據,如:字符串常量("hello")、const修飾的全局變量(const int a = 10)。
.data初始化數據段,存放已初始化的全局變量和靜態變量,如:int g_var = 5(非const且有初始值)。
.bss未初始化數據段,存放未初始化的全局變量、或初始化為0的數據、靜態變量COMMON(用于存放未初始化的非靜態全局變量,如未初始化的大數組int buf[100])。
特點:程序加載時不占用磁盤空間,運行時需通過啟動代碼清 0(避免隨機值影響)。
__bss_start/__bss_end不是實際的段,而是鏈接腳本定義的標記符號,分別表示.bss段的起始和結束地址,供啟動代碼遍歷清 0。

2.編譯過程需要哪些工具,分別什么作用?

從源代碼(.c.S)到可執行程序,需經過預處理→編譯→匯編→鏈接→格式轉換5 個階段,對應工具及作用如下:

1. 預處理工具:gcc -E(預處理器)
  • 作用:處理源代碼中的預處理指令(以#開頭),生成純 C 代碼(.i文件)。
  • 具體操作
    • 展開#include頭文件(如將#include "led.h"替換為頭文件內容);
    • 替換#define宏定義(如將LED_PIN替換為實際值);
    • 刪除注釋、處理條件編譯(#if/#else/#endif)。
  • 示例arm-linux-gnueabihf-gcc -E main.c -o main.i
2. 編譯工具:gcc -S(編譯器)
  • 作用:將預處理后的.i文件(純 C 代碼)轉換為匯編代碼(.s文件)。
  • 核心功能:進行語法檢查、語義分析、代碼優化(如循環展開),最終生成對應架構的匯編指令(如 ARM 架構的ldrstr指令)。
  • 示例arm-linux-gnueabihf-gcc -S main.i -o main.s
3. 匯編工具:gcc -c?或?as(匯編器)
  • 作用:將匯編代碼(.s)轉換為機器碼(二進制目標文件,.o)。
  • 特點.o文件是 “relocatable(可重定位)” 的,即代碼中的地址是相對地址(需后續鏈接器處理)。
  • 示例arm-linux-gnueabihf-gcc -c main.s -o main.o?或?arm-linux-gnueabihf-as main.s -o main.o
4. 鏈接工具:ld(鏈接器)
  • 作用:將多個.o目標文件(如start.omain.oled.o)合并為一個可執行文件(.elf)。
  • 核心操作
    • 解析符號引用(如main函數調用led_init時,找到led_init.text段的實際地址);
    • 按鏈接腳本(如imx6ull.lds)分配各段的內存地址(將相對地址轉換為絕對地址);
    • 處理段的對齊和拼接。
  • 示例arm-linux-gnueabihf-ld -T imx6ull.lds start.o main.o -o led.elf
5. 格式轉換工具:objcopy
  • 作用:將鏈接生成的.elf文件(包含符號表、調試信息等)轉換為純二進制文件(.bin),適用于嵌入式系統加載。
  • 特點.bin文件僅保留可執行代碼和數據,去除調試信息,體積更小,可直接被 CPU 執行。
  • 示例arm-linux-gnueabihf-objcopy -O binary led.elf led.bin
6. 輔助工具:objdump(反匯編器)
  • 作用:將.elf文件反匯編為匯編代碼(.dis),用于調試(如查看 C 代碼對應的匯編指令、定位錯誤地址)。
  • 示例arm-linux-gnueabihf-objdump -D led.elf > led.dis

總結

  • 鏈接腳本是內存布局的 “規劃圖”,決定各段在內存中的位置和內容;
  • 編譯過程是 “源代碼→機器碼” 的轉換鏈,每個工具負責一個階段,最終生成可在目標硬件上運行的二進制文件。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/96634.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/96634.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/96634.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vue中使用keep-alive實現頁面前進刷新、后退緩存的完整方案

Vue中使用keep-alive實現頁面前進刷新、后退緩存的完整方案 在Vue單頁應用中&#xff0c;路由切換時組件默認會經歷完整的銷毀-重建流程&#xff0c;這會導致兩個典型問題&#xff1a;從搜索頁跳轉到列表頁需要重新加載數據&#xff0c;而從詳情頁返回列表頁又希望保留滾動位置…

Visual Studio Code 安裝與更新故障排除:從“拒絕訪問”到成功恢復

Visual Studio Code 安裝與更新故障排除&#xff1a;從“拒絕訪問”到成功恢復的實踐分析 摘要&#xff1a; 本文旨在探討 Visual Studio Code (VS Code) 在安裝與更新過程中常見的故障&#xff0c;特別是涉及“拒絕訪問”錯誤、文件缺失以及快捷方式和任務欄圖標異常等問題。…

簡單UDP網絡程序

目錄 UDP網絡程序服務端 封裝 UdpSocket 服務端創建套接字 服務端綁定 運行服務器 UDP網絡程序客戶端 客戶端創建套接字 客戶端綁定 運行客戶端 通過上篇文章的學習&#xff0c;我們已經對網絡套接字有了一定的了解。在本篇文章中&#xff0c;我們將基于之前掌握的知識…

如何解決 pip install 安裝報錯 ModuleNotFoundError: No module named ‘requests’ 問題

Python系列Bug修復PyCharm控制臺pip install報錯&#xff1a;如何解決 pip install 安裝報錯 ModuleNotFoundError: No module named ‘requests’ 問題 摘要 在日常Python開發過程中&#xff0c;pip install 是我們最常用的依賴安裝命令之一。然而很多開發者在 PyCharm 控制臺…

解釋 ICT, Web2.0, Web3.0 這些術語的中文含義

要理解“ICT Web2.0”術語的中文含義&#xff0c;需先拆解為 ICT 和 Web2.0 兩個核心概念分別解析&#xff0c;再結合二者的關聯明確整體指向&#xff1a; 1. 核心術語拆解&#xff1a;中文含義與核心定義 &#xff08;1&#xff09;ICT&#xff1a;信息與通信技術 中文全稱&am…

IDEA版本控制管理之使用Gitee

使用Gitee如果之前沒用過Gitee&#xff0c;那么IDEA中應該長這樣&#xff08;第一次使用&#xff09;如果之前使用過Gitee&#xff0c;那么IDEA中應該長這樣這種情況&#xff0c;可以先退出Gitee&#xff0c;再拉取Gitee&#xff0c;退出Gitee方法見文章底部好&#xff0c;那么…

NLP(自然語言處理, Natural Language Processing)

讓計算機能夠理解、解釋、操縱和生成人類語言&#xff0c;從而執行有價值的任務。 關注社區&#xff1a;Hugging Face、Papers With Code、GitHub 是現代NLP學習不可或缺的資源。許多最新模型和代碼都在這里開源。 ①、安裝庫 pip install numpy pandas matplotlib nltk scikit…

后端json數據反序列化枚舉類型不匹配的錯誤

后端json數據反序列化枚舉類型不匹配的錯誤后端返回的json格式在前端反序列化報錯System.Text.Json.JsonException:“The JSON value could not be converted to TodoReminderApp.Models.Priorityen. Path: $.Data.Items.$values[0].Priority | LineNumber: 0 | BytePositionIn…

市面上主流接口測試工具對比

公司計劃系統的開展接口自動化測試&#xff0c;需要我這邊調研一下主流的接口測試框架給后端測試&#xff08;主要測試接口&#xff09;的同事介紹一下每個框架的特定和使用方式。后端同事根據他們接口的特點提出一下需求&#xff0c;看哪個框架更適合我們。 2025最新Jmeter接口…

2025.2.4 更新 AI繪畫秋葉aaaki整合包 Stable Diffusion整合包v4.10 +ComfyUI 整合包下載地址

2025.2.4 更新 AI繪畫秋葉aaaki整合包 Stable Diffusion整合包v4.10 ComfyUI 整合包下載地址Stable Diffusion整合包【下載鏈接】ComfyUI整合包【下載鏈接】【報錯解決】Stable Diffusion整合包 【下載鏈接】 下載地址 https://uwtxfkm78ne.feishu.cn/wiki/GHgVwA2LPiE9x2kj4W…

Nginx優化與 SSL/TLS配置

1、隱藏版本號可以使用Fiddler工具抓取數據包&#xff0c;查看Nginx版本&#xff0c;也可以在CentOS中使用命令curl -I http://192.168.10.23 顯示響應報文首部信息。方法一&#xff1a;方法一&#xff1a;修改配置文件方式 vim /usr/local/nginx/conf/nginx.conf http {includ…

JavaWeb05

一、Listener監聽器1、簡介Listener是Servlet規范中的一員在Servlet中&#xff0c;所有的監聽器接口都是以Listener結尾監聽器實際上是Servlet規范留給JavaWeb程序員的一些特殊時機當在某些時機需要執行一段Java代碼時&#xff0c;可以用對應的監聽器2、常用的監聽器接口&#…

科普:在Windows個人電腦上使用Docker的極簡指南

在Windows個人電腦上使用Docker的極簡指南&#xff1a; 1. 快速安裝 下載安裝包&#xff08;若進不了官網&#xff0c;則可能要科學上網&#xff09; 訪問Docker Desktop官方下載頁 訪問Docker官網 選擇Windows及&#xff08;AMD64 也稱為 x86-64&#xff0c;是目前主流 PC的…

【開題答辯全過程】以 “居逸”民宿預訂微信小程序為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

LeetCode 2565.最少得分子序列

給你兩個字符串 s 和 t 。 你可以從字符串 t 中刪除任意數目的字符。 如果沒有從字符串 t 中刪除字符&#xff0c;那么得分為 0 &#xff0c;否則&#xff1a; 令 left 為刪除字符中的最小下標。 令 right 為刪除字符中的最大下標。 字符串的得分為 right - left 1 。 請你返回…

【文獻筆記】PointWeb

參考筆記: https://blog.csdn.net/m0_69412369/article/details/143106494 https://www.cnblogs.com/A-FM/p/PointWeb.html 注:本文的大部分內容是轉載而來 CVPR 2019:PointWeb: Enhancing Local Neighborhood Features for Point Cloud Processing 論文:https://ieeex…

用工招聘小程序:功能版塊與前端設計解析

在當下就業市場日益活躍的背景下&#xff0c;用工招聘小程序應運而生&#xff0c;它以高效、便捷的特點&#xff0c;為求職者與企業搭建起一座溝通的橋梁。本文將深入分析這類小程序的核心功能版塊及其前端設計&#xff0c;探討其如何優化招聘流程&#xff0c;提升用戶體驗。用…

uTools 輕工具 簡潔又方便

uTools 是一款跨平臺輕工具平臺&#xff0c;通過插件化設計提供高效工作方式&#xff0c;支持 Windows、MacOS、Linux 系統。 ? 核心功能 ?超級搜索框?&#xff1a;支持快捷鍵&#xff08;默認 AltSpace&#xff09;呼出&#xff0c;可搜索文件、網頁、應用等。 ??本地文…

圖技術重塑金融未來:悅數圖數據庫如何驅動行業創新與風控變革

隨著大數據的廣泛應用和云計算的快速發展&#xff0c;金融行業的數據已經從“大”轉向了“海”&#xff0c;從而對傳統的數據處理、分析、挖掘等的方法和工具提出了更高的要求&#xff0c;也為金融領域的數據的海量的關聯分析、實時的風控和復雜的決策支持等帶來了一系列的挑戰…

openEuler 24.03 (LTS-SP2)簡單KVM安裝+橋接模式

華為文檔創建虛擬機步驟 配置bios支持虛擬化 2、檢查系統是否支持虛擬化 3、安裝虛擬化相關組件,并啟動 yum install -y qemu virt-install virt-manager libvirt-daemon-qemu edk2-aarch64.noarch virt-viewer systemctl start libvirtd systemctl enable libvirtd4、創建…