Поковырял немножко 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 (тоже есть на руках).
Чем-то напомнило индусский код

Теперь надеюсь, вы поняли, почему я не люблю писать под линукс? Потому что громоздко и тормозит! Нужен чистый поток сознания в программировании!
Сообщение отредактировал __inline__ - Mar 30 2018, 06:25