Quantcast
Channel: MSP low-power microcontroller forum - Recent Threads
Viewing all articles
Browse latest Browse all 21927

RTOS/MSP432P401R: Multitasking won't work with ADCBuf continuos mode

$
0
0

Part Number:MSP432P401R

Tool/software:TI-RTOS

CCS version 7.1.0.00016

Simplink MSP432 SDK version 1.30.00.40

Hi every one,

I'm working on a simple audio project on the MSP-EXP432P401R launch pad with TI-RTOS and TI drivers.

I have 3 tasks:

The first one is ADC task. This task initializes the ADCBuf module in continous mode, the sampling frequency is 48kHz, and then this task will be terminated. Analog signal will be sampled in background, converted to microvolt and store it into a buffer, let me call it AudioBuffer_In[AUDIO_BUFFER_SIZE]. The ADC task has priority level of 3.

Source code of ADC task:

//============= ADCtask.h ======================

#ifndef SOURCEFILES_TASKS_ADCTASK_H_
#define SOURCEFILES_TASKS_ADCTASK_H_

/* ADC sampling frequency in Hz */
#define ADC_SAMPLING_FREQ   48000

#endif /* SOURCEFILES_TASKS_ADCTASK_H_ */



//============= ADCTask.c ======================

/* Standard header files */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>

/* XDC module Headers */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

/* TI-RTOS Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>

/* TI driver Headers */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/ADCBuf.h>

/* Board Header */
#include "Board.h"

#include <SourceFiles/Tasks/MainTask.h>
#include <SourceFiles/Tasks/ADCTask.h>

/*
 * Private variables
 */
ADCBuf_Handle        adcBuf;
ADCBuf_Params        adcBuf_Params;
ADCBuf_Conversion    adcBuf_ContinuousConversion[2];
uint16_t             sampleBufferOne[2][AUDIO_BUFFER_LENGTH];
uint16_t             sampleBufferTwo[2][AUDIO_BUFFER_LENGTH];

/*
 * Functions declaration
 */
void adcTask_Function(UArg arg0, UArg arg1);
void adcBuf_CallBack(ADCBuf_Handle handle, ADCBuf_Conversion *conversion, void *completedADCBuffer, uint32_t completedChannel);

/*
 * Initialize ADC thread.
 */
void ADCTask_Init(void) {

    Task_Handle         adcTask;
    Task_Params         adcTask_Params;
    Error_Block         errorBlock;

    /* Initialize drivers */
    ADCBuf_init();

    /* Initialize error block */
    Error_init(&errorBlock);

    /* Create main task */
    Task_Params_init(&adcTask_Params);
    adcTask_Params.stackSize = ADC_TASK_STACK_SIZE;
    adcTask_Params.priority = ADC_TASK_PRIORITY;
    adcTask = Task_create((Task_FuncPtr)adcTask_Function, &adcTask_Params, &errorBlock);
    if (adcTask == NULL) {
        /* Failed to create ADC task */
        while (1);
    }
}

/*
 * ADC task function.
 */
void adcTask_Function(UArg arg0, UArg arg1) {

    /* Initialize the ADCBuf parameters */
    ADCBuf_Params_init(&adcBuf_Params);
    adcBuf_Params.samplingFrequency = ADC_SAMPLING_FREQ;
    adcBuf_Params.recurrenceMode = ADCBuf_RECURRENCE_MODE_CONTINUOUS;
    adcBuf_Params.returnMode = ADCBuf_RETURN_MODE_CALLBACK;
    adcBuf_Params.callbackFxn = adcBuf_CallBack;

    /* Open the ADCBuf0 */
    adcBuf = ADCBuf_open(Board_ADCBUF0, &adcBuf_Params);
    if (!adcBuf){
        /* AdcBuf did not open correctly. */
        while(1);
    }

    /* Configure the conversion structure */
    adcBuf_ContinuousConversion[0].arg = NULL;
    adcBuf_ContinuousConversion[0].adcChannel = Board_ADCBUF0CHANNEL0;
    adcBuf_ContinuousConversion[0].sampleBuffer = sampleBufferOne[0];
    adcBuf_ContinuousConversion[0].sampleBufferTwo = sampleBufferTwo[0];
    adcBuf_ContinuousConversion[0].samplesRequestedCount = AUDIO_BUFFER_LENGTH;
    adcBuf_ContinuousConversion[1].arg = NULL;
    adcBuf_ContinuousConversion[1].adcChannel = Board_ADCBUF0CHANNEL1;
    adcBuf_ContinuousConversion[1].sampleBuffer = sampleBufferOne[1];
    adcBuf_ContinuousConversion[1].sampleBufferTwo = sampleBufferTwo[1];
    adcBuf_ContinuousConversion[1].samplesRequestedCount = AUDIO_BUFFER_LENGTH;

    /* Start converting */
    if (ADCBuf_convert(adcBuf, adcBuf_ContinuousConversion, 2) != ADCBuf_STATUS_SUCCESS) {
        /* Did not start conversion process correctly. */
        while(1);
    }
}

/*
 * ADCBuf call back function.
 */
void adcBuf_CallBack (ADCBuf_Handle handle, ADCBuf_Conversion *conversion, void *completedADCBuffer, uint32_t completedChannel) {
    /* Adjust raw adc values */
    ADCBuf_adjustRawValues(handle, completedADCBuffer, AUDIO_BUFFER_LENGTH, completedChannel);

    /* Convert ADC values to microvolts and save them into the input audio buffer */
    ADCBuf_convertAdjustedToMicroVolts(handle, completedChannel, completedADCBuffer, AudioBuffer_In[completedChannel], AUDIO_BUFFER_LENGTH);
}

The second one is Main task. This task initialize the 2 other tasks first and then go to a infinite while loop. In the while loop, it take the data in AudioBuffer_In, process the data and store processed data in to another buffer, the AudioBuffer_Out[AUDIO_BUFFER_SIZE]. After that, it will send a semaphore post signal to tell the third task, which is PWM task, to do thier job. The Main task has priority level of 1.

Main task source code:

//================ MainTask.h ====================


#ifndef SOURCEFILES_TASKS_MAINTASK_H_
#define SOURCEFILES_TASKS_MAINTASK_H_

#include <ti/sysbios/knl/Semaphore.h>

/* Main task priority and stack size in bytes */
#define MAIN_TASK_PRIORITY      1
#define MAIN_TASK_STACK_SIZE    1024

/* PWM task priority and stack size in bytes */
#define PWM_TASK_PRIORITY       2
#define PWM_TASK_STACK_SIZE     1024

/* ADC task priority and stack size in bytes */
#define ADC_TASK_PRIORITY       3
#define ADC_TASK_STACK_SIZE     1024

/* Audio buffers length */
#define AUDIO_BUFFER_LENGTH     1024

/* Global variables */
extern Semaphore_Handle         Semaphore;
extern uint32_t                 AudioBuffer_In[2][AUDIO_BUFFER_LENGTH];
extern uint32_t                 AudioBuffer_Out[2][AUDIO_BUFFER_LENGTH];

/* Initialize main task */
extern void                     MainTask_Init(void);

#endif /* SOURCEFILES_TASKS_MAINTASK_H_ */


//================ MainTask.c ====================


/* Standard header files */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>

/* XDC module Headers */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

/* TI-RTOS Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>

/* TI driver Headers */
#include <ti/drivers/GPIO.h>

/* Board Header */
#include "Board.h"

#include <SourceFiles/Tasks/MainTask.h>
#include <SourceFiles/Tasks/PWMTask.h>
#include <SourceFiles/Tasks/ADCTask.h>
#include <SourceFiles/AudioEffects/EchoEffect.h>

/*
 * Global variables
 */
Semaphore_Handle    Semaphore;
uint32_t            AudioBuffer_In[2][AUDIO_BUFFER_LENGTH];
uint32_t            AudioBuffer_Out[2][AUDIO_BUFFER_LENGTH];

/*
 * Private variables.
 */
/* Echo effect variables */
EchoEffect_Params   echoEffect_Params = { 5, 200, 2 };

/*
 * Functions declaration.
 */
void mainTask_Function(UArg arg0, UArg arg1);

/*
 * Initialize main thread.
 */
void MainTask_Init(void) {

    Task_Handle         mainTask;
    Task_Params         mainTask_Params;
    Error_Block         errorBlock;
    Semaphore_Params    semaphore_Params;

    /* Initialize drivers */
    GPIO_init();

    /* Initialize error block */
    Error_init(&errorBlock);

    /* Create main task */
    Task_Params_init(&mainTask_Params);
    mainTask_Params.stackSize = MAIN_TASK_STACK_SIZE;
    mainTask_Params.priority = MAIN_TASK_PRIORITY;
    mainTask = Task_create((Task_FuncPtr)mainTask_Function, &mainTask_Params, &errorBlock);
    if (mainTask == NULL) {
        /* Failed to create main task */
        while (1);
    }

    /* Create a semaphore handle */
    Semaphore_Params_init(&semaphore_Params);
    Semaphore = Semaphore_create(1, &semaphore_Params, &errorBlock);
    if (Semaphore == NULL) {
        /* Failed to create semaphore object */
        while (1);
    }
}

/*
 *  Main task function.
 */
void mainTask_Function(UArg arg0, UArg arg1) {

    /* Initialize ADC task */
    //ADCTask_Init();

    /* Initialize PWM task */
    PWMTask_Init();

    /* Loop forever */
    while(1) {

        GPIO_toggle(Board_GPIO_LED0);

        /* Apply audio effects */
        EchoEffect_ApplyEffect(AudioBuffer_In[0], AudioBuffer_Out[0], AUDIO_BUFFER_LENGTH, &echoEffect_Params);
        EchoEffect_ApplyEffect(AudioBuffer_In[1], AudioBuffer_Out[1], AUDIO_BUFFER_LENGTH, &echoEffect_Params);

        /* Post semaphore */
        Semaphore_post(Semaphore);

        sleep(1);
    }
}

The third task as I mentioned above is PWM task. This task initialize the PWM module first, and in its while loop, it wait for a semaphore signal from the Main task while get blocked by calling a semaphore pend. When the signal comes in, it take the data in AudioBuffer_Out, calculate required duty cycle for each value in that buffer and then change the duty cycle of PWM signal. The PWM has frequency of 250kHz. This task has priority level of 2.

Source code for the PWM task:

//===================== PWMTask.h ===========================


#ifndef SOURCEFILES_TASKS_PWMTASK_H_
#define SOURCEFILES_TASKS_PWMTASK_H_

/* PWM frequency in Hz */
#define PWM_FREQ            250000

/* Initialize the PWM task. */
extern void PWMTask_Init(void);

#endif /* SOURCEFILES_TASKS_PWMTASK_H_ */


//===================== PWMTask.c ===========================


/* Standard header files */
#include <unistd.h>
#include <stdint.h>
#include <stddef.h>

/* XDC module Headers */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

/* TI-RTOS Headers */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Semaphore.h>

/* TI driver Headers */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/PWM.h>

/* Board Header */
#include "Board.h"

#include <SourceFiles/Tasks/MainTask.h>
#include <SourceFiles/Tasks/PWMTask.h>

/*
 * Functions declaration
 */
void pwmTask_Function(UArg arg0, UArg arg1);

/*
 * Initialize PWM thread.
 */
void PWMTask_Init(void) {

    Task_Handle         pwmTask;
    Task_Params         pwmTask_Params;
    Error_Block         errorBlock;

    /* Initialize drivers */
    PWM_init();

    /* Initialize error block */
    Error_init(&errorBlock);

    /* Create main task */
    Task_Params_init(&pwmTask_Params);
    pwmTask_Params.stackSize = PWM_TASK_STACK_SIZE;
    pwmTask_Params.priority = PWM_TASK_PRIORITY;
    pwmTask = Task_create((Task_FuncPtr)pwmTask_Function, &pwmTask_Params, &errorBlock);
    if (pwmTask == NULL) {
        /* Failed to create PWM task */
        while (1);
    }
}

/*
 * PWM task function.
 */
void pwmTask_Function(UArg arg0, UArg arg1) {

    /* PWM handle and parameters */
    PWM_Handle pwm[2];
    PWM_Params pwmParams;

    /* Initialize the PWM parameters */
    PWM_Params_init(&pwmParams);
    pwmParams.idleLevel = PWM_IDLE_LOW;
    pwmParams.dutyUnits = PWM_DUTY_FRACTION;
    pwmParams.dutyValue = PWM_DUTY_FRACTION_MAX / 2;
    pwmParams.periodUnits = PWM_PERIOD_HZ;
    pwmParams.periodValue = PWM_FREQ;

    /* Open and start the pwm[0] */
    pwm[0] = PWM_open(Board_PWM0, &pwmParams);
    if (pwm[0] == NULL) {
        /* Failed to open PWM0 */
        while (1);
    }
    PWM_start(pwm[0]);

    /* Open and start the pwm[1] */
    pwm[1] = PWM_open(Board_PWM1, &pwmParams);
    if (pwm[1] == NULL) {
        /* Failed to open PWM1 */
        while (1);
    }
    PWM_start(pwm[1]);

    /* Loop forever */
    while (1) {

        /* Wait for semaphore to be posted by main task */
        Semaphore_pend(Semaphore, BIOS_WAIT_FOREVER);

        uint16_t i;

        for (i = 0; i < AUDIO_BUFFER_LENGTH; i++) {
            PWM_setDuty(pwm[0], (uint32_t)((((float)AudioBuffer_Out[0][i]) / 2500000) * PWM_DUTY_FRACTION_MAX));
            PWM_setDuty(pwm[1], (uint32_t)((((float)AudioBuffer_Out[1][i]) / 2500000) * PWM_DUTY_FRACTION_MAX));
        }

        GPIO_toggle(Board_GPIO_LED1);
    }
}

The Main task will be initialized right before the BIOS_start() calling. The 2 others will be initialized in main task function.

The problem is the Main task and the PWM task won't work well if I initialize the ADC task. If I don't, the Main task and the PWM task just work well, the Main task take data in AudioBuffer_In (in this case, all values are equal to 0), process the data and send a semaphore post signal. The PWM take the signal immediately because it has higher priority. PWM task do its job and got blocked by calling a semaphore pend, and the Main task run again, and so on. Let look at the line ADCTask_Init(); in the main task function. If I comment this out, that mean there is no ADC task, so the others task just work fine.

Any one help me, please.


Viewing all articles
Browse latest Browse all 21927

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>