|
STM342F4 и FSMC, эксплуатация |
|
|
|
Jun 27 2018, 07:47
|

Местный
  
Группа: Участник
Сообщений: 257
Регистрация: 5-09-17
Пользователь №: 99 126

|
Использую отладочную плату STM32F4Discovery (контроллер STM32F407) и LCD, подключенный по FSMC (дисплей от телефона Sony Ericsson K800i). Обмен данными с дисплеем идёт нормально до частоты процессора 112 МГц. Стоит поднять частоту до 168 МГц - при записи в видеопамять дисплея возникают сбои: неправильная запись данных или декодирует их как команды (при этом дисплею окончательно сносит крышу). Пробовал выставлять разные Address_Setup, Data_Setup - не помогло. Обнаружил, если снизить частоту тактирования на линию порта GPIO D7 - это !CS LCD до 2 МГц, или подсоединить этот вывод через резистор 820 Ом (с меньшими значениями не игрался), то всё работает корректно. Причём, дисплей заводится на сверх-быстрых времянках! В принципиальной схеме на телефон на каждой линии "дисплей-процессор" стоит конденсатор 33 пФ на землю. Дисплей соединён с отладочной платой "макаронами" длиной 10 см. На шине больше ничего кроме дисплея нет. Какие причины столь странного поведения? От чего без резистора на линии !CS дисплей глючит? Код настройки GPIO и FSMC ниже(работает): CODE void GPIO(void) { GPIO_InitTypeDef gpio;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_ GPIOE,ENABLE);
//LCD GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC); // D0 GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC); // D1 GPIO_PinAFConfig(GPIOD,GPIO_PinSource0 ,GPIO_AF_FSMC); // D2 GPIO_PinAFConfig(GPIOD,GPIO_PinSource1 ,GPIO_AF_FSMC); // D3 GPIO_PinAFConfig(GPIOE,GPIO_PinSource7 ,GPIO_AF_FSMC); // D4 GPIO_PinAFConfig(GPIOE,GPIO_PinSource8 ,GPIO_AF_FSMC); // D5 GPIO_PinAFConfig(GPIOE,GPIO_PinSource9 ,GPIO_AF_FSMC); // D6 GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC); // D7 GPIO_PinAFConfig(GPIOD,GPIO_PinSource11,GPIO_AF_FSMC); //A16 => RS GPIO_PinAFConfig(GPIOD,GPIO_PinSource7 ,GPIO_AF_FSMC); //NE1 => CS !!! ВОСПРИИМЧИВ К ПОМЕХАМ !!! РЕЗИСТОР ИЛИ ПОНИЗИТЬ ЧАСТОТУ GPIO D7 GPIO_PinAFConfig(GPIOD,GPIO_PinSource4 ,GPIO_AF_FSMC); //NOE => RD GPIO_PinAFConfig(GPIOD,GPIO_PinSource5 ,GPIO_AF_FSMC); //NWE => WR
gpio.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_7|GPIO_Pin_11 |GPIO_Pin_14|GPIO_Pin_15; gpio.GPIO_Mode=GPIO_Mode_AF; gpio.GPIO_Speed=GPIO_Speed_100MHz; gpio.GPIO_OType=GPIO_OType_PP; gpio.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_Init(GPIOD,&gpio);
gpio.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10; gpio.GPIO_Mode=GPIO_Mode_AF; gpio.GPIO_Speed=GPIO_Speed_100MHz; gpio.GPIO_OType=GPIO_OType_PP; gpio.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_Init(GPIOE,&gpio);
//LCD !RST B11 gpio.GPIO_Pin=GPIO_Pin_11; gpio.GPIO_Mode=GPIO_Mode_OUT; gpio.GPIO_Speed=GPIO_Speed_2MHz; gpio.GPIO_OType=GPIO_OType_PP; gpio.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_Init(GPIOB,&gpio);
//LCD WSYNC B3 gpio.GPIO_Pin=GPIO_Pin_3; gpio.GPIO_Mode=GPIO_Mode_IN; gpio.GPIO_Speed=GPIO_Speed_2MHz; gpio.GPIO_OType=GPIO_OType_PP; gpio.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_Init(GPIOB,&gpio);
//LED TEST D12 gpio.GPIO_Pin=GPIO_Pin_12; gpio.GPIO_Mode=GPIO_Mode_OUT; gpio.GPIO_Speed=GPIO_Speed_2MHz; gpio.GPIO_OType=GPIO_OType_PP; gpio.GPIO_PuPd=GPIO_PuPd_NOPULL; GPIO_Init(GPIOD,&gpio); }
void FSMC(void) //!!! HCLK=168 MHz { FSMC_NORSRAMTimingInitTypeDef fsmcTimingRead,fsmcTimingWrite; FSMC_NORSRAMInitTypeDef fsmc;
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);
fsmcTimingRead.FSMC_AddressSetupTime=1; //!!! fsmcTimingRead.FSMC_AddressHoldTime=0;
fsmcTimingRead.FSMC_DataSetupTime=13; //RD
fsmcTimingRead.FSMC_BusTurnAroundDuration=0; fsmcTimingRead.FSMC_CLKDivision=0; fsmcTimingRead.FSMC_DataLatency=0; fsmcTimingRead.FSMC_AccessMode=FSMC_AccessMode_A;
memcpy(&fsmcTimingWrite,&fsmcTimingRead,sizeof(fsmcTimingRead));
fsmcTimingWrite.FSMC_DataSetupTime=2; //WR
fsmc.FSMC_Bank=FSMC_Bank1_NORSRAM1; fsmc.FSMC_DataAddressMux=FSMC_DataAddressMux_Disable; fsmc.FSMC_MemoryType=FSMC_MemoryType_SRAM; fsmc.FSMC_MemoryDataWidth=FSMC_MemoryDataWidth_8b; fsmc.FSMC_BurstAccessMode=FSMC_BurstAccessMode_Disable; fsmc.FSMC_WaitSignalPolarity=FSMC_WaitSignalPolarity_Low; fsmc.FSMC_WrapMode=FSMC_WrapMode_Disable; fsmc.FSMC_WaitSignalActive=FSMC_WaitSignalActive_BeforeWaitState; fsmc.FSMC_WriteOperation=FSMC_WriteOperation_Enable; fsmc.FSMC_WaitSignal=FSMC_WaitSignal_Disable; fsmc.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable; fsmc.FSMC_ExtendedMode=FSMC_ExtendedMode_Enable; //For Different Read & Write Timings !!! fsmc.FSMC_WriteBurst=FSMC_WriteBurst_Disable;
fsmc.FSMC_ReadWriteTimingStruct=&fsmcTimingRead; fsmc.FSMC_WriteTimingStruct=&fsmcTimingWrite;
FSMC_NORSRAMInit(&fsmc); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1,ENABLE); }
Сообщение отредактировал IgorKossak - Jun 29 2018, 11:34
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
 |
Ответов
|
Jun 28 2018, 06:54
|
Местный
  
Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140

|
Цитата(ViKo @ Jun 28 2018, 08:38)  Дергается на каждый байт. Как для обычных 8 битовых пересылок. Если данные успевают поступать, то всё что в пределах одного #CS объединяется под ним. Вот недавно делал. Тут, правда, 16-битные пересылки, но это не меняет сути. Все 10 записей под одним #CS происходят. CODE __no_init volatile uint16_t cpld_regs[16] @0x60000000;
extern "C" void EXTI0_IRQHandler() { cpld_regs[0] = ppm8s.state.rx.chanel[0].fv_att_h.fvatt; cpld_regs[1] = ppm8s.state.rx.chanel[0].fv_att_v.fvatt; cpld_regs[2] = ppm8s.state.rx.chanel[1].fv_att_h.fvatt;; cpld_regs[3] = ppm8s.state.rx.chanel[1].fv_att_v.fvatt; cpld_regs[4] = ppm8s.state.rx.chanel[2].fv_att_h.fvatt;; cpld_regs[5] = ppm8s.state.rx.chanel[2].fv_att_v.fvatt; cpld_regs[6] = ppm8s.state.rx.chanel[3].fv_att_h.fvatt;; cpld_regs[7] = ppm8s.state.rx.chanel[3].fv_att_v.fvatt; cpld_regs[8] = (uint16_t)ppm8s.state.rx.dt_hp; cpld_regs[9] = (uint16_t)ppm8s.state.rx.dt_vp; GPIOE->BSRR = (1<<4); //LE_RF_OFF=1 EXTI->PR = EXTI_PR_PR0; GPIOE->BSRR = (1<<16+4); //LE_RF_OFF=0 }
|
|
|
|
|
Jun 28 2018, 11:27
|

Местный
  
Группа: Участник
Сообщений: 257
Регистрация: 5-09-17
Пользователь №: 99 126

|
Цитата(VladislavS @ Jun 28 2018, 06:54)  Если данные успевают поступать, то всё что в пределах одного #CS объединяется под ним. Вот недавно делал. Тут, правда, 16-битные пересылки, но это не меняет сути. Все 10 записей под одним #CS происходят. CODE __no_init volatile uint16_t cpld_regs[16] @0x60000000;
extern "C" void EXTI0_IRQHandler() { cpld_regs[0] = ppm8s.state.rx.chanel[0].fv_att_h.fvatt; cpld_regs[1] = ppm8s.state.rx.chanel[0].fv_att_v.fvatt; cpld_regs[2] = ppm8s.state.rx.chanel[1].fv_att_h.fvatt;; cpld_regs[3] = ppm8s.state.rx.chanel[1].fv_att_v.fvatt; cpld_regs[4] = ppm8s.state.rx.chanel[2].fv_att_h.fvatt;; cpld_regs[5] = ppm8s.state.rx.chanel[2].fv_att_v.fvatt; cpld_regs[6] = ppm8s.state.rx.chanel[3].fv_att_h.fvatt;; cpld_regs[7] = ppm8s.state.rx.chanel[3].fv_att_v.fvatt; cpld_regs[8] = (uint16_t)ppm8s.state.rx.dt_hp; cpld_regs[9] = (uint16_t)ppm8s.state.rx.dt_vp; GPIOE->BSRR = (1<<4); //LE_RF_OFF=1 EXTI->PR = EXTI_PR_PR0; GPIOE->BSRR = (1<<16+4); //LE_RF_OFF=0 }
Скиньте плиз свой инит FSMC, интересно глянуть его на предмет бурстов.
|
|
|
|
|
Jun 28 2018, 12:02
|
Местный
  
Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140

|
Цитата(__inline__ @ Jun 28 2018, 14:27)  Скиньте плиз свой инит FSMC, интересно глянуть его на предмет бурстов. Прошу прощения за магические числа, надо будет переписать...  Код //Инициализация FMC для доступа к регистрам CPLD FMC_Bank1->BCR1 = 0x1091; FMC_Bank1->BTR1 = 0x0FFF01F2; CODE FMC_BCR1_MBKEN = 1 FMC_BCR1_MUXEN = 0 FMC_BCR1_MTYP = 00 [SRAM] FMC_BCR1_MWID = 01 [16 бит] FMC_BCR1_FACCEN = 0 FMC_BCR1_BURSTEN = 0 FMC_BCR1_WAITPOL = 0 FMC_BCR1_WRAPMOD = 0 FMC_BCR1_WAITCFG = 0 FMC_BCR1_WREN = 1 FMC_BCR1_WAITEN = 0 FMC_BCR1_EXTMOD = 0 FMC_BCR1_ASYNCWAIT = 0 FMC_BCR1_CPSIZE = 000 FMC_BCR1_CBURSTRW = 0 FMC_BCR1_CCLKEN =0
FMC_BTR1_ADDSET = 2 FMC_BTR1_ADDHLD = F FMC_BTR1_DATAST = 1 FMC_BTR1_BUSTURN = F FMC_BTR1_CLKDIV = F FMC_BTR1_DATLAT = F FMC_BTR1_ACCMOD = 0 [A mode]
Ещё раз хочу отметить, что данные должны успевать поступать. В моём случае процессор молотит на 168 МГц и приведённый выше код скомпилирован очень эффективно. Быстрее, наверное, только DMA, и то не уверен. Всё происходит где-то за 250 нс (плюс/минус точно не помню). CODE LDR.W R3,??DataTable6_1 ;; 0x40013c14 LDRH R2,[R1, #+0] MOV R0,#+1610612736 STRH R2,[R0, #+0] LDRH R2,[R1, #+2] STRH R2,[R0, #+2] LDRH R2,[R1, #+4] STRH R2,[R0, #+4] LDRH R2,[R1, #+6] STRH R2,[R0, #+6] LDRH R2,[R1, #+8] STRH R2,[R0, #+8] LDRH R2,[R1, #+10] STRH R2,[R0, #+10] LDRH R2,[R1, #+12] STRH R2,[R0, #+12] LDRH R2,[R1, #+14] STRH R2,[R0, #+14] LDRB R2,[R1, #+16] STRH R2,[R0, #+16] MOVS R2,#+1 LDRB R1,[R1, #+17] STRH R1,[R0, #+18] MOVS R1,#+16 LDR.W R0,??DataTable6_2 ;; 0x40020c18 STR R1,[R0, #+1024] MOV R1,#+1048576 STR R1,[R0, #+1024] STR R2,[R3, #+0]
|
|
|
|
|
Jun 29 2018, 01:58
|
Местный
  
Группа: Свой
Сообщений: 475
Регистрация: 14-04-05
Из: Москва
Пользователь №: 4 140

|
Цитата(jcxz @ Jun 29 2018, 01:27)  А зачем LDRH/STRH? Потому что в С-коде написаны 16-битные пересылки. Компилятор не имел права ослушаться. Цитата(jcxz @ Jun 29 2018, 01:27)  Разве 32 бита из STR не будут автоматом распилены на две 16-битные записи контроллером шины? Будут, конечно. Только в скорости в моём случае уже не выиграть, я упёрся в скорость устройства в которое пишу, а вот читаемость кода пострадает. Режимы работы шины я настраивал с осциллографом под отладчиком. Отсюда и магические числа вылезли - после отладки просто скопировал значение регистров в код. PS: Да, можно немного сэкономить. Код *(uint32_t *)&cpld_regs[0] = *(uint32_t *)&ppm8s.state.rx.chanel[0]; *(uint32_t *)&cpld_regs[2] = *(uint32_t *)&ppm8s.state.rx.chanel[1]; *(uint32_t *)&cpld_regs[4] = *(uint32_t *)&ppm8s.state.rx.chanel[2]; *(uint32_t *)&cpld_regs[6] = *(uint32_t *)&ppm8s.state.rx.chanel[3]; cpld_regs[8] = (uint16_t)ppm8s.state.rx.dt_hp; //Эти поля uint8_t cpld_regs[9] = (uint16_t)ppm8s.state.rx.dt_vp; И получить LDR/STR на части структуры, которая случайно совпала по расположению в памяти с внешними регистрами. Но мне это категорически не нравится, так как структуру теперь менять ни-ни. А если собирать из двух LDRH один STR, то это ещё и проиграешь в результате. Что потом с этим через N лет кто-то без меня будет делать?
|
|
|
|
|
Jun 29 2018, 04:41
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(VladislavS @ Jun 29 2018, 04:58)  Но мне это категорически не нравится, так как структуру теперь менять ни-ни. А если собирать из двух LDRH один STR, то это ещё и проиграешь в результате. Я в таких случаях обычно использую union: Код union { struct { u16 r0, r1, ..., rx; } r16; struct { u32 r0, r1, ..., ry; } r32; }; Первый член (r16) - логическое представление данных внутри; второй (r32) - для 32-битных обращений при пересылке. Если не нравятся лишние элементы в длинном конечном пути к членам, то можно и без имён r16, r32, просто задав разные имена внутренним членам - современные компиляторы уже нормально понимают безымянные структуры. Имхо - получается наглядно. Хотя конечно - на вкус и цвет.... Цитата(VladislavS @ Jun 29 2018, 04:58)  Что потом с этим через N лет кто-то без меня будет делать?  Всё перепишут на Cortex-Mxxx?
|
|
|
|
Сообщений в этой теме
__inline__ STM342F4 и FSMC Jun 27 2018, 07:47 ViKo Глючит от отражений в линии. Спасают резисторы пос... Jun 27 2018, 08:03 __inline__ Цитата(ViKo @ Jun 27 2018, 09:03) Глючит ... Jun 27 2018, 12:12 k155la3 Надо посмотреть по док. на дисплей, выдерживаются ... Jun 27 2018, 08:54 ViKo Тогда нужно нарисовать на бумаге временную диаграм... Jun 27 2018, 12:20 __inline__ Цитата(ViKo @ Jun 27 2018, 13:20) Тогда н... Jun 27 2018, 13:27 ViKo По моему, шину нужно 8-битовой определить. А посыл... Jun 27 2018, 14:10 __inline__ Цитата(ViKo @ Jun 27 2018, 15:10) По моем... Jun 28 2018, 00:41  VladislavS Цитата(__inline__ @ Jun 28 2018, 03:41) И... Jun 28 2018, 04:15 __inline__ Ещё проделал эксперимент.
Устройство на шине одно... Jun 28 2018, 06:13 ViKo Адресом разделяйте. Jun 28 2018, 06:20 __inline__ Разобрался с быстрым копированием по 128 байт за р... Jul 1 2018, 14:07 __inline__ Дисплей активно работает по FSMC, сбоев не замечен... Jul 2 2018, 09:59 __inline__ Подключил дисплей к Nucleo-144 STM32H743. Переста... Jul 3 2018, 14:10 k155la3 Поосторожнее с "касанием пинцетом". Смен... Jul 3 2018, 15:28 __inline__ Цитата(k155la3 @ Jul 3 2018, 15:28) Поост... Jul 4 2018, 07:30 k155la3 Я не полагался бы так стопроцентно на HAL куба. Ск... Jul 5 2018, 04:05 __inline__ Цитата(k155la3 @ Jul 5 2018, 04:05) Я не ... Jul 5 2018, 07:12 __inline__ Обнаружил, что я не одинок, глюк присутствует ещё ... Jul 5 2018, 11:04 jcxz Цитата(__inline__ @ Jul 5 2018, 14:04) Об... Jul 5 2018, 11:18  __inline__ Цитата(jcxz @ Jul 5 2018, 11:18) И что ха... Jul 5 2018, 12:55   jcxz Цитата(__inline__ @ Jul 5 2018, 15:55) Ну... Jul 5 2018, 14:50 __inline__ Вопрос по поводу кеша возник не случайно. Так как ... Jul 5 2018, 16:50 __inline__ Всё просто замечательно!
Подключил дисплей... Jul 6 2018, 10:11 jcxz Цитата(__inline__ @ Jul 6 2018, 13:11) Ви... Jul 6 2018, 12:18  __inline__ Цитата(jcxz @ Jul 6 2018, 13:18) При FPS=... Jul 6 2018, 12:24   jcxz Цитата(__inline__ @ Jul 6 2018, 15:24) 24... Jul 6 2018, 12:29    __inline__ Цитата(jcxz @ Jul 6 2018, 13:29) Я это по... Jul 6 2018, 13:26     jcxz Цитата(__inline__ @ Jul 6 2018, 16:26) Та... Jul 6 2018, 16:37      __inline__ Цитата(jcxz @ Jul 6 2018, 17:37) 320*240/... Jul 7 2018, 04:10       jcxz Цитата(__inline__ @ Jul 7 2018, 07:10) 2 ... Jul 7 2018, 06:35        __inline__ Цитата(jcxz @ Jul 7 2018, 07:35) Я понима... Jul 7 2018, 06:47         jcxz Цитата(__inline__ @ Jul 7 2018, 09:47) То... Jul 7 2018, 06:56          __inline__ Цитата(jcxz @ Jul 7 2018, 07:56) Туннель ... Jul 7 2018, 07:10 __inline__ Собственно, что мы затеваем: http://vrtp.ru/index.... Jul 9 2018, 09:37
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|