通过Uart ISR更新变量而不中断分配

时间:2018-07-05 01:17:51

标签: c arm embedded

我的传入值在数据包内部。我必须阅读该包,然后使用此包提取实际值。我使用了一些按位运算和“一致性字节填充算法”来形成一个包。

在接收方,当检测到Uart上有传入字节时,MCU将运行ISR。阅读包装。将其发送到解码器函数,该函数返回解码值的数组。

因为我要返回一个数组,所以我不得不使用 malloc 并且必须使用 free(xxx)函数。我学到了使用 free() 在ISR中是个坏主意。所以我以某种方式编辑了我的代码,并将free(xxx)放入了主循环。

在这里,您看到我的中断处理程序函数,该函数在每次成功读取后运行。

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)  
{

//{2,32,2,140,3,168,100,3,1,16,0} this is an example package.End byte is always 0 and there is no other possible occurrence of 0 in 1 package thanks to the COBS algoritm

count_dooku++; // this variable counts how many interrupt has occurred. Mostly usefull For debuging.  If i use free() inside of this function count_dooku stops at 22 which means after reading 2 packages it stopped. If there is no free() interrupts keep working as they should 

if (huart->Instance == USART1)  //current UART 
    {

    int a=0;

   if (Rx_indx==0) {for (int i=0;i<30;i++) Rx_Buffer[i]=0;}   //clear Rx_Buffer before receiving new data 

    if (Rx_data[0]!=a) //if received data different from  package end byte 0 //
        {
        Transfer_cplt=0;// reset Transfer_cplt value to 0 since we are receiving new package 

        Rx_Buffer[Rx_indx++]=Rx_data[0];    //add data to Rx_Buffer
        }
    else            //if received data = 0 which means end of the package
        {

       //now transfer completed, data is ready to read
                 if (Rx_indx==10)  //check the lenght of the package if true continue 
                 {
                    for( int i=0; i < 11; i++ ){
                    un_decoded_data[i]=  *( Rx_Buffer + i ) ; 
                    }  copy package values from buffer to another array.

                        Transfer_cplt=1;  // mission completed. Pakage is in "un_decoded_data"                          
                  }
                 Rx_indx=0;  //reset index counter for new data


          }


    }

 HAL_UART_Receive_IT(&huart1, Rx_data, 1);   //activate UART receive interrupt every time

   }

这是我的主循环:

  int main(void)
 {
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); //initialization of uart in stm32f4 hal library

  while (1)
  {

         if (Transfer_cplt==1)  //if buffer data succesfully transfered to un_decoded_data 
                         {

                    UnStuffData(un_decoded_data, 11,destination) ; //this is Consistive overhead algortim for decoding package. No problem with this one bc it uses global values

                                    predec_package=  make_predec_package(destination); //this function takes decoded data and makes some bit wise operations. and returns array of values with pointer. So i used malloc and after i am done with it i have to free it (below)
                                    free(destination); // this one is problem. Even if not in the ISR still related to ISR so still causing problems. 
                                    for( int i=0; i < 6; i++ ){
                                            decoded_data[i]=     *( predec_package + i ) ;

                                        }
                       }
    }}

以防万一我要添加返回数组并产生问题的函数。这是:

int16_t* make_predec_package( unsigned char *ptr){  //function takes array as input

int8_t n;
uint8_t temp_array[11] = {0};  //temporary array for calculations and also debugging 

int16_t  *temporary = calloc(8, sizeof(*temporary));  //temporary must be freed by caller


if(temporary)
{
     for( int i=0; i < 11; i++ ){
        temp_array[i]        =   *( ptr + i );
     }

     n = temp_array[0];

     //here some bitwise calculations...
    temporary[0] = (temp_array[1]*256 ) + temp_array[2]/4  ;
    temporary[1] = (temp_array[3]*256 )+ temp_array[4]/ 4  ;
    temporary[2]= temp_array[5];
    temporary[3]= temp_array[6];
    temporary[4]= temp_array[7];
    temporary[5]= temp_array[8];
    temporary[6]= temp_array[9];
    temporary[7]= temp_array[10];
}

     // i am returning fully decoded data array with pointer. 
return temporary;  
 }

2 个答案:

答案 0 :(得分:2)

不幸的是,这段代码很幼稚,应该从头开始重写。

您应尽可能减少ISR,并且它不应包含任何应用程序逻辑。从UART接收数据后,ISR应该将数据放在缓冲区中。首选的方法是根本不使用中断,而是使用DMA。

如果您的MCU上没有DMA,则必须提出一种环形缓冲区结构,该结构将充当从ISR到应用程序的FIFO。在读取期间,您需要某种保护方式,以确保读取时(竞争条件)ISR不会写入缓冲区。

由于UART通常非常慢,因此如果您从缓冲区中获取数据的代码比在UART上输入1 + 8 + 1位所需的时间更快,那么只需在读取期间禁用中断就足够了。

然后,最好使用最少的程序设计,将UART驱动程序与应用程序逻辑完全分开。

答案 1 :(得分:-1)

我无法理解free()出了什么问题;功能。 Howaver我建议您也将我们的输出作为指针参数。 经验:

make_predec_package(destination, predec_package);

代替

predec_package=  make_predec_package(destination);

返回指针总是引起我所知道的问题。

以及该更改所涉及的函数内部

void make_predec_package( unsigned char *ptr, int16_t* predec_package){  //function takes array as input

int8_t n;
uint8_t temp_array[11] = {0};  //temporary array for calculations and also debugging 

//int16_t  *temporary = calloc(8, sizeof(*temporary)); 

     for( int i=0; i < 11; i++ ){
     temp_array[i]        =   *( ptr + i );
     }

 n = temp_array[0];

 //here some bitwise calculations...
predec_package[0] = (temp_array[1]*256 ) + temp_array[2]/4  ;
predec_package[1] = (temp_array[3]*256 )+ temp_array[4]/ 4  ;
predec_package[2]= temp_array[5];
predec_package[3]= temp_array[6];
predec_package[4]= temp_array[7];
predec_package[5]= temp_array[8];
predec_package[6]= temp_array[9];
predec_package[7]= temp_array[10];
}

 // i am returning fully decoded data array with pointer. 
 //return temporary;  
 }

只有我看不到您在哪里声明了“ predec_package”,因此请确保长度为right(8 <)的数组。