diff --git a/arch/arm/src/sama5/sam_hsmci.c b/arch/arm/src/sama5/sam_hsmci.c index 1e6b476106..b5093d36b0 100644 --- a/arch/arm/src/sama5/sam_hsmci.c +++ b/arch/arm/src/sama5/sam_hsmci.c @@ -2213,6 +2213,7 @@ static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, unsigned int nwords; const uint32_t *ptr; uint32_t sr; + irqstate_t flags; DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); DEBUGASSERT(((uint32_t)buffer & 3) == 0); @@ -2232,10 +2233,13 @@ static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, /* Copy each word to the TX FIFO * - * REVISIT: If TX data underruns occur, then it may be necessary to - * disable pre-emption around this loop. + * It is necessary to disable pre-emption and interrupts around this loop + * in order to avoid a TX data underrun. */ + sched_lock(); + flags = enter_critical_section(); + nwords = (buflen + 3) >> 2; ptr = (const uint32_t *)buffer; @@ -2260,6 +2264,8 @@ static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, } } + leave_critical_section(flags); + sched_unlock(); return OK; } diff --git a/arch/arm/src/samv7/sam_hsmci.c b/arch/arm/src/samv7/sam_hsmci.c index 687154ae0b..b6df58bc18 100644 --- a/arch/arm/src/samv7/sam_hsmci.c +++ b/arch/arm/src/samv7/sam_hsmci.c @@ -2200,6 +2200,7 @@ static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, unsigned int remaining; const uint32_t *src; uint32_t sr; + irqstate_t flags; DEBUGASSERT(priv != NULL && buffer != NULL && buflen > 0); @@ -2229,10 +2230,13 @@ static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, /* Copy each word to the TX FIFO * - * REVISIT: If TX data underruns occur, then it may be necessary to - * disable pre-emption around this loop. + * It is necessary to disable pre-emption and interrupts around this loop + * in order to avoid a TX data underrun. */ + sched_lock(); + flags = enter_critical_section(); + src = (const uint32_t *)buffer; remaining = buflen; @@ -2302,6 +2306,8 @@ static int sam_sendsetup(FAR struct sdio_dev_s *dev, FAR const uint8_t *buffer, } } + leave_critical_section(flags); + sched_unlock(); return OK; }