_pv 79 29 марта, 2018 Опубликовано 29 марта, 2018 · Жалоба должны быть, но не обязаны. Я глянул даташит на V3s что у меня есть (на английском), там расписаны времянки, но самих стробов CS, WR, адресные биты A* на выводах микроконтроллера НЕ нашёл. Таблицы мультиплексирования выводов тоже молчат. Просто приводят картинку с времянками, которая как бы намекает, что без дополнительной логики (ПЛИС, ЦПЛД,рассыпуха) не обойтись: картинка намекает ровно на обратное. а регистры для доступа к шине, конфигурирования интерфейса, отдельные регистры для чтения/записи по двум отдельным адресам через A1 сделали видимо просто так, да ещё и ноги наружу вывести забыли. таблицы мультиплексирования выводов молчат, так как там либо TCON включается либо нет, а как он уже внутри себя будет свои ноги использовать gpio конечно не знает. подключение LCD с i80 к А20 из китайского официального мануала про lcd, для v3s ещё видимо не запилили, но не думаю что периферийные блоки хоть чем-то отличаются, в даташите там всё тоже самое. а почему линии данных так перекошены - не знаю, в китайском не силён. Был один головняк(SDRAM), будет два (преобразователь SDIO в i8080 для LCD :) ) вы сами себе напридумывали трудностей, чтобы потом их героически преодолевать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 30 марта, 2018 Опубликовано 30 марта, 2018 · Жалоба _pv, большое спасибо! :rolleyes: Вот как раз этой схемы мне не хватало, а я уже хотел логику прикидывать к CLK, LCDDE, чтобы выдать нужную полярность по стробам. Зарегался на том форуме и поинтересовался у китайцев - сказали, что всё как в A10, дали инфу по подключению и даташиты: https://debugdump.com/t_900.html Что понравилось - отвечают очень оперативно, возможно они контачат с Alwinner напрямую. Таблица подключения от A10 по назначению пинов совпадает с вашей картинкой: Очень надеюсь, что в v3s работа с дисплеем в режиме i8080 присутствует и её алгоритм аналогичен как в A20, A10. Почему я не хочу подключать дисплей по параллельному RGB? Потому что контроллер будет постоянно вынужден как угорелый рисовать кадр, в то время как он ещё будет не готов, а это несколько неудобно! Плюс отсутствие режимов LCD с выбором прямоугольника отрисовки, направлений - проще через встроенный контроллер дисплея это делать. Ну и как правило, большинство LCD матриц помимо простого RGB содержат ещё I2C/SPI порт для конфигурации. Так что в плане переносимости мне проще через i8080-BUS работать. Этот Alwinner полон загадок, заманчив высокой тактовой 1,2 ГГц + DDR 400 МГц, QFP корпусом и встроенной памятью. Но его загадочность меня настораживает :) Надо сообразить простейшую плату для опытов (v3s есть на руках), для питания пока поставлю обычнее LDO на 3.3V, 3V, 1.2V и 1.8V (точно в даташите смотреть надо). Наподобие как STM-NUCLEO - по минимуму обвязки: питание, кварц, пины на порты, MCU, SD карта памяти для загрузки. Конечно, после мигания светодиодами и ком-порта, прийдётся ковырять Linux BSP, что наверно трудоемко. А обращаться к дисплею в режиме 8080 как? (команды и данные слать) . Через TCON0_CPU_WR_REG, TCON0_CPU_RD0_REG и TCON0_CPU_RD1_REG ? Команда или данные выбираются через бит 25 регистра TCON0_CPU_IF_REG ? (управление A1). На первых порах конечно, линию DC LCD можно посадить на обычный GPIO без ущерба скорости, но хочется чтобы красиво было. картинка намекает ровно на обратное. а регистры для доступа к шине, конфигурирования интерфейса, отдельные регистры для чтения/записи по двум отдельным адресам через A1 сделали видимо просто так, да ещё и ноги наружу вывести забыли. таблицы мультиплексирования выводов молчат, так как там либо TCON включается либо нет, а как он уже внутри себя будет свои ноги использовать gpio конечно не знает. подключение LCD с i80 к А20 из китайского официального мануала про lcd, для v3s ещё видимо не запилили, но не думаю что периферийные блоки хоть чем-то отличаются, в даташите там всё тоже самое. а почему линии данных так перекошены - не знаю, в китайском не силён. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 30 марта, 2018 Опубликовано 30 марта, 2018 (изменено) · Жалоба Поковырял немножко Linux BSP, "linux-master". Вырисовываются интересные вещи касаемо работы LCD в i8080 bus mode. __s32 LCD_CPU_WR(__u32 screen_id,__u32 index,__u32 data) { tcon0_cpu_wr_16b(screen_id,index,data); return 0; } __s32 LCD_CPU_WR_INDEX(__u32 screen_id,__u32 index) { tcon0_cpu_wr_16b_index(screen_id,index); return 0; } __s32 LCD_CPU_WR_DATA(__u32 screen_id,__u32 data) { tcon0_cpu_wr_16b_data(screen_id,data); return 0; } Пошёл дальше: s32 tcon0_cpu_wr_16b(u32 sel, u32 index, u32 data) { tcon0_cpu_wr_24b(sel,tcon0_cpu_16b_to_24b(index),tcon0_cpu_16b_to_24b(data)); return 0; } u32 tcon0_cpu_16b_to_24b(u32 value) { return ((value & 0xfc00)<<8) | ((value & 0x0300)<<6) | ((value & 0x00e0)<<5) | ((value & 0x001f)<<3); } s32 tcon0_cpu_wr_24b(u32 sel, u32 index, u32 data) { tcon0_cpu_wr_24b_index(sel,index); tcon0_cpu_wr_24b_data(sel,data); return 0; } s32 tcon0_cpu_wr_24b_index(u32 sel, u32 index) { u32 count = 0; while((tcon0_cpu_busy(sel)) && (count < 50)) { count ++; disp_delay_us(100); } lcd_dev[sel]->tcon0_cpu_ctl.bits.ca = 0; lcd_dev[sel]->tcon0_cpu_wr.bits.data_wr = index; return 0; } s32 tcon0_cpu_wr_24b_data(u32 sel, u32 data) { u32 count = 0; while((tcon0_cpu_busy(sel)) && (count < 50)) { count ++; disp_delay_us(100); } lcd_dev[sel]->tcon0_cpu_ctl.bits.ca = 1; //tcon0_cpu_if_reg_t lcd_dev[sel]->tcon0_cpu_wr.bits.data_wr = data; //tcon0_cpu_wr_reg_t return 0; } Тут мы видим, что перед посылкой байтов команды или данных - цикл с ожиданием пока устройство занято. Это очень плохо! Все параллельные шины с которыми приходилось работать - EBI у AT91RM9200, FSMC у STM32, FBI у Блекфина - не имели костыля для ожидания завершения. Сама процедура ожидания: u32 tcon0_cpu_busy(u32 sel) { if(lcd_dev[sel]->tcon0_cpu_ctl.bits.wr_flag || lcd_dev[sel]->tcon0_cpu_ctl.bits.rd_flag) return 1; else return 0; } Ну и интуитивно понятно, что структуры как раз описывают биты и смещения регистров от базового адреса. Как всё сложно описано!!! И всё для того чтобы послать на шину 8080 байт данных!!! Чего стоят только описания структур и юнионов: static volatile __de_lcd_dev_t *lcd_dev[2]; s32 tcon_set_reg_base(u32 sel, u32 base) { lcd_dev[sel]=(__de_lcd_dev_t *)base; return 0; } tcon_set_reg_base(screen_id,para->reg_base[DISP_MOD_LCD0]); tcon_set_reg_base(screen_id,para->reg_base[DISP_MOD_LCD1]); typedef struct { u32 reg_base[DISP_MOD_NUM]; u32 reg_size[DISP_MOD_NUM]; u32 irq_no[DISP_MOD_NUM]; s32 (*disp_int_process)(u32 sel); s32 (*vsync_event)(u32 sel); s32 (*start_process)(void); s32 (*capture_event)(u32 sel); s32 (*shadow_protect)(u32 sel, bool protect); disp_sw_init_para *sw_init_para; }__disp_bsp_init_para; //device define typedef struct { tcon_gctl_reg_t tcon_gctl; //0x000 tcon_gint0_reg_t tcon_gint0; //0x004 tcon_gint1_reg_t tcon_gint1; //0x008 tcon_reservd_reg_t tcon_reg00c; //0x00c tcon0_frm_ctl_reg_t tcon0_frm_ctl; //0x010 tcon0_frm_seed_reg_t tcon0_frm_seed_pr; //0x014 tcon0_frm_seed_reg_t tcon0_frm_seed_pg; //0x018 tcon0_frm_seed_reg_t tcon0_frm_seed_pb; //0x01c tcon0_frm_seed_reg_t tcon0_frm_seed_lr; //0x020 tcon0_frm_seed_reg_t tcon0_frm_seed_lg; //0x024 tcon0_frm_seed_reg_t tcon0_frm_seed_lb; //0x028 tcon0_frm_tab_reg_t tcon0_frm_tbl_0; //0x02c tcon0_frm_tab_reg_t tcon0_frm_tbl_1; //0x030 tcon0_frm_tab_reg_t tcon0_frm_tbl_2; //0x034 tcon0_frm_tab_reg_t tcon0_frm_tbl_3; //0x038 tcon_reservd_reg_t tcon_reg03c; //0x03c tcon0_ctl_reg_t tcon0_ctl; //0x040 tcon0_dclk_reg_t tcon0_dclk; //0x044 tcon0_basic0_reg_t tcon0_basic0; //0x048 tcon0_basic1_reg_t tcon0_basic1; //0x04c tcon0_basic2_reg_t tcon0_basic2; //0x050 tcon0_basic3_reg_t tcon0_basic3; //0x054 tcon0_hv_if_reg_t tcon0_hv_ctl; //0x058 tcon_reservd_reg_t tcon_reg05c; //0x05c tcon0_cpu_if_reg_t tcon0_cpu_ctl; //0x060 tcon0_cpu_wr_reg_t tcon0_cpu_wr; //0x064 tcon0_cpu_rd0_reg_t tcon0_cpu_rd; //0x068 tcon0_cpu_rd1_reg_t tcon0_cpu_fet; //0x06c tcon_reservd_reg_t tcon_reg070[6]; //0x070~0x84 tcon0_io_pol_reg_t tcon0_io_pol; //0x088 tcon0_io_tri_reg_t tcon0_io_tri; //0x08c tcon1_ctl_reg_t tcon1_ctl; //0x090 tcon1_basic0_reg_t tcon1_basic0; //0x094 tcon1_basic1_reg_t tcon1_basic1; //0x098 tcon1_basic2_reg_t tcon1_basic2; //0x09c tcon1_basic3_reg_t tcon1_basic3; //0x0a0 tcon1_basic4_reg_t tcon1_basic4; //0x0a4 tcon1_basic5_reg_t tcon1_basic5; //0x0a8 tcon_reservd_reg_t tcon_reg0ac; //0x0ac tcon1_ps_sync_reg_t tcon1_ps_ctl; //0x0b0 tcon_reservd_reg_t tcon_reg0b4[15]; //0x0b4~0x0ec tcon1_io_pol_reg_t tcon1_io_pol; //0x0f0 tcon1_io_tri_reg_t tcon1_io_tri; //0x0f4 tcon_ecc_fifo_reg_t tcon_ecfifo_ctl; //0x0f8 tcon_debug_reg_t tcon_debug; //0x0fc tcon_ceu_ctl_reg_t tcon_ceu_ctl; //0x110 tcon_reservd_reg_t tcon_reg104[3]; //0x104~0x10c tcon_ceu_coef_mul_reg_t tcon_ceu_coef_rr; //0x110 tcon_ceu_coef_mul_reg_t tcon_ceu_coef_rg; //0x114 tcon_ceu_coef_mul_reg_t tcon_ceu_coef_rb; //0x118 tcon_ceu_coef_add_reg_t tcon_ceu_coef_rc; //0x11c tcon_ceu_coef_mul_reg_t tcon_ceu_coef_gr; //0x120 tcon_ceu_coef_mul_reg_t tcon_ceu_coef_gg; //0x124 tcon_ceu_coef_mul_reg_t tcon_ceu_coef_gb; //0x128 tcon_ceu_coef_add_reg_t tcon_ceu_coef_gc; //0x12c tcon_ceu_coef_mul_reg_t tcon_ceu_coef_br; //0x130 tcon_ceu_coef_mul_reg_t tcon_ceu_coef_bg; //0x134 tcon_ceu_coef_mul_reg_t tcon_ceu_coef_bb; //0x138 tcon_ceu_coef_add_reg_t tcon_ceu_coef_bc; //0x13c tcon_ceu_coef_rang_reg_t tcon_ceu_coef_rv; //0x140 tcon_ceu_coef_rang_reg_t tcon_ceu_coef_gv; //0x144 tcon_ceu_coef_rang_reg_t tcon_ceu_coef_bv; //0x148 tcon_reservd_reg_t tcon_reg14c[5]; //0x14c~0x15c tcon0_cpu_tri0_reg_t tcon0_cpu_tri0; //0x160 tcon0_cpu_tri1_reg_t tcon0_cpu_tri1; //0x164 tcon0_cpu_tri2_reg_t tcon0_cpu_tri2; //0x168 tcon0_cpu_tri3_reg_t tcon0_cpu_tri3; //0x16c tcon0_cpu_tri4_reg_t tcon0_cpu_tri4; //0x170 tcon0_cpu_tri5_reg_t tcon0_cpu_tri5; //0x174 tcon_reservd_reg_t tcon_reg178[2]; //0x178~0x17c tcon_cmap_ctl_reg_t tcon_cmap_ctl; //0x180 tcon_reservd_reg_t tcon_reg184[3]; //0x184~0x18c tcon_cmap_odd0_reg_t tcon_cmap_odd0; //0x190 tcon_cmap_odd1_reg_t tcon_cmap_odd1; //0x194 tcon_cmap_even0_reg_t tcon_cmap_even0; //0x198 tcon_cmap_even1_reg_t tcon_cmap_even1; //0x19c tcon_reservd_reg_t tcon_reg1a0[20]; //0x1a0~0x1ec tcon_safe_period_reg_t tcon_volume_ctl; //0x1f0 tcon_reservd_reg_t tcon_reg1f4[3]; //0x1f4~0x1fc tcon_mux_ctl_reg_t tcon_mul_ctl; //0x200 tcon_reservd_reg_t tcon_reg204[9]; //0x204~0x224 tcon_reservd_reg_t tcon_reg228[54]; //0x228~0x2fc tcon1_fill_ctl_reg_t tcon_fill_ctl; //0x300 tcon1_fill_begin_reg_t tcon_fill_start0; //0x304 tcon1_fill_end_reg_t tcon_fill_end0; //0x308 tcon1_fill_data_reg_t tcon_fill_data0; //0x30c tcon1_fill_begin_reg_t tcon_fill_start1; //0x310 tcon1_fill_end_reg_t tcon_fill_end1; //0x314 tcon1_fill_data_reg_t tcon_fill_data1; //0x318 tcon1_fill_begin_reg_t tcon_fill_start2; //0x31c tcon1_fill_end_reg_t tcon_fill_end2; //0x320 tcon1_fill_data_reg_t tcon_fill_data2; //0x324 tcon_reservd_reg_t tcon_reg328[54]; //0x328~0x3fc tcon_gamma_tlb_reg_t tcon_gamma_tlb[256]; //0x400 }__de_lcd_dev_t; typedef union { u32 dwval; struct { u32 trigger_en : 1; // default: 0; u32 trigger_start : 1; // default: 0; u32 trigger_fifo_en : 1; // default: 0; u32 trigger_fifo_bist_en : 1; // default: 0; u32 trigger_sync_mode : 2; // default: 0; u32 res0 : 10; // default:; u32 flush : 1; // default: 0; u32 auto_ : 1; // default: 0; u32 res1 : 4; // default:; u32 rd_flag : 1; // default: 0; u32 wr_flag : 1; // default: 0; u32 vsync_cs_sel : 1; // default: 0; u32 ca : 1; // default: 0; u32 da : 1; // default: 0; u32 res2 : 1; // default:; u32 cpu_mode : 4; // default: 0; } bits; } tcon0_cpu_if_reg_t; typedef union { u32 dwval; struct { u32 data_wr : 24; // default: 0; u32 res0 : 8; // default:; } bits; } tcon0_cpu_wr_reg_t; Предстоит жёсткий секс с Линуксом :) Начну-ка я наверно с A13, отладочной платы Olinuxino (тоже есть на руках). Чем-то напомнило индусский код :) Теперь надеюсь, вы поняли, почему я не люблю писать под линукс? Потому что громоздко и тормозит! Нужен чистый поток сознания в программировании! Изменено 30 марта, 2018 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 79 30 марта, 2018 Опубликовано 30 марта, 2018 · Жалоба что-то всё действительно загадочно, есть регистр tcon0_cpu_wr_reg у которого по даташиту 24 разряда и который при записи должен писать целиком в LCD_D[23:0], а потом взяли и как попало подключили линии данных, не подряд, а старшие шесть разрядов каждого цвета (ну чтобы 24х разрядный цвет преобразовывать в 666, или 565 схемотехнически), а теперь руками каждый пиксель перепаковываем обратно из 16/18 в 24, а нельзя было просто подключить шину подряд, LCD_D[15:0] или [17:0], и писать данные как есть, раз они уже изначально в таком формате? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 30 марта, 2018 Опубликовано 30 марта, 2018 (изменено) · Жалоба что-то всё действительно загадочно, есть регистр tcon0_cpu_wr_reg у которого по даташиту 24 разряда и который при записи должен писать целиком в LCD_D[23:0], а потом взяли и как попало подключили линии данных, не подряд, а старшие шесть разрядов каждого цвета (ну чтобы 24х разрядный цвет преобразовывать в 666, или 565 схемотехнически), а теперь руками каждый пиксель перепаковываем обратно из 16/18 в 24, а нельзя было просто подключить шину подряд, LCD_D[15:0] или [17:0], и писать данные как есть, раз они уже изначально в таком формате? Я бы отталкивался от того, по каким линиям пойдут биты байта при записи в регистр tcon0_cpu_wr_reg. Проверить в принципе это можно, просто зациклив передачу в этот регистр и путём вызванивания тестером логического уровня на каждом бите. Увы и ах - осциллографа и логического анализатора под рукой нет. :( А так да, получается индусский говнокод с нагромождением. Но к сожалению, нормальных SDK под эти чипы нет Должно хватить вот этого(код я писал): #define CA 25 /* A1位 A1 bit */ #define TCON 0x01C0C000 /* TCON基地址 TCON Base Address */ #define TCON0_CPU_IF_REG *(volatile u32*)(TCON+0x60) #define TCON0_CPU_WR_REG *(volatile u32*)(TCON+0x64) void TCON0_INDEX(u32 index) { TCON0_CPU_IF_REG&=~(1UL<<CA); //清除CA位 clear CA bit TCON0_CPU_WR_REG=index; //写索引 write index } void TCON0_DATA(u32 data) { TCON0_CPU_IF_REG|=(1UL<<CA); //设置CA位 set CA bit TCON0_CPU_WR_REG=data; // 写入数据 write data } Не забыв отремапить ноги GPIO и включив тактирование нужных узлов периферии. и отынитить TCON для режима CPU I/F i8080 :) Ну и второй головняк - тайминги шины. Подозреваю, что на ширину строба записи будет влиять делитель для DCLK, а на длительность цикла - длина VSYNC лили LCDDE Изменено 30 марта, 2018 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться