|
U-boot, mini2440, nand |
|
|
|
Mar 23 2012, 20:06
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 2-02-11
Пользователь №: 62 660

|
Собственно добавляю потдержку в новый u-boot платы mini2440(процессор s3c2440). Неполучается подружить nand flash. Вот что имеем в качестве вывода. CODE NAND: board_nand_init() end of nand_init hwcontrol(): 0xff 0x83 hwcontrol(): 0xffffffff 0x81 raise: Signal # 8 caught raise: Signal # 8 caught dev_ready hwcontrol(): 0x90 0x83 hwcontrol(): 0x00 0x85 hwcontrol(): 0xffffffff 0x81 raise: Signal # 8 caught raise: Signal # 8 caught dev_ready hwcontrol(): 0x90 0x83 hwcontrol(): 0x00 0x85 hwcontrol(): 0xffffffff 0x81 raise: Signal # 8 caught raise: Signal # 8 caught dev_ready hwcontrol(): 0x90 0x83 hwcontrol(): 0x00 0x85 hwcontrol(): 0xffffffff 0x81 raise: Signal # 8 caught raise: Signal # 8 caught dev_ready No NAND device found!!! Как я понимаю проследил в отладке raise: Signal # 8 caught возникет где-то в таймере. Но из-за чего это может быть я незнаю. Может кто наставит на путь истины? Может можно как-то узнать что не так в настройках таймера?
Сообщение отредактировал IgorKossak - Mar 26 2012, 07:23
Причина редактирования: [codebox]!!!
|
|
|
|
|
 |
Ответов
(1 - 8)
|
Mar 25 2012, 20:13
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 2-02-11
Пользователь №: 62 660

|
Так вот что я накопал. Может мне теперь смогут помочь. Вся проблемма начинается аж самой инициализации. Первой сишной функцией которая вызывается является board_init_f она выполняется еше во флеше в ней происходит вся основная инициализация, и таймеров в том числе. Тоесть вызывается вот такая функция. Цитата int timer_init(void) { struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); ulong tmr;
/* use PWM Timer 4 because it has no output */ /* prescaler for Timer 4 is 16 */ writel(0x0f00, &timers->tcfg0); if (timer_load_val == 0) { /* * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 * (default) and prescaler = 16. Should be 10390 * @33.25MHz and 15625 @ 50 MHz */ timer_load_val = get_PCLK() / (2 * 16 * 100); timer_clk = get_PCLK() / (2 * 16); } /* load value for 10 ms timeout */ lastdec = timer_load_val; writel(timer_load_val, &timers->tcntb4); /* auto load, manual update of timer 4 */ tmr = (readl(&timers->tcon) & ~0x0700000) | 0x0600000; writel(tmr, &timers->tcon); /* auto load, start timer 4 */ tmr = (tmr & ~0x0700000) | 0x0500000; writel(tmr, &timers->tcon); timestamp = 0;
return (0); } Тут надо обратить внимание на timer_load_val и на timer_clk. Эти переменные оказываются почемуто во флеше. Тоесть напрмер адресс переменной timer_load_val = 0x52600(флеш мапиться по нулевому адресу) И вовремя работы программы они естественно не меняются. А если еще и посмотреть бинарник которые прошиваю(и который создается во время сборки убута) то по адресу 0x52600 мы увидим нашу будующую переменную и притом отличную от 0. Внимание вопрос что я не так делаю. Ведь этот код относиться не к конкретно моей плате и даже не конкретно моему процессору, и код верный. Собственно дальше из-за этого кода все у меня и не работает. Так-как значения переменной равняется в моем случае 0x17 что по логике вобще не врно и естественно дальше все работает соверенно не так. ЗЫ. Переменные обявленны как , Код int timer_load_val = 0; static ulong timer_clk; Моежт это всетаки косяк. Потому как очень странно выглядит такое обявление глобальных переменных.
Сообщение отредактировал a1ien - Mar 25 2012, 20:26
|
|
|
|
|
Mar 25 2012, 20:37
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 2-02-11
Пользователь №: 62 660

|
get_PCLK() смотрел там все выглядит правильно. вот код CODE static ulong get_PLLCLK(int pllreg) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); ulong r, m, p, s;
if (pllreg == MPLL) r = readl(&clk_power->mpllcon); else if (pllreg == UPLL) r = readl(&clk_power->upllcon); else hang();
m = ((r & 0xFF000) >> 12) + 8; p = ((r & 0x003F0) >> 4) + 2; s = r & 0x3;
#if defined(CONFIG_S3C2440) if (pllreg == MPLL) return 2 * m * (CONFIG_SYS_CLK_FREQ / (p << s)); #endif return (CONFIG_SYS_CLK_FREQ * m) / (p << s);
}
/* return FCLK frequency */ ulong get_FCLK(void) { return get_PLLCLK(MPLL); } ulong get_HCLK(void) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power(); #ifdef CONFIG_S3C2440 switch (readl(&clk_power->clkdivn) & 0x6) { default: case 0: return get_FCLK(); case 2: return get_FCLK() / 2; case 4: return (readl(&clk_power->camdivn) & (1 << 9)) ? get_FCLK() / 8 : get_FCLK() / 4; case 6: return (readl(&clk_power->camdivn) & (1 << 8)) ? get_FCLK() / 6 : get_FCLK() / 3; } #else return (readl(&clk_power->clkdivn) & 2) ? get_FCLK() / 2 : get_FCLK(); #endif } ulong get_PCLK(void) { struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
return (readl(&clk_power->clkdivn) & 1) ? get_HCLK() / 2 : get_HCLK(); } Тоесть делает что и должна. Щас вчитываюсь внимательно в код. Смотрю что и как может тут реально косяк. Если кто хочет код посмотреть то можно в исходники убута залезть вот ссыочка сразу на файл https://github.com/a1ien/u-boot/blob/master...s3c24x0/timer.c
Сообщение отредактировал IgorKossak - Mar 26 2012, 07:24
Причина редактирования: [codebox]!!!
|
|
|
|
|
Mar 26 2012, 07:22
|

Профессионал
    
Группа: Свой
Сообщений: 1 202
Регистрация: 9-01-05
Из: Санкт-Петербург
Пользователь №: 1 861

|
Во-первых, в новом убуте (с релокацией) в таймере нельзя использовать глобальные переменные, т.к. инициализация таймера вызывается еще до релокации и не сделать fixup адресов. Соответственно Вы ловите сигнал #8, вероятно, при делении на ноль. Во-вторых, этот код работы с таймером достаточно древний. Гляньте, как сделано в каком-нить омапе. Надо расширить возвращаемое значение тиков до 64 бит. З.Ы. могу приложить timer.c от s3c2416, кажется таймеря идентичны. CODE /* * © Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * © Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Alex Zuepke <azu@sysgo.de> * * © Copyright 2002 * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */
#include <common.h>
#ifdef CONFIG_S3C2416
#include <asm/io.h> #include <asm/arch/s3c24x0_cpu.h> #include <div64.h>
DECLARE_GLOBAL_DATA_PTR;
#define TIMER_PREDIV_2 0 #define TIMER_PREDIV_4 1 #define TIMER_PREDIV_8 2 #define TIMER_PREDIV_16 3
/* * Timer is 16-bit * So we can have good (small) timer resolution OR good (big) overlap time * PCLK usualy 66 MHz * PCLK / 2 / 33 = 1 MHz, 1 uS @ tick, overlap after 65 mS * PCLK / 4 / 165 = 0.1 MHz ,10 uS @ tick, overlap after 650 mS * PCLK / 16 / 165 = 0.025 MHz, 40 uS @ tick, overlap after 2,5 S * ...etc */
#define TIMER_PRESCALER 165 #define TIMER_PREDIV TIMER_PREDIV_4 //2, 4, 8, 16
static inline unsigned long long tick_to_time(unsigned long long tick) { tick *= CONFIG_SYS_HZ; do_div(tick, gd->timer_rate_hz);
return tick; }
static inline unsigned long long usec_to_tick(unsigned long long usec) { usec *= gd->timer_rate_hz; do_div(usec, 1000000);
return usec; }
int timer_init(void) { struct s3c24x0_timers *timers = s3c24x0_get_base_timers(); ulong tmr;
/* use PWM Timer 4 because it has no output */ /* prescaler for Timer */ writel(((TIMER_PRESCALER - 1) << 8) | (TIMER_PRESCALER - 1), &timers->TCFG0); /* PREDIV */ writel((readl(&timers->TCFG1) & ~(0x0F << 16)) | (TIMER_PREDIV << 16), &timers->TCFG1); /* Reload value */ writel(0xFFFF, &timers->TCNTB4); /* auto load, manual update of Timer 4 */ tmr = (readl(&timers->TCON) & ~0x0700000) | 0x0600000; writel(tmr, &timers->TCON); /* auto load, start Timer 4 */ tmr = (tmr & ~0x0700000) | 0x0500000; writel(tmr, &timers->TCON); gd->lastinc = 0; gd->timer_rate_hz = get_PCLK() / (TIMER_PRESCALER * (1 << (TIMER_PREDIV + 1))); gd->tbu = gd->tbl = 0;
return (0); }
/* * macro to read the count-down 16 bit timer */ static inline ulong READ_TIMER16(void) { struct s3c24x0_timers *timers = s3c24x0_get_base_timers();
return (0xFFFF - ((readl(&timers->TCNTO4) & 0xFFFF))); }
static inline ulong READ_TIMER32(void) { ulong now = READ_TIMER16(); ulong tbl = gd->tbl; if (now >= (tbl & 0xFFFF)) tbl = (tbl & 0xFFFF0000) | now; else tbl = ((tbl & 0xFFFF0000) | now) + 0x00010000; return tbl; }
/* * Get the current 64 bit timer tick count */ unsigned long long get_ticks(void) { ulong now = READ_TIMER32();
/* increment tbu if tbl has rolled over */ if (now < gd->tbl) gd->tbu++; gd->tbl = now; return (((unsigned long long)gd->tbu) << 32) | gd->tbl; }
void __udelay(unsigned long usec) { unsigned long long start; unsigned long long tmo;
start = get_ticks(); /* get current timestamp */ tmo = usec_to_tick(usec); /* convert usecs to ticks */ if (tmo == 0) tmo = 1; while ((get_ticks() - start) < tmo) ; /* loop till time has passed */ }
/* * get_timer(base) can be used to check for timeouts or * to measure elasped time relative to an event: * * ulong start_time = get_timer(0) sets start_time to the current * time value. * get_timer(start_time) returns the time elapsed since then. * * The time is used in CONFIG_SYS_HZ units! */ ulong get_timer(ulong base) { return tick_to_time(get_ticks()) - base; }
ulong get_timer_masked (void) { return tick_to_time(get_ticks()); }
/* * Return the number of timer ticks per second. */ ulong get_tbclk(void) { return gd->timer_rate_hz; }
#endif /* CONFIG_S3C2416 */ Почему-то код не убрался в спойлер
Сообщение отредактировал IgorKossak - Mar 26 2012, 07:24
Причина редактирования: [codebox]!!!
--------------------
Если сверху смотреть, то сбоку кажется, что снизу ничего не видно.
|
|
|
|
|
Mar 26 2012, 08:31
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 2-02-11
Пользователь №: 62 660

|
Цитата Во-первых, в новом убуте (с релокацией) в таймере нельзя использовать глобальные переменные, т.к. инициализация таймера вызывается еще до релокации и не сделать fixup адресов. Соответственно Вы ловите сигнал #8, вероятно, при делении на ноль. Да спасибо вы полностью подтвердили то что я подозревал. Угу именно при делении на 0 и ловлю сигнал #8. Цитата З.Ы. могу приложить timer.c от s3c2416, кажется таймеря идентичны. Спс. щас буду править код.
Сообщение отредактировал a1ien - Mar 26 2012, 08:52
|
|
|
|
|
Mar 26 2012, 11:51
|
Участник

Группа: Участник
Сообщений: 21
Регистрация: 2-02-11
Пользователь №: 62 660

|
Цитата Следующей проблеммой, очевидно, будет хитрый формат nand в области откуда грузится SPL (BL1) Ммм несовсем понял я просто взял драйвер нанд от s3c2410 он есть в убуте. Думаю поидее проблем недолжно быть. Плюс еще есть сорци совсем старого убута года этак 2008 в котором полностью работает моя плата. Цитата Если портирование - не спортивный интерес Нет это спортивный интерес. Просто как практика в изучении убута.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|