Página 1 de 2

[ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 30 Dez 2016 19:10
por andre_luis
Pessoal,


Alguem possui alguma biblioteca minima, sem sistema de arquivos, algo com um simples mapeamento endereço/conteúdo ?
Tudo o que tenho encontrado na Web é muito complicada para o que preciso, que seria apenas o driver SPI.

A proposito, o cartão estará soldado na placa, de modo que não haverá necessidade de leitura externa.


AT+

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 30 Dez 2016 23:55
por andre_luis
Encontrei essa biblioteca, que pareceu ser das mais simples que encontrei:
https://github.com/1nv1/ulibSD

Porém, compilando no WinAVR, me deparei com o seguinte erro...
../main.h:130: error: expected identifier before numeric constant

...na linha abaixo:
Código: Selecionar todos
typedef enum { FALSE=0 , TRUE } BOOLEAN ;


Tentei de tudo, (pre)definir os elementos acima em #define, como também outras variações, mas nada feito.
Alguem teria uma dica de como resolver isso ?


AT+

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 31 Dez 2016 08:10
por edsont
Já tentou sem as atribuições?

Código: Selecionar todos
typedef enum { FALSE, TRUE } BOOLEAN ;

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 31 Dez 2016 11:37
por andre_luis
Sim, mesmo erro.
Tentei pre definir os parametros em preprocessor's #define, mas também nao rolou.

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 31 Dez 2016 12:02
por edsont
andre_teprom escreveu:Sim, mesmo erro.
Tentei pre definir os parametros em preprocessor's #define, mas também nao rolou.


Será que FALSE, TRUE ou BOOLEAN não estariam definidos em outro local ou em alguma lib?

Testa com FALSO, VERDADEIRO e BOOLEANO pra ver se ocorre o mesmo erro.

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 31 Dez 2016 17:11
por andre_luis
Tentei de tudo, e neca...

Bom, acabei desistindo dessa biblioteca acima, e encontrei uma outra no site pudn, que pareceu muuuuuito mais simples:
MMC_SD.h e MMC_SD.c. Tem varios homonimos lá, não lembro do link, mas no cabçalho tem esse texto:
/* ELEC254 Group32 USB SD Card Reader */

O problema é que mesmo essa aí, por mais compacta que seja, ainda lida com sistema de arquivos.
Eu estava precisando de algo bem mais simples, apenas um endereçamento direto.

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 10:46
por Red Neck Guy
cpp code
#include <nxp\iolpc1768.h>
#include "diskio.h"
#include "integer.h"
#include "..\..\hal\sd card\sdcard.h"
#include "sd_diskio.h"


DSTATUS sdStatus=STA_NOINIT;

/***********************************************************************************
* Descrição : Inicialização dos drives do sistema
* Parametros : (unsigned char) número do drive
* Retorno : (DSTATUS)
***********************************************************************************/
unsigned int SD_disk_initialize(void){

if( SD_Init()){
sdStatus &= ~STA_NOINIT;
return 0;
}

sdStatus |= STA_NOINIT;
return STA_NOINIT;
//ToDo: Inserir verificação do flag de proteção de escrita
}
/***********************************************************************************
* Descrição : Lê o status do disco passado no parametro
* Parametros : (unsigned char) número do drive
* Retorno : nenhum
***********************************************************************************/
DSTATUS SD_disk_status (void){

return sdStatus;
}
/***********************************************************************************
* Descrição : Lê um setor de uma das unidades de disco
* Parametros : (unsigned char) drive
* (unsigned char*) buffer
* (unsigned long int) setor
* (unsigned char) tamanho do bloco lido
* Retorno : (DRESULT)
***********************************************************************************/
DRESULT SD_disk_read (unsigned char *buffer,DWORD sector,unsigned char count){

if(SD_ReadSector(sector,buffer,count))
return RES_OK;

return RES_ERROR;
}
/***********************************************************************************
* Descrição : Escreve em um setor de um determinado disco
* Parametros : (unsigned char) drive
* (unsigned char*) buffer
* (unsigned int) número do setor
* (unsigned char) tamanho do bloco escrito
* Retorno : (DRESULT)
***********************************************************************************/
DRESULT SD_disk_write(unsigned char *buff,DWORD sector,unsigned char byte){

if(SD_WriteSector(sector,buff,byte))
return RES_OK;

return RES_ERROR;
}
/***********************************************************************************
* Descrição : Controle de funções específicas do disco
* Parametros : (unsigned char) drive
* (unsigned char) comando
* (void*) ponteiro para a estrutura de controle do
* comando que será executado
* Retorno : nenhum
***********************************************************************************/
DRESULT SD_disk_ioctl(unsigned char ctrl,void *buff){

if(ctrl==GET_BLOCK_SIZE)
*(unsigned int*)buff = 512;

return RES_ERROR;
}
/***********************************************************************************
* Fim do arquivo
***********************************************************************************/

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 10:46
por Red Neck Guy
cpp code
#ifndef _SD_DISK_IO_H_
#define _SD_DISK_IO_H_

unsigned int SD_disk_initialize(void);
DSTATUS SD_disk_status (void);
DRESULT SD_disk_read (unsigned char *buffer,DWORD sector,unsigned char count);
DRESULT SD_disk_write(unsigned char *buff,DWORD sector,unsigned char byte);
DRESULT SD_disk_ioctl(unsigned char ctrl,void *buff);

/***********************************************************************************
* Fim do arquivo
***********************************************************************************/
#endif // _SD_DISK_IO_H_

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 10:47
por Red Neck Guy
cpp code
#include "spi_wrapper_sd.h"
#include "sdcard.h"

/* Command definitions in SPI bus mode */
#define GO_IDLE_STATE 0
#define SEND_OP_COND 1
#define SWITCH_FUNC 6
#define SEND_IF_COND 8
#define SEND_CSD 9
#define SEND_CID 10
#define STOP_TRANSMISSION 12
#define SEND_STATUS 13
#define SET_BLOCKLEN 16
#define READ_SINGLE_BLOCK 17
#define READ_MULTIPLE_BLOCK 18
#define WRITE_SINGLE_BLOCK 24
#define WRITE_MULTIPLE_BLOCK 25
#define APP_CMD 55
#define READ_OCR 58
#define CRC_ON_OFF 59

/* Application specific commands supported by SD.
All these commands shall be preceded with APP_CMD (CMD55). */
#define SD_STATUS 13
#define SD_SEND_OP_COND 41

/* R1 response bit flag definition */
#define R1_NO_ERROR 0x00
#define R1_IN_IDLE_STATE 0x01
#define R1_ERASE_RESET 0x02
#define R1_ILLEGAL_CMD 0x04
#define R1_COM_CRC_ERROR 0x08
#define R1_ERASE_SEQ_ERROR 0x10
#define R1_ADDRESS_ERROR 0x20
#define R1_PARA_ERROR 0x40
#define R1_MASK 0x7F

/* The sector size is fixed to 512bytes in most applications. */
#define SECTOR_SIZE 512


/* Global variables */
unsigned char CardType; /* card type */
CARDCONFIG CardConfig; /* Card configuration */

/* Local variables */
static volatile unsigned int Timer1, Timer2; /* 100Hz decrement timer stopped at zero (disk_timerproc()) */

/** Select the card */
#define SD_Select() do {SPI_CS_Low();} while (0)
/** DeSelect the card */
#define SD_DeSelect() do { SPI_CS_High ();SPI_RecvByte();} while (0)

/* Local functions */
SD_BOOL SD_Init (void);
SD_BOOL SD_ReadSector (unsigned int sect, unsigned char *buf, unsigned int cnt);
SD_BOOL SD_WriteSector (unsigned int sect, const unsigned char *buf, unsigned int cnt);
SD_BOOL SD_ReadConfiguration (void);
unsigned char SD_SendCommand (unsigned char cmd, unsigned int arg, unsigned char *buf, unsigned int len);
unsigned char SD_SendACommand (unsigned char cmd, unsigned int arg, unsigned char *buf, unsigned int len);
SD_BOOL SD_RecvDataBlock (unsigned char *buf, unsigned int len);
SD_BOOL SD_SendDataBlock (const unsigned char *buf, unsigned char tkn, unsigned int len) ;
SD_BOOL SD_WaitForReady (void);

/***********************************************************************************
* Descrição : Função de temporização da biblioteca, deve
* ser executada a cada 10ms
* Parametros : nenhum
* Retorno : nenhum
***********************************************************************************/
void disk_timerproc (void){
static unsigned char counter=10;
unsigned int n;

if(counter){
counter--;
return;
}

counter=10;

n = Timer1; /* 100Hz decrement timer stopped at 0 */
if (n) Timer1 = --n;
n = Timer2;
if (n) Timer2 = --n;
}
/***********************************************************************************
* Descrição : Inicialização do módulo
* Parametros : nenhum
* Retorno : nenhum
***********************************************************************************/
SD_BOOL SD_Init (void)
{
unsigned int i;
unsigned char r1, buf[4];

/* Set card type to unknown */
CardType = CARDTYPE_UNKNOWN;

/* Init SPI interface */
SPI_Init ();

/* Before reset, Send at least 74 clocks at low frequency
(between 100kHz and 400kHz) with CS high and DI (MISO) high. */
SD_DeSelect();
SPI_ConfigClockRate (SPI_CLOCKRATE_LOW);
for (i = 0; i < 10; i++) SPI_SendByte (0xFF);

/* Send CMD0 with CS low to enter SPI mode and reset the card.
The card will enter SPI mode if CS is low during the reception of CMD0.
Since the CMD0 (and CMD8) must be sent as a native command, the CRC field
must have a valid value. */
if (SD_SendCommand (GO_IDLE_STATE, 0, NULL, 0) != R1_IN_IDLE_STATE) // CMD0
{
goto init_end;
}

/* Now the card enters IDLE state. */

/* Card type identification Start ... */

/* Check the card type, needs around 1000ms */
r1 = SD_SendCommand (SEND_IF_COND, 0x1AA, buf, 4); // CMD8
if (r1 & 0x80) goto init_end;

Timer1 = 100; // 1000ms
if (r1 == R1_IN_IDLE_STATE) { /* It's V2.0 or later SD card */
if (buf[2]!= 0x01 || buf[3]!=0xAA) goto init_end;

/* The card is SD V2 and can work at voltage range of 2.7 to 3.6V */

do {
r1 = SD_SendACommand (SD_SEND_OP_COND, 0x40000000, NULL, 0); // ACMD41
if (r1 == 0x00) break;
else if (r1 > 0x01) goto init_end;
} while (Timer1);

if (Timer1 && SD_SendCommand (READ_OCR, 0, buf, 4)==R1_NO_ERROR) // CMD58
CardType = (buf[0] & 0x40) ? CARDTYPE_SDV2_HC : CARDTYPE_SDV2_SC;

} else { /* It's Ver1.x SD card or MMC card */

/* Check if it is SD card */
if (SD_SendCommand (APP_CMD, 0, NULL, 0) & R1_ILLEGAL_CMD)
{
CardType = CARDTYPE_MMC;
while (Timer1 && SD_SendCommand (SEND_OP_COND, 0, NULL, 0));
}
else
{
CardType = CARDTYPE_SDV1;
while (Timer1 && SD_SendACommand (SD_SEND_OP_COND, 0, NULL, 0));
}

if (Timer1 == 0) CardType = CARDTYPE_UNKNOWN;
}

/* For SDHC or SDXC, block length is fixed to 512 bytes, for others,
the block length is set to 512 manually. */
if (CardType == CARDTYPE_MMC ||
CardType == CARDTYPE_SDV1 ||
CardType == CARDTYPE_SDV2_SC )
{
if (SD_SendCommand (SET_BLOCKLEN, SECTOR_SIZE, NULL, 0) != R1_NO_ERROR)
CardType = CARDTYPE_UNKNOWN;
}

init_end:
SD_DeSelect();

if (CardType == CARDTYPE_UNKNOWN)
{
return (SD_FALSE);
}
else /* Init OK. use high speed during data transaction stage. */
{
SPI_ConfigClockRate (SPI_CLOCKRATE_HIGH);
return (SD_TRUE);
}
}
/***********************************************************************************
* @brief Wait for the card is ready.
*
* @param None
* @retval SD_TRUE: Card is ready for read commands.
* SD_FALSE: Card is not ready
***********************************************************************************/
SD_BOOL SD_WaitForReady (void)
{
Timer2 = 50; // 500ms
SPI_RecvByte(); /* Read a byte (Force enable DO output) */
do {
if (SPI_RecvByte () == 0xFF) return SD_TRUE;
} while (Timer2);

return SD_FALSE;
}
/***********************************************************************************
* @brief Send a command and receive a response with specified format.
*
* @param cmd: Specifies the command index.
* @param arg: Specifies the argument.
* @param buf: Pointer to byte array to store the response content.
* @param len: Specifies the byte number to be received after R1 response.
* @retval Value below 0x80 is the normal R1 response (0x0 means no error)
* Value above 0x80 is the additional returned status code.
* 0x81: Card is not ready
* 0x82: command response time out error
***********************************************************************************/
unsigned char SD_SendCommand (unsigned char cmd, unsigned int arg, unsigned char *buf, unsigned int len)
{
unsigned int r1,i;
unsigned char crc_stop;

/* The CS signal must be kept low during a transaction */
SD_Select();

/* Wait until the card is ready to read (DI signal is High) */
if (SD_WaitForReady() == SD_FALSE) return 0x81;

/* Prepare CRC7 + stop bit. For cmd GO_IDLE_STATE and SEND_IF_COND,
the CRC7 should be valid, otherwise, the CRC7 will be ignored. */
if (cmd == GO_IDLE_STATE) crc_stop = 0x95; /* valid CRC7 + stop bit */
else if (cmd == SEND_IF_COND) crc_stop = 0x87; /* valid CRC7 + stop bit */
else crc_stop = 0x01; /* dummy CRC7 + Stop bit */

/* Send 6-byte command with CRC. */
SPI_SendByte (cmd | 0x40);
SPI_SendByte (arg >> 24);
SPI_SendByte (arg >> 16);
SPI_SendByte (arg >> 8);
SPI_SendByte (arg);
SPI_SendByte (crc_stop); /* Valid or dummy CRC plus stop bit */


/* The command response time (Ncr) is 0 to 8 bytes for SDC,
1 to 8 bytes for MMC. */
for (i = 8; i; i--)
{
r1 = SPI_RecvByte ();
if (r1 != 0xFF) break; /* received valid response */
}
if (i == 0) return (0x82); /* command response time out error */

/* Read remaining bytes after R1 response */
if (buf && len)
{
do {
*buf++ = SPI_RecvByte ();
} while (--len);
}

return (r1);
}
/***********************************************************************************
* @brief Send an application specific command for SD card
* and receive a response with specified format.
*
* @param cmd: Specifies the command index.
* @param arg: Specifies the argument.
* @param buf: Pointer to byte array to store the response content.
* @param len: Specifies the byte number to be received after R1 response.
* @retval Value below 0x80 is the normal R1 response(0x0 means no error)
* Value above 0x80 is the additional returned status code.
* 0x81: Card is not ready
* 0x82: command response time out error
*
* Note: All the application specific commands should be precdeded with APP_CMD
***********************************************************************************/
unsigned char SD_SendACommand (unsigned char cmd, unsigned int arg, unsigned char *buf, unsigned int len)
{
unsigned char r1;

/* Send APP_CMD (CMD55) first */
r1 = SD_SendCommand(APP_CMD, 0, NULL, 0);
if (r1 > 1) return r1;

return (SD_SendCommand (cmd, arg, buf, len));
}
/***********************************************************************************
* @brief Read single or multiple sector(s) from memory card.
*
* @param sect: Specifies the starting sector index to read
* @param buf: Pointer to byte array to store the data
* @param cnt: Specifies the count of sectors to read
* @retval SD_TRUE or SD_FALSE.
***********************************************************************************/
SD_BOOL SD_ReadSector (unsigned int sect, unsigned char *buf, unsigned int cnt)
{
SD_BOOL flag;

/* Convert sector-based address to byte-based address for non SDHC */
if (CardType != CARDTYPE_SDV2_HC) sect <<= 9;

flag = SD_FALSE;

if (cnt > 1) /* Read multiple block */
{
if (SD_SendCommand(READ_MULTIPLE_BLOCK, sect, NULL, 0) == R1_NO_ERROR)
{
do {
if (SD_RecvDataBlock(buf, SECTOR_SIZE) == SD_FALSE) break;
buf += SECTOR_SIZE;
} while (--cnt);

/* Stop transmission */
SD_SendCommand(STOP_TRANSMISSION, 0, NULL, 0);

/* Wait for the card is ready */
if (SD_WaitForReady() && cnt==0) flag = SD_TRUE;
}
}
else /* Read single block */
{
if ((SD_SendCommand(READ_SINGLE_BLOCK, sect, NULL, 0)==R1_NO_ERROR) &&
SD_RecvDataBlock(buf, SECTOR_SIZE)==SD_TRUE)
flag = SD_TRUE;
}

/* De-select the card */
SD_DeSelect();

return (flag);
}
/***********************************************************************************
* @brief Write single or multiple sectors to SD/MMC.
*
* @param sect: Specifies the starting sector index to write
* @param buf: Pointer to the data array to be written
* @param cnt: Specifies the number sectors to be written
* @retval SD_TRUE or SD_FALSE
***********************************************************************************/
SD_BOOL SD_WriteSector (unsigned int sect, const unsigned char *buf, unsigned int cnt)
{
SD_BOOL flag;

/* Convert sector-based address to byte-based address for non SDHC */
if (CardType != CARDTYPE_SDV2_HC) sect <<= 9;

flag = SD_FALSE;
if (cnt > 1) /* write multiple block */
{
if (SD_SendCommand (WRITE_MULTIPLE_BLOCK, sect, NULL, 0) == R1_NO_ERROR)
{
do {
if (SD_SendDataBlock (buf, 0xFC, SECTOR_SIZE) == SD_FALSE) break;
buf += SECTOR_SIZE;
} while (--cnt);

/* Send Stop Transmission Token. */
SPI_SendByte (0xFD);

/* Wait for complete */
if (SD_WaitForReady() && cnt==0) flag = SD_TRUE;
}
}
else /* write single block */
{

if ( (SD_SendCommand (WRITE_SINGLE_BLOCK, sect, NULL, 0) == R1_NO_ERROR) &&
(SD_SendDataBlock (buf, 0xFE, SECTOR_SIZE) == SD_TRUE))
flag = SD_TRUE;
}

/* De-select the card */
SD_DeSelect();

return (flag);
}
/***********************************************************************************
* @brief Read card configuration and fill structure CardConfig.
*
* @param None
* @retval SD_TRUE or SD_FALSE.
***********************************************************************************/
SD_BOOL SD_ReadConfiguration ()
{
unsigned char buf[16];
unsigned int i, c_size, c_size_mult, read_bl_len;
SD_BOOL retv;

retv = SD_FALSE;

/* Read OCR */
if (SD_SendCommand(READ_OCR, 0, CardConfig.ocr, 4) != R1_NO_ERROR) goto end;

/* Read CID */
if ((SD_SendCommand(SEND_CID, 0, NULL, 0) != R1_NO_ERROR) ||
SD_RecvDataBlock (CardConfig.cid, 16)==SD_FALSE) goto end;

/* Read CSD */
if ((SD_SendCommand(SEND_CSD, 0, NULL, 0) != R1_NO_ERROR) ||
SD_RecvDataBlock (CardConfig.csd, 16)==SD_FALSE) goto end;

/* sector size */
CardConfig.sectorsize = 512;

/* sector count */
if (((CardConfig.csd[0]>>6) & 0x3) == 0x1) /* CSD V2.0 (for High/eXtended Capacity) */
{
/* Read C_SIZE */
c_size = (((unsigned int)CardConfig.csd[7]<<16) + ((unsigned int)CardConfig.csd[8]<<8) + CardConfig.csd[9]) & 0x3FFFFF;
/* Calculate sector count */
CardConfig.sectorcnt = (c_size + 1) * 1024;

} else /* CSD V1.0 (for Standard Capacity) */
{
/* C_SIZE */
c_size = (((unsigned int)(CardConfig.csd[6]&0x3)<<10) + ((unsigned int)CardConfig.csd[7]<<2) + (CardConfig.csd[8]>>6)) & 0xFFF;
/* C_SIZE_MUTE */
c_size_mult = ((CardConfig.csd[9]&0x3)<<1) + ((CardConfig.csd[10]&0x80)>>7);
/* READ_BL_LEN */
read_bl_len = CardConfig.csd[5] & 0xF;
/* sector count = BLOCKNR*BLOCK_LEN/512, we manually set SECTOR_SIZE to 512*/
//CardConfig.sectorcnt = (c_size+1)*(1<<read_bl_len) * (1<<(c_size_mult+2)) / 512;
CardConfig.sectorcnt = (c_size+1) << (read_bl_len + c_size_mult - 7);
}

/* Get erase block size in unit of sector */
switch (CardType)
{
case CARDTYPE_SDV2_SC:
case CARDTYPE_SDV2_HC:
if ((SD_SendACommand (SD_STATUS, 0, buf, 1) != R1_NO_ERROR) ||
SD_RecvDataBlock(buf, 16) == SD_FALSE) goto end; /* Read partial block */
for (i=64-16;i;i--) SPI_RecvByte(); /* Purge trailing data */
CardConfig.blocksize = 16UL << (buf[10] >> 4); /* Calculate block size based on AU size */
break;
case CARDTYPE_MMC:
CardConfig.blocksize = ((unsigned short int)((CardConfig.csd[10] & 124) >> 2) + 1) * (((CardConfig.csd[10] & 3) << 3) + ((CardConfig.csd[11] & 224) >> 5) + 1);
break;
case CARDTYPE_SDV1:
CardConfig.blocksize = (((CardConfig.csd[10] & 63) << 1) + ((unsigned short int)(CardConfig.csd[11] & 128) >> 7) + 1) << ((CardConfig.csd[13] >> 6) - 1);
break;
default:
goto end;
}

retv = SD_TRUE;
end:
SD_DeSelect ();

return retv;
}
/***********************************************************************************
* @brief Receive a data block with specified length from SD/MMC.
*
* @param buf: Pointer to the data array to store the received data
* @param len: Specifies the length (in byte) to be received.
* The value should be a multiple of 4.
* @retval SD_TRUE or SD_FALSE
***********************************************************************************/
SD_BOOL SD_RecvDataBlock (unsigned char *buf, unsigned int len)
{
unsigned char datatoken;
unsigned int i;

/* Read data token (0xFE) */
Timer1 = 10; /* Data Read Timerout: 100ms */
do {
datatoken = SPI_RecvByte ();
if (datatoken == 0xFE) break;
} while (Timer1);
if(datatoken != 0xFE) return (SD_FALSE); /* data read timeout */

/* Read data block */
for (i = 0; i < len; i++) {
buf[i] = SPI_RecvByte ();
}

/* 2 bytes CRC will be discarded. */
SPI_RecvByte ();
SPI_RecvByte ();

return (SD_TRUE);
}
/***********************************************************************************
* @brief Send a data block with specified length to SD/MMC.
*
* @param buf: Pointer to the data array to store the received data
* @param tkn: Specifies the token to send before the data block
* @param len: Specifies the length (in byte) to send.
* The value should be 512 for memory card.
* @retval SD_TRUE or SD_FALSE
***********************************************************************************/
SD_BOOL SD_SendDataBlock (const unsigned char *buf, unsigned char tkn, unsigned int len)
{
unsigned char recv;
unsigned int i;

/* Send Start Block Token */
SPI_SendByte (tkn);

/* Send data block */
for (i = 0; i < len; i++)
{
SPI_SendByte (buf[i]);
}

/* Send 2 bytes dummy CRC */
SPI_SendByte (0xFF);
SPI_SendByte (0xFF);

/* Read data response to check if the data block has been accepted. */
if (( (SPI_RecvByte ()) & 0x0F) != 0x05)
return (SD_FALSE); /* write error */

/* Wait for wirte complete. */
Timer1 = 20; // 200ms
do {
recv = SPI_RecvByte();
if (recv == 0xFF) break;
} while (Timer1);

if (recv == 0xFF) return SD_TRUE; /* write complete */
else return (SD_FALSE); /* write time out */
}
/***********************************************************************************
* Fim do arquivo
***********************************************************************************/

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 10:48
por Red Neck Guy
cpp code
#ifndef _SDCARD_H_
#define _SDCARD_H_

/* type defintion */
typedef unsigned char SD_BOOL;
#define SD_TRUE 1
#define SD_FALSE 0

#ifndef NULL
#ifdef __cplusplus // EC++
#define NULL 0
#else
#define NULL ((void *) 0)
#endif
#endif

/* Memory card type definitions */
#define CARDTYPE_UNKNOWN 0
#define CARDTYPE_MMC 1 /* MMC */
#define CARDTYPE_SDV1 2 /* V1.x Standard Capacity SD card */
#define CARDTYPE_SDV2_SC 3 /* V2.0 or later Standard Capacity SD card */
#define CARDTYPE_SDV2_HC 4 /* V2.0 or later High/eXtended Capacity SD card */

/* SD/MMC card configuration */
typedef struct tagCARDCONFIG
{
unsigned int sectorsize; /* size (in byte) of each sector, fixed to 512bytes */
unsigned int sectorcnt; /* total sector number */
unsigned int blocksize; /* erase block size in unit of sector */
unsigned char ocr[4]; /* OCR */
unsigned char cid[16]; /* CID */
unsigned char csd[16]; /* CSD */
} CARDCONFIG;

/* Public variables */
extern unsigned char CardType;
extern CARDCONFIG CardConfig;


/* Public functions */
SD_BOOL SD_Init (void);
SD_BOOL SD_ReadSector (unsigned int sect, unsigned char *buf, unsigned int cnt);
SD_BOOL SD_WriteSector (unsigned int sect, const unsigned char *buf, unsigned int cnt);
SD_BOOL SD_ReadConfiguration (void);
void disk_timerproc (void);

/***********************************************************************************
* Fim do arquivo
***********************************************************************************/
#endif // _SDCARD_H_

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 10:51
por Red Neck Guy
Você só precisa implementar as funções de read e write nessa camada, assim o restante acima é pra ser independente da plataforma, mas como nunca revisei não lembro e nem olhei se tem alguma dependência do target.


cpp code
/***********************************************************************************
* Includes
***********************************************************************************/
#include <nxp\iolpc1768.h>

/***********************************************************************************
* Definições
***********************************************************************************/
#define SSP_SR_TFE ((unsigned int)(1<<0)) /** SSP status TX FIFO Empty bit */
#define SSP_SR_TNF ((unsigned int)(1<<1)) /** SSP status TX FIFO not full bit */
#define SSP_SR_RNE ((unsigned int)(1<<2)) /** SSP status RX FIFO not empty bit */
#define SSP_SR_RFF ((unsigned int)(1<<3)) /** SSP status RX FIFO full bit */
#define SSP_SR_BSY ((unsigned int)(1<<4)) /** SSP status SSP Busy bit */
#define SSP_SR_BITMASK ((unsigned int)(0x1F)) /** SSP SR bit mask */

#define CS_PIN_ (0x01)<<6
#define SPI_PCLK 64000000
/***********************************************************************************
* Implementação
***********************************************************************************/

/***********************************************************************************
* @brief Initializes the SSP0.
*
* @param None
* @retval None
***********************************************************************************/
void SPI_Init (void){

// Liga a energia pro módulo
PCONP_bit.PCSSP1 = 1;

// Inicia o chipselect em nível alto
FIO0DIR |= CS_PIN_;
FIO0SET |= CS_PIN_;

// Configura a função SPI1 para os pinos
PINSEL0_bit.P0_7 = 0x02;
PINSEL0_bit.P0_8 = 0x02;
PINSEL0_bit.P0_9 = 0x02;

/* Configure SSP0_PCLK to CCLK(100MHz), default value is CCLK/4 */
//LPC_SC->PCLKSEL1 &= ~(3 << 10);
//LPC_SC->PCLKSEL1 |= (1 << 10); /* SSP0_PCLK=CCLK */
PCLKSEL0_bit.PCLK_SSP1 = 0;//1;

/* 8bit, SPI frame format, CPOL=0, CPHA=0, SCR=0 */
//LPC_SSP1->CR0 = (0x07 << 0) | /* data width: 8bit*/
// (0x00 << 4) | /* frame format: SPI */
// (0x00 << 6) | /* CPOL: low level */
// (0x00 << 7) | /* CPHA: first edge */
// (0x00 << 8); /* SCR = 0 */
SSP1CR0 = (0x07 << 0) | /* data width: 8bit*/
(0x00 << 4) | /* frame format: SPI */
(0x00 << 6) | /* CPOL: low level */
(0x00 << 7) | /* CPHA: first edge */
(0x00 << 8); /* SCR = 0 */

/* Enable SSP0 as a master */
//LPC_SSP1->CR1 = (0x00 << 0) | /* Normal mode */
// (0x01 << 1) | /* Enable SSP0 */
// (0x00 << 2) | /* Master */
// (0x00 << 3); /* slave output disabled */

SSP1CR1 = (0x00 << 0) | /* Normal mode */
(0x01 << 1) | /* Enable SSP0 */
(0x00 << 2) | /* Master */
(0x00 << 3); /* slave output disabled */

/* Configure SSP1 clock rate to 400kHz (100MHz/250) */
SPI_ConfigClockRate (SPI_CLOCKRATE_LOW);

/* Set SSEL to high */
SPI_CS_High ();
}
/***********************************************************************************
* @brief Configure SSP0 clock rate.
*
* @param SPI_CLOCKRATE: Specifies the SPI clock rate.
* The value should be SPI_CLOCKRATE_LOW or SPI_CLOCKRATE_HIGH.
* @retval None
*
* SSP0_CLK = CCLK / SPI_CLOCKRATE
***********************************************************************************/
void SPI_ConfigClockRate (unsigned int SPI_CLOCKRATE){
unsigned int divisor;

divisor = SPI_PCLK/SPI_CLOCKRATE;
divisor &=~(0x01); // Aham!!!! Me diga o que isso faz!!!!! Se souber, está contratado!!!!

SSP1CR0_bit.SCR = divisor<<8;
SSP1CPSR = divisor;
}
/***********************************************************************************
* @brief Set SSEL to low: select spi slave.
*
* @param None.
* @retval None
***********************************************************************************/
void SPI_CS_Low (void){

FIO0CLR |= CS_PIN_;
}
/***********************************************************************************
* @brief Set SSEL to high: de-select spi slave.
*
* @param None.
* @retval None
***********************************************************************************/
void SPI_CS_High (void){

FIO0SET |= CS_PIN_;
}
/***********************************************************************************
* @brief Send one byte via MOSI and simutaniously receive one byte via MISO.
*
* @param data: Specifies the byte to be sent out.
* @retval Returned byte.
*
* Note: Each time send out one byte at MOSI, Rx FIFO will receive one byte.
***********************************************************************************/
unsigned char SPI_SendByte (unsigned char data){
unsigned char temp;

while(! (SSP1SR & 0x02));//Se está setado é pq o buffer está cheio
SSP1DR = data;
while(! (SSP1SR & 0x04));//
temp = SSP1DR;

return temp;
}
/***********************************************************************************
* @brief Receive one byte via MISO.
*
* @param None.
* @retval Returned received byte.
***********************************************************************************/
unsigned char SPI_RecvByte (void){

return SPI_SendByte (0xFF);
}
/***********************************************************************************
* Fim do arquivo
***********************************************************************************/

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 10:56
por Red Neck Guy
E acima dessas duas camadas eu uso o FATfs, é estável e nunca me incomodou.

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 01 Jan 2017 16:44
por andre_luis
Muito obrigado, vou testar depois, mas essa aí não pareceu muito menor que a outra que encontrei..... :wink: De qualquer modo, uma vez funcionando a ideia é impementar o FAT, pra dar suporte a leitura externa no desenvolvimento, apesar de não ser necessário no produto final.

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 02 Jan 2017 17:10
por tcpipchip
Em ultima instancia usa chip serial to fat

Re: [ATmega2560] Biblioteca MMC/SDcard - sem FAT16/32

MensagemEnviado: 02 Jan 2017 17:12
por tcpipchip
Tambem podes testar com spi flash com a lib fs