Перейти к содержанию
    

allsettingsdone

Участник
  • Постов

    32
  • Зарегистрирован

  • Посещение

Весь контент allsettingsdone


  1. Понятно. Просто за последние пол года вы несколько раз мне очень помогли тут. И дело тут не в этом, я стараюсь всегда найти ответ сам и пишу тут только в крайних случаях. Но вы просто мой пример для подражания и кумир. Спасибо вам за всё.
  2. Антоха, спасибо тебе за помощь. Можно у тебя поинтересоваться, откуда у тебя такой богатый опыт во встраиваемых системах? Ты постоянно с этим работаешь на работе или это хобби?
  3. Мне удалось нормально собрать проект с линкер файлом, но с использованием другого тулчейна (GCC с сайта ti). В этом тулчейне экзешники названы по типу "msp-elf-gcc" или "msp-elf-as" и он весит около 520 МБ. В то же время в другом тулчейне они называются "msp-gcc" или "msp-as" и он весит около 125 МБ. Почему между ними такая разница и какой тулчейн следует использовать и где его лучше взять?
  4. Я не пойму почему он лезет в по этому пути, ведь файл с линкер скриптом лежит рядом с makefile (( Сделал так как вы советовали, теперь в выводе линковщик ругается так: msp430-gcc -mmcu=msp430f5529 -Tmsp430f5529.ld -o blink.elf blink.c f:/soft/sublimetext/msp430-gcc/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld.exe: error: no memory region specified for loadable section `.noinit.crt0' collect2: ld returned 1 exit status Но в линкер скрипте, который я хочу подключить, нет такой секции ".noinit.crt0". Я взял стандартный линкер скрипт с сайта ti. (скрипт во вложении) msp430f5529.zip
  5. То же самое: msp430-gcc -mmcu=msp430f5529 -Wl,-Tmsp430f5529.ld -o blink.elf blink.c c:/program files (x86)/sublimetext/msp430-gcc/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld.exe: cannot find files: No such file or directory c:/program files (x86)/sublimetext/msp430-gcc/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld.exe: cannot find (x86)/sublimetext/msp430-gcc/bin/../lib/gcc/../../msp430/lib/ldscripts/msp430f5529/: No such file or directory collect2: ld returned 1 exit status А вот без запятой: msp430-gcc -mmcu=msp430f5529 -Wl -Tmsp430f5529.ld -o blink.elf blink.c cc1.exe: error: unrecognized command line option '-Wl'
  6. Мой первый опыт с MSP430. Перед написанием makefile я решил просто проверить/поиграться с платой MSP430 Launchpad (f5529). В одной папке лежат следующие файлы: - blink.c - msp430f5529.ld Я пытаюсь выполнить в этой папке в командной строке: msp430-gcc -mmcu=msp430f5529 -Tmsp430f5529.ld -o blink.elf blink.c В итоге получаю следующий вывод: c:/program files (x86)/sublimetext/msp430-gcc/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld.exe: cannot find files: No such file or directory c:/program files (x86)/sublimetext/msp430-gcc/bin/../lib/gcc/msp430/4.6.3/../../../../msp430/bin/ld.exe: cannot find (x86)/sublimetext/msp430-gcc/bin/../lib/gcc/../../msp430/lib/ldscripts/msp430f5529/: No such file or directory collect2: ld returned 1 exit status Как я понял, линкер пытается найти линкер скрипт у себя в папках компилятора и не принимает линкер скрипт который я ему передаю. Как это правильно сделать?
  7. Как узнать число, которое нужно записать в AFRH9 и AFRH10, что бы включить альтернативную функцию USART1 на PA9, PA10 на STM32F407? (это число состоит из 4-ёх бит согласно стр. 287 RM0090)
  8. Как вы настраиваете альтернативные функции у GPIO с помощью регистров GPIOx_AFR (например при настройке USART1 на PA9, PA10 на STM32F407VG) ? В стандартном файле описания периферии (stm32f4xx.h) - нет информации и масок для работы с этим регистром. Просто высчитываете сами битовую маску и записываете в этот регистр готовое число?
  9. Так.. В первую очередь мне надо разобраться с синтаксисом makefile и *.ld , понять что за что отвечает и дальше уже пытаться собрать проект.
  10. Дело в том что не нужны костыли в проекте, для того что бы та или иная ошибка не выскакивала. Я бы хотел сделать "скелетный" проект для Sublime text2, и насколько я понимаю, эта ошибка появляется из-за того что я передаю в компилятор слишком мало параметров о самом микроконтроллере, и(или) не подключаю к проекту файл "startup_stm32f10x_md_vl.s". Тут кстати возникает вопрос - как правильно подключить этот файл к проекту? И какая разница компилятору подключен он или нет?
  11. Не получается собрать простенький проект на С++ в Sublime text2. Использую компилятор gcc(GNU Tools ARM Embedded), программу make с самописным простеньким makefile. Пути для gcc и make прописаны в PATH. Вот что пытаюсь собрать: int main() { } Вот настройки проекта sublime text2: { "folders": [ { "path": "." } ], "build_systems": [ { "name": "arm build", "cmd": ["make"], "working_dir": "${project_path}" } ], "settings": { "sublimeclang_options": [ "-std=c++11", "-Wall", "-I${project_path}" ] } } Содержимое makefile: all: arm-none-eabi-gcc main.cpp Вот что получаем на выходе: arm-none-eabi-gcc main.cpp c:/program files (x86)/gnu tools arm embedded/4.8 2014q2/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit': exit.c:(.text.exit+0x2c): undefined reference to `_exit' collect2.exe: error: ld returned 1 exit status make: *** [all] Error 1 [Finished in 0.4s with exit code 2] Как вы думаете, в чем проблема? проект прикрепляю: sm20.zip
  12. Вот допустим я делаю счетчик, пишу test0 DCWU 0xFFFF Затем уменьшаю на 1 ( MOV32 R0, #test0 SUB R0, #1) Её сохранять обратно в память таким образом? - STR R0, [#test0] ? Компилятор выделит память под 4 байта?
  13. Не могу понять как создавать и работать с переменными разного размера в ассемблере в Keil. Директивы DB, DW, DD выдают ошибку(похоже на то, что Keil их вообще не знает), BYTE, WORD, DWORD - то же самое. Как я понял директивы GBLL, GBLS, GBLA создают (в RAM?) переменную и далее ей можно придать значение используя SETA, SETL, SETS, но при попытке повторно сохранить значение этой переменной получаем ошибку при компиляции, да и не понятно где именно в памяти Keil разместит переменную. Можно конечно сделать так Var0 EQU 0x(адрес переменной в памяти), но есть ли другие(более удобные) способы ? И как вообще принято это делать?
  14. Это макрос и от пользователя может прийти что угодно (просто в этом случае я сразу прописал), вот скажем я с юарта буду посылать имя порта, в конечном итоге отправляя его в аргумент этого макроса, тогда получается что приплюсовывать "GPIO_BSRR" к имени порта (у которых код тоже задефайнен, у каждого свой) микроконтроллер будет на лету? Он же не будет знать какой порт будет следующим. Как же так?
  15. Ладно, а что по поводу таких вещей: mov32 R0,#($Port + GPIO_BSRR) Интересно, где именно происходит сложение "$Port + GPIO_BSRR" в данном случае $Port = 0x40001800, а GPIO_BSRR = 0x10. Для такой операции тоже ведь нужно использовать регистры, я пытался проследить этот момент, но именного таких чисел не увидел. И где вообще хранится константы когда мы используем их в виде "mov R0,#4" - вот число 4 здесь, процессор же должен от куда нибудь его взять? Откуда именно (если из ПЗУ, то как узнать по какому адресу компилятор что,где ложит)? Любую программу же можно разбить на отдельные блоки/функции/файлы отвечающие за что-то одно. И можно будет во всем разобраться.
  16. Как раз читаю одну из этих книг. Что касается С, то на нем я как раз и пишу, но есть мнение что качественно и без извращений, писать на асм может дать выигрыш в прозрачности кода и более логически правильному её написанию и именно к микроконтроллерам это очень даже применимо. Я думаю что современный компилятор таки может гораздо лучше человека составить асм код, но когда пишешь на С, то не всегда очевидно какое огромное кол-во операций может повлечь за собой та или иная простенькая строчка на С.
  17. Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм, так что я условился приблизительно регистры R0-R3 использовать с оглядкой на то что они будут постоянно меняться, так как задействованы почти во всех макросах. А уже по ходу выполнения программы буду держать в поле зрения другие регистры с ключевой информацией. Вот ещё что интересно: одно и то же действие можно сделать разными командами и бывает не понятно как лучше поступить. Вот например загрузка в регистр адреса из памяти: (кусочек кода из макроса) mov32 R0,#$Port или ldr R0,=$Port В итоге эти две строчки равнозначны и вот какую из них лучше применять совсем непонятно. Хотелось бы узнать как бы идею и философию подхода к программированию на ассемблере для мк. (может есть годные примеры такого?) Встраивать асемблеровский код в проект на С я не планирую, идея в написании всего проекта на асм, так что я условился приблизительно регистры R0-R3 использовать с оглядкой на то что они будут постоянно меняться, так как задействованы почти во всех макросах. А уже по ходу выполнения программы буду держать в поле зрения другие регистры с ключевой информацией. Вот ещё что интересно: одно и то же действие можно сделать разными командами и бывает не понятно как лучше поступить. Вот например загрузка в регистр адреса памяти: (кусочек кода из макроса) mov32 R0,#$Port или ldr R0,=$Port В итоге эти две строчки равнозначны и вот какую из них лучше применять совсем непонятно. Или вот ещё mov32 R0,#($Port + GPIO_BSRR) Тоже интересно где именно происходит это сложение? Как я понимаю в на эту строчку уйдет далеко не два такта микроконтроллера? Хотелось бы узнать как бы идею и философию подхода к программированию на ассемблере для мк. (может есть годные примеры такого?) PS: с BFI разобрался
  18. По ассемблеру для арм документации и разного рода примеров гораздо меньше для С. Начал осваивать и возникли сомнения, правильный ли подход частого использования макросов и где та грань, свыше которой не стоит заморачиваться с написанием кода. В ассемблера я не силён, в основном по-любительски пишу на С. Но вот раз начал осваивать асм, сделал несколько элементарных макросов для битовых операций, настройки и использования портов. Вопрос в том правильно ли это делать и использовать таким образом (когда в коде используются много макросов), или может быть есть более рациональный способ, как лучше писать на асме для арм. Вот примерчик: STM32F100RB. И что конкретно делает команда bfi R1,R2,#$Pin,#4 ? Определение макросов: ;-------------------------------------- ;Start_GPIO_Conf $Port,$PinRange - начало настройки порта, где $Port - имя порта (GPIOA,..), $PinRange - верхняя/нижняя тетрада порта (GPIO_CR_H/GPIO_CR_L) macro Start_GPIO_Conf $Port,$PinRange mov32 R0,#$Port ;загружаем в регистр "R0" имя порта (его код) из памяти ldr R1,[R0,#$PinRange];загружаем в регистр "R1" значение по адресу из памяти "R0 + #GPIO_CR_H(0x00)" или "R0 + #GPIO_CR_H(0x04)" mend ;-------------------------------------- ;GPIO_Conf $Pin,$Mode - настройка ножек выбраного порта, где $Pin - номер ножки (CNF_Pin_0,..), $Mode - режим ножки (GPIO_OUT_50_PP,..) macro PinConfig $Pin,$Mode movs R2,#$Mode bfi R1,R2,#$Pin,#4 mend ;-------------------------------------- ;End_GPIO_Conf $Port,$PinRange - конец настройки порта, где $Port - имя порта (GPIOA,..), $PinRange - верхняя/нижняя тетрада порта (GPIO_CR_H/GPIO_CR_L) macro End_GPIO_Conf $Port,$PinRange str R1,[R0,#$PinRange];загружаем в память по адресу "R0 + #GPIO_CR_H(0x00)" или "R0 + #GPIO_CR_H(0x04)" значение "R1" mend ;-------------------------------------- ;SetBit_GPIO $Port,$Pin macro SetBit_GPIO $Port,$Pin mov32 R0,#($Port + GPIO_BSRR) mov32 R1,#$Pin str R1,[R0] mend ;-------------------------------------- ;ResetBit_GPIO $Port,$Pin macro ResetBit_GPIO $Port,$Pin mov32 R0,#($Port + GPIO_BRR) mov32 R1,#$Pin str R1,[R0] mend ;-------------------------------------- Использование в программе: ;-------------------------------------- Start_GPIO_Conf GPIOC,GPIO_CR_H PinConfig CNF_Pin_9,GPIO_OUT_50_PP PinConfig CNF_Pin_8,GPIO_OUT_50_PP End_GPIO_Conf GPIOC,GPIO_CR_H ;-------------------------------------- SetBit_GPIO GPIOC,PIN9 SetBit_GPIO GPIOC,PIN8 ;-------------------------------------- Пробный проект в Keil 5 прикреплен: test11_ASM.7z
  19. А вот непонятность в случае если наш МК работает как Slave: и нам надо передать мастеру байт, сами мы не может начать обмен с мастером и ждем пока он опустит нашу NSS в ноль. И что дальше ? Для автоматической отправки ему нашего байта, его надо просто загрузить в "SPI1(или 2)->DR" и ждать? Правильно ли я думаю что для этого у нас должно быть настроено прерывание по приёму от мастера?
  20. Ура, всё работает. Спасибо ребята.
  21. Суть проблемы в том что у меня не получается завести как в режиме мастера, так и в режиме слейва SPI2 на отладочной плате 32F100DISCOVERY. Самое интересное то, что SPI1 я смог настроить и передавал/принимал данные через него, но при такой же инициализации SPI2 (с учетом того что он тактируется уже от APB1) я получаю полное молчание. Пробовал и с программной реализацией NSS и с аппаратной - результата нет вообще. Я больше чем уверен в том что я чего то не учел и не прописал. Вот код (а также прикреплен весь проект в Keil): void init_spi2(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //включаем тактирование порта B RCC_APB2PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); //включаем тактирование SPI2 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //выбераем режим - альтернативная функция с Push-Pull GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;//PB.13 - SCK, PB.14 - MISO, PB.15 - MOSI GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; //выбераем режим - с открытым стоком GPIO_InitStruct.GPIO_Pin = GPIO_Pin_12; //PB.12 - NSS GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //режим - полный дуплекс SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //размер пакета - 8 бит //===========================нулевой ражим работы SPI=========================== SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //настройка нормального состояния на SCK (SCK опущена - когда ничего не передается/принимается) SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //передача/считывание происходит по переднему фронту на MOSI/MISO //============================================================================== SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //управлять состоянием NSS програмно SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32; //предделитель SCK = 32 (при 8 МГц, скорость SPI = 1/((8000000/32)/8)= 1 байт в 32 мкс) SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //первым отправляется старший бит SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //режим - master SPI_Init(SPI2, &SPI_InitStructure); //функция инициализации SPI2 с заданной структурой //SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE); //включаем прерывание по приему байта SPI_Cmd(SPI2, ENABLE); //включаем модуль SPI2 //SPI_NSSInternalSoftwareConfig(SPI1, SPI_NSSInternalSoft_Set); //NVIC_EnableIRQ(SPI2_IRQn); //разрешаем прерывания от SPI2 } test7_nRF24L01_.rar
  22. На сколько я знаю при использовании PLL от HSI - частота на 2 не делится, а при использовании HSE (то есть внешнего резонатора) - для PLL частота аппаратно сама на 2 делится. Так вот что умножай что не умножай - частоты не совпадают, и не получается от PLL сделать например 16 или 24 МГц.
  23. Может так вопрос будет понятнее: =========================================================== В случае тактирования от PLL (а PLL от внешнего кварцевого резонатора (HSE)) 1.Предочистка делителя для HSE RCC->CFGR2 &= ~RCC_CFGR2_PREDIV1; 2.Делить частоту HSE на 1 RCC->CFGR2 |= RCC_CFGR2_PREDIV1_DIV1; 3.Источником сигнала для PLL выбран HSE RCC->CFGR |= RCC_CFGR_PLLSRC; 4.Отключить генератор PLL RCC->CR &= ~RCC_CR_PLLON; 5.Очистить PLLMULL RCC->CFGR &= ~RCC_CFGR_PLLMULL; 6.Коэффициент умножения = 2 RCC->CFGR |= RCC_CFGR_PLLMULL2; 7.Включить генератор PLL RCC->CR |= RCC_CR_PLLON; 8.Ожидание готовности PLL while((RCC->CR & RCC_CR_PLLRDY)==0) {} 9.Очистка битов выбора источника тактового сигнала RCC->CFGR &= ~RCC_CFGR_SW; 10.Выбрать источником тактового сигнала PLL RCC->CFGR |= RCC_CFGR_SW_PLL; 11.Ожидание переключения на PLL while((RCC->CFGR&RCC_CFGR_SWS)!=0x08){} =========================================================== В случае тактирования от внешнего кварца (HSE) 1.Включить генератор HSE RCC->CR |= RCC_CR_HSEON; 2.Ожидание готовности HSE while((RCC->CR & RCC_CR_HSERDY)==0) 3.Очистка битов выбора источника тактового сигнала RCC->CFGR &= ~RCC_CFGR_SW; 4.Выбрать источником тактового сигнала генератор HSE RCC->CFGR |= RCC_CFGR_SW_HSE; =========================================================== В случае тактирования от внутреннего RC-генератора (HSI) без PLL 1.Включить генератор HSI RCC->CR |= RCC_CR_HSION; 2.Ожидание готовности HSI while((RCC->CR & RCC_CR_HSIRDY)==0) {} 3.Очистка битов выбора источника тактового сигнала RCC->CFGR &= ~RCC_CFGR_SW; 4.Выбрать источником тактового сигнала генератор HSI RCC->CFGR |= RCC_CFGR_SW_HSI; =========================================================== И при настройках на одинаковые частоты тактирования (во всех трех случаях должно быть 8 МГц) у меня получаются разные временные задержки. Что я делаю не так?
  24. Keil 4.50

    Новая версия Keil 4.7 просто прелесть, редактирование кода стало гораздо удобнее так как в Keil добавили проверку синтаксиса и ошибок "на лету" и самая главная фича это подстановка возможного аргумента функции или какой-либо переменной "на лету" в код. Но я думаю что в AtmelStudio 6 это всё сделано в разы удобнее, но всё равно приятно.
×
×
  • Создать...