Пример #1
0
//------------------------------------------------------------------------------
/// Starts buffer transfer on the given channel
/// \param channel Particular channel number.
/// \param size Total transfer size in byte.
/// \param callback Optional callback function.
/// \param polling Polling channel status enable.
//------------------------------------------------------------------------------
unsigned char DMAD_BufferTransfer(unsigned char channel, 
                                  unsigned int size, 
                                  DmaCallback callback, 
                                  unsigned char polling)
{
    DmaTransfer *pTransfer = &(dmad.transfers[channel]);
    // Check that no transfer is pending on the channel
    if (pTransfer-> transferSize > 0 ) {
        TRACE_ERROR("DAM transfer is already pending\n\r");
        return DMAD_ERROR_BUSY;
    }
    pTransfer->status = DMAD_ERROR_BUSY; 
    pTransfer->transferSize = size;
    pTransfer->callback = callback; 
    
    if(!polling){
        DMA_EnableIt(DMA_BTC << channel);
    }
    // Enable the channel.
    DMA_EnableChannel(channel);
    
    if(polling){
        while ((DMA_GetChannelStatus() & (DMA_ENA << channel)) == (DMA_ENA << channel));
        pTransfer->callback();
        DMA_DisableChannel(channel);
    }
    return 0;
}
Пример #2
0
//------------------------------------------------------------------------------
//         Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// This handler function must be called by the DMAC interrupt service routine.
/// Identifies which event was activated and calls the associated function.
//------------------------------------------------------------------------------ 
void DMAD_Handler()
{
    unsigned int  status;
    unsigned char channel;
    DmaTransfer *pTransfer;
    status = DMA_GetStatus();
    // Check if the buffer transfer completed is set.
    if(status & AT91C_BTC)
    {
        // Scan each channel status.
        for(channel = 0; channel < DMA_CHANNEL_NUM; channel++) {
            if(!(status & (DMA_BTC << channel))){
                continue;
            }
            
            dmad.transfers[channel].transferSize -= dmad.transfers[channel].bufSize;
            // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit.
            if(dmad.transfers[channel].transferSize <= dmad.transfers[channel].bufSize) {
                DMA_ClearAutoMode(channel);
            }
            // Transfer finished
            if(dmad.transfers[channel].transferSize == 0) {
                pTransfer = &(dmad.transfers[channel]);
                pTransfer->callback();
                DMA_DisableIt(DMA_BTC << channel); 
                DMA_DisableChannel(channel);
            }
            else
            {
                // Write the KEEPON field to clear the STALL states.
                DMA_KeeponChannel(channel);
            }
        }
    }
}
Пример #3
0
//------------------------------------------------------------------------------
/// Initializes the DMA controller.
/// \param dwChannel Particular dwChannel number
/// \param defaultHandler Using the default dmad interrupt handler.
//------------------------------------------------------------------------------
extern void DMAD_Initialize( uint32_t dwChannel, uint32_t defaultHandler )
{
    uint32_t dwStatus ;
    uint32_t dwFlag ;

    /* Enable peripheral clock */
    PMC_EnablePeripheral( ID_DMAC ) ;

    /* Read the dwChannel handler status to ensure the channel is a free channel */
    dwStatus = DMA_GetChannelStatus( DMAC ) ;
    TRACE_INFO( "DMAD_Initialize dwChannel %x  \n\r", dwChannel ) ;
    assert( (dwStatus & (1 << dwChannel)) == 0 ) ;

    /* Clear any pending interrupts on the channel */
    DMA_GetStatus( DMAC ) ;

    /* Disable the channel */
    DMA_DisableChannel( DMAC, dwChannel ) ;

    /* Disable the interrupt */
    dwFlag = 0x3FFFFF ;
    DMA_DisableIt( DMAC, dwFlag ) ;
    /* Enable DMA */
    DMA_Enable( DMAC ) ;

    if ( defaultHandler )
    {
        NVIC_EnableIRQ( DMAC_IRQn ) ;
    }

    // Initialize transfer instance.
    dmad.transfers[dwChannel].transferSize = 0;
}
Пример #4
0
//------------------------------------------------------------------------------
/// Starts buffer transfer on the given channel
/// \param channel Particular channel number.
/// \param size Total transfer size in byte.
/// \param callback Optional callback function.
/// \param polling Polling channel status enable.
//------------------------------------------------------------------------------
U8 DMAD_BufferTransfer(U8 channel, U32 size, DmaCallback callback, U8 polling)
{
	DmaTransfer *pTransfer = &(dmad.transfers[channel]);
	
	if (pTransfer-> transferSize > 0 ) // Check that no transfer is pending on the channel
	{
		DEBUG_MSG("DAM transfer is already pending");
		return DMAD_ERROR_BUSY;
	}
	pTransfer->status = DMAD_ERROR_BUSY; 
	pTransfer->transferSize = size;
	pTransfer->callback = callback; 

	if(!polling)
	{
		DMA_EnableIt(0x1 << channel);
	}
	DMA_EnableChannel(channel); // Enable the channel.
	if(polling)
	{
		while ((DMA_GetChannelStatus() & (0x1 << channel)) == (0x1 << channel));
		if (pTransfer->callback)
		{
			pTransfer->callback();
		}
		pTransfer->transferSize = 0;
		DMA_DisableChannel(channel);
	}
	return 0;
}
Пример #5
0
//------------------------------------------------------------------------------
/// Initializes the DMA controller.
/// \param channel Particular channel number
/// \param defaultHandler Using the default dmad interrupt handler.
//------------------------------------------------------------------------------
void DMAD_Initialize(unsigned char channel, unsigned char defaultHandler)
{
    unsigned int status;
    unsigned int flag;
     
    // Enable peripheral clock
#if !defined(at91sam9rl64)    
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_HDMA;    
#endif    
    
    // Read the channel handler status to ensure the channel is a free channel.
    status = DMA_GetChannelStatus();
    TRACE_INFO ("DMAD_Initialize channel %x  \n\r", channel);
    SANITY_CHECK(!(status & (1 << channel)));
    // Clear any pending interrupts on the channel.
    DMA_GetStatus();
    // Disble the channel.
    DMA_DisableChannel(channel);
    // Disable the interrupt
    flag = 0xffffff;
    DMA_DisableIt(flag);
    // Enable DMA.
    DMA_Enable();
    if(defaultHandler) 
    {
        IRQ_ConfigureIT(AT91C_ID_HDMA, 0, DMAD_Handler);
        IRQ_EnableIT(AT91C_ID_HDMA);
    }
    // Initialize transfer instance.
    dmad.transfers[channel].transferSize = 0;
}
Пример #6
0
//------------------------------------------------------------------------------
/// Returns 1 if no transfer is currently pending on the given channel;
/// otherwise, returns 0.
/// \param channel  Channel number.
//------------------------------------------------------------------------------
unsigned char DMAD_IsFinished(unsigned char channel)
{
    SANITY_CHECK(channel <= DMA_CHANNEL_NUM);
    if (dmad.transfers[channel].transferSize > 0) {
        return 0;
    }
    else {
        DMA_DisableChannel(channel);
        return 1;
    }
}
Пример #7
0
//------------------------------------------------------------------------------
/// Returns 1 if no transfer is currently pending on the given channel;
/// otherwise, returns 0.
/// \param channel  Channel number.
//------------------------------------------------------------------------------
U8 DMAD_IsFinished(U8 channel)
{
	if(dmad.transfers[channel].transferSize > 0)
	{
		return 0;
	}
	else
	{
		DMA_DisableChannel(channel);
		return 1;
	}
}
Пример #8
0
//------------------------------------------------------------------------------
/// Returns 1 if no transfer is currently pending on the given dwChannel;
/// otherwise, returns 0.
/// \param dwChannel  Channel number.
//------------------------------------------------------------------------------
extern uint32_t DMAD_IsFinished( uint32_t dwChannel )
{
    assert( dwChannel <= DMA_CHANNEL_NUM ) ;

    if ( dmad.transfers[dwChannel].transferSize > 0 )
    {
        return 0 ;
    }
    else
    {
        DMA_DisableChannel( DMAC, dwChannel ) ;

        return 1 ;
    }
}
Пример #9
0
//------------------------------------------------------------------------------
//         Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// This handler function must be called by the DMAC interrupt service routine.
/// Identifies which event was activated and calls the associated function.
//------------------------------------------------------------------------------
extern void DMAC_IrqHandler( void )
{
    uint32_t dwStatus ;
    uint32_t dwChannel ;
    DmaTransfer *pTransfer ;

    dwStatus = DMA_GetStatus( DMAC ) ;

    // Check if the buffer transfer completed is set.
    if ( dwStatus & (DMAC_EBCISR_BTC0|DMAC_EBCISR_BTC1|DMAC_EBCISR_BTC2|DMAC_EBCISR_BTC3|DMAC_EBCISR_BTC4|DMAC_EBCISR_BTC5) )
    {
        // Scan each dwChannel status.
        for ( dwChannel = 0 ; dwChannel < DMA_CHANNEL_NUM ; dwChannel++ )
        {
            if ( !(dwStatus & (DMAC_EBCISR_BTC0 << dwChannel)) )
            {
                continue ;
            }

            dmad.transfers[dwChannel].transferSize -= dmad.transfers[dwChannel].bufSize ;

            // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit.
            if ( dmad.transfers[dwChannel].transferSize <= dmad.transfers[dwChannel].bufSize )
            {
                DMA_ClearAutoMode( DMAC, dwChannel ) ;
            }

            // Transfer finished
            if ( dmad.transfers[dwChannel].transferSize == 0 )
            {
                pTransfer = &(dmad.transfers[dwChannel]) ;
                pTransfer->callback() ;
                DMA_DisableIt( DMAC, DMAC_EBCIDR_BTC0 << dwChannel ) ;
                DMA_DisableChannel( DMAC, dwChannel ) ;
            }
            else
            {
                // Write the KEEPON field to clear the STALL states.
                DMA_KeeponChannel( DMAC, dwChannel ) ;
            }
        }
    }
}
Пример #10
0
//------------------------------------------------------------------------------
/// Initializes the DMA controller.
/// \param channel Particular channel number
/// \param defaultHandler Using the default dmad interrupt handler.
//------------------------------------------------------------------------------
void DMAD_Initialize(U8 channel, U8 defaultHandler)
{
//	U32 status;
	U32 flag;
	
//	status = DMA_GetChannelStatus(); // Read the channel handler status to ensure the channel is a free channel.
//	DEBUG_MSG("DMAD_Initialize channel: %x, Status: %x", channel, status);
	DMA_GetStatus(); // Clear any pending interrupts on the channel.
	DMA_DisableChannel(channel); // Disble the channel.
	flag = 0xffffff;
	DMA_DisableIt(flag); // Disable the interrupt
	DMA_Enable(); // Enable DMA.
	if(defaultHandler) 
	{
		IRQ_PeriConf(21, 0, DMAD_Handler);
		IRQ_PeriEn(21);
	}
	dmad.transfers[channel].transferSize = 0; // Initialize transfer instance.
}
Пример #11
0
//------------------------------------------------------------------------------
/// Starts buffer transfer on the given dwChannel
/// \param dwChannel Particular dwChannel number.
/// \param size Total transfer size in byte.
/// \param callback Optional callback function.
/// \param polling Polling dwChannel status enable.
//------------------------------------------------------------------------------
extern uint32_t DMAD_BufferTransfer( uint32_t dwChannel, uint32_t dwSize,
                                     DmaCallback callback, uint32_t dwPolling )
{
    DmaTransfer *pTransfer = &(dmad.transfers[dwChannel]) ;

    // Check that no transfer is pending on the dwChannel
    if ( pTransfer-> transferSize > 0 )
    {
        TRACE_ERROR( "DAM transfer is already pending\n\r" ) ;

        return DMAD_ERROR_BUSY ;
    }

    pTransfer->status = DMAD_ERROR_BUSY ;
    pTransfer->transferSize = dwSize ;
    pTransfer->callback = callback ;

    if ( dwPolling == 0 )
    {
        DMA_EnableIt( DMAC, DMA_BTC << dwChannel ) ;
    }

    // Enable the dwChannel.
    DMA_EnableChannel( DMAC, dwChannel ) ;

    if ( dwPolling != 0 )
    {
        while ( (DMA_GetChannelStatus( DMAC ) & (DMAC_CHSR_ENA0 << dwChannel)) == (DMAC_CHSR_ENA0 << dwChannel)) ;

        if ( pTransfer->callback )
        {
            pTransfer->callback() ;
        }
        pTransfer->transferSize = 0 ;
        DMA_DisableChannel( DMAC, dwChannel ) ;
    }

    return 0 ;
}
Пример #12
0
//------------------------------------------------------------------------------
/// This handler function must be called by the DMAC interrupt service routine.
/// Identifies which event was activated and calls the associated function.
//------------------------------------------------------------------------------ 
void DMAD_Handler()
{
	U32 status;
	U8 channel;
	DmaTransfer *pTransfer;

	status = DMA_GetStatus();
	if(status & (0xFF)) // Check if the buffer transfer completed is set.
	{
		for(channel = 0; channel < 8; channel++) // Scan each channel status.
		{
			if(!(status & (0x1 << channel)))
			{
				continue;
			}

			dmad.transfers[channel].transferSize -= dmad.transfers[channel].bufSize;
			if(dmad.transfers[channel].transferSize <= dmad.transfers[channel].bufSize) // if next buffer is to be the last buffer in the transfer, then clear the automatic mode bit.
			{
				DMA_ClearAutoMode(channel);
			}

			if(dmad.transfers[channel].transferSize == 0) // Transfer finished
			{
				pTransfer = &(dmad.transfers[channel]);
				pTransfer->callback();
				DMA_DisableIt(0x1 << channel); 
				DMA_DisableChannel(channel);
			}
			else
			{
				DMA_KeeponChannel(channel); // Write the KEEPON field to clear the STALL states.
			}
		}
	}
}
int main(void)
{
	facilitatePowersaving();

	// Configure switches
	PORTCFG.MPCMASK = 0xff; // Configure several PINxCTRL registers at the same time
	SWITCHPORT.PIN0CTRL = (SWITCHPORT.PIN0CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLUP_gc; //Enable pull-up to get a defined level on the switches

	SWITCHPORT.DIRCLR = 0xff; // Set port as input

	// Configure LEDs
	PORTCFG.MPCMASK = 0xff; // Configure several PINxCTRL registers at the same time
	LEDPORT.PIN0CTRL = PORT_INVEN_bm; // Invert input to turn the leds on when port output value is 1

	LEDPORT.DIRSET = 0xff; 	// Set port as output
	LEDPORT.OUT = 0x00;  // Set initial value


	// Set up ADCB0 on PB0 to read temp sensor. More of this can be achieved by using driver from appnote AVR1300
	PORTQ.PIN2CTRL = (PORTQ.PIN2CTRL & ~PORT_OPC_gm) | PORT_OPC_PULLDOWN_gc;	// This pin must be grounded to "enable" NTC-resistor
	PORTB.DIRCLR = PIN0;
	PORTB.PIN0CTRL = (PORTB.PIN0CTRL & ~PORT_OPC_gm);

	ADC_CalibrationValues_Load(&ADCB);  // Load factory calibration data for ADC
	ADCB.CH0.CTRL = (ADCB.CH0.CTRL & ~ADC_CH_INPUTMODE_gm) | ADC_CH_INPUTMODE_SINGLEENDED_gc; // Single ended input
	ADCB.CH0.MUXCTRL = (ADCB.CH0.MUXCTRL & ~ADC_CH_MUXPOS_gm) | ADC_CH_MUXPOS_PIN0_gc; // Pin 0 is input	
	ADCB.REFCTRL = (ADCB.REFCTRL & ~ADC_REFSEL_gm) | ADC_REFSEL_VCC_gc;	// Internal AVCC/1.6 as reference

	ADCB.CTRLB |= ADC_FREERUN_bm; // Free running mode
	ADCB.PRESCALER = (ADCB.PRESCALER & ~ADC_PRESCALER_gm) | ADC_PRESCALER_DIV512_gc; // Divide clock by 1024.
	ADCB.CTRLB = (ADCB.CTRLB & ~ADC_RESOLUTION_gm) | ADC_RESOLUTION_8BIT_gc; // Set 8 bit resolution
	ADCB.CTRLA |= ADC_ENABLE_bm; // Enable ADC
	

	// Set up DMA CH0 to transfer from ADC to LEDS. We only read low byte.
	DMA_Enable();
	DMA_SetupBlock( 
                    &DMA.CH0,
			        (void const *) &(ADCB.CH0RES), 
                    DMA_CH_SRCRELOAD_NONE_gc, 
                    DMA_CH_SRCDIR_FIXED_gc,
			        (void const *) &(LEDPORT.OUT), 
                    DMA_CH_DESTRELOAD_NONE_gc, 
                    DMA_CH_DESTDIR_FIXED_gc,
			        1, 
                    DMA_CH_BURSTLEN_1BYTE_gc, 
                    0,
                    true
                );
    DMA_EnableSingleShot( &DMA.CH0 );
	DMA_SetTriggerSource( &DMA.CH0, DMA_CH_TRIGSRC_ADCB_CH0_gc ); // ADC Channel 0 is trigger source.
	


	// Set up interrupt on button 0, or else we can't come back from IDLE
	SWITCHPORT.INTCTRL = (SWITCHPORT.INTCTRL & ~PORT_INT0LVL_gm) | PORT_INT0LVL_LO_gc;
	SWITCHPORT.INT0MASK = SWITCHMASK_ACTIVE;
	SWITCHPORT.PIN0CTRL = (SWITCHPORT.PIN0CTRL & ~PORT_ISC_gm) | PORT_ISC_FALLING_gc;


	// Enable low interrupt level in PMIC and enable global interrupts.
	PMIC.CTRL |= PMIC_LOLVLEN_bm;
	sei();

	// Main loop.
	while (1) {

		if ((SWITCHPORT.IN & SWITCHMASK_ACTIVE) == 0x00)
		{
		// Button 0 pressed. Enter ACTIVE mode again.
			DMA_DisableChannel( &DMA.CH0 );

			SLEEP.CTRL &= ~SLEEP_SEN_bm;	// Disable sleep. sleep() is now ineffective.

		} else if ((SWITCHPORT.IN & SWITCHMASK_IDLE) == 0x00)	
	    {	
		// Button 1 pressed. Enter Idle mode
			DMA_EnableChannel( &DMA.CH0 );			

			// Set and enable sleep.
			SLEEP.CTRL = (SLEEP.CTRL & ~SLEEP_SMODE_gm) | SLEEP_SMODE_IDLE_gc;
			SLEEP.CTRL |= SLEEP_SEN_bm; // Enable sleep.

		} else if (SLEEP.CTRL & SLEEP_SEN_bm) {
			 	// We are in wanting-to-sleep mode, but were awake.
				sleep();
	
		} else { 
			// Do active sampling and transfer of ADC data.
			LEDPORT.OUT = ADCB.CH0RES & 0xFF;
		}

	}
	
}