From 53a1ebf5a3fe2c2554556bb24441e5dedc7ae379 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Fri, 7 Feb 2020 21:43:20 +0100 Subject: [PATCH] Update sreen driver and add fx9860 II driver --- include/kernel/util.h | 3 +- src/kernel/hardware/t6k11/display.s | 158 ++++++++++++++++++++++++-- src/kernel/hardware/t6k11/variant.c | 57 ++++++++++ src/kernel/scheduler/context_switch.s | 107 ----------------- src/kernel/scheduler/handler.S | 2 +- src/kernel/scheduler/start.c | 5 +- src/kernel/util/font.c | 8 +- src/kernel/util/kvram.c | 11 +- 8 files changed, 229 insertions(+), 122 deletions(-) create mode 100644 src/kernel/hardware/t6k11/variant.c delete mode 100644 src/kernel/scheduler/context_switch.s diff --git a/include/kernel/util.h b/include/kernel/util.h index 33552b2..2fef585 100644 --- a/include/kernel/util.h +++ b/include/kernel/util.h @@ -26,7 +26,8 @@ extern void kvram_clr_str_area(int x, int y, int width, int height); extern void printk(int x, int y, char const *str, ...); // Hardware specific function (do not use !) -extern void t6k11_display(void *vram); +extern void t6k11_lcd_driver(void *vram); +extern void t6k11_variant_lcd_driver(uint8_t *vram); //--- // Timer functions. diff --git a/src/kernel/hardware/t6k11/display.s b/src/kernel/hardware/t6k11/display.s index d47a28b..ccf43a3 100644 --- a/src/kernel/hardware/t6k11/display.s +++ b/src/kernel/hardware/t6k11/display.s @@ -1,16 +1,158 @@ -.global _t6k11_display -.type _t6k11_display, @function - .text + +.global _t6k11_lcd_driver +.type _t6k11_lcd_driver, @function + .align 2 /* +** @proto: void _t6k11_lcd_driver(void *vram) +** +** @note: +** This function will display the vram on the screen. +** This is the T6K11 drivers, *DO NOT USE* this function if +** you are not absolutly sure that what you are doing. +** +** @register list: +** 0 - Display mode +** 1 - Counter mode +** 2 - Set analog control mode +** 3 - Set alternating signal mode +** 4 - Set X-address AND Set Y-address +** 5 - Set Z-address +** 6 - Contrast control +** 7 - Data Write AND Data Read +** 8 - Unknown, test mode only +** 9 - Unknown, test mode only +** 10 - Unknown, test mode only +** 11 - Unknown, test mode only +** 12 - D/A converter power control +** 13 - Unknown, test mode only. +** 14 - Unknown, test mode only. +** 15 - Unknown, test mode only. +** +*/ +_t6k11_lcd_driver: + ! To avoid reentrace with the Video + ! RAM and I/O opetation, we need to + ! display data using atomic operation. + ! The next part *SHOULD* be exception save ! + mov.l .sr_int_msk, r1 ! Get SR mask for interrupt blocking. + stc sr, r0 ! Save current SR register data. + mov r0, r2 ! Get SR register data. + or r1, r2 ! Set SR.BL = 1 and SR.IMASK = 0b1111 + ldc r2, sr ! Update SR register + + ! Stack management + mov.l r8, @-r15 ! save r8 register. + mov.l r0, @-r15 ! save SR register. + + ! Get LCD register addresses. + mov.l .LCD_register_selector, r0 ! r0 = LCD register selector address. + mov.l .LCD_data_register, r1 ! r1 = LCD data register. + + ! Set the X-adress counter to up-mode. + ! @note: + ! The X-address counter is used + ! for the row and the Y-addresss counter + ! for the column. + mov #1, r2 ! r0 = counter mode register address. + mov.b r2, @r0 ! Select the counter register. + mov #1, r3 ! r0 = Y-address counter "Yup" mode. + mov.b r3, @r1 ! Set the Y-address counter register to "Yup" mode. + + + ! "pre-generate" register data + ! r0 - LCD register selector + ! r1 - LCD data register + ! r2 - X-address / Y-address counter register + ! r3 - data write address + ! r4 - vram + ! r5 - row counter + ! r6 - Y-address counter + ! r7 - X-address counter + mov #4, r2 ! X-address / Y-address counter. + mov #7, r3 ! Data Write register + mov #64, r5 ! Row counter + mov #0, r6 ! Y-address counter (column, alway 0) + mov #192, r7 ! X-address counter (row, 192 = 0, see documentation) + +row_loop: + ! Select the X-address / Y-address counter. + mov.b r2, @r0 ! Select X/Y address counter register. + + ! Update X-address counter / Reset the Y-address counter + mov.b r7, @r1 ! Set X-address counter to current row + mov.b r6, @r1 ! Set Y-address counter to 0 + + ! Select Data write register. + mov.b r3, @r0 ! Select Data Write register + + ! Avoid loop, so write line manually. + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + mov.b @r4+, r8 + mov.b r8, @r1 + + ! Check next line. + dt r5 ! if (--r5) == 0... + bf.s row_loop ! ...if not, jump at + add #1, r7 ! (db) update row counter. + +exit_part: + ! Exit properly + ldc.l @r15+, sr ! restore SR register + mov.l @r15+, r8 ! resotre r8 register + rts ! exit. + nop ! (db) nop. + +.align 4 +.LCD_register_selector: .long 0xb4000000 /* LCD register selector */ +.LCD_data_register: .long 0xb4010000 /* LCD data register */ +.sr_int_msk: .long 0x100000f0 /* SR interrupt mask */ +.end + + +/* +NOTE: OLD BUT FAST AND NOT SAFE +NOTE: FOR MULTIPLE PROCESS ! _t6k11_display(void *vram) This function will display the vram on the screen. This is the T6K11 drivers, DO NOT USE this function if you are not absolutly sure that what you are doing. TODO: use DMA ? -*/ + # register organisation: # r0 Y axis loop. # r1 LCD register selector. @@ -49,7 +191,7 @@ _t6k11_display: mov.l @r15+, r9 rts mov.l @r15+, r8 - -.align 4 -1: .long 0xb4000000 /* LCD register selector */ -2: .long 0xb4010000 /* LCD data register */ +*/ +!.align 4 +!1: .long 0xb4000000 /* LCD register selector */ +!2: .long 0xb4010000 /* LCD data register */ diff --git a/src/kernel/hardware/t6k11/variant.c b/src/kernel/hardware/t6k11/variant.c new file mode 100644 index 0000000..d5fb4ed --- /dev/null +++ b/src/kernel/hardware/t6k11/variant.c @@ -0,0 +1,57 @@ +#include +#include + +// Internal symbols +static volatile uint8_t *sel = (void *)0xb4000000; +static volatile uint8_t *cmd = (void *)0xb4010000; + +static void command(uint8_t reg, uint8_t data) +{ + *sel = reg; + *cmd = data; +} + +void t6k11_variant_lcd_driver(uint8_t *vram) +{ + int y; + + // Start atomic operations + atomic_start(); + + y = -1; + while (++y < 64) + { + // Row selector + command(8, y | 0x80); + command(8, 4); + + // Send the row's data to the device + // @note: Unroll the loop for more speed (?) + *sel = 10; + *cmd = vram[0]; + *cmd = vram[1]; + *cmd = vram[2]; + *cmd = vram[3]; + + *cmd = vram[4]; + *cmd = vram[5]; + *cmd = vram[6]; + *cmd = vram[7]; + + *cmd = vram[8]; + *cmd = vram[9]; + *cmd = vram[10]; + *cmd = vram[11]; + + *cmd = vram[12]; + *cmd = vram[13]; + *cmd = vram[14]; + *cmd = vram[15]; + + // Update vram ptr + vram = &vram[16]; + } + + // Stop atomic operations + atomic_stop(); +} diff --git a/src/kernel/scheduler/context_switch.s b/src/kernel/scheduler/context_switch.s deleted file mode 100644 index 0108300..0000000 --- a/src/kernel/scheduler/context_switch.s +++ /dev/null @@ -1,107 +0,0 @@ -.text - -.global _sched_context_switch -.type _sched_context_switch, @function - -.align 2 -/* -** void sched_context_switch(common_context_t *current, common_context_t *next); -** -** @note: -** r4 - current scheduler task -** r5 - next task -** r0 - tmp -*/ -_sched_context_switch: - ! Save contexts arg - mov.l r8, @-r15 ! save r8 - mov.l r9, @-r15 ! save r9 - mov r4, r8 ! save current context into unbankable reg - mov r5, r9 ! save next context into unbankable reg - - - ! Update SR register to block interrupt / exception and - ! switch register bank to simalate system call. - ! @note: - ! Normaly this is the TMU0 interrupt so the interrupt - ! and register banck is already switchted BUT durring the - ! bootstrap part, the kernel call this function in "user" - ! context. This is why we force update CPU configuration. - mov.l .sr_msk, r1 ! get mask for SR.BL = 1, SR.RB = 1 and SR.IMASK = 0b1111 - stc sr, r0 ! get SR register - or r1, r0 ! set mask for BL, RB and IMASK - ldc r0, sr ! update SR regsiter - - - ! Restore context arg - mov r8, r4 ! restore current context - mov r9, r5 ! restore next context - mov.l @r15+, r9 ! restore r9 - mov.l @r15+, r8 ! restore r8 - -save_current_context: - ! Check current process - ! @note: current process can be NULL ! - tst r4, r4 ! if current task == NULL... - bt context_load ! ...if yes, jump at - add #84, r4 ! get &process->context (end) - - ! save current context - !sts.l pr, @-r4 ! get pr regsiter - stc.l spc, @-r4 ! get spc regsiter - stc.l ssr, @-r4 ! get ssr regsiter - sts.l mach, @-r4 ! get mach regsiter - sts.l macl, @-r4 ! get macl regsiter - stc.l gbr, @-r4 ! get gbr regsiter - mov.l r15, @-r4 ! get r15 register - mov.l r14, @-r4 ! get r14 regsiter - mov.l r13, @-r4 ! get r13 regsiter - mov.l r12, @-r4 ! get r12 regsiter - mov.l r11, @-r4 ! get r11 regsiter - mov.l r10, @-r4 ! get r10 regsiter - mov.l r9, @-r4 ! get r9 regsiter - mov.l r8, @-r4 ! get r8 regsiter - stc.l R7_BANK, @-r4 ! get "process" r7 regsiter - stc.l R6_BANK, @-r4 ! get "process" r6 regsiter - stc.l R5_BANK, @-r4 ! get "process" r5 regsiter - stc.l R4_BANK, @-r4 ! get "process" r4 regsiter - stc.l R3_BANK, @-r4 ! get "process" r3 regsiter - stc.l R2_BANK, @-r4 ! get "process" r2 regsiter - stc.l R1_BANK, @-r4 ! get "process" r1 regsiter - stc.l R0_BANK, @-r4 ! get "process" r0 regsiter - - -context_load: - ! Load next process - ! @note: next process can not be NULL ! - ldc.l @r5+, R0_BANK ! set "process" r0 regsiter - ldc.l @r5+, R1_BANK ! set "process" r1 regsiter - ldc.l @r5+, R2_BANK ! set "process" r2 regsiter - ldc.l @r5+, R3_BANK ! set "process" r3 regsiter - ldc.l @r5+, R4_BANK ! set "process" r4 regsiter - ldc.l @r5+, R5_BANK ! set "process" r5 regsiter - ldc.l @r5+, R6_BANK ! set "process" r6 regsiter - ldc.l @r5+, R7_BANK ! set "process" r7 regsiter - mov.l @r5+, r8 ! set r8 regsiter - mov.l @r5+, r9 ! set r9 regsiter - mov.l @r5+, r10 ! set r10 regsiter - mov.l @r5+, r11 ! set r11 regsiter - mov.l @r5+, r12 ! set r12 regsiter - mov.l @r5+, r13 ! set r13 regsiter - mov.l @r5+, r14 ! set r14 regsiter - mov.l @r5+, r15 ! set r15 register - ldc.l @r5+, gbr ! set gbr regsiter - lds.l @r5+, macl ! set macl regsiter - lds.l @r5+, mach ! set mach regsiter - ldc.l @r5+, ssr ! set ssr regsiter - ldc.l @r5+, spc ! set spc regsiter - !lds.l @r5+, pr ! set pr regsiter - - - ! Process switch - rte ! use RTE to switch process - nop ! (db) nop - -.align 4 -.sr_msk: .long 0x700000f0 -.end diff --git a/src/kernel/scheduler/handler.S b/src/kernel/scheduler/handler.S index d0910c0..69c7bb0 100644 --- a/src/kernel/scheduler/handler.S +++ b/src/kernel/scheduler/handler.S @@ -198,7 +198,7 @@ process_switch: .sched_schedule: .long _sched_schedule .timer_tstr_register: .long 0xa4490004 .timer_unf_field: .long 0x00000100 -#ifndef __SCHED_DEBUG__ +#ifdef __SCHED_DEBUG__ .sched_debug: .long _sched_debug #endif .end diff --git a/src/kernel/scheduler/start.c b/src/kernel/scheduler/start.c index c4d2be0..d983b41 100644 --- a/src/kernel/scheduler/start.c +++ b/src/kernel/scheduler/start.c @@ -13,7 +13,7 @@ uint32_t sched_timer_tstr_bit = 0; //void sched_handler(void); //FIXME: remove me and wrap timer interrupt when occur !! -static void scheduler_timer_callback(void) +/*static void scheduler_timer_callback(void) { common_context_t *context_current; common_context_t *context_next; @@ -38,7 +38,7 @@ static void scheduler_timer_callback(void) // Context switch sched_context_switch(context_current, context_next); -} +}*/ void sched_start(void) { @@ -93,7 +93,6 @@ void sched_start(void) // @note: I use Po/4 on TMU prescaler // TODO: generate quantum and quantum counter for preemption ! uint32_t ticks = (per_freq / 4) / 16; - //sched_timer_id = timer_install(scheduler_timer_callback, NULL, ticks, 0); sched_timer_id = timer_install(NULL, NULL, ticks, 0); sched_timer_address = (uint32_t)&SH7305_TMU.TIMER[sched_timer_id].TCR; sched_timer_intevt = 0x400 + (0x20 * sched_timer_id); diff --git a/src/kernel/util/font.c b/src/kernel/util/font.c index 1f4f789..ff7dc1b 100644 --- a/src/kernel/util/font.c +++ b/src/kernel/util/font.c @@ -1,5 +1,6 @@ #include #include +#include // Font bitmap. static const uint8_t kernel_font_bitmap[] = { @@ -55,9 +56,11 @@ static void font_draw_core(struct font_block_s *fblock) // this is why we use y << 2 because 2^2 = 4. vram_offset_y = fblock->y << 2; + // Start atomic operations + atomic_start(); + // Draw character, pixer per pixel... (x_x) // TODO: update me !! - // TODO: atomic operation !! y = -1; while (++y < fblock->height) { @@ -80,6 +83,9 @@ static void font_draw_core(struct font_block_s *fblock) fblock->bitmap.y = fblock->bitmap.y + KERNEL_FONT_BITMAP_WIDTH; vram_offset_y = vram_offset_y + 4; } + + // Stop atomic operations + atomic_stop(); } diff --git a/src/kernel/util/kvram.c b/src/kernel/util/kvram.c index 30b4c3a..9d675fe 100644 --- a/src/kernel/util/kvram.c +++ b/src/kernel/util/kvram.c @@ -30,7 +30,11 @@ void kvram_clear(void) void kvram_display(void) { //TODO: handle screen hadware ! - t6k11_display(vram); + //TODO: load dynamically screen driver during the boot + if (*(uint8_t*)0xa0010021 == '3') + t6k11_variant_lcd_driver((void*)vram); + else + t6k11_lcd_driver(vram); } /* kvram_scroll() - Scroll up the Video RAM */ @@ -150,6 +154,9 @@ void kvram_clr_str_area(int x, int y, int width, int height) // Get VRAM offset vram_offset_y = y << 2; + // Start atomic operations + atomic_start(); + //DEbug /*kvram_clear(); printk(0, 0, "kvram_clr_str_area debug !"); @@ -176,6 +183,8 @@ void kvram_clr_str_area(int x, int y, int width, int height) vram_offset_y = vram_offset_y + 4; } + // Stop atomic operations + atomic_start(); } /* kvram_ascii() - Draw ASCII character into Video RAM */