674 lines
19 KiB
C
674 lines
19 KiB
C
/*!
|
|
* \file xc6xxx_hal_spi.c
|
|
*
|
|
* \brief Target xc6xxx hal spi implementation
|
|
*
|
|
* \copyright Revised BSD License, see section \ref LICENSE.
|
|
*
|
|
* \code
|
|
*
|
|
* _ __ _ ________ _
|
|
* | |/ /(_)___ / ____/ /_ (_)___
|
|
* | // / __ \/ / / __ \/ / __ \
|
|
* / |/ / / / / /___/ / / / / /_/ /
|
|
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
|
|
* /_/
|
|
* (C) 2022-2025 XinChip
|
|
*
|
|
* \endcode
|
|
*
|
|
* \author ( XinChip ) Alex-J
|
|
*
|
|
* \author ( XinChip )
|
|
*/
|
|
|
|
/*-----------------------------------------------------------------------------------
|
|
INCLUDE HEADE FILES
|
|
------------------------------------------------------------------------------------*/
|
|
#include "xc6xxx.h"
|
|
|
|
#if XC_CHECK(XC_SPI_ENABLED)
|
|
/*------------------------------------------------------------------------------------
|
|
Global Variables
|
|
-------------------------------------------------------------------------------------*/
|
|
|
|
typedef struct
|
|
{
|
|
bool SPI_DMA_IT_Enable_Flag[3];
|
|
uint8_t SPI_Mode[3];
|
|
} SPI_CtrlBlock_Typedef;
|
|
|
|
SPI_CtrlBlock_Typedef m_spi_cb;
|
|
|
|
/*------------------------------------------------------------------------------------
|
|
Func Prototype
|
|
-------------------------------------------------------------------------------------*/
|
|
eXC_RESULT xc_spi_write_bytes(uint8_t reg_idx, uint8_t *txdata, uint16_t len);
|
|
eXC_RESULT xc_spi_read_bytes(uint8_t reg_idx, uint8_t *rxdata, uint16_t len);
|
|
/*------------------------------------------------------------------------------------
|
|
Functions
|
|
-------------------------------------------------------------------------------------*/
|
|
void xc_spi_init(uint8_t reg_idx, SPI_InitCfg_t *init_cfg)
|
|
{
|
|
#if (USE_XIP == 0)
|
|
if (SPI0_IDX == reg_idx) {
|
|
cpr_rstctl_subrst_sw__ssi0_rstn__setf(RSTCTL_ENABLE);
|
|
cpr_rstctl_subrst_sw__ssi0_rstn__setf(RSTCTL_DISABLE);
|
|
|
|
cpr_ctlapbclken_grctl__ssi0_pclk_en__setf(ENABLE);
|
|
|
|
cpr_ssi0_mclk_ctl__ssi_mclk_div__setf(0);
|
|
cpr_ssi0_mclk_ctl__ssi_mclk_en__setf(1);
|
|
|
|
cpr_ssi_ctrl__ssi0_protocol__setf(SSI_CTRL0_FRF_MOTOROLA);
|
|
|
|
}
|
|
#endif
|
|
if (SPI1_IDX == reg_idx) {
|
|
|
|
cpr_rstctl_subrst_sw__ssi1_rstn__setf(RSTCTL_ENABLE);
|
|
cpr_rstctl_subrst_sw__ssi1_rstn__setf(RSTCTL_DISABLE);
|
|
|
|
cpr_ssi1_mclk_ctl__ssi_mclk_div__setf(0);
|
|
cpr_ssi1_mclk_ctl__ssi_mclk_en__setf(1);
|
|
|
|
cpr_ctlapbclken_grctl__ssi1_pclk_en__setf(ENABLE);
|
|
|
|
if (init_cfg->Mode == SPI_MODE_MASTER) {
|
|
|
|
cpr_ssi_ctrl__ssi1_master_en__setf(ENABLE);
|
|
} else if (init_cfg->Mode == SPI_MODE_SLAVE) {
|
|
|
|
cpr_ssi_ctrl__ssi1_master_en__setf(DISABLE);
|
|
}
|
|
cpr_ssi_ctrl__ssi1_protocol__setf(SSI_CTRL0_FRF_MOTOROLA);
|
|
} else if (SPI2_IDX == reg_idx) {
|
|
|
|
cpr_rstctl_subrst_sw__ssi2_rstn__setf(RSTCTL_ENABLE);
|
|
cpr_rstctl_subrst_sw__ssi2_rstn__setf(RSTCTL_DISABLE);
|
|
|
|
cpr_ssi1_mclk_ctl__ssi2_mclk_div__setf(0);
|
|
cpr_ssi1_mclk_ctl__ssi2_mclk_en__setf(1);
|
|
|
|
cpr_ctlapbclken_grctl__ssi2_pclk_en__setf(ENABLE);
|
|
|
|
cpr_ssi_ctrl__ssi2_protocol__setf(SSI_CTRL0_FRF_MOTOROLA);
|
|
}
|
|
|
|
spi_en_set(reg_idx, DISABLE);
|
|
// sste is automatically set to 1 when spi slave is initialized.
|
|
// therefor, manually clear this bit to 0 here.
|
|
spi_ctrl0__ssi_sste__setf(reg_idx, DISABLE);
|
|
spi_ctrl0__ssi_tmod__setf(reg_idx, init_cfg->Direction);
|
|
spi_ctrl0__ssi_scpol__setf(reg_idx, init_cfg->CLKPolarity);
|
|
spi_ctrl0__ssi_scpha__setf(reg_idx, init_cfg->CLKPhase);
|
|
spi_ctrl0__ssi_dfs__setf(reg_idx, init_cfg->DataSize);
|
|
|
|
spi_ie_set(reg_idx, DISABLE);
|
|
spi_se_set(reg_idx, ENABLE);
|
|
spi_baud__ssi_sckdv__setf(reg_idx, init_cfg->BaudRatePrescaler);
|
|
spi_txftl__ssi_tft__setf(reg_idx, SSI_TXFTL_FIFO_1);
|
|
spi_rxftl__ssi_rft__setf(reg_idx, SSI_RXFTL_FIFO_1);
|
|
}
|
|
|
|
static void xc_spi_enable(uint8_t reg_idx, uint8_t dfs)
|
|
{
|
|
spi_en__ssi_sen__setf(reg_idx, DISABLE);
|
|
spi_dmas_set(reg_idx, DISABLE);
|
|
spi_ctrl0__ssi_dfs__setf(reg_idx, dfs);
|
|
spi_en__ssi_sen__setf(reg_idx, ENABLE);
|
|
}
|
|
|
|
static void xc_spi_disable(uint8_t reg_idx) { spi_en__ssi_sen__setf(reg_idx, DISABLE); }
|
|
|
|
void xc_spi_rxftl_fifo_set(uint8_t reg_idx, uint8_t val)
|
|
{
|
|
spi_rxftl__ssi_rft__setf(reg_idx, val);
|
|
}
|
|
|
|
void xc_spi_txftl_fifo_set(uint8_t reg_idx, uint8_t val)
|
|
{
|
|
spi_txftl__ssi_tft__setf(reg_idx, val);
|
|
}
|
|
|
|
void xc_spi_enable_it(uint8_t reg_idx, uint8_t val) { spi_ie_set(reg_idx, val); }
|
|
|
|
void xc_spi_disable_it(uint8_t reg_idx, uint8_t val) { spi_ie_set(reg_idx, val); }
|
|
|
|
void xc_spi_flash_power_down(uint8_t reg_idx)
|
|
{
|
|
uint8_t txbuff[2] = {0};
|
|
|
|
txbuff[1] = CMD_PWRDWN;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_8BIT);
|
|
xc_spi_write_bytes(reg_idx, txbuff, sizeof(txbuff));
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
|
|
void xc_spi_flash_wake_up(uint8_t reg_idx)
|
|
{
|
|
uint8_t txbuff[2] = {0};
|
|
|
|
txbuff[1] = CMD_RELEASE_PWRDWN;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_8BIT);
|
|
xc_spi_write_bytes(reg_idx, txbuff, sizeof(txbuff));
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
|
|
static uint8_t xc_spi_flash_wait_busy(uint8_t reg_idx)
|
|
{
|
|
uint8_t cmd[2] = {0};
|
|
uint8_t sta[2] = {0xff, 0xff};
|
|
|
|
cmd[0] = CMD_READ_STATUS;
|
|
cmd[1] = 0xff;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
|
|
xc_spi_read_bytes(reg_idx, sta, sizeof(sta));
|
|
xc_spi_disable(reg_idx);
|
|
|
|
return (sta[1] & 0x01);
|
|
}
|
|
|
|
static void xc_spi_flash_write_enable(uint8_t reg_idx)
|
|
{
|
|
uint8_t txbuff[2] = {0};
|
|
|
|
txbuff[1] = CMD_WRITE_ENABLE;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_8BIT);
|
|
xc_spi_write_bytes(reg_idx, txbuff, sizeof(txbuff));
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
|
|
eXC_RESULT xc_spi_flash_erase_sector(uint8_t reg_idx, uint32_t Dst_Addr)
|
|
{
|
|
uint8_t cmd[4];
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
xc_spi_flash_write_enable(reg_idx);
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
|
|
cmd[0] = CMD_SECTOR_ERASE;
|
|
cmd[1] = Dst_Addr >> 16;
|
|
cmd[2] = Dst_Addr >> 8;
|
|
cmd[3] = Dst_Addr;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
#ifndef FAST_SPI
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
#else
|
|
xc_spi_write_2bytes(reg_idx, cmd, sizeof(cmd));
|
|
#endif
|
|
xc_spi_disable(reg_idx);
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
|
|
return XR_OK;
|
|
}
|
|
#if (USE_INTEGRATED_FlASH == USE_PUYA_FlASH)
|
|
void xc_spi_flash_erase_page(uint8_t reg_idx, uint32_t Dst_Addr)
|
|
{
|
|
uint8_t cmd[4];
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
xc_spi_flash_write_enable(reg_idx);
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
|
|
cmd[0] = CMD_PAGE_ERASE;
|
|
cmd[1] = Dst_Addr >> 16;
|
|
cmd[2] = Dst_Addr >> 8;
|
|
cmd[3] = Dst_Addr;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
#ifndef FAST_SPI
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
#else
|
|
xc_spi_write_2bytes(reg_idx, cmd, sizeof(cmd));
|
|
#endif
|
|
xc_spi_disable(reg_idx);
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
}
|
|
#endif
|
|
#ifndef FAST_SPI
|
|
void xc_spi_flash_write_page(uint8_t reg_idx, uint32_t WriteAddr, uint8_t *pBuffer)
|
|
{
|
|
uint32_t addr = WriteAddr;
|
|
uint8_t cmd[16 + 4] = {0};
|
|
|
|
for (uint8_t i = 0; i < 16; i++) {
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
xc_spi_flash_write_enable(reg_idx);
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
|
|
cmd[0] = CMD_PAGE_PROGRAM;
|
|
cmd[1] = addr >> 16;
|
|
cmd[2] = addr >> 8;
|
|
cmd[3] = addr;
|
|
|
|
memcpy(&cmd[4], pBuffer + i * 16, 16);
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
|
|
addr += 16;
|
|
}
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
#else
|
|
void xc_spi_flash_write_page(uint8_t reg_idx, uint32_t WriteAddr, uint8_t *pBuffer)
|
|
{
|
|
|
|
uint8_t cmd[256 + 4] = {0};
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
xc_spi_flash_write_enable(reg_idx);
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
|
|
cmd[0] = CMD_PAGE_PROGRAM;
|
|
cmd[1] = WriteAddr >> 16;
|
|
cmd[2] = WriteAddr >> 8;
|
|
cmd[3] = WriteAddr;
|
|
|
|
memcpy(&cmd[4], pBuffer, FLASH_PAGE_SIZE);
|
|
|
|
xc_spi_write_2bytes(reg_idx, cmd, sizeof(cmd));
|
|
|
|
|
|
while (xc_spi_flash_wait_busy(reg_idx))
|
|
;
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
#endif
|
|
void xc_spi_flash_read_page(uint8_t reg_idx, uint32_t ReadAddr, uint8_t *pBuffer)
|
|
{
|
|
uint8_t cmd[16 + 4] = {0};
|
|
uint8_t mid[16 + 4] = {0};
|
|
uint16_t rx_idx = 0;
|
|
uint32_t addr = ReadAddr;
|
|
|
|
for (uint8_t i = 0; i < 16; i++) {
|
|
cmd[0] = CMD_READ_DATA;
|
|
cmd[1] = addr >> 16;
|
|
cmd[2] = addr >> 8;
|
|
cmd[3] = addr;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
xc_spi_read_bytes(reg_idx, mid, sizeof(cmd));
|
|
|
|
memcpy(&pBuffer[rx_idx], mid + 4, 16);
|
|
addr += 16;
|
|
rx_idx += 16;
|
|
}
|
|
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @brief
|
|
*
|
|
* @param[in]
|
|
* @param[in]
|
|
|
|
* @return[out]
|
|
*
|
|
****************************************************************************************
|
|
*/
|
|
eXC_RESULT xc_spi_flash_write(uint8_t reg_idx, uint32_t addr, uint8_t *buff,
|
|
uint16_t size)
|
|
{
|
|
eXC_RESULT ret = XR_OK;
|
|
uint32_t cur_addr = addr;
|
|
uint32_t end_addr = addr + size;
|
|
uint16_t wt_len = 0;
|
|
// The current page number occupied by this data storage
|
|
// The position occupied by this address on the current page
|
|
uint32_t cur_start_psr = 0;
|
|
uint16_t cur_size;
|
|
|
|
#ifndef GD_FlASH_INTEGRATION
|
|
uint16_t cur_page_num = 0;
|
|
uint8_t temp_buff[FLASH_PAGE_SIZE];
|
|
while (cur_addr != end_addr) {
|
|
/* code */
|
|
cur_page_num = CUR_PAGE_NUM(cur_addr);
|
|
cur_start_psr = CUR_START_PSR(cur_addr);
|
|
|
|
xc_spi_flash_read_page(reg_idx, cur_page_num * FLASH_PAGE_SIZE, temp_buff);
|
|
xc_spi_flash_erase_page(reg_idx, cur_page_num * FLASH_PAGE_SIZE);
|
|
|
|
if (cur_start_psr) {
|
|
cur_size = MIN(FLASH_PAGE_SIZE - cur_start_psr, size - wt_len);
|
|
} else {
|
|
cur_size = MIN(FLASH_PAGE_SIZE, size - wt_len);
|
|
}
|
|
memcpy(&temp_buff[cur_start_psr], buff + wt_len, cur_size);
|
|
wt_len += cur_size;
|
|
cur_addr += cur_size;
|
|
|
|
xc_spi_flash_write_page(reg_idx, cur_page_num * FLASH_PAGE_SIZE, temp_buff);
|
|
}
|
|
#else
|
|
uint16_t cur_sector_num = 0;
|
|
uint8_t temp_buff[FLASH_SECTOR_SIZE] = {0};
|
|
while (cur_addr != end_addr) {
|
|
/* code */
|
|
cur_sector_num = CUR_SECTOR_NUM(cur_addr);
|
|
cur_start_psr = CUR_START_PSR(cur_addr);
|
|
|
|
for(int i=0;i<FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE;i++){
|
|
xc_spi_flash_read_page(reg_idx, CUR_SECTOR_PAGE_ADDR(cur_sector_num, i), temp_buff+i*FLASH_PAGE_SIZE);
|
|
}
|
|
|
|
xc_spi_flash_erase_sector(reg_idx, cur_sector_num * FLASH_SECTOR_SIZE);
|
|
|
|
if (cur_start_psr) {
|
|
cur_size = MIN(FLASH_SECTOR_SIZE - cur_start_psr, size - wt_len);
|
|
} else {
|
|
cur_size = MIN(FLASH_SECTOR_SIZE, size - wt_len);
|
|
}
|
|
|
|
memcpy(&temp_buff[cur_start_psr], buff + wt_len, cur_size);
|
|
wt_len += cur_size;
|
|
cur_addr += cur_size;
|
|
|
|
for(int i=0;i<FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE;i++){
|
|
xc_spi_flash_write_page(reg_idx, CUR_SECTOR_PAGE_ADDR(cur_sector_num, i), temp_buff+i*FLASH_PAGE_SIZE);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @brief
|
|
*
|
|
* @param[in]
|
|
* @param[in]
|
|
|
|
* @return[out]
|
|
*
|
|
****************************************************************************************
|
|
*/
|
|
eXC_RESULT xc_spi_flash_read(uint8_t reg_idx, uint32_t addr, uint8_t *buff,
|
|
uint16_t size)
|
|
{
|
|
eXC_RESULT ret = XR_OK;
|
|
uint32_t cur_addr = addr;
|
|
uint32_t end_addr = addr + size;
|
|
uint16_t rd_len = 0;
|
|
uint16_t cur_page_num = 0;
|
|
uint32_t cur_start_psr = 0;
|
|
uint8_t temp_buff[FLASH_PAGE_SIZE] = {0};
|
|
uint16_t cur_size;
|
|
|
|
while (cur_addr != end_addr) {
|
|
cur_page_num = CUR_PAGE_NUM(cur_addr);
|
|
cur_start_psr = CUR_START_PSR(cur_addr);
|
|
xc_spi_flash_read_page(reg_idx, cur_page_num * FLASH_PAGE_SIZE, temp_buff);
|
|
if (cur_start_psr) {
|
|
cur_size = MIN(FLASH_PAGE_SIZE - cur_start_psr, size - rd_len);
|
|
} else {
|
|
cur_size = MIN(FLASH_PAGE_SIZE, size - rd_len);
|
|
}
|
|
|
|
memcpy(buff + rd_len, &temp_buff[cur_start_psr], cur_size);
|
|
cur_addr += cur_size;
|
|
rd_len += cur_size;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void xc_spi_flash_read_128bit_uid(uint8_t reg_idx, uint8_t *buff)
|
|
{
|
|
while (xc_spi_flash_wait_busy(reg_idx)) {
|
|
DEBUG("line=%d,status=%d\n", __LINE__, xc_spi_flash_wait_busy(reg_idx));
|
|
};
|
|
|
|
uint8_t cmd[21] = {0};
|
|
uint8_t id[21] = {0};
|
|
|
|
cmd[0] = CMD_RUID;
|
|
cmd[1] = 0x00;
|
|
cmd[2] = 0x00;
|
|
cmd[3] = 0x00;
|
|
cmd[4] = 0x00;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
|
|
xc_spi_read_bytes(reg_idx, id, sizeof(id));
|
|
xc_spi_disable(reg_idx);
|
|
|
|
memcpy(buff, &id[5], 16);
|
|
}
|
|
|
|
eXC_RESULT xc_spi_flash_rdid(uint8_t reg_idx, uint8_t *buff)
|
|
{
|
|
while (xc_spi_flash_wait_busy(reg_idx)) {
|
|
DEBUG("line=%d,status=%d\n", __LINE__, xc_spi_flash_wait_busy(reg_idx));
|
|
};
|
|
|
|
uint8_t cmd[4] = {0};
|
|
uint8_t id[4] = {0};
|
|
|
|
cmd[0] = CMD_RDID;
|
|
cmd[1] = 0xff;
|
|
cmd[2] = 0xff;
|
|
cmd[3] = 0xff;
|
|
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
|
|
|
|
xc_spi_read_bytes(reg_idx, id, sizeof(id));
|
|
xc_spi_disable(reg_idx);
|
|
|
|
memcpy(buff, &id[1], 3);
|
|
|
|
return XR_OK;
|
|
}
|
|
|
|
/*---------------------------------- SPI1 Master & Slave API
|
|
* ---------------------------------------*/
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @brief Only Master & Slave
|
|
*
|
|
* @param[in]
|
|
* @param[in]
|
|
****************************************************************************************
|
|
*/
|
|
static void xc_spi_datasize_set(uint8_t reg_idx, uint8_t dfs)
|
|
{
|
|
|
|
spi_en_set(reg_idx, DISABLE);
|
|
spi_ctrl0__ssi_dfs__setf(reg_idx, dfs);
|
|
spi_en_set(reg_idx, ENABLE);
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @brief Only applicable Master & Slave communication
|
|
*
|
|
* @param[in]
|
|
* @param[in]
|
|
****************************************************************************************
|
|
*/
|
|
eXC_RESULT xc_spi_write_bytes(uint8_t reg_idx, uint8_t *txdata, uint16_t len)
|
|
{
|
|
if (len == 0)
|
|
return XR_ERROR;
|
|
uint16_t n;
|
|
uint8_t remain = len % 2;
|
|
uint16_t cnt = len / 2;
|
|
uint16_t mid_data[128 + 1] = {0};
|
|
uint32_t i = 0;
|
|
|
|
while (spi_sts__ssi_tfe__getf(reg_idx) == RESET) {
|
|
i++;
|
|
if (i >= SPI_WAIT_TIMEOUT) {
|
|
DEBUG("func=%s,line=%d,timeout\n", __func__, __LINE__);
|
|
return XR_TIMEOUT;
|
|
}
|
|
}
|
|
|
|
if (cnt != 0) {
|
|
for (n = 0; n < cnt; n++) {
|
|
mid_data[n] = ((txdata[n * 2] << 8) | txdata[n * 2 + 1]);
|
|
}
|
|
}
|
|
|
|
if (remain != 0) {
|
|
for (n = 0; n < remain; n++) {
|
|
mid_data[cnt] |= (txdata[cnt * 2 + n] << (16 - 8 * n));
|
|
}
|
|
}
|
|
|
|
if (cnt != 0) {
|
|
if (remain != 0)
|
|
cnt = cnt + 1;
|
|
for (n = 0; n < cnt; n++)
|
|
spi_data_set(reg_idx, mid_data[n]);
|
|
} else {
|
|
spi_data_set(reg_idx, mid_data[0]);
|
|
}
|
|
|
|
while ((spi_sts__ssi_rfne__getf(reg_idx) == RESET) ||
|
|
(spi_sts__ssi_tfe__getf(reg_idx) == RESET)) {
|
|
i++;
|
|
if (i >= SPI_WAIT_TIMEOUT) {
|
|
// DEBUG("func=%s,line=%d,timeout\n", __func__, __LINE__);
|
|
return XR_TIMEOUT;
|
|
}
|
|
}
|
|
|
|
return XR_OK;
|
|
}
|
|
#if FAST_SPI
|
|
eXC_RESULT xc_spi_write_2bytes(uint8_t reg_idx, uint8_t *txdata, uint16_t size)
|
|
{
|
|
uint32_t time_out;
|
|
uint32_t temp_data;
|
|
uint16_t idx_8bit = 0;
|
|
uint16_t idx_16bit = 0;
|
|
uint8_t remain_size = size % 2;
|
|
uint16_t allign_16bit_size = size >> 1;
|
|
|
|
if (size == 0)
|
|
return XR_ERROR;
|
|
xc_spi_enable(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
while(!(spi_sts_get(reg_idx)&(1<<SSI_TFE_POS)));
|
|
while(idx_16bit < allign_16bit_size)
|
|
{
|
|
temp_data = ((txdata[idx_8bit] << 8) | txdata[idx_8bit+1]);
|
|
spi_data_set(reg_idx, temp_data);
|
|
idx_16bit++;
|
|
idx_8bit+=2;
|
|
}
|
|
if (remain_size != 0 ){
|
|
for (uint8_t i = 0; i < remain_size; i++){
|
|
temp_data |= (txdata[idx_8bit + i] << (8 - 8 * i));
|
|
}
|
|
while (!(spi_sts_get(reg_idx) & (1<<SSI_TFNF_POS)));
|
|
spi_data_set(reg_idx, temp_data);
|
|
}
|
|
while (!(spi_sts_get(reg_idx) & (1<<SSI_TFE_POS)) ||
|
|
(spi_sts_get(reg_idx) & (1<<SSI_BUSY_POS)))
|
|
{
|
|
time_out++;
|
|
if (time_out >= SPI_WAIT_TIMEOUT) {
|
|
DEBUG("func=%s,line=%d,timeout\n", __func__, __LINE__);
|
|
return XR_TIMEOUT;
|
|
}
|
|
}
|
|
return XR_OK;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @brief Only applicable Master & Slave communication
|
|
*
|
|
* @param[in]
|
|
* @param[in]
|
|
****************************************************************************************
|
|
*/
|
|
eXC_RESULT xc_spi_read_bytes(uint8_t reg_idx, uint8_t *rxdata, uint16_t len)
|
|
{
|
|
if (len == 0)
|
|
return XR_ERROR;
|
|
|
|
uint16_t n;
|
|
uint8_t remain = len % 2;
|
|
uint16_t cnt = len / 2;
|
|
uint16_t mid_data = 0;
|
|
|
|
if (cnt != 0) {
|
|
for (n = 0; n < cnt; n++) {
|
|
|
|
mid_data = spi_data_get(reg_idx);
|
|
rxdata[n * 2] = mid_data >> 8;
|
|
rxdata[n * 2 + 1] = mid_data;
|
|
}
|
|
}
|
|
|
|
if (remain != 0) {
|
|
|
|
mid_data = spi_data_get(reg_idx);
|
|
for (n = 0; n < remain; n++) {
|
|
rxdata[cnt * 2 + n] = mid_data >> 8;
|
|
rxdata[cnt * 2 + 1 + n] = mid_data;
|
|
}
|
|
}
|
|
|
|
return XR_OK;
|
|
}
|
|
|
|
/**
|
|
****************************************************************************************
|
|
* @brief Only applicable Master & Slave communication
|
|
*
|
|
* @param[in]
|
|
* @param[in]
|
|
****************************************************************************************
|
|
*/
|
|
void xc_spi_write_and_read_data(uint8_t reg_idx, uint8_t *w_data, uint16_t w_size,
|
|
uint8_t *r_data, uint16_t r_size)
|
|
{
|
|
if (w_size != (spi_rxftl_get(reg_idx) + 1) * 2)
|
|
return;
|
|
xc_spi_datasize_set(reg_idx, SSI_CTRL0_DFS_LEN_16BIT);
|
|
xc_spi_write_bytes(reg_idx, w_data, w_size);
|
|
|
|
while (!(spi_is_get(reg_idx) == SSI_IS_RXFIS_SET))
|
|
;
|
|
xc_spi_read_bytes(reg_idx, r_data, r_size);
|
|
xc_spi_disable(reg_idx);
|
|
}
|
|
|
|
#endif // XC_CHECK(XC_SPI_ENABLED)
|