2014-10-09 50 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。”