मुझे फ्रीआरटीओएस v8 में xQueue को लागू करने में परेशानी हो रही है।

बोर्ड STM32F4 पर आधारित है, और मैं ISR (सीरियल) से मुख्य थ्रेड में डेटा भेजने की कोशिश कर रहा हूं।

एकमात्र समस्या यह है कि मुख्य थ्रेड पर सभी डेटा प्राप्त नहीं होते हैं। मैंने भेजने से पहले बफर की जांच की और यह पूरा हो गया। मुख्य थ्रेड पर, चाहे मैं कितने भी वर्ण भेजूं, मुझे हमेशा बफर के पहले 5 मान प्राप्त होते हैं।

बफर की संरचना (मैंने [10] के बफर के साथ प्रयास किया है, और परिणाम वही है):

typedef struct SerialBuffer
{
    uint8_t Buffer[100];
} SerialBuffer;

कतार का निर्माण:

xQueueSerialDataReceived= xQueueCreate( 10, sizeof( SerialBuffer * ) );

सीरियलपोर्ट पर हैंडलर प्राप्त करें:

SerialBuffer SerialBufferRec;

static int8_t CDC_Receive_FS (uint8_t *Buf, uint32_t *Len)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    uint32_t length = *Len -1;
    //Copy the buffer
    for(int i =0;i<100;i++)
    {
        if(i<=length)SerialBufferRec.Buffer[i]=Buf[i];
        else SerialBufferRec.Buffer[i]=0;
    }

xQueueSendFromISR(xQueueSerialDataReceived,(void *)&SerialBufferRec,&xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

    return (USBD_OK);
}

मुख्य कार्य पर:

SerialBuffer SerialBufferReceived;


void ReceiveAndSendSerialData()
{

if(uxQueueMessagesWaitingFromISR(xQueueSerialDataReceived)>0)
            xQueueReceive(xQueueSerialDataReceived,&SerialBufferReceived,1);
        if(SerialBufferReceived.Buffer[0] != 0)
        {
           ...
        }

}

मैंने एक कार्य से दूसरे कार्य में भेजने की कोशिश की है और ISR का उपयोग नहीं किया है, और परिणाम वही है!

संपादित करें:

समझाते हुए CDC_Receive_FS (uint8_t *Buf, uint32_t *Len) :

अगर मैं पीसी से "abcdefg" स्ट्रिंग भेजता हूं, तो *Buf होगा:

Buf[0]='a' ... until Buf[6]='g' 

और *Len एक uint8_t होगा जिसका मान 7 . होगा

तो, for(int i =0;i<100;i++) केवल यह सुनिश्चित करने के लिए है कि SerialBufferRec.Buffer के सभी 100 पदों को अधिलेखित कर दिया जाएगा। यदि यह प्राप्त बफर की लंबाई से कम है, तो प्राप्त बफर की प्रतिलिपि बनाएँ, अन्यथा शून्य से भरें। यह सरणी में मौजूद अंतिम संदेश को खाली करने में भी मदद करता है।

xQueueSendFromISR कॉल करने से ठीक पहले SerialBufferRec होगा:

SerialBufferRec.Buffer[0]='a'
...
SerialBufferRec.Buffer[6]='g'
SerialBufferRec.Buffer[7]=0
...
SerialBufferRec.Buffer[99]=0

SerialBufferRecived प्राप्त कार्य इस तरह आता है ('f' और 'g' गायब):

SerialBufferRec.Buffer[0]='a'
...
SerialBufferRec.Buffer[4]='e'
SerialBufferRec.Buffer[5]=0
...
SerialBufferRec.Buffer[99]=0
1
Matheus Stumpf 22 पद 2017, 18:46

2 जवाब

सबसे बढ़िया उत्तर

खैर, कोड को फिर से सक्रिय करना, अब यह काम कर रहा है।

मुझे नहीं पता कि कहीं कोई बग तो नहीं था, या कुछ कमी थी।

भविष्य में किसी की मदद करने के लिए, मैं यहां पोस्ट कर रहा हूं कि मेरा कोड कैसे समाप्त हुआ।

@tgregory और @ryyker के प्रयास के लिए धन्यवाद!

एक साझा संरचना बनाई (customEnum.h) :

typedef struct
{
    char Buffer[100];
} SerialBuffer;

मुख्य कार्य में:

xQueueSerialDataReceived= xQueueCreate( 2, sizeof( SerialBuffer) );

if(uxQueueMessagesWaitingFromISR(xQueueSerialDataReceived)>0)
{
    xQueueReceive(xQueueSerialDataReceived,&(SerialBufferReceived),1);
    ...
}

आईएसआर में:

static int8_t CDC_Receive_FS (uint8_t *Buf, uint32_t *Len)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    uint32_t length = *Len -1;
    //Copy the buffer
    for(int i =0;i<100;i++)
    {
        if(i<=length)SerialBufferRec.Buffer[i]=Buf[i];
        else SerialBufferRec.Buffer[i]=0;
    }
    xQueueSendFromISR(xQueueSerialDataReceived,(void *)&SerialBufferRec,&xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken)portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

    return (USBD_OK);
}

मैंने पीसी से 99 वर्णों का एक चार भेजा, और उन सभी को मुख्य धागे पर पूरी तरह से प्राप्त किया।

0
Matheus Stumpf 26 पद 2017, 21:52

...पिछली सामग्री हटा दी गई क्योंकि मूल पोस्ट में नई जानकारी के आलोक में प्रासंगिक नहीं है।

संपादित करें: OP के लिए नई सामग्री पर आधारित, और इस पर निर्भर करता है कि निम्न फ़ंक्शन कैसे काम करता है:

xQueueSendFromISR(xQueueSerialDataReceived,(void *)&SerialBufferRec,&xHigherPriorityTaskWoken);

उदाहरण के आधार पर फ्रीआरटीओएस पर xQueueSendFromISR के उपयोग के संबंध में,

ऐसा प्रतीत होता है कि 100 तत्वों को उस तर्क में पैक करने के बजाय जिसे आप लूप के किनारे से गुजरते हैं, आपको लूप के अंदर प्रति पुनरावृत्ति केवल 1 तत्व पास करना चाहिए:

void vBufferISR( void )
{
char cIn;
BaseType_t xHigherPriorityTaskWoken;

    /* We have not woken a task at the start of the ISR. */
    xHigherPriorityTaskWoken = pdFALSE;

    /* Loop until the buffer is empty. */
    do
    {
        /* Obtain a byte from the buffer. */
        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );

        /* Post the byte. */
        xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );

    } while( portINPUT_BYTE( BUFFER_COUNT ) );

    /* Now the buffer is empty we can switch context if necessary. */
    if( xHigherPriorityTaskWoken )
    {
        /* Actual macro used here is port specific. */
        taskYIELD_FROM_ISR ();
    }
}

आपके कोड में (संक्षिप्त चित्रण) में, यह एक समय में एक बाइट भेजने के लिए अनुवाद करेगा: (ध्यान दें, मैंने संक्षिप्तता के लिए Buf[i] के असाइनमेंट को SerialBufferRec.Buffer[i] में छोटा कर दिया है)

...
char cIn;
for(int i =0;i<100;i++)
{
      xQueueSendFromISR(xQueueSerialDataReceived,&Buf[i],&xHigherPriorityTaskWoken);

}
0
ryyker 22 पद 2017, 21:20