# 2021 年「[資訊科技產業專案設計](https://hackmd.io/@sysprog/info2021/https%3A%2F%2Fhackmd.io%2F%40sysprog%2Finfo2021-homework4)」課程作業 4 contributed by<`owl`> ###### tags: `INFO2021` ## [Realtek---Bluetooth SoC 韌體工程師](https://recruit.realtek.com/zh/index.php?option=com_content&view=article&id=10206) >分公司地點: 新竹 >職類: System/Firmware >工作經驗: 2年 >教育程度: 碩士 ### 職缺內容 1. Bluetooth Protocol Development and Performance Optimization 2. Bluetooth MAC Design Development 3. SoC **CPU/Platform Architecture Development** 4. FPGA Emulation and ASIC **Verification** 5. Troubleshooting :::info 這個職缺跟藍芽晶片有關係,而且看起來要做的工作不只一兩項而已,應該需要多種技能,主要是要懂一點 CPU 、微處理器架構以及硬體驗證。 ::: ### 職缺需求 1. 碩士以上;電機、電機與控制、資訊科學、自動控制、通訊工程、電信、資訊工程、電子相關科系畢業為主。 2. 精通 C Programming Skill。 3. 有 Bluetooth 或其它 SoC 大型專案開發經驗者加分。 4. 有 Security 開發經驗者加分。 5. 熟悉 ARM Cortex CPU加分。 6. 熟悉 RTOS 加分。 7. 熟悉 USB, SDIO, SPI, UART, I2C, I2S, … 等界面加分。 8. 個性積極, 邏輯清晰, 有創造力。 9. 能配合出差協助客戶解決問題。 :::info 1. 符合 2. 基本C語法使用及程式撰寫沒問題,但是需要加強練習資料結構以及演算法 3. 無 4. 無 5. 目前沒有,但是未來規劃會實作 6. 只有理論跟一些簡單實作,個人認為強度不夠 7. 目前沒有,但是未來規劃會實作 8. 符合 9. 沒問題 結論: 符合興趣,具有在嵌入式系統上開發軟體的經驗,但是沒有接觸到比較底層的架構。未來一年內會強化,。 ::: ## [Nvidia---Firmware Engineer, DGX](https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/Taiwan-Taipei/Software-Security-Engineer_JR1946742) >分公司地點: 台北 >職類: Firmware/Embedded >工作經驗: 沒有提到 >教育程度: 碩士 ### 職缺內容 1. Be involved in the **definition, architectural design**, and development of **security firmware** for NVIDIA DGX products with an opportunity to craft its future. 2. Assist with defining and making sure software development process meeting **security standards**. 3. Perform security threat modelling for our software. 4. Design and/or make recommendations for security solutions that apply to the software to satisfy **DGX server security guidelines and requirements**. :::info - 從職缺敘述看來,這個職缺應該是跟 NVIDIA DGX 這個產品線相關,特色是搭載四顆 NVIDIA A100 Tensor 核心 GPU , DGX 系列基本上是用來做人工智慧訓練專用,最大可以達到伺服器等級(NVIDIA DGX Station) ,官網的團隊還有提到,為來他們的產品領域可能會應用於遊戲、自駕車等領域。 - 另一個主要的面向是安全性,顯然這個職缺可能會需要一些資訊安全相關的背景會比較合適。 ::: ### 職缺需求 1. Bachelors or higher in electrical engineering, computer science, or computer engineering (or equivalent experience) 2. Have software design, development, analysis or equivalent experiences. 3. Experience in building and implementing secure software. Familiar with DMTF PLDM, MCTP, SPDM standards is a plus. 4. Experience in embedded software development in Linux environment. 5. Background with FreeRTOS. 6. Experience with security technologies: Root of Trust, etc. 7. Experience in threat modeling and modeling attack-vectors. 8. Background with SBIOS and BMC firmware is a plus. 9. Strong programming skills in C/C++, algorithms, and data structures. 10. Strength being hands-on with development in addition to experience in software security. 11. Deep understanding of computer architecture, operating system fundamentals. 12. A strong teammate; self-motivated with positive attitude with a motivation to learn, grow and build. :::info 1. 符合 2. 符合 3. 無 4. 正在學習中 5. 正在學習中 6. 無 7. 無 8. 無 9. 需要多練習 10. 無軟體安全相關經驗 11. 具備基礎知識 職缺本身十分強調資訊安全相關能力,因為實驗室做的計畫跟資安完全無關,準備起來會相對吃力,因此如果要投遞這個職缺,會把 FreeRTOS 、 embedded C 相關知識做充分準備, ::: ## Nvdia---[Embedded Software Engineer (RDSS Intern)](https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/Taiwan-Taipei/Embedded-Software-Engineer--RDSS-Intern-_JR1945826-1) / [Software Engineer, Jetson Embedded (RDSS Intern)](https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/Taiwan-Taipei/Software-Engineer--Jetson-Embedded--RDSS-Intern-_JR1945820-1) 因為上面那個職缺需要的似乎是比較偏向資訊安全領域的人才,所以我又找了兩個比較通用的職缺,都是針對研發替代役的工作,又是跟嵌入式系統叫相關職缺,所以將兩個職缺的內容合併比較。 ### 職缺內容 **Embedded software engineer** 1. Work directly in developing or integrating NVIDIA automotive or embedded software technology into various NVIDIA automotive or embedded platforms. 2. Might work with customers to provide deep technical assistances. 3. Assist customers to achieve fully optimized design with NVIDIA products. 4. Provide partner feedbacks as to product features and software improvements **Jetson embedded** 1. Improve software quality of the Jetson Platform BSP 2. Developing the Linux BSP features for the Tegra SoC and Jetson Embedded Platform 3. Debian packaging for software release 4. Collaborate with international team for issue triage and debugging :::info 和老師上課說的一樣,我判斷這個職缺應該屬於通用職缺,因為工作內容跟下面的職缺需求比較模糊(相較許多 senior 職缺來說),總體來說,這兩個職缺的共同點應該是都需要對底層的 linux 實作要有相關背景,尤其是 BSD 的部分,應該要熟讀跟 Bootloader 相關的操作比較好,目前我有在 Jetson 嵌入式裝置上開發程式,但是需要額外花時間去了解底層資訊 ::: ### 職缺需求 **Embedded software engineer** 1. Good English language skills to work effectively with global teams. 2. Full experience at Linux, QNX or Android. 3. Excellent C skills. 4. Experience working on embedded systems and ARM processor specific is a plus. 5. Experience working in following areas is a plus: AutoSAR, device drivers, multimedia, graphics, camera software stack, image quality tuning (ISP tuning), OpenCL, OpenCV, CUDA, Deep Learning, and AI. **Jetson embedded** 1. Good Linux architecture knowledge 2. Good C/Python/Shell script programming/debugging skills. 3. Excellent English communication skill 4. Experience in developing Linux software on Jetson development kit or any other similar ARM platform 5. Excellent knowledge on bus specification such as the I2C, SPI, PCIe, NVMe, SD, EMMC or USB :::info 1. Linux 開發相關經,對 linux 本身也具備基礎概念 2. C/Python 語言算熟悉 3. 在嵌入式裝置(ARM)上進行開發 總結: 對於學生來說,投研發替代役看起來機會是比較大的,接下來就是利用半學期時間安排該回去補強的能力以及新能力。唯一需要注意的是準備方向,因為這個職缺跟 RTOS 相關度看起來比較低(這兩個領域也可以是說有重疊的部分啦~),主要是 embedded linux 可能會比較實用,如果兩個領域都想要嘗試看看的話可以嘗試 RT patch linux 跟 free RTOS 開發。 ::: ## 面試題目 Nvidia 的面試題目找到得比想像中的少,但是找過面試題發現,不同公司問的嵌入式相關問題似乎大同小異,所以這個章節我就統一放一些常見的問題,問題範圍主要都是跟嵌入式系統相關。 ### Nvidia 題目(研替為主) 1. **如果硬體不支援乘法,那如何讓 `x = y * 200` 運算的答案是正確的?** 這題我是自己想的,因為後來也沒有查到很滿意的解決方式。顯然面試官希望用比較底層的方式來解決這個問題,所以先假設加法器跟位移仍可以使用。 我的方式需要用到利用到兩個額外的暫存器,作法如下: ```graphviz digraph ptr { rankdir=UD; node[shape=box]; a[label= "x=?"]; b[label= "y"]; c[label= "reg1=0x11001000"]; d[label= "reg2=NULL"] } ``` `0x11001000` 也就是我們的 200 ,我們可以先將 200 看成 $2^7+2^6+2^3$,簡單的分配率使答案拆分成 $y×2^7+y×2^6+y×2^3$ ,也就是分別對 $y$ 位移7、6、3次,然後把得到的答案進行加總。解釋完原理之後,接下來是實作。實際運行: 先把 y 搬移到 `reg2` 中, ```graphviz digraph ptr { rankdir=UD; node[shape=box]; a[label= "x=y×8"]; b[label= "y"]; c[label= "0x11001"]; d[label= " y×8 "] } ``` `x` 存放想要得到的答案, `reg2` 則是儲存當前的 y 乘上2的幾次方,所以同時將 `reg1` 的200做右移運算, `reg2` 做左移運算,如果 `reg1 & 0x1` 為真,將 `reg2` 目前的數值加到 `x` 當中 ```graphviz digraph ptr { rankdir=UD; node[shape=box]; a[label= "x=y×8+y×64"]; b[label= "y"]; c[label= "0x11"]; d[label= " y×64 "] } ``` 當 `reg1` 的32 bit 全部右移完畢時,`x` 得到正確的數值, ```graphviz digraph ptr { rankdir=UD; node[shape=box]; a[label= "x=y×8+y×64+y×128"]; b[label= "y"]; c[label= "0x1"]; d[label= " y×128 "] } ``` 這題的解法應該還有更好的方式,但是這是我想到底層實作可行的方式,只需要用到基礎的加法、位移、搬移跟比較指令(真正組合語言實作還包含分支控制等指令,暫時不考慮) 2. **實作一個 function,參數是 32-bit integer,回傳共有幾個 bits 是 1** 很明顯是 bitwise operation 的問題,而且預期 employer 希望實作的方向效率越高、越省空間越好。 實作的結果可以參考 Leetcode [338. Counting Bits](https://leetcode.com/problems/counting-bits/) ,限定不用 `builtin` 函式,並且要將時間複雜度限制在 $O(n)$ 以內,空間複雜度的部分,只使用到必須回傳的 $O(n)$ ,除此之外使用的多餘記憶體為 $O(1)$ ```c int* countBits(int n){ int *ans = malloc(sizeof(int) * (n+1)); int count = 0; for (int i=0; i < n+1; i++){ count = 0; for (int b = 0; b < 32; b++) { if ((i & (0x1 << b)) != 0) count++; } ans[i] = count; } for (int i =0; i< n+1;i++) printf("%d", ans[i]); return ans; } ``` 所以要回答這一題,只需要關鍵的程式碼部分: ```c int countbit(n){ int count = 0; for (int b = 0; b < 32; b++) if ((n & (0x1 << b)) != 0) count++; return count; } ``` 3. **名詞解釋:** **data section**:這邊指的應該是 data segment ,對一個程式(program)分配的靜態記憶體空間,儲存的是一些已經初始化的靜態變數,例如有經過初始化的 C 語言的==全域變數==(global variables)以及==靜態變數==(static variables),此區域是唯讀。 **heap:** ==動態記憶體配置==的變數,常見的範例如 C 的 `malloc` 、 C++ 的 `new` 等。 **stack:** 儲存函數的==區域變數==,以及各種函數呼叫時需要儲存的資訊(例如函數返回的記憶體位址還有呼叫者函數的狀態等),每一次的函數呼叫就會在堆疊區段建立一個 stack frame,儲存該次呼叫的所有變數與狀態,這樣一來同一個函數重複被呼叫時就會有不同的 stack frame,不會互相干擾,遞迴函數就是透過這樣的機制來執行的。 4. **解釋 interrupt latency**: 指的是發出硬體中斷後到第一個 ISR 指令被執行到之間的延遲時間。 ![](https://i.imgur.com/R6n1KQS.png) 造成這個延遲的原因來自於中斷發生後, CPU 根據中斷表查詢對應的 Interrupt handler ,另外,由於中斷處理具備優先級,所以低階中斷發生後可能不會被馬上執行,而是等待高階中斷先執行完畢之後才會執行。 ### 其他嵌入式相關問題 5. **為什麼 strncpy 並不是一個 memory-safe 的函式?** 這邊的 n 並沒有限制是否超出複製字串長度,因此攻擊者可以刻意讓寫入字串超過複製字串,從而非法修改到其他記憶體。並且 `strncpy` 並不會主動檢查字串的中止符號,因此複製完的字串可能不符合正常字串中指符號擺放的位置,舉例如下: ```graphviz digraph ptr { rank=LR; node[shape=record]; a[label= "<f0> a|<f1> p|<f1> p|<f2> l|<f3> e|<f4> e"]; b[label= "<f0> a|<f1> p|<f1> p|<f2> l|<f3> e|<f4> \\0"]; c[label= "<f0> a|<f1> p|<f1> p|<f2> \\0|<f3> \\0|<f4> \\0"]; d[label= "<f0> a|<f1> \\0|<f1> p|<f2> l|<f3> e|<f4> \\0"] } ``` 另外,過長的字串也會在複製的時候自動被截斷,導致資料的遺失。 6. **C 語言一定必須從 main() 開始執行程式嗎?** 否,其實使用者可以自行定義程式的進入點,如下列範例 ```c #include <stdio.h> #include <stdlib.h> __attribute__((constructor)) void before_main(){ printf("before_main()\n"); } void func1() { printf("exit function1\n"); } void func2() { printf("exit function2\n"); } int main() { printf("This is main()\n"); atexit(func1); atexit(func2); return 0; } __attribute__((destructor)) void after_main(){ printf("After main()\n"); } ``` 輸出結果為: ``` before_main() This is main() exit function1 exit function2 After main() ``` 我們可以看到程式的進入 function 並不是 `main()` ,而是會先執行 `before_main()` 。 7. **為什麼嵌入式開發時需要一個無限迴圈** 這個問題真的很不錯!之前一直以為只有 arduino 系列的開發板才會有 `setup()` 、 `loop()` 函式定義,直到最近看 STM32 的 `main` 函式時,發現 IDE 也幫我們預設了一個永遠循環的 for 迴圈。之所以嵌入式系統需要無限迴圈作為程式主體的原因有以下幾種: ==首先==,嵌入式軟體應用的系統絕大多數的情況之下,我們會希望它持續、甚至永久的運行下去,如果沒有這個無限迴圈,代表程式總有"做完"的那一天,也代表這個嵌入式裝置已經"沒用"了(或是說,不再運作),而這跟我們原先給定的設想並不符合,所以我們只會讓其進入休眠等低功耗模式,但是等到我們需要時可以隨時喚醒這個裝置。所以"休眠"其實也只是無限迴圈的其中一環;==其次==,也是最重要的一點,一般的計算機通常具備作業系統,一旦 user space 的程式結束後,會立即接管控制權,但是嵌入式系統並沒有,所以最好的處理方法就是,執行這個程式時,不要讓系統脫離這個程式的控制,即無限的執行下去。 需要注意的一點是,嵌入式裝置只是"可以"不用作業系統,並不代表一定沒有作業系統,但是低階嵌入式系統像是遙控器、溫度計、血壓計等的確就沒有作業系統。 8. **什麼是看門狗計時器(watchdog timer)?** 看門狗計時器是一個定時電路,本質上是一個倒數計時的計數器(counter),程式啟動時看門狗計時器開始倒數,如果程式正常運行, MCU 會定期發出指令將這個倒數計時重置(有點像定時炸彈一樣),如果倒數到 0 但是 MCU 依然沒有傳送指令的話,代表可能發生軟體故障(如 deadlock 、 infinite loop 之類)或是硬體故障(如IC燒壞),將系統全部重置(RESET)或是切換至冗餘系統。 9. **遞迴函式能不能使用 inline 函式?** 這題真的是有點細節...,我自己看到這個問題直覺是不能合在一起使用,因為 inline function 本身是編譯器優化的方式,當一個函式被宣告成 `inline` 時,編譯器根據最佳化會去判定是否能不能直接在呼叫這個函式的地方直接將其展開(原理接近 `#define`),優點是可以保持函式的封裝性,又可以避免使用 function call ,適合寫成 inline function 的函式通常具有簡短、出現頻率高的特色,編譯器優化階段,如果評估發現 inline function 展開需要造成過多額外的處理時間(如遞迴就是一個很好的例子),就不會將這個函式內嵌到呼叫的程式碼中。 :::info 延伸問題: `inline` 和 `#define` 之間的差異 ::: 10. **解釋 C 中的 Storage Classes** ## [聯發科---5G 工具韌體工程師](https://careers.mediatek.com/eREC/JobSearch/JobDetail/MTK120210122001?langKey=zh-TW) > 分公司地點 新竹 > 職類 Software > 工作經驗 無工作經驗 > 教育程度 碩士 好奇看其他同學的作業的時候翻到的職缺,因為也有些興趣,於是也將它納入考慮。 ### 職缺內容 - 設計與開發嵌入性軟體,實現高效率資訊收集與分析 - 制定軟體開發規範和最佳做法 - 以敏捷式開發,設計兼具彈性/可延展性/可維護性的開放式軟體工具平台架構 - 與世界最新進的通訊團隊合作,定位未來的軟體架構 :::info 評估:對於軟體架構以及軟體設計有相關經驗,並且略懂軟體工程去面試會比較吃香,我自己在這方面是有一些研究,也常常跟同學討論,因此投遞這份工作可能會是不錯的選擇,但是對於第一份工作來說,我比較希望針對嵌入式系統本身的設計做比較深入的研究,也就是解決比較底層的問題,然後對於高層的平台、系統設計會比較知道相關的設計限制等。 ::: ### 職缺需求 1. 熟悉C/C++/Python任一種語言 2. 軟體設計和開發經驗, 困難問題解決充滿興趣 3. 對於工作和新挑戰態度積極負責 4. 快速學習且能夠主動溝通內外團隊 5. 具備嵌入式系統開發經驗 6. 具備大型軟體架構設計, 硬體驗證經驗 尤佳 :::info 1. 熟悉C、C++、python 2. 符合 3. 符合 4. 符合 5. 僅在系統上開發程式,尚未接觸比較底層的實作 6. 不確定自己實驗室的機器人架構設計是否符合大型, ::: ## 自身分析 之前有利用ESP32做過簡單的FreeRTOS實驗。並且實驗室目前準備將現有系統移植到嵌入式裝置上,自己對於系統架構設計以及嵌入式裝置有興趣,只是這是最近才慢慢發現的事情,所以打算接近期末的時候自行利用網路上的一些教學資源學習STM32以及FreeRTOS ### 優勢 - 經手過比較複雜的軟硬體系統(機器人),因此熟悉軟硬體 debug 流程。 - 學的東西比較廣(也比較雜),除了基本的程式語言還有碰過專案管理、系統分析設計、軟體工程以及很多種傳感器的控制 - 相較同學對 linux 較了解,自己也透過直接閱讀原始碼獲得第一手資訊。 ### 劣勢 - 缺乏決定性有強度的大型實作/代表作 - 對於 FreeRTOS 仍需練習大型複雜實作 - 實驗室目前任務是負責整台機器人的系統重構以及新計劃的機器人架構設計,但是跟上述職缺要求可能不到十分吻合。 ### 擬定策略 - 利用實驗室提供之 STM32 開發板了解在ARM架構下開發之套件,目標是能夠理解通訊界面(GPIO、I2C、UART等)並實作Driver、Bootloader等,並實作RTOS ## 參考資料 - [[面試]研替面試分享](https://www.pttweb.cc/bbs/Tech_Job/M.1612848862.A.6D2) - [两万字带你狙击嵌入式笔试面试题](https://www.eet-china.com/mp/a42903.html) - [embedded engineer interview](https://www.quora.com/I-have-an-interview-tomorrow-for-an-embedded-engineer-position-see-description-What-questions-can-I-expect-in-general-and-on-the-technical-side)