單片機的內核有很多種,如51,AVR,ARM,PIC,Power PC, RISCV阿,有很多種的,網上的解釋說內核包含中央運算單元+內部總線+指令解析,還有提到CPU的內核分為兩部分運算器和控制器。不管怎么說吧,內核肯定是軟件或者硬件最核心的部分,可以包含軟件,如Linux內核就是軟件的。對軟件內核不太了解,下面還是說說單片機把,對單片機來說,個人覺得最重要的只要是內核一樣,其匯編指令集也就一樣,代碼基本不太需要改變。
現在再來討論下架構,架構有哈佛架構:兩個獨立的存儲模塊或區域,程序空間與數據空間分開,便於程序與數據同時訪問,另一個位普林斯頓架構,程序空間和數據空間使用同一個存儲器,即我們熟知的馮諾依曼體系結構,既然提到了馮諾依曼體系結構,就不得不說一下該體系結構是如何發展來的,這很有啟發意義。最早的計算器(也就相當於今天的計算機),它是不可以編程的,內部僅有固定用途的程序,當然那時候可能程序的概念都沒有,有的就是一堆連接線,若要改變這個機器的功能必須要重新設計和連接線路,顯然這很不靈活,相當費力氣。於是人們開始想到最好可以靈活的設計一個計算器,它能根據我的需要做出改變而產生不同的功能,這時人們就差不多萌芽了程序的想法,通過一種手段來實現不同的功能(今天的不同程序實現不同功能)。計算機的組成不需要改變,但需要安裝不同的軟件(相當於不同程序)就實現了不同的功能,產生了這個想法,那人們就開始琢磨了,如何將這想法付諸於實踐,人們想到編寫代碼的確是一個好方法(這里可能有待考究,也可能是受到了圖靈機那個無限長的紙帶的啟發),那這樣的話,機器的結構肯定要面臨大的改變了,人們就開始爭論了,你說你的想法好,他說我的想法比較妙,還有到底是十進制阿,八進制,還是其它進制呢。這時候,印證了那句話:偉大的時代造就偉大的人物或偉大的人物造就偉大的時代,這個偉大的人物就是馮諾依曼,他提出來拋棄十進制,采用二進制作為數字計算機的數制基礎。同時他還強調了得預先編制計算機程序,然后由計算機來按照人們事先制定來完成數值計算。既然需要將程序寫到計算機里,那肯定得有地方放這個程序把,於是便又提出了一種叫做存儲器的概念,用於存放程序和數據用的。於是人們按照馮諾依曼所說的理論造出了電子計算機,人們稱這類計算機為馮諾依曼體系結構計算機(其實准確的還是稱之為馮諾依曼體系結構處理器CPU更為准確)
馮諾依曼結構處理器特點:
1. 必須有一個存儲器
2. 必須有一個控制器
3. 必須有一個運算器(算術運算+邏輯運算)
4. 必須有輸入與輸出設備
5. 最突出的一點,程序和數據在一個存儲區不分開,經由同一總線傳輸
馮諾依曼的主要貢獻就是提出並實現了“存儲程序”的概念,由於指令和數據都是二進制的,指令和操作數的地址又密切相關,因此當初想到的是將指令和數據共享同一存儲空間(數據與代碼區不作區分),且指令和數據共享同一總線,類似於下面這張圖:
指令和數據存儲為同一空間,因此具有相同的數據寬度
早期的計算機大多采用這種馮諾依曼結構,如X86等等。但馮諾依曼體系結構都存在同一存儲空間,由於共享同一總線,該計算機取指令與取數據不能同時進行,只有一個完成后再進行下一個,這顯然會降低程序運行的速度(網上的說法為訪存瓶頸),而且由於數據和程序都存放在同一存儲空間,可能會修改程序的執行順序,那就會引起死機(這個地方,死機問題還有待進一步理解,目前我也理解不夠不敢謬論)
鑒於馮諾依曼結構的不足,人們開始考慮是否可以提出一種新的結構來解決此問題,於是人們提出來了哈佛結構,哈佛結構是一種將程序指令存儲和數據存儲分開的存儲器結構,
CPU首先到程序指令存儲器中讀取程序指令內容(取指),解碼后得到數據地址(這里只是比喻,真正譯碼還需要區分是啥指令,是取數據指令才會去得到數據地址),然后執行,再到相應的數據存儲器讀取數據(訪存,這個步驟也不一定是訪問存儲器,也可能是寄存器),最后將相應的結果寫到通用寄存器(這里很容易忽視的,不是寫到存儲器),關於CPU這幾個步驟(現在也是按這個來划分幾級流水線),目前不扯太多了,后面有機會我拿個實際CPU設計咱們分個細節接着嘮嗑,非給整明白不可。回來繼續聊哈佛結構,這個結構將程序指令存儲和數據存儲分開,這可使得指令和數據有不同的數據寬度,這就可以充分利用計算資源了(想到這一點就很nice),附圖:
圖XX哈佛結構相比上面講到的馮諾依曼結構,明顯多了兩條總線,這解決了上面馮諾依曼結構的訪存瓶頸問題,不過它由於總線更為復雜,成本也就上升了(古人說有所得必有所失),由於這種哈佛結構取指令和取數據總線獨立,可同時進行,那么自然其處理能力和速度肯定很高了,所以當今的DSP和ARM家族,這里還有近年來興起的RISCV,大多采用此體系結構。講到現在,芯片中哈佛結構的運用,其實嚴格意義上來講應該算是一種改進型的哈佛結構,因為在其內部總線並沒有增加,像51是總線分時復用。現在的X86 CPU的內存RAM,指令和數據還是還是放在一起,沒有增加總線,還有現今的ARM處理器和X86 處理器一樣,RAM也就只有兩條總線,數據總線與地址總線並沒有像哈佛結構那樣,分成四條總線(數據存儲的地址總線,數據存儲的數據總線,程序存儲器的地址總線,程序存儲器的數據總線),但要注意的是,特別要注意一點,它們的CPU核中,也就是緩存的cache中還是區分了指令緩存(I-cache)和數據緩存(D-cache),所以最終執行的時候,指令和數據還都是從不同地方取出的,所以可以這么來說,CPU的外部為馮諾依曼模型,而CPU內部采用的是哈佛結構,兩個Cache(緩存)獨立,可以同時訪問數據和指令,也就是實現了哈佛結構的功能,這種二者合一的稱之為改進型的哈佛結構,附圖:
至於為什么要設計改進型的哈佛結構呢,因為原來馮諾依曼結構雖然執行效率不高,但其總線結構簡單,成本也低,而哈佛結構其總線復雜,成本高,效率也高,於是結合兩者長處,但又為了降低成本,於是就有了今天的珠聯璧合。另外,值得一說的是,CPU也難以完全采用哈佛結構,原因在於哈佛結構總線過於復雜導致對CPU來說不適應存儲器的擴展,而對微處理器MCU來說則不一樣,它是集成化了的,存儲器都已集成好了,很少會擴展,所以它可能會采用全哈佛,但其成本又限制了這個,所以其大多也采用改進型的哈佛結構。
最后總結一下,哈佛結構和馮諾依曼結構都是一種存儲器結構(這里肯定不是指的物理結構,形象意義上的邏輯結構),哈佛結構是將指令存儲器和數據存儲器分開的一種存儲器結構(代碼與數據獨立編址),而馮諾依曼結構則是將指令存儲器和數據存儲器合在一起的存儲器結構(代碼與數據統一編址)
前面說了哈佛和馮諾依曼結構,接下來我們再來說下架構,說到架構,我們就來說一哈,RISC和CISC。英文注釋,RISC和CISC都是一種指令集的設計,早期是沒有像今天這樣區分CISC和RISC的,RISC也是后來才出現的。在早期的計算機中,編譯器還沒出現,程序都是以機器語言或匯編語言來完成的(像現在很多高級語言都是依賴於編譯器,但這在早期根本就沒有),當時的看法是硬件比編譯器更容易設計,於是工程師們設計了很復雜的硬件,但都是基於復雜的指令的,這些復雜的指令可以直接陳述高級的功能,比如乘加,乘減,就一條指令就搞定,這當然給編程人員帶來了極大的便利,另一個加速復雜化的原因是缺乏大的內存,當時的內存每一個字節都非常珍貴,因此促使這種復雜編碼,長度不等的執行多個操作的復雜指令的誕生,即CISC(Comlex Instruction Set Computer)。早期的X86,C51都是CISC,其指令集很豐富,使得編譯器只做很少的事情(基本不做事情),這樣會使得設計的程序指令數很少,所占的內存也就很少了。
但發展就是這樣,從來沒有一個最好的,只有更好的或者更適合的,人們在研究指令系統合理性的時候發現不能在這么下去了,指令的復雜導致硬件設計也變得更加復雜,也會使得集成和功耗都很難得到進一步的發展,而且也會使得指令過於冗余。於是人們想設計一個新的指令系統來解決這種問題,鐺鐺鐺,這時RISC就誕生了。
RISC既然登場了,就有必要介紹一下,它是如何解決上述問題的,首先它對指令做了精簡,究竟是去掉哪些復雜指令,或者留下哪些呢,這里肯定有個取舍的問題,這時就聯想到了二八原則,實際程序設計中大多只會用到20%的指令,剩下的幾乎很少用到。於是就將這20%的指令作為了精簡下來的指令,而且使這些指令具有同等大小的字節長度,只留下了很少的復雜指令(也是常用的),對於一些不常用的復雜指令采用將多個指令拼湊方式實現(比如前面提到的乘加,原先是一個指令現在可能就拆分成乘法和加法兩個指令進行實現)。這種改變之下對編譯器的要求就高了,對於一個復雜指令,得學會去翻譯成多個指令,另外,由於翻譯的指令多了,這樣也會使得程序變得大了,相應的就會占用CPU更多的內存空間,CPU對內存的訪問也會更多,這也會使得計算機的執行效率打個折扣。針對這以上問題,人們采用了增加寄存器的方法,當然相當於增加了額外的存儲空間(內存),只有載入和存儲指令可以訪問內存,數據處理指令只對寄存器進行操作。
講到RISC指令系統的另一個優勢,就是它本身指令長度一致,指令長度一致的指令執行所需要的機器周期相同,很好降低了指令設計成流水線的復雜度,非常適合搞並行計算。
最后總結下,CISC架構指令雖然復雜,但其很明顯程序執行的速度更快,就是比較費材,而且由於老牌CPU廠商Intel等,早就采用了CISC,為了考慮向下兼容,也不得不在現有的CPU中采用CISC,而RISC則沒有太多歷史包袱,不用考慮向下兼容,所以其設計可以很簡單放的開,不過目前CISC和RISC正在走向融合,正如前面介紹的哈佛與馮諾依曼那樣。Pentitum(Intel 的奔騰系列)是一個例子,它們的CPU內核是基於RISC的,但是它們也能識別CISC,可將其分解為RISC指令指令,這也挺有意思了。