armstrong 说:各种mapper是有标准的吗?还是全靠逆向分析出来的?
好全的nes资料啊,多谢分享
DOUT+DMA模式,太快了!若SPI时钟设为100MHZ,能达到25MB/S;保险起见设置SPI为50MHZ,也有12.5MB/S。
启动个RTOS应用简直了。
#include <stdint.h>
#include <string.h>
#include "f1c100s/reg-ccu.h"
#include "io.h"
#define SPI_USE_DMA (1)
enum {
SPI_GCR = 0x04,
SPI_TCR = 0x08,
SPI_IER = 0x10,
SPI_ISR = 0x14,
SPI_FCR = 0x18,
SPI_FSR = 0x1c,
SPI_WCR = 0x20,
SPI_CCR = 0x24,
SPI_MBC = 0x30,
SPI_MTC = 0x34,
SPI_BCC = 0x38,
SPI_TXD = 0x200,
SPI_RXD = 0x300,
};
#if SPI_USE_DMA > 0
enum {
DMA0 = 0,
DMA1,
DMA2,
DMA3,
};
enum {
NDMA = 0,
DDMA,
};
#define NDMA_TRANS_LEN (128u*1024)
#define DDMA_TRANS_LEN (16u*1024*1024)
/********** DMA info *************/
#define DMA_NO (DMA0)
#define DMA_MODE (NDMA) /* SPI only support NDMA */
#define DMA_TRANS_LEN ((DMA_MODE == NDMA) ? (NDMA_TRANS_LEN) : (DDMA_TRANS_LEN))
#define DMA_BASE (0x01C02000)
#define DMA_ICR (DMA_BASE + 0x00)
#define DMA_ISR (DMA_BASE + 0x04)
#define DMA_PCR (DMA_BASE + 0x08)
#define NDMA_CR(dma_n) (DMA_BASE + 0x100 + 0x20*dma_n + 0x0)
#define NDMA_SRC_ADDR(dma_n) (DMA_BASE + 0x100 + 0x20*dma_n + 0x4)
#define NDMA_DES_ADDR(dma_n) (DMA_BASE + 0x100 + 0x20*dma_n + 0x8)
#define NDMA_BCR(dma_n) (DMA_BASE + 0x100 + 0x20*dma_n + 0xC)
#define DDMA_CR(dma_n) (DMA_BASE + 0x300 + 0x20*dma_n + 0x0)
#define DDMA_SRC_ADDR(dma_n) (DMA_BASE + 0x300 + 0x20*dma_n + 0x4)
#define DDMA_DES_ADDR(dma_n) (DMA_BASE + 0x300 + 0x20*dma_n + 0x8)
#define DDMA_BCR(dma_n) (DMA_BASE + 0x300 + 0x20*dma_n + 0xC)
#define DDMA_PR(dma_n) (DMA_BASE + 0x300 + 0x20*dma_n + 0x18)
#define DDMA_GD(dma_n) (DMA_BASE + 0x300 + 0x20*dma_n + 0x1C)
static void sdelay(int loops)
{
loop_again:
__asm volatile {
SUBS loops, loops, #1
BNE loop_again
}
}
static void sys_dma_init(void)
{
/* Enable gate for DMA clock, and perform softreset */
write32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0, read32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0) | (0x1 << 6));
write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) & (~(0x1 << 6)));
sdelay(20);
write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) | (0x1 << 6));
}
static void sys_dma_deinit(void)
{
write32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0, read32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0) & (~(0x1 << 6)));
}
static uint32_t sys_dma_transfer_len_get(void)
{
return DMA_TRANS_LEN;
}
static void sys_spi_dma_set(void* dst, void* src, uint32_t len)
{
uint32_t val;
write32(NDMA_SRC_ADDR(DMA_NO), (uint32_t)src);
write32(NDMA_DES_ADDR(DMA_NO), (uint32_t)dst);
write32(NDMA_BCR(DMA_NO), len);
val = (1u << 31) | (0x11 << 16) | (0x1 << 5) | (0x4 << 0);
write32(NDMA_CR(DMA_NO), val);
}
static void sys_spi_dma_start(uint32_t len)
{
uint32_t reg_base = 0x01c05000;
uint32_t val;
write32(reg_base + SPI_MBC, len);
write32(reg_base + SPI_MTC, 0);
write32(reg_base + SPI_BCC, (1 << 28)); // dual-mode
val = read32(reg_base + SPI_FCR);
val |= (1 << 8) | (1 << 0);
write32(reg_base + SPI_FCR, val);
write32(reg_base + SPI_TCR, read32(reg_base + SPI_TCR) | (1u << 31));
}
static void sys_dma_wait_end(void)
{
/* when the dma end, it clear this bit automatically */
while (read32(NDMA_CR(DMA_NO)) & (1u << 31));
}
#endif
void sys_spi_flash_init(void)
{
uint32_t addr;
uint32_t val;
/* Config GPIOC0, GPIOC1, GPIOC2 and GPIOC3 */
addr = 0x01c20848 + 0x00;
val = read32(addr);
val &= ~(0xf << ((0 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((0 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((1 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((1 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((2 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((2 & 0x7) << 2));
write32(addr, val);
val = read32(addr);
val &= ~(0xf << ((3 & 0x7) << 2));
val |= ((0x2 & 0x7) << ((3 & 0x7) << 2));
write32(addr, val);
/* Deassert spi0 reset */
addr = 0x01c202c0;
val = read32(addr);
val |= (1 << 20);
write32(addr, val);
/* Open the spi0 bus gate */
addr = 0x01c20000 + 0x60;
val = read32(addr);
val |= (1 << 20);
write32(addr, val);
/* Set spi clock rate control register, divided by 4 */
addr = 0x01c05000;
write32(addr + SPI_CCR, 0x00001001);
/* Enable spi0 and do a soft reset */
addr = 0x01c05000;
val = read32(addr + SPI_GCR);
val |= (1UL << 31) | (1 << 7) | (1 << 1) | (1 << 0); // Transmit Pause Enable (TP_EN)
write32(addr + SPI_GCR, val);
while (read32(addr + SPI_GCR) & (1UL << 31));
val = read32(addr + SPI_TCR);
val &= ~(0x3 << 0);
val |= (1 << 6) | (1 << 2);
write32(addr + SPI_TCR, val);
val = read32(addr + SPI_FCR);
val |= (1UL << 31) | (1 << 15);
write32(addr + SPI_FCR, val);
#if SPI_USE_DMA > 0
sys_dma_init();
#endif
}
void sys_spi_flash_exit(void)
{
uint32_t addr = 0x01c05000;
uint32_t val;
/* Disable the spi0 controller */
val = read32(addr + SPI_GCR);
val &= ~((1 << 1) | (1 << 0));
write32(addr + SPI_GCR, val);
#if SPI_USE_DMA > 0
sys_dma_deinit();
#endif
}
static void sys_spi_select(void)
{
uint32_t addr = 0x01c05000;
uint32_t val;
val = read32(addr + SPI_TCR);
val &= ~((0x3 << 4) | (0x1 << 7));
val |= ((0 & 0x3) << 4) | (0x0 << 7);
write32(addr + SPI_TCR, val);
}
static void sys_spi_deselect(void)
{
uint32_t addr = 0x01c05000;
uint32_t val;
val = read32(addr + SPI_TCR);
val &= ~((0x3 << 4) | (0x1 << 7));
val |= ((0 & 0x3) << 4) | (0x1 << 7);
write32(addr + SPI_TCR, val);
}
static void sys_spi_write_txbuf(uint8_t* buf, int len)
{
uint32_t addr = 0x01c05000;
int i;
if (!buf)
len = 0;
write32(addr + SPI_MTC, len & 0xffffff);
write32(addr + SPI_BCC, len & 0xffffff);
for (i = 0; i < len; ++i)
write8(addr + SPI_TXD, *buf++);
}
static int sys_spi_transfer(void* txbuf, void* rxbuf, int len)
{
uint32_t addr = 0x01c05000;
int count = len;
uint8_t* tx = txbuf;
uint8_t* rx = rxbuf;
uint8_t val;
int n, i;
while (count > 0) {
n = (count <= 64) ? count : 64;
write32(addr + SPI_MBC, n);
sys_spi_write_txbuf(tx, n);
write32(addr + SPI_TCR, read32(addr + SPI_TCR) | (1UL << 31));
while ((read32(addr + SPI_FSR) & 0xff) < n);
for (i = 0; i < n; i++) {
val = read8(addr + SPI_RXD);
if (rx)
*rx++ = val;
}
if (tx)
tx += n;
count -= n;
}
return len;
}
static int sys_spi_write_then_read(void* txbuf, int txlen, void* rxbuf, int rxlen)
{
if (sys_spi_transfer(txbuf, NULL, txlen) != txlen)
return -1;
if (sys_spi_transfer(NULL, rxbuf, rxlen) != rxlen)
return -1;
return 0;
}
void sys_spi_flash_read(int addr, void* buf, int count)
{
uint8_t tx[4];
tx[0] = 0x03;
tx[1] = (uint8_t)(addr >> 16);
tx[2] = (uint8_t)(addr >> 8);
tx[3] = (uint8_t)(addr >> 0);
sys_spi_select();
sys_spi_write_then_read(tx, 4, buf, count);
sys_spi_deselect();
}
void sys_spi_flash_read_dualout(int addr, void* buf, int count)
{
uint32_t reg_base = 0x01c05000;
uint8_t* rxbuf = buf;
uint8_t tx[5];
int n, i, c;
n = 0;
tx[n++] = 0x3b; // fast read dual-output
tx[n++] = (uint8_t)(addr >> 16);
tx[n++] = (uint8_t)(addr >> 8);
tx[n++] = (uint8_t)(addr >> 0);
tx[n++] = 0;
sys_spi_select();
write32(reg_base + SPI_MBC, n);
write32(reg_base + SPI_MTC, n);
write32(reg_base + SPI_BCC, n);
for (i = 0; i < n; i++) {
write8(reg_base + SPI_TXD, tx[i]);
}
write32(reg_base + SPI_TCR, read32(reg_base + SPI_TCR) | (1u << 31));
while (read32(reg_base + SPI_TCR) & (1u << 31));
write32(reg_base + SPI_FCR, read32(reg_base + SPI_FCR) | 0x80008000u);
while (count > 0) {
n = ((count <= 4096) ? count : 4096);
write32(reg_base + SPI_MBC, n);
write32(reg_base + SPI_MTC, 0);
write32(reg_base + SPI_BCC, (1 << 28)); // dual-mode
write32(reg_base + SPI_TCR, read32(reg_base + SPI_TCR) | (1u << 31));
for (i = n; i > 0;) {
if ((c = (read32(reg_base + SPI_FSR) & 0xff)) > 0) {
i -= c;
while (c-- > 0) {
*rxbuf++ = read8(reg_base + SPI_RXD);
}
}
}
count -= n;
}
sys_spi_deselect();
}
#if SPI_USE_DMA > 0
void sys_spi_flash_read_dma(int addr, void* buf, uint32_t count)
{
uint32_t reg_base = 0x01c05000;
uint32_t dma_max_len;
uint8_t* rxbuf = buf;
uint8_t tx[5];
uint32_t n, i;
n = 0;
tx[n++] = 0x3b; // fast read dual-output
tx[n++] = (uint8_t)(addr >> 16);
tx[n++] = (uint8_t)(addr >> 8);
tx[n++] = (uint8_t)(addr >> 0);
tx[n++] = 0;
sys_spi_select();
write32(reg_base + SPI_MBC, n);
write32(reg_base + SPI_MTC, n);
write32(reg_base + SPI_BCC, n);
for (i = 0; i < n; i++) {
write8(reg_base + SPI_TXD, tx[i]);
}
write32(reg_base + SPI_TCR, read32(reg_base + SPI_TCR) | (1u << 31));
while (read32(reg_base + SPI_TCR) & (1u << 31));
write32(reg_base + SPI_FCR, read32(reg_base + SPI_FCR) | 0x80008000u);
dma_max_len = sys_dma_transfer_len_get();
while (count > 0) {
n = ((count <= dma_max_len) ? count : dma_max_len);
sys_spi_dma_set(rxbuf, (void*)(reg_base + SPI_RXD), n);
sys_spi_dma_start(n);
sys_dma_wait_end();
rxbuf += n;
count -= n;
}
sys_spi_deselect();
}
#endif
在spl代码中,用下面的代码替代sys_spi_flash_read函数,就可以最大速度加载app到ram执行。
我的AHB频率是200MHZ,SPI配置为50Mhz(100Mhz不太稳定),下面的代码启用DOUT模式传输,所以理论读取速度是12.5MB/秒。
BROM加载SPL大约150ms,而这段代码加载3MB的app代码仅需250ms,总共400毫秒就能启动3MB的应用程序。
void sys_spi_flash_read_dualout(int addr, void* buf, int count)
{
uint32_t reg_base = 0x01c05000;
uint8_t* rxbuf = buf;
uint8_t tx[5];
int n, i, c;
n = 0;
tx[n++] = 0x3b; // fast read dual-output
tx[n++] = (uint8_t)(addr >> 16);
tx[n++] = (uint8_t)(addr >> 8);
tx[n++] = (uint8_t)(addr >> 0);
tx[n++] = 0;
sys_spi_select();
write32(reg_base + SPI_MBC, n);
write32(reg_base + SPI_MTC, n);
write32(reg_base + SPI_BCC, n);
for (i = 0; i < n; i++) {
write8(reg_base + SPI_TXD, tx[i]);
}
write32(reg_base + SPI_TCR, read32(reg_base + SPI_TCR) | (1u << 31));
while (read32(reg_base + SPI_TCR) & (1u << 31));
write32(reg_base + SPI_FCR, read32(reg_base + SPI_FCR) | 0x80008000u);
while (count > 0) {
n = ((count <= 4096) ? count : 4096);
write32(reg_base + SPI_MBC, n);
write32(reg_base + SPI_MTC, 0);
write32(reg_base + SPI_BCC, (1 << 28)); // dual-mode
write32(reg_base + SPI_TCR, read32(reg_base + SPI_TCR) | (1u << 31));
for (i = n; i > 0;) {
// 这里代码看起来很累赘,但是这样却能快速读空RXFIFO!
if ((c = (read32(reg_base + SPI_FSR) & 0xff)) > 0) {
i -= c;
while (c-- > 0) {
*rxbuf++ = read8(reg_base + SPI_RXD);
}
}
}
count -= n;
}
sys_spi_deselect();
}
@gaoda
看这个:好多人喜欢开源的LVGL,那就随手加个演示吧,代码在gitee上。
文档还是在线的好。官方可以直接修改和增加内容,变更直达用户,不会碎片化。
像乐鑫这样的在线文档系统可以借鉴以下:
https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/index.html
好多人喜欢开源的LVGL,那就随手加个演示吧,代码在gitee上。
https://gitee.com/xuyao2020/F1C100s_with_Keil_RTX4_emWin5.git
(打开FELinside-LVGL.uvproj项目文件编译得到如下视频演示的bin)
gcc编译环境对于习惯了STM32的老人真是太难了,抽空移植到了keil,有需要的可以联系,目前因boot跟公司其他产品通用,暂时没有开源
https://whycan.com/files/members/8049/微信截图_20240329133209.jpg
大佬,请给我一份你截图中的工程,谢谢!我的邮箱是:26750452@qq.com
楼主,这个emWin5.32版的ARM9版库是从哪里抠出来的呢?NXP?
lvgl\examples\porting\lv_port_disp_template.c
void lv_port_disp_init(void)
{
/*-------------------------
* Initialize your display
* -----------------------*/
disp_init();
/*-----------------------------
* Create a buffer for drawing
*----------------------------*/
/**
* LVGL requires a buffer where it internally draws the widgets.
* Later this buffer will passed to your display driver's `flush_cb` to copy its content to your display.
* The buffer has to be greater than 1 display row
*
* There are 3 buffering configurations:
* 1. Create ONE buffer:
* LVGL will draw the display's content here and writes it to your display
*
* 2. Create TWO buffer:
* LVGL will draw the display's content to a buffer and writes it your display.
* You should use DMA to write the buffer's content to the display.
* It will enable LVGL to draw the next part of the screen to the other buffer while
* the data is being sent form the first buffer. It makes rendering and flushing parallel.
*
* 3. Double buffering
* Set 2 screens sized buffers and set disp_drv.full_refresh = 1.
* This way LVGL will always provide the whole rendered screen in `flush_cb`
* and you only need to change the frame buffer's address.
*/
/* Example for 1) */
static lv_disp_draw_buf_t draw_buf_dsc_1;
static lv_color_t buf_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
/* Example for 2) */
static lv_disp_draw_buf_t draw_buf_dsc_2;
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*A buffer for 10 rows*/
static lv_color_t buf_2_1[MY_DISP_HOR_RES * 10]; /*An other buffer for 10 rows*/
lv_disp_draw_buf_init(&draw_buf_dsc_2, buf_2_1, buf_2_1, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
/* Example for 3) also set disp_drv.full_refresh = 1 below*/
static lv_disp_draw_buf_t draw_buf_dsc_3;
static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/
static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*An other screen sized buffer*/
lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * LV_VER_RES_MAX); /*Initialize the display buffer*/
/*-----------------------------------
* Register the display in LVGL
*----------------------------------*/
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set up the functions to access to your display*/
/*Set the resolution of the display*/
disp_drv.hor_res = 480;
disp_drv.ver_res = 320;
/*Used to copy the buffer's content to the display*/
disp_drv.flush_cb = disp_flush;
/*Set a display buffer*/
disp_drv.draw_buf = &draw_buf_dsc_1;
/*Required for Example 3)*/
//disp_drv.full_refresh = 1
/* Fill a memory array with a color if you have GPU.
* Note that, in lv_conf.h you can enable GPUs that has built-in support in LVGL.
* But if you have a different GPU you can use with this callback.*/
//disp_drv.gpu_fill_cb = gpu_fill;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
}
uc/gui-3.98在15年前就网上轻易能下载到了,而且没有内存设备和抗锯齿字体支持的。对目前来说已经太古老了。
还是用这个吧,emWin5.06源代码,组件更多代码更新:
emWin506-Src.7z
搬出我多年前的收藏给楼主助威吧,NEHE OpenGL 教学例程,例程个个精美:
nehegl.zip
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain
以上A配置和RM配置的都支持armv5te,内置none-eabi的newlib库用于生成裸机程序。
能编译linux内核和uboot,但不能编译linux应用程序和rootfs工具集。
深表赞同!
不久的新闻有人微信被封,付出了生命的代价,还不放弃微信。不要过渡依赖微信,要是经营多年的公众号哪天被封搞个鸡儿。
什么平台都不要过渡依赖。那年渣浪被整改,清空了所有用户网盘存的东西,我多年在渣浪积累的无形资产文档都没了。
网友存档
https://info.williamlong.info/2016/04/blog-post_25.html
不要徒方便把自己的无形资产交给平台,搞公众号不如学哇酷站长搞个网站,牢牢拽在自己手里的无形资产。
https://whycan.cn/files/members/4270/22_20200617-0127.png
为什么明明在里面也不能。颜色有什么含义吗
是不是应该这样“./iwlist”
执行mksunxi.exe 时候 报出找不到MSVCR120D.dll,找了个msvcr120d.dll和mksunxi.exe放到一块,弄好了。。。。。
换个版本的mksunxi.exe吧,你这个不是mingw编译的;mingw编译的不会依赖这个dll。
用这个:
mksunxi.7z
可以用类似我开头那种做法,完全可以一次性读完,不需要64字节分组收发嘛,就是不知道为何不对:(
试试看这样写行不?
void sys_spi_flash_read(int addr, void* buf, int count)
{
uint8_t *p = (uint8_t *)buf;
sys_spi_select();
SPI0->MBC = 4;
SPI0->MTC = 4;
SPI0->BCC = 4;
SPI0->TXD = 0x03 | util_rev(addr);
SPI0->TCR |= SPI_TCR_XCH;
while (SPI0->FSR & 0xff) < 4);
read8((uint32_t)&SPI0->RXD);
read8((uint32_t)&SPI0->RXD);
read8((uint32_t)&SPI0->RXD);
read8((uint32_t)&SPI0->RXD);
SPI0->MBC = count;
SPI0->MTC = 0;
SPI0->BCC = 0;
SPI0->TCR |= SPI_TCR_XCH;
while (count > 0) {
if((SPI0->FSR & 0xFF) > 0)
{
*p++ = read8((uint32_t)&SPI0->RXD);
count -= 1;
}
}
sys_spi_deselect();
}
读FIFO时,SPI是停止的;这里的确浪费了传输机会。
不过,count循环中并不会重复发送4字节命令和地址,因为在读取数据时,sys_spi_transfer函数的txbuf参数是NULL,所以循环内的sys_spi_write_txbuf函数会立即返回,没有实际数据发送的。
https://whycan.cn/files/members/1592/2020-05-29_100040.png
我还没用逻辑分析仪测量过。要把这些时间省下来,就只能靠DMA了。
感谢Armstrong的亲临指导,我今天再去测试一下原来代码spi读写的情况,spi频率太高了示波器太烂丢脉冲,不过应该可以发现问题的
原来的代码相当于将总的数据收发切割成64字节成组收发,并且读取rxfifo时候还是spi停止的
64+4字节收发->读rxfiofo,然后再重复这个过程
读FIFO时,SPI是停止的;这里的确浪费了传输机会。
不过,count循环中并不会重复发送4字节命令和地址,因为在读取数据时,sys_spi_transfer函数的txbuf参数是NULL,所以循环内的sys_spi_write_txbuf函数会立即返回,没有实际数据发送的。
上层的flash读函数实际上这样解释:
static int sys_spi_write_then_read(void* txbuf, int txlen, void* rxbuf, int rxlen)
{
// 发送命令+地址
if (sys_spi_transfer(txbuf, NULL, txlen) != txlen)
return -1;
// 连续接收纯数据
if (sys_spi_transfer(NULL, rxbuf, rxlen) != rxlen)
return -1;
return 0;
}
用链接器的redirect功能,把库里的某几个函数旁路掉,自己写函数代替。
或者索性自己写个GUI_DEVICE_API,别用内置<GUIDRV_Lin.h>文件里的驱动就行。
自定义驱动形式如下,有模板的,不难实现,针对内存操作的更简单:
const GUI_DEVICE_API GUIDRV_Template_API = {
//
// Data
//
DEVICE_CLASS_DRIVER,
//
// Drawing functions
//
_DrawBitmap,
_DrawHLine,
_DrawVLine,
_FillRect,
_GetPixelIndex,
_SetPixelIndex,
_XorPixel,
//
// Set origin
//
_SetOrg,
//
// Request information
//
_GetDevFunc,
_GetDevProp,
_GetDevData,
_GetRect,
};
针对tiny200v2的忘了去除lcd屏的pd0+pd12管脚,已修正:
【lichee-nano + tiny200v1】
Tiny200v1_LCD480x272_NS2009A.zip
【tiny200v2】
Tiny200v2_LCD480x272_NS2009A.zip
比如我想从SD NAND(贴片SD卡)里启动,要么在SD NAND 焊到板子上之前将程序烧进去,要么焊到板子上再烧程序上去,这时如果能将DRAM模拟成U盘,直接在电脑上将spl和app拖进去,然后将spl和app烧录进SD NAND,实现程序烧录
嗯,懂了。理论上你可以基于FELinside-f1c100s或者f1c100s-uboot制作出这么个东西来,尚且称它未fel-boot吧。
fel-boot由sunxi-fel送入ddr运行,负责把dram模拟成u盘,等着用户把uboot和linux内核放进“u盘”。但我没搞定usb呢,做不了啊。
我看这东西做起来即使不开源,对别人也是很有用的。
完成同样功能,还有个思路就是自己添加sunxi-fel功能,因为sunxi-fel可以通过usb接口传输一段ARM指令到设备,然后执行它;目前的任何sunxi-fel功能都是这么实现的。可以通过这种方式增加写tf卡和sd-nand的功能;不用模拟成u盘。扩展后的命令形如:
sunxi-fel -p sdnand-write 0 xxx.bin