Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions peripheral/can_u2003/templates/plib_can_common.h.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ typedef struct
unsigned int anmf:1;

/* Data field */
uint8_t data[8];
uint8_t data[64];

} CAN_RX_BUFFER;

Expand Down Expand Up @@ -367,7 +367,7 @@ typedef struct
unsigned int mm:8;

/* Data field */
uint8_t data[8];
uint8_t data[64];

} CAN_TX_BUFFER;

Expand Down
23 changes: 20 additions & 3 deletions peripheral/sercom_u2201/templates/plib_sercom_i2c_master.c.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@
#define RIGHT_ALIGNED (8U)
</#if>

/* Upper bound on the wait for BUSSTATE to return to IDLE after a transfer.
* A STOP takes tens of microseconds even at 100 kHz, so this is a very generous
* margin; its only job is to make the wait finite. See the ISR for why. */
#define SERCOM_I2C_BUSSTATE_IDLE_TIMEOUT (50000U)

static volatile SERCOM_I2C_OBJ ${SERCOM_INSTANCE_NAME?lower_case}I2CObj;

// *****************************************************************************
Expand Down Expand Up @@ -1429,10 +1434,22 @@ void __attribute__((used)) ${SERCOM_INSTANCE_NAME}_I2C_InterruptHandler(void)

${SERCOM_INSTANCE_NAME}_REGS->I2CM.SERCOM_INTFLAG = (uint8_t)SERCOM_I2CM_INTFLAG_Msk;

/* Wait for the NAK and STOP bit to be transmitted out and I2C state machine to rest in IDLE state */
while((${SERCOM_INSTANCE_NAME}_REGS->I2CM.SERCOM_STATUS & SERCOM_I2CM_STATUS_BUSSTATE_Msk) != SERCOM_I2CM_STATUS_BUSSTATE(0x01U))
/* Wait for the NAK and STOP bit to be transmitted out and I2C state machine to rest in IDLE state.
*
* Bounded on purpose. A device that keeps SCL low after the transfer has otherwise completed would
* spin here forever, at interrupt priority, with no fault and no log -- the board simply stops. On
* expiry, report a bus error rather than leaving the transfer to be reported as a success on a bus
* that is still stuck, so the client sees a failed transfer and can recover. */
uint32_t busStateTimeout = SERCOM_I2C_BUSSTATE_IDLE_TIMEOUT;
while((((${SERCOM_INSTANCE_NAME}_REGS->I2CM.SERCOM_STATUS & SERCOM_I2CM_STATUS_BUSSTATE_Msk) != SERCOM_I2CM_STATUS_BUSSTATE(0x01U)))
&& (busStateTimeout > 0U))
{
/* Do nothing */
busStateTimeout--;
}

if(busStateTimeout == 0U)
{
${SERCOM_INSTANCE_NAME?lower_case}I2CObj.error = SERCOM_I2C_ERROR_BUS;
}

if(${SERCOM_INSTANCE_NAME?lower_case}I2CObj.callback != NULL)
Expand Down
63 changes: 63 additions & 0 deletions peripheral/usart_6089/templates/plib_usart.c.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,20 @@ void __attribute__((used)) ${USART_INSTANCE_NAME}_InterruptHandler( void )
}
}
<#else>
/* Receiver timeout */
if (${USART_INSTANCE_NAME}_REGS->US_CSR & US_CSR_USART_TIMEOUT_Msk)
{
if(${USART_INSTANCE_NAME?lower_case}Obj.rxTimeoutCallback != NULL)
{
${USART_INSTANCE_NAME?lower_case}Obj.rxTimeoutCallback(${USART_INSTANCE_NAME?lower_case}Obj.rxTimeoutContext);
}
else
{
/* clear and disable timer to avoid re-raising the timout, reset should be controlled by rxTimeoutCallback */
${USART_INSTANCE_NAME}_ClearReadTimeout();
}
}

/* Receiver status */
if ((${USART_INSTANCE_NAME}_REGS->US_CSR & US_CSR_USART_RXRDY_Msk) != 0U)
{
Expand Down Expand Up @@ -624,6 +638,13 @@ void ${USART_INSTANCE_NAME}_ReadCallbackRegister( USART_CALLBACK callback, uintp
${USART_INSTANCE_NAME?lower_case}Obj.rxContext = context;
}

void ${USART_INSTANCE_NAME}_ReadTimeoutCallbackRegister( USART_CALLBACK callback, uintptr_t context )
{
${USART_INSTANCE_NAME?lower_case}Obj.rxTimeoutCallback = callback;

${USART_INSTANCE_NAME?lower_case}Obj.rxTimeoutContext = context;
}

bool ${USART_INSTANCE_NAME}_WriteIsBusy( void )
{
return ${USART_INSTANCE_NAME?lower_case}Obj.txBusyStatus;
Expand Down Expand Up @@ -669,4 +690,46 @@ size_t ${USART_INSTANCE_NAME}_ReadCountGet( void )
</#if>
}


void ${USART_INSTANCE_NAME}_StartReadTimeoutAfterNextChar(uint32_t nbitperiods)
{
/* update timer value, this also starts the countdown */
${USART_INSTANCE_NAME}_StartReadTimeoutNow(nbitperiods);

/* immediately cancel running countdown (hopefully we're fast enough), and wait for next char */
${USART_INSTANCE_NAME}_REGS->US_CR = US_CR_USART_STTTO_Msk;
}

void ${USART_INSTANCE_NAME}_StartReadTimeoutNow(uint32_t nbitperiods)
{
<#if USART_INTERRUPT_MODE_ENABLE == true>
/* enable USART Rx timeout interrupt */
${USART_INSTANCE_NAME}_REGS->US_IER = US_IER_USART_TIMEOUT_Msk;
</#if>

/* update timer value, immediately starts timeout */
${USART_INSTANCE_NAME}_REGS->US_RTOR = US_RTOR_TO(nbitperiods);
}

void ${USART_INSTANCE_NAME}_RestartReadTimeoutAfterNextChar()
{
${USART_INSTANCE_NAME}_REGS->US_CR = US_CR_USART_STTTO_Msk;
}

void ${USART_INSTANCE_NAME}_RestartReadTimeoutNow()
{
${USART_INSTANCE_NAME}_REGS->US_CR = US_CR_USART_RETTO_Msk;
}

void ${USART_INSTANCE_NAME}_ClearReadTimeout( void )
{
/* reset timer value, stops running timer */
${USART_INSTANCE_NAME}_REGS->US_RTOR = 0;

<#if USART_INTERRUPT_MODE_ENABLE == true>
/* disable USART Rx timeout interrupt */
${USART_INSTANCE_NAME}_REGS->US_IDR = US_IDR_USART_TIMEOUT_Msk;
</#if>
}

</#if>
12 changes: 12 additions & 0 deletions peripheral/usart_6089/templates/plib_usart.h.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ bool ${USART_INSTANCE_NAME}_Write( void *buffer, const size_t size );

bool ${USART_INSTANCE_NAME}_Read( void *buffer, const size_t size );

void ${USART_INSTANCE_NAME}_StartReadTimeoutNow(uint32_t nbitperiods);

void ${USART_INSTANCE_NAME}_StartReadTimeoutAfterNextChar(uint32_t nbitperiods);

void ${USART_INSTANCE_NAME}_RestartReadTimeoutNow( void );

void ${USART_INSTANCE_NAME}_RestartReadTimeoutAfterNextChar( void );

void ${USART_INSTANCE_NAME}_ClearReadTimeout( void );

<#if USART_INTERRUPT_MODE_ENABLE == false>
int ${USART_INSTANCE_NAME}_ReadByte( void );

Expand All @@ -97,6 +107,8 @@ void ${USART_INSTANCE_NAME}_WriteCallbackRegister( USART_CALLBACK callback, uint

void ${USART_INSTANCE_NAME}_ReadCallbackRegister( USART_CALLBACK callback, uintptr_t context );

void ${USART_INSTANCE_NAME}_ReadTimeoutCallbackRegister( USART_CALLBACK callback, uintptr_t context );

</#if>

bool ${USART_INSTANCE_NAME}_TransmitComplete( void );
Expand Down
2 changes: 2 additions & 0 deletions peripheral/usart_6089/templates/plib_usart_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ typedef struct
size_t rxProcessedSize;
USART_CALLBACK rxCallback;
uintptr_t rxContext;
USART_CALLBACK rxTimeoutCallback;
uintptr_t rxTimeoutContext;
bool rxBusyStatus;

USART_ERROR errorStatus;
Expand Down
69 changes: 51 additions & 18 deletions peripheral/xdmac_11161/templates/plib_xdmac.c.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ void __attribute__((used)) ${DMA_INSTANCE_NAME}_InterruptHandler( void )
{
uint32_t chanIntStatus;
uint32_t channel;
XDMAC_TRANSFER_EVENT event = XDMAC_TRANSFER_NONE;

/* Additional temporary variables used to prevent MISRA violations (Rule 13.x) */
bool channelInUse;
Expand All @@ -94,6 +95,7 @@ void __attribute__((used)) ${DMA_INSTANCE_NAME}_InterruptHandler( void )
/* Iterate all channels */
for (channel = 0U; channel < XDMAC_ACTIVE_CHANNELS_MAX; channel++)
{
event = XDMAC_TRANSFER_NONE;
channelInUse = xdmacChannelObj[channel].inUse;
channelContext = xdmacChannelObj[channel].context;

Expand All @@ -105,22 +107,37 @@ void __attribute__((used)) ${DMA_INSTANCE_NAME}_InterruptHandler( void )

if ((chanIntStatus & ( XDMAC_CIS_RBEIS_Msk | XDMAC_CIS_WBEIS_Msk | XDMAC_CIS_ROIS_Msk)) != 0U)
{
xdmacChannelObj[channel].busyStatus = false;

/* It's an error interrupt */
if (NULL != xdmacChannelObj[channel].callback)
{
xdmacChannelObj[channel].callback(XDMAC_TRANSFER_ERROR, channelContext);
}
event = XDMAC_TRANSFER_ERROR;
}
else if ((chanIntStatus & XDMAC_CIS_BIS_Msk) != 0U)
{
xdmacChannelObj[channel].busyStatus = false;

/* It's a block transfer complete interrupt */
event = XDMAC_TRANSFER_COMPLETE;
}
else if ((chanIntStatus & XDMAC_CIS_LIS_Msk) != 0U)
{
/* It's an end of linked list interrupt */
event = XDMAC_TRANSFER_LINKED_LIST_END;
}
else if ((chanIntStatus & XDMAC_CIS_FIS_Msk) != 0U)
{
/* It's an end of flush operation interrupt */
event = XDMAC_TRANSFER_FLUSH_END;
}

if (event != XDMAC_TRANSFER_NONE) {
/* a flush event may occur while a DMA transfer is still running. Therefore don't
* reset the busyStatus in this case.
*/
if (event != XDMAC_TRANSFER_FLUSH_END)
{
xdmacChannelObj[channel].busyStatus = false;
}

if (NULL != xdmacChannelObj[channel].callback)
{
xdmacChannelObj[channel].callback(XDMAC_TRANSFER_COMPLETE, channelContext);
xdmacChannelObj[channel].callback(event, channelContext);
}
}
else
Expand All @@ -137,6 +154,7 @@ void __attribute__((used)) ${DMA_INSTANCE_NAME}_SINT_InterruptHandler( void )
{
uint32_t chanIntStatus;
uint32_t channel;
XDMAC_TRANSFER_EVENT event = XDMAC_TRANSFER_NONE;

/* Additional temporary variables used to prevent MISRA violations (Rule 13.x) */
bool channelInUse;
Expand All @@ -155,22 +173,37 @@ void __attribute__((used)) ${DMA_INSTANCE_NAME}_SINT_InterruptHandler( void )

if ((chanIntStatus & ( XDMAC_CIS_RBEIS_Msk | XDMAC_CIS_WBEIS_Msk | XDMAC_CIS_ROIS_Msk)) != 0U)
{
xdmacChannelObj[channel].busyStatus = false;

/* It's an error interrupt */
if (NULL != xdmacChannelObj[channel].callback)
{
xdmacChannelObj[channel].callback(XDMAC_TRANSFER_ERROR, channelContext);
}
event = XDMAC_TRANSFER_ERROR;
}
else if ((chanIntStatus & XDMAC_CIS_BIS_Msk) != 0U)
{
xdmacChannelObj[channel].busyStatus = false;

/* It's a block transfer complete interrupt */
event = XDMAC_TRANSFER_COMPLETE;
}
else if ((chanIntStatus & XDMAC_CIS_LIS_Msk) != 0U)
{
/* It's an end of linked list interrupt */
event = XDMAC_TRANSFER_LINKED_LIST_END;
}
else if ((chanIntStatus & XDMAC_CIS_FIS_Msk) != 0U)
{
/* It's an end of flush operation interrupt */
event = XDMAC_TRANSFER_FLUSH_END;
}

if (event != XDMAC_TRANSFER_NONE) {
/* a flush event may occur while a DMA transfer is still running. Therefore don't
* reset the busyStatus in this case.
*/
if (event != XDMAC_TRANSFER_FLUSH_END)
{
xdmacChannelObj[channel].busyStatus = false;
}

if (NULL != xdmacChannelObj[channel].callback)
{
xdmacChannelObj[channel].callback(XDMAC_TRANSFER_COMPLETE, channelContext);
xdmacChannelObj[channel].callback(event, channelContext);
}
}
else
Expand Down
8 changes: 7 additions & 1 deletion peripheral/xdmac_11161/templates/plib_xdmac_common.h.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ typedef enum
XDMAC_TRANSFER_COMPLETE = 1,

/* Error while processing the request */
XDMAC_TRANSFER_ERROR = 2
XDMAC_TRANSFER_ERROR = 2,

/* Reached end of linked list */
XDMAC_TRANSFER_LINKED_LIST_END = 3,

/* Requested flush operation has ended */
XDMAC_TRANSFER_FLUSH_END = 4

} XDMAC_TRANSFER_EVENT;

Expand Down