OpenHarmony平臺驅動開發(十五),SDIO

OpenHarmony平臺驅動開發(十五)


SDIO

概述

功能簡介

SDIO(Secure Digital Input and Output)由SD卡發展而來,與SD卡統稱為MMC(MultiMediaCard),二者使用相同的通信協議。SDIO接口兼容以前的SD卡,并且可以連接支持SDIO接口的其他設備。

運作機制

在HDF框架中,SDIO的接口適配模式采用獨立服務模式(如圖1)。在這種模式下,每一個設備對象會獨立發布一個設備服務來處理外部訪問,設備管理器收到API的訪問請求之后,通過提取該請求的參數,達到調用實際設備對象的相應內部方法的目的。獨立服務模式可以直接借助HDFDeviceManager的服務管理能力,但需要為每個設備單獨配置設備節點,若設備過多可能增加內存占用。

獨立服務模式下,核心層不會統一發布一個服務供上層使用,因此這種模式下驅動要為每個控制器發布一個服務,具體表現為:

  • 驅動適配者需要實現HdfDriverEntry的Bind鉤子函數以綁定服務。

  • device_info.hcs文件中deviceNode的policy字段為1或2,不能為0。

SDIO模塊各分層作用:

  • 接口層提供打開SDIO設備、設置塊的大小、讀取數據、寫數據、設置公共信息、獲取公共信息、刷新數據、獨占HOST、釋放Host、使能SDIO功能設備、去使能SDIO功能設備、申請中斷、釋放中斷關閉SDIO設備的接口。

  • 核心層主要提供SDIO控制器的添加、移除及管理的能力,通過鉤子函數與適配層交互。

  • 適配層主要是將鉤子函數的功能實例化,實現具體的功能。

圖 1?SDIO獨立服務模式結構圖

SDIO獨立服務模式結構圖

約束與限制

SDIO模塊API當前僅支持內核態調用。

開發指導

場景介紹

SDIO的應用比較廣泛,目前,有許多手機都支持SDIO功能,并且很多SDIO外設也被開發出來,使得手機外接外設更加容易。常見的SDIO外設有WLAN、GPS、CAMERA、藍牙等。當驅動開發者需要將SDIO設備適配到OpenHarmony時,需要進行SDIO驅動適配,下文將介紹如何進行SDIO驅動適配。

接口說明

為了保證上層在調用SDIO接口時能夠正確的操作硬件,核心層在//drivers/hdf_core/framework/model/storage/include/mmc/mmc_sdio.h中定義了以下鉤子函數。驅動適配者需要在適配層實現這些函數的具體功能,并與這些鉤子函數掛接,從而完成接口層與核心層的交互。

SdioDeviceOps定義:

struct SdioDeviceOps {int32_t (*incrAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);int32_t (*incrAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);int32_t (*fixedAddrReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);int32_t (*fixedAddrWriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size, uint32_t scatterLen);int32_t (*func0ReadBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);int32_t (*func0WriteBytes)(struct SdioDevice *dev, uint8_t *data, uint32_t addr, uint32_t size);int32_t (*setBlockSize)(struct SdioDevice *dev, uint32_t blockSize);int32_t (*getCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);int32_t (*setCommonInfo)(struct SdioDevice *dev, SdioCommonInfo *info, uint32_t infoType);int32_t (*flushData)(struct SdioDevice *dev);int32_t (*enableFunc)(struct SdioDevice *dev);int32_t (*disableFunc)(struct SdioDevice *dev);int32_t (*claimIrq)(struct SdioDevice *dev, SdioIrqHandler *irqHandler);int32_t (*releaseIrq)(struct SdioDevice *dev);int32_t (*findFunc)(struct SdioDevice *dev, struct SdioFunctionConfig *configData);int32_t (*claimHost)(struct SdioDevice *dev);int32_t (*releaseHost)(struct SdioDevice *dev);
};

表 1?SdioDeviceOps結構體成員的鉤子函數功能說明

函數入參出參返回值功能
incrAddrReadBytesdev:結構體指針,SDIO設備控制器
addr:uint32_t類型,地址值
size:uint32_t類型,大小
data:uint8_t類型指針,傳出值HDF_STATUS相關狀態從指定的SDIO地址增量讀取給定長度的數據
incrAddrWriteBytesdev:結構體指針,SDIO設備控制器
data:uint8_t類型指針,傳入值
addr:uint32_t類型,地址值
size:uint32_t類型,大小
HDF_STATUS相關狀態將給定長度的數據增量寫入指定的SDIO地址
fixedAddrReadBytesdev:結構體指針,SDIO設備控制器
addr:uint32_t類型,地址值
size:uint32_t類型,大小
scatterLen:uint32_t類型,數據長度
data:uint8_t類型指針,傳出值HDF_STATUS相關狀態從固定SDIO地址讀取給定長度的數據。
fixedAddrWriteBytesdev:結構體指針,SDIO設備控制器
data:uint8_t類型指針,傳入值
addr:uint32_t類型,地址值
size:uint32_t類型,大小
scatterLen:uint32_t類型,數據長度
HDF_STATUS相關狀態將給定長度的數據寫入固定SDIO地址
func0ReadBytesdev:結構體指針,SDIO設備控制器
addr:uint32_t類型,地址值
size:uint32_t類型,大小
data:uint8_t類型指針,傳出值HDF_STATUS相關狀態從SDIO函數0的地址空間讀取給定長度的數據。
func0WriteBytesdev:結構體指針,SDIO設備控制器
data:uint8_t類型指針,傳入值
addr:uint32_t類型,地址值
size:uint32_t類型,大小
HDF_STATUS相關狀態將給定長度的數據寫入SDIO函數0的地址空間。
setBlockSizedev:結構體指針,SDIO設備控制器
blockSize:uint32_t類型,Block大小
HDF_STATUS相關狀態設置block大小
getCommonInfodev:聯合體指針,SDIO設備控制器
infoType:uint32_t類型,info類型
info:結構體指針,傳出SdioFuncInfo信息HDF_STATUS相關狀態獲取CommonInfo,說明見下
setCommonInfodev:結構體指針,SDIO設備控制器
info:聯合體指針,SdioFuncInfo信息傳入
infoType:uint32_t類型,info類型
HDF_STATUS相關狀態設置CommonInfo,說明見下
flushDatadev:結構體指針,SDIO設備控制器HDF_STATUS相關狀態當SDIO需要重新初始化或發生意外錯誤時調用的函數
enableFuncdev:結構體指針,SDIO設備控制器HDF_STATUS相關狀態使能SDIO設備
disableFuncdev:結構體指針,SDIO設備控制器HDF_STATUS相關狀態去使能SDIO設備
claimIrqdev:結構體指針,SDIO設備控制器
irqHandler:void函數指針
HDF_STATUS相關狀態注冊SDIO中斷
releaseIrqdev:結構體指針,SDIO設備控制器HDF_STATUS相關狀態釋放SDIO中斷
findFuncdev:結構體指針,SDIO設備控制器
configData:結構體指針,SDIO函數關鍵信息
HDF_STATUS相關狀態尋找匹配的funcNum
claimHostdev:結構體指針,SDIO設備控制器HDF_STATUS相關狀態獨占HOST
releaseHostdev:結構體指針,SDIO設備控制器HDF_STATUS相關狀態釋放HOST

icon-note.gif

?說明:
CommonInfo包括maxBlockNum(單個request中最大block數)、maxBlockSize(單個block最大字節數)、maxRequestSize(單個Request最大字節數)、enTimeout(最大超時時間,毫秒)、funcNum(功能編號1~7)、irqCap(IRQ capabilities)、(void *)data。

開發步驟

SDIO模塊適配包含以下四個步驟:

  1. 實例化驅動入口

    • 實例化HdfDriverEntry結構體成員。

    • 調用HDF_INIT將HdfDriverEntry實例化對象注冊到HDF框架中。

  2. 配置屬性文件

    • 在device_info.hcs文件中添加deviceNode描述。

    • 【可選】添加sdio_config.hcs器件屬性文件。

  3. 實例化SDIO控制器對象

    • 初始化SdioDevice成員。

    • 實例化SdioDevice成員SdioDeviceOps。

      icon-note.gif

      ?說明:
      實例化SdioDevice成員SdioDeviceOps,其定義和成員說明見接口說明。

  4. 驅動調試

    【可選】針對新增驅動程序,建議驗證驅動基本功能,例如SDIO控制狀態,中斷響應情況,讀寫數據是否成功等。

開發實例

下方將以//drivers/hdf_core/adapter/khdf/linux/model/storage/sdio_adapter.c為示例,展示需要驅動適配者提供哪些內容來完整實現設備功能。

  1. 實例化驅動入口

    驅動入口必須為HdfDriverEntry(在hdf_device_desc.h中定義)類型的全局變量,且moduleName要和device_info.hcs中保持一致。HDF框架會將所有加載的驅動的HdfDriverEntry對象首地址匯總,形成一個類似數組的段地址空間,方便上層調用。

    一般在加載驅動時HDF會先調用Bind函數,再調用Init函數加載該驅動。當Init調用異常時,HDF框架會調用Release釋放驅動資源并退出。

    SDIO 驅動入口參考:

    struct HdfDriverEntry g_sdioDriverEntry = {.moduleVersion = 1,.Bind = Hi35xxLinuxSdioBind,         // 見Bind開發參考.Init = Hi35xxLinuxSdioInit,         // 見Init開發參考.Release = Hi35xxLinuxSdioRelease,   // 見Release開發參考.moduleName = "HDF_PLATFORM_SDIO",   // 【必要且與HCS文件中里面的moduleName匹配】
    };
    HDF_INIT(g_sdioDriverEntry);             // 調用HDF_INIT將驅動入口注冊到HDF框架中
    
  2. 配置屬性文件

    完成驅動入口注冊之后,下一步請在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode信息,并在sdio_config.hcs中配置器件屬性。deviceNode信息與驅動入口注冊相關,器件屬性值與核心層SdioDevice成員的默認值或限制范圍有密切關系。本例只有一個SDIO控制器,如有多個器件信息,則需要在device_info.hcs文件增加deviceNode信息,以及在sdio_config文件中增加對應的器件屬性。

    獨立服務模式的特點是device_info.hcs文件中設備節點代表著一個設備對象,如果存在多個設備對象,則按需添加,注意服務名與驅動私有數據匹配的關鍵字名稱必須唯一。其中各項參數如表2所示:

    表 2?device_info.hcs節點參數說明

    成員名
    policy驅動服務發布的策略,SDIO設備控制器具體配置為1,表示驅動對內核態發布服務
    priority驅動啟動優先級(0-200),值越大優先級越低。SDIO設備控制器具體配置為30
    permission驅動創建設備節點權限,SDIO設備控制器具體配置為0664
    moduleName驅動名稱,SDIO設備控制器固定為hi3516_mmc_driver
    serviceName驅動對外發布服務的名稱,SDIO設備控制器服務名設置為HDF_PLATFORM_MMC_2
    deviceMatchAttr驅動私有數據匹配的關鍵字,SDIO設備控制器設置為hi3516_mmc_sdio
    • device_info.hcs 配置參考:

      root {device_info {match_attr = "hdf_manager";platform :: host {hostName = "platform_host";priority = 50;device_sdio :: device {device0 :: deviceNode {policy = 1;priority = 70;permission = 0644;moduleName = "HDF_PLATFORM_SDIO";            // 【必要】用于指定驅動名稱,需要與驅動Entry中的moduleName一致。serviceName = "HDF_PLATFORM_MMC_2";          // 【必要】驅動對外發布服務的名稱,必須唯一。deviceMatchAttr = "hisilicon_hi35xx_sdio_0"; // 【必要】用于配置控制器私有數據,要與sdio_config.hcs中對應控制器保持一致。}}}}
      }
      
    • sdio_config.hcs 配置參考:

      root {platform {sdio_config {template sdio_controller {match_attr = "";hostId = 2;                             // 【必要】模式固定為2,在mmc_config.hcs有介紹。devType = 2;                            // 【必要】模式固定為2,在mmc_config.hcs有介紹。}controller_0x2dd1 :: sdio_controller {match_attr = "hisilicon_hi35xx_sdio_0"; // 【必要】需要和device_info.hcs中的deviceMatchAttr值一致。}}
      }
      

      需要注意的是,新增sdio_config.hcs配置文件后,必須在hdf.hcs文件中包含sdio_config.hcs所在路徑信息,否則配置文件無法生效。

  3. 實例化SDIO設備控制器對象

    完成屬性文件配置之后,下一步就是以核心層SdioDevice對象的初始化為核心,包括驅動適配者自定義結構體(傳遞參數和數據),實例化SdioDevice成員SdioDeviceOps(讓用戶可以通過接口來調用驅動底層函數),實現HdfDriverEntry成員函數(Bind、Init、Release)。

    • 自定義結構體參考:

      從驅動的角度看,自定義結構體是參數和數據的載體,而且sdio_config.hcs文件中的數值會被HDF讀入并通過DeviceResourceIface來初始化結構體成員,一些重要數值也會傳遞給核心層對象。

      typedef struct {uint32_t maxBlockNum;    // 單個request最大的block個數uint32_t maxBlockSize;   // 單個block最大的字節數1~2048uint32_t maxRequestSize; // 單個request最大的字節數1~2048uint32_t enTimeout;      // 最大超時時間,單位毫秒,且不能超過一秒。uint32_t funcNum;        // 函數編號1~7uint32_t irqCap;         // 中斷能力void *data;              // 私有數據
      } SdioFuncInfo;// SdioDevice是核心層控制器結構體,其中的成員在Bind函數中會被賦值。
      struct SdioDevice {struct SdDevice sd;struct SdioDeviceOps *sdioOps;struct SdioRegister sdioReg;uint32_t functions;struct SdioFunction *sdioFunc[SDIO_MAX_FUNCTION_NUMBER];struct SdioFunction *curFunction;struct OsalThread thread; // 中斷線程struct OsalSem sem;bool irqPending;bool threadRunning;
      };
      
    • SdioDevice成員鉤子函數結構體SdioDeviceOps的實例化。

      static struct SdioDeviceOps g_sdioDeviceOps = {.incrAddrReadBytes = Hi35xxLinuxSdioIncrAddrReadBytes,.incrAddrWriteBytes = Hi35xxLinuxSdioIncrAddrWriteBytes,.fixedAddrReadBytes = Hi35xxLinuxSdioFixedAddrReadBytes,.fixedAddrWriteBytes = Hi35xxLinuxSdioFixedAddrWriteBytes,.func0ReadBytes = Hi35xxLinuxSdioFunc0ReadBytes,.func0WriteBytes = Hi35xxLinuxSdioFunc0WriteBytes,.setBlockSize = Hi35xxLinuxSdioSetBlockSize,.getCommonInfo = Hi35xxLinuxSdioGetCommonInfo,.setCommonInfo = Hi35xxLinuxSdioSetCommonInfo,.flushData = Hi35xxLinuxSdioFlushData,.enableFunc = Hi35xxLinuxSdioEnableFunc,.disableFunc = Hi35xxLinuxSdioDisableFunc,.claimIrq = Hi35xxLinuxSdioClaimIrq,.releaseIrq = Hi35xxLinuxSdioReleaseIrq,.findFunc = Hi35xxLinuxSdioFindFunc,.claimHost = Hi35xxLinuxSdioClaimHost,.releaseHost = Hi35xxLinuxSdioReleaseHost,
      };
      
    • Bind函數開發參考。

      入參:

      HdfDeviceObject是整個驅動對外提供的接口參數,具備HCS配置文件的信息。

      返回值:

      HDF_STATUS相關狀態 (表3為部分展示,如需使用其他狀態,可參考//drivers/hdf_core/interfaces/inner_api/utils/hdf_base.h中HDF_STATUS的定義)。

      表 3?HDF_STATUS相關狀態說明

      狀態(值)問題描述
      HDF_ERR_INVALID_OBJECT控制器對象非法
      HDF_ERR_MALLOC_FAIL內存分配失敗
      HDF_ERR_IOI/O?錯誤
      HDF_SUCCESS初始化成功
      HDF_FAILURE初始化失敗

      函數說明:

      初始化自定義結構體對象,初始化SdioCntlr成員,調用核心層SdioCntlrAdd函數,以及其他驅動適配者自定義初始化操作。

      static int32_t Hi35xxLinuxSdioBind(struct HdfDeviceObject *obj)
      {struct MmcCntlr *cntlr = NULL;int32_t ret;......cntlr = (struct MmcCntlr *)OsalMemCalloc(sizeof(struct MmcCntlr));// 分配內存......cntlr->ops = &g_sdioCntlrOps;                                     // 【必要】struct MmcCntlrOps g_sdioCntlrOps={// .rescanSdioDev = Hi35xxLinuxSdioRescan,};cntlr->hdfDevObj = obj;                                           // 【必要】使HdfDeviceObject與MmcCntlr可以相互轉化的前提obj->service = &cntlr->service;                                   // 【必要】使HdfDeviceObject與MmcCntlr可以相互轉化的前提ret = Hi35xxLinuxSdioCntlrParse(cntlr, obj);                      // 【必要】初始化cntlr的index、devType,失敗則goto _ERR。......ret = MmcCntlrAdd(cntlr);                                         // 【必要】調用核心層mmc_core.c的函數,失敗則goto _ERR。......ret = MmcCntlrAllocDev(cntlr, (enum MmcDevType)cntlr->devType);   // 【必要】調用核心層mmc_core.c的函數,失敗則goto _ERR。......MmcDeviceAddOps(cntlr->curDev, &g_sdioDeviceOps);                 // 【必要】調用核心層mmc_core.c的函數,鉤子函數掛載。HDF_LOGD("Hi35xxLinuxSdioBind: Success!");return HDF_SUCCESS;_ERR:Hi35xxLinuxSdioDeleteCntlr(cntlr);HDF_LOGE("Hi35xxLinuxSdioBind: Fail!");return HDF_FAILURE;
      }
      
    • Init函數開發參考。

      入參:

      HdfDeviceObject是整個驅動對外提供的接口參數,具備HCS配置文件的信息。

      返回值:

      HDF_STATUS相關狀態。

      函數說明:

      無操作,可根據驅動適配者需要添加。

      static int32_t Hi35xxLinuxSdioInit(struct HdfDeviceObject *obj)
      {(void)obj;        // 無操作,可根據驅動適配者的需要進行添加HDF_LOGD("Hi35xxLinuxSdioInit: Success!");return HDF_SUCCESS;
      }
      
    • Release函數開發參考。

      入參:

      HdfDeviceObject是整個驅動對外提供的接口參數,具備HCS配置文件的信息。

      返回值:

      無。

      函數說明:

      釋放內存和刪除控制器,該函數需要在驅動入口結構體中賦值給Release接口,當HDF框架調用Init函數初始化驅動失敗時,可以調用Release釋放驅動資源。

      icon-note.gif

      ?說明:
      所有強制轉換獲取相應對象的操作前提是在Bind函數中具備對應賦值的操作。

      static void Hi35xxLinuxSdioRelease(struct HdfDeviceObject *obj)
      {if (obj == NULL) {return;}Hi35xxLinuxSdioDeleteCntlr((struct MmcCntlr *)obj->service); // 【必要】自定義的內存釋放函數,這里有HdfDeviceObject到MmcCntlr的強制轉換
      }
      
  4. 驅動調試

    【可選】針對新增驅動程序,建議驗證驅動基本功能,例如SDIO控制狀態,中斷響應情況,讀寫數據是否成功等。

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

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

相關文章

使用FastAPI和React以及MongoDB構建全棧Web應用03 全棧開發快速入門

一、什么是全棧開發 A full-stack web application is a complete software application that encompasses both the frontend and backend components. It’s designed to interact with users through a web browser and perform actions that involve data processing and …

Coco AI 開源應用程序 - 搜索、連接、協作、您的個人 AI 搜索和助手,都在一個空間中。

一、軟件介紹 文末提供程序和源碼下載 Coco AI 是一個統一的搜索平臺,可將您的所有企業應用程序和數據(Google Workspace、Dropbox、Confluent Wiki、GitHub 等)連接到一個功能強大的搜索界面中。此存儲庫包含為桌面和移動設備構建的 Coco 應…

CSS經典布局之圣杯布局和雙飛翼布局

目標: 中間自適應,兩邊定寬,并且三欄布局在一行展示。 圣杯布局 實現方法: 通過float搭建布局margin使三列布局到一行上relative相對定位調整位置; 給外部容器添加padding,通過相對定位調整左右兩列的…

# 實時英文 OCR 文字識別:從攝像頭到 PyQt5 界面的實現

實時英文 OCR 文字識別:從攝像頭到 PyQt5 界面的實現 引言 在數字化時代,文字識別技術(OCR)在眾多領域中發揮著重要作用。無論是文檔掃描、車牌識別還是實時視頻流中的文字提取,OCR 技術都能提供高效且準確的解決方案…

<C#>log4net 的配置文件配置項詳細介紹

log4net 是一個功能強大的日志記錄工具&#xff0c;通過配置文件可以靈活地控制日志的輸出方式、格式、級別等。以下是對 log4net 配置文件常見配置項的詳細介紹&#xff1a; 根元素 <log4net> 這是 log4net 配置文件的根元素&#xff0c;所有配置項都要包含在該元素內…

編譯docker版openresty

使用alpine為基礎鏡像 # 使用Alpine作為基礎鏡像 FROM alpine:3.18# 替換為阿里云鏡像源&#xff0c;并安裝必要的依賴 RUN sed -i s|https://dl-cdn.alpinelinux.org/alpine|https://mirrors.aliyun.com/alpine|g /etc/apk/repositories && \apk add --no-cache \bui…

conda 輸出指定python環境的庫 輸出為 yaml文件

conda 輸出指定python環境的庫 輸出為 yaml文件。 有時為了項目部署&#xff0c;需要匹配之前的python環境&#xff0c;需要輸出對應的python依賴庫。 假設你的目標環境名為 myenv&#xff0c;運行以下命令&#xff1a; conda env export -n myenv > myenv_environment.ym…

[Java][Leetcode middle] 121. 買賣股票的最佳時機

暴力循環 總是以最低的價格買入&#xff0c;以最高的價格賣出: 例如第一天買入&#xff0c;去找剩下n-1天的最高價格&#xff0c;計算利潤 依次計算到n-1天買入&#xff1b; 比較上述利潤 // 運行時間超時。 o(n^2)public int maxProfit1(int[] prices) {int profit 0;for (i…

克隆虛擬機組成集群

一、克隆虛擬機 1. 準備基礎虛擬機 確保基礎虛擬機已安裝好操作系統&#xff08;如 Ubuntu&#xff09;、Java 和 Hadoop。關閉防火墻并禁用 SELinux&#xff08;如適用&#xff09;&#xff1a; bash sudo ufw disable # Ubuntu sudo systemctl disable firewalld # CentO…

記錄一次使用thinkphp使用PhpSpreadsheet擴展導出數據,解決身份證號碼等信息科學計數法問題處理

PhpSpreadsheet官網 PhpSpreadsheet安裝 composer require phpoffice/phpspreadsheet使用composer安裝時一定要下載php對應的版本&#xff0c;下載之前使用php -v檢查當前php版本 簡單使用 <?php require vendor/autoload.php;use PhpOffice\PhpSpreadsheet\Spreadshee…

前端工程化:從 Webpack 到 Vite

引言 前端工程化是現代Web開發不可或缺的一部分&#xff0c;它通過自動化流程和標準化實踐&#xff0c;提高了開發效率和代碼質量。在這個領域中&#xff0c;構建工具扮演著核心角色&#xff0c;而Webpack和Vite則是其中的兩位重要角色。本文將探討前端工程化的演進歷程&#…

Leetcode 3543. Maximum Weighted K-Edge Path

Leetcode 3543. Maximum Weighted K-Edge Path 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3543. Maximum Weighted K-Edge Path 1. 解題思路 這一題思路上就是一個遍歷的思路&#xff0c;我們只需要考察每一個節點作為起點時&#xff0c;所有長為 k k k的線段的長度&…

香橙派zero3 安卓TV12,更換桌面launcher,開機自啟動kodi

打開開發者模式&#xff0c;連擊版本號&#xff0c;基本上都是這樣。 adb連接 查找桌面包名 adb shell dumpsys activity activities | findstr mResumedActivity 禁用原桌面com.android.tv.launcher&#xff0c;已經安裝了projectivylauncher434.apk桌面。 adb shell pm …

半小時快速入門Spring AI:使用騰訊云編程助手CodeBuddy 開發簡易聊天程序

引言 隨著人工智能&#xff08;AI&#xff09;技術的飛速發展&#xff0c;越來越多的開發者開始探索如何將AI集成到自己的應用中。人工智能正在迅速改變各行各業的工作方式&#xff0c;從自動化客服到智能推薦系統&#xff0c;AI的應用幾乎無處不在。Spring AI作為一種開源框架…

【unity游戲開發——編輯器擴展】使用MenuItem自定義菜單欄拓展

免職聲明&#xff1a; 1、目前本博客分享的大部分知識產出方式是&#xff1a;學習別人知識自己實際做一遍自己的理解擴展內容自己整理、歸納、總結再分享。2、正如博客簡介所說&#xff1a;這里沒有教程&#xff0c;這里只做學習分享。所有的內容都是學習筆記&#xff0c;可以說…

數學復習筆記 7

前言 現在復習線代基礎&#xff0c;慢慢打基礎。。 轉置 方陣轉置之后行列式保持不變。我的筆記感覺主要不是整理知識點&#xff0c;主要是把我的一些理解記錄下來。這才是我自己的東西&#xff0c;那些需要記住的知識和內容記住就好了。記住轉置有四個性質&#xff0c;在講…

AIGC時代的內容安全:AI檢測技術如何應對新型風險挑戰?

在數字時代&#xff0c;互聯網內容以文本、圖像、音頻和視頻等形式呈現爆發式增長&#xff0c;深刻塑造了信息傳播的格局。然而&#xff0c;內容的快速傳播也帶來了嚴峻挑戰&#xff1a;違法信息&#xff08;如涉黃、涉政&#xff09;、虛假廣告、網絡暴力等內容不僅威脅用戶體…

PyTorch中的nn.Embedding應用詳解

PyTorch 文章目錄 PyTorch前言一、nn.Embedding的基本原理二、nn.Embedding的實際應用簡單的例子自然語言處理任務 前言 在深度學習中&#xff0c;詞嵌入&#xff08;Word Embedding&#xff09;是一種常見的技術&#xff0c;用于將離散的詞匯或符號映射到連續的向量空間。這種…

AI 檢測原創論文:技術迷思與教育本質的悖論思考

當高校將 AI 寫作檢測工具作為學術誠信的 "電子判官"&#xff0c;一場由技術理性引發的教育異化正在悄然上演。GPT-4 檢測工具將人類創作的論文誤判為 AI 生成的概率高達 23%&#xff08;斯坦福大學 2024 年研究數據&#xff09;&#xff0c;這種 "以 AI 制 AI&…

langchain4j集成QWen、Redis聊天記憶持久化

langchain4j實現聊天記憶默認是基于進程內存的方式&#xff0c;InMemoryChatMemoryStore是具體的實現了&#xff0c;是將聊天記錄到一個map中&#xff0c;如果用戶大的話&#xff0c;會造成內存溢出以及數據安全問題。位了解決這個問題 langchain4提供了ChatMemoryStore接口&am…