реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> как работать с IAP?
cornflyer
сообщение Jan 28 2009, 14:26
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



Кто-нибудь научился работать с флеш-памятью LPC2148 через IAP?
Пока я лучше и проще выхода не нашел как поставить внешний i2c eeprom....
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 28 2009, 15:10
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(cornflyer @ Jan 28 2009, 17:26) *
Кто-нибудь научился работать...

 нашел как поставить внешний i2c eeprom....


A, что, кто-нибудь это (после чтения документации и многочисленных обсуждений на форуме ) не умеет smile.gif. А вообще смотря для чего, у меня I2C EEPROM почти всегда, не смотря на то, что и во FLASH многое что пишется (приложения, прошивки FPGA,.....).


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jan 29 2009, 12:47
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



на форуме нет внятного описания как работать с IAP, нет рабочего кода, только какие-то танцы с бубном smile.gif
пробовал код с форума - то пишет, то не пишет... непонятно почему
в самой документации на lpc2148 - только пару строк
хотя я все делал как требуется:
выключал прерывания
вызывал функцию подготовки флеша
потом писал туда массив байт из RAM'а
выложи свой рабочий код, который пишет и читает внутреннюю FLASH через IAP smile.gif
Go to the top of the page
 
+Quote Post
Nixon
сообщение Jan 29 2009, 13:14
Сообщение #4


Гуру
******

Группа: Админы
Сообщений: 2 736
Регистрация: 17-06-04
Из: Киев
Пользователь №: 48



Кроме документации существует еще и application note. Там и описание и код, все есть.


--------------------
Вам помочь или не мешать?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 29 2009, 15:31
Сообщение #5


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(cornflyer @ Jan 29 2009, 14:47) *
выложи свой рабочий код, который пишет и читает внутреннюю FLASH через IAP smile.gif
Тут принято несколько иначе - вы выложите свой код, а мы покажем, что в нем не так. Уж для чтения-то зачем IAP???


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Jan 30 2009, 06:51
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



да, я читал application note AN10256
компилятор Keil, target опция USE THUMB MODE включена....

CODE
/*
* IAP In-System Application Programming
*/

#include <LPC21xx.H>

// Clock Frequency
#define XTAL 12000000 // Oscillator Frequency

#ifdef BYPASS_IAP
#define CPUCLK XTAL // CPU Clock without PLL
#else
#define CPUCLK (XTAL*4) // CPU Clock with PLL
#endif

#define CCLK (XTAL / 1000) // CPU Clock without PLL in kHz

// Phase Locked Loop (PLL) definitions
#define PLL_BASE 0xE01FC080 // PLL Base Address
#define PLLCON_OFS 0x00 // PLL Control Offset
#define PLLSTAT_OFS 0x08 // PLL Status Offset
#define PLLFEED_OFS 0x0C // PLL Feed Offset
#define PLLCON_PLLE 0x01 // PLL Enable
#define PLLCON_PLLD 0x00 // PLL Disable
#define PLLCON_PLLC 0x03 // PLL Connect(0x02) | PLL Enable
#define PLLSTAT_PLOCK 0x0400 //1<<10 // PLL Lock Status


struct iap_in {
unsigned int cmd;
unsigned int par[4];
};

typedef void (*IAP)(struct iap_in *in, unsigned int *result);
#define iap_entry ((IAP) 0x7FFFFFF1) // IAP entry point


/* Default Interrupt Function: may be called when interrupts are disabled */
void def_isr (void) __irq {
;
}


#ifdef BYPASS_IAP
/*
* Switch CPU to PLL clock
*/
void start_pll (void) {
__asm {
LDR R0, =PLL_BASE
MOV R1, #0xAA
MOV R2, #0x55

// Enable PLL
MOV R3, #PLLCON_PLLE
STR R3, [R0, #PLLCON_OFS]
STR R1, [R0, #PLLFEED_OFS]
STR R2, [R0, #PLLFEED_OFS]

// Wait until PLL Locked
LDR R2, =PLLSTAT_PLOCK
PLL_Loop:
LDR R3, [R0, #PLLSTAT_OFS]
CMP R3, R2
BEQ PLL_Loop

// Switch to PLL Clock
MOV R2, #0x55
MOV R3, #PLLCON_PLLC
STR R3, [R0, #PLLCON_OFS]
STR R1, [R0, #PLLFEED_OFS]
STR R2, [R0, #PLLFEED_OFS]
}
}


/*
* Switch CPU to standard XTAL
*/
void stop_pll(void) __arm {
__asm {
LDR R0, =PLL_BASE
MOV R1, #0xAA
MOV R2, #0x55

// Disable PLL
MOV R3, #PLLCON_PLLD
STR R3, [R0, #PLLCON_OFS]
STR R1, [R0, #PLLFEED_OFS]
STR R2, [R0, #PLLFEED_OFS]
}
}

#endif

/*
* Convert 'addr' to sector number
*/
unsigned int get_secnum (void *addr) {
unsigned int n;

n = ((unsigned int) addr >> 13) & 0x1F; // pseudo sector number

if (n >= (0x30000 >> 13)) {
n -= 14; // high small 8kB Sectors (
}
else if (n >= (0x10000 >> 13)) {
n = 7 + (n >> 3); // large 64kB Sectors
}
return (n); // sector number
}


/*
* Erase Sector between 'start' and 'end'
* Return: IAP error code (0 when OK)
* NOTES: start needs to be a 256 byte boundary
* size should be 256, 512, 1024 or 4089
*/
unsigned int erase (void* start, void* end) {
struct iap_in iap; // IAP input parameters
unsigned int result[16]; // IAP results
unsigned int save_VicInt; // for saving of interrupt enable register

save_VicInt = VICIntEnable; // save interrupt enable status
VICIntEnClr = 0xFFFFFFFF; // disable all interrupts

#ifdef BYPASS_IAP
stop_pll(); // IAP requires to run without PLL
#endif

iap.cmd = 50; // IAP Command: Prepare Sectors for Write
iap.par[0] = get_secnum (start); // start sector
iap.par[1] = get_secnum (end); // end sector
iap_entry (&iap, result); // call IAP function
if (result[0]) goto exit; // an error occured?

iap.cmd = 52; // IAP command: Erase Flash
iap.par[0] = get_secnum (start); // start sector
iap.par[1] = get_secnum (end); // end sector
iap.par[2] = CCLK; // CPU clock
iap_entry (&iap, result); // call IAP function

exit:

#ifdef BYPASS_IAP
start_pll(); // start PLL
#endif

VICIntEnable = save_VicInt; // enable interrupts
return (result[0]);
}


/*
* Program *data to flash_addr. number of bytes specified by size
* Return: IAP error code (0 when OK)
* Note:
*/
unsigned int program (void *flash_addr, void *data, unsigned int size) {
struct iap_in iap; // IAP input parameters
unsigned int result[16]; // IAP results
unsigned int save_VicInt; // for saving of interrupt enable register

save_VicInt = VICIntEnable; // save interrupt enable status
VICIntEnClr = 0xFFFFFFFF; // disable all interrupts

#ifdef BYPASS_IAP
stop_pll(); // IAP requires to run without PLL
#endif

iap.cmd = 50; // IAP Command: Prepare Sectors for Write
iap.par[0] = get_secnum (flash_addr); // start sector
iap.par[1] = iap.par[0]; // end Sektor
iap_entry (&iap, result); // call IAP function
if (result[0]) goto exit; // an error occured?

iap.cmd = 51; // IAP Command: Copy RAM to Flash
iap.par[0] = (unsigned int) flash_addr; // destination-addr
iap.par[1] = (unsigned int) data; // source-addr
iap.par[2] = size; // number of bytes
iap.par[3] = CCLK; // CPU clock
iap_entry (&iap, result); // call IAP function

exit:

#ifdef BYPASS_IAP
start_pll(); // start PLL
#endif

VICIntEnable = save_VicInt; // enable interrupts
return (result[0]);
}



unsigned char vals[512];


void main (void) {
unsigned int i;

unsigned int volatile start;

for (start = 0; start < 1000000; start++) {
; // wait for debugger connection (about 0.3 sec)
}

VICDefVectAddr = (unsigned int) def_isr; // for spurious interrupts

for (i = 0; i < sizeof (vals); i++) {
vals[i] = (unsigned char) i;
}

program (0x30000, vals, sizeof (vals));
program (0x31000, vals, sizeof (vals));
program (0x32000, vals, sizeof (vals));
erase (0x30000, 0x31FFF);
erase (0x32000, 0x33FFF);

while (1);
}


Go to the top of the page
 
+Quote Post
zltigo
сообщение Jan 30 2009, 08:48
Сообщение #7


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(cornflyer @ Jan 29 2009, 15:47) *
на форуме нет внятного описания как работать с IAP, нет рабочего кода, только какие-то танцы с бубном smile.gif



Никаких танцев при шатном использовании.

Цитата
..непонятно почему


На вопрос "почему" отвечает сам IAP возвращая коды ошибок, только вот Вы их анализировать не считаете нужным sad.gif. Начните с этого

Цитата
в самой документации на lpc2148 - только пару строк


Вообще-то там целый раздел...


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
segment
сообщение Jan 31 2009, 16:32
Сообщение #8


Местный
***

Группа: Участник
Сообщений: 352
Регистрация: 10-08-06
Из: Санкт-Петербург
Пользователь №: 19 471



Кстати да, интересная тема. Может ктонибудь объяснит или напишет небольшой РАБОЧИЙ, самое главное РАБОЧИЙ, код для работы с flash.
А так же интересует вопрос - как чтолибо сохранить во flash, то есть как определяем свободные диапазоны адресов? и что они не будут заняты в будущем?

Просто мысль была сохранять данные, чтобы при выключении они сохранялись. В АВРках было проще, там почти везде был еепром
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jan 31 2009, 16:36
Сообщение #9


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Сега @ Jan 31 2009, 18:32) *
то есть как определяем свободные диапазоны адресов? и что они не будут заняты в будущем?
Резервируем нужную область в скрипте линкера. Он будет ругаться, если в будущем будет попытка ее занять чем-то другим.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Feb 2 2009, 07:21
Сообщение #10


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



внутренний flash стоит использовать для хранения редкоменяющейся инфы...
часто писать во внутренний flash - плохой стиль
у него ресурс всего 100000 циклов записи....
запись через IAP занимает время, причем проц не обрабатывает прерывания....
если 100 раз в сутки приходица сохранять инфу - лучше писать во внешний eeprom
у него ресурс 1000000 циклов
вот например можно поставить i2c eeprom M24C64
код для чтения/записи приведен ниже:
Код
#include "lpc214x.h"
/*-------------------------------------------------------------------------*/
#define SDA_BIT    (1<<3)//for olimex board
#define SCL_BIT    (1<<2)//for olimex board
#define I2C_ADDR (0x50)//I2C Slave Address
/*-------------------------------------------------------------------------*/
void I2C_DELAY(void){
    volatile z=1000;
    while(z) z--;
}
/*-------------------------------------------------------------------------*/
unsigned char I2C_SDA(void){
    return (IOPIN0&SDA_BIT);    
}
/*-------------------------------------------------------------------------*/
void I2C_SDA_HIGH(void){
    IODIR0 &=~ SDA_BIT;//input    
}
/* -------------------------------------------------------------------------*/
void I2C_SDA_LOW(void){
    IOCLR0 = SDA_BIT;
    IODIR0 |= SDA_BIT;//output low
}
/*-------------------------------------------------------------------------*/
void I2C_SCL_HIGH(void){
    IODIR0 &=~ SCL_BIT;//input
}
/*-------------------------------------------------------------------------*/
void I2C_SCL_LOW(void){
    IOCLR0 = SCL_BIT;
    IODIR0 |= SCL_BIT;//output low
}
/*-------------------------------------------------------------------------*/
unsigned char i2c_send_byte(unsigned char b){
    unsigned char result = 0;
    unsigned int i = 0;
    for(i=0;i<8;i++){
        //Set Data
        if(b&0x80){// == 1000 0000
            I2C_SDA_HIGH();
        }else{
            I2C_SDA_LOW();
        }
        b = b<<1;//shift left by one position
        I2C_DELAY();
        I2C_SCL_HIGH();//make clock pulse
        I2C_DELAY();
        I2C_SCL_LOW();
        I2C_DELAY();    
    }
    //Acknowledge
    I2C_SDA_HIGH();
    I2C_DELAY();
    I2C_SCL_HIGH();//make clock pulse
    I2C_DELAY();
    if(I2C_SDA()){//check i2c slave acknowledge
        result = 1;
    }else{
        result = 0;
    }
    I2C_SCL_LOW();
    I2C_DELAY();
    return result;
}
/*-------------------------------------------------------------------------*/
unsigned char i2c_write(unsigned int addr,unsigned char b){
    unsigned char result = 0;
    //Initial state (stop condition)
    I2C_SCL_HIGH();
    I2C_DELAY();
    I2C_SDA_HIGH();
    I2C_DELAY();
    //Start (start condition)
    I2C_SDA_LOW();
    I2C_DELAY();
    I2C_SCL_LOW();
    I2C_DELAY();
    //Send i2c address
    if(i2c_send_byte(I2C_ADDR<<1)){//RW=0
        result = 1;
    }else{
        if(i2c_send_byte(addr>>8))result = 1;//high addr
        if(i2c_send_byte(addr))result = 1;//low addr
        if(i2c_send_byte(b))result = 1;
    }
    //Stop (stop condition)
    I2C_SDA_LOW();
    I2C_DELAY();
    I2C_SCL_HIGH();
    I2C_DELAY();
    I2C_SDA_HIGH();
    I2C_DELAY();
    return result;
}
/*-------------------------------------------------------------------------*/
void i2c_write_byte(unsigned int addr, unsigned char b){
    unsigned char result = 1;
    while(result)result = i2c_write(addr,b);
}
/*-------------------------------------------------------------------------*/
void i2c_read_page(unsigned int addr, unsigned char *page_buff, unsigned int page_length){
    unsigned char data_byte = 0;
    int b;
    //Initial state
    I2C_SCL_HIGH();
    I2C_DELAY();
    I2C_SDA_HIGH();
    I2C_DELAY();
    //Start (start condition)
    I2C_SDA_LOW();
    I2C_DELAY();
    I2C_SCL_LOW();
    I2C_DELAY();
    //Send address
    i2c_send_byte(I2C_ADDR<<1);//RW=0
    i2c_send_byte(addr>>8);//high addr
    i2c_send_byte(addr);//low addr
    //Start (start condition)
    I2C_SCL_HIGH();
    I2C_DELAY();
    I2C_SDA_LOW();
    I2C_DELAY();
    I2C_SCL_LOW();
    I2C_DELAY();
    i2c_send_byte((I2C_ADDR<<1)|0x01);//RW = 1
    while(page_length){//read page    
        I2C_SDA_HIGH();
        for(b=8;b--;){
            I2C_DELAY;
            I2C_SCL_HIGH();
            I2C_DELAY();
            data_byte = (data_byte<<1)|((I2C_SDA())?0x01:0x00);
            I2C_DELAY();
            I2C_SCL_LOW();
            I2C_DELAY();
        }
        *page_buff = data_byte;
        page_buff++;
        data_byte = 0;
        page_length--;
        //Acknowledge
        if(page_length) I2C_SDA_LOW(); else I2C_SDA_HIGH();
        I2C_DELAY();
        I2C_SCL_HIGH();
        I2C_DELAY();
        I2C_DELAY();
        I2C_SCL_LOW();
        I2C_DELAY();
    }
    //Stop (stop condition)
    I2C_SDA_LOW();
    I2C_DELAY();
    I2C_SCL_HIGH();
    I2C_DELAY();
    I2C_SDA_HIGH();
    I2C_DELAY();
}
Go to the top of the page
 
+Quote Post
Qwertty
сообщение Feb 2 2009, 07:46
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527



Цитата(cornflyer @ Feb 2 2009, 10:21) *
вот например можно поставить i2c eeprom M24C64
код для чтения/записи приведен ниже:

А почему софтовый I2C???
Go to the top of the page
 
+Quote Post
yuri_t
сообщение Feb 2 2009, 08:22
Сообщение #12


Частый гость
**

Группа: Свой
Сообщений: 163
Регистрация: 24-08-05
Пользователь №: 7 937



По поводу IAP можно посмотреть здесь:

http://www.tnkernel.com/usb_fw_upgrader.html
(usb-fwu-1-0-1-lpc214x.zip -> fwu_asm.s)

По поводу I2C - здесь:
Прикрепленные файлы
Прикрепленный файл  LPC2xx_I2Clib.zip ( 9.04 килобайт ) Кол-во скачиваний: 88
 
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Feb 2 2009, 11:17
Сообщение #13


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



преимущества софтового i2c :
- софтовый i2c меньше занимает, работает без глюков wink.gif (смотри еррату на lpc2148)
- SDA и SCL можно на любые ноги повесить

мой личный опыт показывает что код, написанный на все случаи жизни - работает медленно, глючит и
много жрет ресурсов....
поэтому я стараюсь кодить только то, что нужно для решения поставленной задачи
Go to the top of the page
 
+Quote Post
zltigo
сообщение Feb 2 2009, 12:48
Сообщение #14


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(cornflyer @ Feb 2 2009, 14:17) *
софтовый i2c меньше занимает, работает без глюков wink.gif (смотри еррату на lpc2148)



Смотреть нечего - уже ДЕСЯТКИ лет I2C на любых Филипсовских контролерах никаких errata и глюков не имеет, является отлитым в бронзе стандартом. И, как Вам показалось, заработавший copy-paste  из интернету софтового I2C не повод изрекать глупости про "глюки", "ресурсы" и "медленность".

 


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
cornflyer
сообщение Feb 3 2009, 07:47
Сообщение #15


Частый гость
**

Группа: Свой
Сообщений: 166
Регистрация: 11-07-06
Из: Dubna
Пользователь №: 18 729



согласен.
перечитал еррату - действительно с i2с в lpc2148 проблем нет. похоже я перепутал с другим камнем.
i2c контроллер нужен если на шине много устройств
а если всего один eeprom и к тому же накосячил с разводкой - тут поможет только софтверный i2c.
скоро буду разводить новую плату под ecos - вот тут мне понадовица i2c контроллер

P.S. кстати, нашел в ecos'е пару багов - неправильно было определено адресное смещение - должно быть 0x10000000
из-за этого код больше 1Mb не работал...
и еще там не включена опция кэширования.....
в итоге после фиксов все заработало в 10 раз (!!!!) быстрее!
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 27th June 2025 - 10:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01527 секунд с 7
ELECTRONIX ©2004-2016