hpw422初始版本

This commit is contained in:
xushaoxiang
2026-06-04 09:13:55 +08:00
commit 982da04a92
3279 changed files with 860351 additions and 0 deletions
@@ -0,0 +1,662 @@
/*!
* \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"
#include "xc_drv_fmc_spi.h"
/*------------------------------------------------------------------------------------
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);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
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);
xc_spi_write_bytes(reg_idx, cmd, sizeof(cmd));
xc_spi_disable(reg_idx);
while (xc_spi_flash_wait_busy(reg_idx))
;
}
#endif
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);
}
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 writeAddr, uint8_t *buff,
uint16_t size)
{
uint32_t cur_addr = writeAddr;
uint32_t end_addr = writeAddr + size;
uint16_t wt_len = 0;
// The current page number occupied by this data storage
uint16_t CurSectorNum = 0;
uint16_t CurPageNum = 0;
// The position occupied by this address on the current page
uint32_t CurStartPsr = 0;
uint32_t mid = 0;
xc_spi_flash_rdid(reg_idx ,(uint8_t*)&mid);
if(mid != GD_FlASH_RDID){
uint8_t temp_buff[FLASH_PAGE_SIZE];
while (cur_addr != end_addr) {
/* code */
CurPageNum = CUR_PAGE_NUM(cur_addr);
CurStartPsr = CUR_START_PSR(cur_addr);
xc_spi_flash_read_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE, temp_buff);
xc_spi_flash_erase_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE);
if (CurStartPsr) {
memcpy(&temp_buff[CurStartPsr], buff + wt_len,
(FLASH_PAGE_SIZE - CurStartPsr) > size - wt_len // 当前扇区剩余的空间是否满足写长度
? size - wt_len
: (FLASH_PAGE_SIZE - CurStartPsr));
wt_len += wt_len + ((FLASH_PAGE_SIZE - CurStartPsr) > size - wt_len
? size - wt_len
: (FLASH_PAGE_SIZE - CurStartPsr));
cur_addr += wt_len;
} else {
memcpy(temp_buff, buff + wt_len,
size - wt_len > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE
: size - wt_len);
cur_addr += (size - wt_len > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE
: size - wt_len);
wt_len += (size - wt_len > FLASH_PAGE_SIZE ? FLASH_PAGE_SIZE
: size - wt_len);
}
xc_spi_flash_write_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE, temp_buff);
}
}else if(mid == GD_FlASH_RDID){
uint8_t temp_buff[FLASH_SECTOR_SIZE];
while (cur_addr != end_addr) {
/* code */
CurSectorNum = CUR_SECTOR_NUM(cur_addr);
CurStartPsr = CUR_START_PSR(cur_addr);
for(int i=0;i<FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE;i++){
xc_spi_flash_read_page(reg_idx, CurSectorNum * FLASH_SECTOR_SIZE + i* FLASH_PAGE_SIZE, temp_buff+i*FLASH_PAGE_SIZE);
}
xc_spi_flash_erase_sector(reg_idx ,CurSectorNum * FLASH_SECTOR_SIZE);
if (CurStartPsr) {
memcpy(&temp_buff[CurStartPsr], buff + wt_len,
(FLASH_SECTOR_SIZE - CurStartPsr) > size - wt_len // 当前扇区剩余的空间是否满足写长度
? size - wt_len
: (FLASH_SECTOR_SIZE - CurStartPsr));
wt_len += wt_len + ((FLASH_SECTOR_SIZE - CurStartPsr) > size - wt_len
? size - wt_len
: (FLASH_SECTOR_SIZE - CurStartPsr));
cur_addr += wt_len;
} else {
memcpy(temp_buff, buff + wt_len,
size - wt_len > FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE
: size - wt_len);
cur_addr += (size - wt_len > FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE
: size - wt_len);
wt_len += (size - wt_len > FLASH_SECTOR_SIZE ? FLASH_SECTOR_SIZE
: size - wt_len);
}
for(int i=0;i<FLASH_SECTOR_SIZE/FLASH_PAGE_SIZE;i++){
xc_spi_flash_write_page(reg_idx, CurSectorNum * FLASH_SECTOR_SIZE + i* FLASH_PAGE_SIZE, temp_buff+i*FLASH_PAGE_SIZE);
}
}
}
return XR_OK;
}
/**
****************************************************************************************
* @brief
*
* @param[in]
* @param[in]
* @return[out]
*
****************************************************************************************
*/
eXC_RESULT xc_spi_flash_read(uint8_t reg_idx, uint32_t readAddr, uint8_t *buff,
uint16_t len)
{
eXC_RESULT ret = XR_OK;
// The page number to be occupied by the data written this time
uint16_t ReqPageCnt = 0;
// The current page number occupied by this data storage
uint16_t CurPageNum = 0;
// The position occupied by this address on the current page
uint16_t CurStartPsr = 0;
// The next page number that may be occupied by this data storage
uint16_t NextPageNum = 0;
// The end address of the next page that may be occupied by this data
// storage
uint16_t NextStopPsr = 0;
uint8_t temp_buff[FLASH_PAGE_SIZE] = {0};
if (len <= FLASH_PAGE_SIZE) {
CurPageNum = CUR_PAGE_NUM(readAddr);
CurStartPsr = CUR_START_PSR(readAddr);
if ((len + CurStartPsr) > FLASH_PAGE_SIZE)
ReqPageCnt = 2;
else
ReqPageCnt = 1;
if (ReqPageCnt == 1) // Note that only one page is read here
{
xc_spi_flash_read_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE,
temp_buff);
memcpy(buff, &temp_buff[CurStartPsr], len);
} else if (ReqPageCnt == 2) {
NextPageNum = CurPageNum + 1;
NextStopPsr = len + CurStartPsr - FLASH_PAGE_SIZE;
// First page read
xc_spi_flash_read_page(reg_idx, CurPageNum * FLASH_PAGE_SIZE,
temp_buff);
memcpy(buff, &temp_buff[CurStartPsr], len - NextStopPsr);
// second page read
uint16_t HaveCopyNum = len - NextStopPsr;
xc_spi_flash_read_page(reg_idx, NextPageNum * FLASH_PAGE_SIZE,
temp_buff);
memcpy(buff + HaveCopyNum, temp_buff, NextStopPsr);
}
} else {
CurPageNum = CUR_PAGE_NUM(readAddr);
CurStartPsr = CUR_START_PSR(readAddr);
NextPageNum = CurPageNum + 1;
uint16_t buff_idx = 0;
uint16_t pre_len = NextPageNum * FLASH_PAGE_SIZE - readAddr;
uint32_t pre_addr = CurPageNum * FLASH_PAGE_SIZE;
xc_spi_flash_read_page(reg_idx, pre_addr, temp_buff);
memcpy(buff, &temp_buff[CurStartPsr], pre_len);
buff_idx += pre_len;
pre_addr = NextPageNum * FLASH_PAGE_SIZE;
while (buff_idx < len) {
if ((len - buff_idx) >= FLASH_PAGE_SIZE) {
xc_spi_flash_read_page(reg_idx, pre_addr, temp_buff);
memcpy(&buff[buff_idx], temp_buff, FLASH_PAGE_SIZE);
buff_idx += FLASH_PAGE_SIZE;
pre_addr += FLASH_PAGE_SIZE;
} else {
xc_spi_flash_read_page(reg_idx, pre_addr, temp_buff);
memcpy(&buff[buff_idx], temp_buff, len - buff_idx);
buff_idx += (len - buff_idx);
pre_addr += (len - buff_idx);
}
}
}
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};
uint16_t i = 0;
while (spi_sts__ssi_tfe__getf(reg_idx) == RESET) {
i++;
if (i >= SPI_WAIT_TIMEOUT) {
//h
// 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;
}
/**
****************************************************************************************
* @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);
}