jcxz 243 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 17 часов назад, Ruslan1 сказал: Димаю, что-то не так с рефрешем при перепутанных A10/A11 и какая-то часть ячеек портится, а дальше косвенная адресация приводит к крешу. Бурст моим МК не поддерживается, так что остается рефреш банков. При рефреше вроде как линии адреса вообще не используются. А адрес получается от внутреннего счётчика рефреша в чипе SDRAM. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 5 hours ago, jcxz said: При рефреше вроде как линии адреса вообще не используются. А адрес получается от внутреннего счётчика рефреша в чипе SDRAM. Знаю только что с перепутанными линиями работает плохо, а если запаять A10-A11 правильно, то начинает работать корректно. Вариантов тут всего два: 1) что-то в самой SDRAM в случае перепутанных A10-A11 работает "не так". 2) ошибка в программе: что-то такое, что при использовании 8-мегабайтной микросхемы незаметно, а при использовании первых 8 мегабайт из 32-Мб микросхемы с перепутанными A10-A11 проявляется. Например, попытка выйти за границы памяти (косвенная адресация, стек, и т.д.). Мне важно понять, что это именно (1), а не (2) и проблема действительно решается перепайкой, а не просто становится незаметна. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 3 часа назад, Ruslan1 сказал: Например, попытка выйти за границы памяти (косвенная адресация, стек, и т.д.). Это решается элементарно использованием MPU. Для Cortex-M использование MPU - это признак хорошего тона при написании ПО в любом случае. имхо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 17 minutes ago, jcxz said: Это решается элементарно использованием MPU. Для Cortex-M использование MPU - это признак хорошего тона при написании ПО в любом случае. имхо. Не понял, можете пояснить? как использование MPU может создать ошибку, которую не видно при использовании другой микросхемы памяти? У меня в файле *.sct прописано что есть только 8 мегабайт (да и то разделено на два фрагмента): ; ************************************************************* ; *** Scatter file for firmware *** ; ************************************************************* LR_IROM1 0x08020000 0x000D0000 { ; load region size_region ER_IROM1 0x08020000 0x000D0000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00020000 { ; RW data .ANY (+RW +ZI) } RW_IRAM3 0x20020000 0x00010000 { ; stack for FreeRTOS data } RW_IRAM2 0x10000000 0x00010000 { ; CCM startup_stm32f4xx.o (STACK) *(.ccm) } RW_RAM1 0xC0000000 UNINIT 0x00700000 { ; 7MB RAM stack for FreeRTOS *(.ram1) } RW_RAM2 0xC0700000 UNINIT 0x00100000 { ; 1MB for static vars *(.ram) } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 18 минут назад, Ruslan1 сказал: Не понял, можете пояснить? как использование MPU может создать ошибку, которую не видно при использовании другой микросхемы памяти? Внимательнее посмотрите какую часть вашего сообщения я процитировал. MPU позволяет выявить попытки выхода за границы существующих регионов памяти. Для регионов реально существующей памяти нужно разрешить доступ (желательно - разные типы для областей data rw, data ro, исполняемого кода и пространства IO-портов), а для всего адресного пространства поставить запрет на любой доступ (фоновым регионом с низким приоритетом). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DmitryM 0 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 10 hours ago, jcxz said: При рефреше вроде как линии адреса вообще не используются. А адрес получается от внутреннего счётчика рефреша в чипе SDRAM. Заблуждение. Address inputs: A[12:0] are sampled during the ACTIVE command (row address A[12:0]) and READ or WRITE command (column address A[9:0] and A11 for x4; A[9:0] for x8; A[8:0] for x16; with A10 defining auto precharge) to select one location out of the memory array in the respective bank. A10 is sampled during a PRECHARGE command to determine if all banks are to be precharged (A10 HIGH) or bank selected by BA[1:0] (LOW). The address inputs also provide the op-code during a LOAD MODE REGISTER command. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 27 minutes ago, DmitryM said: Заблуждение. Address inputs: A[12:0] are sampled during the ACTIVE command (row address A[12:0]) and READ or WRITE command (column address A[9:0] and A11 for x4; A[9:0] for x8; A[8:0] for x16; with A10 defining auto precharge) to select one location out of the memory array in the respective bank. A10 is sampled during a PRECHARGE command to determine if all banks are to be precharged (A10 HIGH) or bank selected by BA[1:0] (LOW). The address inputs also provide the op-code during a LOAD MODE REGISTER command. посмотрите мое сообщение от 19 декабря:https://electronix.ru/forum/index.php?app=forums&module=forums&controller=topic&id=146583&do=findComment&comment=1600287. Цитата оттуда: Quote The AutoPrecharge is not supported. FMC_A[10] must be connected to the external memory address A[10] but it will be always driven ‘low’. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 1 hour ago, jcxz said: Внимательнее посмотрите какую часть вашего сообщения я процитировал. MPU позволяет выявить попытки выхода за границы существующих регионов памяти. Для регионов реально существующей памяти нужно разрешить доступ (желательно - разные типы для областей data rw, data ro, исполняемого кода и пространства IO-портов), а для всего адресного пространства поставить запрет на любой доступ (фоновым регионом с низким приоритетом). Понял, спасибо. MPU сейчас не применяю, и даже не возникло мысли с помощью MPU вылавливать выход за границы. Отличная идея, вставлю в план работ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 15 января, 2019 Опубликовано 15 января, 2019 · Жалоба 5 часов назад, Ruslan1 сказал: Понял, спасибо. MPU сейчас не применяю, и даже не возникло мысли с помощью MPU вылавливать выход за границы. Отличная идея, вставлю в план работ. Может Вам поможет - приведу свою функцию инициализации MPU для проекта на таком же МК (STM32F429): //Инит MPU void MPUinit() { #if MPU_ENABLE #define T(base, size, tex, c, b, s, ap, xn, srd) \ {(base##ULL) >> size << size, \ (size) - 1 << 1 | (ap) << 24 | (xn) << 28 | (srd) << 8 | \ (tex) << 19 | (c) << 17 | (b) << 16 | (s) << 18} struct { u32 addr, attr; } static const t[] = { //приоритет регионов возрастает сверху вниз // s // i t s // z e a x r //base e x c b s p n d #if defined(_CODE_RAM) T(0x00000000, 32, 0, 0, 1, 1, 3, 1, 0x59), //IO T(0x10000000, 16, 0, 1, 0, 0, 7, 0, 0), //RAM_regionA (код) T(0x20000000, 18, 0, 1, 0, 0, 7, 0, 0xF8), //RAM_regionB (код) T(0x20000000, 18, 0, 1, 0, 1, 3, 1, 0xC7), //RAM_regionC (данные) T(0x40024000, 12, 0, 1, 0, 1, 3, 1, 0), //RAM_regionD (данные) T(0xD0000000, 23, 0, 1, 1, 1, 3, 1, 0) //SDRAM_region (данные) #elif defined(_CODE_SDRAM) T(0x00000000, 32, 0, 0, 1, 1, 3, 1, 0x59), //IO T(0x10000000, 16, 0, 1, 0, 1, 3, 1, 0), //RAM_regionA (данные) T(0x20000000, 17, 0, 1, 0, 0, 7, 0, 0), //RAM_regionB (код) T(0x20020000, 16, 0, 1, 0, 1, 3, 1, 0), //RAM_regionB (данные) T(0x40024000, 12, 0, 1, 0, 1, 3, 1, 0), //RAM_regionD (данные) T(0xD0000000, 23, 0, 1, 1, 1, 3, 1, 0), //SDRAM_regionB (данные) T(0xD0000000, 18, 0, 1, 1, 0, 7, 0, 0) //SDRAM_regionA (код) #else T(0x00000000, 32, 0, 0, 1, 1, 3, 1, 0x59), //IO T(0x08000000, 21, 0, 1, 0, 0, 7, 0, 0), //FLASH_regionA (код) T(0x10000000, 16, 0, 1, 0, 1, 3, 1, 0), //RAM_regionA (данные) T(0x20000000, 18, 0, 1, 0, 1, 3, 1, 0xC0), //RAM_regionB (данные) T(0x2002FFE0, 5, 0, 1, 0, 0, 7, 0, 0), //RAM_regionC (код) T(0x40024000, 12, 0, 1, 0, 1, 3, 1, 0), //RAM_regionD (данные) T(0xD0000000, 23, 0, 1, 1, 1, 3, 1, 0) //SDRAM_region (данные) #endif }; ASSERT_STATIC(ncell(t) < 9, 0); //кол-во регионов, определённых в t, должно быть не более 8 __DSB(); __ISB(); NVIC.MPU.CTRL = 0; if (((volatile u8 *)&NVIC.MPU.TYPE)[1] < ncell(t)) trap(TRAP_INTERNAL); u32 j; int i = ncell(t) - 1; do { NVIC.MPU.RNR = i; NVIC.MPU.RGN[0].RASR_L = j = t[i].attr; NVIC.MPU.RGN[0].RBAR = t[i].addr; NVIC.MPU.RGN[0].RASR_H = j >> 16; NVIC.MPU.RGN[0].RASR_L = j | B0; } while (--i >= 0); NVIC.HFSR = B1 | B30; //чистим статусы fault-ов NVIC.CFSR = ~0; //чистим статусы fault-ов NVIC.MPU.CTRL = B0; __DSB(); __ISB(); #undef T #endif //MPU_ENABLE } #if defined(_CODE_RAM) - компиляция для выполнения кода из SRAM; #elif defined(_CODE_SDRAM) - компиляция для выполнения кода из SDRAM; остальное - выполнение из флешь. 6 часов назад, DmitryM сказал: Заблуждение. precharge - это не рефреш. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 11 часов назад, jcxz сказал: ASSERT_STATIC(ncell(t) < 9, 0); //кол-во регионов, определённых в t, должно быть не более 8 Можно взглянуть на реализацию этого макроса? И ncell() тоже... Больно интересно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 2 часа назад, Arlleex сказал: Можно взглянуть на реализацию этого макроса? И ncell() тоже... Больно интересно А, ну да, как-то не подумал ncell() - это у меня стандартный макрос, возвращающий количество элементов массива, используется в куче мест кода; ASSERT_STATIC() - макрос, из названия которого следует, что его задача аналогична задаче стандартного макроса ASSERT(), но он проверяет условие на этапе компиляции и не создаёт исполняемого кода; удобен там где хочется проверить на валидность некоторые константы заданные сложными выражениями (не вычисляемыми препроцессором - содержащими enum/sizeof() и пр.), которые невозможно вычислить внутри условного #if...#endif, но неохота генерить лишний исполняемый код, да и хочется, чтобы при неверном условии компиляция просто не происходила. На всякий случай вставил сюда почти все свои общие макросы, вдруг ещё чего забыл Спойлер #define concatAB_(a, b) a##b #define concatABC_(a, b, c) a##b##c #define concatABCD_(a, b, c, d) a##b##c##d #define concatABCDE_(a, b, c, d, e) a##b##c##d##e #define concatABCDEF_(a, b, c, d, e, f) a##b##c##d##e##f #define concatAB(a, b) concatAB_(a, b) #define concatABC(a, b, c) concatABC_(a, b, c) #define concatABCD(a, b, c, d) concatABCD_(a, b, c, d) #define concatABCDE(a, b, c, d, e) concatABCDE_(a, b, c, d, e) #define concatABCDEF(a, b, c, d, e, f) concatABCDEF_(a, b, c, d, e, f) #define concatVOID #define concat_SUBST2(a, b, c, d, e, f, g, h, i, j, k, l, ...) \ a##b##c##d##e##f##g##h##i##j##k##l #define concat_SUBST(...) concat_SUBST2(__VA_ARGS__) #define concat(...) concat_SUBST(__VA_ARGS__, concatVOID, concatVOID, \ concatVOID, concatVOID, concatVOID, concatVOID, concatVOID, concatVOID, \ concatVOID, concatVOID) #define selectA(a, ...) a #define selectB(a, b, ...) b #define selectC(a, b, c, ...) c #define selectD(a, b, c, d, ...) d #define selectE(a, b, c, d, e, ...) e #define selectF(a, b, c, d, e, f, ...) f #define lenof(var) (sizeof(var) * ((CHAR_BIT + 7) / 8)) #define ncell(m) (sizeof(m) / sizeof((m)[0])) #define shift(a, b) (((b) > 0) ? (a) << (b): (!(b)) ? (a): (a) >> -(b)) #define ptrsizeof(m) (void *)&(m), sizeof(m) #define offsetof(typ, member) (size_t)&(((typ *)NULL)->member) #define sizof(typ, member) sizeof(((typ *)NULL)->member) #define MIN(a, b) (((a) < (b)) ? (a): (b)) #define MAX(a, b) (((a) > (b)) ? (a): (b)) #define isMulti(a, b) ((a) / (b) * (b) == (a)) //a is a multiple of b? #define divCeil(a, b) (((a) + (b) - 1) / (b)) //деление a/b с округлением до ближайшего большего целого #define divRound(a, b) (((a) + (b) / 2) / (b)) //деление a/b с округлением до ближайшего целого #define assert_static(x) ((x) ? 1: 1 / (x)) //проверка условия x и генерация ошибки компиляции если x==0 #define ASSERT_STATIC(x, n) enum {concatAB(ASSERT_STATIC_, n) = (x) ? 1: 1 / (uint)(x)} //аналогично assert_static(), но для вставки как строка кода, а не как выражение #define TO_STRING_SUBST2(a) "" #a #define TO_STRING(a) TO_STRING_SUBST2(a) #define toSW(a, b) ((a) | (uint)(b) << 8) #define toDW(a, b, c, d) ((a) | (u32)(b) << 8 | (u32)(c) << 16 | (u32)(d) << 24) //Приведение x к типу UQ0.16, SQ1.15, UQ0.32, SQ1.31 соответственно. #define toUQ16(x) ((((double)(x) * B16) >= B16) ? B16 - 1: (uint)((double)(x) * B16)) #define toSQ16(x) ((((double)(x) * B15) >= B15) ? (s16)(B15 - 1): (((double)(x) * B15) <= (s16)B15) ? 1 - (s16)B15: (int)((double)(x) * B15)) #define toUQ32(x) ((((double)(x) * B32) >= B32) ? B32 - 1: (u32)((double)(x) * B32)) #define toSQ32(x) ((((double)(x) * B31) >= B31) ? (s32)(B31 - 1): (((double)(x) * B31) <= (s32)B31) ? 1 - (s32)B31: (s32)((double)(x) * B31)) #define toSQ16s(x) ((((double)(x) * B15) >= B15) ? (s16)B15: ((double)(x) > 0) ? (s16)((double)-(x) * B15): assert_static(0)) #define toSQ32s(x) ((((double)(x) * B31) >= B31) ? (s32)B31: ((double)(x) > 0) ? (s32)((double)-(x) * B31): assert_static(0)) Второй аргумент ASSERT_STATIC() это просто порядковый номер этого макроса внутри данной области видимости где он используется. В приведённом коде - внутри функции MPUinit(). Если макрос используется не внутри функции, а просто в файле - то порядковый номер внутри этого файла. Я просто не смог придумать как сделать такую проверку без порядкового номера, в случае если в данной области видимости нужно использовать несколько ASSERT_STATIC(). Может кто придумает лучше, как обойтись без этого номера? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 190 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба Только что, jcxz сказал: На всякий случай вставил сюда почти все свои общие макросы, вдруг ещё чего забыл Благодарю, поизучаю трюки Сейчас просто решил для себя тоже создать некую базу удобных макросов, вот и собираю по крупицам интересные и полезные макросы для себя. Только что, jcxz сказал: Может кто придумает лучше, как обойтись без этого номера? Использовать __LINE__? Правда, тогда ASSERT_STATIC нельзя будет использовать в одной и той же строке кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Ruslan1 17 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 15 hours ago, jcxz said: Может Вам поможет - приведу свою функцию инициализации MPU для проекта на таком же МК (STM32F429): Огромное спасибо! Не знаю поможет или нет, но не использовать имеющиеся в МК ресурсы, позволяющие увеличить надежность - это грех. Так что даже специальный Issue создал "задействовать MPU" в моем проекте, чтоб не забыть и не потерять. Копирайт в коде- jcxz/Omsk/Russia :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 243 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 1 час назад, Arlleex сказал: Благодарю, поизучаю трюки Я старался давать говорящие имена, но если что будет непонятно по макросам - спрашивайте. Цитата Использовать __LINE__? Правда, тогда ASSERT_STATIC нельзя будет использовать в одной и той же строке кода. Спасибо!! Хорошее решение. Как то я не подумал про predefined preprocessor symbols. Проверил такое решение - работает. Только я использовал не __LINE__, а __COUNTER__. Теперь выглядит так: #define ASSERT_STATIC(x) enum {concatAB(ASSERT_STATIC_, __COUNTER__) = (x) ? 1: 1 / (x)} так можно и несколько их писать в одной строке (хотя я так не делаю :) 45 минут назад, Ruslan1 сказал: Копирайт в коде- jcxz/Omsk/Russia :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 16 января, 2019 Опубликовано 16 января, 2019 · Жалоба 6 hours ago, jcxz said: Может кто придумает лучше, как обойтись без этого номера? Вы же используете IAR, так почему бы не использовать static_assert? Правда придётся задействовать компилятор Си++, но он же переварит сишный код. 6 hours ago, jcxz said: #define sizof(typ, member) sizeof(((typ *)NULL)->member) Название макроса... мммм... мягко говоря опасное Слишком коррелирует с sizeof. 21 hours ago, jcxz said: Может Вам поможет - приведу свою функцию инициализации MPU для проекта на таком же МК (STM32F429) Класс! Спасибо! Я думаю, для LPC4337 не слишком долго адаптировать, MPU-то всё равно платформенно независим Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться