Multifunction DAQ

cancel
Showing results for 
Search instead for 
Did you mean: 

6133 DAQ DMA configuration

Solved!
Go to solution

I have a system where data acquisition is triggered, not continuous. It is triggered every 2ms. On each trigger, 4000 samples from each of two 16 bit channels are needed. ie. 16000 bytes. At the moment I have written an application that runs, but there is a buffer overflow for the DMA channel reported by the C++ class (tDMAChannel). Below I have shown the initialization and start functions. And the read function, based on an online example. The application doesn't do much more, so there should be very little delay getting back to read more data. Have I made a mistake in configuration? Having the aiSampleStart onDemand parameter kFalse or kTrue didn't change the result.

What should be the value for DMA_BYTES in the startDMA function below?

 

void NI6133::init ()
{
    m_bar1 = m_bus->createAddressSpace(kPCI_BAR1);
    m_board = new tSSeries(m_bar1);
    m_stc = new tSTC(m_bar1);
    m_scarab = new tScarabInput(m_bar1);
    // TODO what is 0x80 ?
    m_scarab->setAddressOffset(0x80);

    // DMA objects
    m_bar0 = m_bus->createAddressSpace(kPCI_BAR0);
    m_mite = new tMITE(m_bar0);
    // TODO what is 0x500 ?
    m_mite->setAddressOffset(0x500);
    m_dma = new tDMAChannel(m_bus, m_mite);

    // program device
    // Put board in known state
    disableInterrupts(m_stc, m_board);
    MSCClockConfig(m_stc);
    interruptConfig(m_stc);
    initInputScarab(m_scarab, getScarabSizeInBytes(m_board));

    // Initialize/Config Device
    aiInitFrontEnd(m_board, ADC_RESOLUTION, END_OF_CONVERT_DELAY);

    //Reset & config ADC
    aiReset(m_stc);
    aiPersonalize(m_stc, m_board);

    aiConfigChannel(m_stc, m_board, NUM_ADC_CHANNELS, m_gainSetting);

    // AI Timing control
    aiTriggerSync(m_stc, 0); // 1 for finite & continuous, 0 for on demand
    aiNumberOfSamples(m_stc, m_numberOfSamples, kFalse); // false for finite, true for continuous
    aiSampleStart(m_stc, DAQ_SAMPLE_RATE, &m_actualSampleRate, kFalse); // true for on demand, false for finite & continuous
    slogf(_SLOG_SETCODE(_SLOGC_OP, 0), _SLOG_INFO, "DAQ sample rate %f", m_actualSampleRate);
    aiConvert(m_stc);
    aiSampleStop(m_stc);

    //Configure DIO 0-7 as output
    m_stc->DIO_Control.writeDIO_Pins_Dir(0xFF);
    //theSTC->DIO_Output.writeDIO_Parallel_Data_Out(0x01);
    m_stc->DIO_Output.writeDIO_Parallel_Data_Out(0x00);
}

 

bool NI6133::startDMA ()
{
    m_scarab->Control.setDisableContinuousDREQDrive(0);
    m_scarab->Control.setEnableContinuousDREQDrive(1);
    m_scarab->Control.setEnableDREQ(1);
    m_scarab->Control.flush();

    m_board->AIAO_Select.writeInput(1);

    // Configure and start DMA Channel
    // DMA operations use bytes instead of samples.
    // The 6133 transfer 32-bits at a time (2 samples)

    tDMAError status = m_dma->config(0, tDMAChannel::kRing, tDMAChannel::kIn, DMA_BYTES, tDMAChannel::k32bit);
    if (status != kNoError)
    {
        slogf(_SLOG_SETCODE(_SLOGC_OP, 0), _SLOG_NOTICE, "Error: DMA configuration (%d)", status);
        return false;
    }

    status = m_dma->start();
    if (status != kNoError)
    {
        slogf(_SLOG_SETCODE(_SLOGC_OP, 0), _SLOG_NOTICE, "Error: DMA start (%d)", status);
        return false;
    }
    return true;
}

 

void NI6133::start ()
{
    // Start the DMA engine before arming/starting the AI engine.
    if (m_useDMA)
    {
        if (!startDMA())
        {
            slogf(_SLOG_SETCODE(_SLOGC_OP, 0), _SLOG_NOTICE, "Failed to start DMA for NI6133. Defaulting to register reading.");
            m_useDMA = false;
        }
    }
    // Arm and start AI engine
    aiArm(m_stc, m_scarab);
    aiStart(m_stc);
}

 

/** Number of microseconds to delay before retry DMA read to fulfill requested number of bytes */
#define MICROSEC_RETRY_DMA_READ 10
/** Number of DMA read retries before declaring no data available */
#define RETRY_DMA_READ_MAX 10

 

tDMAError NI6133::dmaRead (u32 userSizeInBytes, u8 * buffer, u32 * pBytesRead)
{
    tDMAError status = kNoError;
    u32 bytesAvailable = 0;
    unsigned tries = 0; // number of times attempted read without result
    *pBytesRead = 0;
    while ((*pBytesRead < m_totalBytesInDMA) && (kNoError == status))
    {
        // query the number of bytes in the DMA buffers
        status = m_dma->read(0, NULL, &bytesAvailable);

        // if there is enough data, read
        if (bytesAvailable >= userSizeInBytes)
        {
            status = m_dma->read(userSizeInBytes, buffer, &bytesAvailable);
            *pBytesRead += userSizeInBytes;
            break;
        }

        // check for errors
        if (status != kNoError)
            break;

        // check timeout
        if (++tries == RETRY_DMA_READ_MAX)
        {
            status = kDataNotAvailable;
            break;
        }

        usleep(MICROSEC_RETRY_DMA_READ);
    }
    if (status != m_lastStatusDMA)
    {
        slogf(_SLOG_SETCODE(_SLOGC_OP, 0), _SLOG_INFO, "DAQ DMA read status %d", status);
        m_lastStatusDMA = status;
    }
    return status;
}

0 Kudos
Message 1 of 2
(2,140 Views)
Solution
Accepted by topic author Sorterralee

It turned out to be a simple buffer size issue, and don't use a time consuming console debug output. I set DMA_BYTES to be double the number of bytes received from a single sample set of 4000 samples on each of 2 channels. ie. 32000 bytes.

Message 2 of 2
(2,110 Views)