页次: 1
D1芯片的SVD寄存器文件,有什么好用的工具去看这玩意吗?
keil有所谓的svd文件,就是看寄存器的,但是keil肯定不可能支持riscv啊。
非常感谢,我搜了两天了,都没有找到,难道是关键字不对
我用官方 评估板 tina都没找到,f1c200s里有,但是没看仔细,忘记还有公版这个关键字
晕哥 说:agnd 说:晕啊,买了拆了还能退么?
据说热风枪 吹保修标签可以完整撕下 (逃
可以在tf卡位置怼一下jlink看一下芯片么
http://linux-sunxi.org/images/thumb/0/05/JTAG_MicroSD_UART-front.jpeg/180px-JTAG_MicroSD_UART-front.jpeg
哪里可以搞到这个tf转接板
基本像musb的寄存器,只是寄存器偏移不一样,还有就是中断需要写入才清除中断标志位
musb_programming_guide.pdf
usb主机通道发送数据前,除了设置设备地址,还需要设置端点地址,请问端点地址是在哪里设置
由于spi操作在spl引导和uboot引导的程序中表现出截然不同的反应,我务必要搞明白这个uboot到底做了哪些工作
一直没搞明白这个命令到底是如何启动bin文件的
首先进入fel模式后,0地址上写入了一段称为USB.FEL的spl代码,和我们自定义的eGON.BT0是不同的
我理解的sunxi-fel uboot过程是这样的:
fel读取spl代码,复制除spl header部分的spl代码到sizeof(spl header)地址,然后运行,最后重新返回fel。
从代码上可知此spl做了以下工作:初始化clk,dram,mmu,复制spl代码到dram区(此时spl已经更新过,spl header被vector代替)
接下来解析uboot程序,复制uboot程序到对应dram区,从ih_ep处开始运行
我尝试后汇报结论
还是不行,真的是见鬼了。。。为什么uboot引导的就可以呢,spl引导的就是不行
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();
}
这个非常类似,不过那一个是已经完成的产品
试试看这样写行不?
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
上层的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; }
这两天忙其它事情一直没时间测试,刚刚我测试结果,每64字节收发中间有3.6us停顿,相当于22.5个字节收发,这个开销比我预计的还要大bu shao
F1C100s的SPI模块有64字节接收FIFO和64字节发送FIFO。
上面的代码把count分成多份接收,每份最多接收64字节,这是充分利用接收FIFO;发送同理。
每次往TXD寄存器只写1个字节,没试过你这样往TXD一次写4字节。
其实即便一次写4字节,也不能提高速度的;因为处理器写1字节的时间远小于SPI传送1字节的时间,所以最终瓶颈还是在SPI传输上。
感谢Armstrong的亲临指导,我今天再去测试一下原来代码spi读写的情况,spi频率太高了示波器太烂丢脉冲,不过应该可以发现问题的
原来的代码相当于将总的数据收发切割成64字节成组收发,并且读取rxfifo时候还是spi停止的
64+4字节收发->读rxfiofo,然后再重复这个过程
由于spi频率是ahb的1/4,因此一个字节spi相当于32次ahb操作, fifo读刚好等效2个字节的收发
没看懂这个问题,我记得没错uboot的spl不就是burst么,一次性就读取完了并非一个个发地址阿。
还是你说的是DMA的burst?双线读取我试过内核驱动没什么问题,理论上也能在spl中用。
以下是Armstrong兄的例程代码,读取flash的具体过程,应该也是xboot的
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;
}
明显这里是有多次spi burst的
请问楼主有没有遇到spi在用户程序可行,spl代码不行的问题
向这个代码,能不能看出有什么问题?
void sys_spi_flash_read(int addr, void* buf, int count)
{
uint8_t *p = (uint8_t *)buf;
SPI0->TXD = 0x03 | util_rev(addr);
SPI0->MBC = 4 + count;
SPI0->MTC = 4;
SPI0->BCC = 4;
SPI0->TCR |= SPI_TCR_XCH;
while (count > 0) {
if((SPI0->FSR & SPI_FSR_RXFIFO_CNT) >= 1)
{
*p++ = *(uint8_t *)&SPI0->RXD;
count -= 1;
}
}
}
坛子里,f1c100s例程操作spiflash的做法都是都是通过spi单次收发的方式模拟03命令序列,这种做法很低效,坛子里很多网友说过这个问题了
我仔细研读手册,发现f1c100s支持spi突发模式,和双线模式,如果能用上这两个特点的话,程序加载会增长一倍以上
Armstrong兄的例程spiflash加载程序只需要不到1秒就能显示画面,如果再优化一下,估计不到0.5秒就可以了,真正做到秒开
现在的问题,以下代码在用户程序中是完好的,在spl代码中却不行,不知道谁能发现其中奥妙?
void sys_spi_flash_read(int addr, void* buf, int count)
{
uint8_t *p = (uint8_t *)buf;
SPI0->TXD = 0x03 | util_rev(addr);
SPI0->MBC = 4 + count;
SPI0->MTC = 4;
SPI0->BCC = 4;
SPI0->TCR |= SPI_TCR_XCH;
while (count > 0) {
if((SPI0->FSR & SPI_FSR_RXFIFO_CNT) >= 1)
{
*p++ = *(uint8_t *)&SPI0->RXD;
count -= 1;
}
}
}
Wait State意思不知道。
Burst Length大约是每次传输数据,在总线上连续传几个“Data Width”那么大的数据。
对于从内存到内存,Burst Length设为4直接就可以用。
对于从内存到外设或外设到内存的DMA,如果Burst Length设为4,外设的FIFO一般有trigger level也要对应改。比如trigger level默认为1,表示FIFO里只要有1个数据就发送DRQ,让DMA来拷走。当Burst Length为4,trigger level也要>=4。
反过来,如果是从内存到外设拷数据的,FIFO的trigger level需要 <= (FIFO总长度 - 4)。
这个Burst Length是不是应该理解为一次总线占用,Burst Length次总线传输,实际等效为Burst Length * Data Width
我记得stm32后续版本(非f1系列)的dma就有这种概念
我也晒晒装备,居家办公,自如的小房子。
这桌子不错,有购买链接吗
BROM的责任就是依次寻找合法的引导程序, TF -> SPI NOR -> SPI NAND -> BROM USB
找到之后就加载到内部 32K SRAM
然后把PC指针指向 SRAM因为iram大小的限制,所以需要多级跳转
如果足够大,就跟单片机一样了,直接跑了
SRAM的造价应该是很昂贵的
速度也最快
IRAM里面可以放向量表,这样也会比DDR 更快一些
晕哥,f1c100s有没有这个iram,越发看不明白了,boot0这个代码是不是就是BROM
参考手册Memory Mapping章节:
Module Address (It is for Cluster CPU) Size (byte)
BROM 0x0000 0000---0x0000 7FFF 32K
SRAM A 0x0001 0000---0x0001 9FFF 40K
是不是SRAM A 指代iram,那应该是有40k啊
我就不多说的,你懂的,下载后就别分享了,请移步
https://download.csdn.net/download/sjj_11/12051955
楼主,能否再次分享下之前分析过的f1c100s的keil工程,你之前的帖子已经找不到了
我的qq 543488289
刚刚用摄像头扫了一下二维码, 其实是一个网址:
您好晕哥,请问您有下载wps_90网友的帖子里的工程项目吗?这个帖子被删除了,我希望能参考下他的keil项目
批量价GD会比STM32便宜一点点, 几片片的样品价就未必了.
虽然我用ST, 但是还是希望大家支持国产, 支持兆易创新
这样 ST 的价格才不会那么嚣张, 哈哈。
STM32F103RBT6: https://item.szlcsc.com/9244.html
GD32F103RBT6: https://item.szlcsc.com/79097.html
BLM32F103RBT6: https://item.szlcsc.com/91598.html就像我用苹果手机, 不过还是支持华为小米, 有了搅局者,苹果才不会那么嚣张。
兄弟你这看法有点意思,我支持但我就是不用哈哈哈
页次: 1