詳解嵌入式系統(tǒng)Boot-Loader

上電之后(bootload階段)該做什么


1怠缸、第一行程序

拿到空PCB板之后睁蕾,硬件工程師首先會(huì)測(cè)試各主要線路是否通連秕狰,各焊點(diǎn)是否有空焊帘皿、斷接或短路的情況东跪,然后逐個(gè)模塊焊接上去。之后需要驗(yàn)證系統(tǒng)上電之后鹰溜,CPU與各組件的供電電壓是否正常虽填,供給CPU的震蕩電路能否能夠正常起振,外部存儲(chǔ)器能否正常讀寫曹动。當(dāng)把我們的程序用JTAG工具下載到板子上后斋日,在真正調(diào)試系統(tǒng)前需要做好以下檢查:

  • 利用調(diào)試工具,在程序的第一行設(shè)定斷點(diǎn)墓陈,確定程序有停下來(lái)恶守;
  • 檢查CPU的程序計(jì)數(shù)器PC是否正確;
  • 檢查CPU內(nèi)部RAM的內(nèi)容和我們下載的可執(zhí)行文件是否相同贡必;
  • 程序的第一行命令為設(shè)定CPU狀態(tài)寄存器兔港,并觀察CPU的狀態(tài)寄存器是否如預(yù)期改變;
  • 繼續(xù)單步執(zhí)行仔拟,確認(rèn)PC寄存器是否會(huì)跟著改變衫樊,且每行命令的執(zhí)行結(jié)果都是正確的。

檢查完以上各項(xiàng)后利花,只能證明板子上的電源電路以及CPU是正常的橡伞,接下來(lái)要繼續(xù)驗(yàn)證CPU與外圍設(shè)備盒揉,確認(rèn)板子的正確性與穩(wěn)定性后,才能進(jìn)行下一步測(cè)試兑徘。


2刚盈、基本硬件測(cè)試

既然Boot-Loader的責(zé)任是幫其它程序布置可運(yùn)行的環(huán)境,那么就要做好以下驗(yàn)證:

  • CPU寄存器(狀態(tài)寄存器挂脑、通用寄存器藕漱、內(nèi)存映射寄存器)操作測(cè)試;
// 設(shè)定SP(Stack Point)寄存器
//
asm("xld.w  %r15, 0x2000");
asm("ld.w %sp, %r15");

// 設(shè)定CPU的狀態(tài)寄存器
//
asm("xld.w  %r15, 0x200010");
asm("ld.w   %psr, %r15");

// 將寄存器0x300023的bit 1設(shè)為1
*(volatile unsigned char *)0x300023 |= 0x2;
  • Stack Pointer的設(shè)置是否正確崭闲?函數(shù)調(diào)用是否正確運(yùn)行肋联?
  • 中斷是量表設(shè)置是否正確?中斷矢量程序是否正常運(yùn)行?
  • 存儲(chǔ)器初始化及其操作測(cè)試刁俭,保證所有的存儲(chǔ)器都可以正常讀寫橄仍;
  • 將數(shù)據(jù)段載入RAM,對(duì)bss段設(shè)定初值牍戚,并將需要在RAM中運(yùn)行的程序載入到RAM侮繁。保證當(dāng)主程序執(zhí)行起來(lái)后,全局變量的初始值都是正確的如孝。

只有確保以上測(cè)試通過(guò)后才能進(jìn)行下一步工作宪哩。


(1)確認(rèn)函數(shù)調(diào)用能否正常運(yùn)行

正確設(shè)置堆棧(Stack)是函數(shù)能否成功調(diào)用的前提,在嵌入式系統(tǒng)開(kāi)發(fā)時(shí)第晰,系統(tǒng)要自行管理堆棧锁孟,如果管理不當(dāng),可能會(huì)發(fā)生函數(shù)調(diào)用或調(diào)用幾層之后就死機(jī)的狀況茁瘦。因?yàn)镃語(yǔ)言利用堆棧完成以下事項(xiàng):

  • 存儲(chǔ)函數(shù)返回地址品抽;
  • 函數(shù)調(diào)用時(shí)的參數(shù)傳遞(參數(shù)較多時(shí));
  • 存儲(chǔ)函數(shù)內(nèi)部的局部變量甜熔;
  • 中斷服務(wù)程序執(zhí)行時(shí)(發(fā)生中斷時(shí))圆恤,存儲(chǔ)CPU當(dāng)前狀態(tài)及返回地址。

堆棧頂點(diǎn)地址(Stack Point)的配置是一件很重要的事纺非,但卻極易被人忽略哑了。主要是在Windows或Linux上編程時(shí),操作系統(tǒng)在產(chǎn)生可執(zhí)行文件時(shí)烧颖,linker會(huì)自動(dòng)幫程序加上一段Startup Code弱左,其中就包含了Stack存儲(chǔ)器的配置。但在無(wú)操作系統(tǒng)的嵌入式系統(tǒng)中炕淮,調(diào)用任何函數(shù)之前都要先為其設(shè)置好堆棽鸹穑空間(Stack Point)。

當(dāng)用C語(yǔ)言調(diào)用了一個(gè)函數(shù),例如fun(a,b)们镜,編譯后的機(jī)器碼應(yīng)該包含以下動(dòng)作:

  • 執(zhí)行指令push彻坛,將參數(shù)a和b存入Stack兑燥,同時(shí)堆棧指針SP減一足陨;
  • 將當(dāng)前程序計(jì)數(shù)寄存器PC的值(也即返回地址:函數(shù)調(diào)用指令的下一條指令地址)存到堆棧中叫乌;
  • 執(zhí)行指令Call,把PC的值設(shè)為函數(shù)fun()的地址嚼鹉,下一個(gè)被執(zhí)行的指令就是函數(shù)的第一條命令贩汉。
  • 當(dāng)函數(shù)fun執(zhí)行時(shí),可利用當(dāng)前SP的值計(jì)算出參數(shù)a和b的地址锚赤;
  • 如果函數(shù)內(nèi)部有局部變量匹舞,則依次將這些變量存到堆棧中。所以在嵌入式開(kāi)發(fā)中盡量不要定義size太大的變量线脚,否則有棧溢出(Stack Overflow)的風(fēng)險(xiǎn)赐稽。
  • 當(dāng)函數(shù)執(zhí)行完畢,CPU會(huì)執(zhí)行ret命令浑侥,該命令會(huì)從Stack頂層取出返回地址姊舵,然后賦值給PC寄存器,則下個(gè)指令就會(huì)執(zhí)行函數(shù)后面的下一行指令锭吨,從而完成函數(shù)的調(diào)用蠢莺。

如果SP寄存器沒(méi)有設(shè)定到正確的地址寒匙,或是沒(méi)有配置足夠大的存儲(chǔ)區(qū)域作為椓闳纾空間,那么在調(diào)用函數(shù)時(shí)很可能就會(huì)出錯(cuò)锄弱。下圖就是一個(gè)椏祭伲空間溢出,破壞程序數(shù)據(jù)段的例子:

局部變量太大導(dǎo)致Stack Overflow

為避免以上情況的發(fā)生会宪,一般會(huì)選擇某塊RAM 的頂端(最大地址)當(dāng)作SP寄存器的初值肖卧,但具體棧的大小定位多少合適要根據(jù)具體軟硬件環(huán)境和項(xiàng)目要求。一般采用的方法是掸鹅,剛開(kāi)始稍微定義大一點(diǎn)塞帐,例如2KB-4KB左右,然后讓測(cè)試人員運(yùn)行完系統(tǒng)所有功能(函數(shù))后巍沙,記錄下SP在每次函數(shù)調(diào)用后的最小值葵姥,它與棧頂?shù)刂返牟罹褪撬枳钚?臻g句携,一般會(huì)稍微再放一點(diǎn)榔幸。


(2)確認(rèn)中斷系統(tǒng)能否正常運(yùn)行

負(fù)責(zé)寫驅(qū)動(dòng)程序的工程師要將中斷服務(wù)程序的地址填入中斷矢量表,并必須保證當(dāng)驅(qū)動(dòng)程序被執(zhí)行時(shí),中斷系統(tǒng)是正常的削咆。一般來(lái)說(shuō)主要做好以下工作:

  • 中斷矢量表數(shù)組牍疏,詳細(xì)注解每個(gè)entry代表的中斷源;
  • 如果是外接中斷控制器拨齐,要先完成中斷控制器的驅(qū)動(dòng)程序鳞陨,才能開(kāi)始中斷系統(tǒng)的測(cè)試。
  • 設(shè)定CPU的中斷矢量表地址寄存器(有些CPU無(wú)中斷矢量表地址寄存器瞻惋,但它會(huì)指定某個(gè)固定地址為中斷矢量表的地址)
  • 設(shè)定CPU的中斷控制寄存器(優(yōu)先級(jí)炊邦、中斷允許位等)
  • 確定中斷被觸發(fā)后,對(duì)應(yīng)的ISR會(huì)被執(zhí)行熟史。
  • 提供ISR的范例馁害,讓ISR編寫者不用知道中斷系統(tǒng)的細(xì)節(jié)。
// ISR模板
//
void isr_template(void)
{
    // 將所有通用目的寄存器存到堆棧
    //
    asm("pushn %r15"); /*將r0 - r15 都存到堆棧中 */
    
    //將ALR與AHR寄存器通過(guò)r1存到堆棧
    //你無(wú)需搞清ALR和AHR是什么寄存器蹂匹,不同的CPU有不同的寄存器需要存儲(chǔ)
    //
    asm("ld.w   %r1, %alr");
    asm("ld.w   %r0, %ahr");
    asm("pushn  %r1");
    
    //調(diào)用C語(yǔ)言函數(shù)your_ISR碘菜,即真正ISR要處理的事寫在該函數(shù)里就行
    //
    asm("xcall your_ISR");
    
    //從堆棧中取回被調(diào)用時(shí)的ALR和AHR寄存器的值
    //
    asm("popn   %r1");
    asm("ld.w   %alr, %r1");
    asm("ld.w   %ahr, %r0");
    
    //從堆棧中取回r1 - r15的值
    //
    asm("popn   %r15");
    
    //執(zhí)行中斷返回指令,返回被中斷的程序
    //
    asm("reti");
}

在以上各環(huán)節(jié)中容易出錯(cuò)的地方有:

  • 中斷優(yōu)先級(jí)寄存器沒(méi)設(shè)正確限寞;
  • 中斷矢量表中各個(gè)entry與中斷源的對(duì)應(yīng)關(guān)系錯(cuò)誤忍啸;
  • 中斷矢量表地址設(shè)置錯(cuò)誤,很多CPU會(huì)要求中斷矢量表的地址要設(shè)置在偶數(shù)地址或是4的倍數(shù)履植,甚至是128KB的倍數(shù)计雌。

那如何判斷ISR有沒(méi)有被正確執(zhí)行呢?一般的方法是選擇一個(gè)簡(jiǎn)單的中斷源(例如除0錯(cuò)誤中斷)玫霎,在其ISR中設(shè)定一個(gè)斷點(diǎn)凿滤,然后單步執(zhí)行,看能否順利執(zhí)行ISR程序及正確返回中斷發(fā)生的地方(除零指令的下一條語(yǔ)句)庶近。

(3)存儲(chǔ)器測(cè)試

存儲(chǔ)器出問(wèn)題的地方有:

  • 硬件方面:數(shù)據(jù)線翁脆、地址線連接錯(cuò)誤;

  • 軟件方面:SRAM鼻种、NOR Flash反番、ROM不需要額外電路,直接可以使用叉钥,但SDRAM則還需要額外的SDRAM Controler電路才能使用罢缸,程序必須先設(shè)定好SDRAM Controler的配置(SDRAM大小、速度等)投队;

  • 外部存儲(chǔ)器的時(shí)序設(shè)置枫疆,若時(shí)序設(shè)定太快,系統(tǒng)會(huì)不穩(wěn)定蛾洛,太慢养铸,則系統(tǒng)性能變差雁芙。一般CPU的Timing設(shè)定表會(huì)說(shuō)明應(yīng)該如何設(shè)定。

  • 在進(jìn)行下部工作前要先測(cè)試存儲(chǔ)器的每一個(gè)Byte钞螟,確保讀寫(如果可以寫入的話)正常兔甘。方法是對(duì)每一個(gè)字節(jié)依次寫入0x00、0xFF鳞滨、0x55洞焙、0xAA,確保每一位都會(huì)被寫入0與1拯啦。

  • int SRAM_testing(void)
    {
        int i,counter =0;
        //待測(cè)RAM起始地址為0x2000000,大小為2MB.
        unsigned char *pointer = (unsigned char *)0x2000000;
        unsigned char data[4]={0x00,0xFF,0x55,0xAA};
        
        for(i=0; i<4; i++)
        {    // 逐一對(duì)每個(gè)字節(jié)寫入某特殊值
            for(j=0; j<(8*1024*1024); j++)
                pointer[i] = data[i] 
             // 逐一讀出每個(gè)字節(jié)澡匪,判斷寫入的值是否正確      
            for(j=0; j<(8*1024*1024); j++)
                pointer[i]==data[i]?::counter++;
        }      
        return counter; //返回出錯(cuò)字節(jié)的個(gè)數(shù)  
    }
    
  • 對(duì)于只讀ROM,如何驗(yàn)證燒錄到存儲(chǔ)器中的數(shù)據(jù)和原始映像文件一致呢褒链?一般會(huì)采用校驗(yàn)和檢驗(yàn)法唁情。即分別計(jì)算原始映像文件和燒錄到ROM中文件的校驗(yàn)和是否相等。

  • /***************************************************************
    Function Name: calculate_ROM_checksum
    Function Purpuse:計(jì)算起始地址為0x2000000甫匹,size為8MB存儲(chǔ)器的校驗(yàn)和
    ****************************************************************/
    unsigned long calculate_ROM_checksum(void)
    {
        unsigned long checksum = 0;
        unsigned char *pointer = 0x2000000;
        for(i=0; i<(8*1024*1024); i++)
            checksum += pointer[i];
        return checksum;
    }
    

(4)CPU初始化

在Boot-Loader階段因該做好以下CPU相關(guān)的設(shè)定:

  • 設(shè)定堆棧指針寄存器SP甸鸟;
  • 設(shè)定狀態(tài)寄存器,禁止中斷兵迅;
  • 設(shè)定中斷矢量表指針抢韭;
  • 設(shè)定CPU執(zhí)行狀態(tài)(時(shí)鐘時(shí)序);
  • 設(shè)定存儲(chǔ)器控制器(如果用到了類似SDRAM的存儲(chǔ)器)恍箭;
  • 設(shè)定CPU操作各存儲(chǔ)器的時(shí)序刻恭;
  • 設(shè)定CPU的PIN腳功能;
  • 初始化外圍設(shè)備(LCD Controler扯夭、USB Controler鳍贾、SD卡接口等)

3、載入程序段與數(shù)據(jù)初始化

(1)載入data段

有初值的全局變量必須被存儲(chǔ)在可執(zhí)行文件中勉抓、被燒錄到ROM里贾漏。但執(zhí)行時(shí)因?yàn)檫@些全局變量的值會(huì)被改變候学,所以當(dāng)然不能在ROM里運(yùn)行藕筋,連接時(shí)必須尋址到RAM中。正因?yàn)檫@種 “存儲(chǔ)在ROM梳码,運(yùn)行在RAM” 的特性隐圾,才有傳輸data段的需要,且必須在所有程序使用全局變量前完成這些事掰茶。

執(zhí)行時(shí)期的存儲(chǔ)器使用狀況

上圖中暇藏,data段的內(nèi)容原本在可執(zhí)行文件中的rodata段之后,但執(zhí)行時(shí)濒蒋,需要將data段復(fù)制到RAM中的bss段之后盐碱。連接腳本如下:

.data __END_bss : AT(__END_rodata)
{
    __START_data = .;
    *(.data);
    __END_data = .;
    
    // 定義可在程序中使用的變量“__START_data_LMA”,表示data段的存儲(chǔ)起始地址LMA
    __START_data_LMA = LOADADDR(.data);
    
    //定義可在程序中使用的變量“__SIZE_DATA”,表示data段的大小
    __SIZE_DATA = __END_data - __START_data;
}

傳輸程序如下:

/**************************************************
Function Name: copy_data_section()
Function Purpuse:將可執(zhí)行文件中的數(shù)據(jù)段復(fù)制到內(nèi)存中
***************************************************/
extern unsigned long *__START_data;
extern unsigned long *__START_data_LMA;
extern int __SIZE_DATA;

void copy_data_section(void)
{
   int i;
   unsigned long *dest = __START_data;
   unsigned long *src = __START_data_LMA;
   //假設(shè)data段的大小是4的整數(shù)倍個(gè)字節(jié)
   for(i=0; i<(__SIZE_DATA/4); i++)
       dest[i] = src[i];    
}

(2)設(shè)定bss段

bss段的設(shè)定較為簡(jiǎn)單把兔,因?yàn)閎ss段里的成員都是沒(méi)有初始值的全局變量,所有根本不需要存儲(chǔ)空間瓮顽,在執(zhí)行時(shí)只要把bss段的執(zhí)行空間(VMA)都設(shè)為0即可县好。

/*******************************************
定義bss段,起始地址(VMA)從0開(kāi)始
******************************************/
.bss 0x0 : 
{
    __START_bss = .;
    *(.bss);
    __END_bss = .;
    
    //定義可在程序中使用的變量:__SIZE_BSS
    __SIZE_BSS = __END_bss - __START_bss;
}

設(shè)定bss段為0的代碼如下:

/**************************************************
Function Name: clear_bss_section()
Function Purpuse:將bss段清零
***************************************************/
extern unsigned long * __START_bss;
extern int __START_BSS;

void clear_bss_section(void)
{
    int i;
    unsigned long * dest = __START_bss;
    //假設(shè)bss段的大小為4的整數(shù)倍字節(jié)大小
    for(i=0; i<(__SIZE_BSS/4); i++)
        dest[i] = 0;
}

Attention:在boot階段暖混,data段和bss段一定要先設(shè)定缕贡,否則執(zhí)行期間全局變量的值就不正確。換句話說(shuō)拣播,在設(shè)定完data和bss段之前晾咪,boot-load程序是不能使用全局變量的,如果一定要使用贮配,那就避免在定義全局變量時(shí)賦值谍倦,一定要在程序內(nèi)明確賦值才行。例如:

<img src="https://cdn.jsdelivr.net/gh/Leon1023/leon_pics/img/20201125224022.png" alt="Boot-Loader程序使用全局變量時(shí)必須謹(jǐn)慎" style="zoom:80%;" />

(3)載入text段

當(dāng)某個(gè)系統(tǒng)程序或者應(yīng)用程序模塊需要較高的執(zhí)行速度時(shí)泪勒,往往可以將他們復(fù)制到系統(tǒng)內(nèi)存中執(zhí)行剂跟。但系統(tǒng)內(nèi)存往往空間有限,不可能同時(shí)全部加載進(jìn)去酣藻。所以我們一般會(huì)寫一個(gè)函數(shù)曹洽,并尋址到同一個(gè)地址,在需要時(shí)才做載入的動(dòng)作辽剧。

各種類型的存儲(chǔ)器性能由大至小分別為:CPU寄存器送淆、CPU cache、CPU內(nèi)部RAM怕轿、外部SRAM偷崩、NOR Flash、SDRAM撞羽、Mask ROM阐斜、NAND Flash。

NAND Flash:價(jià)格低诀紊,容量大谒出,可把其想象成類似硬盤的設(shè)備,只不過(guò)無(wú)法直接尋址操作邻奠,程序無(wú)法再上面直接執(zhí)行笤喳;

NOR Flash:價(jià)格高,容量小碌宴,但讀數(shù)據(jù)快杀狡,可把其想象成可重復(fù)寫的ROM,程序可在上面直接運(yùn)行贰镣。

Mask ROM:成本高呜象,容量有限膳凝,但程序可直接在上面運(yùn)行;

SDRAM:性價(jià)比高恭陡,一般作為系統(tǒng)的外置內(nèi)存鸠项,程序可直接在上面運(yùn)行;

SRAM:價(jià)格昂貴子姜,容量小祟绊,一般作為系統(tǒng)的內(nèi)置內(nèi)存,程序可在上面直接運(yùn)行哥捕。

(4)幾種系統(tǒng)存儲(chǔ)器架構(gòu)

  • 從NAND Flash啟動(dòng)的架構(gòu):

  • image-20201125230828425
  • 啟動(dòng)流程為

    • 上電后牧抽,CPU內(nèi)置程序會(huì)從NAND Flash的特定地址(一般是第一個(gè)block塊地址)讀出Boot-Loader程序到CPU的內(nèi)部?jī)?nèi)存中。
    • CPU將控制權(quán)交給內(nèi)部存儲(chǔ)器中的Boot-Loader遥赚;
    • Boot-Loader初始化SDRAM扬舒,再?gòu)腘AND Flash中將主程序載入到SDRAM中;
    • Boot-Loader將控制權(quán)交給主程序凫佛。

    獲取更多知識(shí)讲坎,請(qǐng)點(diǎn)擊關(guān)注:
    嵌入式Linux&ARM
    CSDN博客
    簡(jiǎn)書博客
    知乎專欄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市愧薛,隨后出現(xiàn)的幾起案子晨炕,更是在濱河造成了極大的恐慌,老刑警劉巖毫炉,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓮栗,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡瞄勾,警方通過(guò)查閱死者的電腦和手機(jī)费奸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)进陡,“玉大人愿阐,你說(shuō)我怎么就攤上這事≈壕危” “怎么了缨历?”我有些...
    開(kāi)封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)盗蟆。 經(jīng)常有香客問(wèn)我戈二,道長(zhǎng),這世上最難降的妖魔是什么喳资? 我笑而不...
    開(kāi)封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮腾供,結(jié)果婚禮上仆邓,老公的妹妹穿的比我還像新娘鲜滩。我一直安慰自己,他們只是感情好节值,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布徙硅。 她就那樣靜靜地躺著,像睡著了一般搞疗。 火紅的嫁衣襯著肌膚如雪嗓蘑。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天匿乃,我揣著相機(jī)與錄音桩皿,去河邊找鬼。 笑死幢炸,一個(gè)胖子當(dāng)著我的面吹牛泄隔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宛徊,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼佛嬉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了闸天?” 一聲冷哼從身側(cè)響起暖呕,我...
    開(kāi)封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎苞氮,沒(méi)想到半個(gè)月后缰揪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡葱淳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年钝腺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赞厕。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡艳狐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出皿桑,到底是詐尸還是另有隱情毫目,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布诲侮,位于F島的核電站镀虐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏沟绪。R本人自食惡果不足惜刮便,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绽慈。 院中可真熱鬧恨旱,春花似錦辈毯、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至仪芒,卻和暖如春唁影,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掂名。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工据沈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铆隘。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓卓舵,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親膀钠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掏湾,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容