女人被狂躁到高潮视频免费无遮挡,内射人妻骚骚骚,免费人成小说在线观看网站,九九影院午夜理论片少妇,免费av永久免费网址

當前位置:首頁 > 汽車電子1 > 糖果Autosar
[導讀]禮拜三接到一個學弟的問題,學弟在實習,說有個很奇葩的bug解決不了,我說你描述一下吧大概就是利用spi命令向flash里的某個地址寫入數(shù)據(jù),boot之后bootloader從flash的該地址里讀數(shù)據(jù),但是現(xiàn)在的問題是,偶爾讀出來的數(shù)據(jù)不對,貌似是數(shù)據(jù)沒有寫進去,該問題目前只出現(xiàn)...


禮拜三接到一個學弟的問題,學弟在實習,說有個很奇葩的bug解決不了,我說你描述一下吧


大概就是利用spi命令向flash里的某個地址寫入數(shù)據(jù),boot之后bootloader從flash的該地址里讀數(shù)據(jù),但是現(xiàn)在的問題是,偶爾讀出來的數(shù)據(jù)不對,貌似是數(shù)據(jù)沒有寫進去,該問題目前只出現(xiàn)了三次,再次復現(xiàn)不太好整


遇見這種問題,也沒太好的辦法,我讓他先單步調試,看看write的時候,spi的接口發(fā)回來的status是ok還是error


調了大概十來次,都是ok,好,基本可以排除硬件本身的問題了,接口是直接用的cubemx的,應該也不會有問題


那么會是神馬問題呢?我自己也很納悶,按說如果硬件本身沒問題,接口是對的,數(shù)據(jù)的寫入沒有理由不成功


我問寫入和讀取的請求是怎么調用的,學弟說代碼沒法全部發(fā)給我看,我說懂的,那你就給我說說架構方面是怎么設計的


學弟語音加屏幕繪圖操作一頓,我大概明白了,于是我自己畫了一幅圖:




學弟還給我發(fā)來了文檔的鏈接,我一看,用的是keil lib的接口:


Signal Events


以及


Mail Queue


我和學弟確認之后的偽碼如下:


#define WRITE_REQUEST       0
#define READ_REQUEST        1
#define WRITE_SIGNAL        0x01
#define READ_SIGNAL         0x02
osMailQId  mail;


// Write reuqest
void write_request (void) {
T_MEAS *mptr;

mptr = osMailAlloc(mail, osWaitForever); // Allocate memory
mptr->info = WRITE_REQUEST;
osMailPut(mail, mptr); // Send Mail
osSignalWait(WRITE_SIGNAL,TIMEOUT);
/*******
Do something
********/

osMailFree(mail, mptr); // free memory allocated for mail
osThreadYield(); // Cooperative multitasking
}

// Read reuqest
void read_request (void) {
T_MEAS *mptr;

mptr = osMailAlloc(mail, osWaitForever); // Allocate memory
mptr->info = READ_REQUEST;
osMailPut(mail, mptr); // Send Mail
osSignalWait(READ_SIGNAL,TIMEOUT);

/*******
Do something
********/

osMailFree(mail, mptr); // Delete the request from the message queue
osThreadYield(); // Cooperative multitasking
}


//Message Queue
void message_queue_thread (void) {
T_MEAS  *rptr;
osEvent  evt;

for (;;) {
evt = osMailGet(mail, osWaitForever); // wait for mail
if (evt.status == osEventMail) {
if (evt.info == WRITE_REQUEST)
{
/********
Write data to the flash
*********/

if(write succeed)
{
osSignalSet(thread_id, WRITE_SIGNAL); //Send write signal
}
}

if (evt.info == READ_REQUEST)
{
/********
Read data to the flash
*********/

if(read succeed)
{
osSignalSet(thread_id, READ_SIGNAL); //Send write signal
}
}
}
}
}


看著貌似沒有什么問題,總共三個函數(shù),兩個發(fā)請求,一個處理請求,發(fā)送請求的函數(shù)向請求隊列即message queue存儲一個請求,處理請求的函數(shù)負責接收和處理該請求,處理結束以后向發(fā)送請求的線程發(fā)送一個信號量,發(fā)送請求的線程從阻塞處,即osSignalWait處繼續(xù)向下運行,從請求隊列里free掉該請求


那么問題來了,請求是從哪里free掉的呢?


這其實是一個典型的生產(chǎn)消費者模型,發(fā)送讀和寫請求的線程皆為生產(chǎn)者,處理請求的線程為消費者,但是現(xiàn)在,從請求隊列里remove掉請求的操作被生產(chǎn)者自己執(zhí)行了,而根據(jù)經(jīng)典理論,這個操作的執(zhí)行權,應該屬于消費者,即處理請求的線程


我和學弟說了大概我的意思,學弟表示,可是從邏輯上看似乎這么些也沒有問題,我說,沒關系,咱們現(xiàn)在來設想一種race condition:




你看,如果你先發(fā)送的是寫請求,緊隨其后跟了一個讀請求,而在處理線程里,讀請求的完成快于寫請求,也就是雖然寫請求的發(fā)送早于讀請求,但是讀請求的完成早于寫請求,讀請求被消息隊列free掉也早于寫請求,這會導致兩種情況:


  1. 你的寫請求壓根還沒完成,讀請求就完成了,被消息隊列處理并被讀請求自己free了,等于讀了個寂寞,那么你不可能讀到寫進去的數(shù)據(jù)


  2. 因為我們并不知道keil接口的具體實現(xiàn),庫是以庫文件的形式呈現(xiàn)的,你看不到代碼,如果這個osMailFree相當于queue的pop,應該彈出第一個元素,可生產(chǎn)者自己free掉自己的請求時無法保證該請求的指針指向的是第一個元素,那么有可能造成未知的指針問題,這更為嚴重,有潛在的內(nèi)存泄露可能


針對這種問題我的方案是這樣的:


#define WRITE_REQUEST       0
#define READ_REQUEST        1
#define WRITE_SIGNAL        0x01
#define READ_SIGNAL         0x02
#define FINISH_SIGNAL       0x03
osMailQId  mail;


// Write reuqest
void write_request (void) {
T_MEAS *mptr;

mptr = osMailAlloc(mail, osWaitForever); // Allocate memory
mptr->info = WRITE_REQUEST;
osMailPut(mail, mptr); // Send Mail
osDelay(10);
osSignalWait(WRITE_SIGNAL,TIMEOUT);

/*******
Do something
********/


osSignalSet(thread_id, FINISH_SIGNAL); // free memory allocated for mail
osThreadYield(); // Cooperative multitasking
}

// Read reuqest
void read_request (void) {
T_MEAS *mptr;

mptr = osMailAlloc(mail, osWaitForever); // Allocate memory
mptr->info = READ_REQUEST;
osMailPut(mail, mptr); // Send Mail
osDelay(10);
osSignalWait(READ_SIGNAL,TIMEOUT);

/*******
Do something
********/

osDelay(10);
osSignalSet(thread_id, FINISH_SIGNAL);
osThreadYield(); // Cooperative multitasking
}


//Message Queue
void message_queue_thread (void) {
T_MEAS  *rptr;
osEvent  evt;

for (;;) {
evt = osMailGet(mail, osWaitForever); // wait for mail
if (evt.status == osEventMail) {
if (evt.info == WRITE_REQUEST)
{
/********
Write data to the flash
*********/

if(write succeed)
{
osSignalSet(thread_id, WRITE_SIGNAL); //Send write signal
}
}

if (evt.info == READ_REQUEST)
{
/********
Read data to the flash
*********/

if(read succeed)
{
osSignalSet(thread_id, READ_SIGNAL); //Send write signal
}
}
osDelay(10);
osSignalWait(FINISH_SIGNAL,TIMEOUT);
osMailFree(mail, evt);
}
}
}


核心思想就是最簡單的,讓生產(chǎn)者負責生產(chǎn),由消費者負責消費,避免他們之間串線,才能有效保證任務按照正確的順序運行,osDelay不能夠省略,否則可能造成經(jīng)典的“你丫先把手撒開”“你TM先撒開我再撒開”的死鎖問題


希望學弟調試順利,對于不能一直復現(xiàn)的問題,其實也很難看到直觀的效果,如果以后沒再出現(xiàn)相應的問題,就當他解決了吧



本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。

糖果Autosar

96 篇文章

關注

發(fā)布文章

編輯精選

技術子站

關閉