Jump to content

    

Pasha 111

Свой
  • Content Count

    154
  • Joined

  • Last visited

Community Reputation

0 Обычный

About Pasha 111

  • Rank
    Частый гость
  • Birthday 04/14/1987

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array
  1. Да, это тоже интересно :) Вообще LPC1110 единственный проц в линейке, у которого 1 КБ ОЗУ, у остальных больше. Я вообще хотел что-то в SOIC корпусе, выбрал LPC1112 с 4 КБ ОЗУ, но в продаже его не было, а был LPC1110. Поскольку программа (которую уже тоже написал :) ) для него совсем простенькая, то решил взять то, что есть в магазине. А оно вона как вышло - написанием ещё двух программ...
  2. Будет время - напишу, самому интересно. Можно и в IAR написать. У них у обоих бутлоадеры не подходят получается :)
  3. Потому что у них там для LPC11xx и для LPC210x один исходник и лежит в \arm\src\flashloader\FlashNXPLPC210x. Там столько много всего понаписано, что разбираться не хотелось. Плюс мне же его надо было бы сокращать, чтобы он как раз в SRAM вмещался с остатком в 256 байт под буфер для страницы флеш, не факт что получилось бы (у IAR и Segger же не получилось, хотя может они и не думали, что будут процы с 1 КБ ОЗУ, и соответственно не оптимизировали особо код). Короче решил как решил. Ну и плюс если кому-то нужно будет, то этот исходник и не для IAR'а можно использовать (ну кроме .icf).
  4. Всё, написал свой Flash Loader для SPI. Суть такая: один процессор с большим объёмом памяти принимает по UART с компа прошивку и отправляет её по SPI в LPC1110, делая небольшие паузы каждые 256 байт (пока последний пишет во флеш). Вот файлы кода, может кому-то нужно. Здесь нужно обратить внимание вот на что: 1) из-за малого количества ОЗУ, пришлось урезать табличку прерываний с 0xC0 байт до 0x20, причём делать все 8 ячеек по 4 байта, т.к. в 8-ю линковщик кладёт контрольную сумму, которую потом сверяет ISP; 2) из-за такой урезанной таблички не работают никакие прерывания, кроме reset handler'а, да и не нужны они здесь. Плюс ко всему: "Before making any IAP call, either disable the interrupts or ensure that the user interrupt vectors are active in RAM and that the interrupt handlers reside in RAM. The IAP code does not use or disable interrupts.", так что прерывания я сразу отключаю. 3) "Flash programming commands use the top 32 bytes of on-chip RAM. The maximum stack usage in the user allocated stack space is 128 bytes and it grows downwards.", то есть нельзя трогать последние 32 байта ОЗУ - их использует IAP, также IAP может использовать до 128 байт стека, поэтому стек делаю размером 128 + 32 = 160 (0xA0) байт. SPI надо настроить как 16 data bits, POL = 0, PHASE = 0. При приёме каждого следующего слова оно отправляется обратно, чтобы Master мог проверить корректность приёма Оптимизация максимальная по размеру. Вот файлы для моего SPI Flash Loader'а: LPC1110FD20_SRAM.icf /*###ICF### Section handled by ICF editor, don't touch! ****/ /*-Editor annotation file-*/ /* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */ /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x10000000; /*-Memory Regions-*/ define symbol __ICFEDIT_region_ROM_start__ = 0x10000020; define symbol __ICFEDIT_region_ROM_end__ = 0x1000020F; define symbol __ICFEDIT_region_RAM_start__ = 0x10000210; define symbol __ICFEDIT_region_RAM_end__ = 0x100003DF; /*-Sizes-*/ define symbol __ICFEDIT_size_cstack__ = 0xA0; define symbol __ICFEDIT_size_heap__ = 0x00; /**** End of ICF editor section. ###ICF###*/ define symbol __CRP_start__ = 0x000002FC; define symbol __CRP_end__ = 0x000002FF; define memory mem with size = 4G; define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__] - mem:[from 0x10000050 to 0x10000060]; define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; define region CRP_region = mem:[from __CRP_start__ to __CRP_end__]; define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { }; define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; initialize by copy { readwrite }; do not initialize { section .noinit }; place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; place in ROM_region { readonly }; place in RAM_region { readwrite, block CSTACK, block HEAP }; place in CRP_region { section .crp }; cstartup.s MODULE ?cstartup ;; Forward declaration of sections. SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start PUBLIC __vector_table DATA __vector_table DCD sfe(CSTACK) ; Top of Stack DCD __iar_program_start ; Reset Handler DCD 0 DCD 0 DCD 0 DCD 0 DCD 0 DCD 0 ; NXP vector table CRC position END main.cpp //------------------------------------------------------------------------------ #include <intrinsics.h> #include <nxp/iolpc1110fd20.h> //------------------------------------------------------------------------------ #define PAGE_WORDS (256 / 2) #define PAGES_COUNT (16) #define IAP_LOCATION (0x1fff1ff1) #define IRC_IN_KHZ (12000) #define C_PREPARE_SECTOR (50) #define C_COPY_RAM_TO_FLASH (51) #define C_ERASE_SECTOR (52) #define C_BLANK_CHECK_SECTOR (53) #define C_READ_PART_ID (54) #define C_READ_BOOT_CODE_REV (55) #define C_COMPARE (56) #define C_REINVOKE_ISP (57) #define C_READ_UID (58) #define S_CMD_SUCCESS (0) #define S_INVALID_COMMAND (1) #define S_SRC_ADDR_ERROR (2) #define S_DST_ADDR_ERROR (3) #define S_SRC_ADDR_NOT_MAPPED (4) #define S_DST_ADDR_NOT_MAPPED (5) #define S_COUNT_ERROR (6) #define S_INVALID_SECTOR (7) #define S_SECTOR_NOT_BLANK (8) #define S_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION (9) #define S_COMPARE_ERROR (10) #define S_BUSY (11) #define S_INVALD_PARAM (12) //------------------------------------------------------------------------------ typedef unsigned int uint32; typedef unsigned short int uint16; typedef unsigned char uint8; typedef void (*IAP)(uint32 *, uint32 *); //------------------------------------------------------------------------------ __no_init uint16 buf[PAGE_WORDS]; __no_init uint32 command_param[5]; __no_init uint32 status_result[4]; IAP iap_entry = (IAP)IAP_LOCATION; uint16 word = 0; uint16 page = 0; //------------------------------------------------------------------------------ void main(void) { __disable_interrupt(); SYSMEMREMAP = 0x01; // SRAM remap // SYS, ROM, RAM, FLASHREG, FLASHARRAY, GPIO, SSP0, IOCON SYSAHBCLKCTRL |= 0x1085F; IOCON_PIO0_2 = 1; // SSEL0 IOCON_SCK_LOC = 2; // Selects SCK0 function in pin location PIO0_6/SCK0 IOCON_PIO0_6 = 2; // SCK0 IOCON_PIO0_8 = 1; // MISO0 IOCON_PIO0_9 = 1; // MOSI0 PRESETCTRL = 0x01; // deassert SSP0 reset SSP0CLKDIV = 1; // div = 1 SSP0CPSR = 2; // div = 2 SSP0CR0 = 0xF; // data bits = 16, pol=0, phase=0 SSP0CR1 = (1 << 1) | (1 << 2); // enable in slave mode; command_param[0] = C_PREPARE_SECTOR; command_param[1] = 0; command_param[2] = 0; command_param[3] = 0; command_param[4] = 0; iap_entry(command_param, status_result); command_param[0] = C_ERASE_SECTOR; command_param[1] = 0; command_param[2] = 0; command_param[3] = IRC_IN_KHZ; command_param[4] = 0; iap_entry(command_param, status_result); while(true) { if(SSP0SR & (1 << 2)) { buf[word] = SSP0DR; SSP0DR = buf[word]; word++; if(word == PAGE_WORDS) { command_param[0] = C_PREPARE_SECTOR; command_param[1] = 0; command_param[2] = 0; command_param[3] = 0; command_param[4] = 0; iap_entry(command_param, status_result); command_param[0] = C_COPY_RAM_TO_FLASH; command_param[1] = page * PAGE_WORDS * 2; command_param[2] = (uint32)buf; command_param[3] = PAGE_WORDS * 2; command_param[4] = IRC_IN_KHZ; iap_entry(command_param, status_result); page++; if(page == PAGES_COUNT) while(true); // end of flash word = 0; } } } } //------------------------------------------------------------------------------ Для отладки делаю так: 1) компилирую в IAR'е конечную прошивку для LPC1110 (жму F7); 2) загружаю и запускаю отладку в SRAM программы FlashLoader'а в другом окне IAR'а; 3) потом отправляю с компа прошивку по UART в другой проц, который после приёма кидает её в LPC1110 по SPI; 4) останавливаю отладку flash loadera и в первом окне IAR'а с конечной программой жму "Debug without downloading". 5) отлаживаю нужную программу. Весь процесс до начала отладки занимает секунд 10, не идеально, но всего в пару кликов и с возможностью отладки.
  5. Если снять эту галку, то при попытке прошить по Ctrl+D выскакивает сообщение: "RAM area configured for this target is too small. Abort debug session?". Решил попробовать написать свой прошивальщик, только через SPI. У меня LPC1110 соединён на плате с другим процессором по SPI. Хочу попробовать так: в LPC1110 в RAM загружаю через SWD программу для прошивки, которая принимает страницы по 256 байт по SPI и пишет их во flash используя IAP.
  6. Ну на офф. сайте написано вот что: Если зайти со страницы J-Link'а на "Here is the complete list of microcontrollers and memories that are supported by J-Link.", то про LPC1110 написано "Supported flash types: Parallel CFI NOR flash, Internal flash". То есть всё ок должно быть. Но мне кажется, то они просто всё семейство в список добавили и всё. Слишком большой у них с IAR'овским flash loader видимо, что 1 КБ ОЗУ не хватает :( Написать им можно наверно, но думаю что толку мало будет.
  7. SEGGER J-Link Commander V6.16d (Compiled Jun 21 2017 19:08:48) DLL version V6.16d, compiled Jun 21 2017 19:08:15
  8. Пробовал. Как J-Flash, так J-Flash Lite. Ещё вручную командами через J-Link Commander. Пишет: "RAM area configured for this target is too small. Failed to program tagret". Причём в J-Flash выбирал LPC1110, соответственно размеры памяти SRAM и Flash он отображает верно. Так всё прошивается, но только в SRAM.
  9. Всем привет! Проблема такая: есть проц LPC1110FD20 (4KB Flash, 1KB RAM, Cortex-M0). Там только SWD. Собственно микроконтроллер через SWD определяется, память через J-Mem можно посмотреть, можно reset сделать и т.д. Но при попытке прошить в IAR выскакивает сообщение с ошибкой: "Flash loader buffer size (136) cannot be smaller than page size (256)". Я так понял, когда загрузчик переписывается в RAM, ему остаётся только 136 байт под буфер для записи во флеш, а размер страницы 256 байт, поэтому дальше работать он не может. Что делать? На сайте IAR'а конкретно для LPC1110FD20 написано что всё ОК: что и флешлоадер есть, и отладка и dds и всё что хочешь. Может они скопом просто написали про всё семейство LPC11xx и не стали проверять под все процы? Может есть исходник загрузчика, чтобы его упростить конкретно под LPC1110, он ведь универсальный для них, и наверное есть лишнее что-то. Что посоветуете? Процов уже 15 штук куплено, печатные платы уже готовы. Знаю что есть LPC1112FD20, у которого 4 KB RAM. Его куплю если ничего уже не поможет. Да, UART, через который проц можно прошить средствами встроенного загрузчика, к сожалению на плате не разведён. Получается никак проц уже не прошить? P.S. Написал сейчас простенькую программу для мигания светодиодом, подключённым к процессору, и сделал .icf файл для настройки Linker'а для записи программы в SRAM - всё работает, светодиод мигает, отладка идёт. Так что проблема видимо именно в нехватке SRAM.
  10. prottoss Мне нужно отправлять по SPI данные сразу на несколько устройств. В одном случае я делаю один буфер и всё. А в случае управления chip select'ом через PIO я должен буфер разбить на несколько: по одному для каждого устройства, и отправлять их по очереди, чтобы chip select менять между отправками. Это лучше, конечно, чем отправлять через прерывания, но всё равно 1) неудобно и 2) не так эффективно.
  11. prottoss Ну это всё понятно, конечно, но дёргание chip select'а через PIO делает бесполезным использование DMA. DmitryM Почему нормально? Такое происходит только если в регистре настройки конкретного chip select'а выставлен в 1 бит CSAAT (Chip Select Active After Transfer), только тогда при передаче байт один за другим chip select будет выставлен на низкий уровень, а на высокий вернётся только после передачи элемента данных, где выставлен в 1 бит LASTXFER (Last Transfer). Так всё и работает при реализации передачи через прерывания. При работе через PDC так почему-то не работает, бит LASTXFER ни на что не влияет. Сейчас буду делать с данными-заглушками, так, по идее, должно работать, но способ не очень нравится.
  12. Всем привет! Решил для разгрузки процессора AT91SAM7X128 перенести весь обмен данными (UART, SPI) на работу через PDC. Написал один код для работы с PDC (pdc.h и pdc.cpp). А код для работы с UART и SPI его, соответственно, использует. Так вот UART теперь работает просто замечательно, а вот SPI - нет. Настроен он у меня для работы с Variable Peripheral, т.е. номер chip select'а указывается прямо в регистре данных (да, учёл, что PDC в этом режиме SPI переписывает куски по 4 байта за раз - значения регистра отправки). Проблема вот в чём: если SPI работает через прерывания (AT91C_SPI_RDRF и AT91C_SPI_TXEMPTY), то все отправляются как надо, а если включить PDC и использовать прерывания AT91C_SPI_ENDRX и AT91C_SPI_ENDTX (при абсолютно тех же настройках самого контроллера SPI), то всё работает так же, и переписываются те же данные, но chip select не стробирует, а один раз устанавливается на низкий уровень в самом начале передачи буфера, а потом, в самом конце, опять возвращается на высокий уровень. Бит AT91C_SPI_LASTXFER, помещенный в каждую ячейку буфера для отправки, не помогает. Нашёл на просторах инета вот такой вот ответ: Using PDC, how to toggle SPI Chip Select between each data transfer? Здесь рекомендуют в буфере каждую вторую ячейку использовать как заглушку, отправляя данные на неподключённый chip select. Тогда chip select начнёт стробироваться. Но ведь нужно тогда в 2 раза бОльший массив иметь, да и вообще, какие-то костыли получаются. Как правильно сделать, чтобы SPI нормально через PDC работал в режиме Variable Peripheral?
  13. VslavX Всё, разобрался. Первое, IarBuild ничего в stderr не выводит, но я всё равно подправил свой скрипт так, чтобы и данные с этого потока шли на обработку. Второе, студии, как оказалось, всё равно по какому потоку в неё сообщения об ошибках идут - всё выводит и, если соответствует формату, добавляет в Error List. Третье, понял что делает перловый скрипт :) Дело в том, что у студии и IAR'а формат ошибок отличаются. Студия отказывается добавлять ошибку в ErrorList, если в названии ошибки есть символы '[' и ']' (может быть и ещё есть), а у IAR'а как раз ошибки вроде "[Pe127]". Плюс должен быть пробел между словом "error" или "warning" и номером/скобкой, а у IAR'а его нет. Сам проверял сидел :) В итоге поменял скрипт и добавил туда парсер, который всё это и делает. Плюс заменяет ключевое слово "Remark" на "warning", ибо студия его не понимает. А сам скрипт теперь выводит ещё аргументы командной строки, с которыми его запустили. Вообщем вот IarBuild for MSVS script v0.1 :) IarBuild.zip
  14. VslavX Спасибо за скрипт! Никогда не понимал людей, пишущих на перле :) Если я правильно понял, то делает он не совсем это. IarBuild (только сейчас проверил) вообще ничего в stderr не выводит. А вот если в качестве компилятора для студии прописать какой-нибудь .bat-файл, а в нём написать: echo aaa.cpp(1) : Error 1 : error text >&2 то тогда в студии добавиться ошибка в Error List (строчка делает echo в stderr). Так что студия добавляет ошибки в Error List только если они пишутся в stderr. А строка "2>&1 | " копирует в stdout, то, что IarBuild выводит в свой stderr (чисто на всякий случай, как я понял), а потом результат всего вывода (оператор "|" считывает выходные данные одной команды и записывает их на вход другой команды) перенаправляется в перл скрипт (т.е. и выводы stdout и stderr). Так что реально должно работать и так: <путь и имя исполняемого файла компилятора> <параметры компилятора> > <исполняемый файл интерпретатора Perl> <имя файла скрипта> Просто в этом случае не будут видны возможные сообщения об ошибках самого компилятора. У меня нет интерпретатора перл, и ставить его лень, щас на c# по быстрому парсер напишу и выведу в stderr ошибки :)
  15. Делал в своё время класс для работы с монохромным изображением. Тут, как я понял, нужно тоже самое. Bitmap_mono.h #ifndef _CCBITMAP_MONO_H #define _CCBITMAP_MONO_H // Типы данных #ifndef TYPES_DEFINED #define TYPES_DEFINED typedef signed long long int64; typedef signed int int32; typedef signed short int int16; typedef signed char int8; typedef unsigned long long uint64; typedef unsigned int uint32; typedef unsigned short int uint16; typedef unsigned char uint8; #endif class CBITMAP_MONO { private: uint8 *buf; uint32 width; uint32 height; public: CBITMAP_MONO(void); ~CBITMAP_MONO(void); uint32 bind(uint8 *new_buf, uint32 new_width, uint32 new_height); void clear(uint32 color); void invert(); void set_pixel(uint32 x, uint32 y, uint32 color); uint32 get_pixel(uint32 x, uint32 y); }; #endif Bitmap_mono.cpp //------------------------------------------------------------------------------ #include "Bitmap_mono.h" //------------------------------------------------------------------------------ CBITMAP_MONO::CBITMAP_MONO(void) { buf = 0; } //------------------------------------------------------------------------------ CBITMAP_MONO::~CBITMAP_MONO(void) { } //------------------------------------------------------------------------------ uint32 CBITMAP_MONO::bind(uint8 *new_buf, uint32 new_width, uint32 new_height) { if(new_buf == 0) return 0; if(new_width == 0) return 0; if(new_height == 0) return 0; buf = new_buf; width = new_width; height = new_height; return 1; } //------------------------------------------------------------------------------ void CBITMAP_MONO::clear(uint32 color) { uint32 size = width * height / 8; if((width * height) % 8) size++; if(color) { for(uint32 i = 0; i < size; i++) buf[i] = 0xFF; } else { for(uint32 i = 0; i < size; i++) buf[i] = 0x00; } } //------------------------------------------------------------------------------ void CBITMAP_MONO::invert() { uint32 size = width * height / 8; if((width * height) % 8) size++; for(uint32 i = 0; i < size; i++) buf[i] = ~buf[i]; } //------------------------------------------------------------------------------ void CBITMAP_MONO::set_pixel(uint32 x, uint32 y, uint32 color) { if(x >= width) return; if(y >= height) return; uint32 pix_num = y * width + x; uint32 byte_num = pix_num / 8; uint8 img_byte = buf[byte_num]; if(color) { img_byte |= 1 << (pix_num % 8); buf[byte_num] = img_byte; } else { img_byte &= ~(1 << (pix_num % 8)); buf[byte_num] = img_byte; } } //------------------------------------------------------------------------------ uint32 CBITMAP_MONO::get_pixel(uint32 x, uint32 y) { if(x >= width) return 0x000000; if(y >= height) return 0x000000; uint32 pix_num = y * width + x; uint32 byte_num = pix_num / 8; uint8 img_byte = buf[byte_num]; if(img_byte & (1 << (pix_num % 8))) return 0xFFFFFF; else return 0x000000; } //------------------------------------------------------------------------------ Использование: const uint32 width = 20; const uint32 height = 35; uint8 buf[width * height / 8 + 1]; CBITMAP_MONO bmp; bmp.bind(buf, width, height); bmp.set_pixel(3, 14, 1); if(bmp.get_pixel(3, 14)) { // .... } Да, если хочется юзать STL, то там есть стандартный контейнер - bitset http://www.cplusplus.com/reference/stl/bitset/ Правда неизвестно как он реализован в IAR'е и сколько памяти будет занимать.