vovka1960 0 18 июля, 2011 Опубликовано 18 июля, 2011 · Жалоба Имеем в наличие TMS320C6455. На входе второго клока - 40MHz. Т.е. тактовая частота DDR контроллера = 40*20/2 = 400МГц. Тактовая частота процессора = 1ГГц. Кроме того имеем 2 штуки MT47H32M16HR-25E c Tck=2.5nS и CL=5. Далее - пишется программа на С (без оптимизации), которая в цикле читает 200 раз косвенно по адресу читает из внутреннего ОЗУ в регистр некоторое значение. Потом дергается GPIO пин, подключенный к осциллографу, потом абсолютно идентичный цикл, в котором в качестве косвенного адреса выступает адрес DDRAM. И - снова дергает пин GPIO. Итог - время для 200 чтений внутренней памяти - 6.2uS, время для 200 чтений DDRAM - 22.6uS. Вычитаем, делим на 200 и получаем, что одно чтение (а читаю я словами по 32 бита - потому как две микросхемы по 16) из DDRAM занимает примерно 80nS. Вот и вопрос - не многовато ли? Настройки контроллера делались исключительно по формулам, приведенным в соответствующем PDF-е. Если что - иогу тут их выложить. Объясните - где тут фокус зарыт, почему так медленно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 236 18 июля, 2011 Опубликовано 18 июля, 2011 (изменено) · Жалоба Вы меряете не время чтения памяти, а время выполнения GPIO. Не удивлюсь, если один вывод в GPIO дольше чем все 200 чтений внутренней RAM. :) Неверная методика измерений. Надо делать примерно так: дёргаете ногой 1раз, делаете N чтений из DDR, дёргаете ногой 2раз, делаете N+M чтений из DDR, дёргаете ногой 3раз. Вычитаете время (2раз-1раз) из (3раз-2раз), делите на M. Да и программу лучше компилить с полной оптимизацией, объявив указатель чтения как: volatile u32 *p Изменено 18 июля, 2011 пользователем jcxz Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vovka1960 0 19 июля, 2011 Опубликовано 19 июля, 2011 · Жалоба Вы меряете не время чтения памяти, а время выполнения GPIO. Не удивлюсь, если один вывод в GPIO дольше чем все 200 чтений внутренней RAM. :) Увы - если бы в этом было дело.. Но суть в том, что с ног GPIO я начинал. И четко знаю, что состояние ног GPIO меняется с частотой 133 МГц. Т.е максимальная погрешность, вносимая обменом по GPIO составляет 8 нс. Т.е. ей можно пренебречь. На всякий случай - привожу текст программы: register volatile Uint32 *gpset, *gpclr; volatile Uint32 *pram, ram, *vram = &ram; Uint32 eram; unsigned short xxx; int i; gpset = &(((CSL_GpioRegs*)CSL_GPIO_0_REGS)->SET_DATA); gpclr = &(((CSL_GpioRegs*)CSL_GPIO_0_REGS)->CLR_DATA); ram - 0x12345678; for (;;) { *gpclr = CSL_FMK(GPIO_SET_DATA_SET4, CSL_GPIO_SET_DATA_SET_SET); for (i = 0, pram = (volatile Uint32 *) DDR2_BASE_ADDR; i < 200; i++, pram++) eram = *vram; *gpset = CSL_FMK(GPIO_SET_DATA_SET4, CSL_GPIO_SET_DATA_SET_SET); for (i = 0, pram = (volatile Uint32 *) DDR2_BASE_ADDR; i < 200; i++, pram++) eram = *pram; } А вот инициализация контроллера DDRAM: register Uint32 mask, mask2; /*PERCFG1 - enable DDRAM interface*/ CSL_FINST(((CSL_DevRegs*)CSL_DEV_REGS)->PERCFG1, DEV_PERCFG1_DDR2CTL, ENABLE); /*DMCCTL*/ CSL_FINST (((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->DMCCTL, DDR2_DMCCTL_IFRESET, ASSERT); mask = ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG; ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG = mask | CSL_DDR2_SDCFG_BOOT_UNLOCK_MASK; ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG = mask & ~(CSL_DDR2_SDCFG_BOOT_UNLOCK_MASK | CSL_DDR2_SDCFG_DDR_DRIVE_MASK); mask = ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG; ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG = mask | CSL_DDR2_SDCFG_TIMUNLOCK_MASK; /*SDTIM1*/ mask2 = CSL_FMK(DDR2_SDTIM1_T_RFC, 41) | CSL_FMK(DDR2_SDTIM1_T_RP, 4) | CSL_FMK(DDR2_SDTIM1_T_RCD, 4) | CSL_FMK(DDR2_SDTIM1_T_WR, 5) | CSL_FMK(DDR2_SDTIM1_T_RAS, 16) | CSL_FMK(DDR2_SDTIM1_T_RC, 22) | CSL_FMK(DDR2_SDTIM1_T_RRD, 4) | CSL_FMK(DDR2_SDTIM1_T_WTR, 2); ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDTIM1 = mask2; /*SDTIM2*/ mask2 = CSL_FMK(DDR2_SDTIM2_T_ODT, 2) | CSL_FMK(DDR2_SDTIM2_T_SXNR, 46) | CSL_FMK(DDR2_SDTIM2_T_SXRD, 199) | CSL_FMK(DDR2_SDTIM2_T_RTP, 2) | CSL_FMK(DDR2_SDTIM2_T_CKE, 2); ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDTIM2 = mask2; /* SDRFC*/ ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDRFC = CSL_FMK( DDR2_SDRFC_REFRESH_RATE, 1560 ); mask &= ~CSL_DDR2_SDCFG_TIMUNLOCK_MASK; ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG = mask; /*DMCCTL*/ CSL_FINS (((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->DMCCTL, DDR2_DMCCTL_RL, 6); mask &= ~(CSL_DDR2_SDCFG_NM_MASK|CSL_DDR2_SDCFG_CL_MASK|CSL_DDR2_SDCFG_IBANK_MASK|CSL_ DDR2_SDCFG_PAGESIZE_MASK); mask |= CSL_FMK(DDR2_SDCFG_NM, CSL_DDR2_SDCFG_NM_32BIT) | CSL_FMK(DDR2_SDCFG_CL, CSL_DDR2_SDCFG_CL_FIVE) | CSL_FMK(DDR2_SDCFG_IBANK, CSL_DDR2_SDCFG_IBANK_FOUR) | CSL_FMK(DDR2_SDCFG_PAGESIZE, CSL_DDR2_SDCFG_PAGESIZE_1024W_PAGE); ((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->SDCFG = mask; /*DMCCTL*/ CSL_FINST (((CSL_Ddr2Regs *) CSL_DDR2_0_REGS)->DMCCTL, DDR2_DMCCTL_IFRESET, RELEASE); Могу привести расчет значений, устанавливаемых в регистры.. Вроде - все делал аккуратно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться