|
|
@ -26,7 +26,6 @@ |
|
|
|
* 1.4 huangjin 2023/12/26 adaptive pd2308 |
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/***************************** Include Files *********************************/ |
|
|
|
|
|
|
|
#include <string.h> |
|
|
@ -43,27 +42,14 @@ |
|
|
|
|
|
|
|
/***************** Macros (Inline Functions) Definitions *********************/ |
|
|
|
#define FSPIM_DEBUG_TAG "SPIM" |
|
|
|
#define FSPIM_ERROR(format, ...) FT_DEBUG_PRINT_E(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_WARN(format, ...) FT_DEBUG_PRINT_W(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_INFO(format, ...) FT_DEBUG_PRINT_I(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_ERROR(format, ...) FT_DEBUG_PRINT_E(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_WARN(format, ...) FT_DEBUG_PRINT_W(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_INFO(format, ...) FT_DEBUG_PRINT_I(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
#define FSPIM_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSPIM_DEBUG_TAG, format, ##__VA_ARGS__) |
|
|
|
|
|
|
|
/************************** Function Prototypes ******************************/ |
|
|
|
FError FSpimReset(FSpim *instance_p); |
|
|
|
|
|
|
|
/************************** Variable Definitions *****************************/ |
|
|
|
static const char *FSPIM_ERROR_CODE_MSG[FSPIM_NUM_OF_ERR_CODE] = |
|
|
|
{ |
|
|
|
"FSPIM_SUCCESS : The fspim was successful", |
|
|
|
"FSPIM_ERR_INVAL_STATE : The fspim invalid state", |
|
|
|
"FSPIM_ERR_NOT_READY : The fspim driver is not ready", |
|
|
|
"FSPIM_ERR_INVAL_PARAM : The fspim input parameter is invalid", |
|
|
|
"FSPIM_ERR_BUS_BUSY : The fspim bus is busy", |
|
|
|
"FSPIM_ERR_NOT_SUPPORT : Operations are not supported by fspim", |
|
|
|
"FSPIM_ERR_TIMEOUT : The fspim waits for a timeout", |
|
|
|
"FSPIM_ERR_TRANS_FAIL : The fspim data transmission failed", |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/ |
|
|
|
|
|
|
@ -86,20 +72,20 @@ FError FSpimCfgInitialize(FSpim *instance_p, const FSpimConfig *input_config_p) |
|
|
|
|
|
|
|
FError ret = FSPIM_SUCCESS; |
|
|
|
/*
|
|
|
|
* If the device is started, disallow the initialize and return a Status |
|
|
|
* indicating it is started. This allows the user to de-initialize the device |
|
|
|
* and reinitialize, but prevents a user from inadvertently |
|
|
|
* initializing. |
|
|
|
*/ |
|
|
|
* If the device is started, disallow the initialize and return a Status |
|
|
|
* indicating it is started. This allows the user to de-initialize the device |
|
|
|
* and reinitialize, but prevents a user from inadvertently |
|
|
|
* initializing. |
|
|
|
*/ |
|
|
|
if (FT_COMPONENT_IS_READY == instance_p->is_ready) |
|
|
|
{ |
|
|
|
FSPIM_WARN("The device has been initialized!!!"); |
|
|
|
} |
|
|
|
|
|
|
|
/*
|
|
|
|
* Set default values and configuration data, including setting the |
|
|
|
* callback handlers to stubs so the system will not crash should the |
|
|
|
* application not assign its own callbacks. |
|
|
|
* Set default values and configuration data, including setting the |
|
|
|
* callback handlers to stubs so the system will not crash should the |
|
|
|
* application not assign its own callbacks. |
|
|
|
*/ |
|
|
|
FSpimDeInitialize(instance_p); |
|
|
|
instance_p->config = *input_config_p; |
|
|
@ -166,7 +152,7 @@ FError FSpimReset(FSpim *instance_p) |
|
|
|
/* 选择串行时钟极性和相位 */ |
|
|
|
FSpimSetCpha(base_addr, instance_p->config.cpha); |
|
|
|
FSpimSetCpol(base_addr, instance_p->config.cpol); |
|
|
|
|
|
|
|
|
|
|
|
/* 设置传输模式 */ |
|
|
|
FSpimSetTransMode(base_addr, FSPIM_TRANS_MODE_RX_TX); |
|
|
|
|
|
|
@ -181,42 +167,29 @@ FError FSpimReset(FSpim *instance_p) |
|
|
|
if (0 == instance_p->tx_fifo_len) |
|
|
|
{ |
|
|
|
fifo = FSpimGetTxFifoDepth(base_addr); /* 检测fifo深度 */ |
|
|
|
instance_p->tx_fifo_len = ((fifo == 1) ? 0 : fifo); |
|
|
|
instance_p->tx_fifo_len = fifo; |
|
|
|
FSPIM_INFO("The fifo depth is %d ,tx effective length bits %d", fifo, instance_p->tx_fifo_len); |
|
|
|
} |
|
|
|
|
|
|
|
if (0 == instance_p->rx_fifo_len) |
|
|
|
{ |
|
|
|
fifo = FSpimGetRxFifoDepth(base_addr); |
|
|
|
instance_p->rx_fifo_len = ((fifo == 1) ? 0 : fifo); |
|
|
|
instance_p->rx_fifo_len = fifo; |
|
|
|
FSPIM_INFO("The fifo depth is %d ,rx effective length bits %d", fifo, instance_p->rx_fifo_len); |
|
|
|
} |
|
|
|
|
|
|
|
FSPIM_WRITE_REG32(base_addr, FSPIM_DMA_CR_OFFSET, 0x0); /* disable ddma */ |
|
|
|
|
|
|
|
if (instance_p->config.en_dma) |
|
|
|
if(instance_p->config.trans_way == TRANS_WAY_DDMA) |
|
|
|
{ |
|
|
|
/* recv data in continuous way */ |
|
|
|
FSpimSetCtrlR1(base_addr, FSPIM_CTRL_R1_NDF_64KB); |
|
|
|
|
|
|
|
/* setup fifo threshold */ |
|
|
|
FSpimSetRxFifoThreshold(base_addr, instance_p->rx_fifo_len); |
|
|
|
FSpimSetTxFifoThreshold(base_addr, instance_p->tx_fifo_len); |
|
|
|
|
|
|
|
/* setup fifo DMA level to trigger interrupt */ |
|
|
|
FSpimSetRxDMALevel(base_addr, FSPIM_RX_DMA_LEVEL); |
|
|
|
FSpimSetTxDMALevel(base_addr, FSPIM_TX_DMA_LEVEL); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
FSpimSetCtrlR1(base_addr, 0); |
|
|
|
|
|
|
|
FSpimSetRxFifoThreshold(base_addr, 0); |
|
|
|
FSpimSetTxFifoThreshold(base_addr, 0); |
|
|
|
FSpimSetRxDMALevel(base_addr, 0); |
|
|
|
FSpimSetTxDMALevel(base_addr, 0); |
|
|
|
instance_p->config.en_dma = TRUE; |
|
|
|
} |
|
|
|
|
|
|
|
FSpimSetCtrlR1(base_addr, 0); |
|
|
|
FSpimSetRxFifoThreshold(base_addr, instance_p->config.rx_fifo_threshold); |
|
|
|
FSpimSetTxFifoThreshold(base_addr, instance_p->config.tx_fifo_threshold); |
|
|
|
FSpimSetRxDMALevel(base_addr, instance_p->config.rx_dma_level); |
|
|
|
FSpimSetTxDMALevel(base_addr, instance_p->config.tx_dma_level); |
|
|
|
|
|
|
|
ret = FSpimSetSpeed(base_addr, instance_p->config.freq_hz); |
|
|
|
if (FSPIM_SUCCESS != ret) |
|
|
@ -224,7 +197,7 @@ FError FSpimReset(FSpim *instance_p) |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
FSPIM_WRITE_REG32(base_addr, FSPIM_RX_SAMPLE_DLY_OFFSET, FSPIM_DEFAULT_RSD); |
|
|
|
FSPIM_WRITE_REG32(base_addr, FSPIM_RX_SAMPLE_DLY_OFFSET, 0); |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
@ -251,7 +224,7 @@ FError FSpimSetOption(FSpim *instance_p, FSpimOption option, u32 value) |
|
|
|
} |
|
|
|
|
|
|
|
FSpimSetEnable(base_addr, FALSE); |
|
|
|
|
|
|
|
|
|
|
|
if (option == FSPIM_CPOLTYPE_OPTION) |
|
|
|
{ |
|
|
|
if (value == FSPIM_CPOL_HIGH || value == FSPIM_CPOL_LOW) |
|
|
@ -377,7 +350,8 @@ static fsize_t FSpimGetTxRound(FSpim *instance_p) |
|
|
|
FSpimGetTxFifoLevel(base_addr); |
|
|
|
|
|
|
|
rx_tx_gap = ((fsize_t)(instance_p->length - instance_p->rx_count) - |
|
|
|
(fsize_t)(instance_p->length - instance_p->tx_count)) / data_width; |
|
|
|
(fsize_t)(instance_p->length - instance_p->tx_count)) / |
|
|
|
data_width; |
|
|
|
|
|
|
|
FSPIM_DEBUG("tx_left_round: %d, tx_fifo_room: %d, gap: %d, instance_p->tx_count: %ld", |
|
|
|
tx_left_round, |
|
|
@ -412,23 +386,23 @@ void FSpimFifoTx(FSpim *instance_p) |
|
|
|
{ |
|
|
|
data = FSPIM_ONE_BYTE_DATA_MASK; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while (tx_round) |
|
|
|
{ |
|
|
|
if(instance_p->tx_buff) |
|
|
|
if (instance_p->tx_buff) |
|
|
|
{ |
|
|
|
if (FSPIM_1_BYTE == data_width) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Data Transfer Width is Byte (8 bit). |
|
|
|
*/ |
|
|
|
* Data Transfer Width is Byte (8 bit). |
|
|
|
*/ |
|
|
|
data = *(u8 *)(instance_p->tx_buff); |
|
|
|
} |
|
|
|
else if (FSPIM_2_BYTE == data_width) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Data Transfer Width is Half Word (16 bit). |
|
|
|
*/ |
|
|
|
* Data Transfer Width is Half Word (16 bit). |
|
|
|
*/ |
|
|
|
data = *(u16 *)(instance_p->tx_buff); |
|
|
|
} |
|
|
|
else |
|
|
@ -456,8 +430,8 @@ static fsize_t FSpimGetRxRound(FSpim *instance_p) |
|
|
|
uintptr base_addr = instance_p->config.base_addr; |
|
|
|
|
|
|
|
fsize_t rx_left_round = (fsize_t)(instance_p->length - instance_p->rx_count) / data_width; |
|
|
|
|
|
|
|
FSPIM_DEBUG("left round %d, rx level %d,instance_p->rx_count %ld", rx_left_round, FSpimGetRxFifoLevel(base_addr),instance_p->rx_count); |
|
|
|
|
|
|
|
FSPIM_DEBUG("left round %d, rx level %d,instance_p->rx_count %ld", rx_left_round, FSpimGetRxFifoLevel(base_addr), instance_p->rx_count); |
|
|
|
return min(rx_left_round, (fsize_t)FSpimGetRxFifoLevel(base_addr)); |
|
|
|
} |
|
|
|
|
|
|
@ -478,21 +452,21 @@ void FSpimFifoRx(FSpim *instance_p) |
|
|
|
while (rx_round) |
|
|
|
{ |
|
|
|
data = FSpimReadData(base_addr); |
|
|
|
if(instance_p->rx_buff) |
|
|
|
if (instance_p->rx_buff) |
|
|
|
{ |
|
|
|
if (FSPIM_1_BYTE == data_width) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Data Transfer Width is Byte (8 bit). |
|
|
|
*/ |
|
|
|
* Data Transfer Width is Byte (8 bit). |
|
|
|
*/ |
|
|
|
*(u8 *)(instance_p->rx_buff) = (u8)data; |
|
|
|
FSPIM_DEBUG(" recv 0x%x", *(u8 *)(instance_p->rx_buff)); |
|
|
|
} |
|
|
|
else if (FSPIM_2_BYTE == data_width) |
|
|
|
{ |
|
|
|
/*
|
|
|
|
* Data Transfer Width is Half Word (16 bit). |
|
|
|
*/ |
|
|
|
* Data Transfer Width is Half Word (16 bit). |
|
|
|
*/ |
|
|
|
*(u16 *)(instance_p->rx_buff) = (u16)data; |
|
|
|
FSPIM_DEBUG(" recv 0x%x", *(u16 *)(instance_p->rx_buff)); |
|
|
|
} |
|
|
@ -502,7 +476,7 @@ void FSpimFifoRx(FSpim *instance_p) |
|
|
|
} |
|
|
|
instance_p->rx_buff += data_width; |
|
|
|
} |
|
|
|
instance_p->rx_count += data_width; |
|
|
|
instance_p->rx_count += data_width; |
|
|
|
rx_round--; |
|
|
|
} |
|
|
|
|
|
|
@ -534,7 +508,7 @@ FError FSpimTransferPollFifo(FSpim *instance_p, const void *tx_buf, void *rx_buf |
|
|
|
FSPIM_ERROR("The device is not initialized!!!"); |
|
|
|
return FSPIM_ERR_NOT_READY; |
|
|
|
} |
|
|
|
FSPIM_DEBUG("buff address rx= %x, tx=%x\r\n", rx_buf,tx_buf); |
|
|
|
FSPIM_DEBUG("buff address rx= %x, tx=%x\r\n", rx_buf, tx_buf); |
|
|
|
FSpimSetEnable(base_addr, FALSE); |
|
|
|
|
|
|
|
reg_val = FSpimGetCtrlR0(base_addr); |
|
|
@ -569,13 +543,12 @@ FError FSpimTransferPollFifo(FSpim *instance_p, const void *tx_buf, void *rx_buf |
|
|
|
instance_p->rx_buff, len); |
|
|
|
|
|
|
|
FSpimSetEnable(base_addr, TRUE); |
|
|
|
|
|
|
|
do |
|
|
|
{ |
|
|
|
{ |
|
|
|
FSpimFifoTx(instance_p); |
|
|
|
FSpimFifoRx(instance_p); |
|
|
|
} |
|
|
|
while(instance_p->tx_count < len || instance_p->rx_count < len); |
|
|
|
|
|
|
|
} while (instance_p->tx_count < len || instance_p->rx_count < len); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
@ -632,7 +605,7 @@ FError FSpimTransferByInterrupt(FSpim *instance_p, const void *tx_buf, void *rx_ |
|
|
|
instance_p->tx_buff = tx_buf; |
|
|
|
instance_p->rx_buff = rx_buf; |
|
|
|
/* 设置中断触发的时机,fifo填满一半,或者所有的数据填完 */ |
|
|
|
tx_level = min(instance_p->tx_fifo_len / 2, instance_p->length / data_width); |
|
|
|
tx_level = min(instance_p->tx_fifo_len / 2 + 1, instance_p->length / data_width); |
|
|
|
FSpimSetTxFifoThreshold(base_addr, tx_level); |
|
|
|
FSpimUmaskIrq(base_addr, FSPIM_IMR_TXEIS | FSPIM_IMR_TXOIS | FSPIM_IMR_RXUIS | FSPIM_IMR_RXOIS); |
|
|
|
|
|
|
@ -659,7 +632,6 @@ FError FSpimTransferDMA(FSpim *instance_p) |
|
|
|
|
|
|
|
/* disable ddma */ |
|
|
|
FSpimDisenableDdmaChannel(base_addr); |
|
|
|
|
|
|
|
|
|
|
|
if (FT_COMPONENT_IS_READY != instance_p->is_ready) |
|
|
|
{ |
|
|
@ -730,27 +702,3 @@ void FSpimSetChipSelection(FSpim *instance_p, boolean on) |
|
|
|
|
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @name: FSpimErrorToMessage |
|
|
|
* @msg: 获取FSPIM模块错误码对应的错误信息 |
|
|
|
* @return {const char *}, 错误码信息,NULL表示失败 |
|
|
|
* @param {FError} error, FSPIM输入错误码 |
|
|
|
*/ |
|
|
|
const char *FSpimErrorToMessage(FError error) |
|
|
|
{ |
|
|
|
const char *msg = NULL; |
|
|
|
if ((FSPIM_SUCCESS != error) && (FSPIM_ERR_CODE_PREFIX != (error & (FT_ERRCODE_SYS_MODULE_MASK | FT_ERRCODE_SUB_MODULE_MASK)))) |
|
|
|
{ |
|
|
|
/* if input error do not belong to this module */ |
|
|
|
return msg; |
|
|
|
} |
|
|
|
u32 index = error & FT_ERRCODE_TAIL_VALUE_MASK; |
|
|
|
|
|
|
|
if (index < FSPIM_NUM_OF_ERR_CODE) |
|
|
|
{ |
|
|
|
msg = FSPIM_ERROR_CODE_MSG[index]; |
|
|
|
} |
|
|
|
|
|
|
|
return msg; |
|
|
|
} |
|
|
|