W806 W800 W801 SDIO的SPI模式驱动TFTLCD
/***************************************************************************** * * File Name : main.c * * Description: main * * Copyright (c) 2014 Winner Micro Electronic Design Co., Ltd. * All rights reserved. * * Author : dave * * Date : 2014-6-14 *****************************************************************************/ #include "wm_include.h" #include "wm_gpio_afsel.h" #include "wm_pmu.h" #include "wm_sdio_host.h" #include "wm_cpu.h" #include "wm_dma.h" #include "string.h" #include "wm_uart.h" #include "FreeRTOS.h" #include "rtoslist.h" #include "rtosqueue.h" int wm_sd_card_dma_config(u32*mbuf,u32 bufsize,u8 dir); void delay_cnt(int count); //#include <new> //#include "protocal.h" //#include <functional> static int sm_sdh_wait_interrupt(uint8_t srcbit, int timeout) { int ret = 0; unsigned int tmp = (1 << srcbit); volatile int vtimeout= timeout; if(vtimeout == -1) { vtimeout = 0x7FFFF; } while(1) { if(SDIO_HOST->MMC_INT_SRC & tmp) { SDIO_HOST->MMC_INT_SRC |= tmp; if(SDIO_HOST->MMC_INT_SRC) { printf("Err Int 0x%x\n", SDIO_HOST->MMC_INT_SRC); } break; } vtimeout--; if((vtimeout == 0) || (vtimeout < 0)) { ret = 1; //timeout, err break; } delay_cnt(1); } return ret; } static const uint8_t st7789_init_seq[] = { 1, 20, 0x01, // Software reset 1, 10, 0x11, // Exit sleep mode 2, 2, 0x3a, 0x55, // Set colour mode to 16 bit 2, 0, 0x36, 0x00, // Set MADCTL: row then column, refresh is bottom to top ???? 5, 0, 0x2a, 0x00, 0x00, 0x00, 0xf0, // CASET: column addresses from 0 to 240 (f0) 5, 0, 0x2b, 0x00, 0x00, 0x01, 0x40, // RASET: row addresses from 0 to 240 (f0) 1, 2, 0x21, // Inversion on, then 10 ms delay (supposedly a hack?) 1, 2, 0x13, // Normal display on, then 10 ms delay 1, 2, 0x29, // Main screen turn on, then wait 500 ms 0 // Terminate list }; #define PIN_CS WM_IO_PA_11 #define PIN_DC WM_IO_PA_12 #define PIN_RESET WM_IO_PA_13 static inline void lcd_set_dc_cs(bool dc, bool cs) { tls_gpio_write(PIN_DC, dc); tls_gpio_write(PIN_CS, cs); } static inline void st7789_lcd_wait_idle(){ } static inline void st7789_lcd_put(u8 d){ SDIO_HOST->BUF_CTL = 0x4820; SDIO_HOST->DATA_BUF[0] = d; SDIO_HOST->MMC_BYTECNTL = 1; SDIO_HOST->MMC_IO = 0x01; while (1) { if ((SDIO_HOST->MMC_IO & 0x01) == 0x00) break; } } static inline void lcd_write_cmd(const uint8_t *cmd, size_t count) { st7789_lcd_wait_idle(); lcd_set_dc_cs(0, 0); st7789_lcd_put(*cmd++); if (count >= 2) { st7789_lcd_wait_idle(); lcd_set_dc_cs(1, 0); for (size_t i = 0; i < count - 1; ++i) st7789_lcd_put( *cmd++); } st7789_lcd_wait_idle(); lcd_set_dc_cs(1, 1); } static inline void lcd_init(const uint8_t *init_seq) { const uint8_t *cmd = init_seq; while (*cmd) { lcd_write_cmd(cmd + 2, *cmd); tls_os_time_delay(*(cmd + 1) * 5/2); cmd += *cmd + 2; } } static inline void st7789_start_pixels() { uint8_t cmd = 0x2c; // RAMWR lcd_write_cmd( &cmd, 1); lcd_set_dc_cs(1, 0); } static inline void init_sdio_spimode(){ tls_io_cfg_set(WM_IO_PA_09, WM_IO_OPTION1);/*CK*/ tls_io_cfg_set(WM_IO_PA_10, WM_IO_OPTION1);/*CMD*/ tls_open_peripheral_clock(TLS_PERIPHERAL_TYPE_SDIO_MASTER); tls_bitband_write(HR_CLK_RST_CTL, 27, 0); tls_bitband_write(HR_CLK_RST_CTL, 27, 1); while (tls_bitband_read(HR_CLK_RST_CTL, 27) == 0); tls_sys_clk sysclk; tls_sys_clk_get(&sysclk); SDIO_HOST->MMC_CARDSEL = 0xC0 | (sysclk.cpuclk / 2 - 1);//0xd3; //enable module, enable mmcclk SDIO_HOST->MMC_CTL = 0x542 | 0 << 3;//0xC3; //4bits, low speed, 1/4 divider, auto transfer, mmc mode. SDIO_HOST->MMC_INT_MASK = 0x100; //unmask sdio data interrupt. SDIO_HOST->MMC_CRCCTL = 0x00; // SDIO_HOST->MMC_TIMEOUTCNT = 0; SDIO_HOST->MMC_BYTECNTL = 0; } void writetest(){ int block_cnt = 1; int datalen=512 * block_cnt; SDIO_HOST->BUF_CTL = 0x4820; for (int i = 0; i < 128; i++) SDIO_HOST->DATA_BUF[i] = i; SDIO_HOST->MMC_BYTECNTL = datalen; tls_gpio_write(WM_IO_PB_08, 0); SDIO_HOST->MMC_IO = 0x01; while (1) { if ((SDIO_HOST->MMC_IO & 0x01) == 0x00) break; } tls_gpio_write(WM_IO_PB_08, 1); } void writetestDMA() { int block_cnt = 1; int datalen=512 * block_cnt; u32 *buf = (u32 *) tls_mem_alloc(datalen); for (int i = 0; i < datalen ; i++) ((uint8_t*)buf)[i] = i&0xff; SDIO_HOST->BUF_CTL = 0x4000; //disable dma, int dma_channel = wm_sd_card_dma_config((u32 *) buf, datalen, 1); SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly tls_gpio_write(WM_IO_PB_08, 0); SDIO_HOST->MMC_BYTECNTL = datalen; SDIO_HOST->MMC_IO = 0x01; while (1) { if ((SDIO_HOST->MMC_IO & 0x01) == 0x00) break; } tls_gpio_write(WM_IO_PB_08, 1); tls_dma_free(dma_channel); } int wm_sd_card_dma_config__(u32*mbuf,u32 bufsize,u8 dir) { int ch; u32 addr_inc = 0; ch = tls_dma_request(0, NULL); DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_OFF; if(dir) { DMA_SRCADDR_REG(ch) = (unsigned int)mbuf; DMA_DESTADDR_REG(ch) = (unsigned int)SDIO_HOST->DATA_BUF; addr_inc = DMA_CTRL_SRC_ADDR_INC; } else { DMA_SRCADDR_REG(ch) = (unsigned int)SDIO_HOST->DATA_BUF; DMA_DESTADDR_REG(ch) = (unsigned int)mbuf; addr_inc =DMA_CTRL_DEST_ADDR_INC; } // u32 mode=DMA_CTRL_DATA_SIZE_BYTE; // if(bufsize&1==0){ // mode=DMA_CTRL_DATA_SIZE_SHORT; // if(bufsize&2==0) // mode=DMA_CTRL_DATA_SIZE_WORD; // } DMA_CTRL_REG(ch) = addr_inc | DMA_CTRL_DATA_SIZE_WORD | (bufsize << 8); DMA_MODE_REG(ch) = DMA_MODE_SEL_SDIOHOST | DMA_MODE_HARD_MODE; DMA_CHNLCTRL_REG(ch) = DMA_CHNL_CTRL_CHNL_ON; return ch; } void write_SDIO_SPI_DMA(u32* data,int len) { while (1) { if ((SDIO_HOST->MMC_IO & 0x01) == 0x00) break; } u32 offset=0; while(len>0){ int datalen=len; if(len>0xfffc) datalen=0xfffc; len-=datalen; SDIO_HOST->BUF_CTL = 0x4000; //disable dma, int dma_channel = wm_sd_card_dma_config__((u32 *) data+offset, datalen, 1); SDIO_HOST->BUF_CTL = 0xC20; //enable dma, write sd card SDIO_HOST->MMC_INT_SRC |= 0x7ff; // clear all firstly SDIO_HOST->MMC_BYTECNTL = datalen; SDIO_HOST->MMC_IO = 0x01; offset+=datalen/4; while (1) { if ((SDIO_HOST->BUF_CTL & 0x400) == 0x00) break; } tls_dma_free(dma_channel); } } //#define WHITE 0xFFFF //#define BLACK 0x0000 //#define BLUE 0x001F //#define BRED 0XF81F //#define GRED 0XFFE0 //#define GBLUE 0X07FF //#define RED 0xF800 //#define MAGENTA 0xF81F //#define GREEN 0x07E0 //#define CYAN 0x7FFF //#define YELLOW 0xFFE0 //#define BROWN 0XBC40 //棕色 //#define BRRED 0XFC07 //棕红色 //#define GRAY 0X8430 //灰色 void UartMain(void) { printf("\n uart task \n"); tls_gpio_cfg(PIN_CS, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); tls_gpio_write(PIN_CS, 1); tls_gpio_cfg(PIN_DC, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); tls_gpio_write(PIN_DC, 1); tls_gpio_cfg(PIN_RESET, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); tls_gpio_write(PIN_RESET, 0); tls_gpio_cfg(WM_IO_PA_08, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_PULLHIGH); tls_gpio_write(WM_IO_PA_08, 1); tls_os_time_delay(100); tls_gpio_write(PIN_RESET, 1); init_sdio_spimode(); lcd_init(st7789_init_seq); static u32 buf[240*120]; int count=0; u16 buff[]={WHITE,BLACK,BLUE,BRED,GRED,YELLOW,RED,GRAY}; while (1) { if(++count>=7) { count = 0; } u16*buf1=(u16*)buf; st7789_start_pixels(); for (int x=0;x<240;x++) for(int y=0;y<240;y++){ // buf1[y*320+x]=(((x+count)&0x1f)<<11)|(((y+count)&0x3f)<<5)|(((x+y+count)&0x1f)); buf1[y*240+x]=buff[count]; } write_SDIO_SPI_DMA((u32*)buf1,240*240*2); tls_os_time_delay(1000); // write_SDIO_SPI_DMA((u32*)buf1,240*240); } } void UserMain(void) { printf("\n User task \n"); tls_os_task_t uarttask; void* uartstack=malloc(16384); tls_os_task_create(&uarttask, "UartMain", UartMain, (void *)NULL, (u8 *)uartstack, /* 任务栈的起始地址 */ 16384, /* 任务栈的大小 */ 3, 0); }