Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как выделить область памяти?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры > AVR32
dinar21
Как выделить область памяти во flash,чтобы компилятор не занимал ее и чтобы во время работы контроллера была возможность записи на нее?
alexeyv
1. Какой контроллер?
2. Какая среда/язык программирования?
dinar21
AT32UC3B0256, AVR32Studio, C ?

И еще такой вопрос, чтобы на ассемблере писать для этого контроллера в какой среде программирования лучше всего?
Dopler
Вам бы досконально изучить примеры, которые я выкладывал в соседней ветке, и таких бы вопросов не возникало. Там в файле скрипта линкера всего десяток строчек, разберитесь в них, и все станет понятно.
dinar21
А как-нибудь в программе контроллера это реализовать нельзя?
Dopler
Это зависит от того, что вы понимаете под словом "выделить" и под "возможностью записи". В общем виде компилятор не назначает никаких глобальных адресов, этим занимается компоновщик (linker).
dinar21
Выделить, т.е. задать некоторое количество ячеек памяти во flash так,чтобы потом при выполнении программы контроллера можно было попрограммой записать в эти ячейки данные.
dinar21
Цитата(dinar21 @ May 18 2011, 05:14) *
Выделить, т.е. задать некоторое количество ячеек памяти во flash так,чтобы потом при выполнении программы контроллера можно было попрограммой записать в эти ячейки данные.

Нашел для этого Flash User Page. Осталось разобраться как в него записывать и как обращаться.

Ни у кого нет примера раоты с пользовательской страницей ( Flash User Page) ???
msalov
Цитата(dinar21 @ May 18 2011, 05:14) *
Выделить, т.е. задать некоторое количество ячеек памяти во flash так,чтобы потом при выполнении программы контроллера можно было попрограммой записать в эти ячейки данные.

Выделить некоторый объём флешь, очень просто - объявите массив нужного размера с нужным выравниванием - вот вам и страница "для личный нужд".
Storejet
Как раз недавно писал кое-что в user page. Сам наковырял что смог из примеров. На идельность не претендую, но если надо могу выложить код.
dinar21
Цитата(Storejet @ May 18 2011, 09:54) *
Как раз недавно писал кое-что в user page. Сам наковырял что смог из примеров. На идельность не претендую, но если надо могу выложить код.

Буду благодарен
Storejet
для начала создаем структуру, которая будет размещаться во flash памяти. Я привожу кусок из свое программы, а вообще структура может быть любая.
typedef const struct
{
char Part_number[32];// шифр прибора (ASCII)
char Mnem[4];//мнемоника прибора (ASCII)
char Add_Mnem[4];// дополнительная мнемоника (ASCII)
char Making_Year[4]; //календарный год изготовления прибора (ASCII)
char Defis_1; //Дефис (ASCII)
char Making_Month[2]; //календарный месяц изготовления прибора (ASCII)
char Defis_2; //Дефис (ASCII)
char Making_Day[2];//календарный день изготовления прибора(ASCII)
U8 UIN_Number[2];//Уникальный нмер прибора (HEX)
U8 Sch_Version; //Схемотехническая верся контроллера (HEX)
U8 Soft_Version; //Программная версия контроллера (HEX)
U8 Calibr_Size[4]; //Размер калибровочной записи (HEX)
char Calibr_Name[12]; // Имя калибровочной записи (ASCII)
U8 BLK_Size[4]; // Длина BUF, байт (HEX)
U8 TTO[2]; //TTO , ms (HEX)
U8 FRAM_Size[4]; //длина FRAM, байт (HEX)
U8 SRAM_Size[4]; //Длина SRAM, байт (HEX
U8 Reserved[44]; //Резерв


} nvram_data_t;





//Размещаем структуру идентификатора () в пользовательской странице Flash памяти
__attribute__((__section__(".userpage"))) //".userpage"
static nvram_data_t user_nvram_data;
;




Далее для работы с данными из flash памяти объявляю указатель
nvram_data_t *user_page=&user_nvram_data; // объявляем указатель

Вот некоторые константы, которые будут прописываться в пользовательскую страницу

const char Part_number[32]={'x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x','x'};// шифр прибора (ASCII)

const char Mnem[4]={'B','K','3','5'};//мнемоника прибора (ASCII)

const char Add_Mnem[4]={' ',' ',' ',' '};// дополнительная мнемоника (ASCII)

const char Making_Year[4]={'2','0','1','1'}; //календарный год изготовления прибора (ASCII)



Функция, которая пропишет константы в пользовательскую страницу:


void ID_write_init (void){

//Смотрим, записано ли что нибудь в пользовательской странице Flash (она будет пуста в новом контроллере)
if (flashc_quick_user_page_read()){
//Записываем во Flash изначальные данные
//Записываем новые данные во flash
flashc_memcpy((void*)&user_page->Part_number,&Part_number,sizeof(user_page->Part_number),TRUE);

flashc_memcpy((void*)&user_page->Mnem,&Mnem,sizeof(user_page->Mnem),TRUE);

flashc_memcpy((void*)&user_page->Add_Mnem,&Add_Mnem,sizeof(user_page->Add_Mnem),TRUE);

flashc_memcpy((void*)&user_page->Making_Year,&Making_Year,sizeof(user_page->Making_Year),TRUE);
}







Если нужно обратиться к данным, размещенным нами в памяти, делаем так:
usart_putchar(USART_ADDR, user_page->Part_number[0]);
usart_putchar(USART_ADDR, user_page->Part_number[1]); ну и так далее

Если что-то не понятно или неправильно, пишите...



dinar21
Цитата(Storejet @ May 18 2011, 12:51) *
U8 UIN_Number[2];//Уникальный нмер прибора (HEX)
U8 Sch_Version; //Схемотехническая верся контроллера (HEX)
U8 Soft_Version; //Программная версия контроллера (HEX)
U8 Calibr_Size[4]; //Размер калибровочной записи (HEX)
U8 TTO[2]; //TTO , ms (HEX)
U8 FRAM_Size[4]; //длина FRAM, байт (HEX)
U8 SRAM_Size[4]; //Длина SRAM, байт (HEX
U8 Reserved[44]; //Резерв


} nvram_data_t;


Что значит U8 ?
Storejet
typedef unsigned char U8 -тип данных unsigned char, длина 8 бит
dinar21
Цитата(Storejet @ May 19 2011, 08:37) *
typedef unsigned char U8 -тип данных unsigned char, длина 8 бит

Точно. Туплю.

А нет примера программы прерывания от PWM ?
Storejet
Нет, а в чем там проблема? Приведитете код
dinar21
Цитата(Storejet @ May 19 2011, 12:36) *
Нет, а в чем там проблема? Приведитете код

CODE

#include <avr32/io.h>
#include "compiler.h"
#include "board.h"
#include "intc.h"
#include "power_clocks_lib.h"
#include "gpio.h"
#include "usart.h"
#include "pwm.h"
#include "pm.h"

# define EXAMPLE_PWM_PIN AVR32_PWM_0_0_PIN
# define EXAMPLE_PWM_FUNCTION AVR32_PWM_0_0_FUNCTION
# define EXAMPLE_PWM_CHANNEL_ID 0

# define EXAMPLE_GCLK_ID 0
# define EXAMPLE_GCLK_PIN AVR32_PM_GCLK_0_PIN
# define EXAMPLE_GCLK_FUNCTION AVR32_PM_GCLK_0_FUNCTION

# define EXAMPLE_PWM (&AVR32_PWM)
# define EXAMPLE_PWM_IRQ AVR32_PWM_IRQ

bool front;
int shet;

/*! \ краткое USART обработчик прерывания.
*
* \ к сведению `__attribute__ ((__interrupt__)) '(под GNU GCC для AVR32) и
* `__interrupt" (под IAR Embedded Workbench для Atmel AVR32) с функцией
* атрибуты используются для управления `Rete 'инструкции.
*/
#if defined (__GNUC__)
__attribute__((__interrupt__))
#elif defined(__ICCAVR32__)
__interrupt
#endif



static void pwm_int_handler(void) // п/п формирования пилы
{
if (front==true) // признак спадающего фронта
{if (shet!=0x00000000) AVR32_GPIO.port[1].ovr = shet-- ; // уменьшаем с на 1 до тех пор пока оно не 0
else {front=false;
AVR32_GPIO.port[1].ovr = shet;
}
}
else // иначе признак возрастающего фронта
{if (shet!=0x00000200) AVR32_GPIO.port[1].ovr = shet++ ; // увеличиваем с на 1 до тех пор пока оно не 512
else {front=true;
AVR32_GPIO.port[1].ovr = shet;
}
}
}

static void local_start_highfreq_clock(void) // п/п задания частоты процессора 60 МГц
{
volatile avr32_pm_t* pm = &AVR32_PM;
/* \Примечание во всех расчетах предположить, что Osc0 частота 12 МГц. */

pm_switch_to_osc0(pm, FOSC0, OSC0_STARTUP); // переключение тактирования на Osc0.

/* Установка ФАПЧ0 на Osc0, Mul = 9, делитель на 1, lockcount = , то есть. 12Mhzx10 = 120MHz/2=60МГц выходной */

pm_pll_setup(pm,
0, // разрешение использования ФАПЧ0
9, // MUL=10 умножение частоты кварца на 10
1, // DIV=1 деление частоты на 1
0, // Выбираем Osc0/PLL0 или Osc1/PLL1
16); // lockcount in main clock for the PLL wait lock

/*
Эта функция устанавливает опции ФАПЧ.
*pm Base address of the Power Manager (i.e. &AVR32_PM)
pll PLL number 0
pll_freq Set to 1 for VCO frequency range 80-180MHz, set to 0 for VCO frequency range 160-240Mhz.
pll_div2 Divide the PLL output frequency by 2 (this settings does not change the FVCO value)
pll_wbwdisable 1 Disable the Wide-Bandith Mode (Wide-Bandwith mode allow a faster startup time and out-of-lock time). 0 to enable the Wide-Bandith Mode.
*/
/* Выходная VCO частта ФАПЧ 120 MHz. Мы делим ее на 2 с pll_div2=1. Это позволяет разрешить дальше тактировать CPU на 60 MHz */
pm_pll_set_option(pm, 0, 1, 1, 0);

/* Enable PLL0 */
/*
void pm_pll_enable(volatile avr32_pm_t* pm,
unsigned int pll) {
*/
pm_pll_enable(pm,0);

/* Wait for PLL0 locked */
pm_wait_for_pll0_locked(pm) ;

/* Деление тактовой частоты PBA на 2 пурем деления тактовой частоты CPU (PBA clock = 60MHz/2 = 30 MHz).
Pheripheral Bus A clock divisor enable = 1
Pheripheral Bus A select = 0
Pheripheral Bus B clock divisor enable = 0
Pheripheral Bus B select = 0
High Speed Bus clock divisor enable = 0
High Speed Bus select = 0
*/
pm_cksel(pm, 1, 1, 0, 0, 0, 0);// тактирование внешней периферии от CPU / 4=60 Мгц/4=15МГц

pm_switch_to_clock(pm, AVR32_PM_MCSEL_PLL0); /* Переключение тактовой частоты процессора на 60 MHz */

}

static void local_enable_gclk_on_gpio(volatile avr32_pm_t* pm)
{
int gc = EXAMPLE_GCLK_ID;


/* установка на gc (вданном случае PA30) на прием от ФАПЧ и деление на 2^3=8 */
pm_gc_setup(pm, gc, 1, 0, 1, 3);

/* разрешение gc */
pm_gc_enable(pm,gc);
/* Назначение gc на выход GPIO */
gpio_enable_module_pin(EXAMPLE_GCLK_PIN, EXAMPLE_GCLK_FUNCTION);
// Note that gclk0_1 is GPIO pin 51 pb19 on AT32UC3A0512 QFP144.
// Note that gclk2 is GPIO pin 30 pa30 on AT32UC3B0256 QFP64.
// Note that gclk1 is GPIO pin 43 pb11 on AT32UC3A3256 QFP144.
// Note that gclk1 is GPIO pin 6 pa06 on AT32UC3L064 pin 10 on QFP48.
// Note that gclk0 is GPIO pin 54 pb22 on AT32UC3C0512C QFP144.
}


int main(void) // основное тело программы
{
volatile avr32_pm_t* pm = &AVR32_PM;

// Настройка Osc0 в кристалле режиме (т.е. использование внешнего источника кристалла, с
// частота FOSC0) с соответствующим время запуска затем переключиться Главные часы
// источник Osc0.
//pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);

// Отключить все прерывания
Disable_global_interrupt();


pwm_opt_t pwm_opt; // PWM option config.
avr32_pwm_channel_t pwm_channel = { .ccnt = 0 }; // к.
// номер канала и, например, используется в ряде функций.
// Это определяется как локальная переменная для простоты использования.
unsigned int channel_id;

channel_id = EXAMPLE_PWM_CHANNEL_ID;
gpio_enable_module_pin(EXAMPLE_PWM_PIN, EXAMPLE_PWM_FUNCTION);

// конфигурация PWM controller .
pwm_opt.diva = AVR32_PWM_DIVA_CLK_OFF;
pwm_opt.divb = AVR32_PWM_DIVB_CLK_OFF;
pwm_opt.prea = AVR32_PWM_PREA_MCK;
pwm_opt.preb = AVR32_PWM_PREB_MCK;

pwm_init(&pwm_opt);

pwm_channel.CMR.calg = PWM_MODE_LEFT_ALIGNED; // режим канала.
pwm_channel.CMR.cpol = PWM_POLARITY_LOW; // полярность канала.
pwm_channel.CMR.cpd = PWM_UPDATE_DUTY; // не используется в начальное время.
pwm_channel.CMR.cpre = AVR32_PWM_CPRE_MCK_DIV_32; // канальный предделитель.
pwm_channel.cdty = 6; // рабочий цикл канала, должен быть < CPRD.
pwm_channel.cprd = 12; // период канала.
pwm_channel.cupd = 0; // обновление канала здесь не используется.
// С такими настройками, период выходного сигнала будет :
// (12000000/32)/12 == 31250 Hz ==32 мкс
// prescaler == 32, period == 12.

// Инициализация векторов прерываний.
INTC_init_interrupts();
// Регистрация USART обработчик прерывания на контроллер прерываний.
// usart_int_handler является обработчик прерывания для регистров
// EXAMPLE_USART_IRQ является IRQ из обработчика прерывания для регистров
// AVR32_INTC_INT0 является прерывание уровень приоритета назначить группу
// это IRQ.
// недействительными INTC_register_interrupt (__int_handler обработчик, неподписанные IRQ Int, неподписанные int_level Int);
INTC_register_interrupt(&pwm_int_handler, EXAMPLE_PWM_IRQ, AVR32_INTC_INT0);

// Включить USART Rx прерывания.
EXAMPLE_PWM->ier = 1;


AVR32_GPIO.port[1].oders =0x000003FE; // Конфигурируем соответствующие ножки на выход
AVR32_GPIO.port[1].gpers =0x000003FE; // Включаем эти ножки порта


/* Начало высокой тактовой частоте и переключаться Main Clock с этой высокой тактовой частоты */
local_start_highfreq_clock();

/* Настройка общих часы с высокой тактовой частотой и выхода его на GPIO PIN */
// local_start_gc();
local_enable_gclk_on_gpio(pm);// включение внешнего тактирования 7,5 МГц на ножку
// Включить все прерывания.
Enable_global_interrupt();

pwm_channel_init(channel_id, &pwm_channel); // Установить конфигурацию каналов 0.

pwm_start_channels(1 << channel_id); // стартовать канал 0.


// У нас ничего не осталось делать в основной, так что мы можем перейти к устройству сна
// Режим работы: мы просто должны быть уверены, что модуль USART будет по-прежнему быть активным
// в выбранном режиме ожидания. спящий режим для использования режима МЕРЗЛЫХ сна:
// в этом режиме РВ часы все еще активны (так модуль USART который
// на периферийных шин-прежнему будет активным в то время как процессор и HSB будет
// остановлен).
// -
// Модули связи с внешними цепями, как правило, будет отключен
// перед входом в спящий режим, который остановит работы модуля: это не
// в случае режима сна заморожены.
// -
// Когда прерывания USART происходит, это будет после процессора до которой будет
// выполнение кода обработчика прерывания затем вернуться к а (1) петли ниже
// выполнить инструкции спать снова.


while(1)
{
// Если есть шанс, что любой PB операций записи являются неполными, процессор
// должен выполнять операции чтения из любого зарегистрироваться на шины PB до
// выполнение сна инструкции.
// AVR32_INTC.ipr[0]; // Пустышка читать
}
}


Работать должно так: по прерываниям от PWM должно выдаваться параллельно число по ножкам PB1-PB9 с увеличением на 1. PWM работает на частоте 31250Гц(вывел на отдельную ножку PA7,смотрю по осциллографу) , т.е на ножке PB1 должен быть меандр с частотой в 2 раза меньше,а у меня порядка 90кГц и не зависит от PWM ( меняю частоту PWM, PB1 остается прежним). Не судите строго, я с С недавно разбераюсь, пытался из нескольких примеров скомпоновать. http://electronix.ru/forum/style_images/1/...icons/icon9.gif
Maximm
Цитата(gotty @ May 18 2011, 09:50) *
Выделить некоторый объём флешь, очень просто - объявите массив нужного размера с нужным выравниванием - вот вам и страница "для личный нужд".


А резве в этом случае массив не в ОЗУ будет расположен?

Если не прав, то как указать компоновщику, что данные должны располагаться именно в ОЗУ?
Dopler
Цитата(Maximm @ May 31 2011, 05:45) *
А резве в этом случае массив не в ОЗУ будет расположен?

Если не прав, то как указать компоновщику, что данные должны располагаться именно в ОЗУ?


В компоновщике нет понятий "ОЗУ" или "Flash". Компоновщик оперирует секциями, и размещает эти секции в памяти так, как указано в его скрипте (пусть даже в скрипте по-умолчанию, который в компоновщик вшит намертво). А данные в секции размещает компилятор. По-умолчанию в GCC данные попадают в секцию .DATA. Если данные надо разместить в другую секцию, то это делается специальными директивами, в общем случае разными для разных компиляторов.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.