Go Down

Topic: Leer bancos de memoria SD (Read 2889 times) previous topic - next topic

Lucario448

Lo de Byte a Byte es por que quiero poder guardar algo asi

Code: [Select]
int a = 5;

pero en la SD y luego almacenar variables de todo tipo y que el usuario pueda estructurar sus variables mas o menos como documentos pero que la clase se encargue de no escribir una en sima de otra dentro de la sd.
En mi librería, eso sería con:
Code: [Select]
SdRaw.write((byte*)&a, sizeof(int));

Aceptar cualquier tipo de dato en una sola función es posible, eso es lo que hacen get y put de EEPROM mediante plantillas. Originalmente, iba a implementar algo similar; pero me di por vencido desde que en cada intento siempre había un error de compilación nada descriptivo, que ninguno de este foro en español me supo decir al respecto.


Cambio un valor del Buffer y se lo envio de vuelta a la SD.
Igual, no hagas la actualización con demasiada frecuencia o no ganarás nada aún con búfer.

En mi caso, la escritura al medio físico sólo ocurre al llamado implícito y explícito de flush. El llamado implícito ocurre cuando: se cambia de sector o cuando se "cierra" la interacción con la tarjeta (como cerrar un archivo).
flush actualiza según lo dicte la respectiva bandera (variable boolean), no si el contenido del búfer realmente haya cambiado; lo que significa que hacer esto:
Code: [Select]
SdRaw.write(SdRaw.peek());
// Esto no altera en absoluto el contenido del búfer, sin embargo de todas formas lo marca como "modificado y debe actualizarse"

Podría considerarse como un "bug". Lo correcto sería validarlo mediante una suma de verificación, pero no lo hago porque eso le restaría velocidad para, por ejemplo, un datalogger.



Es verdad y no tiene sentido, pero si yo lograba escribir un solo byte en la SD sin alterar el resto del sector, podia escribir tantos byte como se me antoje
Te recuerdo que la idea del búfer es almacenar cuantos cambios se tengan que hacer, sin tener que actualizarlos todos al medio físico.


y si tengo un archivo el cual ya esta hecho pero solo quiero cambiar una porción de este mientras el código se ejecuta
Ufff, eso sería ya entrar en otra liga: la interpretación de un sistema de archivos (FAT32 en este caso). Necesitas buscar en toda la tabla de asignaciones para saber dónde exactamente inicia el archivo (muy probablemente indexado en clústeres de 4096 bytes u 8 sectores, en vez de directamente sectores de 512 bytes); y si el archivo está fragmentado... qué Dios te ayude.

Eso de "mientras el código se ejecuta" me suena a interrupciones; un ATmega328P no es un procesador multihilo como para ejecutar dos secuencias de código exactamente al mismo tiempo.


Supongamos que se te ocurre escribir desde el sector 4 en la posición 490 una cadena de 50 caracteres.
Logicamente que no entra en ese sector.
entonces mi método pretende escribir lo que puede en el sector 4 y el resto en el sector 5 sin alterar lo que hay en ese sector en los lugares que no ocupo la cadena de 50 caracteres.
Lo mismo por mi parte; las lecturas/escrituras consecutivas eventualmente provoca un cambio automático de sector (y de banco de ser el caso).

La funcion size a breves rasgos ¿de donde toma el valor de la cantidad de memoria?
Si la de mi librería, pues con cardSize de Sd2Card.


size esta sobrecargada verdad.

porque size tambien da la cantidad de caracteres que tiene un documento.
Nunca he visto que size esté sobrecargado; quizás lo hayas confundido con sizeof, strlen o String.length().
sizeof puede ser resultado de un cálculo hecho en tiempo de compilación, o alguna sección de la memoria que asocie una longitud (almacenada como un int) con un puntero.
strlen cuenta la cantidad de bytes de un array, hasta encontrarse con un cero.
String.length() simplemente retorna el valor del contador de caracteres, que es parte del objeto en sí.


Vi un archivo txt con el programa HxD y la particularidad es que una cadena como por ejemplo "stringCGE" se escribe saltando un byte asi"S-t-r-i-n-g-C-G-E"
Oh sí, el lado que muestra los valores de forma ASCII hace eso: pone un pequeño espacio entre caracteres.
Si es que literalmente hay un byte de por medio, eso ya es Unicode.


size en la libreria SD lo que me da es la cantidad de caracteres que tiene un archivo TXT.
En realidad es de bytes, pero como los caracteres ASCII son de esa longitud, al final viene siendo la misma cosa.
A nivel bajo, ese dato está en la entrada del archivo (son 4 bytes), en algún lugar de toda la tabla de asignaciones. En un sistema FAT, un entrada de archivo tiene: nombre SFN, fecha y hora de creación, fecha y hora de última modificación, atributos de Windows (archivo, sólo lectura, oculto y archivo del sistema), número del primer clúster (ojo que no es un sector absoluto) donde está ubicado y longitud real del archivo. No necesariamente en ese orden, pero sí sé que contiene toda esa información.


¿Sera que se puedo escribir un boceto en la SD y que arduino lea ese boceto y lo ejecute?
Precompilado... solo que el microprocesador tenga a la memoria RAM como parte del PC ("program counter", no "personal computer" :P ); de lo contrario solo que sea implementando un intérprete, algo así como lo hace Python.


"Discúlpenme si es que jodo tanto sabiendo tan poco"
Por mi no te preocupes, que he participado hasta en un hilo con 8 páginas.
Si no respondo rápido, puede que esté en otras o durmiendo; en espacial cuando tarde o temprano me caigan los deberes universitarios. Si no vuelvo a responder, o es porque lo doy por solucionado, o es porque quedé "en blanco" como para seguir dando respuestas.

StringCGE

#31
Mar 18, 2017, 03:15 am Last Edit: Mar 18, 2017, 03:21 am by StringCGE
Quote
Aceptar cualquier tipo de dato en una sola función es posible, eso es lo que hacen get y put de EEPROM mediante plantillas. Originalmente, iba a implementar algo similar; pero me di por vencido desde que en cada intento siempre había un error de compilación nada descriptivo, que ninguno de este foro en español me supo decir al respecto.
Podrías decirme cual es el error y ver como lo implemento en mi código.

El hecho es que soy empirico en esto y hacer un programa que lea una SD de Byte en Byte fue mera practica para poder hacer cosas mucho mejores.
Ahora que mencionas eso pienso que crees que mi idea es hacer esto.

enviar a la SD "StringCGE" al sector 2 y que lo haga byte a byte que serian 9 escrituras individuales pero la verdad no se me cruzo eso por la mente.

Lo que hago es un metodo que por ejemplo.

Quiero escribir una cadena con 50 caracteres en el sector 20 y desde la posición 492 quedándome solo
20 caracteres antes de llegar a los 512 byte que tiene el sector.
Entonces mi metodo escribe los primeros 20 caracteres en el sector 20 sin alterar las 491 posiciones anteriores (byte) y continua su escritura en los 30 byte mas del sector 21 sin alterar lo que falta de ese sector.

En cuanto a Fat. Pues mi intención es hacerme mi propia librería a modo de practica para manejar fat y formatear desde arduino y luego seguir con mi propio formato.

Interrupciones Claro que no. en otro programa se me ocurrió que arduino ejecute dos funciones al mismo tiempo pero como no es una core i2, la mejor opción si quiero eso seria ejecutar códigos separados en dos arduinos corriendo a la vez y sincronizados pero ya abriré otro hilo para eso en cuanto plantee mejor la situación.

Me doy cuenta que pòr responder por partes ya he explicado algo y se queda hay (ejemplo de escritura en dos sectores).

Tengo ideas que van mas aya de mis conocimientos y mueren hay. Hasta que tengo el conocimiento y emergen con mas fuerza.
Por cierto.
Error quemando bootloader first mismatch at byte 0x0000 no resuelvo eso y creo que seria bueno saber que se hace con eso.
Olvidarlo o intentar algo por saber las causas para no cometer el mismo error en la proxima

Lucario448

Podrías decirme cual es el error y ver como lo implemento en mi código.
Código (lectura):
Code: [Select]
template< typename T > unsigned int SdRawClass::get(unsigned long idx, const T& t) {
  if (!seek(idx)) return 0;
  return readBytes((unsigned char*)&t, sizeof(t));
}


Error:
Code: [Select]
C:\Users\Usuario\AppData\Local\Temp\ccTtTKqk.ltrans0.ltrans.o: In function `main':

ccTtTKqk.ltrans0.o:(.text.startup+0x486): undefined reference to `unsigned int SdRawClass::get<int>(unsigned long, int const&)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Error de compilación



El hecho es que soy empirico en esto y hacer un programa que lea una SD de Byte en Byte fue mera practica para poder hacer cosas mucho mejores.
Ojalá y en serio lo mejores.


la mejor opción si quiero eso seria ejecutar códigos separados en dos arduinos corriendo a la vez y sincronizados pero ya abriré otro hilo para eso en cuanto plantee mejor la situación.
Se oye interesante. Yo lo más cercano que he hecho, es interconectar (e intercomunicar) dos Arduinos mediante USART.

Tengo ideas que van mas aya de mis conocimientos y mueren hay. Hasta que tengo el conocimiento y emergen con mas fuerza.
Tiene sentido...


Error quemando bootloader first mismatch at byte 0x0000 no resuelvo eso y creo que seria bueno saber que se hace con eso.
Respondo por aquí porque ese hilo está muy viejo como para responder.

Los "mismatch" son causados porque supuestamente el programa no se está escribiendo como se debe; básicamente es una verficación de integridad. Podrías probar subiendo programas con un convertidor USB/UART TTL externo; de lo contrario revisar las configuraciones para deshabilitar la verficación, y correr el riesgo.

StringCGE

Cuando pregunte. Asumí que el código en cuestion tenia que ver con el IDE de arduino.

Code: [Select]
undefined reference to me paso cuando en Dev C++ yo intente hacer un programa con WinAPI y quería trazar una linea directamente sobre la ventana y me decía que esta indefinida la función LineTo que esta presente en windows.h en alguna parte de ese mar de librerias.

Ahora que uso Visual Basic Se que tengo que graficar una linea dentro de un pictureBox O al menos es lo que me da a entender el Propio Visual Basic.

Entonces en Dev C++ me sale indefinido no porque la función o método no esta sino porque esta requiere algún otro medio para funcionar.

Es lo que puedo comprender a breves rasgos.

Para seguir en esa función yo busco todo lo que esta involucrado al rededor del error pero no tengo la clase SdRawClass en la librería SD de arduino y por hay vi main y exe lo cual indica que es una aplicación windows y asumo que es una clase que la estas haciendo por como se ve desde mi perspectiva.
Ademas no se que función cumple esto
Code: [Select]
template< typename T >

y desde ya tiempos no se que es esto

Code: [Select]
const T& t
Así que en vez de ayudar creo que termino siendo ayudado al rededor de esta función de lectura.

Se desvió el tema Y el arduino es un NANO en del error y tendría que desoldar el TTL o el AT mega.

ahora ya tengo el código para leer string y ya vi la EEPROM

Code: [Select]
EEPROM.update(address, val);
EEPROM.write(addr, val);


No son metodos que entienda del todo pero de hay.
Mi código para SD_Byte cumple con esas expectativas.

Ya compensare a ver los mensajes de Info de la sd Y cuando termine eso quiero publicar mi libreria para que me corrijan pero quiero hacerlo de modo que sea libre su uso pero me pertenezca y no me molesten por derechos de autor cuando en un centro educativo me digan "Lo copiaste de Internet".
Ya compensare  a buscar

Lucario448

#34
Mar 18, 2017, 08:27 pm Last Edit: Mar 18, 2017, 08:28 pm by Lucario448
Entonces en Dev C++ me sale indefinido no porque la función o método no esta sino porque esta requiere algún otro medio para funcionar.
Para mi caso no creo que aplique; o simplemente no entendí esa afirmación.

Para seguir en esa función yo busco todo lo que esta involucrado al rededor del error pero no tengo la clase SdRawClass en la librería SD de arduino
SdRawClass es el nombre de la clase de mi librería, definitivamente no iba a existir en SD.


Ademas no se que función cumple esto
Code: [Select]
template< typename T >
Indicativo de que la función es un plantilla. typename T quiere decir que trabaja con cualquier tipo de dato; y que en la implementación ese tipo de dato lo llamaremos 'T'.
En POO, es la contraparte de una "función genérica".

y desde ya tiempos no se que es esto

Code: [Select]
const T& t
Fue copiado de get en EEPROM; se supone que realiza un paso por referencia "implícito" de la variable que se le ingrese. T es el tipo de dato definido en la plantilla (ver arriba).

Implícito porque...
Code: [Select]
EEPROM.get(0, variable);
¿De qué otra forma la función puede obtener el puntero sin tener que anteponerle '&' al nombre de esa variable?


y ya vi la EEPROM

Code: [Select]
EEPROM.update(address, val);
EEPROM.write(addr, val);


No son metodos que entienda del todo
Yo sí, excepto por el hecho de que la definición les funciona y la obtención implícita del puntero.

StringCGE

Ya e visto el registro CSD de la tarjeta SD y con
Code: [Select]

Archive Sd2Card.cpp
Line 132  uint32_t Sd2Card::cardSize(void) {

me retorna como valor int 285 y hex 11D vistos en el monitor serial y mi SD es de 4 gb.

Que se supone que me dice ese número. 

Lucario448

Que uint32_t es el equivalente a unsigned long, no a int. 0x011D deben ser los dos bytes menos significativos de un valor de 4 bytes, pues lógicamente está muy fuera de la realidad.

Si el conteo de bloques fuera con 16 bits, no se podrían direccionar más de 32 MB.

StringCGE

bueno hay si me exprese mal aquí dejo de donde sale todo.
Code: [Select]
typedef struct CSDV2 {
  // byte 0
  unsigned reserved1 : 6;
  unsigned csd_ver : 2;
  // byte 1
  uint8_t taac;
  // byte 2
  uint8_t nsac;
  // byte 3
  uint8_t tran_speed;
  // byte 4
  uint8_t ccc_high;
  // byte 5
  unsigned read_bl_len : 4;
  unsigned ccc_low : 4;
  // byte 6
  unsigned reserved2 : 4;
  unsigned dsr_imp : 1;
  unsigned read_blk_misalign :1;
  unsigned write_blk_misalign : 1;
  unsigned read_bl_partial : 1;
  // byte 7
  unsigned reserved3 : 2;
  unsigned c_size_high : 6;
  // byte 8
  uint8_t c_size_mid;
  // byte 9
  uint8_t c_size_low;
  // byte 10
  unsigned sector_size_high : 6;
  unsigned erase_blk_en : 1;
  unsigned reserved4 : 1;
  // byte 11
  unsigned wp_grp_size : 7;
  unsigned sector_size_low : 1;
  // byte 12
  unsigned write_bl_len_high : 2;
  unsigned r2w_factor : 3;
  unsigned reserved5 : 2;
  unsigned wp_grp_enable : 1;
  // byte 13
  unsigned reserved6 : 5;
  unsigned write_partial : 1;
  unsigned write_bl_len_low : 2;
  // byte 14
  unsigned reserved7: 2;
  unsigned file_format : 2;
  unsigned tmp_write_protect : 1;
  unsigned perm_write_protect : 1;
  unsigned copy : 1;
  unsigned file_format_grp : 1;
  // byte 15
  unsigned always1 : 1;
  unsigned crc : 7;
} csd2_t;


Esa estructura es de SDInfo.h

ahora
Code: [Select]
Registro CSD

0 FE 2 54 4D 53 41 30 34 47 11 38 A8 A2 C6 0 E1 B7 E7 6F

Eso es lo que obtengo por el monitor serial del registro CSD y segun lo que he leido

0x0 = estado de la SD

0xFE = data token listo para envio de lo que se le pida a la sd (en este caso registro CSD)

el registro esta compuesto por 128 bit o 16 byte que seria desde 0x02 (incluido) hasta 0xB7 (incluido)

Mi modificación de funcion

Code: [Select]
bool readRegister(uint8_t cmd, void* buf) {
 
  uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
  txrx_spiSD(cmd,0,0xFF);
  mmm = 1;
  while(mmm){
    LeeSD();
    if (R1_SD == 0xFE){
      mmm = 0;
    }
  }
  mmm = 1;
 
  // guardar datos en la estructura del registro CSD
  for (uint16_t i = 0; i < 16; i++){LeeSD(); dst[i] = R1_SD;}
  LeeSD();  // get first crc byte
  LeeSD();  // get second crc byte
  return true;

 fail:
  return false;
}

Si ve la libreria de SD comprendera mas y se me cruzo por la cabeza que tal vez este desalineado el registro SD con respecto a la estructura
Ademas hay cosas que no entiendo en ese codigo pero ya haré mis bocetos en arduino para ver como funcionan las cosas en ese codigo.

Ahora por hay se encuentra un while para mas raro con mmm que es un booleano global y de hecho me hace mas fácil la visión de alguna falla en while pero también provoca errores que dan un dolor de cabeza.

y lo que tengo inconvenientes.

Code: [Select]
uint32_t cardSize(void) {
  csd_t csd;
  if (!readRegister(0x4A, &csd)) return 0;
  if (csd.v1.csd_ver == 0) {
    uint8_t read_bl_len = csd.v1.read_bl_len;
    uint16_t c_size = (csd.v1.c_size_high << 10)
                      | (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
    uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
                          | csd.v1.c_size_mult_low;
    return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
  } else if (csd.v2.csd_ver == 1) {
    uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
                      | (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
    return (c_size + 1) << 10;
  } else {
    Serial.println("Error 0101");
    return 0;
  }
}


esa función retorna uint32_t el cual es almacenado en una variable llamada R_32 Respuesta de 32 bit por eso el nombre.

Y se saca por el monitor serial asi.
Code: [Select]
Serial.println(R_32);
Serial.println(R_32,HEX);

A eso me refería como int y Hex pero muy mal expresado.

StringCGE

Lo que olvide poner es que la razón de esto es ver cuantos sectores tengo para escribir.

Lucario448

#39
Mar 25, 2017, 04:20 am Last Edit: Mar 25, 2017, 04:22 am by Lucario448
Prueba imprimiendo los valores de cada byte, para corroborar que el valor realmente no esté fuera de la realidad:

Code: [Select]
byte* b = (byte*)&R_32;
for (byte i = 0; i < sizeof(uint32_t); i++) {
  Serial.print(b[i]);
  Serial.write(' ');
}

StringCGE

Si lo hice pero de todos modos me entra la duda de porque ese valor de la función cardSize.
¿Como se cuantos sectores físicos x tarjeta desde el programa?
No quiero tener que estar viendo si la tarjeta es de 4gb entones tendrá x sectores segun la asociación SD.

Lucario448

#41
Mar 25, 2017, 11:20 pm Last Edit: Mar 25, 2017, 11:21 pm by Lucario448
¿Como se cuantos sectores físicos x tarjeta desde el programa?
Pues con esa función.

Sd2Card es una abstracción del medio físico, independientemente de las particiones o sistema de archivos.

Go Up