未验证 提交 cbd062ca 编写于 作者: W wolfJane 提交者: GitHub

[bsp/n32g45x] drv_spi.c中添加超时检测避免卡死 (#5820)

* 为spi添加超时检测,避免卡死。提取公共部份,避免代码复制。
上级 a0f8d437
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2022-03-06 BalanceTWK first version * 2022-03-06 BalanceTWK first version
* 2022-04-16 wolfJane fix spixfer, add time out check
*/ */
#include <board.h> #include <board.h>
...@@ -22,6 +23,8 @@ ...@@ -22,6 +23,8 @@
#define LOG_TAG "drv.spi" #define LOG_TAG "drv.spi"
#include <drv_log.h> #include <drv_log.h>
#define SPI_TIME_OUT (1000)
enum enum
{ {
#ifdef BSP_USING_SPI1 #ifdef BSP_USING_SPI1
...@@ -235,13 +238,57 @@ static rt_err_t spi_configure(struct rt_spi_device *device, ...@@ -235,13 +238,57 @@ static rt_err_t spi_configure(struct rt_spi_device *device,
return n32_spi_init(spi_drv, configuration); return n32_spi_init(spi_drv, configuration);
} }
static int _spi_recv(SPI_Module *hspi,
uint8_t *tx_buff,
uint8_t *rx_buff,
uint32_t length,
uint32_t timeout)
{
/* Init tickstart for timeout management*/
uint32_t tickstart = rt_tick_get();
uint8_t dat = 0;
if ((tx_buff == RT_NULL) && (rx_buff == RT_NULL) || (length == 0))
{
return RT_EIO;
}
while (length--)
{
while (SPI_I2S_GetStatus(hspi, SPI_I2S_TE_FLAG) == RESET)
{
if ((rt_tick_get() - tickstart) > timeout)
{
return RT_ETIMEOUT;
}
}
SPI_I2S_TransmitData(hspi, *tx_buff++);
while (SPI_I2S_GetStatus(hspi, SPI_I2S_RNE_FLAG) == RESET)
{
if ((rt_tick_get() - tickstart) > timeout)
{
return RT_ETIMEOUT;
}
}
dat = SPI_I2S_ReceiveData(hspi);
if (rx_buff)
{
*rx_buff++ = dat;
}
}
return RT_EOK;
}
static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message) static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *message)
{ {
rt_size_t message_length; rt_size_t send_length;
rt_size_t i = 0;
rt_uint8_t *recv_buf; rt_uint8_t *recv_buf;
const rt_uint8_t *send_buf; const rt_uint8_t *send_buf;
rt_err_t stat = RT_EOK;
/* Check Direction parameter */
RT_ASSERT(device != RT_NULL); RT_ASSERT(device != RT_NULL);
RT_ASSERT(device->bus != RT_NULL); RT_ASSERT(device->bus != RT_NULL);
RT_ASSERT(device->bus->parent.user_data != RT_NULL); RT_ASSERT(device->bus->parent.user_data != RT_NULL);
...@@ -254,12 +301,16 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message * ...@@ -254,12 +301,16 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS)) if (message->cs_take && !(device->config.mode & RT_SPI_NO_CS))
{ {
if (device->config.mode & RT_SPI_CS_HIGH) if (device->config.mode & RT_SPI_CS_HIGH)
{
GPIO_SetBits(cs->module, cs->pin); GPIO_SetBits(cs->module, cs->pin);
}
else else
{
GPIO_ResetBits(cs->module, cs->pin); GPIO_ResetBits(cs->module, cs->pin);
} }
}
message_length = message->length; send_length = message->length;
recv_buf = message->recv_buf; recv_buf = message->recv_buf;
send_buf = message->send_buf; send_buf = message->send_buf;
...@@ -267,38 +318,44 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message * ...@@ -267,38 +318,44 @@ static rt_uint32_t spixfer(struct rt_spi_device *device, struct rt_spi_message *
if (message->send_buf && message->recv_buf) if (message->send_buf && message->recv_buf)
{ {
LOG_D("%s:%d", __FUNCTION__, __LINE__); LOG_D("%s:%d", __FUNCTION__, __LINE__);
stat = RT_EIO;
} }
else if (message->send_buf) else if (message->send_buf)
{ {
while (message_length--) stat = _spi_recv(spi_handle,
{ (uint8_t *)send_buf,
while (SPI_I2S_GetStatus(spi_handle, SPI_I2S_TE_FLAG) == RESET); RT_NULL,
SPI_I2S_TransmitData(spi_handle, send_buf[i++]); send_length,
while (SPI_I2S_GetStatus(spi_handle, SPI_I2S_RNE_FLAG) == RESET); SPI_TIME_OUT);
SPI_I2S_ReceiveData(spi_handle);
}
} }
else else
{ {
while (message_length--) rt_memset(recv_buf, 0xff, send_length);
{ stat = _spi_recv(spi_handle,
while (SPI_I2S_GetStatus(spi_handle, SPI_I2S_TE_FLAG) == RESET); (uint8_t *)recv_buf,
SPI_I2S_TransmitData(spi_handle, 0xff); (uint8_t *)recv_buf,
while (SPI_I2S_GetStatus(spi_handle, SPI_I2S_RNE_FLAG) == RESET); send_length,
recv_buf[i++] = (rt_uint8_t)SPI_I2S_ReceiveData(spi_handle); SPI_TIME_OUT);
}
} }
if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS)) if (message->cs_release && !(device->config.mode & RT_SPI_NO_CS))
{ {
if (device->config.mode & RT_SPI_CS_HIGH) if (device->config.mode & RT_SPI_CS_HIGH)
{
GPIO_ResetBits(cs->module, cs->pin); GPIO_ResetBits(cs->module, cs->pin);
}
else else
{
GPIO_SetBits(cs->module, cs->pin); GPIO_SetBits(cs->module, cs->pin);
} }
}
if (stat != RT_EOK)
{
send_length = 0;
}
return message->length; return send_length;
} }
static const struct rt_spi_ops n32_spi_ops = static const struct rt_spi_ops n32_spi_ops =
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册