This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP432P4111: msp432p4111 more ADC sampleBuffer

Part Number: MSP432P4111

Hi,

I'm continous sampling ADC values and get an interrupt all 1000 samples. These samples I am sending from the ISR via queue. To do this I have two variants:

1. Send the data via queue:
- Dereferencing the completedADCBuffer in the xQueueSendFromISR() with a "*" fails: error #169: argument of type "void" is incompatible with parameter of type "const void *const"
- Normally I avoid this variant because of data coping in the ISR

int main(void)
{
	.
	.
	.
	/* Configure the conversion struct */
	continuousConversion.arg = NULL;
	continuousConversion.adcChannel = Board_ADCBUF0CHANNEL1;
	continuousConversion.sampleBuffer = sampleBufferOne;
	continuousConversion.sampleBufferTwo = sampleBufferTwo;
	continuousConversion.samplesRequestedCount = ADCBUFFERSIZE;
		
	xQueueADC = xQueueCreate( 10, 1000 * 2);// uint16_t => 2 byte unsigned integer
	.
	.
	.
}

void adcBufCallback(ADCBuf_Handle handle, ADCBuf_Conversion *conversion,
    void *completedADCBuffer, uint32_t completedChannel) {

    if( xQueueADC != 0 )
    {
       BaseType_t xHigherPriorityTaskWoken;
	   xHigherPriorityTaskWoken = pdFALSE;
	   xQueueSendFromISR( xQueueADC, *completedADCBuffer, &xHigherPriorityTaskWoken );
	   if( xHigherPriorityTaskWoken )
	   {
		   portYIELD_FROM_ISR (xHigherPriorityTaskWoken);
	   }
    }
}


2. Send only the data pointer via queue but with more ADC sampleBuffer:
- Is this possible to increase the number of sampleBuffer to 10? I think it needs more than only editing the conversion struct !?
- Is the xQueueCreate() correct?

int main(void)
{
	.
	.
	.
	/* Configure the conversion struct */
	continuousConversion.arg = NULL;
	continuousConversion.adcChannel = Board_ADCBUF0CHANNEL1;
	continuousConversion.sampleBuffer1 = sampleBuffer1;
	continuousConversion.sampleBuffer2 = sampleBuffer2;
	continuousConversion.sampleBuffer3 = sampleBuffer3;
	.
	.
	.
	continuousConversion.sampleBuffer10 = sampleBuffer10;
	continuousConversion.samplesRequestedCount = ADCBUFFERSIZE;
		
	xQueueADC = xQueueCreate( 10, sizeof(uint16_t ADCBuf[1000] *));// uint16_t => 2 byte unsigned integer
	.
	.
	.
}

void adcBufCallback(ADCBuf_Handle handle, ADCBuf_Conversion *conversion,
    void *completedADCBuffer, uint32_t completedChannel) {

    if( xQueueADC != 0 )
    {
       BaseType_t xHigherPriorityTaskWoken;
	   xHigherPriorityTaskWoken = pdFALSE;
	   xQueueSendFromISR( xQueueADC, completedADCBuffer, &xHigherPriorityTaskWoken );
	   if( xHigherPriorityTaskWoken )
	   {
		   portYIELD_FROM_ISR (xHigherPriorityTaskWoken);
	   }
    }
}

I would be glad if someone could give me an advice.

Thanks

  • Hello,

    user5841294 said:
    Is this possible to increase the number of sampleBuffer to 10? I think it needs more than only editing the conversion struct !?

    Looking at the code, adding extra sampleBuffer means assigning a buffer to an element of the structure continuousConversion. To see if this possible, please check if the structure definition of continuousConversion has the necessary elements.

    user5841294 said:
    Is the xQueueCreate() correct?

    For help on xQueueCreate please check the FreeRTOS documentation for this API.

    Thanks,

    Sai

  • Hello,

    Sai Reddy said:
    To see if this possible, please check if the structure definition of continuousConversion has the necessary elements.

    I looked into the Technical Reference Manual and the datasheet but I don't found information if it is possible to extend the continuous conversion struct.

    What I found is the struct definition in ADCBuf.h:

    /*!
     *  @brief
     *  An ::ADCBuf_Conversion data structure is used with ADCBuf_convert(). It indicates
     *  which channel to perform the ADC conversion on, how many conversions to make, and where to put them.
     *  The arg variable is an user-definable argument which gets passed to the
     *  ::ADCBuf_Callback when the ADC driver is in ::ADCBuf_RETURN_MODE_CALLBACK.
     */
    typedef struct ADCBuf_Conversion_ {
        uint16_t            samplesRequestedCount;      /*!< Number of samples to convert and return */
        void                *sampleBuffer;              /*!< Buffer the results of the conversions are stored in */
        void                *sampleBufferTwo;           /*!< A second buffer that is filled in ::ADCBuf_RECURRENCE_MODE_CONTINUOUS mode while
                                                            the first buffer is processed by the application. The value is not used in
                                                            ::ADCBuf_RECURRENCE_MODE_ONE_SHOT mode. */
        void                *arg;                       /*!< Argument to be passed to the callback function in ::ADCBuf_RETURN_MODE_CALLBACK */
        uint32_t            adcChannel;                 /*!< Channel to perform the ADC conversion on. Mapping of channel to pin or internal signal is device specific. */
    } ADCBuf_Conversion;

    If I would extend with *sampleBufferThree... and so on I think it wouldn't work. I have to edit the code that handles this.

    Which c file is resonsible for this?

    Thanks

  • My intention of pointing you to the structure definition of "continuousConversion" was so that you can identify that you cannot assign the extra buffers.

    The path that you are going down would mean having to change the behavior of the driver, that means it would take a lot of time, effort and understanding of the driver. The driver is located in the folder "./source/ti/drivers/adcbuf/", but I would recommend reconsidering the approach.

    Why do you need so many buffers? Why can't 2 buffers do the same work as 10 buffers, if all you need is one buffer filling up while the other one is being emptied?

    Thanks,
    Sai
  • Hi Sai,

    I have a special DSP computation which needs 5000 ADC samples. To reduce copying and SRAM memory I thought to use a pointer to each 1000-sample-buffer that I get every DMA interrupt. This Pointer I would send via Queue to the computation task. If all 5 queue elements (5000 samples) are available, the computation task copy the samples in a computation buffer. Because of the fact that I only have 2 DMA buffers the values would be overriden before the computation could use it.

    The advantage is that I only need the computation buffer. The size of the queue is only the size of the five pointers instead of 5000 samples.

    Thanks

  • user5841294 said:
    Because of the fact that I only have 2 DMA buffers the values would be overriden before the computation could use it.

    Did you already verify if the buffers are being filled-up before they can be emptied? You might have to adjust priorities of the tasks. 

    user5841294 said:
    The advantage is that I only need the computation buffer. The size of the queue is only the size of the five pointers instead of 5000 samples.

    Why can't you use this approach with 2 buffers? You could still pass the address of the buffer (that needs computation) to the queue.

    Thanks,

    Sai

  • Hi,

    Sai Reddy said:
    Did you already verify if the buffers are being filled-up before they can be emptied? You might have to adjust priorities of the tasks. 

    Yes, because the ISR will only be executed if the DMA Buffer if full (1000 samples).

    Maybe this two picture shows my purpose. The first picture shows the current situation, I pass the every 1000 samples by value via queue to the computation. It works but it needs to much SRAM.

    The best would be to pass s pointer to every 1000 samples (to every buffer) via  queue to the computation. When the first 5 pointer (sample 0...5k) arrive they will be used for computation. Meanwhile, the next 5k (5k...10k) samples will be collected and send via pointer in the queue. At this time the first 5k (0...5k) samples or the first 5 buffers were already used for computation. Now they can be filled with new samples from the ADC/DMA:

    Thanks

  • Hello,

    Apologize for the delay in getting back on this post!

    From the first picture, you can still pass the DMA buffer by reference right. Maybe I am missing the point here of why you can't pass the buffer. The only concern that I would have is, can you process this buffer soon enough that it is available for the next transaction.

    Thanks,

    Sai

  • Hello,

    the problem of why it can't work with the "passing by reference" methode is that I need ten DMA buffer not only two (A and B). In the second picture I tried to explain it. With only two buffers I have the problem that I can't pass 5000 samples to computation by reference. After the second (B) buffer is full, the first will be overriden.
    Do you know what I try to say?

    Thanks

  • Hello,

    The driver is configuring the DMA in ping pong mode. This means that the DMA will copy data to the ping buffer for one transcation and for the next transaction it will copy data to pong buffer, then to the ping buffer and so on. The DMA cannot be configured to use more than 2 buffers in ping-pong mode.

    The CPU will have to copy data from the DMA buffers (in your figure Buffer A and Buffer B) to other locations if needed.

    Hope this helps!

    Regards,

    Sai

  • Hello,

    a pity that it is not possible to extend to more buffers.

    Thank you for support!

    Regards

**Attention** This is a public forum