页次: 1
PMOS开关电路,很常见呀。不过要注意VGS数值不要超过12V
https://whycan.com/files/members/1798/屏幕截图_20240722_122744.png
这电路我也常用 不过没有c3和r6 这种开关管一般cg不小 有要求开关速度的场合可以调r2和r8
另外r4我通常用10k以上的 基本周围有啥电阻就用啥 减少规格型号
用 Swap 能对付对付不?
https://3dpandme.com/2022/08/13/tutorial-orange-pi-zero-plus-klipper-install/
someone did it with a 256MB board.
全志带CSI的SOC都会有类似这样的指标,例如V851s的
Video Input
ISP with maximum resolution of 2560 x 1440, up to 4Mbps @ 30fps
10-bit Parallel CSI interface up to 4x 720p30
4-lane MIPI CSI input or two 2-lane MIPI CSI inputs up to 4Mbps @ 30 fps
请问大神,抓静止图像时是否可以超过4M像素,毕竟在CSI寄存器里图像尺寸是13位的。
我想上12M的传感器IMX577,视频时差不多FHD(2 Binning),有拍照时能抓12M就好。
@david
coremark/mhz对比, esp32c3比esp32单核还高,所以riscv架构比lx6优秀。总的coremark,160mhz的esp32c3差90就赶上240mhz的单核esp32了。
https://whycan.com/files/members/1315/202438.png
S2为什么还会慢些 难道Lx7还不如Lx6
这种并联差分总线 应该只需要在终端做终结
这两块代码供参考
inline static void f1c100s_debe_set_address(struct lcd_f1c100s_device *dev)
{
struct f1c100s_debe_reg_t * debe = (struct f1c100s_debe_reg_t *)(dev->virtdebe);
write32((rt_uint32_t)&debe->layer0_addr_low32b, (uint32_t)(dev->lcd_info.framebuffer[fb_bank? 1:0]) << 3); // address in bits 3->8bit(byte address)
write32((rt_uint32_t)&debe->layer0_addr_high4b, (uint32_t)(dev->lcd_info.framebuffer[fb_bank? 1:0]) >> 29);
//write32((rt_uint32_t)&debe->layer0_addr_low32b, (uint32_t)vram << 3);
//write32((rt_uint32_t)&debe->layer0_addr_high4b, (uint32_t)vram >> 29);
}
static inline void f1c100s_debe_set_mode(struct lcd_f1c100s_device *dev)
{
struct f1c100s_debe_reg_t * debe = (struct f1c100s_debe_reg_t *)(dev->virtdebe);
rt_uint32_t val;
rt_uint32_t mode_val;
// enable debe, layer0 but set the reset
mode_val = (1<<8) | (1<<0);
write32((rt_uint32_t)&debe->mode, mode_val);
write32((rt_uint32_t)&debe->disp_size, (((dev->lcd_info.height) - 1) << 16) | (((dev->lcd_info.width) - 1) << 0));
write32((rt_uint32_t)&debe->layer0_size, (((dev->lcd_info.height) - 1) << 16) | (((dev->lcd_info.width) - 1) << 0));
f1c100s_debe_set_address(dev);
//write32((rt_uint32_t)&debe->layer0_addr_low32b, (uint32_t)(dev->lcd_info.framebuffer) << 3); // address in bits 3->8bit(byte address)
//write32((rt_uint32_t)&debe->layer0_addr_high4b, (uint32_t)(dev->lcd_info.framebuffer) >> 29);
//val = (1<<2); // swap B R, i.e. BGR
val = 0;
if (dev->lcd_info.bits_per_pixel == 16)
{
val |= (0x05 << 8);
write32((rt_uint32_t)&debe->layer0_stride, ((dev->lcd_info.width) << 4)); // line width in bits 5->32bit, 4->16bit
}
else // FIXME: default 32bit RGB
{
val |= (0x09 << 8);
write32((rt_uint32_t)&debe->layer0_stride, ((dev->lcd_info.width) << 5)); // line width in bits 5->32bit, 4->16bit
}
write32((rt_uint32_t)&debe->layer0_attr1_ctrl, val);
// start debe
mode_val |= (1 << 1);
write32((rt_uint32_t)&debe->mode, mode_val);
}
static inline void f1c100s_tcon_set_mode(struct lcd_f1c100s_device *dev)
{
struct f1c100s_tcon_reg_t * tcon = (struct f1c100s_tcon_reg_t *)dev->virttcon;
int bp, total;
rt_uint32_t val;
val = read32((rt_uint32_t)&tcon->ctrl);
val &= ~(0x1 << 0);
write32((rt_uint32_t)&tcon->ctrl, val);
val = (dev->timing.v_front_porch + dev->timing.v_back_porch + dev->timing.v_sync_len);
write32((rt_uint32_t)&tcon->tcon0_ctrl, (1 << 31) | ((val & 0x1f) << 4));
// val = clk_get_rate(dev->clktcon) / dev->timing.pixel_clock_hz;
// rt_kprintf("get_video_pll_clk:%d\n", get_video_pll_clk());
val = get_video_pll_clk() / dev->timing.pixel_clock_hz;
write32((rt_uint32_t)&tcon->tcon0_dclk, (0xf << 28) | (val << 0));
write32((rt_uint32_t)&tcon->tcon0_timing_active, ((dev->lcd_info.width - 1) << 16) | ((dev->lcd_info.height - 1) << 0));
bp = dev->timing.h_sync_len + dev->timing.h_back_porch;
total = dev->lcd_info.width + dev->timing.h_front_porch + bp;
write32((rt_uint32_t)&tcon->tcon0_timing_h, ((total - 1) << 16) | ((bp - 1) << 0));
bp = dev->timing.v_sync_len + dev->timing.v_back_porch;
total = dev->lcd_info.height + dev->timing.v_front_porch + bp;
write32((rt_uint32_t)&tcon->tcon0_timing_v, ((total * 2) << 16) | ((bp - 1) << 0));
write32((rt_uint32_t)&tcon->tcon0_timing_sync, ((dev->timing.h_sync_len - 1) << 16) | ((dev->timing.v_sync_len - 1) << 0));
write32((rt_uint32_t)&tcon->tcon0_hv_intf, 0);
write32((rt_uint32_t)&tcon->tcon0_cpu_intf, 0);
if(dev->lcd_info.bits_per_pixel == 24 || dev->lcd_info.bits_per_pixel == 16 || dev->lcd_info.bits_per_pixel == 32)
{
write32((rt_uint32_t)&tcon->tcon0_frm_seed[0], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[1], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[2], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[3], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[4], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[5], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_table[0], 0x01010000);
write32((rt_uint32_t)&tcon->tcon0_frm_table[1], 0x15151111);
write32((rt_uint32_t)&tcon->tcon0_frm_table[2], 0x57575555);
write32((rt_uint32_t)&tcon->tcon0_frm_table[3], 0x7f7f7777);
// 最高支持18位
write32((rt_uint32_t)&tcon->tcon0_frm_ctrl, (dev->lcd_info.bits_per_pixel == 24 || dev->lcd_info.bits_per_pixel == 32) ? ((1 << 31) | (0 << 4)) : ((1 << 31) | (5 << 4)));
}
val = (1 << 28);
if(!dev->timing.h_sync_active)
val |= (1 << 25);
if(!dev->timing.v_sync_active)
val |= (1 << 24);
if(!dev->timing.den_active)
val |= (1 << 27);
if(!dev->timing.clk_active)
val |= (1 << 26);
write32((rt_uint32_t)&tcon->tcon0_io_polarity, val);
write32((rt_uint32_t)&tcon->tcon0_io_tristate, 0);
}
本以为RGB565的时候每个像素2字节?不过初步设置后如果按照2字节分配FB,只有一半显示,而且显示的还是4字节每像素的样子,例如memset设置成0x80显示的是灰色。
用的这款源码 https://github.com/vvhh2002/lv7_rtthread_f1c100s.git
小改 使用#define LCD_FORMAT RTGRAPHIC_PIXEL_FORMAT_RGB565P而已
相关寄存器设置部分是这样
if(dev->lcd_info.bits_per_pixel == 24 || dev->lcd_info.bits_per_pixel == 16 || dev->lcd_info.bits_per_pixel == 32)
{
write32((rt_uint32_t)&tcon->tcon0_frm_seed[0], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[1], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[2], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[3], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[4], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_seed[5], 0x11111111);
write32((rt_uint32_t)&tcon->tcon0_frm_table[0], 0x01010000);
write32((rt_uint32_t)&tcon->tcon0_frm_table[1], 0x15151111);
write32((rt_uint32_t)&tcon->tcon0_frm_table[2], 0x57575555);
write32((rt_uint32_t)&tcon->tcon0_frm_table[3], 0x7f7f7777);
// 最高支持18位
write32((rt_uint32_t)&tcon->tcon0_frm_ctrl, (dev->lcd_info.bits_per_pixel == 24 || dev->lcd_info.bits_per_pixel == 32) ? ((1 << 31) | (0 << 4)) : ((1 << 31) | (5 << 4)));
}
还有
/**
* @brief 设置DEBE模式(DEBE控制显示尺寸和显示缓冲地址)
*
* @param dev 设备指针
*/
static inline void f1c100s_debe_set_mode(struct lcd_f1c100s_device *dev)
{
struct f1c100s_debe_reg_t * debe = (struct f1c100s_debe_reg_t *)(dev->virtdebe);
rt_uint32_t val;
val = read32((rt_uint32_t)&debe->mode);
val |= (1 << 0);
write32((rt_uint32_t)&debe->mode, val);
write32((rt_uint32_t)&debe->disp_size, (((dev->lcd_info.height) - 1) << 16) | (((dev->lcd_info.width) - 1) << 0));
write32((rt_uint32_t)&debe->layer0_size, (((dev->lcd_info.height) - 1) << 16) | (((dev->lcd_info.width) - 1) << 0));
write32((rt_uint32_t)&debe->layer0_stride, ((dev->lcd_info.width) << 5));
write32((rt_uint32_t)&debe->layer0_addr_low32b, (uint32_t)(dev->lcd_info.framebuffer) << 3);
write32((rt_uint32_t)&debe->layer0_addr_high4b, (uint32_t)(dev->lcd_info.framebuffer) >> 29);
//write32((rt_uint32_t)&debe->layer0_attr1_ctrl, 0x09 << 8);
write32((rt_uint32_t)&debe->layer0_attr1_ctrl, (0x09 << 8)|(1<<2));
//write32((rt_uint32_t)&debe->layer0_attr1_ctrl, 0x0A << 8);
val = read32((rt_uint32_t)&debe->mode);
val |= (1 << 8);
write32((rt_uint32_t)&debe->mode, val);
val = read32((rt_uint32_t)&debe->reg_ctrl);
val |= (1 << 0);
write32((rt_uint32_t)&debe->reg_ctrl, val);
val = read32((rt_uint32_t)&debe->mode);
val |= (1 << 1);
write32((rt_uint32_t)&debe->mode, val);
}
以上都是大神原来的代码,我没改动。
感觉是不是RGB565的哪个寄存器没设置到位?要是RGB565用不了2字节每像素的话就没有意义了。
我上份imx586的资料吧 这个是48mp的IMX586-AAJH5-C_0.0.1_Datasheet(1).pdf
我们(sipeed)与全志(Allwinner)深度合作推广D1, 会赠送一批D1开发板给主线linux开发者~
https://whycan.com/files/members/456/微信图片_20210428181009.jpg
目前已率先在D1上跑起来了的debian:
https://whycan.com/files/members/456/微信图片_20210427141420.png
希望更多用户参与到D1的主线化开发中~
荔枝要出新品吗
我上个pdf版本的 个人对这货不看好 喊了一堆口号 连个结构框图都没有 还不如全志的文档
HCSEMI_B200 Brief Datasheet190827.pdf
david 说:这事能否硬件上解决 功放电源上电时软启动
f1c耳机输出功率多大 能带个小扬声器做音效么?目前我加了个功放 还没调到那里 DAC接的是HPR
我接的是耳机,可以很好驱动起来。较小扬声器可能问题不大
因为是直驱耳机,所以不知道去除上电璞声音一般是怎么去除的
上电后量下C1和C2两端的电压 如果电容可以去掉直接用电阻耦合的话 隔直电容两端电压应该基本为0
如果不为0 量下HPL,HPR对HPCOM的电压,如果HPR和HPL对HPCOM的电压是一致的 有可能就是HPCOM偏置电压没设好,看看是要调高还是调低 在HPCOM,HPCOMFB和地或电源间接个点位器 看看能否调偏置电压。
如果软件上能解决的话看看有没有上电时序可以用的 也就是用一些小脉冲逐渐让C1和C2充电
PS HPCOM电压应该是AVCC的一半 先量这个电压对不对
体积确实小 电源用一般适配器吗
这芯片貌似没有图像传感器接口
https://pic4.zhimg.com/v2-f7da598994ef49c5f9eaa5e16b4ae220_1440w.jpg?source=172ae18b
SSD201/SSD202芯片芯片规格:· A7双核1.2GHz,内置DDR2-64MByte /DDR3-128MByte;
· 支持MIPI/RGB接口点屏,支持FHD(1920*1080)高清屏;
· 内置硬件2D图形加速,支持硬件90度转屏;
· 内置双MAC,内置一个PHY,支持双100M以太网接口,性价比高;
· 内置H.264/H.265硬解码,支持FHD@60fps;
· 支持MJPEG编码FHD(1920*1080)@15fps;
· 内置codec芯片,无需外挂codec,支持语音对讲;
· 支持离线语音关键字识别,无需外加任何芯片;
· 支持2路模拟mic,支持4路数字mic接口;
· 支持2路USB2.0 Host,支持外挂WIFI芯片;
· 配套SigmaStar WIFI芯片,性能高,有自定义优化协议,实现级联,空旷传输达500米距离。
· QFN128封装,PCB可以走2层板。
· 芯片采用linux操作系统,3s快速开机,系统成熟稳定。
现在遇到个非常严重的问题,那就是这个CSI好像还是彻底不工作,清大佬们给帮忙看下啥问题,
#include <rtthread.h>
#include <rtdevice.h>
#include <rthw.h>
#include "iomem.h"
#include "reg-ccu.h"
#include "drv_clock.h"
#include "drv_gpio.h"
#include "interrupt.h"
#include "drv_csi.h"
#ifdef CSI_DEBUG
#define CSI_DBG(...) rt_kprintf("[CSI]"),rt_kprintf(__VA_ARGS__)
#else
#define CSI_DBG(...)
#endif
#define CSI_BASE_ADDR (0x01CB0000)
#define CSI_CCU_BUS_SOFT_RST_BASE (F1C100S_CCU_BASE | CCU_BUS_SOFT_RST1)
#define CSI_CCU_BUS_CSI_CLK_BASE (F1C100S_CCU_BASE | CCU_CSI_CLK)
#define CSI_CCU_BUS_SOFT_RST_BIT (1 << 8)
#define RAW_STREAM 0
#define PASS_THROUGH 0
#define VREF_POL 1
#define HREF_POL 1
#define CLK_POL 1
#define VS_INT 0x80
#define FD_INT 0x02
#define CD_INT 0x01
#define HOR_START 2
#define VER_START 2
#define CSI ((struct csi_reg_struct *) CSI_BASE_ADDR)
#define CSI_BUF_SIZE (1280+4)*720
uint8_t pix_buf[CSI_BUF_SIZE];
void csi_set_size(int x, int y)
{
CSI -> hsize = ((x&0x1fff) << 16) | HOR_START;
CSI -> vsize = ((y&0x1fff) << 16) | VER_START;
CSI -> buf_len = (x&0x1fff);
}
void csi_setup()
{
// if (!CSI) return -RT_ENOSYS;
// return 0;
}
#define DBUF_EN 0 // disable double buffering for the momen
void csi_dump(void)
{
int i;
rt_kprintf("CSI Regs\n");
for(i=0; i<=0x48; i+=4)
{
volatile uint32_t *ptr;
ptr = (volatile uint32_t *)(CSI_BASE_ADDR + i);
rt_kprintf("0x%02X 0x%08X\n", i, *ptr);
}
}
int csi_test(void)
{
int i;
uint32_t sum;
for(i=0; i<CSI_BUF_SIZE; i++) pix_buf[i] = 0;
csi_set_size(1280, 720);
CSI -> fifo0_bufa = (uint32_t)pix_buf;
CSI -> fifo0_bufb = (uint32_t)pix_buf;
CSI -> buf_ctl = DBUF_EN; // FIXME
//CSI -> int_en = 1; // enable CD_INT_EN
CSI -> int_en = 0; // not using INT
CSI -> cap = 0x01; // start single capture
rt_thread_delay(RT_TICK_PER_SECOND);
rt_kprintf("CSI capture ");
if (CSI -> int_sta & 0x01)
{
rt_kprintf("OK\n");
}
else
{
rt_kprintf("FAILED\n");
csi_dump();
}
sum = 0;
for(i=0; i<CSI_BUF_SIZE; i++) sum += pix_buf[i];
rt_kprintf("SUM: 0x%08X\n", sum);
return 0;
}
MSH_CMD_EXPORT(csi_test, csi_test);
void csi_irq_handle(int irqno, void *param)
{
CSI -> int_sta = 0;
}
int rt_hw_csi_init(void)
{
if (video_set_pll_clk(96000000) == RT_EOK)
{
rt_kprintf("Video clock ok\n");
}
else
{
rt_kprintf("Video clock failed 0x%08X\n", CCU->pll_video_ctrl);
}
// Set GPIO
gpio_set_func(GPIO_PORT_E, GPIO_PIN_0, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_1, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_2, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_3, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_4, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_5, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_6, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_7, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_8, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_9, IO_FUN_1);
gpio_set_func(GPIO_PORT_E, GPIO_PIN_10, IO_FUN_1);
gpio_set_pull_mode(GPIO_PORT_E, GPIO_PIN_0, PULL_DOWN); // HSYNC
gpio_set_pull_mode(GPIO_PORT_E, GPIO_PIN_1, PULL_DOWN); // VSYNC
gpio_set_pull_mode(GPIO_PORT_E, GPIO_PIN_2, PULL_DOWN); // PCLK
// enable CSI clock
bus_gate_clk_enalbe(CSI_GATING);
// set CSI MCLK
write32(CSI_CCU_BUS_CSI_CLK_BASE, 1<<15);
// release the reset
write32(CSI_CCU_BUS_SOFT_RST_BASE, read32(CSI_CCU_BUS_SOFT_RST_BASE)|CSI_CCU_BUS_SOFT_RST_BIT);
//csi_dump();
// setup CSI registers
CSI -> en = 1;
//csi_dump();
// Raw data
CSI -> cfg = (RAW_STREAM << 20) | (PASS_THROUGH << 16) | (VREF_POL << 2)
| (HREF_POL << 1) | CLK_POL;
CSI -> scale = (0xf << 24) | 0xffff; // take all the pixels
// install the ISR
//rt_hw_interrupt_install(CSI_INTERRUPT, csi_irq_handle, NULL, "USB");
//rt_hw_interrupt_umask(CSI_INTERRUPT);
return 0;
}
//INIT_DEVICE_EXPORT(rt_hw_csi_init);
目前运行记录是这样的
\ | /
- RT - Thread Operating System
/ | \ 4.0.2 build Sep 22 2020
2006 - 2019 Copyright by rt-thread team
[I/I2C] I2C bus [i2c0] registered
periph_get_pll_clk:600000000
cpu_get_clk:408000000
ahb_get_clk:200000000
apb_get_clk:100000000
ddr_get_pll_clk:312000000
video_get_pll_clk:96000000
Video clock ok
msh >csi_test
CSI capture FAILED
CSI Regs
0x00 0x00000001
0x04 0x00000007
0x08 0x00000000
0x0C 0x00000000
0x10 0x800200E4
0x14 0x800200E4
0x18 0x00000000
0x1C 0x00000000
0x20 0x00000000
0x24 0x00000000
0x28 0x00000000
0x2C 0x00000000
0x30 0x00000000
0x34 0x00000000
0x38 0x00000000
0x3C 0x00000000
0x40 0x05000002
0x44 0x02D00002
0x48 0x00000500
SUM: 0x00000000
msh >
把USB core 从0xA0到0x3FF的地址空间扫了一遍,发现有些寄存器有内容,可能是DMA的,具体内容不详,
0x00C0 0x33DE
0x00C2 0x000B
0x00C4 0x0FFF
0x00C6 0x0FFF
0x00C8 0x00FF
0x00D0 0x0FFF
0x00D2 0x0FFF
0x00D4 0x0FFF
0x00D6 0x0FFF
0x00D8 0x000F
0x00E0 0x01FF
0x00E2 0x0F1F
0x00E4 0x0F00
扫描代码
for(i= 0xa0; i<0x3ff; i+=2)
{
dt = USBC_Readw(USBC0_BASE + i);
if (dt != 0)
{
rt_kprintf("0x%04X 0x%04X\n", i, dt);
}
else
{
USBC_Writew(0xfff, USBC0_BASE + i);
dt = USBC_Readw(USBC0_BASE + i);
if (dt != 0)
{
rt_kprintf("0x%04X 0x%04X\n", i, dt);
}
}
}
扫完之后USB就不好用了,要重新断电,肯定是有改动的。
Performance Tuning
usb.h里加入适合RTT的头文件:
#ifdef USB_USE_RTT
# include "rtthread.h"
# define usbprint(...) rt_kprintf(__VA_ARGS__)
//# define usbprint(...) // do not print at all
#else
# include <printf.h>
# define usbprint printf
#endif
微微凉的代码里用了好多printf,连中断里都有,应该是为了调试方便,不过会影响性能。根据需要选择usbprint的宏定义。TODO:应该加debug level选项,有些信息还是要dump的。
将USB的Class和SubClass都改为0x02,这样可以自动使用win10内置的驱动,不需要手工配置。
#define USB_CDC_CLASS 0x02 // for using Win10 default driver
#define USB_CDC_SUBCLASS 0x02
static USB_DeviceDescriptor cdc_devDesc =
{
sizeof(USB_DeviceDescriptor),
DEVICE_DESCRIPTOR, //1
#if DWC_FORCE_SPEED_FULL
0x0111, // Version 1.11
#else
0x0200, // Version 2.0
#endif
USB_CDC_CLASS, // bDeviceClass
USB_CDC_SUBCLASS, // bDeviceSubClass
0x00,
64, /* Ep0 FIFO size */
USB_CDC_VID, // VID
USB_CDC_PID, // PID
USB_FUNCTION_RELEASE_NO,
0x01, //iManufacturer;
0x02, //iProduct;
0x00,
0x01
};
static USB_DeviceDescriptor cdc_devFullSpeedDesc =
{
sizeof(USB_DeviceDescriptor),
DEVICE_DESCRIPTOR, //1
0x0111, //Version 1.11
USB_CDC_CLASS,
USB_CDC_SUBCLASS,
0x00,
64, /* Ep0 FIFO size */
USB_CDC_VID,
USB_CDC_PID,
USB_FUNCTION_RELEASE_NO+1,
0x01, //iManufacturer;
0x02, //iProduct;
0x00,
0x01
};
Bug & Fix:
高速USB居然没打开,连主机后只跑到12M。加入 USBC_REG_set_bit_b(USBC_BP_POWER_D_HIGH_SPEED_EN, USBC_REG_PCTL(USBC0_BASE)); 目前暂时放在void USBC_PhyConfig(void)里,不过那个好像是USB Core的选项。
CDC串口指令后要等配置信息,原来的代码只检查一次,所以没有printf的延时,就会因为等不到配置信息而没有相应,导致串口打不开。在static void class_setup_request(USB_DeviceRequest* req_data)里做如下修改,
while(Timeout--)
{
len = USBC_ReadLenFromFifo(USBC_EP_TYPE_EP0);
if(len == 7)
{
usbprint("set_line_coding:readlen:%d\n",len);
unsigned char tmp[7];
usb_device_read_data_ep_pack(0,tmp,7);
set_line_codingstatic_ext(tmp);
usb_device_read_data_status_ep0(1);
usb_device_set_ep0_state(EP0_IDLE);
port_line_coding_flag = 0;
break;
}
}
if (!Timeout)
{
rt_kprintf("timeout, len %d\n", len);
}
最近要用F1C100S做个USB的项目,Linux虽然是标准选项,但是想先试下RTT,毕竟项目不复杂,用RTT简洁很多,启动速度也快。于是整合了若干大神在F1C100S做的开创成果,包括:
裸奔USB第一人: https://whycan.com/t_1810.html
基于Keil的开发框架: https://whycan.com/t_5205.html
RTT相关: https://whycan.com/t_4942.html https://whycan.com/t_3958.html
Linux参考: https://whycan.com/t_3087.html
目标是在RTT上获得高效稳定的CDC Device方案。
这代码用Keil的MDK编译很不顺,用裸奔的gcc编译RTT也有些问题,用RTT开发环境自带的gcc就好,注意修改Keil项目的工具设置。用Keil的好处是可以直接下到DRAM里,并且可以设置断点,查看内存,但是变量显示好像gcc跟Keil衔接还有问题,变量显示的不对。
Dump了寄存器,看看有啥不对的,
------ USB PHY Clock -------
USBPHY_CLK_REG:0x00000003
BUS_CLK_GATE0_REG:0x01304000
BUS_CLK_RST_REG:0x01304000
------ USB PHY Reg -------
USBC_REG_ISCR:0x5303fc00
USBC_REG_PHYCTL:0x00000000 这些是没实现么 数据都是0
USBC_REG_PHYBIST:0x00000000
USBC_REG_PHYTUNE:0x00000000
USBC_REG_CSR:0x00000000
------ USB Core Reg -------
USBC_REG_FADDR:0x0b
USBC_REG_PCTL:0x70 这个基本意思是开启高速USB使能,并且已经联机在高速USB
USBC_REG_INTTx:0x0000 中断这些还要再研究
USBC_REG_INTRx:0x0000
USBC_REG_INTTxE:0x0007
USBC_REG_INTRxE:0x0002
USBC_REG_INTUSB:0x0308
USBC_REG_INTUSBE:0x0027
USBC_REG_FRNUM:0x065d
USBC_REG_VEND0:0x00
USBC_REG_EPIND:0x0001
USBC_REG_TXMAXP:0x0200
USBC_REG_RXMAXP:0x0200
USBC_REG_TXFIFOSZ:0x07 这是说有1KByte的FIFO但是还没设置成double buffer
USBC_REG_RXFIFOSZ:0x07
USBC_REG_TXFIFOAD:0x0080 FIFO的内存地址,0x80*8 = 0x400, 就是1K了,BTW,谁知道System Config那个模块是怎么用的,到处没资料
USBC_REG_RXFIFOAD:0x0000
USBC_REG_DEVCTL:0x99 工作在Device模式,VBUS有效
USBC_REG_CONFIGDATA:0xde 内核配置情况:包合并,小头机,高速ISO,动态FIFO,软件连接
------ USB Misc -------
USBC_REG_PMU_IRQ:0x0043031a
目前的情况是,在数据量比较大时,回传的数据,就是IN数据,会偶尔出现丢包的情况。
传输代码如下,已经简单加入同步机制,抄的代码,不知道对不对。
u32 USBC_WritePacket(void *fifo, u32 cnt, void *buff)
{
u32 len = 0;
u32 i32 = 0;
u32 i8 = 0;
u8 *buf8 = 0;
u32 *buf32 = 0;
volatile int Timeout = 10000000;
while((USBC_Dev_IsWriteDataReady(USBC_EP_TYPE_TX))&&(--Timeout)); // wait for last write to clear
if (!Timeout)
{
rt_kprintf("*");
return 0;
}
//--<1>-- adjust data
buf32 = buff;
len = cnt;
i32 = len >> 2;
i8 = len & 0x03;
//--<2>-- deal with 4byte part
while (i32--)
{
USBC_Writel(*buf32++, fifo);
}
//--<3>-- deal with no 4byte part
buf8 = (u8 *)buf32;
while (i8--) {
USBC_Writeb(*buf8++, fifo);
}
return len;
}
另外测试代码
#elif (CDC_TEST_SEL == CDC_TEST_IN)
uint8_t test_buf[512];
uint16_t test_len = *((uint16_t *)pdat);
//rt_kprintf("test len: %d\n", test_len);
int i;
for(i=0; i<512; i++) test_buf[i] = (i&0xff);
while(test_len)
{
if (test_len > 512)
{
usb_device_write_data(1,test_buf,512);
test_len -= 512;
}
else
{
usb_device_write_data(1,test_buf,test_len);
test_len = 0;
}
}
#endif
目前小改一下的,
u32 USBC_WritePacket(void *fifo, u32 cnt, void *buff)
{
u32 len = 0;
u32 i32 = 0;
u32 i8 = 0;
u8 *buf8 = 0;
u32 *buf32 = 0;
volatile int Timeout = 10000000;
while((USBC_Dev_IsWriteDataReady(USBC_EP_TYPE_TX))&&(--Timeout)); // wait for last write to clear
if (!Timeout)
{
rt_kprintf("*");
return 0;
}
//--<1>-- adjust data
buf32 = buff;
len = cnt;
i32 = len >> 2;
i8 = len & 0x03;
//--<2>-- deal with 4byte part
while (i32--)
{
USBC_Writel(*buf32++, fifo);
}
//--<3>-- deal with no 4byte part
buf8 = (u8 *)buf32;
while (i8--) {
USBC_Writeb(*buf8++, fifo);
}
return len;
}
感谢楼上的填坑, 终于从FLASH中启动能正常使用USB CDC类了, 在使用过程中发现 只要将USB的调试打印信息屏蔽, 然后USB就不正常了。最后发现是在usb_cdc.c文件中有只要将usbprint("set_line_coding\n")与usbprint("get_line_coding\n")这两行注释屏蔽USB就不正常。猜想可能是由于屏蔽那两行打印信息导致后面不能正常操作某些寄存器。 哎USB太复杂了, 只能倚靠前辈的力量。
usb_cdc.c 这样改,
static void class_setup_request(USB_DeviceRequest* req_data)
{
unsigned char bRequest = req_data->bRequest;
int Timeout = USB_TIMEOUT_COUNT;
int len;
//u32 des_length,data_tmp[26],data_flag;
if(bRequest == 0x20)//set_line_coding
{
//set_line_coding(handle, req_data);
//usb_device_read_data_status_ep0(0);
usbprint("set_line_coding\n");
port_line_coding_flag = 1;
while(Timeout--)
{
len = USBC_ReadLenFromFifo(USBC_EP_TYPE_EP0);
if(len == 7)
{
usbprint("set_line_coding:readlen:%d\n",len);
unsigned char tmp[7];
usb_device_read_data_ep_pack(0,tmp,7);
set_line_codingstatic_ext(tmp);
usb_device_read_data_status_ep0(1);
usb_device_set_ep0_state(EP0_IDLE);
port_line_coding_flag = 0;
break;
}
}
if (!Timeout)
{
rt_kprintf("timeout, len %d\n", len);
}
//GD_USB_Set_CSR0L(0x88);
}
发现自己走了好多弯路,其实裸跑的Keil工程的启动文件可以直接嫁接到RTT的启动文件中,之前一直没成功是想太多了,现把我能用的代码放上,供参考。
开发环境:windows
开发工具:RT ENV
RT版本: 4.0.2
测试工程基于RT源码中BSP中的allwinner_tina系列,将附件解压至BSP目录下,scons一下即可完成编译。下载程序时,让F1C100s进入FEL模式,运行批处理flashtospi.bat即可完成程序下载。
如果要用在别的工程中,只需进行如下操作:(均指在ENV开发工具和RT源码结构中)
1.拷贝bootloader文件夹、tools文件夹、flashtospi.bat文件到对应工程目录下
2.用示例代码的link.lds链接文件替换掉工程的链接文件
3.用示例代码的libcpu\start_gcc.S启动文件替换掉工程的启动文件
进行如上操作后即可实现秒启动APP了(当然也不是秒启动,FEL过程还是费了大概0.几秒的时间,但相对用RT boot来说就快多了)
allwinner_tina_autoboot.rar
楼主辛苦,这代码很有参考价值,谢谢。不过这套代码只支持gcc对吧,我用keil的时候说Please make sure your toolchains is GNU GCC!。
https://whycan.cn/files/members/457/usbAn.png
我也做了一个,把usb换成了typeC。
这板开源还是卖钱?有订购链接么?
按晕哥的提示,参考了 彩虹派V3s开发板原理图 和 A10 LCD 调试手册 这两份资料,画了块RGB屏转 i80屏的转接板。等打样回来慢慢调~
(图上丝印1脚和常用的线序是反的)
板子画的不错,祝早日调通。
白嫖: https://github.com/aodzip/sun6i-mipi-csi
MIPI-CSI2 驱动已经测试OV5640摄像头2Lane模式 1080P@15FPS 720P@30FPS
DVP没测试,因为主线本身就支持DVP,希望没给它改坏吧
楼主牛,好像硬件编码也搞定了?
可能已经有人发过了 Allwinner_F1C200s-User-Manual.pdf
U-Boot 2018.01-05676-g0018878-dirty (May 11 2018 - 21:37:08 +0800) Allwinner Technology
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.15.0-rc8-licheepi-nano+ (zx@zx-VirtualBox) (gcc version 7.2.1 20171011 (Linaro GCC 7.2-2017.11)) #3 Thu May 10 22:06:57 CST 2018
[ 0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
[ 0.000000] CPU: VIVT data cache, VIVT instruction cache
[ 0.000000] OF: fdt: Machine model: Lichee Pi Nano
[ 0.000000] Memory policy: Data cache writeback
顺便问下,你这个是在哪个分支上编译的?
页次: 1