嵌入式程式設計師應該知道的16個問題

2021-08-30 01:26:55 字數 2594 閱讀 4129

***

9、位操作(bit manipulation)

嵌入式系統總是要使用者對變數或暫存器進行位操作。給定乙個整型變數a,寫兩段**,第乙個設定a的bit 3,第二個清除a 的bit 3。在以上兩個操作中,要保持其它位不變。 對這個問題有三種基本的反應

1)不知道如何下手。該被面者從沒做過任何嵌入式系統的工作。

2) 用bit fields。bit fields是被扔到c語言死角的東西,它保證你的**在不同編譯器之間是不可移植的,同時也保證了的你的**是不可重用的。

3) 用 #defines 和 bit masks 操作。這是乙個有極高可移植性的方法,是應該被用到的方法。最佳的解決方案如下:

#define bit3 (0x1 << 3) (採用巨集將數字定義為有意義的bit3,明確,不易出錯,改起來方便)

static int a;

void set_bit3(void)

void clear_bit3(void)

考點:在嵌入式系統中,時刻要關注移植性,具體的程式中不要出現具體的數字,這些數字都應該define成某個有意義的符號,可讀性可移植性都很強,比如

#define bit(x) (0x1 << (x))

x作為引數可以很方便的對任意位進行操作,意義明確,更改替換方便

10、訪問固定的記憶體位置(accessing fixed memory locations)

嵌入式系統經常具有要求程式設計師去訪問某特定的記憶體位置的特點。

在某工程中,要求設定一絕對位址為0x67a9的整型變數的值為0xaa66。編譯器是乙個純粹的ansi編譯器。寫**去完成這一任務。這一問題測試你是否知道為了訪問一絕對位址把乙個整型數強制轉換(typecast)為一指標是合法的。這一問題的實現方式隨著個人風格不同而不同。典型的類似**如下:

int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa55;

*(int * const)(0x67a9) = 0xaa55;

即使你的品味更接近第二種方案,但我建議你在面試時使用第一種方案。

在嵌入式系統中,對於大量此型別資料如硬體暫存器應該採用如下方式

typedef volatile unsigned int hard_reg;

#define reg_name (*(hard_reg *)addr)

即將addr強制轉換為乙個指向hard_reg型別資料的指標,*hard_reg為volatile的無符號整型數

11、中斷(interrupts)

__interrupt double compute_area (double radius)

這個函式有太多的錯誤了,以至讓人不知從何說起了(前提是非作業系統下的中斷服務函式):

1)isr 不能返回乙個值(都應該為void型別)。如果你不懂這個,那麼你不會被雇用的。

2)isr 不能傳遞引數。如果你沒有看到這一點,你被雇用的機會等同第一項。

3)在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額外的暫存器入棧,有些處理器/編譯器就是不允許在isr中做浮點運算。此外,isr應該是短而有效率的,在isr中做浮點運算是不明智的。

///另外中斷服務程式是執行在核心態的(linux),核心通常是不支援浮點運算的。

核心中的printk和標準庫的printf不一樣,前者因為由核心直接實現,不能支援浮點。

在<linux核心設計與實現>的第一章中核心開發的特點一小節裡就有比較了核心開發與應用開發的差異。其中一點就是核心程式設計時浮點數的問題,書中有一句話是:核心程式設計時浮點數很難使用

因為沒有浮點單元,核心要支援浮點必須把核心以soft-float 方式重新編譯,其連線所有的庫也都要用soft-float 方式編譯.

否則另外一種方式使用整數定義浮點型別加浮點預算庫完成你的工作,

如果你的核心裡編譯進了浮點支援,那麼是可以的。要不核心或是模組不能用float或是double內型的變數或函式

在配置核心的時候把浮點模擬器選上,應該是可以支援的,但是速度非常慢。

我曾經遇到過,硬體明明支援浮點運算的fpu,但是編譯核心的時候選上了浮點模擬器,結果所有的應用程式的浮點運算速度都非常慢。所以我懷疑要支援浮點只要編譯核心的時候選上,對於應用程式不需要怎麼關心。

///4) 與第三點一脈相承,printf()經常有重入和效能上的問題。如果你丟掉了第三和第四點,我不會太為難你的。不用說,如果你能得到後兩點,那麼你的被雇用前景越來越光明了。

12、符號擴充套件的**例子(code examples)

下面的**輸出是什麼,為什麼?

void foo(void)

vc6.0測試情況

void main(void)

/*unsigned int a + int b = fffffff2*/

這個問題測試你是否懂得c語言中的整數自動轉換原則,我發現有些開發者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是 ">6"。原因是當表示式中存在有符號型別和無符號型別時所有的運算元都自動轉換為無符號型別。因此-20變成了乙個非常大的正整數,所以該表示式計算出的結果大於6。這一點對於頻繁用到無符號資料型別的嵌入式系統(硬體暫存器的值全部是無符號的)來說是丰常重要的。如果你答錯了這個問題,你也就到了得不到這份工作的邊緣。

嵌入式程式設計師應該知道的0x10個基本問題

例子 code examples 12 下面的 輸出是什麼,為什麼?void foo void 這個問題測試你是否懂得c語言中的整數自動轉換原則,我發現有些開發者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是 6 原因是當表示式中存在有符號型別和無符號型別時所有的運算元都自動轉換為無符號...

程式設計師應該知道的事情

今天中午在 cxuan 的群內討論tdd和lambda的問題 炸出來一位前輩,為我們分享了很多知識 真正的大佬 借用 cxuan 的話來說,就是能夠使自己思想受到淘洗,資訊量大能讓你產生冥思 涵蓋了技術 職業規劃 業務 管理 特在這裡總結一下,希望大家看完也能有所收穫 不要過度追求新技術 新框架,每...

成為嵌入式程式設計師應知道的0x10個問題

c語言測試是招聘嵌入式系統程式設計師過程中必須而且有效的方法。這些年,我既參加也組織了許多這種測試,在這過程中我意識到這些測試能為面試者和被面試者提供許多有用資訊,此外,撇開面試的壓力不談,這種測試也是相當有趣的。從被面試者的角度來講,你能了解許多關於出題者或監考者的情況。這個測試只是出題者為顯示其...