Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Портирование ядра. Написал драйвер UART как корректно его подключить.
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Linux
Sanoend
Здравствуйте. Я пытаюсь портировать ядро линукс на процессор SPMP8000 (основан на arm926).
Я написал свой драйвер ЮАРТ (пока сильно упрощенный вариант).
Вот код драйвера:

CODE
#include <linux/console.h>
#include <linux/serial_core.h>
#include <asm/io.h>
#include <mach/serial.h>

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <linux/termios.h>
#include <linux/amba/bus.h>
#include <linux/amba/serial.h>
#include <linux/io.h>
#include <mach/platform.h>
#include <mach/hardware.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/setup.h>
#include <asm/mach/arch.h>
#include <asm/mach/flash.h>
#include <asm/mach/irq.h>
#include <asm/mach/map.h>
#include <asm/mach/time.h>




//запись символа в юарт0
static void putc(int c)
{
int timeout=4000;

if (UART0_STATUS1 & 0x1E) return;
while (timeout > 0) {
if ((UART0_STATUS2 & 0x10) && ((UART0_STATUS3 & 4) == 0)) {
UART0_DATA = c;
break;
}
timeout--;
}
}

// функция printk в ЮАРТ
static void sanoprintk(struct console *co, const char *s, u_int count){
int i;
/* Пишем каждый символ */
for (i = 0; i < count; i++, s++) {
if (*s == '\n'){
putc('\r');
}
putc(*s);
}
}


static int __init sano_console_setup(struct console *co, char *options)
{
return 0;
}


/* Заполняем структуру консоли */

static struct console sano_uart_console = {
.name = "ttyS", /* Имя консоли */
.write = sanoprintk, /* Как делать printk в консоли */
// .device = uart_console_device, /* Предоставлена ядром serial */
.setup = sano_console_setup,
.flags = CON_PRINTBUFFER, /* Флаг по умолчанию */
.index = -1, /* Инициализация в неправильное значение */
};
//register_console(&sano_uart_console);


/* Инициализация консоли */

static int __init sano_uart_console_init(void)
{
/* Регистрация этой консоли */
register_console(&sano_uart_console);
return 0;
}

console_initcall(sano_uart_console_init); /* Метка инициализации консоли */

В Makefile arch части добавил obj-y += serial.o, ядро собирается и драйвер в его добавляется, но вывод сообщений в ЮАРТ не происходит.

Однако если я в файде /init/main.c добавляю свою функцию sanoprintk , а так же заполняю и инициализирую структуру static struct console sano_uart_console прямо в начале функции start_kernel, то вывод в юарт работает так как надо.
Выглядит это примерно так
CODE
#ifdef STANDALONE_DEBUG
#define putstr printf
#else

static void sanoprintk(struct console *co, const char *s, u_int count);

#include <mach/uncompress.h>
#endif

static void sanoprintk(struct console *co, const char *s, u_int count){
int i;
/* Пишем каждый символ */
for (i = 0; i < count; i++, s++) {
if (*s == '\n'){
putc('\r');
}
putc(*s);
}
}

asmlinkage void __init start_kernel(void)
{
/* Параметры каждого из поддерживаемых портов USB_UART */
/* Заполняем структуру консоли */

static struct console sano_uart_console = {
.name = "ttyS", /* Имя консоли */
.write = sanoprintk, /* Как делать printk в консоли */
.flags = CON_PRINTBUFFER, /* Флаг по умолчанию */
.index = -1, /* Инициализация в неправильное значение */
};
register_console(&sano_uart_console);



Однако, это крайне не верное решение. Подскажите пожалуйста как подключить драйвер вынесенный в отдельный файл arch части ядра.

П.С. извиняюсь за много текста, но так и не понял как запехать тег CODE под спойлер
IgorKossak
Цитата(Sanoend @ Aug 16 2012, 11:38) *
П.С. извиняюсь за много текста, но так и не понял как запехать тег CODE под спойлер

Вместо тэга CODE надо использовать CODEBOX (при размере кода более 10 строк).
Idle
Цитата(Sanoend @ Aug 16 2012, 12:38) *
Здравствуйте. Я пытаюсь портировать ядро линукс на процессор SPMP8000 (основан на arm926).

здравствуйте, всё спортировано до нас http://lists.infradead.org/pipermail/linux...ber/068699.html
Sanoend
IgorKossak - спасибо. Буду знать и использовать.

Idle - да я видел это. Но не смог найти где скачать эти файлы.
Всё что можно я даже выдернул из общехо хода переписки в той рассылке, но там многого не хватает.
В ванильном ядре присутствует строка в arch/arm/tools/mach-types
letcool MACH_LETCOOL LETCOOL 3617
но больше нету не чего. Даже в arch/arm/Makefile отсутствует machine-$(CONFIG_ARCH_LETCOOL) не говоря уже об
arch/arm/mach-spmp8000/ и т.д.

я пробовал писать Zoltan Devai.
Может быть я что-то не понимаю. И вы мне подскажите где добыть патч для этой платформы.
Idle
Цитата(Sanoend @ Aug 21 2012, 10:58) *
Idle - да я видел это. Но не смог найти где скачать эти файлы.

файлы разбиты на 9 писем в этом треде, из письма копипасти в файл - это и будет патч

Цитата(Sanoend @ Aug 21 2012, 10:58) *
В ванильном ядре присутствует строка в arch/arm/tools/mach-types

ну правильно, не включили же ничего, парень спортировал, запостил патч для того ядра, для которого писал, ему показали что не так и всё на этом

выясни ядро, на которое лягут патчи и собери, потом, если надо будет - портируй патчи на более свежее

Sanoend
Я так и пробовал. К сожалению в переписке не хватает некоторых файлов.
Например, clkdev.h на него есть ссылка в clkdev.c
но самого это файла нету. И т.д. примерно после 40-50 пересборок с лечением ошибок я сдался.
Сколько там их всего я не знаю.
Idle
Цитата(Sanoend @ Aug 21 2012, 12:08) *
Например, clkdev.h на него есть ссылка в clkdev.c

так это #include <linux/clkdev.h>, его и не должно там быть
Sanoend
нет
linux/clkdev.h
берется не из mach части а из общих инклайдов.

Я возможно перепутал название файлов т.к. в действительности #include <mach/clkdev.h> я сейчас не вижу.
Но я точно помню, что каких-то файлов не хватало.
Хотя возможно я где-то совершил ошибку.
Думаю стоит попробовать ещё раз. Не подскажите как определить под какую версию ядра писался этот патч.
Переписка датируется "Sun Oct 9 12:36:04 EDT 2011" я исходил из этого и брал последнее на тот момент ядро.
Но мне кажется я ошибся.

П.С. Спасибо большое за помощь.
Idle
Цитата(Sanoend @ Aug 21 2012, 12:59) *
Не подскажите как определить под какую версию ядра писался этот патч.
Переписка датируется "Sun Oct 9 12:36:04 EDT 2011" я исходил из этого и брал последнее на тот момент ядро.

не знаю, я бы тоже взял последнее на тот момент
Sanoend
есть ещё патч в2
http://lists.infradead.org/pipermail/linux...ber/070007.html
Idle
Цитата(Sanoend @ Aug 21 2012, 13:18) *

а, этот товарищ у кого-то сделал cherry-pick, попробуй тогда на ванильное 3.2 наложить
Sanoend
Можно чуть подробнее, что такое cherry-pick ?

Какой патч мне надо наложить? Нужно сначала собрать всё из сообщений первого патча, потом добавить к нему из второго патча, а потом накладывать на ванильное 3.2 ?

П.С. всегда такие сложности по сборке патчей из кучи писем? Не проще ли разработчику организовать что-то вроде git в котором будет и чистое ядро и пропатченое. Так можно будет скачивать и сразу патченое ядро и даже автоматом получать файл патча.
Idle
Цитата(Sanoend @ Aug 21 2012, 14:21) *
Можно чуть подробнее, что такое cherry-pick ?

он там когда разрабатывал, дёрнул один патч из девелоперской ветки разработчика системы прерываний

Цитата(Sanoend @ Aug 21 2012, 14:21) *
Какой патч мне надо наложить? Нужно сначала собрать всё из сообщений первого патча, потом добавить к нему из второго патча, а потом накладывать на ванильное 3.2 ?

нет, сразу бери v2, сохраняй 5 писем в 5 файлов с патчами и накладывай (текст письма можно даже не удалять) на ванильное 3.2

Цитата(Sanoend @ Aug 21 2012, 14:21) *
П.С. всегда такие сложности по сборке патчей из кучи писем?

не знаю, беру обычно из коммитов
Sanoend
второй патч 3.2.28
Куча ошибок сборки
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c: In function ‘cpu_suspend’:
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:42:32: error: dereferencing pointer to incomplete type
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:56:3: error: implicit declaration of function ‘cpu_switch_mm’
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:57:3: error: implicit declaration of function ‘local_flush_tlb_all’
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c: In function ‘cpu_suspend_init’:
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:65:2: error: implicit declaration of function ‘pgd_alloc’
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:65:27: error: ‘init_mm’ undeclared (first use in this function)
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:65:27: note: each undeclared identifier is reported only once for each function it appears in
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:68:3: error: implicit declaration of function ‘identity_mapping_add’
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/suspend.c:68:50: error: ‘SECTION_SIZE’ undeclared (first use in this function)
Idle
хм, а без патча собирается? он в arch/arm/kernel/suspend.c что-то правил?

упд
под другую какую-нибудь борду с тем же ядром в soc у тебя собирается?
Sanoend
нет в suspend.c он не чего не правил.
Заметил полную не состоятельность патча.
Патч не чего не добавляет не в
/arch/arm/tools/mach-types
/arch/arm/Kconfig
/arch/arm/Makefile
/arch/arm/mm/Kconfig
а без этого ИМХО новая платформа просто не добавится.
Ну да фиг с ним, я не гордый. Раскидал руками всё что надо. Строчки добавил.

В конфиге явно прописал
CONFIG_SUSPEND=n
CONFIG_SUSPEND_FREEZER=n
и т.д.
но в той директории в которую я собираю появляется конфиг сформированный через автокоф компилятора и в нем
CONFIG_SUSPEND=y
CONFIG_SUSPEND_FREEZER=y
Почему игнорируются опции, которые я подставил не представляю.

Dron_Gus
Цитата(Sanoend @ Aug 21 2012, 17:57) *
CONFIG_SUSPEND=n

Вроде должно быть:
# CONFIG_SUSPEND not set

Смотрите внимательней, может какме другие настройки включают это. Вообще, я бы поотключал через menuconfig, можно быстро найти необходимые настройки "/". Плюс, будет видно, что оно еще тянет и от чего зависит.
Idle
Цитата(Sanoend @ Aug 21 2012, 17:57) *
Заметил полную не состоятельность патча.

sm.gif

Цитата(Sanoend @ Aug 21 2012, 17:57) *
/arch/arm/Kconfig
/arch/arm/Makefile

есть они там

патчи ложатся, суспенд отключи через menuconfig

Sanoend
Idle - файлы
/arch/arm/Kconfig
/arch/arm/Makefile
есть в первом патче но нет во втором.

Но не суть. Я решил попробовать собрать ядро с первым патчем.
Собрал всё что нужно из переписки, создал файлы патчей.
Попробовал пропатсчить ядра 3.0.4 , 3.1.1 , 3.1.2 , 3.2.0 , 3.2.1
всегда один и тот же результат. Ошибка при сборке
Код
/home/armkernel/source/patchtest/linux-3.1.1/arch/arm/kernel/entry-armv.S: Assembler messages:
/home/armkernel/source/patchtest/linux-3.1.1/arch/arm/kernel/entry-armv.S:211: Error: bad instruction `get_irqnr_preamble r6,lr'
/home/armkernel/source/patchtest/linux-3.1.1/arch/arm/kernel/entry-armv.S:211: Error: bad instruction `get_irqnr_and_base r0,r2,r6,lr'
/home/armkernel/source/patchtest/linux-3.1.1/arch/arm/kernel/entry-armv.S:408: Error: bad instruction `get_irqnr_preamble r6,lr'
/home/armkernel/source/patchtest/linux-3.1.1/arch/arm/kernel/entry-armv.S:408: Error: bad instruction `get_irqnr_and_base r0,r2,r6,lr'
make[2]: *** [arch/arm/kernel/entry-armv.o] Error 1
make[1]: *** [arch/arm/kernel] Error 2
make: *** [sub-make] Error 2


Зато разобрался почему ядро игнорировало мои опции конфигурирования.
Я таскал свой конфиг с ветки 2.6.31, для третьей ветки в нем многого не хватало.
Через автоконф перевел его на третью ветку, а затем руками подправил всё что нужно.

Но что делать я ошибками сборки, я пока не представляю. Под ARM VERSATILE ядро успешно собирается. Значит ошибка где-то в mach части под мой камень.
Или в конфигурации, например, верно выбран процессор, но не верна целевая платформа.
Разбираюсь дальше....
Idle
Цитата(Sanoend @ Aug 22 2012, 12:32) *
/arch/arm/Kconfig
/arch/arm/Makefile
есть в первом патче но нет во втором.

так вот же в пятой части: http://lists.infradead.org/pipermail/linux...ber/070011.html

Цитата(Sanoend @ Aug 22 2012, 12:32) *
всегда один и тот же результат. Ошибка при сборке

да, у меня такие же ошибки, но тулчейн специально не ставил, не уверен что подходит
Sanoend
если поменять в конфиге
CONFIG_ARCH_VERSATILE=y на
CONFIG_ARCH_VERSATILE=n

а
CONFIG_ARCH_SHARK=y
то ошибки получаются другие.
Похоже на третьей ветке ядра по мимо процесора надо ещё и целевую платформу выбрать.
Какую выбирать для этого проца пока не знаю.
Но сейчас попробую покурить сырцы mach части. Может там какую подсказку найду.
Idle
Цитата(Sanoend @ Aug 22 2012, 12:32) *
Или в конфигурации, например, верно выбран процессор, но не верна целевая платформа.

да, что-то не так с выбором архитектуры
Цитата
-D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi
Sanoend
Цитата(Idle @ Aug 22 2012, 12:59) *
-D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=arm9tdmi
можно по подробнее про вот эту строку? а то я что-то не понял.
Жаль, что к патчу не прилагается defconfig
Idle
Цитата(Sanoend @ Aug 22 2012, 14:04) *
можно по подробнее про вот эту строку? а то я что-то не понял.

вообще, а какое там ядро-то? может тот самое?
Sanoend
Не понял ядро чего? Процессора, если так , то spmp8000 основан на ARM926, а он в свою очередь имеет V5 architecture
Idle
Цитата(Sanoend @ Aug 22 2012, 14:43) *
Не понял ядро чего? Процессора, если так , то spmp8000 основан на ARM926, а он в свою очередь имеет V5 architecture

понятно, значит с ядром порядок
в arch/arm/mach-spmp8000/include/mach не хватает макросов (get_irqnr_preamble и прочие) или инклудов откуда их брать
это я уже не в курсе - к армоводам
Sanoend
Idle спасибо вам за помощь.
Ну опубликую для истории, куда двинулся дальше.
get_irqnr_preamble и т.д. в действительности не хватало в mach части. Я уже писал их для ядра 2.6.31
по этому просто добавил в /mach/include/entry-macro.S строки
Код
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/platform.h>

<-----><------>.macro<>disable_fiq
<------><------>.endm
<------><------>.macro  get_irqnr_preamble, base, tmp
<------><------>.endm
<------><------>.macro  arch_ret_to_user, tmp1, tmp2
<------><------>.endm
<------><------>.macro<>get_irqnr_and_base, irqnr, irqstat, base, tmp
<------><------>.endm

и создал там же файл platform.h
Код
#ifndef __PLATFORM_H__
#define __PLATFORM_H__


#define>SPMP8K_IO_BASE<><------>0x90000000


#define>SPMP8K_UART0_BASE<----->0x92B04000
#define>SPMP8K_UART0_DATA<----->0x00
#define>SPMP8K_UART0_STAT1<---->0x14<-->// 0x92B04014
#define>SPMP8K_UART0_STAT2<---->0x18<-->// 0x92B04018
#define>SPMP8K_UART0_STAT3<---->0x20<-->//


Эта ошибка пропала. Компиляция двинулась чуть дальше и стала появляться ошибка

/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/debug.S: Assembler messages:
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/debug.S:159: Error: too many positional arguments
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/kernel/debug.S:175: Error: too many positional arguments


Ну тут более менее понятно в чем причина, видимо в более старых (или наоборот новых) версиях ядра, передавались два параметра в addruart и именно это и объявленно в
/arch/arm/mach-spmp8000/include/mach/debug-macro.S
Код
<------>.macro  addruart, rp, rv
<------>mov     \rp, #0x92000000
<------>add<--->\rp, #0x00B00000
<------>add<--->\rp, #0x00004000
<------>orr<--->\rv, \rp, #0xF0000000
<------>.endm

#define UART_SHIFT 2
#include <asm/hardware/debug-8250.S>

а в /arch/arm/kernel/debug.S вызов идет с тремя параметрами
Код
<------><------>addruart_current r3, r1, r2

На данный моммент я решил не вникать, что там такое изменили и решил проблему самым простым и не правильным образом (только для теста)
в /arch/arm/mach-spmp8000/include/mach/debug-macro.S

Код
<------>.macro  addruart, rp, rv, rb


и встретил новую ошибку компиляции
CC arch/arm/mach-spmp8000/core.o
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/mach-spmp8000/core.c: In function ‘spmp8000_init_irq’:
/home/armkernel/source/patchtest/linux-3.2.28/arch/arm/mach-spmp8000/core.c:90:2: error: implicit declaration of function ‘vic_of_init’
а вот такие ошибки всегда ставят меня в полный тупик.
неявное объявление функции "vic_of_init" , как его сделать явным?

у меня есть подозрение, что функция vic_of_init вызывается, но не где не объявлена. Или объявлена но не инклудится.
Ход моих мыслей верный?
Idle
Цитата(Sanoend @ Aug 22 2012, 15:44) *
у меня есть подозрение, что функция vic_of_init вызывается, но не где не объявлена. Или объявлена но не инклудится.
Ход моих мыслей верный?

да, такой функции нигде нет
Sanoend
посмотрел в ванили 3.5.х там эта функция есть. Так что похоже патч предназначен для более познего ядра.
В ядре 3.2.1 этой функции так же нет.
Буду лазить тут
http://lxr.free-electrons.com/source/arch/...mmon/vic.c#L407
и искать в какой версии она появилась. Затем попробую скачать и пропатчить эту версию.
Посмотрим на что ругаться будет.
Сильнее всего угнетает перспектива по новой править конфиг.
Sanoend
Ядро упорно собирается под арм версализ.
Пытаюсь выставить через
make ARCH=arm menuconfig и загрузку своего конфига нужный мне процессор в system type -> ARM system type
нудный мне проц. А там его нету.
Хотя на более раних версиях ядра было SPMP8000 SoC.
Думаю как сделать что бы он появился.
Idle
а зачем тебе свой конфиг, выбери в дефолтном нужный soc, отключи суспенд а остальное ненужное отключай по мере поступления ошибок, я так и сделал когда дошёл у себя до ошибок с отсутствием макросов


Sanoend
Удалось собрать ядро. В данный момент запускается до Uncompres Linux kernel ....
Целиком исходники выложить?
Как думаете может стоит создать публичный GIT ? Мало ли кому ещё пригодится.
Sanoend
Удалось запустить ядро.
Прежде всего хочу поблагодарить всех кто помогал советом.
Я создал проек на гулокоде и написал там пару статей по неочевидным, на мой взгляд, момментам. Вот ссылка
https://code.google.com/p/linux-on-spmp8000/w/list

Сейчас мучаюсь с запуском экрана. Дисплей совместимый с PSP (пробовали перекидывать). По этому логично предположить что драйвер нужно использовать "Epson S1D13XXX FB Driver". Если верить DTS файлу, а так же данныйм в дизасемблированной родной прошивке, то адресом framebuffer должен быть 0x93000000
я пытался запустить дисплей инициализируя драйвер на этот адрес, но всегда получал сообщение
Код
probe called: device is c01d51a8
Epson S1D13XXX FB Driver
s1d13xxxfb: unknown chip production id 0, revision 0
s1d13xxxfb: please contant maintainer


Добавил дополнительные отладочные строки в цикле сравнения увидел вот это
Код
probe called: device is c01d51a8
Epson S1D13XXX FB Driver
s1d13xxxfb: prod_id = 0, s1d13xxxfb_prod_ids = 3
s1d13xxxfb: prod_id = 0, s1d13xxxfb_prod_ids = 4
s1d13xxxfb: prod_id = 0, s1d13xxxfb_prod_ids = 7
s1d13xxxfb: unknown chip production id 0, revision 0
s1d13xxxfb: please contant maintainer


Прот этом значение переменной prod_id берется как:
Код
<------>/* production id is top 6 bits */
prod_id = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) >> 2;
<------>/* revision id is lower 2 bits */
revision = s1d13xxxfb_readreg(default_par, S1DREG_REV_CODE) & 0x3;


где S1DREG_REV_CODE имеет смещение ноль, относительно адреса начала фрейм буферра.

Я пробовал задать руками значения prod_id равные 3,4,7 в этом случае ядро пытается делить на ноль и уходит в панику.
Подскажите пожалуйста в какую сторону копать дальше.
kurtis
Я могу ошибаться, но как мне кажется, драйвер ничего не знает о том, как и куда у вас подключен контроллер экрана. Вы когда посылаете команды контроллеру, у вас какая-то активность на шине есть?
Sanoend
Спасибо за наводку. Активность на шине посмотрю.
Расскажите пожалуйста, в общих чертах, как сделать, что бы драйвер знал о том как и куда подключен дисплей.
В данный моммент я провожу инит дисплея так
CODE

#define EPSONREGSTART 0x93000000
#define EPSONREGLEN 0x00100000
#define EPSONFBSTART 0x93200000
/* 512kB framebuffer */
#define EPSONFBLEN 512*1024


static struct s1d13xxxfb_regval s1d13xxxfb_initregs[] = {
/* line 344 of HP's doc */
{0x0000,0x04}, // Prod + Rev Code Register
{0x0001,0x00}, // Miscellaneous Register
{0x01FC,0x00}, // Display Mode Register
{0x0004,0x00}, // General IO Pins Configuration Register 0
{0x0005,0x00}, // General IO Pins Configuration Register 1
{0x0008,0x00}, // General IO Pins Control Register 0
{0x0009,0x00}, // General IO Pins Control Register 1
{0x0010,0x01}, // Memory Clock Configuration Register
{0x0014,0x11}, // LCD Pixel Clock Configuration Register
{0x0018,0x01}, // CRT/TV Pixel Clock Configuration Register
{0x001C,0x01}, // MediaPlug Clock Configuration Register
{0x001E,0x01}, // CPU To Memory Wait State Select Register
{0x0020,0x00}, // Memory Configuration Register
{0x0021,0x45}, // DRAM Refresh Rate Register
{0x002A,0x01}, // DRAM Timings Control Register 0
{0x002B,0x03}, // DRAM Timings Control Register 1
{0x0030,0x1c}, // Panel Type Register
{0x0031,0x00}, // MOD Rate Register
{0x0032,0x4F}, // LCD Horizontal Display Width Register
{0x0034,0x07}, // LCD Horizontal Non-Display Period Register
{0x0035,0x01}, // TFT FPLINE Start Position Register
{0x0036,0x0B}, // TFT FPLINE Pulse Width Register
{0x0038,0xEF}, // LCD Vertical Display Height Register 0
{0x0039,0x00}, // LCD Vertical Display Height Register 1
{0x003A,0x13}, // LCD Vertical Non-Display Period Register
{0x003B,0x0B}, // TFT FPFRAME Start Position Register
{0x003C,0x01}, // TFT FPFRAME Pulse Width Register
{0x0040,0x05}, // LCD Display Mode Register (2:4bpp,3:8bpp,5:16bpp)
{0x0041,0x00}, // LCD Miscellaneous Register
{0x0042,0x00}, // LCD Display Start Address Register 0
{0x0043,0x00}, // LCD Display Start Address Register 1
{0x0044,0x00}, // LCD Display Start Address Register 2
{0x0046,0x80}, // LCD Memory Address Offset Register 0
{0x0047,0x02}, // LCD Memory Address Offset Register 1
{0x0048,0x00}, // LCD Pixel Panning Register
{0x004A,0x00}, // LCD Display FIFO High Threshold Control Register
{0x004B,0x00}, // LCD Display FIFO Low Threshold Control Register
{0x0050,0x4F}, // CRT/TV Horizontal Display Width Register
{0x0052,0x13}, // CRT/TV Horizontal Non-Display Period Register
{0x0053,0x01}, // CRT/TV HRTC Start Position Register
{0x0054,0x0B}, // CRT/TV HRTC Pulse Width Register
{0x0056,0xDF}, // CRT/TV Vertical Display Height Register 0
{0x0057,0x01}, // CRT/TV Vertical Display Height Register 1
{0x0058,0x2B}, // CRT/TV Vertical Non-Display Period Register
{0x0059,0x09}, // CRT/TV VRTC Start Position Register
{0x005A,0x01}, // CRT/TV VRTC Pulse Width Register
{0x005B,0x10}, // TV Output Control Register
{0x0060,0x03}, // CRT/TV Display Mode Register (2:4bpp,3:8bpp,5:16bpp)
{0x0062,0x00}, // CRT/TV Display Start Address Register 0
{0x0063,0x00}, // CRT/TV Display Start Address Register 1
{0x0064,0x00}, // CRT/TV Display Start Address Register 2
{0x0066,0x40}, // CRT/TV Memory Address Offset Register 0
{0x0067,0x01}, // CRT/TV Memory Address Offset Register 1
{0x0068,0x00}, // CRT/TV Pixel Panning Register
{0x006A,0x00}, // CRT/TV Display FIFO High Threshold Control Register
{0x006B,0x00}, // CRT/TV Display FIFO Low Threshold Control Register
{0x0070,0x00}, // LCD Ink/Cursor Control Register
{0x0071,0x01}, // LCD Ink/Cursor Start Address Register
{0x0072,0x00}, // LCD Cursor X Position Register 0
{0x0073,0x00}, // LCD Cursor X Position Register 1
{0x0074,0x00}, // LCD Cursor Y Position Register 0
{0x0075,0x00}, // LCD Cursor Y Position Register 1
{0x0076,0x00}, // LCD Ink/Cursor Blue Color 0 Register
{0x0077,0x00}, // LCD Ink/Cursor Green Color 0 Register
{0x0078,0x00}, // LCD Ink/Cursor Red Color 0 Register
{0x007A,0x1F}, // LCD Ink/Cursor Blue Color 1 Register
{0x007B,0x3F}, // LCD Ink/Cursor Green Color 1 Register
{0x007C,0x1F}, // LCD Ink/Cursor Red Color 1 Register
{0x007E,0x00}, // LCD Ink/Cursor FIFO Threshold Register
{0x0080,0x00}, // CRT/TV Ink/Cursor Control Register
{0x0081,0x01}, // CRT/TV Ink/Cursor Start Address Register
{0x0082,0x00}, // CRT/TV Cursor X Position Register 0
{0x0083,0x00}, // CRT/TV Cursor X Position Register 1
{0x0084,0x00}, // CRT/TV Cursor Y Position Register 0
{0x0085,0x00}, // CRT/TV Cursor Y Position Register 1
{0x0086,0x00}, // CRT/TV Ink/Cursor Blue Color 0 Register
{0x0087,0x00}, // CRT/TV Ink/Cursor Green Color 0 Register
{0x0088,0x00}, // CRT/TV Ink/Cursor Red Color 0 Register
{0x008A,0x1F}, // CRT/TV Ink/Cursor Blue Color 1 Register
{0x008B,0x3F}, // CRT/TV Ink/Cursor Green Color 1 Register
{0x008C,0x1F}, // CRT/TV Ink/Cursor Red Color 1 Register
{0x008E,0x00}, // CRT/TV Ink/Cursor FIFO Threshold Register
{0x0100,0x00}, // BitBlt Control Register 0
{0x0101,0x00}, // BitBlt Control Register 1
{0x0102,0x00}, // BitBlt ROP Code/Color Expansion Register
{0x0103,0x00}, // BitBlt Operation Register
{0x0104,0x00}, // BitBlt Source Start Address Register 0
{0x0105,0x00}, // BitBlt Source Start Address Register 1
{0x0106,0x00}, // BitBlt Source Start Address Register 2
{0x0108,0x00}, // BitBlt Destination Start Address Register 0
{0x0109,0x00}, // BitBlt Destination Start Address Register 1
{0x010A,0x00}, // BitBlt Destination Start Address Register 2
{0x010C,0x00}, // BitBlt Memory Address Offset Register 0
{0x010D,0x00}, // BitBlt Memory Address Offset Register 1
{0x0110,0x00}, // BitBlt Width Register 0
{0x0111,0x00}, // BitBlt Width Register 1
{0x0112,0x00}, // BitBlt Height Register 0
{0x0113,0x00}, // BitBlt Height Register 1
{0x0114,0x00}, // BitBlt Background Color Register 0
{0x0115,0x00}, // BitBlt Background Color Register 1
{0x0118,0x00}, // BitBlt Foreground Color Register 0
{0x0119,0x00}, // BitBlt Foreground Color Register 1
{0x01E0,0x00}, // Look-Up Table Mode Register
{0x01E2,0x00}, // Look-Up Table Address Register
/* not sure, wouldn't like to mess with the driver */
{0x01E4,0x00}, // Look-Up Table Data Register
/* jornada doc says 0x00, but I trust the driver */
{0x01F0,0x10}, // Power Save Configuration Register
{0x01F1,0x00}, // Power Save Status Register
{0x01F4,0x00}, // CPU-to-Memory Access Watchdog Timer Register
{0x01FC,0x01}, // Display Mode Register(0x01:LCD, 0x02:CRT, 0x03:LCD&CRT)
};


static struct s1d13xxxfb_pdata s1d13xxxfb_data = {
.initregs = s1d13xxxfb_initregs,
.initregssize = ARRAY_SIZE(s1d13xxxfb_initregs),
.platform_init_video = NULL
};

static struct resource s1d13xxxfb_resources[] = {
[0] = {
.start = EPSONFBSTART,
.end = EPSONFBSTART + EPSONFBLEN,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = EPSONREGSTART,
.end = EPSONREGSTART + EPSONREGLEN,
.flags = IORESOURCE_MEM,
}
};

static struct platform_device s1d13xxxfb_device = {
.name = S1D_DEVICENAME,
.id = 0,
.dev = {
.platform_data = &s1d13xxxfb_data,
},
.num_resources = ARRAY_SIZE(s1d13xxxfb_resources),
.resource = s1d13xxxfb_resources,
};

static struct platform_device *devices[] __initdata = {
&s1d13xxxfb_device,
};


static int __init spmp_displ_init(void)
{


int ret = -ENODEV;
ret = platform_add_devices(devices, ARRAY_SIZE(devices));
return ret;
}

arch_initcall(spmp_displ_init);




kurtis
Я бегло глянул драйвер s1d13xxxfb.c, там походу пространство ввода-вывода экрана транслируется в основную область памяти. Нужно посмотреть в документации на процессор, куда он транслирует различную периферию, может вы просто с адресом ошиблись.

Цитата
что бы драйвер знал о том как и куда подключен дисплей.

В вашем случае все должно происходить прозрачно, т.к. все должно работать через память. Но, например, в драйвере есть такой код
Код
835         if (pdata && pdata->platform_init_video)
836                 pdata->platform_init_video();
где вызывается platform_init_video(), которое может делать что-то очень важно. Например, первое что приходит в голову, это правильно сконфигурировать пины процессора для работы с внешнем контроллером экрана.


У вас platform_add_devices(devices, ARRAY_SIZE(devices)) выполняется без ошибок?
Может ваша область памяти уже кем-то занята?
Idle
Цитата(kurtis @ Sep 4 2012, 13:03) *
Нужно посмотреть в документации на процессор, куда он транслирует различную периферию, может вы просто с адресом ошиблись.

soc закрытый, документации нет, у него только некие исходинки под ecos
Sanoend
Как уже сказали документации нет.
Исходников под eCos мало и большинство фейк.
Данные для сборки ядра брал дизасемблируя прошивку, а так же опирался на патч который обсуждался выше.
Память сейчас не занята, когда эта память была занята было сообщение :
Код
Epson S1D13XXX FB Driver
Trying to free nonexistent resource <0000000093000000-0000000093100000>

что бы убрать это сообщение я вырезал из патча который брал за основу Следующие вещи:
/arch/arm/boot/dts/spmp8000.dtsi
CODE

<------>axi {
<------><------>compatible = "simple-bus";
<------><------>#address-cells = <1>;
<------><------>#size-cells = <1>;
<------><------>ranges = <0x93000000 0x93000000 0x800000>;

<------><------>fb@93000000 {
<------><------><------>compatible = "sunplus,spmp8000-lcd";
<------><------><------>reg = <0x93000000 0x1000>;
<------><------><------>interrupt-parent = <&vic0>;
<------><------><------>interrupts = <23>;
<------><------>};

<------><------>axi-apb {
<------><------><------>compatible = "simple-bus";
<------><------><------>#address-cells = <1>;
<------><------><------>#size-cells = <1>;
<------><------><------>ranges = <0x93010000 0x93010000 0x10000>;

<------><------><------>dma@93010000 {
<------><------><------><------>compatible = "sunplus,spmp8000-apbdma-a";
<------><------><------><------>reg = <0x93010000 0x1000>;
<------><------><------><------>interrupt-parent = <&vic0>;
<------><------><------><------>interrupts = <24 25 26 27>;
<------><------><------>};

<------><------><------>i2s@93012000 {
<------><------><------><------>compatible = "sunplus,spmp8000-i2s-tx";
<------><------><------><------>reg = <0x93012000 0x1000>;
<------><------><------><------>interrupt-parent = <&vic0>;
<------><------><------><------>interrupts = <13>;
<------><------><------>};

<------><------><------>i2s@9301D000 {
<------><------><------><------>compatible = "sunplus,spmp8000-i2s-rx";
<------><------><------><------>reg = <0x9301D000 0x1000>;
<------><------><------><------>interrupt-parent = <&vic0>;
<------><------><------><------>interrupts = <14>;
<------><------><------>};

<------><------><------>adc@9301F000 {
<------><------><------><------>compatible = "sunplus,spmp8000-adc";
<------><------><------><------>reg = <0x9301F000 0x20>;
<------><------><------><------>interrupt-parent = <&vic1>;
<------><------><------><------>interrupts = <27>;
<------><------><------>};

<------><------><------>codec@9301F020 {
<------><------><------><------>compatible = "sunplus,spmp8000-codec";
<------><------><------><------>reg = <0x9301F020 0x20>;
<------><------><------>};
<------><------>};
<------>};



и файла борды убрал
CODE

<------>OF_DEV_AUXDATA("pwm-backlight", 0, "pwm-backlight",
<------><------><------>&backlight_letcool),
<------>OF_DEV_AUXDATA("sunplus,spmp8000-lcd", 0x93000000, "93000000.fb",
<------><------><------>&spmp8000fb_letcool),




Буду дальше копать исходную прошивку на проц. Попытаюсь найти есть ли там конфигурация ножек процессора.

Вот АСМ код инита дисплея из родной прошивки
CODE

// SPMP8000 LCD controller

typedef lcd_info_ctx {
uint32_t flags; // 0x00
uint16_t width; // 0x04
uint16_t height; // 0x06
uint16_t // 0x08
uint16_t // 0x0A
uint32_t frm_buff; // 0x0c
uint16_t osd_width; // 0x10
uint16_t osd_height; // 0x12

uint32_t osd_buff; // 0x18
uint8_t // 0x1c
uint8_t // 0x1d
}

setLCDFrameBuffer:
LDR R3, =lcd_info_ctx
STR R0, [R3,#0xC]
MOVL R3, 0x93000054
STR R0, [R3]
LDR R3, =lcd_direct_update
LDR R3, [R3]
CMP R3, #0
MOVLNE R3, 0x93000078
MOVNE R2, #1
STRNE R2, [R3]
BX LR

// void cyg_interrupt_create(cyg_vector_t vector, cyg_priority_t priority, cyg_addrword_t data, cyg_ISR_t* isr,
// cyg_DSR_t* dsr, cyg_handle_t* handle, cyg_interrupt* intr);

0029965C lcd_gen_init

00298CFC lcd_init2(width, height)
cyg_interrupt_create(0x17, 10, ???, lcd_isr_default)
-> 00297AF4 lcd_isr_default

002978C8 LCDC_S110_init
002972A8 hal_lcd_init
00292A74 scu_lcd_enable(freq_div_factor)

002995D0 lcd_suspend
00299514 lcd_resume

00298E68 osd_init2
00297870 OSDC_S110_init


LCDC_BASE 0x93000000

#define LCDC_CTRL (LCDC_BASE + 0x00) // write 0x10000
#define LCDC_UNK1 (LCDC_BASE + 0x04)
#define LCDC_UNK2 (LCDC_BASE + 0x08) // lcd_info_ctx[10]
#define LCDC_HOR_FBLK (LCDC_BASE + 0x0c)
#define LCDC_HOR_BBLK (LCDC_BASE + 0x14)
#define LCDC_HOR_SYNCW (LCDC_BASE + 0x28)
#define LCDC_VER_FBLK (LCDC_BASE + 0x18)
#define LCDC_VER_BBLK (LCDC_BASE + 0x1c)
#define LCDC_VER_SYNCW (LCDC_BASE + 0x2c)

.text:002D30B4 LDR R3, =gFrameBufferMgr ; param_R2
.text:002D30B8 LDR R2, =set_lcd_fb_format
.text:002D30BC STR R2, [R3]
.text:002D30C0 LDR R2, =getLCDBuffFormat
.text:002D30C4 STR R2, [R3,#4]
.text:002D30C8 LDR R2, =getLCDWidth
.text:002D30CC STR R2, [R3,#8]
.text:002D30D0 LDR R2, =getLCDHeight
.text:002D30D4 STR R2, [R3,#0xC]
.text:002D30D8 LDR R2, =getLCDShadowBuffer
.text:002D30DC STR R2, [R3,#0x10]
.text:002D30E0 LDR R2, =getLCDFrameBuffer
.text:002D30E4 STR R2, [R3,#0x14]
.text:002D30E8 LDR R2, =setLCDFrameBuffer
.text:002D30EC STR R2, [R3,#0x18]
.text:002D30F0 LDR R2, =lcd_flip
.text:002D30F4 STR R2, [R3,#0x1C]
.text:002D30F8 LDR R2, =lcd_gen_init
.text:002D30FC STR R2, [R3,#0x20]
.text:002D3100 LDR R2, =lcd_clear
.text:002D3104 STR R2, [R3,#0x24]
.text:002D3108 LDR R2, =wait_lcd_frame_end
.text:002D310C STR R2, [R3,#0x28]
.text:002D3110 LDR R2, =setLCDShadowBuffer
.text:002D3114 STR R2, [R3,#0x2C]
.text:002D3118 LDR R2, =lcd_suspend
.text:002D311C STR R2, [R3,#0x30]
.text:002D3120 LDR R2, =lcd_resume
.text:002D3124 STR R2, [R3,#0x34]
.text:002D3128 LDR R2, =lcd_enable_layer_no_osd
.text:002D312C STR R2, [R3,#0x38]
.text:002D3130 LDR R2, =lcd_set_bright_level ; param_R1
.text:002D3134 STR R2, [R3,#0x3C]
.text:002D3138 B loc_2D3264
.text:002D313C ; ---------------------------------------------------------------------------
.text:002D313C
.text:002D313C loc_2D313C ; CODE XREF: setFrameBufferMgr+4Cj
.text:002D313C LDR R0, =aSetframebuff_1 ; int
.text:002D3140 BL diag_printf
.text:002D3144 LDR R3, =gFrameBufferMgr ; param_R2
.text:002D3148 LDR R2, =set_osd_fb_format
.text:002D314C STR R2, [R3]
.text:002D3150 LDR R2, =getOSDBuffFormat
.text:002D3154 STR R2, [R3,#4]
.text:002D3158 LDR R2, =getOSDWidth
.text:002D315C STR R2, [R3,#8]
.text:002D3160 LDR R2, =getOSDHeight
.text:002D3164 STR R2, [R3,#0xC]
.text:002D3168 LDR R2, =getOSDShadowBuffer
.text:002D316C STR R2, [R3,#0x10]
.text:002D3170 LDR R2, =getOSDFrameBuffer
.text:002D3174 STR R2, [R3,#0x14]
.text:002D3178 LDR R2, =setOSDFrameBuffer
.text:002D317C STR R2, [R3,#0x18]
.text:002D3180 LDR R2, =lcd_osd_flip
.text:002D3184 STR R2, [R3,#0x1C]
.text:002D3188 LDR R2, =lcd_gen_init
.text:002D318C STR R2, [R3,#0x20]
.text:002D3190 LDR R2, =lcd_osd_clear
.text:002D3194 STR R2, [R3,#0x24]
.text:002D3198 LDR R2, =wait_lcd_frame_end
.text:002D319C STR R2, [R3,#0x28]
.text:002D31A0 LDR R2, =setOSDShadowBuffer
.text:002D31A4 STR R2, [R3,#0x2C]
.text:002D31A8 LDR R2, =lcd_suspend
.text:002D31AC STR R2, [R3,#0x30]
.text:002D31B0 LDR R2, =lcd_resume
.text:002D31B4 STR R2, [R3,#0x34]
.text:002D31B8 LDR R2, =lcd_enable_layer
.text:002D31BC STR R2, [R3,#0x38]
.text:002D31C0 LDR R2, =lcd_set_bright_level ; param_R1
.text:002D31C4 STR R2, [R3,#0x3C]
.text:002D31C8 B loc_2D3264
.text:002D31CC ; ---------------------------------------------------------------------------
.text:002D31CC
.text:002D31CC loc_2D31CC ; CODE XREF: setFrameBufferMgr+40j
.text:002D31CC LDR R0, =aSetframebuff_2 ; int
.text:002D31D0 BL diag_printf
.text:002D31D4 MOV R2, #2
.text:002D31D8 LDR R3, =g_FrameBuffDev
.text:002D31DC STR R2, [R3]
.text:002D31E0 LDR R3, =gFrameBufferMgr
.text:002D31E4 LDR R2, =set_tv_osd_fb_format
.text:002D31E8 STR R2, [R3]
.text:002D31EC LDR R2, =get_tv_osd_BuffFormat
.text:002D31F0 STR R2, [R3,#4]
.text:002D31F4 LDR R2, =get_tv_osd_width
.text:002D31F8 STR R2, [R3,#8]
.text:002D31FC LDR R2, =get_tv_osd_height
.text:002D3200 STR R2, [R3,#0xC]
.text:002D3204 LDR R2, =get_tv_osd_ShadowBuffer
.text:002D3208 STR R2, [R3,#0x10]
.text:002D320C LDR R2, =get_tv_osd_FrameBuffer
.text:002D3210 STR R2, [R3,#0x14]
.text:002D3214 LDR R2, =set_tv_osd_FrameBuffer
.text:002D3218 STR R2, [R3,#0x18]
.text:002D321C LDR R2, =tv_osd_flip
.text:002D3220 STR R2, [R3,#0x1C]
.text:002D3224 LDR R2, =tv_gen_init
.text:002D3228 STR R2, [R3,#0x20]
.text:002D322C LDR R2, =tv_osd_clear
.text:002D3230 STR R2, [R3,#0x24]
.text:002D3234 LDR R2, =tv_out_wait_frame_end
.text:002D3238 STR R2, [R3,#0x28]
.text:002D323C LDR R2, =set_tv_osd_ShadowBuffer
.text:002D3240 STR R2, [R3,#0x2C]
.text:002D3244 LDR R2, =tv_suspend
.text:002D3248 STR R2, [R3,#0x30]
.text:002D324C LDR R2, =tv_resume
.text:002D3250 STR R2, [R3,#0x34]
.text:002D3254 LDR R2, =tv_enable_layer
.text:002D3258 STR R2, [R3,#0x38]
.text:002D325C LDR R2, =tv_set_bright_level
.text:002D3260 STR R2, [R3,#0x3C]
.text:002D3264
.text:002D3264 loc_2D3264 ; CODE XREF: setFrameBufferMgr+50j
.text:002D3264 ; setFrameBufferMgr+58j ...
.text:002D3264 BL cyg_scheduler_unlock
.text:002D3268 LDR R0, =aSetframebuff_3 ; int
.text:002D326C BL diag_printf
.text:002D3270 LDMFD SP, {R4,R11,SP,PC}
.text:002D3270 ; End of function setFrameBufferMgr




Посмотрел активность на шинах. На дисплей не подаётся клок. Копаю в эту сторону.
Sanoend
Новости и вопросы с полей.
На контроллер ЛСД не поступают тактовые импульсы.
Я обнаружил что в родной прошивке данный "клок" включается так:
CODE

EXPORT scu_set_disp_clk
scu_set_disp_clk
; CODE XREF: scu_lcm_enable+10^Yp
; scu_lcd_enable+4^Yp ...
LDR R2, =0x93007000 ;задать регистру Р2 адрес 0x93007000
LDR R3, [R2,#0x80] ;косвенно считать в регистр Р3 содержимое памяти по адресу Р2+смещение 0x80
BIC R3, R3, #0x100
STR R3, [R2,#0x80]
BIC R3, R3, #0xFF
SUB R0, R0, #1
ORR R0, R0, R3
STR R0, [R2,#0x80]
ORR R0, R0, #0x100
STR R0, [R2,#0x80]
BX LR
; End of function scu_set_disp_clk


Получается, что в ядре просто нужно создать таймер, который бы записывал по адресу 0x93007080 значение FF для включения и 00 для выключения.
Но я не как не могу найти в поисковике как писать драйвера таймеров, я попробовал решить проблему "в лоб" и сделать записть регистра вот так
writeb(0xFF, SPMP8000_SCU_A_BASE + SCU_A_LCD_CLK_CFG);
и вот так
__raw_writeb(0xFF, SPMP8000_SCU_A_BASE + SCU_A_LCD_CLK_CFG);
Соответсвенно задав в заголовочных файлах значения
Код
#define SPMP8000_SCU_A_BASE 0x93007000
#define SCU_A_LCD_CLK_CFG 0x80


И естественно получил ошибки типа
Unable to handle kernel NULL pointer dereference at virtual address 93007080
и
g request at virtual address 93007080
т.к. ядро естественно пытается обращатся к виртуальным адресам.

Подскажите пожалуйста как правильно написать драйвер clock и что можно взять за основу. За ранее спасибо.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.