2014-10-09 95 views
0

我模擬一個設備,它將接收數據字節並在時鐘有下降沿時寫入寄存器。我已經創建了一個單獨的pthread,它將考慮將時鐘從高位移到低位。C:使用pthreads和程序不退出for循環

現在我的問題是,在主線程我有控制檯要求用戶鍵入一個十六進制值寫入「設備」,然後它調用一個SendCommand(uint32_t addr,uint16_t數據)函數來做到這一點。由於它應該每個時鐘週期一次發送一個位,所以我把它放在一個for循環中。這裏是send命令功能:

void SendCmd(uint32_t loadAddr, uint16_t data) 
{ 
    dest = &loadAddr; 
    int i; 
    printf("%d\n\n",status); 
    for(i=15; i>=0; --i) { 
     pthread_cond_wait(&rising_edge, &data_lock); 
     *dest = (*dest << 1)|(data & 0x8000) >> 15; 
       //  ^^^^^^^^ get MSB 
       //    ^^^^^ move the MSB down to the LSB, assuming the 
       //      peripheral wants the bit in the LSB. 
     pthread_cond_wait(&falling_edge, &data_lock); 
     data <<= 1; 
     printf("%d\ti=%d\n",*dest,i); 
    } 
    pthread_mutex_unlock(&data_lock); 
    status = ENABLED_IDLE; 
} 

i = 0時,該循環應該退出並返回到主函數,其中它會要求用戶輸入其他十六進制值。但它沒有,我似乎無法找到爲什麼它退出循環之前會卡住。

編輯:凍結實際發生之前函數執行過:

int main() 
{ 
    State status = DISABLED; 
    Clock clk = LOW; 
    int exit_flag = 0; 
    char Command[20]; 
    pthread_t clk_t; 
    pthread_cond_init(&en_sig, NULL); 
    pthread_cond_init(&rising_edge, NULL); 
    pthread_cond_init(&falling_edge, NULL); 
    pthread_mutex_init(&clk_lock, NULL); 
    pthread_mutex_init(&data_lock, NULL); 
    pthread_create(&clk_t, NULL, simClk, NULL); 
    while(!exit_flag) 
    { 
     if(status != ENABLED_ACTIVE) 
     { 
      fputs("(enable/disable/write [addr] [word_0] [word_1*]/quit): ", stdout); 
      fflush(stdout); 
      if (fgets(Command, sizeof Command, stdin) != NULL) 
      { 
       char *newline = strchr(Command, '\n'); 
       if (newline != NULL) 
       { 
        *newline = '\0'; 
       } 
      } 

      if(strcasecmp(Command,"quit")==0) 
      { 
       printf("\nShutting Down!\n\n"); 
       pthread_cancel(&clk_t); 
       pthread_mutex_destroy(&clk_lock); 
       exit_flag = ~exit_flag; 
       continue; 
      } 

      if(strcasecmp(Command,"enable")==0) 
      { 
       if(status != DISABLED) 
       { 
        printf("\nSynthesizer is already enabled!\n\n"); 
        continue; 
       } 
       status = ENABLED_IDLE; 
       nanosleep(&ecsWait, NULL); 
       printf("\nEnabled!\n\n"); 
       pthread_cond_signal(&en_sig); 
       continue; 
      } 

      if(strcasecmp(Command,"disable")==0) 
      { 
       status = DISABLED; 
       // pthread_mutex_lock(&clk_lock); 
       printf("\nDisabled!\n\n"); 
       continue; 
      } 

      if(strcasecmp(Command,"w")==0) 
      { 
       if(status != ENABLED_IDLE) 
       { 
        printf("\nSynthesizer is not enabled!\n\n"); 
        continue; 
       } 
       printf("\nWriting!\n\n"); 
       status = ENABLED_ACTIVE;  //FREEZE OCCURS HERE! 
       SendCmd(NREGISTER_ADDR,0xF13F); 
       continue; 
      } 

      printf("Invalid command!\n"); 
     } 
    } 
    return 0; 

} 
+0

'dest =&loadAddr'顯示不正確,這表示您正在寫入本地變量loadAddr的地址。如果'loadAddr'是一個實際地址,也許你想寫'volatile uint8_t * dest =(uint8_t *)loadAddr'。 – user4815162342 2014-10-09 17:59:33

+0

您是否看到每個呼叫有16行輸出? – 2014-10-09 18:02:03

+0

'i> = 0'意味着循環應該在'i'命中'-1'而不是'0'時退出,但是由於'i'在您的示例中被簽名,所以循環應該仍然退出。這個樣子的輸出是什麼樣的? '我'不斷向'-INT_MAX'遞減還是在某處損壞? – iwolf 2014-10-09 18:03:28

回答

2

問題:主線程需要其他線程調用pthread_cond_signal之前調用pthread_cond_wait。如果另一個線程在主線程正在等待條件之前發出信號,那麼pthread_cond_wait將不會返回。

所以,你需要確保的事情以正確的順序發生,而這也正是互斥的用武之地。之前,您應該鎖定互斥創建其他線程,只有當您使用完解鎖互斥條件變量。另一個線程需要鎖定互斥鎖,發出信號並釋放互斥鎖。主線程

僞代碼

init mutex 
lock the mutex 
init condition variable 
create the other thread 
while (!done) 
{ 
    wait for condition 
    do something useful after the condition is signaled 
} 
unlock the mutex 

僞的,當它需要告知病情

lock the mutex 
signal the condition 
unlock the mutex 

明顯的問題其他線程代碼:「但是,如果主線程總是有互斥鎖定,另一個線程將如何獲得互斥鎖?「。答案:「pthread_cond_wait在內部解鎖互斥體,這就是爲什麼您將互斥體傳遞到pthread_cond_wait。」