在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何開發(fā)與位置無關(guān)的 STM32 完整工程

MCU開發(fā)加油站 ? 來源:STM32單片機(jī) ? 作者:STM32單片機(jī) ? 2022-09-15 09:59 ? 次閱讀

1、前言

最近有客戶詢問,能否使用 STM32CubeIDE 在編譯時(shí)通過設(shè)置某個(gè)編譯選項(xiàng),讓STM32 應(yīng)用與存儲位置無關(guān)。這樣的優(yōu)勢是能使同一個(gè)固件被燒在 STM32 Flash 里的不同位置, 而在系統(tǒng) Bootloader 里只需要跳到相應(yīng)的位置就可以正常執(zhí)行固件代碼。客戶希望STM32 代碼從 Flash 里執(zhí)行,不復(fù)制到 RAM 里;客戶希望是一個(gè)完整的映像,而不僅僅是其中某個(gè)函數(shù)做到了位置無關(guān)。

2、分析

嵌入式場景下,不一定有操作系統(tǒng)。即使有操作系統(tǒng),一般也是 RTOS。一般 RTOS沒有一個(gè)通用的程序加載器。因此,存儲位置無關(guān)的需求,在這時(shí)可以說無關(guān)緊要。但是,如果客戶需要進(jìn)行在線固件更新,例如 IoT 應(yīng)用的固件升級,那么位置無關(guān)就存在價(jià)值了。位置無關(guān)之后,對于不同的軟件版本,不需要頻繁的為燒寫位置的反復(fù)改變而修改編譯鏈接腳本。也不需要在代碼里顯式的在兩個(gè) Bank 之間進(jìn)行切換。

最簡單的情況是所有的代碼都復(fù)制到內(nèi)存執(zhí)行。因?yàn)?Flash 的功能只是進(jìn)行存儲,自然對 Flash 的位置沒有任何要求。但大部分 MCU 用戶面臨的真實(shí)案例都是 Flash 比較大,例如 ,1M 字節(jié) ;RAM 比較小,例如,128K 字節(jié)。在這種情況下,代碼在 Flash 原地執(zhí)行就是一個(gè)必須的選擇。Flash 位置改變,會(huì)影響從 Bootloader 跳轉(zhuǎn)之后的固件執(zhí)行時(shí)的 PC 指針,也就是 PC指針值會(huì)發(fā)生相應(yīng)的變化。位置無關(guān)的原理,是讓應(yīng)用程序經(jīng)過編譯后所生成的映像,其中的代碼和數(shù)據(jù),都是基于相對代碼的位置進(jìn)行引用。那么,當(dāng)應(yīng)用被搬到不同位置時(shí),他們的相對位置不變,從而執(zhí)行不受影響。

代碼和數(shù)據(jù)基于絕對地址還是基于相對地址,是由編譯器所決定。以客戶要求的

STM32CubeIDE 編譯工具為例,我們可以看到在[Project]->[Properties]->[C/C++ Build]->[Settings]->[Tool Settings]->[MCU GCC Compiler]->[Miscellaneous]已經(jīng)有一項(xiàng)[Position Independent Code (-fPIC)]。

是否只要選一下-fPIC 選項(xiàng)就大功告成了呢?答案是沒有那么簡單。

f79506e8-341f-11ed-ba43-dac502259ad0.png

事實(shí)上,對于完整應(yīng)用程序工程,用戶應(yīng)該經(jīng)過這些步驟將其變成位置無關(guān):? 選擇正確的編譯器選項(xiàng)

? 去掉或者替換掉那些包含絕對位置的庫文件

? 修改代碼中的 Flash 絕對地址(這里以 STM32H7 的 CRC_Example 例程為例,

其他情況下有可能要修改更多) o 在 startup_xxx.s 匯編代碼里的 sidata

o 在 system_xxx.c 里的 SCB->VTOR 以及中斷向量表內(nèi)容

o GOT

對于完整工程,要正確的跳轉(zhuǎn)到應(yīng)用程序進(jìn)行執(zhí)行,還需要由 Bootloader 向應(yīng)用程序提供或者由應(yīng)用程序在鏈接時(shí)自身解析計(jì)算,得到以下信息:

? Flash 偏移量

? 中斷向量表的開始以及結(jié)束地址

? GOT 的開始以及結(jié)束地址

我們接下來就舉例說明這些步驟。

3、步驟

3.1. 選擇正確的編譯器選項(xiàng)

如果我們不使用任何編譯選項(xiàng),編出來的代碼會(huì)怎么樣?我們可以通過.list 文件進(jìn)行查看。.list 文件在 STM32 例程中默認(rèn)生成,如果沒有請勾選如下選項(xiàng), 在 [Project]->[Properties]->[C/C++ Build]->[Settings]->[Tool Settings]->[MCU Post Build outputs]->[Generate list file],可參考下圖。

f7a7d3a4-341f-11ed-ba43-dac502259ad0.png

f7bb0e42-341f-11ed-ba43-dac502259ad0.png

f7d2fee4-341f-11ed-ba43-dac502259ad0.png

我們看到代碼中直接使用了變量的絕對地址,例如 0x2000 0028。我們不要被 literal pool 文字池的使用所迷惑,那個(gè)基于 PC 的操作只是為了取變量的絕對地址,例如, 0x2000 0028,并沒有將絕對地址變成相對地址。

當(dāng)然大家說這里是 RAM 地址,沒有關(guān)系。我們選擇這個(gè)函數(shù)來說明,是因?yàn)槲恢脽o關(guān)的編譯器選項(xiàng)是不區(qū)分 RAM 還是 Flash 里的變量,而這個(gè)函數(shù)最簡單容易理解。如果我們查看另外一個(gè)復(fù)雜一點(diǎn)的函數(shù),例如,HAL_RCC_ClockConfig,我們可以看到以下對Flash 里變量的直接使用。這就不妙了,因?yàn)橐坏└淖兞?Flash 下載的位置,在絕對地址處就取不出變量的真實(shí)內(nèi)容了。

f7e3c436-341f-11ed-ba43-dac502259ad0.png

我們沒有辦法一個(gè)一個(gè)查找修改所有的變量。當(dāng)然這里的變量是指全局變量。如果要修改,我們希望編譯器能把他們集中在一起。對于此,編譯器提供了多個(gè)編譯選項(xiàng)。例如,PIC 是位置無關(guān)代碼, PIE 是位置無關(guān)執(zhí)行。PIC 和 PIE 這兩者類似,但是存在一個(gè)顯著的差異是 PIE 會(huì)對部分全局變量優(yōu)化。我們可以觀察到用兩種不同編譯選項(xiàng)的效果。

f7f47cf4-341f-11ed-ba43-dac502259ad0.png

其中 80004C0 地址處包含的是 GOT 自身的偏移量,存在 r2 里,要在兩次取全局變量 uwTickFreq 和 uwTick 時(shí)引用。GCC 編譯器引入 GOT 全局偏移量表來解決全局變量的絕對地址的問題。在之前對絕對地址的直接使用,現(xiàn)在被轉(zhuǎn)化成先取得 GOT 入口相對于 PC 的偏移,再獲得實(shí)際變量相對于 GOT 入口的偏移,從而得到實(shí)際變量的地址。計(jì)算公式如下:

實(shí)際變量的絕對地址=PC + GOT 相對于 PC 的偏移 + 變量地址相對于 GOT 的偏移

GOT 只有一個(gè),如果代碼放在不同的位置,代碼自身就可以根據(jù) Bootloader 傳遞過來的信息,或者自行計(jì)算來對 GOT 進(jìn)行更新。這樣變量的地址就和新的 Flash 偏移相匹配。

f807ca2a-341f-11ed-ba43-dac502259ad0.png

這里可以看到 80004c0 對應(yīng)的 uwTick(可以從 str 指令結(jié)合 C 語言源代碼快速知道它對應(yīng)于 uwTick)不再使用 GOT 偏移,而是相對于 PC 的偏移(與前文相比,多了一條指令 “add r3,pc”)。換句話說,PIE 對局部的全局變量做了優(yōu)化。這個(gè)優(yōu)化顯然不是我們所需要的。因?yàn)槿绱艘詠恚琑AM 變量的地址就會(huì)隨著 PC 的不同而不同。而我們則希望所有對RAM 的用法不發(fā)生變化。

為了能夠修改 GOT 內(nèi)容,我們選擇將 GOT 最終存放在 RAM 中,導(dǎo)致代碼中對 GOT的尋址也是使用了相對于 PC 的偏移。而因?yàn)?RAM 有限,或者因?yàn)闆]有虛擬內(nèi)存的緣故,我們不希望 RAM 的用法有所不同,否則,可能代價(jià)很大。這時(shí),一旦 Flash 代碼位置發(fā)生變化引起 PC 指針變化,GOT 就無法找到。因此,即使我們不使用 PIE,PIC 也沒有辦法單獨(dú)使用。為了確保沒有任何存放在 RAM 里的變量的位置是相對于 PC 的偏移。我們應(yīng)該使用如下所有編譯選項(xiàng),single-pic-base 讓系統(tǒng)只使用一個(gè) PIC 基址,就是下文反匯編中看到

r9;no-pic-data-is-text-relative 則讓編譯器不要讓任何變量相對于 PC 尋址。

f81762be-341f-11ed-ba43-dac502259ad0.png

f8276736-341f-11ed-ba43-dac502259ad0.png

這樣實(shí)際變量的絕對地址,就變成實(shí)際變量的絕對地址=PIC 基址 + GOT 相對于 PIC 基址的偏移 + 變量地址相對于 GOT的偏移使用以上編譯選項(xiàng),這樣我們看到 HAL_IncTick 就如下所示:

f83fb610-341f-11ed-ba43-dac502259ad0.png

這樣所有在 RAM 里的全局變量都是相對于 GOT 的偏移。注意,這個(gè)時(shí)候你編譯出來的代碼現(xiàn)在沒有辦法進(jìn)行測試,盡管你只是改了編譯選項(xiàng)。這是因?yàn)?PIC 的基址需要你通過寄存器 r9 顯式指定。在本例中,我們在鏈接腳本里如下定義 GOT 的位置:

f8542d3e-341f-11ed-ba43-dac502259ad0.png

因此,我們可以很容易的從.map 文件中獲得 GOT_START 的 RAM 地址,0x2000 0000,它就是 PIC 的基址。如果想測試編譯器選項(xiàng)是否如我們所期望,我們可以在Reset_Handler 開始部分加上如下語句(參考后文內(nèi)存布局的代碼):

f86b1986-341f-11ed-ba43-dac502259ad0.png

經(jīng)過測試,我們可以確信,編譯器選項(xiàng)的改動(dòng)對我們最終執(zhí)行結(jié)果沒有影響。

值得注意的是,STM32 用戶的代碼,例如 RTOS 的移植, 也可能使用寄存器 r9。在這種情況,用戶應(yīng)當(dāng)解決沖突。一般情況寄存器 r9 對應(yīng)用程序并不是必要的。

3.2. 去掉或者替換掉那些包含絕對位置的庫文件

我們要將位置無關(guān)的庫去掉或者替換掉。在 STM32 參考代碼里,我們需要

startup_xxx.s 里 C 庫調(diào)用去掉。示例如下:

f883fc62-341f-11ed-ba43-dac502259ad0.png

3.3. 修改 Flash 絕對地址

3.3.1. 內(nèi)存布局

如果要對代碼中的 Flash 絕對地址進(jìn)行修改,我們需要知道存放 Flash 絕對地址的 RAM起始和結(jié)束地址,以及需要增加或減少的 Flash 偏移量。存放 Flash 絕對地址的 RAM 起始和結(jié)束地址,在編譯時(shí)可以讓應(yīng)用代碼本身借助自身鏈接腳本在鏈接時(shí)導(dǎo)出的變量得到,然后由應(yīng)用程序在運(yùn)行時(shí)存放在 RAM 中的固定位置;也可以在編譯后從.map 文件或使用工具解析 elf 文件獲得,然后作為應(yīng)用程序一部分的元信息,例如,給應(yīng)用程序加個(gè)頭部存放元信息,由 Bootloader 下載并解析,將其放入到 RAM 固定位置。

我們規(guī)劃在一段 RAM 里按如下順序存放如下元信息,它可以是應(yīng)用程序本身在最初階段自我存放在這里,也可以簡單的由 Bootloader 解析元信息后,跳轉(zhuǎn)到應(yīng)用程序之前就存放在這里。

f893b15c-341f-11ed-ba43-dac502259ad0.png

我們在前文已經(jīng)在鏈接腳本中定義了 GOT_START 和 GOT_END,我們還需要在鏈接腳本中定義 VT_START 和 VT_END。如下圖所示:

f8a1f0dc-341f-11ed-ba43-dac502259ad0.png

如果我們希望 Bootloader 僅僅是做簡單的跳轉(zhuǎn),我們可以將規(guī)劃這段內(nèi)存的工作,交給應(yīng)用程序的初始化部分(在 “l(fā)dr sp, =_estack”之前)。假定 0x0 處對應(yīng)為 0x2400 0000,參考代碼如下:

f8b484fe-341f-11ed-ba43-dac502259ad0.png

3.3.2. 匯編代碼

3.3.2.1. _sidata

在默認(rèn)的 STM32 工程中,還有一些對變量絕對地址的使用。在 startup_xxx.s 有許多地方使用絕對地址,它們不能被編譯器收集到 GOT 中。其中,默認(rèn)在鏈接腳本里的_sidata,標(biāo)志 flash 里 RAM 數(shù)據(jù)區(qū)的 Flash 位置,需要修改。

f8d1235c-341f-11ed-ba43-dac502259ad0.png

注意,變量絕對地址本身不是個(gè)問題,而對它解應(yīng)用,取它的內(nèi)容才會(huì)發(fā)生錯(cuò)誤。而這里的 _sidata 是要被初始化代碼使用,目的是將 Flash 的內(nèi)容搬移到 RAM 里。我們顯然要對_sidata 進(jìn)行修改,否則無法取得正確的內(nèi)容到 RAM 里。

根據(jù)前文的內(nèi)存布局,我們可以把 Flash 的偏移量從內(nèi)存中放置在寄存器 r8 里,例如:

f8e20532-341f-11ed-ba43-dac502259ad0.png

則我們只需要一行簡單的代碼 “add r3,r8” 就可以修正_sidata 的地址。

f8f6f37a-341f-11ed-ba43-dac502259ad0.png

3.3.3. C 代碼

3.3.3.1. 公共函數(shù)

如果一段內(nèi)存的數(shù)據(jù)都是硬編碼,我們只需要一個(gè)公共函數(shù)就可以對其循環(huán)進(jìn)行修正。我們需要知道什么樣的地址之外不是 Flash 地址,那么就對這樣的值不做修改。例如,我們定義 0x1fff ffff 之外的就不是 Falsh 地址,相應(yīng)的宏定義如下:

f901f82e-341f-11ed-ba43-dac502259ad0.png

3.3.3.2. SCB->VTOR

在 C 語言中如果使用賦值語句進(jìn)行硬編碼,編譯器也無法進(jìn)行收集。例如在

system_stm32xxxx.c 中的 SystemInit 有如下語句:

f9172eba-341f-11ed-ba43-dac502259ad0.png

中斷向量表相關(guān)的內(nèi)容需要修改,包括兩部分:

? 中斷向量表的內(nèi)存位置

? 中斷向量表的內(nèi)容

我們應(yīng)該將中斷向量表復(fù)制到 RAM 里,通過 UpdateOffset 函數(shù)修正其中包含的所有Flash 絕對地址的值,同時(shí)通過對 SCB->VTOR 賦值來將中斷向量表的位置指向我們修改過內(nèi)容的 RAM 地址。注意,VTOR 所指向的地址 VT_RAM_START 要按照 ARM 要求,根據(jù)中斷總大小向上進(jìn)行 2 的冪次對齊,例如,37 個(gè)字大小要使用 64 個(gè)字對齊。另外,中斷向量表的內(nèi)容,也包含有 RAM 地址,對此,我們并不需要修改。當(dāng)然,UpdateOffset 函數(shù)已

經(jīng)考慮到這一點(diǎn),所以我們可以直接使用它。更新中斷向量表以及 VTOR 的參考代碼如下:

f932eb96-341f-11ed-ba43-dac502259ad0.png

3.3.3.3. GOT

編譯器已經(jīng)將 C 語言中所有全局變量的地址都收集到 GOT 中,因此我們很容易對其Flash 地址的內(nèi)容進(jìn)行修正,參考代碼如下:

f94ba028-341f-11ed-ba43-dac502259ad0.png

4、總結(jié)

除非你僅僅是運(yùn)行一小塊代碼,否則開發(fā)位置無關(guān)的 STM32 完整工程,不僅僅要設(shè)置正確的編譯器選項(xiàng),還要保證它所鏈接的預(yù)編譯的庫不含有絕對地址引用,要保證所有源代碼里沒有對絕對地址的硬編碼,包括修改 data 區(qū)的 Flash 起始地址,中斷向量表的內(nèi)容與位置,以及 GOT 的內(nèi)容。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 存儲
    +關(guān)注

    關(guān)注

    13

    文章

    4411

    瀏覽量

    86466
  • STM32
    +關(guān)注

    關(guān)注

    2277

    文章

    10952

    瀏覽量

    359244
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4355

    瀏覽量

    63319
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4858

    瀏覽量

    69551

原文標(biāo)題:如何開發(fā)與存儲位置無關(guān)的 STM32 應(yīng)用

文章出處:【微信號:mcugeek,微信公眾號:MCU開發(fā)加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM32應(yīng)用與存儲位置無關(guān)

    Bootloader 里只需要跳到相應(yīng)的位置就可以正常執(zhí)行固件代碼。客戶希望STM32 代碼從 Flash 里執(zhí)行,不復(fù)制到 RAM 里;客戶希望是一個(gè)完整的映像,而不僅僅是其中某個(gè)函數(shù)做到了
    發(fā)表于 09-05 11:43 ?894次閱讀

    ARM的位置無關(guān)程序設(shè)計(jì)在Bootloader中的應(yīng)用

    ARM的位置無關(guān)程序設(shè)計(jì)在Bootloader中的應(yīng)用
    發(fā)表于 10-26 21:33

    轉(zhuǎn):使用STM32CubeMX生成用于STM32-V5開發(fā)板的USART工程

    本期教程使用STM32CubeMX生成可用于STM32-V5開發(fā)板的USART1工程,通過本期教程讓大家對STM32CubeMX有個(gè)整體的認(rèn)
    發(fā)表于 09-09 11:17

    位置無關(guān)的代碼

    ) }--------------------------------------------這里把代碼段等鏈接到外存地址,那么確實(shí)在引導(dǎo)代碼里要注意“位置無關(guān)的代碼”問題,個(gè)人查了一些資料,只是提到bl,adr等相對pc的一些指令用法 .rodata ALIGN(4
    發(fā)表于 06-17 05:45

    ARM的位置無關(guān)程序設(shè)計(jì)在Bootloader中的應(yīng)用

    ARM的位置無關(guān)程序設(shè)計(jì)在Bootloader中的應(yīng)用 ARM處理器支持位置無關(guān)的程序設(shè)計(jì),這種程序加載到存儲器的任意地址空間都可以正常運(yùn)行,其設(shè)計(jì)方法在嵌
    發(fā)表于 03-29 15:12 ?1297次閱讀

    ARM處理器的位置無關(guān)程序設(shè)計(jì)

    ARM處理器支持位置無關(guān)的程序設(shè)計(jì),這種程序加載到存儲器的任意地址空間都可以正常運(yùn)行,其設(shè)計(jì)方法在嵌入式應(yīng)用系統(tǒng)開發(fā)中具有重要的作用。尤其在裸機(jī)狀態(tài)下開發(fā)Bootloader程序及
    發(fā)表于 09-22 17:03 ?1061次閱讀

    EM-STM3210E開發(fā)完整資料

    EMBEST(英蓓特)的STM32開發(fā)板EM-STM3210E的完整資料。EMBEST是ST的官方合作伙伴。 內(nèi)容: 1 開發(fā)板用戶手冊(P
    發(fā)表于 05-13 16:40 ?21次下載

    ARM處理器位置無關(guān)的程序設(shè)計(jì)方案解析

    ARM處理器支持位置無關(guān)的程序設(shè)計(jì),這種程序加載到存儲器的任意地址空間都可以正常運(yùn)行,其設(shè)計(jì)方法在嵌入式應(yīng)用系統(tǒng)開發(fā)中具有重要的作用。尤其在裸機(jī)狀態(tài)下開發(fā)Bootloader程序及進(jìn)行
    發(fā)表于 10-27 13:00 ?4次下載

    ARM處理器的位置無關(guān)程序設(shè)計(jì)

    ARM處理器支持位置無關(guān)的程序設(shè)計(jì),這種程序加載到存儲器的任意地址空間都可以正常運(yùn)行,其設(shè)計(jì)方法在嵌入式應(yīng)用系統(tǒng)開發(fā)中具有重要的作用。尤其在裸機(jī)狀態(tài)下開發(fā)Bootloader程序及進(jìn)行
    發(fā)表于 12-01 01:16 ?613次閱讀

    Linux下C語言共享庫的位置無關(guān)實(shí)現(xiàn)原理分析

    如何創(chuàng)建一個(gè)*可執(zhí)行*的共享庫 一文談完了如何讓共享庫可直接執(zhí)行,本文再來談?wù)劰蚕韼斓倪\(yùn)行時(shí)位置無關(guān)(PIC)是如何做到的。
    的頭像 發(fā)表于 11-28 16:20 ?3149次閱讀

    實(shí)例介紹如何使用STM32開發(fā)工具Keil建立工程

    ????本文通過點(diǎn)亮LED的簡單例子,梳理以下如何使用STM32開發(fā)工具Keil建立工程。 ????假設(shè)你手里有STM32開發(fā)板。 ???
    的頭像 發(fā)表于 02-01 14:00 ?6663次閱讀
    實(shí)例介紹如何使用<b class='flag-5'>STM32</b><b class='flag-5'>開發(fā)</b>工具Keil建立<b class='flag-5'>工程</b>

    畢業(yè)論文 | 基于STM32的雙輪平衡小車設(shè)計(jì)(基于Keil5的完整注釋版代碼工程,原器件清單)

    畢業(yè)論文 | 基于STM32的雙輪平衡小車設(shè)計(jì)(基于Keil5的完整注釋版代碼工程,原器件清單)
    發(fā)表于 11-21 20:06 ?0次下載
    畢業(yè)論文 | 基于<b class='flag-5'>STM32</b>的雙輪平衡小車設(shè)計(jì)(基于Keil5的<b class='flag-5'>完整</b>注釋版代碼<b class='flag-5'>工程</b>,原器件清單)

    STM32開發(fā),使用IAR軟件建立工程

    STM32開發(fā),使用IAR軟件建立工程1 概述1.1 資源概述1.2 在IAR中建立工程2 IAR建立STM32
    發(fā)表于 12-03 10:51 ?14次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>開發(fā)</b>,使用IAR軟件建立<b class='flag-5'>工程</b>

    ESP8266 WIFI的stm32f103的完整工程

    ESP8266WIFI 的stm32f103 的完整工程資料分享
    發(fā)表于 11-17 15:23 ?32次下載

    如何開發(fā)與存儲位置無關(guān)STM32應(yīng)用?

    如何開發(fā)與存儲位置無關(guān)STM32應(yīng)用?
    的頭像 發(fā)表于 10-18 16:46 ?689次閱讀
    如何<b class='flag-5'>開發(fā)</b>與存儲<b class='flag-5'>位置</b><b class='flag-5'>無關(guān)</b>的<b class='flag-5'>STM32</b>應(yīng)用?
    主站蜘蛛池模板: 视频在线观看一区二区 | 国产99色| 四虎1515hh永久久免费 | 美女扒开下面让男人捅 | 久久久久激情免费观看 | 欧美射射射| 一级特黄性色生活片一区二区 | 男人性天堂 | 欧美性满足hd1819 | 都市激情综合 | 欧美色视频在线观看 | 亚洲操图| 日本边添边爱边摸边做边爱 | 日本黄色免费在线 | 欧美一级日韩一级亚洲一级 | 国产小视频网站 | 超h 高h 污肉男男 | 午夜啪啪免费视频 | 久久久久国产精品四虎 | 日本高清www| 喷潮白浆 | 婷婷在线网 | 久久夜夜肉肉热热日日 | 一级特黄性色生活片一区二区 | 播放欧亚一级特黄录像 | 簧片视频在线观看 | 国产2021成人精品 | 4hu44四虎在线观看 | 一级特黄aa大片一又好看 | 天天操狠狠操夜夜操 | 国产激爽大片在线播放 | 永久免费在线观看 | 1000部啪啪勿入十八免费 | 免费恐怖片 | 亚洲一区二区免费视频 | 色久优优 | 99久久99久久精品免费看子伦 | 四虎影院最新地址 | 日本加勒比在线播放 | 天天爱天天操天天干 | 日本在线色视频 |