Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: U-boot, mini2440, nand
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
a1ien
Собственно добавляю потдержку в новый 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 возникет где-то в таймере. Но из-за чего это может быть я незнаю. Может кто наставит на путь истины?

Может можно как-то узнать что не так в настройках таймера?
a1ien
Так вот что я накопал. Может мне теперь смогут помочь.
Вся проблемма начинается аж самой инициализации.
Первой сишной функцией которая вызывается является 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;

Моежт это всетаки косяк. Потому как очень странно выглядит такое обявление глобальных переменных.
aaarrr
Посмотрите, что из себя представляет get_PCLK().
a1ien
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
Dron_Gus
Во-первых, в новом убуте (с релокацией) в таймере нельзя использовать глобальные переменные, т.к. инициализация таймера вызывается еще до релокации и не сделать 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 */

Почему-то код не убрался в спойлер
a1ien
Цитата
Во-первых, в новом убуте (с релокацией) в таймере нельзя использовать глобальные переменные, т.к. инициализация таймера вызывается еще до релокации и не сделать fixup адресов. Соответственно Вы ловите сигнал #8, вероятно, при делении на ноль.

Да спасибо вы полностью подтвердили то что я подозревал. Угу именно при делении на 0 и ловлю сигнал #8.

Цитата
З.Ы. могу приложить timer.c от s3c2416, кажется таймеря идентичны.

Спс. щас буду править код.
Dron_Gus
Следующей проблеммой, очевидно, будет хитрый формат nand в области откуда грузится SPL (BL1). Тут тоже стоит глянуть в драйвер нанд от ОМАП и реализовать аналогичную команду "nandecc sw|hw". Если портирование - не спортивный интерес, то пишите, я сброшу драйвер от 2416 (тоже, вроде, аналогичный).
a1ien
Цитата
Следующей проблеммой, очевидно, будет хитрый формат nand в области откуда грузится SPL (BL1)

Ммм несовсем понял я просто взял драйвер нанд от s3c2410 он есть в убуте. Думаю поидее проблем недолжно быть. Плюс еще есть сорци совсем старого убута года этак 2008 в котором полностью работает моя плата.
Цитата
Если портирование - не спортивный интерес

Нет это спортивный интерес. Просто как практика в изучении убута.
Dron_Gus
Да. Видимо перепутал. У следующих контроллеров (2416, 2450, 6410) область первичного загрузчика пишется с нестандартной ECC и форматом OOB. Для большей отказоустойчивости. У меня при портировании это был основной затык (встроенный загрузчик не хотел грузить мой код), пока полностью не перекопал самсунговские исходники (s3c-u-boot-1.1.6)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.