Начинающий - avr32 включает светодиод, компилятор не видит переменные
У меня есть микропроцессор at32uc3b0256 и я хочу включить светодиоды (простая программа из примеров). Для этого я использую Atmel Studio. Я нашел пример кода:
#ifndef F_CPU
#define F_CPU 16000000UL // 16 MHz clock speed
#endif
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRC = 0xFF; //Makes PORTC as Output
while(1) //infinite loop
{
PORTC = 0xFF; //Turns ON All LEDs
_delay_ms(1000); //1 second delay
PORTC= 0x00; //Turns OFF All LEDs
_delay_ms(1000); //1 second delay
}
}
Но когда я написал это в Atmel Studio, у меня возникли некоторые ошибки, Atmel Studio не видит DDRC и PORT как переменные. Как я могу это исправить? Экранная форма Atmel Studio
1 ответ
Вы используете пример GPIO для архитектуры AVR8. Архитектура AVR32 совершенно отличается, представляя модуль GPIO в виде отдельного блока HW, подключенного через PBA (я думаю). Там нет регистров, как DDRC
,...
Вы можете посмотреть на архитектуру AVR32 как на сеть подкомпонентов, где ядро MCU является только одним из модулей. Есть две основные шины PBA и PBB, каждая из которых подключена к разным модулям.
Для работы прошивки AVR32 необходимо сделать следующее:
настроить и запустить основные тактовые частоты ядра MCU, которые вы хотите использовать
Ядро AVR32 MCU после сброса обычно работает на тактовой частоте 32 кГц. Для достижения лучшей производительности вам нужны тактовые частоты до 66 МГц. Я обычно запускаю PLL на некоторой общей частоте и делю все часы (CPU, PBA, PBB, HSB) от нее позже. В качестве источника для ФАПЧ вам нужны часы, например, внутренний RC или генератор, управляемый внешним кристаллом. Если вы хотите также USB, то вам нужно помнить, что ему нужна определенная частота, так что компромисс... Для получения дополнительной информации проверьте модуль SCIF в техническом описании и / или в примерах.
переключиться на него при правильном запуске
Либо подождите немного (100 мс), либо проверьте, работают ли часы напрямую (я думаю, что у модуля SCIF есть некоторые возможности).
настроить / запустить используемые модули HW
теперь делай свое дело
Bootlaoder
Еще одна вещь, о которой вам нужно позаботиться, это загрузчик. Мне не нравится JTAG, так как у меня плохой опыт с ним (не нужно много жарить его, и программирование с ним действительно неудобно). С JTAG вы можете легко уничтожить загрузчик (каждый чип поставляется вместе с ним), и, поверьте мне, вернуть его к работе - это очень неприятно.
Загрузчик с другой стороны прост и элегантен. Например, я использую FLIP и имеет простой командный файл для программирования чипа. Тогда я просто открываю командную строку и выполняю ее. И при каждом перестроении / программировании я просто нажимал стрелку вверх, чтобы повторить последнюю команду в приглашении, и нажимал ввод. По сравнению со многими кликами с JTAG это намного быстрее и проще. Вот пример cmd:
avr32-objcopy -O ihex AT32UC3L064.elf AT32UC3L064.hex Batchisp -device AT32UC3L064 -hardware RS232 -port COM1 -baudrate 115200 -operation onfail abort memory flash erase f blankcheck loadbuffer AT32UC3L064.hex program start reset 0
avr32-objcopy.exe
находится в каталоге бен AVR studio.С Bootloader вы должны сообщить компилятору, что ваша программа не запускается в
0x0000
потому что это будет совпадать с загрузчиком. Для этого посмотрите примеры батутов.
Вот как обычно выглядит мое приложение AVR32:
#include <avr32/io.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "intc.c"
#include "gpio.c"
#include "pm_uc3l.c"
#include "scif_uc3l.c"
#include "adcifb.c"
#include "flashcdw.c"
#include "pdca.c"
//#include "pwma.c"
#include "tc.c"
#include "usart.c"
#include "eic.c"
#include "genclk.h"
#include "osc.c"
#include "dfll.c"
#include "sysclk.c"
#include "status_codes.h"
#include "cycle_counter.h"
#include "sleep.h"
#include "delay.c"
#define cpu_clk 30000000
#define _LED AVR32_PIN_PA04
void system_init()
{
delay_init(115000);
Disable_global_interrupt();
INTC_init_interrupts();
scif_start_rc120M();
delay_ms(100);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_CPU,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBA,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_PBB,PM_CKSEL_DIVRATIO_4);
pm_set_clk_domain_div((pm_clk_domain_t)AVR32_PM_CLK_GRP_HSB,PM_CKSEL_DIVRATIO_4);
pm_set_all_cksel(SCIF_RC120M_FREQ_HZ,cpu_clk,cpu_clk,cpu_clk);
flashcdw_set_flash_waitstate_and_readmode(cpu_clk);
pm_set_mclk_source(PM_CLK_SRC_RC120M);
delay_init(cpu_clk);
}
//------------------------------------------------------------------------------------------------
void wait_ms(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
dt=((dt*cpu_clk)+999)/1000;
t0&=RDTSC_mask;
for (;;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=dt) break;
}
}
//------------------------------------------------------------------------------------------------
void wait_us(U32 dt)
{
U32 t0,t1;
t0=Get_system_register(AVR32_COUNT);
dt=((dt*cpu_clk)+999999)/1000000;
t0&=RDTSC_mask;
for (;;)
{
t1=Get_system_register(AVR32_COUNT);
t1&=RDTSC_mask;
if (t0>t1) t1+=RDTSC_mask+1;
if ((t1-t0)>=dt) break;
}
}
//------------------------------------------------------------------------------------------------
int main(void)
{
system_init();
// here init what you need
gpio_configure_pin(_LED,GPIO_DIR_OUTPUT|GPIO_INIT_HIGH);
for (;;)
{
// here do your stuff
gpio_tgl_gpio_pin(_LED);
wait_ms(200);
}
//------------------------------------------------------------------------------------------------
Я не использую менеджер фреймворков, вместо этого я сам включаю материал... и мой фреймворк переписан, чтобы избежать ненужных включений и замедлений компиляции. Также имейте в виду, что обновления фреймворка не всегда совместимы, поэтому иногда после обновления ваш код не будет компилироваться... Лучше иметь один цельный фреймворк и не обновлять его, если в этом нет особой необходимости.
Выберите только те модули, которые вам нужны (не нужно включать их все). Например вам нужно intc,gpio,scif
и т. д. мои включения относятся к более крупному проекту, поэтому многие из них бесполезны для вас, а также не все заголовки / модули доступны для всех чипов AVR32.
Я получил немного не по теме (я думаю, что это было необходимо), поэтому вернемся к GPIO
API и архитектура полностью изменены. Не дайте себя обмануть именами пин-кодов. Например пин PA35
не означает порт A
штырь 35
!!! Нет порта PA
Это просто соглашение об именах, не имеющее никакого реального смысла для архитектуры, что немного глупо и заняло у меня некоторое время, чтобы справиться с этим. Есть столько портов, сколько нужно, чтобы покрыть все контакты. Поддержка каждого порта 32
контакты и номер контакта - это то, что вам нужно знать.
Каждый штифт определяется где-то в avr32/io.h
как определение, как AVR32_PIN_PA04
и содержит числовое значение положения штыря в микросхемах GPIO. Чтобы получить порт / маску gpio, вы просто делаете это:
port = pin>>5
mask = 1<<(pin&31)
Теперь для прямого доступа к регистрам GPIO рекомендую посмотреть gpio.c
, Вы можете установить, res, проверить, прочитать 32 контакта за раз, чтобы ускорить (если они находятся на том же порту). Скорость зависит главным образом от тактовой частоты шины (обычно PBA для GPIO), поэтому, если ваши часы для нее низкие, не ожидайте высокой скорости переключения. Остерегайтесь доступа к GPIO медленно, и если его не использовать с умом, это может снизить производительность вашего кода...
Если штифты HW, выбранные для вашего приложения, сделаны с умом, вы можете получить действительно высокую скорость. Например, я получил скорость переключения около 2-5 МГц!!!
Вот пример установки пин из gpio.c
void gpio_set_gpio_pin(uint32_t pin)
{
U32 bit= 1 << (pin & 0x1F);
volatile avr32_gpio_port_t *gpio_port = &GPIO.port[pin >> 5];
gpio_port->ovrs = bit; // Value to be driven on the I/O line: 1.
gpio_port->oders = bit; // The GPIO output driver is enabled for that pin.
gpio_port->gpers = bit; // The GPIO module controls that pin.
}
Вы можете использовать это, чтобы установить несколько контактов на одном и том же порту, просто заменив bit
с маской всех контактов, которые вы хотите установить...
Если вы используете прерывания для GPIO, имейте в виду, что контроллер прерываний INTC также является отдельным модулем, соединенным шиной, и неправильная установка часов или состояний ожидания может вызвать огромные проблемы.