Пример #1
0
/*******************************************************************************
  Function:
    void SYS_DMA_TasksISR(SYS_MODULE_OBJ object, DMA_CHANNEL activeChannel)

  Summary:
    Maintains the system service's state machine and implements its ISR

  Description:
    This routine is used to maintain the DMA system service's internal state machine
    and implement its ISR for DMA interrupt trigger implementations(interrupt mode).
    This function is specifically designed for DMA interrupt trigger
    implementations (interrupt mode).
    In interrupt mode, this function should be called in the interrupt
    service routine of the DMA channel that is associated with this transfer.

  Remarks:
    It is called by appropriate raw ISR.

    This routine may execute in an ISR context and will never block or access any
    resources that may cause it to block.
 */
void SYS_DMA_TasksISR(SYS_MODULE_OBJ object, DMA_CHANNEL activeChannel)
{
    SYS_DMA_CHANNEL_OBJECT *chanObj;
    DMA_CHANNEL_INT_SOURCE chanIntSrc;

    /* Find out the interrupt source number for the active DMA channel */
     chanIntSrc = PLIB_DMA_ChannelXTriggerSourceNumberGet(DMA_ID_0, activeChannel);

    /* Check whether the active DMA channel interrupt has occurred */
   // if(true == SYS_INT_SourceStatusGet(chanIntSrc))
   // {
        if(true == PLIB_DMA_ChannelXINTSourceFlagGet(DMA_ID_0,activeChannel,
                        DMA_INT_BLOCK_TRANSFER_COMPLETE))
        {
            /* Channel is by default disabled on completion of a block transfer */

            /* Clear the Block transfer complete flag */
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,activeChannel,
                     DMA_INT_BLOCK_TRANSFER_COMPLETE);

            SYS_INT_SourceStatusClear(chanIntSrc);

            /* Find out the channel object and give a callback */
            chanObj = (SYS_DMA_CHANNEL_OBJECT *) &gSysDMAChannelObj[activeChannel];
            chanObj->errorInfo = SYS_DMA_ERROR_NONE;
			if(NULL != chanObj->pEventCallBack)
			{
	            chanObj->pEventCallBack(SYS_DMA_TRANSFER_EVENT_COMPLETE,
                         (SYS_DMA_CHANNEL_HANDLE)chanObj,chanObj->hClientArg);
			}

        }
        else if(true == PLIB_DMA_ChannelXINTSourceFlagGet(DMA_ID_0,activeChannel,
                        DMA_INT_TRANSFER_ABORT))
        {
            /* Channel is by default disabled on Transfer Abortion */

            /* Clear the Abort transfer complete flag */
            PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,activeChannel,
                        DMA_INT_TRANSFER_ABORT);

            SYS_INT_SourceStatusClear(chanIntSrc);

            /* Find out the channel object and give a callback */
            chanObj = (SYS_DMA_CHANNEL_OBJECT *) &gSysDMAChannelObj[activeChannel];
            chanObj->errorInfo = SYS_DMA_ERROR_NONE;
			if(NULL != chanObj->pEventCallBack)
			{
	            chanObj->pEventCallBack(SYS_DMA_TRANSFER_EVENT_ABORT,
                        (SYS_DMA_CHANNEL_HANDLE)chanObj,chanObj->hClientArg);
			}
        }
        else
        {
            ;
        }
  //  }
    return;
}
Пример #2
0
/****************************************************************************
 * Function:        TcpIpEthIsr
 *
 * PreCondition:    TCPIPInit, PIC32MACEventSetNotifyEvents should have been called.
 *
 * Input:           p - PIC32 MAC descriptor pointer
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function processes the Ethernet interrupts and reports the events back to the user.
 *
 * Note:            None
 ******************************************************************************/
static void TcpIpEthIsr(void* p)
{
    eEthEvents          currEthEvents, currGroupEvents;
    PIC32_EV_GROUP_DCPT* pDcpt;
    int                 grpIx;
    PIC32_EMB_MAC_DCPT* pMacD = (PIC32_EMB_MAC_DCPT*)p;

    currEthEvents = EthEventsGet();

    // process per group
    pDcpt = pMacD->mData._pic32_ev_group_dcpt;
    for(grpIx = 0; grpIx < sizeof(pMacD->mData._pic32_ev_group_dcpt)/sizeof(*pMacD->mData._pic32_ev_group_dcpt); grpIx++)
    {
        currGroupEvents = currEthEvents & pDcpt->_EthEnabledEvents;     //  keep just the relevant ones
        if(currGroupEvents)
        {
            pDcpt->_EthPendingEvents |= currGroupEvents;                    // add the new events
            pDcpt->_TcpPendingEvents |= _XtlEventsEth2Tcp(currGroupEvents);

            EthEventsEnableClr(currGroupEvents);         // these will get reported; disable them until ack is received back
            EthEventsClr(currGroupEvents);               // acknowledge the ETHC
            if(pDcpt->_TcpNotifyFnc)
            {
                (*pDcpt->_TcpNotifyFnc)(pDcpt->_TcpNotifyParam, pDcpt->_TcpPendingEvents);     // let the user know
            }
        }
        pDcpt++;
    }



    SYS_INT_SourceStatusClear(pMacD->mData._macIntSrc);         // acknowledge the int Controller
}
Пример #3
0
void DRV_USART_TasksTransmit(SYS_MODULE_OBJ object)
{
    /* This is the USART Driver Transmit tasks routine.
       In this function, the driver checks if a transmit
       interrupt is active and if there are any buffers in
       queue. If so the buffer is serviced. A buffer that
       is serviced completely is removed from the queue.
     */

    DRV_USART_OBJ * hDriver = &gDrvUSARTObj[object];

    if((!hDriver->inUse) || (hDriver->status != SYS_STATUS_READY))
    {
        /* This intance of the driver is not initialized. Don't
         * do anything */
        return;
    }

    if(SYS_INT_SourceStatusGet(hDriver->txInterruptSource))
    {
        /* The USART driver is configured to generate an
           interrupt when the FIFO is empty. Additionally
           the queue is not empty. Which means there is 
           work to done in this routine. */

        _DRV_USART_TRANSMIT_BUFFER_QUEUE_TASKS(hDriver);        
        
        /* Clear up the interrupt flag */
        SYS_INT_SourceStatusClear(hDriver->txInterruptSource);
    }
}
Пример #4
0
/*******************************************************************************
  Function:
    TCPIP_MAC_EVENT_RESULT    MRF24W_MACEventSetNotifyHandler(TCPIP_MAC_HANDLE hMac, TCPIP_MAC_EVENT_GROUP tcpEvGroup, pMacEventF eventHandler, void* hParam)

  Summary:
    Sets a new event notification handler.

  Description:
    This function sets a new event notification handler.
    This is a handler specified by the user of the stack.
    The caller can use the handler to be notified of MAC events.
    Whenever a notification occurs the passed events have to be eventually processed:
    - Stack should process the TCPIP_EV_RX_PKTPEND, TCPIP_EV_TX_DONE  events
    - Process the specific (error) condition
    - Acknowledge the events by calling MRF24W_MACEventAck() so that they can be re-enabled.

  Precondition:
   TCPIPInit should have been called.
   tcpEvGroup valid value 

  Parameters:
    hMac      - parameter identifying the intended MAC  
    tcpEvGroup   - group of events the notification handler refers to
    eventHandler - the event notification handler
    
  Returns:
    TCPIP_MAC_EVRES_OK  if operation succeeded,
    an error code otherwise

  Example:
    <code>
    MRF24W_MACEventSetNotifyHandler( hMac, TCPIP_MAC_EVGROUP_ALL, myEventHandler, myParam );
    </code>

  Remarks:   
    The notification handler will be called from the ISR which detects the corresponding event.
    The event notification handler has to be kept as short as possible and non-blocking.
    Mainly useful for RTOS integration where this handler will wake-up a thread that waits for a MAC event to occur.

    The event notification system also enables the user of the TCPIP stack to call into the stack
    for processing only when there are relevant events rather than being forced to periodically call
    from within a loop at unknown moments.

    Without a notification handler the stack user can still call MRF24W_MACEventGetPending() to see if processing by the stack needed.

    This is a default way of adding interrupt processing to the stack.
    A separate ISR to catch the Ethernet MAC events and process accordingly
    could be added.

    All the groups specified in the TCPIP_MAC_EVENT_GROUP enumeration is supported.
    However, once a handler for TCPIP_MAC_EVGROUP_ALL is registered all event processing
    will be reported using this global handler.

    Use 0 to remove the handler for a specific event group.

    Not multi-threaded safe accross different TCPIP_MAC_EVENT_GROUP groups.
*****************************************************************************/
TCPIP_MAC_EVENT_RESULT MRF24W_MACEventSetNotifyHandler(TCPIP_MAC_HANDLE hMac, TCPIP_MAC_EVENT_GROUP tcpEvGroup, pMacEventF eventHandler, void* hParam)
{
    if(tcpEvGroup != TCPIP_MAC_EVGROUP_ALL)
    {
        return TCPIP_MAC_EVRES_GROUP_ERR;
    }
        
    int rfILev;
    
    if(_mrfGroupDcpt._mrfEnabledEvents)
    {   // already have some active     
        rfILev = SYS_INT_SourceDisable(MRFWB0M_INT_SOURCE);      // stop ints for a while

        _mrfGroupDcpt._mrfNotifyFnc = eventHandler;     // set new handler
        _mrfGroupDcpt._mrfNotifyParam = hParam;   
    
        SYS_INT_SourceStatusClear(MRFWB0M_INT_SOURCE);
        SYS_INT_SourceRestore(MRFWB0M_INT_SOURCE, rfILev);   // re-enable
    }
    else
    {
        _mrfGroupDcpt._mrfNotifyFnc = eventHandler;     // set new handler
        _mrfGroupDcpt._mrfNotifyParam = hParam;   
    }
    return TCPIP_MAC_EVRES_OK;
}
Пример #5
0
/*******************************************************************************
  Function:
    TCPIP_MAC_EVENT_RESULT    PIC32MACEventInit(TCPIP_MAC_HANDLE hMac, int intPri, int intSubPri)

  Summary:
    Initializes the ethernet event notification.

  Description:
     This function initializes the ethernet event notification.
     It performs any resource allocation that may be needed.

  Precondition:
     None.

  Parameters:
    hMac      - parameter identifying the intended MAC  
    intPri     - priority of the TCPIP interrupt events
    intSubPri  - sub-priority of the TCPIP interrupt events
    
  Returns:
    TCPIP_MAC_EVRES_OK  if initialization succeeded,
    an error code otherwise

  Example:
    <code>
    PIC32MACEventInit( hMac, 4, 3 );
    </code>

  Remarks:

    Not multi-threaded safe.
*****************************************************************************/
TCPIP_MAC_EVENT_RESULT PIC32MACEventInit(TCPIP_MAC_HANDLE hMac, int intPri, int intSubPri)
{
    int grpIx;
    PIC32_EV_GROUP_DCPT*    pDcpt; 
    PIC32_EMB_MAC_DCPT*     pMacD = (PIC32_EMB_MAC_DCPT*)hMac;

    SYS_INT_SourceDisable(pMacD->mData._macIntSrc);      // stop Eth ints
    SYS_INT_SourceStatusClear(pMacD->mData._macIntSrc);
    SYS_INT_PrioritySet(pMacD->mData._macIntSrc, (INT_PRIORITY_LEVEL_1-1)+intPri);
    SYS_INT_SubprioritySet(pMacD->mData._macIntSrc, INT_SUB_PRIORITY_LEVEL_0+intSubPri);
    SYS_INT_DynamicRegister(pMacD->mData._macIntSrc, TcpIpEthIsr, pMacD); 
    
    pDcpt = pMacD->mData._pic32_ev_group_dcpt;
    for(grpIx = 0; grpIx < sizeof(pMacD->mData._pic32_ev_group_dcpt)/sizeof(*pMacD->mData._pic32_ev_group_dcpt); grpIx++)
    {
        pDcpt->_TcpGroupEventsMask = _pic32_mac_group_ev_mask[grpIx];
        pDcpt->_TcpEnabledEvents = pDcpt->_TcpPendingEvents = TCPIP_EV_NONE;
        pDcpt->_EthEnabledEvents = pDcpt->_EthPendingEvents = 0;
        pDcpt->_TcpNotifyFnc = 0;
        pDcpt++;
    }

    _hEventMac = hMac;    
    return TCPIP_MAC_EVRES_OK;
}
Пример #6
0
int32_t DRV_SPI1_ISRErrorTasks(struct DRV_SPI_OBJ * dObj)
{

    if (dObj->currentJob == NULL)
    {
        return 0;
    }

    register DRV_SPI_JOB_OBJECT * currentJob = dObj->currentJob;

    if (PLIB_SPI_ReceiverHasOverflowed(SPI_ID_2))
    {
        if (currentJob->completeCB != NULL)
        {
            (*currentJob->completeCB)(DRV_SPI_BUFFER_EVENT_ERROR, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
        }
        currentJob->status = DRV_SPI_BUFFER_EVENT_ERROR;
        if (dObj->operationEnded != NULL)
        {
            (*dObj->operationEnded)(DRV_SPI_BUFFER_EVENT_ERROR, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
        }
        if (DRV_SPI_SYS_QUEUE_FreeElement(dObj->queue, currentJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
        {
            SYS_ASSERT(false, "\r\nSPI Driver: Queue free element error.");
            return 0;
        }
        dObj->currentJob = NULL;
        PLIB_SPI_BufferClear(SPI_ID_2);
        PLIB_SPI_ReceiverOverflowClear (SPI_ID_2 );
        SYS_INT_SourceStatusClear(INT_SOURCE_SPI_2_ERROR);

    }
    return 0;
}
Пример #7
0
void __ISR( _TIMER_3_VECTOR ) _T3Interrupt(void)
{

    GFX_DRV_SSD1926_Tasks();

    // Clear flag
    SYS_INT_SourceStatusClear(INT_SOURCE_TIMER_3);
}
Пример #8
0
/*******************************************************************************
  Function:
    TCPIP_MAC_RES    MRF24W_MACEventDeInit(TCPIP_MAC_HANDLE hMac )

  Summary:
    De-initializes the Ethernet event notification.

  Description:
     This function de-initializes the Ethernet event notification.
     It performs any resource clean-up that may be needed.

  Precondition:
     None.

  Parameters:
    hMac      - parameter identifying the intended MAC

  Returns:
    TCPIP_MAC_RES_OK  always

  Example:
    <code>
    MRF24W_MACEventDeInit( hMac );
    </code>

  Remarks:

    Not multi-threaded safe.
 *******************************************************************************/
TCPIP_MAC_RES MRF24W_MACEventDeInit(MRF24W_MAC_DCPT *pDcpt)
{
    SYS_INT_SourceDisable(MRF_INT_SOURCE); // stop MRF ints
    SYS_INT_SourceStatusClear(MRF_INT_SOURCE);

    s_mrfGroupDcpt.mrfNotifyFnc     = 0;
    s_mrfGroupDcpt.mrfEnabledEvents = false;
    s_mrfGroupDcpt.mrfPendingEvents = 0;

    return TCPIP_MAC_RES_OK;
}
/****************************************************************************
 * Function:        DRV_EXTPHY_IntInit
 *
 * PreCondition:    EthInit and EthPhyInit should have been called.
 *
 * Input:         hClientObj - A valid open-instance handle, returned from the driver's open routine
 *                  src - interrupt source
 *                  intPri - intrrupt priority
 *                  intSubPri - Interuupt Sub Priority
 *
 * Output:         none
 *
 *
 * Side Effects:    None
 *
 * Overview:       Initialize External Interrupt 3.	One can take this as reference for their WOL 
 *                      Interrupt.
 *
 * Note:            None
 *****************************************************************************/
void DRV_EXTPHY_IntInit(DRV_HANDLE hClientObj,INT_SOURCE src,int intPri, int intSubPri)
{
	// set up the External Interrupt 3 with a prioirty of 5 and 1 sub-priority    

    SYS_INT_SourceDisable(src);      // stop Eth ints
    SYS_INT_SourceStatusClear(src);
    SYS_INT_VectorPrioritySet(src, intPri);
    SYS_INT_VectorSubprioritySet(src, intSubPri);

    SYS_INT_SourceEnable(src);

}
Пример #10
0
/*********************************************************************
 * Function: Timer4 ISR
 *
 * PreCondition: none
 *
 * Input: none
 *
 * Output: none
 *
 * Side Effects: none
 *
 * Overview: increments tick counter. Tick is approx. 1 ms.
 *
 * Note: none
 *F
 ********************************************************************/
void __ISR( _TIMER_4_VECTOR ) _T4Interrupt(void)
{
    TouchGetMsg();
    
    SYS_MSG_Tasks( hSysMsg );

    tick++;

    TouchDetectPosition();

    // Clear flag
    SYS_INT_SourceStatusClear(INT_SOURCE_TIMER_4);
}
Пример #11
0
/*******************************************************************************
  Function:
    TCPIP_MAC_EVENT_RESULT    MRF24W_MACEventDeInit(TCPIP_MAC_HANDLE hMac )

  Summary:
    De-initializes the ethernet event notification.

  Description:
     This function de-initializes the ethernet event notification.
     It performs any resource clean-up that may be needed.

  Precondition:
     None.

  Parameters:
    hMac      - parameter identifying the intended MAC  
    
  Returns:
    TCPIP_MAC_EVRES_OK  always

  Example:
    <code>
    MRF24W_MACEventDeInit( hMac );
    </code>

  Remarks:

    Not multi-threaded safe.
*****************************************************************************/
TCPIP_MAC_EVENT_RESULT MRF24W_MACEventDeInit(TCPIP_MAC_HANDLE hMac)
{


    SYS_INT_SourceDisable(MRFWB0M_INT_SOURCE);      // stop MRF ints
    SYS_INT_SourceStatusClear(MRFWB0M_INT_SOURCE);
    SYS_INT_DynamicRegister(MRFWB0M_INT_SOURCE, 0, 0); 

    _mrfGroupDcpt._mrfNotifyFnc = 0;
    _mrfGroupDcpt._mrfEnabledEvents = false;
    _mrfGroupDcpt._mrfPendingEvents = 0;

    return TCPIP_MAC_EVRES_OK;
}
Пример #12
0
/*******************************************************************************
 * Function:        DRV_WIFI_MRF24W_ISR
 *
 * PreCondition:    TCPIPInit, _MRF24W_MACEventSetMask should have been called.
 *
 * Input:           p - unused
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function processes the Ethernet interrupts and reports the events back to the user.
 *
 * Note:            None
 *******************************************************************************/
void DRV_WIFI_MRF24W_ISR(SYS_MODULE_OBJ index)
{
    if (s_mrfGroupDcpt.mrfEnabledEvents )
    {
        s_mrfGroupDcpt.mrfPendingEvents = TCPIP_MAC_EV_TX_DONE;
        if (s_mrfGroupDcpt.mrfNotifyFnc)
        {
            (*s_mrfGroupDcpt.mrfNotifyFnc)(s_mrfGroupDcpt.mrfPendingEvents, s_mrfGroupDcpt.mrfNotifyParam);
        }
    }

    SYS_INT_SourceDisable(MRF_INT_SOURCE); // disable further interrupts
    SYS_INT_SourceStatusClear(MRF_INT_SOURCE); // acknowledge the int Controller

    /* invoke MRF handler */
    DRV_WIFI_INT_Handle();
}
Пример #13
0
/****************************************************************************
 * Function:        MRF24W_ISR
 *
 * PreCondition:    TCPIPInit, MRF24W_MACEventSetNotifyEvents should have been called.
 *
 * Input:           p - unused
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        This function processes the Ethernet interrupts and reports the events back to the user.
 *
 * Note:            None
 ******************************************************************************/
void MRF24W_ISR(void* p)
{
    
    if(_mrfGroupDcpt._mrfEnabledEvents )
    {
        _mrfGroupDcpt._mrfPendingEvents = TCPIP_EV_RX_PKTPEND|TCPIP_EV_TX_DONE;
        if(_mrfGroupDcpt._mrfNotifyFnc)
        {
            (*_mrfGroupDcpt._mrfNotifyFnc)(_mrfGroupDcpt._mrfNotifyParam, _mrfGroupDcpt._mrfPendingEvents);  
        }
        
    }
    
    SYS_INT_SourceDisable(MRFWB0M_INT_SOURCE);        // disable further interrupts
    SYS_INT_SourceStatusClear(MRFWB0M_INT_SOURCE);      // acknowledge the int Controller

    /* invoke MRF handler */
    WFEintHandler();
}
Пример #14
0
/****************************************************************************
 * Function:        DRV_EXTPHY_IntInit
 *
 * PreCondition:    EthInit and EthPhyInit should have been called.
 *
 * Input:         hClientObj - A valid open-instance handle, returned from the driver's open routine
 *                  src - interrupt source
 *                  intPri - intrrupt priority
 *                  intSubPri - Interuupt Sub Priority
 *
 * Output:         none
 *
 *
 * Side Effects:    None
 *
 * Overview:       Initialize External Interrupt 3.	One can take this as refreence for their WOL 
 *                      Interrupt.
 *
 * Note:            None
 *****************************************************************************/
static void DRV_EXTPHY_IntInit(DRV_HANDLE hClientObj,SYS_INT_SOURCE src,int intPri, int intSubPri)
{
	// set up the External Interrupt 3 with a prioirty of 5 and 1 sub-priority    

    SYS_INT_SourceDisable(src);      // stop Eth ints
    SYS_INT_SourceStatusClear(src);
    
#if defined (HARMONY_INT)
    SYS_INT_VectorPrioritySet(src, intPri);
    SYS_INT_VectorSubprioritySet(src, intSubPri);
#else
    SYS_INT_PrioritySet(src, intPri);
    SYS_INT_SubprioritySet(src, intSubPri);
    SYS_INT_DynamicRegister(src, LAN8740WOLIsr, (void*)&hClientObj);
#endif
    
    SYS_INT_SourceEnable(src);


}
Пример #15
0
/*******************************************************************************
  Function:
    TCPIP_MAC_EVENT_RESULT    MRF24W_MACEventInit(TCPIP_MAC_HANDLE hMac, int intPri, int intSubPri)

  Summary:
    Initializes the ethernet event notification.

  Description:
     This function initializes the ethernet event notification.
     It performs any resource allocation that may be needed.

  Precondition:
     None.

  Parameters:
    hMac      - parameter identifying the intended MAC  
    intPri     - priority of the TCPIP interrupt events
    intSubPri  - sub-priority of the TCPIP interrupt events
    
  Returns:
    TCPIP_MAC_EVRES_OK  if initialization succeeded,
    an error code otherwise

  Example:
    <code>
    MRF24W_MACEventInit( hMac, 4, 3 );
    </code>

  Remarks:

    Not multi-threaded safe.
*****************************************************************************/
TCPIP_MAC_EVENT_RESULT MRF24W_MACEventInit(TCPIP_MAC_HANDLE hMac, int intPri, int intSubPri)
{
    SYS_INT_SourceDisable(MRFWB0M_INT_SOURCE);      // stop MRF ints
    SYS_INT_SourceStatusClear(MRFWB0M_INT_SOURCE);
    SYS_INT_PrioritySet(MRFWB0M_INT_SOURCE, (INT_PRIORITY_LEVEL_1-1)+intPri);
#if defined (__C32__)
    SYS_INT_SubprioritySet(MRFWB0M_INT_SOURCE, INT_SUB_PRIORITY_LEVEL_0+intSubPri);
#endif
    SYS_INT_DynamicRegister(MRFWB0M_INT_SOURCE, MRF24W_ISR, 0); 
    
    _mrfGroupDcpt._mrfNotifyFnc = 0;
    _mrfGroupDcpt._mrfEnabledEvents = false;
    _mrfGroupDcpt._mrfPendingEvents = 0;

    _mrfUsrEvent.trafficEvents = _mrfUsrEvent.mgmtEvents = 0;
    _mrfUsrEvent.trafficEventInfo = _mrfUsrEvent.mgmtEventInfo =0;


    return TCPIP_MAC_EVRES_OK;
}
Пример #16
0
void SYS_DMA_TasksError(SYS_MODULE_OBJ object)
{
    SYS_DMA_CHANNEL_OBJECT *chanObj;
    DMA_CHANNEL channels;
    DMA_CHANNEL_INT_SOURCE chanIntSrc;

    /* Go through each DMA channel and service it */
    for (channels = DMA_CHANNEL_0; channels < DMA_NUMBER_OF_CHANNELS; channels++)
    {
		/* Find out the interrupt source number for the last active DMA channel */
		chanIntSrc = PLIB_DMA_ChannelXTriggerSourceNumberGet(DMA_ID_0, channels);

		/* Check whether the active DMA channel interrupt has occured */
		if(true == SYS_INT_SourceStatusGet(chanIntSrc))
		{
			if(true == PLIB_DMA_ChannelXINTSourceFlagGet(DMA_ID_0,channels,
						DMA_INT_ADDRESS_ERROR))
			{
				/* Channel is by default disabled on completion of a block transfer */

				/* Clear the Block transfer complete flag */
				PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0,channels,
						DMA_INT_ADDRESS_ERROR);

				SYS_INT_SourceStatusClear(chanIntSrc);

				/* Find out the channel object and give a callback */
				chanObj = (SYS_DMA_CHANNEL_OBJECT *) &gSysDMAChannelObj[channels];
				chanObj->errorInfo = SYS_DMA_ERROR_ADDRESS_ERROR;
                if(NULL != chanObj->pEventCallBack)
                {                
                    chanObj->pEventCallBack(SYS_DMA_TRANSFER_EVENT_ERROR,
						(SYS_DMA_CHANNEL_HANDLE)chanObj,chanObj->hClientArg);
                }
			}
		}
	}
    return;
}
Пример #17
0
/*******************************************************************************
  Function:
    TCPIP_MAC_RES    MRF24W_MACEventInit(TCPIP_MAC_HANDLE hMac, TCPIP_MAC_EventF eventF, const void* eventParam, int intPri, int intSubPri)

  Summary:
    Initializes the ethernet event notification.

  Description:
     This function initializes the ethernet event notification.
     It performs any resource allocation that may be needed.

  Precondition:
     None.

  Parameters:
    hMac      - parameter identifying the intended MAC  
    intPri     - priority of the TCPIP interrupt events
    intSubPri  - sub-priority of the TCPIP interrupt events
    
  Returns:
    TCPIP_MAC_RES_OK  if initialization succeeded,
    an error code otherwise

  Example:
    <code>
    MRF24W_MACEventInit( hMac, 4, 3 );
    </code>

  Remarks:

    Not multi-threaded safe.
*****************************************************************************/
TCPIP_MAC_RES MRF24W_MACEventInit(TCPIP_MAC_HANDLE hMac, TCPIP_MAC_EventF eventF, const void* eventParam, int intPri, int intSubPri)
{

#if 0  //todo: jian. you should fix this
    SYS_INT_SourceDisable(MRFWB0M_INT_SOURCE);      // stop MRF ints
    SYS_INT_SourceStatusClear(MRFWB0M_INT_SOURCE);
    SYS_INT_PrioritySet(MRFWB0M_INT_SOURCE, (INT_PRIORITY_LEVEL_1-1)+intPri);
    SYS_INT_SubprioritySet(MRFWB0M_INT_SOURCE, INT_SUB_PRIORITY_LEVEL_0+intSubPri);
#endif
    SYS_INT_DynamicRegister(MRFWB0M_INT_SOURCE, MRF24W_ISR, 0); 
    
    _mrfGroupDcpt._mrfNotifyFnc = eventF;     // set new handler
    _mrfGroupDcpt._mrfNotifyParam = eventParam;   
    _mrfGroupDcpt._mrfEnabledEvents = false;
    _mrfGroupDcpt._mrfPendingEvents = 0;

    _mrfUsrEvent.trafficEvents = _mrfUsrEvent.mgmtEvents = 0;
    _mrfUsrEvent.trafficEventInfo = _mrfUsrEvent.mgmtEventInfo =0;

 
    return TCPIP_MAC_RES_OK;
}
Пример #18
0
/*******************************************************************************
  Function:
    TCPIP_MAC_EVENT_RESULT    PIC32MACEventDeInit(TCPIP_MAC_HANDLE hMac )

  Summary:
    De-initializes the ethernet event notification.

  Description:
     This function de-initializes the ethernet event notification.
     It performs any resource clean-up that may be needed.

  Precondition:
     None.

  Parameters:
    hMac      - parameter identifying the intended MAC  
    
  Returns:
    TCPIP_MAC_EVRES_OK  always

  Example:
    <code>
    PIC32MACEventDeInit( hMac );
    </code>

  Remarks:

    Not multi-threaded safe.
*****************************************************************************/
TCPIP_MAC_EVENT_RESULT PIC32MACEventDeInit(TCPIP_MAC_HANDLE hMac)
{
    int grpIx;
    PIC32_EV_GROUP_DCPT*  pDcpt; 
    PIC32_EMB_MAC_DCPT*     pMacD = (PIC32_EMB_MAC_DCPT*)hMac;


    SYS_INT_SourceDisable(pMacD->mData._macIntSrc);      // stop Eth ints
    SYS_INT_SourceStatusClear(pMacD->mData._macIntSrc);
    SYS_INT_DynamicRegister(pMacD->mData._macIntSrc, 0, 0); 

    pDcpt = pMacD->mData._pic32_ev_group_dcpt;
    for(grpIx = 0; grpIx < sizeof(pMacD->mData._pic32_ev_group_dcpt)/sizeof(*pMacD->mData._pic32_ev_group_dcpt); grpIx++)
    {
        pDcpt->_TcpNotifyFnc = 0;
        pDcpt->_TcpEnabledEvents = pDcpt->_TcpPendingEvents = TCPIP_EV_NONE;
        pDcpt->_EthEnabledEvents = pDcpt->_EthPendingEvents = 0;
        pDcpt++;
    }

    _hEventMac = 0;
    return TCPIP_MAC_EVRES_OK;
}
Пример #19
0
/*******************************************************************************
  Function:
    TCPIP_MAC_EVENT_RESULT    PIC32MACEventSetNotifyHandler(TCPIP_MAC_HANDLE hMac, TCPIP_MAC_EVENT_GROUP tcpEvGroup, pMacEventF eventHandler, void* hParam)

  Summary:
    Sets a new event notification handler.

  Description:
    This function sets a new event notification handler.
    This is a handler specified by the user of the stack.
    The caller can use the handler to be notified of MAC events.
    Whenever a notification occurs the passed events have to be eventually processed:
    - Stack should process the TCPIP_EV_RX_PKTPEND, TCPIP_EV_TX_DONE  events
    - Process the specific (error) condition
    - Acknowledge the events by calling PIC32MACEventAck() so that they can be re-enabled.

  Precondition:
   TCPIPInit should have been called.
   tcpEvGroup valid value 

  Parameters:
    hMac      - parameter identifying the intended MAC  
    tcpEvGroup   - group of events the notification handler refers to
    eventHandler - the event notification handler
    
  Returns:
    TCPIP_MAC_EVRES_OK  if operation succeeded,
    an error code otherwise

  Example:
    <code>
    PIC32MACEventSetNotifyHandler( hMac, TCPIP_MAC_EVGROUP_ALL, myEventHandler, myParam );
    </code>

  Remarks:   
    The notification handler will be called from the ISR which detects the corresponding event.
    The event notification handler has to be kept as short as possible and non-blocking.
    Mainly useful for RTOS integration where this handler will wake-up a thread that waits for a MAC event to occur.

    The event notification system also enables the user of the TCPIP stack to call into the stack
    for processing only when there are relevant events rather than being forced to periodically call
    from within a loop at unknown moments.

    Without a notification handler the stack user can still call PIC32MACEventGetPending() to see if processing by the stack needed.

    This is a default way of adding interrupt processing to the stack.
    A separate ISR to catch the Ethernet MAC events and process accordingly
    could be added.

    All the groups specified in the TCPIP_MAC_EVENT_GROUP enumeration is supported.
    However, once a handler for TCPIP_MAC_EVGROUP_ALL is registered all event processing
    will be reported using this global handler.

    Use 0 to remove the handler for a specific event group.

    Not multi-threaded safe accross different TCPIP_MAC_EVENT_GROUP groups.
*****************************************************************************/
TCPIP_MAC_EVENT_RESULT PIC32MACEventSetNotifyHandler(TCPIP_MAC_HANDLE hMac, TCPIP_MAC_EVENT_GROUP tcpEvGroup, pMacEventF eventHandler, void* hParam)
{
    int                   ethILev;
    PIC32_EMB_MAC_DCPT*     pMacD = (PIC32_EMB_MAC_DCPT*)hMac;
    PIC32_EV_GROUP_DCPT*  pDcpt = pMacD->mData._pic32_ev_group_dcpt+tcpEvGroup; 
    
    if(pDcpt->_TcpEnabledEvents != 0)
    {   // already have some active     
        ethILev = SYS_INT_SourceDisable(pMacD->mData._macIntSrc);      // stop ints for a while

        pDcpt->_TcpNotifyFnc = eventHandler;     // set new handler
        pDcpt->_TcpNotifyParam = hParam;
    
        SYS_INT_SourceStatusClear(pMacD->mData._macIntSrc);
        SYS_INT_SourceRestore(pMacD->mData._macIntSrc, ethILev);   // re-enable
    }
    else
    {
        pDcpt->_TcpNotifyFnc = eventHandler;     // set new handler
        pDcpt->_TcpNotifyParam = hParam;
    }
    return TCPIP_MAC_EVRES_OK;
}
Пример #20
0
void DRV_USART_TasksReceive(SYS_MODULE_OBJ object)
{
    /* This is the USART Driver Receive tasks routine. If the receive
       interrupt flag is set, the tasks routines are executed.
     */

    DRV_USART_OBJ * hDriver = &gDrvUSARTObj[object];

    if((!hDriver->inUse) || (hDriver->status != SYS_STATUS_READY))
    {
        /* This intance of the driver is not initialized. Dont
           do anything */

        return;
    }

    if(SYS_INT_SourceStatusGet(hDriver->rxInterruptSource)) 
    {
        _DRV_USART_RECEIVE_BUFFER_QUEUE_TASKS(hDriver);        
    
        /* Clear up the interrupt flag */
        SYS_INT_SourceStatusClear(hDriver->rxInterruptSource);
    }
}
		void __attribute__((interrupt, no_auto_psv)) _MI2C2Interrupt(void)
	#endif
#endif
{
    ACCEL_BOOL polling;
    ACCEL_CMD_DATA *pCmdData;
    uint32_t *pIndex;
//    uint8_t **pRxBuffer;
    uint8_t *pRxBuffer;
    
//    if(I2CPriority == ACCEL_PRIORIY)
//    {
//        pCmdData = accelData;
//        pIndex = &accelIdx;
////        pRxBuffer = &AccelRxBuffer;
//        pRxBuffer = AccelRxBuffer;
//    }
//    else
//    {
////        pCmdData = (ACCEL_CMD_DATA *)EepromI2CData;
////        pIndex = &EepromI2CIdx;
////        pRxBuffer = &EepromRxBuffer;
//    }
    
    pCmdData = accelData;
    pIndex = &accelIdx;
    pRxBuffer = AccelRxBuffer;
//    AccelRxBuffer += 4;
    
    if(SYS_INT_SourceStatusGet(ACCEL_BMA250_I2C_SOURCE))
    {
        polling = ACCEL_FALSE;

        switch(pCmdData[*pIndex].cmd)
        {
        case ACCEL_CMD_START:
            PLIB_I2C_MasterStart(ACCEL_BMA250_I2C_MODULE);
            break;

        case ACCEL_CMD_RESTART:
            PLIB_I2C_MasterStartRepeat(ACCEL_BMA250_I2C_MODULE);
            break;

        case ACCEL_CMD_STOP:
            PLIB_I2C_MasterStop(ACCEL_BMA250_I2C_MODULE);
            break;

        case ACCEL_CMD_TX_BYTE:
            PLIB_I2C_TransmitterByteSend(ACCEL_BMA250_I2C_MODULE, pCmdData[*pIndex].data);
            break;

        case ACCEL_CMD_EN_RX:
            PLIB_I2C_MasterReceiverClock1Byte(ACCEL_BMA250_I2C_MODULE);
            break;

        case ACCEL_CMD_RX_BYTE:
//            **pRxBuffer = PLIB_I2C_ReceivedByteGet(ACCEL_BMA250_I2C_MODULE);
//            (*pRxBuffer)++;
            *pRxBuffer = PLIB_I2C_ReceivedByteGet(ACCEL_BMA250_I2C_MODULE);
            pRxBuffer++;
            break;

        case ACCEL_CMD_ACK:
            PLIB_I2C_ReceivedByteAcknowledge(ACCEL_BMA250_I2C_MODULE, pCmdData[*pIndex].data);
            break;

        case ACCEL_CMD_ACK_POLL:
            polling = ACCEL_TRUE;
            if(!PLIB_I2C_TransmitterByteWasAcknowledged(ACCEL_BMA250_I2C_MODULE))

            {
                (*pIndex) -= 4;
            }
           break;

        default:
            accelData[*pIndex].cmd = ACCEL_DONE;
        case ACCEL_DONE:
#ifndef ACCEL_USE_EXTERNAL_INTERUPT_HANDLER
            SYS_INT_SourceDisable(ACCEL_BMA250_I2C_SOURCE);
            accelData[0].cmd = ACCEL_DONE;
            break;
#else
            *pIndex = ACCEL_INVALID_IDX;
            return;
#endif
        }
        SYS_INT_SourceStatusClear(ACCEL_BMA250_I2C_SOURCE);

        if(pCmdData[*pIndex].cmd != ACCEL_DONE)
        {
            if((pCmdData[*pIndex].cmd == ACCEL_CMD_RX_BYTE) || (polling))
            {
                SYS_INT_SourceStatusSet(ACCEL_BMA250_I2C_SOURCE);
            }

            (*pIndex)++;
        }else
        {
            *pIndex = ACCEL_INVALID_IDX;
            I2CPriority = FREE_PRIORITY;
        }
    }

}
Пример #22
0
SYS_MODULE_OBJ DRV_USART_Initialize
(
    const SYS_MODULE_INDEX drvIndex,
    const SYS_MODULE_INIT * const init
)
{
    DRV_USART_OBJ *dObj = (DRV_USART_OBJ*)NULL;
    DRV_USART_INIT *usartInit = NULL ;

    /* Check if the specified driver index is in valid range */
    if(drvIndex >= DRV_USART_INSTANCES_NUMBER)
    {
        SYS_DEBUG(0, "Invalid driver index");
        return SYS_MODULE_OBJ_INVALID;
    }

    /* Check if this hardware instance was already initialized */
    if(gDrvUSARTObj[drvIndex].inUse != false)
    {
        SYS_DEBUG(0, "Instance already in use");
        return SYS_MODULE_OBJ_INVALID;
    }

    /* Assign to the local pointer the init data passed */
    usartInit = ( DRV_USART_INIT * ) init ;

    /* Disable the USART module */
    PLIB_USART_Disable (usartInit->usartID) ;

    /* Allocate the driver object and set the operation flag to be in use */
    dObj = &gDrvUSARTObj[drvIndex];
    dObj->inUse = true;

    /* Update the USART PLIB Id and other parameters. */

    dObj->nClients              = 0;
    dObj->moduleId              = usartInit->usartID;
    dObj->brgClock              = usartInit->brgClock;
    dObj->isExclusive           = false;
    dObj->queueSizeRead         = usartInit->queueSizeReceive;
    dObj->queueSizeWrite        = usartInit->queueSizeTransmit;
    dObj->dmaChannelRead        = usartInit->dmaReceive;
    dObj->dmaChannelWrite       = usartInit->dmaTransmit;
    dObj->txInterruptSource     = usartInit->interruptTransmit;
    dObj->rxInterruptSource     = usartInit->interruptReceive;
    dObj->errorInterruptSource  = usartInit->interruptError;
    dObj->dmaInterruptTransmit  = usartInit->dmaInterruptTransmit;
    dObj->dmaInterruptReceive   = usartInit->dmaInterruptReceive;
    dObj->interruptNestingCount = 0;
    dObj->queueSizeCurrentRead  = 0; 
    dObj->queueSizeCurrentWrite = 0;

    /* Setup the Hardware */
    _DRV_USART_HardwareSetup(usartInit->usartID, usartInit ) ;

    /* Clear the interrupts */
    SYS_INT_SourceStatusClear(dObj->txInterruptSource);
    SYS_INT_SourceStatusClear(dObj->rxInterruptSource);
    SYS_INT_SourceStatusClear(dObj->errorInterruptSource);

    /* Enable the interrupt source in case of interrupt mode */
    _DRV_USART_InterruptSourceEnable(dObj->errorInterruptSource);

    /* TODO: Enable DMA interrupts if the DMA channel is selected */

    /* Create the hardware instance mutex. */
     OSAL_ASSERT((OSAL_MUTEX_Create(&(dObj->mutexDriverInstance)) == OSAL_RESULT_TRUE),
                 "Unable to create hardware instance mutex");


    /* Check if the global mutexes have been created. If not
       then create these. */

     if(!gDrvUSARTCommonDataObj.membersAreInitialized)
     {
         /* This means that mutexes where not created. Create them. */
         OSAL_ASSERT((OSAL_MUTEX_Create(&(gDrvUSARTCommonDataObj.mutexClientObjects)) == OSAL_RESULT_TRUE),
                     "Unable to create client instance mutex");
         OSAL_ASSERT((OSAL_MUTEX_Create(&(gDrvUSARTCommonDataObj.mutexBufferQueueObjects)) == OSAL_RESULT_TRUE),
                     "Unable to create buffer queue objects mutex");

         /* Set this flag so that global mutexes get allocated only once */
         gDrvUSARTCommonDataObj.membersAreInitialized = true;
     }

    /* Enable the USART module */
    PLIB_USART_Enable(usartInit->usartID) ;

    /* Update the status */
    dObj->status = SYS_STATUS_READY;

    /* Return the object structure */
    return ( (SYS_MODULE_OBJ)drvIndex );
} 
Пример #23
0
SYS_MODULE_OBJ DRV_SPI0_Initialize(void)
{
    DRV_SPI_OBJ *dObj = (DRV_SPI_OBJ*)NULL;

    dObj = &gDrvSPI0Obj;

    /* Disable the SPI module to configure it*/
    PLIB_SPI_Disable ( SPI_ID_1 );

    /* Set up Master or Slave Mode*/
    PLIB_SPI_MasterEnable ( SPI_ID_1 );
    PLIB_SPI_PinDisable(SPI_ID_1, SPI_PIN_SLAVE_SELECT);

    /* Set up if the SPI is allowed to run while the rest of the CPU is in idle mode*/
    PLIB_SPI_StopInIdleDisable( SPI_ID_1 );

    /* Set up clock Polarity and output data phase*/
    PLIB_SPI_ClockPolaritySelect( SPI_ID_1, SPI_CLOCK_POLARITY_IDLE_LOW );
    PLIB_SPI_OutputDataPhaseSelect( SPI_ID_1, SPI_OUTPUT_DATA_PHASE_ON_IDLE_TO_ACTIVE_CLOCK );

    /* Set up the Input Sample Phase*/
    PLIB_SPI_InputSamplePhaseSelect ( SPI_ID_1, SPI_INPUT_SAMPLING_PHASE_IN_MIDDLE);

    /* Communication Width Selection */
    PLIB_SPI_CommunicationWidthSelect ( SPI_ID_1, SPI_COMMUNICATION_WIDTH_8BITS );

    /* Baud rate selection */
    PLIB_SPI_BaudRateSet( SPI_ID_1 , SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_2), 1000000 );

    /* Protocol selection */
    PLIB_SPI_FramedCommunicationDisable( SPI_ID_1  );
    #if defined (PLIB_SPI_ExistsAudioProtocolControl)
            if (PLIB_SPI_ExistsAudioProtocolControl(SPI_ID_1))
            {
                PLIB_SPI_AudioProtocolDisable(SPI_ID_1);
            }
    #endif

    /* Buffer type selection */
    #if defined (PLIB_SPI_ExistsFIFOControl)
        if (PLIB_SPI_ExistsFIFOControl( SPI_ID_1 ))
        {
            PLIB_SPI_FIFODisable( SPI_ID_1 );
        }
    #endif

    PLIB_SPI_BufferClear( SPI_ID_1 );
    PLIB_SPI_ReceiverOverflowClear ( SPI_ID_1 );

    /* Initialize Queue only once for all instances of SPI driver*/
    if (DRV_SPI_SYS_QUEUE_Initialize(&qmInitData, &hQueueManager) != DRV_SPI_SYS_QUEUE_SUCCESS)
    {
        SYS_ASSERT(false, "\r\nSPI Driver: Could not create queuing system.");
        return SYS_MODULE_OBJ_INVALID;
    }

    /* Update the Queue parameters. */
    qInitData.maxElements = 10; //Queue size
    qInitData.reserveElements = 1; //Mininmum number of job queues reserved

    /* Create Queue for this instance of SPI */
    if (DRV_SPI_SYS_QUEUE_CreateQueue(hQueueManager, &qInitData, &dObj->queue) != DRV_SPI_SYS_QUEUE_SUCCESS)
    {
        SYS_ASSERT(false, "\r\nSPI Driver: Could not set up driver instance queue.");
        return SYS_MODULE_OBJ_INVALID;

    }

    /* Update the SPI OBJECT parameters. */
    dObj->operationStarting = NULL;
    dObj->operationEnded = NULL;

    SYS_INT_SourceDisable(INT_SOURCE_SPI_1_TRANSMIT);
    SYS_INT_SourceDisable(INT_SOURCE_SPI_1_RECEIVE);
    SYS_INT_SourceEnable(INT_SOURCE_SPI_1_ERROR);

    /* Clear all interrupt sources */
    SYS_INT_SourceStatusClear(INT_SOURCE_SPI_1_TRANSMIT);
    SYS_INT_SourceStatusClear(INT_SOURCE_SPI_1_RECEIVE);
    SYS_INT_SourceStatusClear(INT_SOURCE_SPI_1_ERROR);

    /* Enable the Module */
    PLIB_SPI_Enable(SPI_ID_1);

    return (SYS_MODULE_OBJ)DRV_SPI_INDEX_0 ;
}
int32_t DRV_SPI_ISRMasterEBM8BitTasks ( struct DRV_SPI_DRIVER_OBJECT * pDrvInstance )    
{
    bool continueLoop;
    
    /* Disable the interrupts */
    SYS_INT_SourceDisable(pDrvInstance->rxInterruptSource);
    SYS_INT_SourceDisable(pDrvInstance->txInterruptSource);
    SYS_INT_SourceDisable(pDrvInstance->errInterruptSource);
    do {
        
        DRV_SPI_JOB_OBJECT * currentJob = pDrvInstance->currentJob;
        SPI_MODULE_ID spiId = pDrvInstance->spiId;
        /* Check for a new task */
        if (pDrvInstance->currentJob == NULL)
        {
            if (DRV_SPI_SYS_QUEUE_Dequeue(pDrvInstance->queue, (void *)&(pDrvInstance->currentJob)) != DRV_SPI_SYS_QUEUE_SUCCESS)
            {
                SYS_ASSERT(false, "\r\nSPI Driver: Error in dequeing.");
                return 0;       
            }
            if (pDrvInstance->currentJob == NULL)
            {
                pDrvInstance->txEnabled = false;
                return 0;
            }
            currentJob = pDrvInstance->currentJob;

            pDrvInstance->symbolsInProgress = 0;

            /* Call the operation starting function pointer.  This can be used to modify the slave select lines */
            DRV_SPI_CLIENT_OBJECT * pClient = (DRV_SPI_CLIENT_OBJECT*)currentJob->pClient;
            if (pClient->operationStarting != NULL)
            {
                (*pClient->operationStarting)(DRV_SPI_BUFFER_EVENT_PROCESSING, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
            }
            /* Check the baud rate.  If its different set the new baud rate*/
            if (pClient->baudRate != pDrvInstance->currentBaudRate)
            {
                PLIB_SPI_BaudRateSet( spiId , SYS_CLK_PeripheralFrequencyGet(pDrvInstance->spiClk), pClient->baudRate );
                pDrvInstance->currentBaudRate = pClient->baudRate;
            }
            
            /* List the new job as processing*/
            currentJob->status = DRV_SPI_BUFFER_EVENT_PROCESSING;
            if (currentJob->dataLeftToTx +currentJob->dummyLeftToTx > PLIB_SPI_RX_8BIT_FIFO_SIZE(spiId))
            {
                PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_TRANSMIT_BUFFER_IS_1HALF_EMPTY_OR_MORE);
                PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_RECEIVE_BUFFER_IS_1HALF_FULL_OR_MORE);
            }
            /* Flush out the Receive buffer */
            PLIB_SPI_BufferClear(spiId);
        }

        /* Set up DMA Receive job.  This is done here to ensure that the RX job is ready to receive when TXing starts*/
        if ((pDrvInstance->rxDmaThreshold != 0) && (currentJob->dataLeftToRx > pDrvInstance->rxDmaThreshold))
        {
            PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_RECEIVE_BUFFER_IS_NOT_EMPTY);
            uint8_t * ptr = &(currentJob->rxBuffer[currentJob->dataRxed]);
            uint32_t len = MIN(MIN(PLIB_DMA_MAX_TRF_SIZE, DRV_SPI_DMA_TXFER_SIZE), currentJob->dataLeftToRx);
            void * spiPtr = PLIB_SPI_BufferAddressGet(spiId);
            currentJob->rxDMAProgressStage = DRV_SPI_DMA_DATA_INPROGRESS;
            currentJob->dataLeftToRx -= len;
            currentJob->dataRxed += len;
            pDrvInstance->rxEnabled = false;
            SYS_DMA_ChannelTransferAdd(pDrvInstance->rxDmaChannelHandle, spiPtr, 1, ptr, len, 1);
        }
        else if ((currentJob->rxDMAProgressStage == DRV_SPI_DMA_NONE) && (currentJob->dataLeftToRx == 0) && (pDrvInstance->rxDmaThreshold != 0) && (currentJob->dummyLeftToRx > pDrvInstance->rxDmaThreshold))
        {
            PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_RECEIVE_BUFFER_IS_NOT_EMPTY);
            uint8_t * ptr = sDrvSpiRxDummy;
            uint32_t len = MIN(MIN(MIN(PLIB_DMA_MAX_TRF_SIZE, DRV_SPI_DMA_DUMMY_BUFFER_SIZE), DRV_SPI_DMA_TXFER_SIZE), currentJob->dummyLeftToRx);
            void * spiPtr = PLIB_SPI_BufferAddressGet(spiId);
            currentJob->rxDMAProgressStage = DRV_SPI_DMA_DUMMY_INPROGRESS;
            currentJob->dummyLeftToRx -= len;
            pDrvInstance->rxEnabled = false;
            SYS_DMA_ChannelTransferAdd(pDrvInstance->rxDmaChannelHandle, spiPtr, 1, ptr, len, 1);
        }       
        /* Set up the DMA Transmit job here.  This is done after the RX job to help prevent buffer overruns.*/
        if ((pDrvInstance->txDmaThreshold != 0) && (currentJob->dataLeftToTx > pDrvInstance->txDmaThreshold))
        {
            PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_TRANSMIT_BUFFER_IS_1HALF_EMPTY_OR_MORE);
            uint8_t * ptr = &(currentJob->txBuffer[currentJob->dataTxed]);
            uint32_t len = MIN(MIN(PLIB_DMA_MAX_TRF_SIZE, DRV_SPI_DMA_TXFER_SIZE), currentJob->dataLeftToTx);
            void * spiPtr = PLIB_SPI_BufferAddressGet(pDrvInstance->spiId);
            currentJob->txDMAProgressStage = DRV_SPI_DMA_DATA_INPROGRESS;
            currentJob->dataLeftToTx -= len;
            currentJob->dataTxed += len;
            pDrvInstance->txEnabled = false;
            SYS_DMA_ChannelTransferAdd(pDrvInstance->txDmaChannelHandle, ptr, len, spiPtr, 1, 1);

        }
        else if ((currentJob->txDMAProgressStage == DRV_SPI_DMA_NONE) && (currentJob->dataLeftToTx == 0) && (pDrvInstance->txDmaThreshold != 0) && (currentJob->dummyLeftToTx > pDrvInstance->txDmaThreshold))
        {
            PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_TRANSMIT_BUFFER_IS_1HALF_EMPTY_OR_MORE);
            uint8_t * ptr = sDrvSpiTxDummy;
            uint32_t len = MIN(MIN(MIN(PLIB_DMA_MAX_TRF_SIZE, DRV_SPI_DMA_DUMMY_BUFFER_SIZE), DRV_SPI_DMA_TXFER_SIZE), currentJob->dummyLeftToTx);
            void * spiPtr = PLIB_SPI_BufferAddressGet(pDrvInstance->spiId);
            currentJob->txDMAProgressStage = DRV_SPI_DMA_DUMMY_INPROGRESS;
            currentJob->dummyLeftToTx -= len;
            pDrvInstance->txEnabled = false;
            SYS_DMA_ChannelTransferAdd(pDrvInstance->txDmaChannelHandle, ptr, len, spiPtr, 1, 1);
        }
        bool rxDMAInProgress = (currentJob->rxDMAProgressStage == DRV_SPI_DMA_DATA_INPROGRESS) || (currentJob->rxDMAProgressStage == DRV_SPI_DMA_DUMMY_INPROGRESS);
        bool txDMAInProgress = (currentJob->txDMAProgressStage == DRV_SPI_DMA_DATA_INPROGRESS) || (currentJob->txDMAProgressStage == DRV_SPI_DMA_DUMMY_INPROGRESS);
                
        continueLoop = false;
        /* Execute the sub tasks */

        DRV_SPI_ISRErrorTasks(pDrvInstance);
        
        /* Figure out how many bytes are left to be received */
        size_t bytesLeft = currentJob->dataLeftToRx + currentJob->dummyLeftToRx;
        // Check to see if we have any data left to receive and update the bytes left.

        if ((bytesLeft != 0) && !rxDMAInProgress)
        {
            DRV_SPI_MasterEBMReceive8BitISR(pDrvInstance);
            bytesLeft = currentJob->dataLeftToRx + currentJob->dummyLeftToRx;
        }
        
        if 
            (!txDMAInProgress &&
            (currentJob->dataLeftToTx +currentJob->dummyLeftToTx != 0)
            )
        {
            DRV_SPI_MasterEBMSend8BitISR(pDrvInstance);
        }
        
        if ((bytesLeft == 0) && !rxDMAInProgress && !txDMAInProgress)
        {
                    // Disable the interrupt, or more correctly don't re-enable it later*/
                    pDrvInstance->rxEnabled = false;
                    /* Job is complete*/
                    currentJob->status = DRV_SPI_BUFFER_EVENT_COMPLETE;
                    /* Call the job complete call back*/
                    if (currentJob->completeCB != NULL)
                    {
                        (*currentJob->completeCB)(DRV_SPI_BUFFER_EVENT_COMPLETE, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
                    }
                    /* Call the operation complete call back.  This is different than the
                       job complete callback.  This can be used to modify the Slave Select line.
                       The job complete callback can be used to free a client that is blocked 
                       waiting for complete*/
                    DRV_SPI_CLIENT_OBJECT * pClient = (DRV_SPI_CLIENT_OBJECT*)currentJob->pClient;
                    if (pClient->operationEnded != NULL)
                    {
                        (*pClient->operationEnded)(DRV_SPI_BUFFER_EVENT_COMPLETE, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
                    }
                    /* Return the job back to the free queue*/
                    if (DRV_SPI_SYS_QUEUE_FreeElement(pDrvInstance->queue, currentJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
                    {
                        SYS_ASSERT(false, "\r\nSPI Driver: Queue free element error.");
                        return 0;
                    }
                    /* Clean up */
                    pDrvInstance->currentJob = NULL;
                    if (!DRV_SPI_SYS_QUEUE_IsEmpty(pDrvInstance->queue))
                    {
                        continueLoop = true;    
                        continue;
                    }
                    else
                    {
                        break;
                    }
                }
        else if (rxDMAInProgress)
        {
            // DMA is in progress
            // Wipe out the symbols in Progress
            pDrvInstance->rxEnabled = false;
            pDrvInstance->symbolsInProgress = 0;
        }

    
        /* Check to see if the interrupts would fire again if so just go back into 
           the loop instead of suffering the interrupt latency of exiting and re-entering*/
        if (pDrvInstance->currentJob != NULL)
        {   
            /* Clear the Interrupts */
            SYS_INT_SourceStatusClear(pDrvInstance->rxInterruptSource);
            SYS_INT_SourceStatusClear(pDrvInstance->txInterruptSource);
            SYS_INT_SourceStatusClear(pDrvInstance->errInterruptSource);
            /* Interrupts should immediately become active again if they're in a fired condition */
            if (((pDrvInstance->rxEnabled) && SYS_INT_SourceStatusGet(pDrvInstance->rxInterruptSource)) ||
                ((pDrvInstance->txEnabled) && SYS_INT_SourceStatusGet(pDrvInstance->txInterruptSource)) ||
                (SYS_INT_SourceStatusGet(pDrvInstance->errInterruptSource)))
            {
                /* Interrupt would fire again anyway so we should just go back to the start*/
                continueLoop = true;
                continue;                            
            }
            /* If we're here then we know that the interrupt should not be firing again so we can exit cleanly*/
            /* Clear the interrupts now that we're done*/
            /* Re-enable the interrupts*/
            if (pDrvInstance->rxEnabled)
            {
                SYS_INT_SourceEnable(pDrvInstance->rxInterruptSource);
            }
            if (pDrvInstance->txEnabled)
            {
                SYS_INT_SourceEnable(pDrvInstance->txInterruptSource);
            }
            return 0;            
        }
    
    } while(continueLoop);
    /* if we're here it means that we have no more jobs in the queue, tx and rx interrupts will be re-enabled by the BufferAdd* functions*/
    SYS_INT_SourceStatusClear(pDrvInstance->rxInterruptSource);
    SYS_INT_SourceStatusClear(pDrvInstance->txInterruptSource);
    return 0;
}
Пример #25
0
int32_t DRV_SPI_ISRSlaveEBM8BitTasks ( struct DRV_SPI_DRIVER_OBJECT * pDrvInstance )
{
    volatile bool continueLoop;
    SYS_INT_SourceDisable(pDrvInstance->rxInterruptSource);
    SYS_INT_SourceDisable(pDrvInstance->txInterruptSource);
    SYS_INT_SourceDisable(pDrvInstance->errInterruptSource);
    do {
        
        continueLoop = false;
        DRV_SPI_JOB_OBJECT * currentJob = pDrvInstance->currentJob;
        SPI_MODULE_ID spiId = pDrvInstance->spiId;
    
        if (pDrvInstance->currentJob == NULL)
        {
            if (DRV_SPI_SYS_QUEUE_Dequeue(pDrvInstance->queue, (void *)&(pDrvInstance->currentJob)) != DRV_SPI_SYS_QUEUE_SUCCESS)
            {
                SYS_ASSERT(false, "\r\nSPI Driver: Error in dequeing.");
                return 0;       
            }
            if (pDrvInstance->currentJob == NULL)
            {
                pDrvInstance->txEnabled = false;
                return 0;
            }
            currentJob = pDrvInstance->currentJob;
            pDrvInstance->symbolsInProgress = 0;

            /* Call the operation starting function pointer.  This can be used to modify the slave select lines */
            DRV_SPI_CLIENT_OBJECT * pClient = (DRV_SPI_CLIENT_OBJECT*)currentJob->pClient;
            if (pClient->operationStarting != NULL)
            {
                (*pClient->operationStarting)(DRV_SPI_BUFFER_EVENT_PROCESSING, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
            }
            
            /* List the new job as processing*/
            currentJob->status = DRV_SPI_BUFFER_EVENT_PROCESSING;
            if (currentJob->dataLeftToTx > PLIB_SPI_RX_8BIT_FIFO_SIZE(spiId))
            {
                PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_TRANSMIT_BUFFER_IS_1HALF_EMPTY_OR_MORE);
                PLIB_SPI_FIFOInterruptModeSelect(spiId, SPI_FIFO_INTERRUPT_WHEN_RECEIVE_BUFFER_IS_1HALF_FULL_OR_MORE);
            }
            /* Flush out the Receive buffer */
            PLIB_SPI_BufferClear(spiId);
        }
        
        
        if (currentJob->dataLeftToRx + currentJob->dummyLeftToRx != 0)
        {
            DRV_SPI_SlaveEBMReceive8BitISR(pDrvInstance);
        }
        if (currentJob->dataLeftToTx != 0)
        {
            DRV_SPI_SlaveEBMSend8BitISR(pDrvInstance);
        }
        else
        {
            pDrvInstance->txEnabled = false;
            pDrvInstance->rxEnabled = true;
        }
        
        DRV_SPI_ISRErrorTasks(pDrvInstance);
    
        /* Check to see if the job is done */
        if (currentJob->dataLeftToRx + currentJob->dummyLeftToRx == 0)
        {
            // Disable the interrupt, or more correctly don't re-enable it later*/
            pDrvInstance->rxEnabled = false;
            /* Job is complete*/
            currentJob->status = DRV_SPI_BUFFER_EVENT_COMPLETE;
            /* Call the job complete call back*/
            if (currentJob->completeCB != NULL)
            {
                (*currentJob->completeCB)(DRV_SPI_BUFFER_EVENT_COMPLETE, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
            }
            /* Call the operation complete call back.  This is different than the
               job complete callback.  This can be used to modify the Slave Select line.
               The job complete callback can be used to free a client that is blocked 
               waiting for complete*/
            DRV_SPI_CLIENT_OBJECT * pClient = (DRV_SPI_CLIENT_OBJECT*)currentJob->pClient;
            if (pClient->operationEnded != NULL)
            {
                (*pClient->operationEnded)(DRV_SPI_BUFFER_EVENT_COMPLETE, (DRV_SPI_BUFFER_HANDLE)currentJob, currentJob->context);
            }
            /* Return the job back to the free queue*/
            if (DRV_SPI_SYS_QUEUE_FreeElement(pDrvInstance->queue, currentJob) != DRV_SPI_SYS_QUEUE_SUCCESS)
            {
                SYS_ASSERT(false, "\r\nSPI Driver: Queue free element error.");
                return 0;
            }
            /* Clean up */
            pDrvInstance->currentJob = NULL;
            if (!DRV_SPI_SYS_QUEUE_IsEmpty(pDrvInstance->queue))
            {
                continueLoop = true;    
                continue;
            }
        }

        /* Check to see if the interrupts would fire again if so just go back into 
           the loop instead of suffering the interrupt latency of exiting and re-entering*/
        if (pDrvInstance->currentJob != NULL)
        {
            /* Clear the Interrupts */
            SYS_INT_SourceStatusClear(pDrvInstance->rxInterruptSource);
            SYS_INT_SourceStatusClear(pDrvInstance->txInterruptSource);
            SYS_INT_SourceStatusClear(pDrvInstance->errInterruptSource);
            
            /* Interrupts should immediately become active again if they're in a fired condition */
            if ((SYS_INT_SourceStatusGet(pDrvInstance->rxInterruptSource)) ||
                (SYS_INT_SourceStatusGet(pDrvInstance->errInterruptSource)))
            {
                /* Interrupt would fire again anyway so we should just go back to the start*/
                continueLoop = true;
                continue;                            
            }
            /* If we're here then we know that the interrupt should not be firing immediately so enable it and exit */
            SYS_INT_SourceEnable(pDrvInstance->rxInterruptSource);

            return 0;            
        }

    } while(continueLoop);
    return 0;
}