» »

C in funkcije ter #define

C in funkcije ter #define

drVrh ::

Pozdrav vsem,

prosil bi da mi pomagate rešiti nekakšen problem zaradi premalo programerskega znanja.

Imam h in c file za vpis v RAM mikroprocesorja, in sicer funkcija za vpis, pripravo in brianje so takšne: (funkc0)
//vpis v ram
int iap_copy_ram_to_flash(void* ram_address, void* flash_address, unsigned int count) 
.....
//priprava sektorja
int iap_prepare_sector(unsigned int sector_start, unsigned int sector_end)
.....
//brisanje sektorja
int iap_erase_sector(unsigned int sector_start, unsigned int sector_end)
.....


Potem pa iz mojega razreda kličem te funkcije tako: (funkc1)
//priprava sektorja
iap_status = (__e_iap_status) iap_prepare_sector(CONFIG_FLASH_SECTOR,
	    	            (CONFIG_FLASH_SECTOR + CONFIG_FLASH_SECTOR_SIZE));
	    	    if (iap_status != CMD_SUCCESS) while(1);
.....
//brisanje sektorja
iap_status = (__e_iap_status) iap_erase_sector(CONFIG_FLASH_SECTOR,
	    	            (CONFIG_FLASH_SECTOR + CONFIG_FLASH_SECTOR_SIZE));
	    	    if (iap_status != CMD_SUCCESS) while(1);
.....
//pisanje v sektor
iap_status = (__e_iap_status) iap_copy_ram_to_flash(&demo_messg,
	    	            (void *)CONFIG_FLASH_OFFSET, 256);
	    	    if (iap_status != CMD_SUCCESS) while(1);


Sedaj pa za test sem imel definirane spremenljivke in makroje tako:

#define CONFIG_FLASH_OFFSET            0x00006000				//preberi 26.3.6. table 371 obvezno !!!!!!			
#define CONFIG_FLASH_SECTOR            (CONFIG_FLASH_OFFSET >> 12)
#define CONFIG_FLASH_SECTOR_SIZE    1
static uint8_t demo_messg = 123;
__e_iap_status iap_status;


Zdaj bi pa jaz rad naredil nekakšno unierzalno funkcijo, ki bi imela vhodne parametre, naslov in podatek. Tako da bi rad samo poklical funkc1, v katero bi poslal parametre naslov in podatek ter bi funkc1 naredila vse tiste korake zgoraj ter klicala funkc0.

Funkc0 je splošna in je nebi rad spreminjal ker je najbolj preizkuena ter robustna.
Problem se pojavi ko želim računati ter definirati ter parametre
#define CONFIG_FLASH_OFFSET            0x00006000				//preberi 26.3.6. table 371 obvezno !!!!!!			
#define CONFIG_FLASH_SECTOR            (CONFIG_FLASH_OFFSET >> 12)
#define CONFIG_FLASH_SECTOR_SIZE    1
static uint8_t demo_messg = 123;


Jaz vbistvu sploh ne vem kakšnega tipa bi dal te parametre da bi jih v vhodo v funkc1 sprepoznalo ter poslalo naprej v funkc0.

Za lažje razumevanje prilagam še celotne c in h ter main programe.

main.c:
/*
*
*	shranjevanje skozi IAP v ram 
*	glede naslova moraš obvezno prebrati 26.3.6. FLASH CONFIGURATZION FOR LPC1114 SERIES TABEL 371 TAM
*	ntr piše kak je size naslovov. 
*/

#include "iap_driver.h"

#define CONFIG_FLASH_OFFSET            0x00006000				//preberi 26.3.6. table 371 obvezno !!!!!!			
#define CONFIG_FLASH_SECTOR            (CONFIG_FLASH_OFFSET >> 12)
#define CONFIG_FLASH_SECTOR_SIZE    1

static uint8_t demo_messg = 123;
char sv[] = "";
static uint8_t st;

int main(void) {
	__e_iap_status iap_status;
	iap_init();

	 while(1){ //infinite loop

 /* Prepare the sector for erase */
	    	    iap_status = (__e_iap_status) iap_prepare_sector(CONFIG_FLASH_SECTOR,
	    	            (CONFIG_FLASH_SECTOR + CONFIG_FLASH_SECTOR_SIZE));
	    	    if (iap_status != CMD_SUCCESS) while(1);

	    	    /* Erase the sector */
	    	    iap_status = (__e_iap_status) iap_erase_sector(CONFIG_FLASH_SECTOR,
	    	            (CONFIG_FLASH_SECTOR + CONFIG_FLASH_SECTOR_SIZE));
	    	    if (iap_status != CMD_SUCCESS) while(1);

	    	    /* Prepare the sector for writing */
	    	    iap_status = (__e_iap_status) iap_prepare_sector(CONFIG_FLASH_SECTOR,
	    	            (CONFIG_FLASH_SECTOR + CONFIG_FLASH_SECTOR_SIZE));
	    	    if (iap_status != CMD_SUCCESS) while(1);

	    	    /* write data to flash */
	    	    iap_status = (__e_iap_status) iap_copy_ram_to_flash(&demo_messg,
	    	            (void *)CONFIG_FLASH_OFFSET, 256);
	    	    if (iap_status != CMD_SUCCESS) while(1);


	    	    st = * ((uint8_t *) 0x00006000);					///branje iz flasha na omenjen naslov 

	    	    itoa(st, sv, 10);			//pretvorba v char
	    	    PotisniChar(0, 0, 1, sv);		//izpis na LCD

	}
}


iap_driver.c:
/*

 */

#include <LPC122x.h>
#include "iap_driver.h"

/*
 * The IAP funtion address in LPC11xx ROM
 */
#define IAP_ADDRESS            0x1FFF1FF1

/*
 * Command codes for IAP
 */
#define PREPARE_SECTOR        50
#define COPY_RAM_TO_FLASH    51
#define ERASE_SECTOR        52
#define BLANK_CHECK_SECTOR    53
#define READ_PART_ID        54
#define READ_BOOT_CODE_REV    55
#define COMPARE                56
#define REINVOKE_ISP        57
#define READ_UID            58

typedef unsigned int (*IAP)(unsigned int[], unsigned int[]);
static const IAP iap_entry = (IAP) IAP_ADDRESS;

/*---------------------------------------------------------------------------
 * Public functions
 */

/**
 * Init IAP driver
 * @return    0 for success
 */
int iap_init(void) {
    /* Need to update 'SystemCoreClock' according to the current clock settings
     * It's needed as IAP parameter
     */
    SystemCoreClockUpdate();
    return 0;
}

/**
 * Erase flash sector(s)
 *
 * @param sector_start  The start of the sector to be erased
 * @param sector_end    The end of the sector to be erased
 *
 * @return CMD_SUCCESS, BUSY, SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
 *         or INVALID_SECTOR
 */
int iap_erase_sector(unsigned int sector_start, unsigned int sector_end) {
    unsigned int command[5];
    unsigned int result[4];

    command[0] = ERASE_SECTOR;
    command[1] = (unsigned int) sector_start;
    command[2] = (unsigned int) sector_end;
    command[3] = SystemCoreClock / 1000;
    iap_entry(command, result);

    return (int) result[0];
}

/**
 * Prepare flash sector(s) for erase / writing
 *
 * @param sector_start  The start of the sector to be prepared
 * @param sector_end    The end of the sector to be prepared
 *
 * @return CMD_SUCCESS, BUSY, or INVALID_SECTOR
 */
int iap_prepare_sector(unsigned int sector_start, unsigned int sector_end) {
    unsigned int command[5];
    unsigned int result[4];

    command[0] = PREPARE_SECTOR;
    command[1] = (unsigned int) sector_start;
    command[2] = (unsigned int) sector_end;
    iap_entry(command, result);

    return (int) result[0];
}

/**
 * Copy RAM contents into flash
 *
 * @param ram_address    RAM address to be copied
 *                       It should be in word boundary
 * @param flash_address  Flash address where the contents are to be copied
 *                       It should be within 256bytes boundary
 * @param count          Number of data to be copied (in bytes)
 *                       The options: 256, 512, 1024, 4096
 *
 * @return CMD_SUCCESS, BUSY, or INVALID_SECTOR
 */
int iap_copy_ram_to_flash(void* ram_address, void* flash_address,
        unsigned int count) {
    unsigned int command[5];
    unsigned int result[4];

    command[0] = COPY_RAM_TO_FLASH;
    command[1] = (unsigned int) flash_address;
    command[2] = (unsigned int) ram_address;
    command[3] = count;
    command[4] = SystemCoreClock / 1000;
    iap_entry(command, result);

    return (int) result[0];
}


ter iap_driver.h
/*

 */

#ifndef IAP_DRIVER_H_
#define IAP_DRIVER_H_

/*
 * IAP status codes
 */
typedef enum {
    CMD_SUCCESS = 0,
    INVALID_COMMAND,
    SRC_ADDR_ERROR,
    DST_ADDR_ERROR,
    SRC_ADDR_NOT_MAPPED,
    DST_ADDR_NOT_MAPPED,
    COUNT_ERROR,
    INVALID_SECTOR,
    SECTOR_NOT_BLANK,
    SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
    COMPARE_ERROR,
    BUSY,
} __e_iap_status;

/**
 * Init IAP driver
 * @return    0 for success
 */
int iap_init(void);

/**
 * Erase flash sector(s)
 *
 * @param sector_start  The start of the sector to be erased
 * @param sector_end    The end of the sector to be erased
 *
 * @return CMD_SUCCESS, BUSY, SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION,
 *         or INVALID_SECTOR
 */
int iap_erase_sector(unsigned int sector_start, unsigned int sector_end);

/**
 * Prepare flash sector(s) for erase / writing
 *
 * @param sector_start  The start of the sector to be prepared
 * @param sector_end    The end of the sector to be prepared
 *
 * @return CMD_SUCCESS, BUSY, or INVALID_SECTOR
 */
int iap_prepare_sector(unsigned int sector_start, unsigned int sector_end);

/**
 * Copy RAM contents into flash
 *
 * @param ram_address    RAM address to be copied
 *                       It should be in word boundary
 * @param flash_address  Flash address where the contents are to be copied
 *                       It should be within 256bytes boundary
 * @param count          Number of data to be copied (in bytes)
 *                       The options: 256, 512, 1024, 4096
 *
 * @return CMD_SUCCESS, BUSY, or INVALID_SECTOR
 */
int iap_copy_ram_to_flash(void* ram_address, void* flash_address,
        unsigned int count);

#endif /* IAP_DRIVER_H_ */



Najlepša hvala za pomoč, upam da mi boste lahko pomagali in se bil dovolj razumljiv sploh kaj hočem.
Zelo me bega spremenljivka tipa void *, ki je v funkk0. Kakšna je pravzaprav to spr.
  • spremenil: drVrh ()

drVrh ::

Sem uspel nekako narediti sam vse zadeve, toda semi pojavi en warning, ki pa ga ne znam razbiti.
Kodo imam sedaj takole:

void SaveIntoFlashINT(void* naslov, void* input_data){
		unsigned int cfs = ((unsigned int)naslov >> 12);
		unsigned int cfss = 1;
		static uint8_t prestavljen_data = 0;
		//#define CONFIG_FLASH_SECTOR_SIZE    1

	   // Prepare the sector for erase
	    iap_status = (__e_iap_status) iap_prepare_sector(cfs,
	            (cfs + cfss));
	    if (iap_status != CMD_SUCCESS) while(1);

	    // Erase the sector
	    iap_status = (__e_iap_status) iap_erase_sector(cfs,
	            (cfs + cfss));
	    if (iap_status != CMD_SUCCESS) while(1);

	    // Prepare the sector for writing
	    iap_status = (__e_iap_status) iap_prepare_sector(cfs,
	            (cfs + cfss));
	    if (iap_status != CMD_SUCCESS) while(1);
	    prestavljen_data = (uint8_t)input_data;
	    // write data to flash
	    iap_status = (__e_iap_status) iap_copy_ram_to_flash(&prestavljen_data,
	            (void *)naslov, 256);
	    if (iap_status != CMD_SUCCESS) while(1);
}


pojavi pa se mi warning
cast from pointer to integer of different size [-Wpointer-to-int-cast]


Kaže pa na vrstico 17, zgoraj v kodi.
prestavljen_data = (uint8_t)input_data;

Zgodovina sprememb…

  • spremenil: drVrh ()

smoke ::

Spremenljivka input_data je kazalec, probaj tak:
prestavljen_data = *(uint8_t*)input_data;


Zgornja koda spremeni tip spremenljivke input_data v kazalec na uint8_t ter vzame prvi zlog iz tega naslova.

drVrh ::

Warning-a sicer res ni več, toda mi pa spremeni vrednosti. Ob vrednosti 4 mi spremeni na 73.

smoke ::

Aha, jaz sem predvideval da se podatek nahaja na naslovu na katerega kaže input_data. Očitno ne. Torej če zdaj prav razumem je podatek, ki ga rabiš shranjen v input_data? Če ja, zakaj je input_data tipa void* ? Naj bo kar tipa uint8_t in ne rabiš nič typecastat.

marceb ::

kazalci tipa void so nevarni za delo, obstajajo zato ker C ne pozna direktno virtualnih funkcij (pozna pa funkcijo na pointer).
drugače pa ja pazi da castaš v pravo obliko ozrioma vsaj misliš da je prava oblika, ki se nahaja na tistem naslovu.

MrStein ::

input_data je kazalec, toej verjetno 32 bitov.
prestavljen_data pa 8 bitni int.

Zakaj bi tlačil prvo v drugega? Kaka logika bi to naj bila? Kaj s tem hoče koda narediti?

Sploh, ker potem prestavljen_data uporabiš samo enkrat, kot parameter za iap_copy_ram_to_flash().
Ne bi tam kar direktno input_data uporabil?
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

drVrh ::

Jaz kličem funkcijo takole:
SaveIntoFlashINT(F_DRZAVA, 4);


F_DRZAVA pa je:
 #define F_DRZAVA 	0x00006000


prestavljen_data = (uint8_t)input_data;

Tisti stavek je tam zato, ker se mi naslov input_data ob vstopu v funkcijo iap_copy_ram_to_flash spremeni na 268443568, moral pa bi biti vsaj manj, ker mi program javi napako SRC_ADDR_NOT_MAPPED

Če debugiram s tem stavkom:
prestavljen_data = *(uint8_t*)input_data;

imam naslov 268435868 in se mi spremeni vrednost.

Če debugiram s tem stavkom:
prestavljen_data = (uint8_t* )input_data;

imam vrednost vredu (naslov: 268435868) toda imam warning:
assignment makes integer from pointer without a cast	


Če uporabljam drug stavek, mi drugače naredi vse vredu tudi vrednost je prava, ko jo kličem:
nekki = * ((uint8_t *) F_DRZAVA);
	    	 itoa(nekki, nekkic, 10);
	    	 PotisniChar(0, 0, 1, nekkic);

Zgodovina sprememb…

  • spremenil: drVrh ()

gumby ::

void * je kazalec na "nekaj", torej na objekt, ki nima tipa. Smisel takega kazalca je ravno v tem, da ni treba cast operatorja pri prirejanju...
my brain hurts

drVrh ::

Hvala, ste mi že zgoraj napisali toda mi sploh ni potegnilo kaj mislite s cast itd. Zdaj imam brez cast.

Zdaj pa imam vprašanje, ker sem kompliciral s temi tipi itd. kako bi ugotovil do kot mi seže sedaj ta spremenljivka 4. Rabi di vedel naslednji naslov kam lahko zadevo shranim.

Zgodovina sprememb…

  • spremenil: drVrh ()

drVrh ::

In pa kako bi naredil da bi shranil polje int v spomin, polje veliko 336 bitov (42bajtov). Pač for zanka spomin povečuje pa shranjujem?
So še kakšne druge opcije.

drVrh ::

Aja pa še vedno dobim isti warninig kljub temu da odstranim cast.

prestavljen_data = input_data;

sas084 ::

Zlo na hitro sem pregledu vs post tko da mogoče sm ki spustil ma vseeno, SaveIntoFlashINT maš definirano kot:
void SaveIntoFlashINT(void* naslov, void* input_data)

Notr daš dva parametra, pointer na naslov in pointer na podatke. Ti funkcijo kličeš kot:
SaveIntoFlashINT(F_DRZAVA, 4);

Sklepam da je F_DRZAVA naslov, 4 pa je direktna vrednost podatka, kar pomoje ni prov ker glede na definicijo SaveIntoFlashINT bi moral dat notr pointer ki kaže na podatek 4 (mogoče se pa motim in je 4 dejansko pointer na podatke). Glede na definicijo iap_copy_ram_to_flash
int iap_copy_ram_to_flash(void* ram_address, void* flash_address, unsigned int count);

si jaz tko razlagam da se preprosto kliče na ta način:
iap_status = (__e_iap_status) iap_copy_ram_to_flash(input_data, (void *)naslov, 256);

MrStein ::

Ja, pomagalo bi, če bi povedal, kaj sploh hočeš narediti oziroma doseči.

Aha, zdaj vidim. En integer bi rad shranil.

To bi šlo takole:
iap_status = (__e_iap_status) iap_copy_ram_to_flash(input_data,
                naslov, 1);

S tem, da količen 1 ne podpira.

Torej:
- ali preberaš staro vsebino sektorja, vpišeš svoj INT v prebrano kopijo, ter na koncu jo zapišš nazaj na sektor
- ali sektor prepišeš z svojim INT preostali del sektorja pa daš na ničle (ali karkoli, v glavnem stara vsebina se izgubi, prepiše)
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

Zgodovina sprememb…

  • spremenil: MrStein ()

MrStein ::

V vsakem primeru lahko pišeš le bloke po 256 bajtov.
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

marceb ::

tako kot je MrStein napisal, dobro definiraj svoja vprašanja, ker težko človek ve kje imaš sploh problem.
I'm sorry. My responses are limited. You must ask the right questions.

misek ::

MrStein je izjavil:

V vsakem primeru lahko pišeš le bloke po 256 bajtov.
Ne vem če to drži. Ponavadi je omejitev v brisanju, ki je po podatkih iz datasheet-a 512 bytov. Pišeš pa lahko 4 byte naenkrat. Vsaj tako je delovalo na STM32F4, ko sem pred leti implementiral podobno zadevo (branje in zapisovanje konfiguracije kar v flash pomnilnik).

Edit: Sem se spomnil da sem zadevo uporabil tudi za nalaganje nove verzije programske kode preko HTTP/FTP protokola.

Zgodovina sprememb…

  • spremenil: misek ()

MrStein ::

/**
 * Copy RAM contents into flash
 *
 * @param ram_address    RAM address to be copied
 *                       It should be in word boundary
 * @param flash_address  Flash address where the contents are to be copied
 *                       It should be within 256bytes boundary
 * @param count          Number of data to be copied (in bytes)
 *                       The options: 256, 512, 1024, 4096
 *
 * @return CMD_SUCCESS, BUSY, or INVALID_SECTOR
 */
int iap_copy_ram_to_flash(void* ram_address, void* flash_address,
        unsigned int count) {


----> The options: 256, 512, 1024, 4096
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

Zgodovina sprememb…

  • spremenil: MrStein ()

drVrh ::

Zadeva teče na LPC1114, na njem imam Menu in bi rad da kar user nastai bi se to shranilo. Ker ta LPC nima EEPROM moram shranjevati preko IAP v ram (flash) ne vem zdaj kam. Shranjuje se na način prikazan tule, dostopaš pa do njega s kazalcem.
Vedno je treba pred pisanjem podatka pirpaviti sektor in ga nato zapisati, sedaj sem naredil to funkcijo, je ista kot zgoraj le brez brisanja na začetku:

void SaveIntoFlashINT(void* naslov, void* input_data){
	unsigned int cfs = ((unsigned int)naslov >> 12);
	unsigned int cfss = 1;
		static uint8_t prestavljen_data = 0;
	    // Prepare the sector for writing
	    iap_status = (__e_iap_status) iap_prepare_sector(cfs,
	            (cfs + cfss));
	    if (iap_status != CMD_SUCCESS) while(1);
	    prestavljen_data = input_data;
	    // write data to flash
	    iap_status = (__e_iap_status) iap_copy_ram_to_flash(&prestavljen_data,
	            (void *)naslov, 256);
	    if (iap_status != CMD_SUCCESS) while(1);
}


Problem pa je da ta LPC nima funkcije da bi izbrisal posamezen page v sektorju ampak moraš zbrisati celoten sektor. Sedaj pa se mi poraja vprašanje ali moram vedno zbrisati sektor pred pisanjem ali ne. Ker se mi v vpisovanje na isto mesto drugiš tretjič ... zgodi da nimam več noter številke ampak samo ničlo.
Recimo pri meniju imam ko pritisnem tipko menu da potrdim izbiro jezikqa primer za kurzor na prvem mestu.

switch (y) {
	case 1: {
	country = 0;
	SaveIntoFlashINT(F_DRZAVA, country);
	drzava = 0;		//english
	drzavaDow =* ((uint8_t *) F_DRZAVA);
	drzavaDow++;	//ker imamo prejšnje jezike nastavljene od 0 naprej morajo biti da deluje spodnja formula od 1 naprej da velja
	ZacetniZaslon();
....


Niti ne vem ali mi spravi v drzavaDow celo številko ali samo prvo oz. kaj drugega.

drVrh ::

EDIT: Največji problem je da moraš pred pisanjem zbirsati vedno celoten sektor. V vsakem času pa ga lahko spraviš na nič.

Sedaj pa imam idejo, kako bi naredil funkcijo bi shranjevala v neko spremenljivko vse vhodne podatke, ter na koncu zapisala. Tako bi lahko zapisal več pdoatkov naenkrat, le z časovnim zamikom ne bi se zapisalo takoj. (ena opcija)

Druga pa je da pač za vsak podatek uporabim svoj sektor (1 sektor 4kB (8 sektorjev za cel lpc)) kar je malo smotano glede na to da imam še samo 12 K prostora pa mora biti še vizualni izgled in i2c komunikacija.

drVrh ::

Idejo imam sedaj takšno:

void PrirpaviPodatek(unsgined int pod){
              var RAM |= pod << i;
              if(i < 32){i++;}else{
                           i = 0;
                            ShraniVFlash(pod);
              }
}


Samo to mi zdaj shrani največ 32 bitov, jaz jih pa moram 336 naenkrat. Ne vem kako naj spravim toliko bitov v FLASH.

Vesoljc ::

1) naredi komplet kopijo flasha v ramu (align to 256b)
2) buffer v ramu logicno razbijes na sektorje velike 256b
3) ko moras kaj spremeniti, popravis to v ramu, ter oznacis kateri sektor je sedaj umazan-dirty
4) ko koncas editing, grez cez seznam sektorjev, pogledas ce je dirty in ga zapises v flash

google:
- how to align memory
- bit wise operations
- bit packing
Abnormal behavior of abnormal brain makes me normal...

drVrh ::

Imam pa še eno opcijo, saj skozi IAP omogoče zapis 256B 512, 1024 ... B, zato se mora omogočati da ti tudi dobiš takšen pdoatek.
Nova ideja če bi postavil kazalec kar na array?
Zdaj imam tak array:
char* LunicaSoncek[48] = {};

Toda rabim pa samo polje veliko 336 bitov, ker se nastavi 336 enič ali nul, nič več ne znam definirati polja.
Sedaj ima narejeno tako da najbolj enostavo vnašam kar stringe "0" ali "1" kar pa je absolutno peveliko za shranjevanje.

Vesoljc tvoja ideja mi je všeč toda nisem sposoben narediti kaj takega.

Zgodovina sprememb…

  • spremenil: drVrh ()

Vesoljc ::

zakaj ne?
znas alocirat dovolj velik byte buffer, da spravis notr cel flash?
znas prebrat notr cel content flasha?
ko to naredis, velikost bufferja "mod-as" z 256 (X % 256), dobis stevilo sektorjev, iz tega allociras toliko velik byte buffer, ki ga uporabljas za markiranje dirty statusa. na loadu (flash->ram) in save (ram->flash) ta dirty buffer memsetas na 0. ko delas save, gres cez dirty buffer, ce je vrednost na indexu nonzero, potem da je ta sektor dirty, index pretvoris v offset (i * 256). ta offset pristejes naslovu bufferja v katerem imas vsebino flasha, ter dobis od kod moras zacet kopirat memory v flash, skopiras pa 256b, ker je to velikost enega sektorja.

const int BufferSize = 1024 * 1204; // 1mb
const int SectorSize = 256;
const int DirtyBufferSize = BufferSize % SectorSize; // 4096
byte* Buffer = malloc(BufferSize);
byte* DirtyBuffer = malloc(DirtyBufferSize);


void LoadFromFlash(byte* dest, int size, int secsize)
{
    // predvidevam, da se flash memory zacne na lokaciji 0?
    for(int a = 0; a < size; a += secsize)
    { 
        // iap_KOPIRAJ_FLASH_V_RAM(kam, od kje, koliko);
        // iap_KOPIRAJ_FLASH_V_RAM(dest + a, a, secsize);
    }
}

void SaveFromRamToFlash(byte* src, byte* dirty, int count, int secsize)
{
    for(int a = 0; a < count; a++)
    {
        if(dirty[a] != 0)
        {
           dirty[a] = 0; // clear
//           iap_copy_ram_to_flash(void* ram_address, void* flash_address, unsigned int count)
           // spet predvidevam, da se flash mem zacne na 0
           iap_copy_ram_to_flash(src + (a * secsize), a * secsize, secsize)
        }
    }
}

void main()
{
   LoadFromFlash(Buffer, BufferSize, SectorSize);
   // update values
   SaveFromRamToFlash(Buffer, DirtyBuffer, DirtyBufferSize, SectorSize);
}



zdej rabis pa se Get/Set funkcije za popravljat vsebino. ce rabis manipulacijo posameznih bitov, pogugli bitset, bitfield. pac iz rama potegnes iz prave lokacije X bytov, jih zbases v bitfield, popravis specificne bite, in zbases nazaj v ram.

pa vsak Set klic, zracuna katerih sektorjev se dotika, in jih nastavi na dirty.
Abnormal behavior of abnormal brain makes me normal...

Zgodovina sprememb…

  • spremenil: Vesoljc ()

drVrh ::

Ja program mi trenutno zasede cca 22k in potem imam podatke na 6 sektorju to je na cca 24k naslovu. Razmišljal sem da bi podatke dal na 6 in 7 sektor, to sta zadnja dva.
En sektor je velik 4k, ima jih 8.

Fora je v tem da se bo program še dopolnjevla in za zdaj upal da mi ne bo zasedel do 6 sektorja. Ok po tvojem načinu bi lahko zato uporabil samo en sektor v katerega bi shranjeval podatke. recimo 7 sektor, za kar pa verjetno program ne bo dosegel.

V podatke moram shraniti Lunico ali Sonček (1 ali 0) na pol urni set, torej 48 nastavitev za en dan krat 7 je to 336 bitov. Plus shraniti moram še izbiro uporabnika za jezik, to pa so številke od 1 do 7. (engl, slo, ger, ita, fra, tur, rus.).

Zgodovina sprememb…

  • spremenil: drVrh ()

drVrh ::

V UM je tabela 371 na strani 419, kjer je zapisan do koliko seže flash z naslovi. Moja opcije je tista ki gre do 7 sektorja.

Ja zadeva v flashu se bere na način kazalca. Pač postavim kazalec na naslov. Na tak način:
var = * ((uint8_t *) 0x00007000);


Ne vem v katero spremenljivkpo bi shranil 4k flasha.

Aja ne morem pa brisati posamezen page.

Zgodovina sprememb…

  • spremenil: drVrh ()

misek ::

Malce nerodno si se tega lotil. Tvoje rutine so za IAP (in application programming). Zato tudi tako veliki bloki za shrannjevanje.
Poišči raje eno kodo za emulacijo EEPROM-a. Sam sem izhajal iz AN2594: EEPROM emulation in STM32F10x microcontrollers.

drVrh ::

Tale LPC nima EEPROM-a, ravno v tem poanta vsega ....

drVrh ::

Sedaj če prav razumem rabim bitfield, ki je struktura v katero se iz RAM-a skopirajo podatki.

Vesoljc ::

Abnormal behavior of abnormal brain makes me normal...

misek ::

drVrh je izjavil:

Tale LPC nima EEPROM-a, ravno v tem poanta vsega ....
Saj poanta je ravno to, da emuliraš eeprom funkcionalnost v flashu. Poglej AN, ki sem ga omenil.

drVrh ::

Ok razumem, toda ne vem kako naj skopiram podatke iz flasha v strukturo, ki je v RAM. Recimo da imam strukturo.

struct IzFlasha{
unsigned int jezik: 8;
unsigned int LunicaSoncek : 336;
} status;

In sedaj napolnim stzrukturo z:

IzFlasha.jezik = *(uint8_t *) F_ADDR_OF_DATA; // toda ne vem kako bi naredil da bi samo prvi bajt prenselo tu notri ne pa vsega

če pa želim polniti strukturo LunicaSoncek pa imam:

IzFlasha.LunicaSoncek = *(uint8_t *) F_ADDR_OF_DATA;// toda ne vem kako bi naredil da bi samo prave bajte, ki so namenjeni za data lunica soncek prenselo tu notri ne pa vsega

Hmmm.

drVrh ::

OK ga recimo offsetam za toliko mest tja, sja to vem.
recimo potem takole:

Izflasha izf;
izf.jezik = *(uint8_t *) F_ADDR_OF_DATA;
izf.LunicaSoncek =  *(uint8_t *) (F_ADDR_OF_DATA << 8); //naslov je šiftan za 8 bitov naprej.


Kako se vam zdi ?

Zgodovina sprememb…

  • spremenil: drVrh ()

drVrh ::

Opcija namesto šiftanja: bi lahko uporabil funkcijo realloc?

drVrh ::

Ko želim definirati strukturu mi vrže vn napake:
	struct Podatki{
		unsigned int Jezik			: 8;
		unsigned int Ponedeljek		: 48;
		unsigned int Torek			: 48;
		unsigned int Sreda 			: 48;
		unsigned int Cetrtek 		: 48;
		unsigned int Petek 			: 48;
		unsigned int Sobota 		: 48;
		unsigned int Nedelja 		: 48;
	};



width of 'Cetrtek' exceeds its type
prav tako za ponedeljek, torek, sreda, petek, sobota in nedelja. Za jezik ne vrže ven nič.

Zgodovina sprememb…

  • spremenil: drVrh ()

drVrh ::

Sem sedaj naredil takole:
	struct Podatki{
		unsigned long Jezik				: 8;
		unsigned long PonedeljekAM		: 24;
		unsigned long PonedeljekPM		: 24;
		unsigned long TorekAM			: 24;
		unsigned long TorekAPM			: 24;
		unsigned long SredaAM 			: 24;
		unsigned long SredaPM 			: 24;
		unsigned long CetrtekAM 		: 24;
		unsigned long CetrtekPM 		: 24;
		unsigned long PetekAM 			: 24;
		unsigned long PetekPM 			: 24;
		unsigned long SobotaAM 			: 24;
		unsigned long SobotaPM 			: 24;
		unsigned long NedeljaAM 		: 24;
		unsigned long NedeljaPM 		: 24;
	}Podatki;

drVrh ::

Zanima me ali je s for zanko možno prestavljati elemente v strukturi.

void LoadFromFlash(){
	
	//prvi pdoatek
	for(int a = 0; a < 8; a++){
		Podatki.Jezik = *(uint8_t *) F_DRZAVA + a;		
	}
	//drugi podatek
	for(int a = 0; a < )
V TEJ FOR ZANKI BI RAD NAPOLNIL DNEVE ... EN ELEMENT JE DOLG 24 BITOV EN DAN JE DOLG DVA ELEMNETA ... KO BI NAPOLNILO EN ELEMENT BI PRESTAVIL NA DRUGEGA 

}

drVrh ::

OK imam idejo da bi podatke skopiral s pomočjo memcpy funkcije.

void LoadFromFlash(){
//prvi del pdoatkov
	memcpy(Podatki.Jezik, F_LOC, sizeof(Podatki.Jezik));
//drugi del podatkov
	for(int i = 0; i <= 7; i++){
	        memcpy(Dan[i].AM, F_LOC + (sizeof(Podatki.Jezik)), sizeof(Dan[i].AM));
	        memcpy(Dan[i].PM, F_LOC + (sizeof(Podatki.Jezik), sizeof(Dan[i].PM));
        }
}


Za drugi del podatkov bi naredil drugo strukturo, recimo takole:
	struct Dan[7]{
		long AM : 24;
		long PM : 24;		
	}Dan;

Ali je pravilne oblike.
Toda za naprej pa nevem več, ali jem ožno ti dve strukturi pred kopiranjem združiti v eno.

misek ::

Kot sem že napisal si delaš daleč preveč dela in odkrivaš toplo vodo. Uporabljaš IAP funkcionalnost za nekaj drugega in zato imaš toliko težav. Googlaj "EEPROM emulation in Flash" pa boš našel en kup zadetkov s kodo, ki dela točno to, kar ti želiš (shranjevanje podatkov v flash pomnilnik in branje iz njega).

drVrh ::

Sem iskal direktno za LPC pa ne najdem za ta moj model. Večina kod je da se brišejo page-ji pri meni pa se page ne smejo brisati ampak celoten sektor itd.

drVrh ::

Sem napisal funkcijo za loadanje iz flasha

void LoadFromFlash(){
	int stevc;

	memcpy(Podatki.Jezik, F_DRZAVA, 1);
	for(stevc = 0; stevc < 7;  stevc++){

		memcpy(Podatki.dawt[stevc].AM, F_DRZAVA, 3);
		memcpy(Podatki.dawt[stevc].PM, F_DRZAVA, 3);
	}
}


Strukturo sem naredil tako:
	typedef struct Dan{
		long AM : 24;
		long PM : 24;
	}Dan;

	struct Podatki{
		unsigned long Jezik	 : 8;
		struct Dan dawt[7];

	}Podatki;


Pri stavkih z memcpy mi vrže ven warning:
passing argument 1 of 'memcpy' makes pointer from integer without a cast

(4 x warning)

Kako se znebim tega warning-a, saj če dam pred Podatki.dawt[stevc].AM znak & mi napiše error, da ne gre dostopa do naslova bitfielda.

gumby ::

Warning je zato, ker funkciji podaš samo spremenljivko, ne pa kazalec na njo.
my brain hurts

drVrh ::

Zdravo,

želim sprogramirati strukturo s 24 bit fieldi, ko jo napolnim s 24 enicami, rezulat ni pravi.
struktura je:

union 
{
	struct
	{
		long AM :24;
	}dayAM;
	
	struct
	{
		long PM :24;
	}dayPM;
}tDay[7];

int main(){
	char str[80];
	char str1[50];
	long long kvoc = 0;
	int day = 0;
	int ura = 0;
	int binNum[24], i, j = 0;
	while(day < 7){	
		for(ura = 0; ura < 24; ura++){			
			tDay[day].dayAM.AM |= (1 << ura);			
		}
		if(ura >= 24){
			day++;
			ura = 0;
		}
	}
	
	tDay[1].dayAM.AM = (1 << 0 | 1 << 1 | 0 << 2);	
	day = 0;
	while(day < 7){
		printf( "Value : %u\n", tDay[day].dayAM.AM);
		kvoc = tDay[0].dayAM.AM;
		printf( "Velikost : %u\n", sizeof(kvoc));
		day++;
	}


V prvem izpisu se mi mora izpisati 16777215, saj je to pretvorba 24 enic v DEC zapis. Izpiše pa se mi: 4294967295
Kaj delam narobe?

Zanima me še ali je možno kako pogledati kakšno vrednost ima določen bitField, recimo if(bitField[15] == 1){....

Zgodovina sprememb…

  • spremenil: drVrh ()

Randomness ::

#include <stdio.h>

int main()
{
    unsigned int a, i;

    a = 0x00ffffff; // hex
    printf("dec: %u, oct: %o, hex: %x\n", a, a, a);

    a = 077777777; // oct
    printf("dec: %u, oct:%o, hex: %x\n", a, a, a);

    a = ~0U >> 8;
    printf("dec: %u, oct:%o, hex: %x\n", a, a, a);

    for (i = 0; i < 32; i++) {
        printf("%d-th bit is %d\n", i, a & (1 << i) ? 1 : 0);
    }

    return 0;
}

drVrh ::

Ugotovil sem da mi napolni vse 32 bitov z enicam, jaz pa ima for zanko narejeno samo do 24, ne znajdem se zakaj.


union 
{
	struct
	{
		long AM :24;
	}dayAM;	
	struct
	{
		long PM :24;
	}dayPM;
}tDay[7];

	while(day < 7){	
		for(ura = 0; ura < 24; ura++){			
			tDay[day].dayAM.AM |= (1 << ura);			
		}
		if(ura >= 24){
			day++;
			ura = 0;
		}
	}

drVrh ::

Zgornji problem je bil ker sem imel LOONG tip v strukturi, sem spremenil v unsigned int sedaj je vredu.
Imam pa naslednji problem. Ko želim podatke shrnaiti v dayAM.AM, se mi podatke shraniju tudi v dayPM.PM, zakaj? Koda je naslednja:

/*PROCES VPISOVANJA ... NA ZAČETKU JE POTREBNO BRISTAI ZATEM PA VPISOVATI*/
	/*PROCES BRISANJA*/
	for (i = 0; i < 24; i++) {
		tDay[id].dayAM.AM = ((0) << i);	
	}	
	
	/*PROCES VPISOVANJA PODATKOV*/
	for(i = 0; i < 24; i++){
		printf("%d: ", i);	
		scanf ("%d", &it); 

		tDay[id].dayAM.AM |= ((it) << i);
	}
	
	/*PROCES IZPISOVANJA*/
	for (i = 0; i < 24; i++) {
		printf("%d", tDay[id].dayAM.AM & (1 << i) ? 1 : 0);				
	}


Izpišem pa jih takole:

	for (i = 0; i < 24; i++) {
		printf("%d", tDay[id].dayAM.AM & (1 << i) ? 1 : 0);				
	}
	//scanf ("%d", &it); 	
		scanf ("%d", &it); 
	if(it == 1){		
		day = 0;		
		while(day < 7){			
			for (i = 0; i < 32; i++) {
				printf("%d", tDay[day].dayAM.AM & (1 << i) ? 1 : 0);				
			}
			//i = 0;	
			printf(": AM Day[%d]\n ", day);
			day++;
		}
		i= 0;
			day = 0;
		while(day < 7){
			for (i = 0; i < 32; i++) {
				printf("%d", tDay[day].dayPM.PM & (1 << i) ? 1 : 0);				
			}
			//i = 0;	
			printf(": PM Day[%d]\n ", day);
			day++;
		}			
	}


Na sliki se vidi s prvim modrim kaj sem vpisal, z ostalima dvema modrima pa je izpis.
 Slika

Slika

Zgodovina sprememb…

  • spremenil: drVrh ()

misek ::

drVrh je izjavil:

Ko želim podatke shrnaiti v dayAM.AM, se mi podatke shraniju tudi v dayPM.PM, zakaj?
Ker si dayAM in dayPM delita isti prostor - uporabljaš namreč union.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C] LPC1343 - UART - AT commands

Oddelek: Programiranje
91127 (1017) JanezovJanez
»

Arduino "leteče luči"

Oddelek: Elektrotehnika in elektronika
132994 (1871) zrataj4201
»

[C++] problem z binarnimi datotekami

Oddelek: Programiranje
9942 (807) mallard
»

[C/C++] unsigned long lala = -1;

Oddelek: Programiranje
51162 (1121) Vesoljc
»

Uporaba .dll

Oddelek: Programiranje
61373 (1333) Vesoljc

Več podobnih tem