diff --git a/.travis.yml b/.travis.yml index fbcb1241f3..f42b07b7c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,6 +28,7 @@ env: - RTT_BSP='asm9260t' RTT_TOOL_CHAIN='sourcery-arm' - RTT_BSP='at91sam9260' RTT_TOOL_CHAIN='sourcery-arm' - RTT_BSP='allwinner_tina' RTT_TOOL_CHAIN='sourcery-arm' + - RTT_BSP='imxrt1052-evk' RTT_TOOL_CHAIN='sourcery-arm' # - RTT_BSP='avr32uc3b0' RTT_TOOL_CHAIN='atmel-avr32' # - RTT_BSP='bf533' # no scons - RTT_BSP='efm32' RTT_TOOL_CHAIN='sourcery-arm' diff --git a/README.md b/README.md index 01a828711a..279ce96c23 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # RT-Thread # +[中文页](README_zh.md) | + [![Build Status](https://travis-ci.org/RT-Thread/rt-thread.svg)](https://travis-ci.org/RT-Thread/rt-thread) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/RT-Thread/rt-thread?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) diff --git a/bsp/CME_M7/rtconfig.py b/bsp/CME_M7/rtconfig.py index ebaa7dc334..134ef61559 100644 --- a/bsp/CME_M7/rtconfig.py +++ b/bsp/CME_M7/rtconfig.py @@ -16,7 +16,7 @@ elif CROSS_TOOL == 'keil': EXEC_PATH = 'C:/Keil' elif CROSS_TOOL == 'iar': PLATFORM = 'iar' - IAR_PATH = 'C:/Program Files/IAR Systems/Embedded Workbench 6.0 Evaluation' + EXEC_PATH = 'C:/Program Files/IAR Systems/Embedded Workbench 6.0 Evaluation' if os.getenv('RTT_EXEC_PATH'): EXEC_PATH = os.getenv('RTT_EXEC_PATH') @@ -106,7 +106,7 @@ elif PLATFORM == 'iar': CFLAGS += ' --cpu=Cortex-M3' CFLAGS += ' -e' CFLAGS += ' --fpu=None' - CFLAGS += ' --dlib_config "' + IAR_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' CFLAGS += ' -Ol' AFLAGS = '' @@ -120,5 +120,5 @@ elif PLATFORM == 'iar': LFLAGS += ' --semihosting' LFLAGS += ' --entry __iar_program_start' - EXEC_PATH = IAR_PATH + '/arm/bin/' + EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = '' diff --git a/bsp/allwinner_tina/drivers/Kconfig b/bsp/allwinner_tina/drivers/Kconfig index b7efb5de20..e5ce892e29 100644 --- a/bsp/allwinner_tina/drivers/Kconfig +++ b/bsp/allwinner_tina/drivers/Kconfig @@ -14,3 +14,24 @@ config TINA_USING_UART2 bool "Using UART2" select RT_USING_SERIAL default y + +config TINA_USING_SDIO0 + bool "Using SDIO0" + select RT_USING_SDIO + default y + +config TINA_USING_SPI0 + bool "Using spi0" + select RT_USING_SPI + default y + +config TINA_USING_SPI1 + bool "Using spi1" + select RT_USING_SPI + default y + +config TINA_USING_SPI_FLASH + bool "Using flash" + select TINA_USING_SPI0 + select RT_USING_SFUD + default y diff --git a/bsp/allwinner_tina/drivers/drv_clock.c b/bsp/allwinner_tina/drivers/drv_clock.c index ad0d829683..b55cd6af4c 100644 --- a/bsp/allwinner_tina/drivers/drv_clock.c +++ b/bsp/allwinner_tina/drivers/drv_clock.c @@ -525,3 +525,89 @@ rt_err_t bus_software_reset_enalbe(enum bus_gate bus) return RT_EOK; } +rt_err_t mmc_set_clk(enum mmc_clk_id clk_id, int hz) +{ + unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly; + volatile rt_uint32_t *mmc_clk = (clk_id == SDMMC0) ? \ + (&CCU->sdmmc0_clk) : (&CCU->sdmmc1_clk); + + if (hz < 0) + { + return RT_EINVAL; + } + + if (hz == 0) + { + *mmc_clk &= ~(0x1 << 31); + return RT_EOK; + } + + if (hz <= 24000000) + { + pll = (0x0 << 24); + pll_hz = 24000000; + } + else + { + pll = (0x1 << 24); + pll_hz = periph_get_pll_clk(); + } + + div = pll_hz / hz; + if (pll_hz % hz) + { + div++; + } + + n = 0; + while (div > 16) + { + n++; + div = (div + 1) / 2; + } + + if (n > 3) + { + return -1; + } + + /* determine delays */ + if (hz <= 400000) + { + oclk_dly = 0; + sclk_dly = 0; + } + else if (hz <= 25000000) + { + oclk_dly = 0; + sclk_dly = 5; + } + else if (hz <= 50000000) + { + oclk_dly = 3; + sclk_dly = 4; + } + else + { + /* hz > 50000000 */ + oclk_dly = 1; + sclk_dly = 4; + } + + *mmc_clk = (0x1 << 31) | pll | (sclk_dly << 20) | \ + (n << 16) | (oclk_dly << 8) | (div - 1); + + return RT_EOK; +} + +rt_err_t dram_gate_clk_enable(enum dram_gate dram_gate) +{ + CCU->dram_gating |= (0x01 << dram_gate); + return RT_EOK; +} + +rt_err_t dram_gate_clk_disable(enum dram_gate dram_gate) +{ + CCU->dram_gating &= ~(0x01 << dram_gate); + return RT_EOK; +} diff --git a/bsp/allwinner_tina/drivers/drv_clock.h b/bsp/allwinner_tina/drivers/drv_clock.h index 7b71d77fa0..c1cb87af0a 100644 --- a/bsp/allwinner_tina/drivers/drv_clock.h +++ b/bsp/allwinner_tina/drivers/drv_clock.h @@ -34,13 +34,6 @@ #define CLK_PLL_SRC (0x02) #define PRE_DIV_SRC (0x03) -/* */ -#define BE_GATING_DRAM (0x1<<26) -#define FE_GATING_DRAM (0x1<<24) -#define TVD_GATING_DRAM (0x1<<3) -#define DEINTERLACE_GATING_DRAM (0x1<<2) -#define CSI_GATING_DRAM (0x1<<1) -#define VE_GATING_DRAM (0x1<<0) /* */ #define TCON_PLL_VIDEO_X1 (0x000) @@ -142,6 +135,21 @@ enum bus_gate AUDIO_CODEC_GATING = (0x00 | (0x2 << BUS_GATE_OFFSET_BIT)), }; +enum dram_gate +{ + BE_GATING_DRAM = 26, + FE_GATING_DRAM = 24, + TVD_GATING_DRAM = 3, + DEINTERLACE_GATING_DRAM = 2, + CSI_GATING_DRAM = 1, + VE_GATING_DRAM = 0 +}; +enum mmc_clk_id +{ + SDMMC0, + SDMMC1, +}; + struct tina_ccu { volatile rt_uint32_t pll_cpu_ctrl; /* 0x000 */ @@ -240,4 +248,8 @@ rt_err_t bus_gate_clk_disalbe(enum bus_gate bus); rt_err_t bus_software_reset_enalbe(enum bus_gate bus); rt_err_t bus_software_reset_disalbe(enum bus_gate bus); +rt_err_t dram_gate_clk_enable(enum dram_gate dram_gate); +rt_err_t dram_gate_clk_disable(enum dram_gate dram_gate); + +rt_err_t mmc_set_clk(enum mmc_clk_id clk_id, int hz); #endif \ No newline at end of file diff --git a/bsp/allwinner_tina/drivers/drv_sdio.c b/bsp/allwinner_tina/drivers/drv_sdio.c new file mode 100644 index 0000000000..72b43c0e22 --- /dev/null +++ b/bsp/allwinner_tina/drivers/drv_sdio.c @@ -0,0 +1,795 @@ +/* + * File : drv_sdio.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-02-08 RT-Thread the first version + */ +#include +#include +#include +#include + +#include "drv_sdio.h" +#include "interrupt.h" +#include "mmu.h" +#include "drv_gpio.h" +#include "drv_clock.h" + +#define DBG_ENABLE +#define DBG_SECTION_NAME "[MMC]" +// #define DBG_LEVEL DBG_LOG +// #define DBG_LEVEL DBG_INFO +#define DBG_LEVEL DBG_WARNING +// #define DBG_LEVEL DBG_ERROR +#define DBG_COLOR +#include + +#ifdef RT_USING_SDIO +#define CONFIG_MMC_USE_DMA +#define DMA_ALIGN (32U) + +struct mmc_xfe_des +{ + rt_uint32_t size; /* block size */ + rt_uint32_t num; /* block num */ + rt_uint8_t *buff; /* buff addr */ + rt_uint32_t flag; /* write or read or stream */ +#define MMC_DATA_WRITE (1 << 0) +#define MMC_DATA_READ (1 << 1) +#define MMC_DATA_STREAM (1 << 2) +}; + +struct mmc_flag +{ + volatile rt_uint32_t risr; + volatile rt_uint32_t idst; +}; + +struct sdio_drv +{ + struct rt_mmcsd_host *host; + struct rt_mmcsd_req *req; + struct rt_semaphore rt_sem; + struct mmc_xfe_des xfe; + struct mmc_flag flag; + tina_mmc_t mmc_des; + rt_uint8_t *mmc_buf; + rt_uint8_t usedma; + +}; + +#ifdef CONFIG_MMC_USE_DMA +#ifdef TINA_USING_SDIO0 +ALIGN(32) static rt_uint8_t dma_buffer[64 * 1024]; +#endif +#endif + +static void mmc_request_end(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req); + +static void mmc_delay_us(int us) +{ + volatile unsigned int temp; + + while (us--) + { + temp = 0x2f; + while (temp--) + { + temp = temp; + }; + } +} + +static void mmc_dump_errinfo(unsigned int err) +{ + dbg_log(DBG_ERROR, "[err]:0x%08x, %s%s%s%s%s%s%s%s%s%s%s\n", + err, + err & SDXC_RespErr ? " RE" : "", + err & SDXC_RespCRCErr ? " RCE" : "", + err & SDXC_DataCRCErr ? " DCE" : "", + err & SDXC_RespTimeout ? " RTO" : "", + err & SDXC_DataTimeout ? " DTO" : "", + err & SDXC_DataStarve ? " DS" : "", + err & SDXC_FIFORunErr ? " FE" : "", + err & SDXC_HardWLocked ? " HL" : "", + err & SDXC_StartBitErr ? " SBE" : "", + err & SDXC_EndBitErr ? " EBE" : "", + err == 0 ? " STO" : "" + ); +} + +static int mmc_update_clk(tina_mmc_t mmc) +{ + rt_uint32_t cmd; + rt_uint32_t timeout = 2000000; + + /* cmd load */ + cmd = SDXC_LOAD_CMD | SDXC_UPDATE_CLOCK_CMD | SDXC_WAIT_OVER_CMD; + mmc->cmdr_reg = cmd; + /* while load success */ + while ((mmc->cmdr_reg & SDXC_LOAD_CMD) && (--timeout)) + { + mmc_delay_us(1); + } + if (!timeout) + { + dbg_log(DBG_ERROR, "mmc update clk failed\n"); + return -RT_ERROR; + } + /* clean interrupt */ + mmc->risr_reg = mmc->risr_reg; + return RT_EOK; +} + +static rt_err_t mmc_trans_data_by_dma(tina_mmc_t mmc, struct mmc_xfe_des *xfe) +{ + ALIGN(32) static struct mmc_des_v4p1 pdes[128]; // mast ALIGN(32) + unsigned i, rval; + unsigned des_idx; + unsigned length = xfe->size * xfe->num; + unsigned buff_frag_num = length >> SDXC_DES_NUM_SHIFT; + unsigned remain = length & (SDXC_DES_BUFFER_MAX_LEN - 1); + + if (remain) + { + buff_frag_num ++; + } + else + { + remain = SDXC_DES_BUFFER_MAX_LEN; + } + memset(pdes, 0, sizeof(pdes)); + mmu_clean_dcache((rt_uint32_t)(xfe->buff), length); + for (i = 0, des_idx = 0; i < buff_frag_num; i++, des_idx++) + { + // memset((void*)&pdes[des_idx], 0, sizeof(struct mmc_v4p1)); + pdes[des_idx].des_chain = 1; + pdes[des_idx].own = 1; + pdes[des_idx].dic = 1; + if ((buff_frag_num > 1) && (i != buff_frag_num - 1)) + { + pdes[des_idx].data_buf1_sz = SDXC_DES_BUFFER_MAX_LEN; + } + else + { + pdes[des_idx].data_buf1_sz = remain; + } + pdes[des_idx].buf_addr_ptr1 = (unsigned long)(xfe->buff) + i * SDXC_DES_BUFFER_MAX_LEN; + if (i == 0) + { + pdes[des_idx].first_des = 1; + } + + if (i == (buff_frag_num - 1)) + { + pdes[des_idx].dic = 0; + pdes[des_idx].last_des = 1; + pdes[des_idx].end_of_ring = 1; + pdes[des_idx].buf_addr_ptr2 = 0; + } + else + { + pdes[des_idx].buf_addr_ptr2 = (unsigned long)&pdes[des_idx+1]; + } + + dbg_log(DBG_LOG, "frag %d, remain %d, des[%d](%08x): " \ + "[0] = %08x, [1] = %08x, [2] = %08x, [3] = %08x\n", \ + i, remain, des_idx, (unsigned int)&pdes[des_idx], + (unsigned int)((unsigned int*)&pdes[des_idx])[0], (unsigned int)((unsigned int*)&pdes[des_idx])[1], + (unsigned int)((unsigned int*)&pdes[des_idx])[2], (unsigned int)((unsigned int*)&pdes[des_idx])[3]); + } + mmu_clean_dcache((rt_uint32_t)pdes, sizeof(struct mmc_des_v4p1) * (des_idx + 1)); + + /* + * GCTRLREG + * GCTRL[2] : DMA reset + * GCTRL[5] : DMA enable + * + * IDMACREG + * IDMAC[0] : IDMA soft reset + * IDMAC[1] : IDMA fix burst flag + * IDMAC[7] : IDMA on + * + * IDIECREG + * IDIE[0] : IDMA transmit interrupt flag + * IDIE[1] : IDMA receive interrupt flag + */ + rval = mmc->gctl_reg; + mmc->gctl_reg = rval | (1 << 5) | (1 << 2); /* dma enable */ + mmc->dmac_reg = (1 << 0); /* idma reset */ + while(mmc->dmac_reg & 0x1) {}; /* wait idma reset done */ + mmc->dmac_reg = (1 << 1) | (1 << 7); /* idma on */ + rval = mmc->idie_reg & (~3); + if (xfe->flag == MMC_DATA_WRITE) + rval |= (1 << 0); + else + rval |= (1 << 1); + mmc->idie_reg = rval; + mmc->dlba_reg = (unsigned long)pdes; + mmc->fwlr_reg = (2U << 28) | (7U << 16) | 8; + + return 0; +} + +static rt_err_t mmc_trans_data_by_cpu(tina_mmc_t mmc, struct mmc_xfe_des *xfe) +{ + unsigned i; + unsigned byte_cnt = xfe->size * xfe->num; + unsigned *buff = (unsigned *)(xfe->buff); + volatile unsigned timeout = 2000000; + + if (xfe->flag == MMC_DATA_WRITE) + { + for (i = 0; i < (byte_cnt >> 2); i++) + { + while(--timeout && (mmc->star_reg & (1 << 3))); + + if (timeout <= 0) + { + dbg_log(DBG_ERROR, "write data by cpu failed status:0x%08x\n", mmc->star_reg); + return -RT_ERROR; + } + mmc->fifo_reg = buff[i]; + timeout = 2000000; + } + } + else + { + for (i = 0; i < (byte_cnt >> 2); i++) + { + while(--timeout && (mmc->star_reg & (1 << 2))); + + if (timeout <= 0) + { + dbg_log(DBG_ERROR, "read data by cpu failed status:0x%08x\n", mmc->star_reg); + return -RT_ERROR; + } + buff[i] = mmc->fifo_reg; + timeout = 2000000; + } + } + + return RT_EOK; +} + +static rt_err_t mmc_config_clock(tina_mmc_t mmc, int clk) +{ + rt_uint32_t rval = 0; + + /* disable card clock */ + rval = mmc->ckcr_reg; + rval &= ~(1 << 16); + mmc->ckcr_reg = rval; + if (mmc_update_clk(mmc) != RT_EOK) + { + dbg_log(DBG_ERROR, "clk update fail line:%d\n", __LINE__); + return -RT_ERROR; + } + + if (mmc == MMC0) + { + mmc_set_clk(SDMMC0, clk); + } + else + { + mmc_set_clk(SDMMC1, clk); + } + + /* Re-enable card clock */ + rval = mmc->ckcr_reg; + rval |= (0x1 << 16); //(3 << 16); + mmc->ckcr_reg = rval; + if(mmc_update_clk(mmc) != RT_EOK) + { + dbg_log(DBG_ERROR, "clk update fail line:%d\n", __LINE__); + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t mmc_set_ios(tina_mmc_t mmc, int clk, int bus_width) +{ + dbg_log(DBG_LOG, "mmc set io bus width:%d clock:%d\n", \ + (bus_width == MMCSD_BUS_WIDTH_8 ? 8 : (bus_width == MMCSD_BUS_WIDTH_4 ? 4 : 1)), clk); + /* change clock */ + if (clk && (mmc_config_clock(mmc, clk) != RT_EOK)) + { + dbg_log(DBG_ERROR, "update clock failed\n"); + return -RT_ERROR; + } + + /* Change bus width */ + if (bus_width == MMCSD_BUS_WIDTH_8) + { + mmc->bwdr_reg = 2; + } + else if (bus_width == MMCSD_BUS_WIDTH_4) + { + mmc->bwdr_reg = 1; + } + else + { + mmc->bwdr_reg = 0; + } + + return RT_EOK; +} + +static int mmc_send_cmd(struct rt_mmcsd_host *host, struct rt_mmcsd_cmd *cmd) +{ + + unsigned int cmdval = 0x80000000; + signed int timeout = 0; + int err = 0; + unsigned int status = 0; + struct rt_mmcsd_data *data = cmd->data; + unsigned int bytecnt = 0; + struct sdio_drv *sdio_des = (struct sdio_drv *)host->private_data; + tina_mmc_t mmc = sdio_des->mmc_des; + + timeout = 5000 * 1000; + status = mmc->star_reg; + while (status & (1 << 9)) + { + dbg_log(DBG_LOG, "note: check card busy\n"); + + status = mmc->star_reg; + if (!timeout--) + { + err = -1; + dbg_log(DBG_ERROR, "mmc cmd12 busy timeout data:0x%08x\n", status); + return err; + } + mmc_delay_us(1); + } + /* + * CMDREG + * CMD[5:0] : Command index + * CMD[6] : Has response + * CMD[7] : Long response + * CMD[8] : Check response CRC + * CMD[9] : Has data + * CMD[10] : Write + * CMD[11] : Steam mode + * CMD[12] : Auto stop + * CMD[13] : Wait previous over + * CMD[14] : About cmd + * CMD[15] : Send initialization + * CMD[21] : Update clock + * CMD[31] : Load cmd + */ + if (!cmd->cmd_code) + cmdval |= (1 << 15); + if (resp_type(cmd) != RESP_NONE) + cmdval |= (1 << 6); + if (resp_type(cmd) == RESP_R2) + cmdval |= (1 << 7); + if ((resp_type(cmd) != RESP_R3) && (resp_type(cmd) != RESP_R4)) + cmdval |= (1 << 8); + + if (data) + { + cmdval |= (1 << 9) | (1 << 13); + if (data->flags & DATA_DIR_WRITE) + cmdval |= (1 << 10); + if (data->blks > 1) + cmdval |= (1 << 12); + mmc->bksr_reg = data->blksize; + bytecnt = data->blksize * data->blks; + mmc->bycr_reg = bytecnt; + } + + dbg_log(DBG_LOG, "cmd %d(0x%08x), arg 0x%08x\n", cmd->cmd_code, cmdval | cmd->cmd_code, cmd->arg); + mmc->cagr_reg = cmd->arg; + if (!data) + { + mmc->cmdr_reg = cmdval | cmd->cmd_code; + mmc->imkr_reg |= 0x1 << 2; + } + + /* + * transfer data and check status + * STATREG[2] : FIFO empty + * STATREG[3] : FIFO full + */ + if (data) + { + dbg_log(DBG_LOG, "mmc trans data %d bytes addr:0x%08x\n", bytecnt, data); +#ifdef CONFIG_MMC_USE_DMA + if (bytecnt > 64) + { +#else + if (0) + { +#endif + sdio_des->usedma = 1; + mmc->gctl_reg = mmc->gctl_reg & (~0x80000000); + mmc_trans_data_by_dma(mmc, &sdio_des->xfe); + mmc->cmdr_reg = cmdval | cmd->cmd_code; + } + else + { + sdio_des->usedma = 0; + mmc->gctl_reg = mmc->gctl_reg | 0x80000000; + mmc->cmdr_reg = cmdval | cmd->cmd_code; + mmc_trans_data_by_cpu(mmc, &sdio_des->xfe); + } + + if (data->blks > 1) + { + mmc->imkr_reg |= (0x1 << 14); + } + else + { + mmc->imkr_reg |= (0x1 << 3); + } + } + + mmc->imkr_reg |= 0xbfc2; + + if (data) + { + //TODO:2 * bytecnt * 4? + timeout = sdio_des->usedma ? (2 * bytecnt * 4) : 100; //0.04us(25M)*2(4bit width)*25() + if (timeout < 10) + { + timeout = 10; + } + } + else + { + timeout = 200; + } + + if (rt_sem_take(&sdio_des->rt_sem, timeout) != RT_EOK) + { + err = (mmc->risr_reg | sdio_des->flag.risr) & 0xbfc2; + goto out; + } + + err = (mmc->risr_reg | sdio_des->flag.risr) & 0xbfc2; + if (err) + { + cmd->err = -RT_ETIMEOUT; + goto out; + } + + if (resp_type(cmd) == RESP_R2) + { + cmd->resp[3] = mmc->resp0_reg; + cmd->resp[2] = mmc->resp1_reg; + cmd->resp[1] = mmc->resp2_reg; + cmd->resp[0] = mmc->resp3_reg; + dbg_log(DBG_LOG, "mmc resp 0x%08x 0x%08x 0x%08x 0x%08x\n", + cmd->resp[0], cmd->resp[1], cmd->resp[2], cmd->resp[3]); + } + else + { + cmd->resp[0] = mmc->resp0_reg; + dbg_log(DBG_LOG, "mmc resp 0x%08x\n", cmd->resp[0]); + } + +out: + if (err) + { + mmc_dump_errinfo(err & 0xbfc2); + } + if (data && sdio_des->usedma) + { + /* IDMASTAREG + * IDST[0] : idma tx int + * IDST[1] : idma rx int + * IDST[2] : idma fatal bus error + * IDST[4] : idma descriptor invalid + * IDST[5] : idma error summary + * IDST[8] : idma normal interrupt sumary + * IDST[9] : idma abnormal interrupt sumary + */ + status = mmc->idst_reg; + mmc->idst_reg = status; + mmc->idie_reg = 0; + mmc->dmac_reg = 0; + mmc->gctl_reg = mmc->gctl_reg & (~(1 << 5)); + } + if (err) + { + if (data && (data->flags & DATA_DIR_READ) && (bytecnt == 512)) + { + mmc->gctl_reg = mmc->gctl_reg | 0x80000000; + mmc->dbgc_reg = 0xdeb; + timeout = 1000; + dbg_log(DBG_LOG, "Read remain data\n"); + while (mmc->bbcr_reg < 512) + { + unsigned int tmp = mmc->fifo_reg; + tmp = tmp; + dbg_log(DBG_LOG, "Read data 0x%08x, bbcr 0x%04x\n", tmp, mmc->bbcr_reg); + mmc_delay_us(1); + if (!(timeout--)) + { + dbg_log(DBG_ERROR, "Read remain data timeout\n"); + break; + } + } + } + + mmc->gctl_reg = 0x7; + while (mmc->gctl_reg & 0x7) { }; + + mmc_update_clk(mmc); + cmd->err = -RT_ETIMEOUT; + dbg_log(DBG_ERROR, "mmc cmd %d err\n", cmd->cmd_code); + } + + mmc->gctl_reg &= ~(0x1 << 4); + mmc->imkr_reg &= ~0xffff; + mmc->risr_reg = 0xffffffff; + mmc->gctl_reg |= 0x1 << 4; + while (!rt_sem_take(&sdio_des->rt_sem, 0)) {} + mmc_request_end(sdio_des->host, sdio_des->req); + + return err; +} + +static void mmc_request_end(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + struct rt_mmcsd_data *data; + unsigned byte_cnt; + struct sdio_drv *sdio = (struct sdio_drv *)host->private_data; + +#ifdef CONFIG_MMC_USE_DMA + data = req->cmd->data; + if (data) + { + byte_cnt = data->blksize * data->blks; + if ((byte_cnt > 64) && (data->flags & DATA_DIR_READ)) + { + mmu_invalidate_dcache((rt_uint32_t)sdio->xfe.buff, (rt_uint32_t)byte_cnt); + + if (((rt_uint32_t)data->buf) & (DMA_ALIGN - 1)) + { + memcpy(data->buf, sdio->xfe.buff, byte_cnt); + } + } + } +#endif + mmcsd_req_complete(host); +} + +static void sdio_request_send(struct rt_mmcsd_host *host, struct rt_mmcsd_req *req) +{ + struct rt_mmcsd_data *data; + int byte_cnt; + struct sdio_drv *sdio; + + sdio = (struct sdio_drv *)host->private_data; + sdio->req = req; + data = req->cmd->data; + + if (data) + { + sdio->xfe.size = data->blksize; + sdio->xfe.num = data->blks; + sdio->xfe.buff = (rt_uint8_t *)data->buf; + sdio->xfe.flag = (data->flags & DATA_DIR_WRITE) ? \ + MMC_DATA_WRITE : MMC_DATA_READ; +#ifdef CONFIG_MMC_USE_DMA + byte_cnt = data->blksize * data->blks; + if ((byte_cnt > 64) && (((rt_uint32_t)data->buf) & (DMA_ALIGN - 1))) + { + sdio->xfe.buff = (rt_uint8_t *)sdio->mmc_buf; + if (data->flags & DATA_DIR_WRITE) + { + memcpy(sdio->mmc_buf, data->buf, byte_cnt); + mmu_clean_dcache((rt_uint32_t)sdio->mmc_buf, (rt_uint32_t)byte_cnt); + } + } +#endif + } + + memset(&sdio->flag, 0, sizeof(struct mmc_flag)); + mmc_send_cmd(host, req->cmd); + + return; +} + +static void sdio_set_iocfg(struct rt_mmcsd_host *host, struct rt_mmcsd_io_cfg *io_cfg) +{ + int clk = io_cfg->clock; + int width = io_cfg->bus_width; + struct sdio_drv *sdio_des = (struct sdio_drv *)host->private_data; + tina_mmc_t mmc = sdio_des->mmc_des; + + mmc_set_ios(mmc, clk, width); +} + +static const struct rt_mmcsd_host_ops ops = +{ + sdio_request_send, + sdio_set_iocfg, + RT_NULL, + RT_NULL, +}; + +static void sdio_interrupt_handle(int irqno, void *param) +{ + rt_uint32_t risr, idst; + rt_uint32_t status; + struct sdio_drv *sdio_des = (struct sdio_drv *)param; + struct rt_mmcsd_data *data = sdio_des->req->cmd->data; + tina_mmc_t mmc = sdio_des->mmc_des; + + risr = mmc->risr_reg; + idst = mmc->idst_reg; + + mmc->risr_reg = risr & mmc->imkr_reg; + mmc->idst_reg = idst & mmc->idie_reg; + + sdio_des->flag.risr |= risr; + sdio_des->flag.idst |= idst; + + if (data) + { + int done = 0; + + status = sdio_des->flag.risr | mmc->risr_reg; + if (data->blks > 1)//not wait auto stop when MMC_CMD_MANUAL is set + { + if (sdio_des->usedma) + done = ((status & (1 << 14)) && (sdio_des->flag.idst & 0x3)) ? 1 : 0; + else + done = status & (1 << 14); + } + else + { + if (sdio_des->usedma) + done = ((status & (1 << 3)) && (sdio_des->flag.idst & 0x3)) ? 1 : 0; + else + done = status & (1 << 3); + } + + if (done) + { + rt_sem_release(&sdio_des->rt_sem); + } + } + else + { + rt_sem_release(&sdio_des->rt_sem); + } +} + +static void sdio_gpio_init(struct sdio_drv *sdio_des) +{ + int pin; + + if ((rt_uint32_t)sdio_des->mmc_des == MMC0_BASE_ADDR) + { + /* SDC0: PF0-PF5 */ + for (pin = GPIO_PIN_0; pin <= GPIO_PIN_5; pin++) + { + gpio_set_func(GPIO_PORT_F, pin, IO_FUN_1); + gpio_set_pull_mode(GPIO_PORT_F, pin, PULL_UP); + gpio_set_drive_level(GPIO_PORT_F, pin, DRV_LEVEL_2); + } + } + else if ((rt_uint32_t)sdio_des->mmc_des == MMC1_BASE_ADDR) + { + //todo: config gpio port + RT_ASSERT(0); + } + +} + +static void sdio_clk_io_on(struct sdio_drv *sdio_des) +{ + if ((rt_uint32_t)sdio_des->mmc_des == MMC0_BASE_ADDR) + { + CCU->bus_clk_gating0 |= 0x1 << 8; + CCU->bus_soft_rst0 |= 0x1 << 8; + } + else if ((rt_uint32_t)sdio_des->mmc_des == MMC1_BASE_ADDR) + { + CCU->bus_clk_gating0 |= 0x1 << 9; + CCU->bus_soft_rst0 |= 0x1 << 9; + } + + mmc_set_clk(SDMMC0, 24000000); +} + +static void sdio_irq_init(void *param) +{ + struct sdio_drv *sdio_des = (struct sdio_drv *)param; + + if ((rt_uint32_t)sdio_des->mmc_des == MMC0_BASE_ADDR) + { + rt_hw_interrupt_install(SDC0_INTERRUPT, sdio_interrupt_handle, param, "mmc0_irq"); + rt_hw_interrupt_umask(SDC0_INTERRUPT); + } + else if ((rt_uint32_t)sdio_des->mmc_des == MMC1_BASE_ADDR) + { + rt_hw_interrupt_install(SDC1_INTERRUPT, sdio_interrupt_handle, param, "mmc1_irq"); + rt_hw_interrupt_umask(SDC1_INTERRUPT); + } + + sdio_des->mmc_des->gctl_reg |= (0x1 << 4); +} + +int tina_sdio_init(void) +{ + struct rt_mmcsd_host *host; + +#ifdef TINA_USING_SDIO0 + { + static struct sdio_drv _sdio_drv; + + host = mmcsd_alloc_host(); + if (!host) + { + dbg_log(DBG_ERROR, "alloc host failed\n"); + goto err; + } + + if (rt_sem_init(&_sdio_drv.rt_sem, "sdio_sem", RT_NULL, RT_IPC_FLAG_FIFO)) + { + dbg_log(DBG_ERROR, "sem init failed\n"); + goto err; + } + _sdio_drv.mmc_des = (tina_mmc_t)MMC0_BASE_ADDR; + _sdio_drv.mmc_buf = dma_buffer; + //init gpio pin + sdio_gpio_init(&_sdio_drv); + //clk is on + sdio_clk_io_on(&_sdio_drv); + //irq init + sdio_irq_init(&_sdio_drv); + + host->ops = &ops; + host->freq_min = 400 * 1000; + host->freq_max = 50 * 1000 * 1000; + host->valid_ocr = VDD_26_27 | VDD_27_28 | VDD_28_29 | VDD_29_30 | VDD_30_31 | VDD_31_32 | + VDD_32_33 | VDD_33_34 | VDD_34_35 | VDD_35_36; + host->flags = MMCSD_BUSWIDTH_4 | MMCSD_MUTBLKWRITE | MMCSD_SUP_SDIO_IRQ | MMCSD_SUP_HIGHSPEED; + host->max_seg_size = 2048; + host->max_dma_segs = 10; + host->max_blk_size = 512; + host->max_blk_count = 4096; + + host->private_data = &_sdio_drv; + + _sdio_drv.host = host; + + mmcsd_change(host); + } +#endif + + return RT_EOK; + +err: + if (host) + { + rt_free(host); + } + + return RT_ERROR; +} +INIT_APP_EXPORT(tina_sdio_init); +#endif diff --git a/bsp/allwinner_tina/drivers/drv_sdio.h b/bsp/allwinner_tina/drivers/drv_sdio.h new file mode 100644 index 0000000000..742d5362e1 --- /dev/null +++ b/bsp/allwinner_tina/drivers/drv_sdio.h @@ -0,0 +1,180 @@ +/* + * File : drv_sdio.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-02-08 RT-Thread the first version + */ +#ifndef __DRV_SDIO_H__ +#define __DRV_SDIO_H__ + + +#define MMC0_BASE_ADDR 0x01C0F000 +#define MMC1_BASE_ADDR 0x01C10000 + +struct tina_mmc +{ + volatile rt_uint32_t gctl_reg; /* (0x000) */ + volatile rt_uint32_t ckcr_reg; /* (0x004) */ + volatile rt_uint32_t tmor_reg; /* (0x008) */ + volatile rt_uint32_t bwdr_reg; /* (0x00C) */ + volatile rt_uint32_t bksr_reg; /* (0x010) */ + volatile rt_uint32_t bycr_reg; /* (0x014) */ + volatile rt_uint32_t cmdr_reg; /* (0x018) */ + volatile rt_uint32_t cagr_reg; /* (0x01C) */ + volatile rt_uint32_t resp0_reg; /* (0x020) */ + volatile rt_uint32_t resp1_reg; /* (0x024) */ + volatile rt_uint32_t resp2_reg; /* (0x028) */ + volatile rt_uint32_t resp3_reg; /* (0x02C) */ + volatile rt_uint32_t imkr_reg; /* (0x030) */ + volatile rt_uint32_t misr_reg; /* (0x034) */ + volatile rt_uint32_t risr_reg; /* (0x038) */ + volatile rt_uint32_t star_reg; /* (0x03C) */ + volatile rt_uint32_t fwlr_reg; /* (0x040) */ + volatile rt_uint32_t funs_reg; /* (0x044) */ + volatile rt_uint32_t cbcr_reg; /* (0x048) */ + volatile rt_uint32_t bbcr_reg; /* (0x04C) */ + volatile rt_uint32_t dbgc_reg; /* (0x050) */ + volatile rt_uint32_t reserved0; + volatile rt_uint32_t a12a_reg; /* (0x058) */ + volatile rt_uint32_t reserved1[7]; + volatile rt_uint32_t hwrst_reg; /* (0x078) */ + volatile rt_uint32_t reserved2; + volatile rt_uint32_t dmac_reg; /* (0x080) */ + volatile rt_uint32_t dlba_reg; /* (0x084) */ + volatile rt_uint32_t idst_reg; /* (0x088) */ + volatile rt_uint32_t idie_reg; /* (0x08C) */ + volatile rt_uint32_t chda_reg; /* (0x090) */ + volatile rt_uint32_t cbda_reg; /* (0x094) */ + volatile rt_uint32_t reserved3[26]; + volatile rt_uint32_t card_thldc_reg; /* (0x100) */ + volatile rt_uint32_t reserved4[2]; + volatile rt_uint32_t emmc_dsbd_reg; /* (0x10c) */ + volatile rt_uint32_t reserved5[12]; + volatile rt_uint32_t reserved6[48]; + volatile rt_uint32_t fifo_reg; /* (0x200) */ +}; + +typedef struct tina_mmc *tina_mmc_t; + +#define MMC0 ((tina_mmc_t)MMC0_BASE_ADDR) +#define MMC1 ((tina_mmc_t)MMC1_BASE_ADDR) + + +#define BIT(x) (1<<(x)) +/* Struct for Intrrrupt Information */ +#define SDXC_RespErr BIT(1) //0x2 +#define SDXC_CmdDone BIT(2) //0x4 +#define SDXC_DataOver BIT(3) //0x8 +#define SDXC_TxDataReq BIT(4) //0x10 +#define SDXC_RxDataReq BIT(5) //0x20 +#define SDXC_RespCRCErr BIT(6) //0x40 +#define SDXC_DataCRCErr BIT(7) //0x80 +#define SDXC_RespTimeout BIT(8) //0x100 +#define SDXC_ACKRcv BIT(8) //0x100 +#define SDXC_DataTimeout BIT(9) //0x200 +#define SDXC_BootStart BIT(9) //0x200 +#define SDXC_DataStarve BIT(10) //0x400 +#define SDXC_VolChgDone BIT(10) //0x400 +#define SDXC_FIFORunErr BIT(11) //0x800 +#define SDXC_HardWLocked BIT(12) //0x1000 +#define SDXC_StartBitErr BIT(13) //0x2000 +#define SDXC_AutoCMDDone BIT(14) //0x4000 +#define SDXC_EndBitErr BIT(15) //0x8000 +#define SDXC_SDIOInt BIT(16) //0x10000 +#define SDXC_CardInsert BIT(30) //0x40000000 +#define SDXC_CardRemove BIT(31) //0x80000000 +#define SDXC_IntErrBit (SDXC_RespErr | SDXC_RespCRCErr | SDXC_DataCRCErr \ + | SDXC_RespTimeout | SDXC_DataTimeout | SDXC_FIFORunErr \ + | SDXC_HardWLocked | SDXC_StartBitErr | SDXC_EndBitErr) //0xbfc2 + +/* + SD CMD reg +REG[0-5] : Cmd ID +REG[6] : Has response +REG[7] : Long response +REG[8] : Check response CRC +REG[9] : Has data +REG[10] : Write +REG[11] : Steam mode +REG[12] : Auto stop +REG[13] : Wait previous over +REG[14] : About cmd +REG[15] : Send initialization +REG[21] : Update clock +REG[31] : Load cmd +*/ +#define SDXC_RESPONSE_CMD BIT(6) +#define SDXC_LONG_RESPONSE_CMD BIT(7) +#define SDXC_CHECK_CRC_CMD BIT(8) +#define SDXC_HAS_DATA_CMD BIT(9) +#define SDXC_WRITE_CMD BIT(10) +#define SDXC_STEAM_CMD BIT(11) +#define SDXC_AUTO_STOP_CMD BIT(12) +#define SDXC_WAIT_OVER_CMD BIT(13) +#define SDXC_ABOUT_CMD BIT(14) +#define SDXC_SEND_INIT_CMD BIT(15) +#define SDXC_UPDATE_CLOCK_CMD BIT(21) +#define SDXC_LOAD_CMD BIT(31) + +/* + SD status reg +REG[0] : FIFO_RX_LEVEL +REG[1] : FIFO_TX_LEVEL +REG[2] : FIFO_EMPTY +REG[3] : FIFO_FULL +REG[4-7] : FSM_STA +REG[8] : CARD_PRESENT +REG[9] : CARD_BUSY +REG[10] : FSM_BUSY +REG[11-16]: RESP_IDX +REG[17-21]: FIFO_LEVEL +REG[31] : DMA_REQ +*/ + +#define SDXC_FIFO_RX_LEVEL BIT(0) +#define SDXC_FIFO_TX_LEVEL BIT(1) +#define SDXC_FIFO_EMPTY BIT(2) +#define SDXC_FIFO_FULL BIT(3) +#define SDXC_CARD_PRESENT BIT(8) +#define SDXC_CARD_BUSY BIT(9) +#define SDXC_FSM_BUSY BIT(10) +#define SDXC_DMA_REQ BIT(31) + +struct mmc_des_v4p1 +{ + rt_uint32_t : 1, + dic : 1, /* disable interrupt on completion */ + last_des : 1, /* 1-this data buffer is the last buffer */ + first_des : 1, /* 1-data buffer is the first buffer,0-data buffer contained in the next descriptor is 1st buffer */ + des_chain : 1, /* 1-the 2nd address in the descriptor is the next descriptor address */ + end_of_ring : 1, /* 1-last descriptor flag when using dual data buffer in descriptor */ + : 24, + card_err_sum : 1, /* transfer error flag */ + own : 1; /* des owner:1-idma owns it, 0-host owns it */ + +#define SDXC_DES_NUM_SHIFT 12 /* smhc2!! */ +#define SDXC_DES_BUFFER_MAX_LEN (1 << SDXC_DES_NUM_SHIFT) + rt_uint32_t data_buf1_sz : 16, + data_buf2_sz : 16; + rt_uint32_t buf_addr_ptr1; + rt_uint32_t buf_addr_ptr2; +}; + +#endif diff --git a/bsp/allwinner_tina/drivers/spi/SConscript b/bsp/allwinner_tina/drivers/spi/SConscript new file mode 100644 index 0000000000..6995b9ebda --- /dev/null +++ b/bsp/allwinner_tina/drivers/spi/SConscript @@ -0,0 +1,9 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') +CPPPATH = [cwd, str(Dir('#'))] + +group = DefineGroup('spi', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/bsp/allwinner_tina/drivers/spi/drv_spi.c b/bsp/allwinner_tina/drivers/spi/drv_spi.c new file mode 100644 index 0000000000..9f01878ae3 --- /dev/null +++ b/bsp/allwinner_tina/drivers/spi/drv_spi.c @@ -0,0 +1,793 @@ +/* + * File : drv_spi.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017-08-30 tanek first implementation. + */ + +#include +#include +#include +#include + +#include "drv_spi.h" +#include "drv_gpio.h" +#include "drv_clock.h" + +#define SPI_BUS_MAX_CLK (30 * 1000 * 1000) + +#define DBG_ENABLE +#define DBG_SECTION_NAME "[SPI]" +#define DBG_LEVEL DBG_WARNING +#define DBG_COLOR +#include + +#ifdef RT_USING_SPI + +//#define DEBUG + +#define ARR_LEN(__N) (sizeof(__N) / sizeof(__N[0])) + +#ifdef DEBUG +#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +#define __SPI_STATIC_INLINE__ rt_inline + +/* + * @brief Hardware Layer Interface + */ +__SPI_STATIC_INLINE__ +rt_uint32_t SPI_GetVersion(SPI_T *spi) +{ + return spi->VER; +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_Reset(SPI_T *spi) +{ + HAL_SET_BIT(spi->CTRL, SPI_CTRL_RST_MASK); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetMode(SPI_T *spi, SPI_CTRL_Mode mode) +{ + HAL_MODIFY_REG(spi->CTRL, SPI_CTRL_MODE_MASK, mode); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_Enable(SPI_T *spi) +{ + HAL_SET_BIT(spi->CTRL, SPI_CTRL_EN_MASK); +} + +__SPI_STATIC_INLINE__ +void SPI_Disable(SPI_T *spi) +{ + HAL_CLR_BIT(spi->CTRL, SPI_CTRL_EN_MASK); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_StartTransmit(SPI_T *spi) +{ + HAL_SET_BIT(spi->TCTRL, SPI_TCTRL_XCH_MASK); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetFirstTransmitBit(SPI_T *spi, SPI_TCTRL_Fbs bit) +{ + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_FBS_MASK, bit); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_EnableRapidsMode(SPI_T *spi, bool delay_sample) +{ + HAL_SET_BIT(spi->TCTRL, SPI_TCTRL_RPSM_MASK); + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SDC_MASK, delay_sample << SPI_TCTRL_SDC_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_DisableRapidsMode(SPI_T *spi) +{ + HAL_CLR_BIT(spi->TCTRL, SPI_TCTRL_RPSM_MASK); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetDuplex(SPI_T *spi, SPI_TCTRL_DHB_Duplex duplex) +{ + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_DHB_MASK, duplex); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetCsLevel(SPI_T *spi, bool level) +{ + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_LEVEL_MASK, level << SPI_TCTRL_SS_LEVEL_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_ManualChipSelect(SPI_T *spi, SPI_TCTRL_SS_Sel cs) +{ + HAL_SET_BIT(spi->TCTRL, SPI_TCTRL_SS_OWNER_MASK); + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_SEL_MASK, cs); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_AutoChipSelect(SPI_T *spi, SPI_TCTRL_SS_Sel cs, bool cs_remain) +{ + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_SEL_MASK, cs); + HAL_CLR_BIT(spi->TCTRL, SPI_TCTRL_SS_OWNER_MASK); + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SS_CTL_MASK, (!cs_remain) << SPI_TCTRL_SS_CTL_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetCsIdle(SPI_T *spi, bool idle) +{ + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_SPOL_MASK, (!!idle) << SPI_TCTRL_SPOL_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetSclkMode(SPI_T *spi, SPI_SCLK_Mode mode) +{ + HAL_MODIFY_REG(spi->TCTRL, SPI_TCTRL_CPOL_MASK | SPI_TCTRL_CPHA_MASK, mode); +} + +typedef enum +{ + SPI_INT_CS_DESELECT = SPI_IER_SS_INT_EN_MASK, + SPI_INT_TRANSFER_COMPLETE = SPI_IER_TC_INT_EN_MASK, + SPI_INT_TXFIFO_UNDER_RUN = SPI_IER_TF_UDR_INT_EN_MASK, + SPI_INT_TXFIFO_OVERFLOW = SPI_IER_TF_OVF_INT_EN_MASK, + SPI_INT_RXFIFO_UNDER_RUN = SPI_IER_RF_UDR_INT_EN_MASK, + SPI_INT_RXFIFO_OVERFLOW = SPI_IER_RF_OVF_INT_EN_MASK, + SPI_INT_TXFIFO_FULL = SPI_IER_TF_FUL_INT_EN_MASK, + SPI_INT_TXFIFO_EMPTY = SPI_IER_TX_EMP_INT_EN_MASK, + SPI_INT_TXFIFO_READY = SPI_IER_TX_ERQ_INT_EN_MASK, + SPI_INT_RXFIFO_FULL = SPI_IER_RF_FUL_INT_EN_MASK, + SPI_INT_RXFIFO_EMPTY = SPI_IER_RX_EMP_INT_EN_MASK, + SPI_INT_RXFIFO_READY = SPI_IER_RF_RDY_INT_EN_MASK +} SPI_Int_Type; + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_EnableInt(SPI_T *spi, SPI_Int_Type type) +{ + HAL_SET_BIT(spi->IER, type); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_DisableInt(SPI_T *spi, SPI_Int_Type type) +{ + HAL_CLR_BIT(spi->IER, type); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +bool SPI_IntState(SPI_T *spi, SPI_Int_Type type) +{ + return !!HAL_GET_BIT(spi->STA, type); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +bool SPI_ClearInt(SPI_T *spi, SPI_Int_Type type) +{ + HAL_SET_BIT(spi->STA, type); + return HAL_GET_BIT(spi->STA, type); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_DebugReadTx(SPI_T *spi, rt_uint32_t *data) +{ + // tbc... +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_DebugWriteRx(SPI_T *spi, rt_uint32_t *data) +{ + // tbc... +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_ResetTxFifo(SPI_T *spi) +{ + HAL_SET_BIT(spi->FCTL, SPI_FCTL_TF_RST_MASK); + while (HAL_GET_BIT(spi->FCTL, SPI_FCTL_TF_RST_MASK) != 0); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_ResetRxFifo(SPI_T *spi) +{ + HAL_SET_BIT(spi->FCTL, SPI_FCTL_RF_RST_MASK); + while (HAL_GET_BIT(spi->FCTL, SPI_FCTL_RF_RST_MASK) != 0); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_DMA(SPI_T *spi, bool txEn, bool rxEn) +{ + HAL_MODIFY_REG(spi->FCTL, + SPI_FCTL_TF_DRQ_EN_MASK | SPI_FCTL_RF_DRQ_EN_MASK, + ((!!txEn) << SPI_FCTL_TF_DRQ_EN_SHIFT) | ((!!rxEn) << SPI_FCTL_RF_DRQ_EN_SHIFT)); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetTxFifoThreshold(SPI_T *spi, uint8_t threshold) +{ + HAL_MODIFY_REG(spi->FCTL, SPI_FCTL_TX_TRIG_LEVEL_MASK, threshold << SPI_FCTL_TX_TRIG_LEVEL_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetRxFifoThreshold(SPI_T *spi, uint8_t threshold) +{ + HAL_MODIFY_REG(spi->FCTL, SPI_FCTL_RX_TRIG_LEVEL_MASK, threshold << SPI_FCTL_RX_TRIG_LEVEL_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +uint8_t SPI_GetTxFifoCounter(SPI_T *spi) +{ + return (uint8_t)((spi->FST & SPI_FST_TF_CNT_MASK) >> SPI_FST_TF_CNT_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +uint8_t SPI_GetRxFifoCounter(SPI_T *spi) +{ + return (uint8_t)((spi->FST & SPI_FST_RF_CNT_MASK) >> SPI_FST_RF_CNT_SHIFT); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_EnableDualMode(SPI_T *spi) +{ + HAL_SET_BIT(spi->BCC, SPI_BCC_DRM_MASK); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_DisableDualMode(SPI_T *spi) +{ + HAL_CLR_BIT(spi->BCC, SPI_BCC_DRM_MASK); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetInterval(SPI_T *spi, uint16_t nSCLK) +{ + HAL_MODIFY_REG(spi->WAIT, SPI_WAIT_WCC_MASK, nSCLK << SPI_WAIT_WCC_SHIFT); +} + +/* + * @brief + */ +static void SPI_SetClkDiv(SPI_T *spi, uint16_t div) +{ + uint8_t n = 0; + if (div < 1) + { + return; + } + + if (div > 2 * (0xFF + 1)) + { + HAL_CLR_BIT(spi->CCTR, SPI_CCTR_DRS_MASK); + do + { + div = (div == 1) ? 0 : ((div + 1) / 2); + n++; + } + while (div); + + HAL_MODIFY_REG(spi->CCTR, SPI_CCTR_CDR1_MASK, (n & 0x0F) << SPI_CCTR_CDR1_SHIFT); + } + else + { + HAL_SET_BIT(spi->CCTR, SPI_CCTR_DRS_MASK); + n = ((div + 1) / 2) - 1; + HAL_MODIFY_REG(spi->CCTR, SPI_CCTR_CDR2_MASK, (n & 0xFF) << SPI_CCTR_CDR2_SHIFT); + } +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_SetDataSize(SPI_T *spi, rt_uint32_t data_size, rt_uint32_t dummy_size) +{ + HAL_MODIFY_REG(spi->BC, SPI_BC_MBC_MASK, data_size + dummy_size); + HAL_MODIFY_REG(spi->TC, SPI_TC_MWTC_MASK, data_size); + HAL_MODIFY_REG(spi->BCC, SPI_BCC_STC_MASK, data_size); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_Write(SPI_T *spi, uint8_t *data) +{ + HAL_REG_8BIT(&spi->TXD) = *data; +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +void SPI_Read(SPI_T *spi, uint8_t *data) +{ + *data = HAL_REG_8BIT(&spi->RXD); +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +uint8_t *SPI_TxAddress(SPI_T *spi) +{ + return (uint8_t *)&spi->TXD; +} + +/* + * @brief + */ +__SPI_STATIC_INLINE__ +uint8_t *SPI_RxAddress(SPI_T *spi) +{ + return (uint8_t *)&spi->RXD; +} + +/* private rt-thread spi ops function */ +static rt_err_t configure(struct rt_spi_device *device, struct rt_spi_configuration *configuration); +static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message); + +static struct rt_spi_ops tina_spi_ops = +{ + configure, + xfer +}; + +static rt_err_t configure(struct rt_spi_device *device, + struct rt_spi_configuration *configuration) +{ + struct rt_spi_bus *spi_bus = (struct rt_spi_bus *)device->bus; + struct tina_spi_cs *tina_spi_cs = device->parent.user_data; + struct tina_spi *_spi_info = (struct tina_spi *)spi_bus->parent.user_data; + SPI_T *spi = _spi_info->spi; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + RT_ASSERT(device != RT_NULL); + RT_ASSERT(configuration != RT_NULL); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + DEBUG_PRINTF("spi address: %08X\n", (rt_uint32_t)spi); + + SPI_Disable(spi); + SPI_Reset(spi); + SPI_ResetRxFifo(spi); + SPI_ResetTxFifo(spi); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + /* data_width */ + if (configuration->data_width != 8) + { + DEBUG_PRINTF("error: data_width is %d\n", configuration->data_width); + return RT_EIO; + } + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + SPI_SetDuplex(spi, SPI_TCTRL_DHB_FULL_DUPLEX); + SPI_SetMode(spi, SPI_CTRL_MODE_MASTER); + + /* MSB or LSB */ + if (configuration->mode & RT_SPI_MSB) + { + SPI_SetFirstTransmitBit(spi, SPI_TCTRL_FBS_MSB); + } + else + { + SPI_SetFirstTransmitBit(spi, SPI_TCTRL_FBS_LSB); + } + + switch (configuration->mode) + { + case RT_SPI_MODE_0: + SPI_SetSclkMode(spi, SPI_SCLK_Mode0); + break; + case RT_SPI_MODE_1: + SPI_SetSclkMode(spi, SPI_SCLK_Mode1); + break; + case RT_SPI_MODE_2: + SPI_SetSclkMode(spi, SPI_SCLK_Mode2); + break; + case RT_SPI_MODE_3: + SPI_SetSclkMode(spi, SPI_SCLK_Mode3); + break; + } + + /* baudrate */ + { + unsigned int spi_clock = 0; + rt_uint32_t max_hz; + rt_uint32_t div; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + max_hz = configuration->max_hz; + + if (max_hz > SPI_BUS_MAX_CLK) + { + max_hz = SPI_BUS_MAX_CLK; + } + spi_clock = ahb_get_clk(); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + div = (spi_clock + max_hz - 1) / max_hz; + + dbg_log(DBG_LOG, "configuration->max_hz: %d\n", configuration->max_hz); + dbg_log(DBG_LOG, "max freq: %d\n", max_hz); + dbg_log(DBG_LOG, "spi_clock: %d\n", spi_clock); + dbg_log(DBG_LOG, "div: %d\n", div); + + SPI_SetClkDiv(spi, div / 2); + } /* baudrate */ + + SPI_ManualChipSelect(spi, tina_spi_cs->cs); + SPI_SetDataSize(spi, 0, 0); + SPI_Enable(spi); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + return RT_EOK; +}; + +static rt_uint32_t xfer(struct rt_spi_device *device, struct rt_spi_message *message) +{ + struct rt_spi_bus *r6_spi_bus = (struct rt_spi_bus *)device->bus; + struct tina_spi *_spi_info = (struct tina_spi *)r6_spi_bus->parent.user_data; + SPI_T *spi = _spi_info->spi; + struct rt_spi_configuration *config = &device->config; + struct tina_spi_cs *tina_spi_cs = device->parent.user_data; + + RT_ASSERT(device != NULL); + RT_ASSERT(message != NULL); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + DEBUG_PRINTF("spi_info: %08X\n", (rt_uint32_t)_spi_info); + DEBUG_PRINTF("spi address: %08X\n", (rt_uint32_t)spi); + + /* take CS */ + if (message->cs_take) + { + SPI_ManualChipSelect(spi, tina_spi_cs->cs); + SPI_SetCsLevel(spi, false); + DEBUG_PRINTF("spi take cs\n"); + } + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + { + if ((config->data_width <= 8) && (message->length > 0)) + { + const rt_uint8_t *send_ptr = message->send_buf; + rt_uint8_t *recv_ptr = message->recv_buf; + rt_uint32_t tx_size = message->length; + rt_uint32_t rx_size = message->length; + + DEBUG_PRINTF("spi poll transfer start: %d\n", tx_size); + + SPI_ResetTxFifo(spi); + SPI_ResetRxFifo(spi); + SPI_SetDataSize(spi, tx_size, 0); + + SPI_StartTransmit(spi); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + while (tx_size > 0 || rx_size > 0) + { + uint8_t tx_data = 0xFF; + uint8_t rx_data = 0xFF; + + while ((SPI_GetTxFifoCounter(spi) < SPI_FIFO_SIZE) && (tx_size > 0)) + { + if (send_ptr != RT_NULL) + { + tx_data = *send_ptr++; + } + SPI_Write(spi, &tx_data); + tx_size--; + } + + while (SPI_GetRxFifoCounter(spi) > 0) + { + rx_size--; + SPI_Read(spi, &rx_data); + + if (recv_ptr != RT_NULL) + { + *recv_ptr++ = rx_data; + } + } + } + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + if ((tx_size != 0) || (rx_size != 0)) + { + DEBUG_PRINTF("spi_tx_rx error with tx count = %d, rx count = %d.\n", tx_size, rx_size); + + return 0; + } + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + while (SPI_IntState(spi, SPI_INT_TRANSFER_COMPLETE) == 0); + SPI_ClearInt(spi, SPI_INT_TRANSFER_COMPLETE); + + DEBUG_PRINTF("spi poll transfer finsh\n"); + } + else if (config->data_width > 8) + { + DEBUG_PRINTF("data width: %d\n", config->data_width); + RT_ASSERT(NULL); + } + } + + /* release CS */ + if (message->cs_release) + { + SPI_SetCsLevel(spi, true); + DEBUG_PRINTF("spi release cs\n"); + } + + return message->length; +}; + +#ifdef TINA_USING_SPI0 +static struct rt_spi_bus spi_bus0; +#endif + +#ifdef TINA_USING_SPI1 +static struct rt_spi_bus spi_bus1; +#endif + +static const struct tina_spi spis[] = +{ +#ifdef TINA_USING_SPI0 + {(SPI_T *)SPI0_BASE_ADDR, SPI0_GATING, &spi_bus0}, +#endif + +#ifdef TINA_USING_SPI1 + {(SPI_T *)SPI1_BASE_ADDR, SPI1_GATING, &spi_bus1}, +#endif +}; + + + +/** \brief init and register r6 spi bus. + * + * \param SPI: R6 SPI, e.g: SPI1,SPI2,SPI3. + * \param spi_bus_name: spi bus name, e.g: "spi1" + * \return + * + */ +rt_err_t tina_spi_bus_register(SPI_T *spi, const char *spi_bus_name) +{ + int i; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + RT_ASSERT(spi_bus_name != RT_NULL); + + for (i = 0; i < ARR_LEN(spis); i++) + { + if (spi == spis[i].spi) + { + bus_software_reset_disalbe(spis[i].spi_gate); + bus_gate_clk_enalbe(spis[i].spi_gate); + + spis[i].spi_bus->parent.user_data = (void *)&spis[i]; + DEBUG_PRINTF("bus addr: %08X\n", (rt_uint32_t)spis[i].spi_bus); + DEBUG_PRINTF("user_data: %08X\n", (rt_uint32_t)spis[i].spi_bus->parent.user_data); + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + rt_spi_bus_register(spis[i].spi_bus, spi_bus_name, &tina_spi_ops); + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + return RT_EOK; + } + } + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + return RT_ERROR; +} + +int rt_hw_spi_init(void) +{ + DEBUG_PRINTF("register spi bus\n"); + +#ifdef TINA_USING_SPI0 + /* register spi bus */ + { + rt_err_t result; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + gpio_set_func(GPIO_PORT_C, GPIO_PIN_0, IO_FUN_1); + gpio_set_func(GPIO_PORT_C, GPIO_PIN_2, IO_FUN_1); + gpio_set_func(GPIO_PORT_C, GPIO_PIN_3, IO_FUN_1); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + + result = tina_spi_bus_register((SPI_T *)SPI0_BASE_ADDR, "spi0"); + if (result != RT_EOK) + { + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + return result; + } + } + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + /* attach cs */ + { + static struct rt_spi_device spi_device; + static struct tina_spi_cs spi_cs; + rt_err_t result; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + spi_cs.cs = SPI_TCTRL_SS_SEL_SS0; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + gpio_set_func(GPIO_PORT_C, GPIO_PIN_1, IO_FUN_1); + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + result = rt_spi_bus_attach_device(&spi_device, "spi00", "spi0", (void *)&spi_cs); + if (result != RT_EOK) + { + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + return result; + } + } + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); +#endif + +#ifdef TINA_USING_SPI1 + /* register spi bus */ + { + rt_err_t result; + + gpio_set_func(GPIO_PORT_A, GPIO_PIN_1, IO_FUN_5); + gpio_set_func(GPIO_PORT_A, GPIO_PIN_2, IO_FUN_5); + gpio_set_func(GPIO_PORT_A, GPIO_PIN_3, IO_FUN_5); + + result = tina_spi_bus_register((SPI_T *)SPI1_BASE_ADDR, "spi1"); + if (result != RT_EOK) + { + DEBUG_PRINTF("register spi bus faild: %d\n", result); + return result; + } + } + + DEBUG_PRINTF("attach cs\n"); + /* attach cs */ + { + static struct rt_spi_device spi_device; + static struct tina_spi_cs spi_cs; + rt_err_t result; + + spi_cs.cs = SPI_TCTRL_SS_SEL_SS0; + gpio_set_func(GPIO_PORT_A, GPIO_PIN_0, IO_FUN_5); + + result = rt_spi_bus_attach_device(&spi_device, "spi10", "spi1", (void *)&spi_cs); + if (result != RT_EOK) + { + DEBUG_PRINTF("attach cs faild: %d\n", result); + return result; + } + } +#endif + + return RT_EOK; +} +INIT_BOARD_EXPORT(rt_hw_spi_init); +#endif diff --git a/bsp/allwinner_tina/drivers/spi/drv_spi.h b/bsp/allwinner_tina/drivers/spi/drv_spi.h new file mode 100644 index 0000000000..e9b9981542 --- /dev/null +++ b/bsp/allwinner_tina/drivers/spi/drv_spi.h @@ -0,0 +1,428 @@ +/* + * File : drv_spi.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-02-08 RT-Thread the first version + */ + +#ifndef __DRV_SPI_H__ +#define __DRV_SPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif +/********************** private ************************************/ + +#define SPI0_BASE_ADDR (0x01C05000) +#define SPI1_BASE_ADDR (0x01C06000) + +/** + * @brief Serial Peripheral Interface + */ +typedef struct +{ + volatile rt_uint32_t VER; /* SPI Version number Register, Address offset: 0x00 */ + volatile rt_uint32_t CTRL; /* SPI Global Control Register, Address offset: 0x04 */ + volatile rt_uint32_t TCTRL; /* SPI Transfer Control Register, Address offset: 0x08 */ + volatile rt_uint32_t RESERVED1[1]; /* Reserved, 0x0C */ + volatile rt_uint32_t IER; /* SPI Interrupt Control Register, Address offset: 0x10 */ + volatile rt_uint32_t STA; /* SPI Interrupt Status Register, Address offset: 0x14 */ + volatile rt_uint32_t FCTL; /* SPI FIFO Control Register, Address offset: 0x18 */ + volatile rt_uint32_t FST; /* SPI FIFO Status Register, Address offset: 0x1C */ + volatile rt_uint32_t WAIT; /* SPI Wait Clock Counter Register, Address offset: 0x20 */ + volatile rt_uint32_t CCTR; /* SPI Clock Rate Control Register, Address offset: 0x24 */ + volatile rt_uint32_t RESERVED2[2]; /* Reserved, 0x28-0x2C */ + volatile rt_uint32_t BC; /* SPI Master mode Burst Control Register, Address offset: 0x30 */ + volatile rt_uint32_t TC; /* SPI Master mode Transmit Counter Register, Address offset: 0x34 */ + volatile rt_uint32_t BCC; /* SPI Burst Control Register, Address offset: 0x38 */ + volatile rt_uint32_t RESERVED3[19]; /* Reserved, 0x3C-0x84 */ + volatile rt_uint32_t NDMA_MODE_CTRL; /* SPI Nomal DMA Mode Control Regist Address offset: 0x88 */ + volatile rt_uint32_t RESERVED4[93]; /* Reserved, 0x8C-0x1FC */ + volatile rt_uint32_t TXD; /* SPI TX Date Register, Address offset: 0x200 */ + volatile rt_uint32_t RESERVED5[63]; /* Reserved, 0x204-0x2FC */ + volatile rt_uint32_t RXD; /* SPI RX Date Register, Address offset: 0x300 */ +} SPI_T; + +/* + * @brief SPI Global Control Register + */ +#define SPI_CTRL_RST_SHIFT (31) +#define SPI_CTRL_RST_MASK (0x1U << SPI_CTRL_RST_SHIFT) + +#define SPI_CTRL_TP_EN_SHIFT (7) +#define SPI_CTRL_TP_EN_MASK (0x1U << SPI_CTRL_TP_EN_SHIFT) + +#define SPI_CTRL_MODE_SHIFT (1) +#define SPI_CTRL_MODE_MASK (0x1U << SPI_CTRL_MODE_SHIFT) +typedef enum +{ + SPI_CTRL_MODE_SLAVE = 0 << SPI_CTRL_MODE_SHIFT, + SPI_CTRL_MODE_MASTER = 1 << SPI_CTRL_MODE_SHIFT +} SPI_CTRL_Mode; + +#define SPI_CTRL_EN_SHIFT (0) +#define SPI_CTRL_EN_MASK (0x1U << SPI_CTRL_EN_SHIFT) +typedef enum +{ + SPI_CTRL_EN_DISABLE = 0 << SPI_CTRL_EN_SHIFT, + SPI_CTRL_EN_ENABLE = 1 << SPI_CTRL_EN_SHIFT +} SPI_CTRL_En; + +/* + * @brief SPI Transfer Control Register + */ +#define SPI_TCTRL_XCH_SHIFT (31) +#define SPI_TCTRL_XCH_MASK (0x1U << SPI_TCTRL_XCH_SHIFT) +typedef enum +{ + SPI_TCTRL_XCH_IDLE = 0 << SPI_TCTRL_XCH_SHIFT, + SPI_TCTRL_XCH_START = 1 << SPI_TCTRL_XCH_SHIFT +} SPI_TCTRL_Xch; + +#define SPI_TCTRL_SDDM_SHIFT (14) +#define SPI_TCTRL_SDDM_MASK (0x0U << SPI_TCTRL_SDDM_SHIFT) +typedef enum +{ + SPI_TCTRL_SDDM_SEND_NODELAY = 0 << SPI_TCTRL_SDDM_SHIFT, + SPI_TCTRL_SDDM_SEND_DELAY = 1 << SPI_TCTRL_SDDM_SHIFT +} SPI_TCTRL_Sddm; + +#define SPI_TCTRL_SDM_SHIFT (13) +#define SPI_TCTRL_SDM_MASK (0x1U << SPI_TCTRL_SDM_SHIFT) +typedef enum +{ + SPI_TCTRL_SDM_SAMPLE_NODELAY = 1 << SPI_TCTRL_SDM_SHIFT, + SPI_TCTRL_SDM_SAMPLE_DELAY = 0 << SPI_TCTRL_SDM_SHIFT +} SPI_TCTRL_Sdm; + +#define SPI_TCTRL_FBS_SHIFT (12) +#define SPI_TCTRL_FBS_MASK (0x1U << SPI_TCTRL_FBS_SHIFT) +typedef enum +{ + SPI_TCTRL_FBS_MSB = 0 << SPI_TCTRL_FBS_SHIFT, + SPI_TCTRL_FBS_LSB = 1 << SPI_TCTRL_FBS_SHIFT +} SPI_TCTRL_Fbs; + +#define SPI_TCTRL_SDC_SHIFT (11) +#define SPI_TCTRL_SDC_MASK (0x1U << SPI_TCTRL_SDC_SHIFT) + +#define SPI_TCTRL_RPSM_SHIFT (10) +#define SPI_TCTRL_RPSM_MASK (0x1U << SPI_TCTRL_RPSM_SHIFT) + +#define SPI_TCTRL_DDB_SHIFT (9) +#define SPI_TCTRL_DDB_MASK (0x1U << SPI_TCTRL_DDB_SHIFT) + +#define SPI_TCTRL_DHB_SHIFT (8) +#define SPI_TCTRL_DHB_MASK (0x1U << SPI_TCTRL_DHB_SHIFT) +typedef enum +{ + SPI_TCTRL_DHB_FULL_DUPLEX = 0 << SPI_TCTRL_DHB_SHIFT, + SPI_TCTRL_DHB_HALF_DUPLEX = 1 << SPI_TCTRL_DHB_SHIFT +} SPI_TCTRL_DHB_Duplex; + +#define SPI_TCTRL_SS_LEVEL_SHIFT (7) +#define SPI_TCTRL_SS_LEVEL_MASK (0x1U << SPI_TCTRL_SS_LEVEL_SHIFT) + +#define SPI_TCTRL_SS_OWNER_SHIFT (6) +#define SPI_TCTRL_SS_OWNER_MASK (0x1U << SPI_TCTRL_SS_OWNER_SHIFT) +typedef enum +{ + SPI_TCTRL_SS_OWNER_CONTROLLER = 0 << SPI_TCTRL_SS_OWNER_SHIFT, + SPI_TCTRL_SS_OWNER_SOFTWARE = 1 << SPI_TCTRL_SS_OWNER_SHIFT +} SPI_TCTRL_SS_OWNER; + +#define SPI_TCTRL_SS_SEL_SHIFT (4) +#define SPI_TCTRL_SS_SEL_MASK (0x3U << SPI_TCTRL_SS_SEL_SHIFT) +typedef enum +{ + SPI_TCTRL_SS_SEL_SS0 = 0 << SPI_TCTRL_SS_SEL_SHIFT, + SPI_TCTRL_SS_SEL_SS1 = 1 << SPI_TCTRL_SS_SEL_SHIFT, + SPI_TCTRL_SS_SEL_SS2 = 2 << SPI_TCTRL_SS_SEL_SHIFT, + SPI_TCTRL_SS_SEL_SS3 = 3 << SPI_TCTRL_SS_SEL_SHIFT +} SPI_TCTRL_SS_Sel; + +#define SPI_TCTRL_SS_CTL_SHIFT (3) +#define SPI_TCTRL_SS_CTL_MASK (0x1U << SPI_TCTRL_SS_CTL_SHIFT) + +#define SPI_TCTRL_SPOL_SHIFT (2) +#define SPI_TCTRL_SPOL_MASK (0x1U << SPI_TCTRL_SPOL_SHIFT) + +#define SPI_TCTRL_CPOL_SHIFT (1) +#define SPI_TCTRL_CPOL_MASK (0x1U << SPI_TCTRL_CPOL_SHIFT) +typedef enum +{ + SPI_TCTRL_CPOL_HIGH = 0 << SPI_TCTRL_CPOL_SHIFT, + SPI_TCTRL_CPOL_LOW = 1 << SPI_TCTRL_CPOL_SHIFT +} SPI_TCTRL_Cpol; + +#define SPI_TCTRL_CPHA_SHIFT (0) +#define SPI_TCTRL_CPHA_MASK (0x1U << SPI_TCTRL_CPHA_SHIFT) +typedef enum +{ + SPI_TCTRL_CPHA_PHASE0 = 0 << SPI_TCTRL_CPHA_SHIFT, + SPI_TCTRL_CPHA_PHASE1 = 1 << SPI_TCTRL_CPHA_SHIFT +} SPI_TCTRL_Cpha; + +typedef enum +{ + SPI_SCLK_Mode0 = 0 << SPI_TCTRL_CPHA_SHIFT, + SPI_SCLK_Mode1 = 1 << SPI_TCTRL_CPHA_SHIFT, + SPI_SCLK_Mode2 = 2 << SPI_TCTRL_CPHA_SHIFT, + SPI_SCLK_Mode3 = 3 << SPI_TCTRL_CPHA_SHIFT +} SPI_SCLK_Mode; + +/* + * @brief SPI Interrupt Control Register + */ +#define SPI_IER_SS_INT_EN_SHIFT (13) +#define SPI_IER_SS_INT_EN_MASK (0x1U << SPI_IER_SS_INT_EN_SHIFT) + +#define SPI_IER_TC_INT_EN_SHIFT (12) +#define SPI_IER_TC_INT_EN_MASK (0x1U << SPI_IER_TC_INT_EN_SHIFT) + +#define SPI_IER_TF_UDR_INT_EN_SHIFT (11) +#define SPI_IER_TF_UDR_INT_EN_MASK (0x1U << SPI_IER_TF_UDR_INT_EN_SHIFT) + +#define SPI_IER_TF_OVF_INT_EN_SHIFT (10) +#define SPI_IER_TF_OVF_INT_EN_MASK (0x1U << SPI_IER_TF_OVF_INT_EN_SHIFT) + +#define SPI_IER_RF_UDR_INT_EN_SHIFT (9) +#define SPI_IER_RF_UDR_INT_EN_MASK (0x1U << SPI_IER_RF_UDR_INT_EN_SHIFT) + +#define SPI_IER_RF_OVF_INT_EN_SHIFT (8) +#define SPI_IER_RF_OVF_INT_EN_MASK (0x1U << SPI_IER_RF_OVF_INT_EN_SHIFT) + +#define SPI_IER_TF_FUL_INT_EN_SHIFT (6) +#define SPI_IER_TF_FUL_INT_EN_MASK (0x1U << SPI_IER_TF_FUL_INT_EN_SHIFT) + +#define SPI_IER_TX_EMP_INT_EN_SHIFT (5) +#define SPI_IER_TX_EMP_INT_EN_MASK (0x1U << SPI_IER_TX_EMP_INT_EN_SHIFT) + +#define SPI_IER_TX_ERQ_INT_EN_SHIFT (4) +#define SPI_IER_TX_ERQ_INT_EN_MASK (0x1U << SPI_IER_TX_ERQ_INT_EN_SHIFT) + +#define SPI_IER_RF_FUL_INT_EN_SHIFT (2) +#define SPI_IER_RF_FUL_INT_EN_MASK (0x1U << SPI_IER_RF_FUL_INT_EN_SHIFT) + +#define SPI_IER_RX_EMP_INT_EN_SHIFT (1) +#define SPI_IER_RX_EMP_INT_EN_MASK (0x1U << SPI_IER_RX_EMP_INT_EN_SHIFT) + +#define SPI_IER_RF_RDY_INT_EN_SHIFT (0) +#define SPI_IER_RF_RDY_INT_EN_MASK (0x1U << SPI_IER_RF_RDY_INT_EN_SHIFT) + +/* + * @brief SPI Interrupt Status Register + */ +#define SPI_STA_SSI_SHIFT (13) +#define SPI_STA_SSI_MASK (0x1U << SPI_STA_SSI_SHIFT) + +#define SPI_STA_TC_SHIFT (12) +#define SPI_STA_TC_MASK (0x1U << SPI_STA_TC_SHIFT) + +#define SPI_STA_TF_UDF_SHIFT (11) +#define SPI_STA_TF_UDF_MASK (0x1U << SPI_STA_TF_UDF_SHIFT) + +#define SPI_STA_TF_OVF_SHIFT (10) +#define SPI_STA_TF_OVF_MASK (0x1U << SPI_STA_TF_OVF_SHIFT) + +#define SPI_STA_RX_UDF_SHIFT (9) +#define SPI_STA_RX_UDF_MASK (0x1U << SPI_STA_RX_UDF_SHIFT) + +#define SPI_STA_RX_OVF_SHIFT (8) +#define SPI_STA_RX_OVF_MASK (0x1U << SPI_STA_RX_OVF_SHIFT) + +#define SPI_STA_TX_FULL_SHIFT (6) +#define SPI_STA_TX_FULL_MASK (0x1U << SPI_STA_TX_FULL_SHIFT) + +#define SPI_STA_TX_EMP_SHIFT (5) +#define SPI_STA_TX_EMP_MASK (0x1U << SPI_STA_TX_EMP_SHIFT) + +#define SPI_STA_TX_READY_SHIFT (4) +#define SPI_STA_TX_READY_MASK (0x1U << SPI_STA_TX_READY_SHIFT) + +#define SPI_STA_RX_FULL_SHIFT (2) +#define SPI_STA_RX_FULL_MASK (0x1U << SPI_STA_RX_FULL_SHIFT) + +#define SPI_STA_RX_EMP_SHIFT (1) +#define SPI_STA_RX_EMP_MASK (0x1U << SPI_STA_RX_EMP_SHIFT) + +#define SPI_STA_RX_RDY_SHIFT (0) +#define SPI_STA_RX_RDY_MASK (0x1U << SPI_STA_RX_RDY_SHIFT) + +/* + * @brief SPI FIFO Control Register + */ +#define SPI_FCTL_TF_RST_SHIFT (31) +#define SPI_FCTL_TF_RST_MASK (0x1U << SPI_FCTL_TF_RST_SHIFT) + +#define SPI_FCTL_TF_TEST_EN_SHIFT (30) +#define SPI_FCTL_TF_TEST_EN_MASK (0x1U << SPI_FCTL_TF_TEST_EN_SHIFT) + +#define SPI_FCTL_TF_DRQ_EN_SHIFT (24) +#define SPI_FCTL_TF_DRQ_EN_MASK (0x1U << SPI_FCTL_TF_DRQ_EN_SHIFT) +#define SPI_FCTL_TF_DRQ_EN_BIT HAL_BIT(24) + +#define SPI_FCTL_TX_TRIG_LEVEL_SHIFT (16) +#define SPI_FCTL_TX_TRIG_LEVEL_MASK (0xFFU << SPI_FCTL_TX_TRIG_LEVEL_SHIFT) + +#define SPI_FCTL_RF_RST_SHIFT (15) +#define SPI_FCTL_RF_RST_MASK (0x1U << SPI_FCTL_RF_RST_SHIFT) + +#define SPI_FCTL_RF_TEST_SHIFT (14) +#define SPI_FCTL_RF_TEST_MASK (0x1U << SPI_FCTL_RF_TEST_SHIFT) + +#define SPI_FCTL_RF_DRQ_EN_SHIFT (8) +#define SPI_FCTL_RF_DRQ_EN_MASK (0x1U << SPI_FCTL_RF_DRQ_EN_SHIFT) + +#define SPI_FCTL_RX_TRIG_LEVEL_SHIFT (0) +#define SPI_FCTL_RX_TRIG_LEVEL_MASK (0xFFU << SPI_FCTL_RX_TRIG_LEVEL_SHIFT) + +/* + * @brief SPI FIFO Status Registe + */ +#define SPI_FST_TB_WR_SHIFT (31) +#define SPI_FST_TB_WR_MASK (0x1U << SPI_FST_TB_WR_SHIFT) + +#define SPI_FST_TB_CNT_SHIFT (28) +#define SPI_FST_TB_CNT_MASK (0x7U << SPI_FST_TB_CNT_SHIFT) + +#define SPI_FST_TF_CNT_SHIFT (16) +#define SPI_FST_TF_CNT_MASK (0xFFU << SPI_FST_TF_CNT_SHIFT) + +#define SPI_FST_RB_WR_SHIFT (15) +#define SPI_FST_RB_WR_MASK (0x1U << SPI_FST_RB_WR_SHIFT) + +#define SPI_FST_RB_CNT_SHIFT (12) +#define SPI_FST_RB_CNT_MASK (0x7U << SPI_FST_RB_CNT_SHIFT) + +#define SPI_FST_RF_CNT_SHIFT (0) +#define SPI_FST_RF_CNT_MASK (0xFFU << SPI_FST_RF_CNT_SHIFT) + +/* + * @brief SPI Wait Clock Counter Register + */ +#define SPI_WAIT_SWC_SHIFT (16) +#define SPI_WAIT_SWC_MASK (0xFU << SPI_WAIT_SWC_SHIFT) + +#define SPI_WAIT_WCC_SHIFT (0) +#define SPI_WAIT_WCC_MASK (0xFFFFU << SPI_WAIT_WCC_SHIFT) + +/* + * @brief SPI Clock Rate Control Register + */ +#define SPI_CCTR_DRS_SHIFT (12) +#define SPI_CCTR_DRS_MASK (0x1U << SPI_CCTR_DRS_SHIFT) +typedef enum +{ + SPI_CCTR_DRS_type_divRate1 = 0 << SPI_CCTR_DRS_SHIFT, + SPI_CCTR_DRS_type_divRate2 = 1 << SPI_CCTR_DRS_SHIFT +} SPI_CCTR_DRS_type; + +#define SPI_CCTR_CDR1_SHIFT (8) +#define SPI_CCTR_CDR1_MASK (0xFU << SPI_CCTR_CDR1_SHIFT) + +#define SPI_CCTR_CDR2_SHIFT (0) +#define SPI_CCTR_CDR2_MASK (0xFFU << SPI_CCTR_CDR2_SHIFT) + +/* + * @brief SPI Master mode Burst Control Register + */ +#define SPI_BC_MBC_SHIFT (0) +#define SPI_BC_MBC_MASK (0xFFFFFFU << SPI_BC_MBC_SHIFT) + +/* + * @brief SPI Master mode Transmit Counter Register + */ +#define SPI_TC_MWTC_SHIFT (0) +#define SPI_TC_MWTC_MASK (0xFFFFFFU << SPI_TC_MWTC_SHIFT) + +/* + * @brief SPI Burst Control Register + */ +#define SPI_BCC_DRM_SHIFT (28) +#define SPI_BCC_DRM_MASK (0x1U << SPI_BCC_DRM_SHIFT) + +#define SPI_BCC_DBC_SHIFT (24) +#define SPI_BCC_DBC_MASK (0xFU << SPI_BCC_DBC_SHIFT) + +#define SPI_BCC_STC_SHIFT (0) +#define SPI_BCC_STC_MASK (0xFFFFFFU << SPI_BCC_STC_SHIFT) + +/* + * @brief SPI Nomal DMA Mode Control Regist + */ +#define SPI_NDMA_MODE_CTRL_SHIFT (0) +#define SPI_NDMA_MODE_CTRL_MASK (0xFFU << SPI_NDMA_MODE_CTRL_SHIFT) + +/* + * @brief SPI TX Date Register + */ +#define SPI_TXD_SHIFT (0) +#define SPI_TXD_MASK (0xFFFFFFFFU << SPI_TXD_SHIFT) + +/* + * @brief SPI RX Date Register + */ +#define SPI_RXD_SHIFT (0) +#define SPI_RXD_MASK (0xFFFFFFFFU << SPI_RXD_SHIFT) + +/* other */ +#define SPI_FIFO_SIZE (64) +#define SPI_MAX_WAIT_MS (2000) +#define SPI_SOURCE_CLK (24 * 1000 * 1000) + +/* io ops */ +#define HAL_BIT(pos) (1U << (pos)) + +#define HAL_SET_BIT(reg, mask) ((reg) |= (mask)) +#define HAL_CLR_BIT(reg, mask) ((reg) &= ~(mask)) +#define HAL_GET_BIT(reg, mask) ((reg) & (mask)) +#define HAL_GET_BIT_VAL(reg, shift, vmask) (((reg) >> (shift)) & (vmask)) + +#define HAL_MODIFY_REG(reg, clr_mask, set_mask) \ + ((reg) = (((reg) & (~(clr_mask))) | (set_mask))) + +/* access LSBs of a 32-bit register (little endian only) */ +#define HAL_REG_32BIT(reg_addr) (*((volatile rt_uint32_t *)(reg_addr))) +#define HAL_REG_16BIT(reg_addr) (*((volatile rt_uint16_t *)(reg_addr))) +#define HAL_REG_8BIT(reg_addr) (*((volatile rt_uint8_t *)(reg_addr))) + +#define HAL_WAIT_FOREVER OS_WAIT_FOREVER + +#define HAL_ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0])) + +struct tina_spi +{ + SPI_T *spi; + unsigned int spi_gate; + struct rt_spi_bus *spi_bus; +}; + +struct tina_spi_cs +{ + SPI_TCTRL_SS_Sel cs; +}; +/* public function */ +rt_err_t r6_spi_bus_register(SPI_T *spi, const char *spi_bus_name); + +#ifdef __cplusplus +} +#endif +#endif // diff --git a/bsp/allwinner_tina/drivers/spi/drv_spi_flash.c b/bsp/allwinner_tina/drivers/spi/drv_spi_flash.c new file mode 100644 index 0000000000..9e2f339df4 --- /dev/null +++ b/bsp/allwinner_tina/drivers/spi/drv_spi_flash.c @@ -0,0 +1,80 @@ +/* + * File : drv_spi_flash.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-02-08 RT-Thread the first version + */ + +#include +#include +#include + +#define DBG_ENABLE +#define DBG_SECTION_NAME "[FLASH]" +#define DBG_LEVEL DBG_LOG +#define DBG_COLOR +#include + +#define SPI_FLASH_DEVICE_NAME "spi00" +#define SPI_FLASH_CHIP "gd25qxx" + +//#define DEBUG + +#ifdef DEBUG +#define DEBUG_PRINTF(...) rt_kprintf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + +#ifdef TINA_USING_SPI_FLASH + +#include "spi_flash.h" + +#if defined(RT_USING_SFUD) +#include "spi_flash_sfud.h" +rt_spi_flash_device_t spi_device; +int rt_hw_spi_flash_with_sfud_init(void) +{ + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + spi_device = rt_sfud_flash_probe(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME); + if (spi_device == NULL) + { + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + return RT_ERROR; + }; + + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + return RT_EOK; +} +INIT_PREV_EXPORT(rt_hw_spi_flash_with_sfud_init); + +#elif defined(RT_USING_W25QXX) +#include "spi_flash_w25qxx.h" + +int rt_hw_spi_flash_init(void) +{ + DEBUG_PRINTF("%s -> %d\n", __FUNCTION__, __LINE__); + return w25qxx_init(SPI_FLASH_CHIP, SPI_FLASH_DEVICE_NAME); +} +INIT_DEVICE_EXPORT(rt_hw_spi_flash_init); + +#endif + +#endif \ No newline at end of file diff --git a/bsp/asm9260t/rtconfig.py b/bsp/asm9260t/rtconfig.py index 2a7b809133..5b58a675e3 100644 --- a/bsp/asm9260t/rtconfig.py +++ b/bsp/asm9260t/rtconfig.py @@ -17,7 +17,7 @@ elif CROSS_TOOL == 'keil': EXEC_PATH = 'C:/Keil_v5' elif CROSS_TOOL == 'iar': PLATFORM = 'iar' - IAR_PATH = 'C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.0' + EXEC_PATH = 'C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.0' if os.getenv('RTT_EXEC_PATH'): EXEC_PATH = os.getenv('RTT_EXEC_PATH') @@ -113,7 +113,7 @@ elif PLATFORM == 'iar': CFLAGS += ' --endian=little' CFLAGS += ' -e' CFLAGS += ' --fpu=none' - CFLAGS += ' --dlib_config "' + IAR_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' CFLAGS += ' --silent' AFLAGS = '--cpu '+ DEVICE @@ -135,5 +135,5 @@ elif PLATFORM == 'iar': LFLAGS += ' --map ' + MAP_FILE LFLAGS += ' --silent' - EXEC_PATH = IAR_PATH + '/arm/bin/' + EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = 'ielftool --silent --bin $TARGET ' + TARGET_NAME diff --git a/bsp/at91sam9260/rtconfig.py b/bsp/at91sam9260/rtconfig.py index fe64534a71..2ebf071443 100755 --- a/bsp/at91sam9260/rtconfig.py +++ b/bsp/at91sam9260/rtconfig.py @@ -16,7 +16,7 @@ elif CROSS_TOOL == 'keil': EXEC_PATH = 'C:/Keil_v5' elif CROSS_TOOL == 'iar': PLATFORM = 'iar' - IAR_PATH = 'C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.0' + EXEC_PATH = 'C:/Program Files (x86)/IAR Systems/Embedded Workbench 7.0' if os.getenv('RTT_EXEC_PATH'): EXEC_PATH = os.getenv('RTT_EXEC_PATH') @@ -111,7 +111,7 @@ elif PLATFORM == 'iar': CFLAGS += ' --endian=little' CFLAGS += ' -e' CFLAGS += ' --fpu=none' - CFLAGS += ' --dlib_config "' + IAR_PATH + '/arm/INC/c/DLib_Config_Normal.h"' + CFLAGS += ' --dlib_config "' + EXEC_PATH + '/arm/INC/c/DLib_Config_Normal.h"' CFLAGS += ' --silent' AFLAGS = '--cpu '+ DEVICE @@ -133,5 +133,5 @@ elif PLATFORM == 'iar': LFLAGS += ' --map ' + MAP_FILE LFLAGS += ' --silent' - EXEC_PATH = IAR_PATH + '/arm/bin/' + EXEC_PATH = EXEC_PATH + '/arm/bin/' POST_ACTION = 'ielftool --silent --bin $TARGET ' + TARGET_NAME diff --git a/bsp/gd32450z-eval/project.ewp b/bsp/gd32450z-eval/project.ewp index 668bf4899e..b26015f8f6 100644 --- a/bsp/gd32450z-eval/project.ewp +++ b/bsp/gd32450z-eval/project.ewp @@ -298,32 +298,28 @@